diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index a83263d7d..000000000 --- a/.appveyor.yml +++ /dev/null @@ -1,39 +0,0 @@ -version: 1.0.{build} -os: Visual Studio 2017 -platform: x64 -clone_folder: C:\projects\libigl -shallow_clone: true -branches: - only: - - master - - dev -environment: - matrix: - - CONFIG: Debug - BOOST_ROOT: C:/Libraries/boost_1_65_1 - PYTHON: 37 - - CONFIG: Release - BOOST_ROOT: C:/Libraries/boost_1_65_1 - PYTHON: 37 -install: - - cinstall: python -build: - parallel: true -build_script: - - cd c:\projects\libigl - # Tutorials and tests - - set PATH=C:\Python%PYTHON%-x64;C:\Python%PYTHON%-x64\Scripts;%PATH% - - mkdir build - - cd build - - cmake -DCMAKE_BUILD_TYPE=%CONFIG% - -DLIBIGL_WITH_CGAL=ON - -DLIBIGL_WITH_COMISO=OFF - -G "Visual Studio 15 2017 Win64" - ../ - - set MSBuildLogger="C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" - - set MSBuildOptions=/v:m /m /p:BuildInParallel=true /p:Configuration=%CONFIG% /logger:%MSBuildLogger% - - msbuild %MSBuildOptions% libigl.sln - -test_script: - - set CTEST_OUTPUT_ON_FAILURE=1 - - ctest -C %CONFIG% --verbose --output-on-failure -j 2 diff --git a/.github/workflows/continuous.yml b/.github/workflows/continuous.yml new file mode 100644 index 000000000..f1f6f2506 --- /dev/null +++ b/.github/workflows/continuous.yml @@ -0,0 +1,141 @@ +name: Build + +on: + push: {} + pull_request: {} + +env: + CTEST_OUTPUT_ON_FAILURE: ON + CTEST_PARALLEL_LEVEL: 2 + +jobs: + #################### + # Linux / macOS + #################### + + Unix: + name: ${{ matrix.name }} (${{ matrix.config }}, ${{ matrix.static }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-18.04, macos-latest] + config: [Release] + static: [ON, OFF] + include: + - os: macos-latest + name: macOS + - os: ubuntu-18.04 + name: Linux + env: + LIBIGL_NUM_THREADS: 1 # See https://github.com/libigl/libigl/pull/996 + steps: + - name: Checkout repository + uses: actions/checkout@v1 + with: + fetch-depth: 1 + + - name: Dependencies (Linux) + if: runner.os == 'Linux' + run: | + sudo apt-get install \ + libblas-dev \ + libboost-filesystem-dev \ + libboost-system-dev \ + libboost-thread-dev \ + libglu1-mesa-dev \ + liblapack-dev \ + libmpfr-dev \ + xorg-dev \ + ccache + + - name: Dependencies (macOS) + if: runner.os == 'macOS' + run: brew install boost gmp mpfr ccache + + - name: Cache Build + id: cache-build + uses: actions/cache@v1 + with: + path: ~/.ccache + key: ${{ runner.os }}-${{ matrix.config }}-${{ matrix.static }}-cache + + - name: Prepare ccache + run: | + ccache --max-size=1.0G + ccache -V && ccache --show-stats && ccache --zero-stats + + - name: Configure + run: | + mkdir -p build + cd build + cmake .. \ + -DCMAKE_CXX_COMPILER_LAUNCHER=ccache \ + -DCMAKE_BUILD_TYPE=${{ matrix.config }} \ + -DLIBIGL_USE_STATIC_LIBRARY=${{ matrix.static }} \ + -DLIBIGL_WITH_CGAL=ON \ + -DLIBIGL_WITH_COMISO=ON + + - name: Build + run: cd build; make -j2; ccache --show-stats + + - name: Tests + run: cd build; ctest --verbose + + #################### + # Windows + #################### + + Windows: + runs-on: windows-2019 + env: + CC: cl.exe + CXX: cl.exe + strategy: + fail-fast: false + matrix: + config: [Release] + static: [ON, OFF] + steps: + - name: Checkout repository + uses: actions/checkout@v1 + with: + fetch-depth: 1 + - uses: seanmiddleditch/gha-setup-ninja@master + + # https://github.com/actions/cache/issues/101 + - name: Set env + run: echo "::set-env name=appdata::$($env:LOCALAPPDATA)" + + - name: Cache build + id: cache-build + uses: actions/cache@v1 + with: + path: ${{ env.appdata }}\Mozilla\sccache + key: ${{ runner.os }}-${{ matrix.config }}-${{ matrix.static }}-cache + + - name: Prepare sccache + run: | + Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh') + scoop install sccache --global + # Scoop modifies the PATH so we make the modified PATH global. + echo "::set-env name=PATH::$env:PATH" + + # We run configure + build in the same step, since they both need to call VsDevCmd + # Also, cmd uses ^ to break commands into multiple lines (in powershell this is `) + - name: Configure and build + shell: cmd + run: | + call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=x64 + cmake -G Ninja ^ + -DCMAKE_CXX_COMPILER_LAUNCHER=sccache ^ + -DCMAKE_BUILD_TYPE=${{ matrix.config }} ^ + -DLIBIGL_USE_STATIC_LIBRARY=${{ matrix.static }} ^ + -DLIBIGL_WITH_CGAL=ON ^ + -DLIBIGL_WITH_COMISO=OFF ^ + -B build ^ + -S . + cmake --build build + + - name: Tests + run: cd build; ctest --verbose diff --git a/.github/workflows/daily.yml b/.github/workflows/daily.yml new file mode 100644 index 000000000..bae7f9721 --- /dev/null +++ b/.github/workflows/daily.yml @@ -0,0 +1,169 @@ +name: Daily + +on: + schedule: + - cron: '0 4 * * *' + +env: + CTEST_OUTPUT_ON_FAILURE: ON + CTEST_PARALLEL_LEVEL: 2 + +jobs: + #################### + # Linux / macOS + #################### + + # Part of this file is inspired from + # https://github.com/onqtam/doctest/blob/dev/.github/workflows/main.yml + + Unix: + name: ${{ matrix.name }} (${{ matrix.config }}, ${{ matrix.static }}) + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + name: [ + ubuntu-18.04-gcc-7, + ubuntu-18.04-gcc-8, + ubuntu-18.04-gcc-9, + ubuntu-18.04-clang-7, + ubuntu-18.04-clang-8, + ubuntu-18.04-clang-9, + macOS-latest, + ] + config: [Debug, Release] + static: [ON, OFF] + include: + - name: ubuntu-18.04-gcc-7 + os: ubuntu-18.04 + compiler: gcc + version: "7" + + - name: ubuntu-18.04-gcc-8 + os: ubuntu-18.04 + compiler: gcc + version: "8" + + - name: ubuntu-18.04-gcc-9 + os: ubuntu-18.04 + compiler: gcc + version: "9" + + - name: ubuntu-18.04-clang-7 + os: ubuntu-18.04 + compiler: clang + version: "7" + + - name: ubuntu-18.04-clang-8 + os: ubuntu-18.04 + compiler: clang + version: "8" + + - name: ubuntu-18.04-clang-9 + os: ubuntu-18.04 + compiler: clang + version: "9" + + - name: macOS-latest + os: macOS-latest + env: + LIBIGL_NUM_THREADS: 1 # See https://github.com/libigl/libigl/pull/996 + steps: + - name: Checkout repository + uses: actions/checkout@v1 + with: + fetch-depth: 1 + + - name: Dependencies (Linux) + if: runner.os == 'Linux' + run: | + # LLVM 9 is not in Bionic's repositories so we add the official LLVM repository. + if [ "${{ matrix.compiler }}" = "clang" ] && [ "${{ matrix.version }}" = "9" ]; then + sudo add-apt-repository "deb http://apt.llvm.org/bionic/ llvm-toolchain-bionic-9 main" + fi + sudo apt-get update + + if [ "${{ matrix.compiler }}" = "gcc" ]; then + sudo apt-get install -y g++-${{ matrix.version }} + echo "::set-env name=CC::gcc-${{ matrix.version }}" + echo "::set-env name=CXX::g++-${{ matrix.version }}" + else + sudo apt-get install -y clang-${{ matrix.version }} + echo "::set-env name=CC::clang-${{ matrix.version }}" + echo "::set-env name=CXX::clang++-${{ matrix.version }}" + fi + + sudo apt-get install \ + libblas-dev \ + libboost-filesystem-dev \ + libboost-system-dev \ + libboost-thread-dev \ + libglu1-mesa-dev \ + liblapack-dev \ + libmpfr-dev \ + xorg-dev + + - name: Dependencies (macOS) + if: runner.os == 'macOS' + run: brew install boost gmp mpfr + + - name: Configure + run: | + mkdir -p build + cd build + cmake .. \ + -DCMAKE_BUILD_TYPE=${{ matrix.config }} \ + -DLIBIGL_USE_STATIC_LIBRARY=${{ matrix.static }} \ + -DLIBIGL_WITH_CGAL=ON \ + -DLIBIGL_WITH_COMISO=ON + + - name: Build + run: cd build; make -j2 + + - name: Tests + run: cd build; ctest --verbose + + #################### + # Windows + #################### + + Windows: + runs-on: windows-2019 + env: + CC: cl.exe + CXX: cl.exe + strategy: + fail-fast: false + matrix: + config: [Debug, Release] + static: [ON, OFF] + include: + - config: Debug + tutorials: OFF + - config: Release + tutorials: ON + steps: + - name: Checkout repository + uses: actions/checkout@v1 + with: + fetch-depth: 1 + - uses: seanmiddleditch/gha-setup-ninja@master + + # We run configure + build in the same step, since they both need to call VsDevCmd + # Also, cmd uses ^ to break commands into multiple lines (in powershell this is `) + - name: Configure and build + shell: cmd + run: | + call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=x64 + cmake -G Ninja ^ + -DCMAKE_BUILD_TYPE=${{ matrix.config }} ^ + -DLIBIGL_USE_STATIC_LIBRARY=${{ matrix.static }} ^ + -DLIBIGL_BUILD_TUTORIALS=${{ matrix.tutorials }} ^ + -DLIBIGL_WITH_CGAL=ON ^ + -DLIBIGL_WITH_COMISO=OFF ^ + -B build ^ + -S . + cmake --build build + + - name: Tests + run: cd build; ctest --verbose diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index a1440aaeb..000000000 --- a/.travis.yml +++ /dev/null @@ -1,78 +0,0 @@ -dist: trusty -sudo: true -language: cpp -cache: ccache -addons: - apt: - sources: - - ubuntu-toolchain-r-test - packages: - - g++-7 - - gcc-7 - - libblas-dev - - libboost-filesystem-dev - - libboost-system-dev - - libboost-thread-dev - - libglu1-mesa-dev - - liblapack-dev - - libmpfr-dev - - libpython3-dev - - python3-setuptools - - xorg-dev - homebrew: - packages: - - ccache -matrix: - include: - - os: linux - compiler: gcc # 4.8.4 by default on Trusty - env: - - MATRIX_EVAL="export CONFIG=Release PYTHON=python3" - - os: linux - compiler: gcc-7 - env: - - MATRIX_EVAL="export CC=gcc-7 CXX=g++-7 CONFIG=Release PYTHON=python3" - - os: linux # same config like above but with -DLIBIGL_USE_STATIC_LIBRARY=OFF to test static and header-only builds - compiler: gcc-7 - env: - - MATRIX_EVAL="export CC=gcc-7 CXX=g++-7 CONFIG=Release PYTHON=python3 CMAKE_EXTRA='-DLIBIGL_USE_STATIC_LIBRARY=OFF'" - - os: linux - compiler: gcc-7 - env: - - MATRIX_EVAL="export CC=gcc-7 CXX=g++-7 CONFIG=Release PYTHON=python3 CMAKE_EXTRA='-DLIBIGL_EIGEN_VERSION=3.3.7'" - - os: osx - compiler: clang - env: - - MATRIX_EVAL="export CONFIG=Debug PYTHON=python3 LIBIGL_NUM_THREADS=1" - - os: osx # same config like above but with -DLIBIGL_USE_STATIC_LIBRARY=OFF to test static and header-only builds - compiler: clang - env: - - MATRIX_EVAL="export CONFIG=Debug PYTHON=python3 LIBIGL_NUM_THREADS=1 CMAKE_EXTRA='-DLIBIGL_USE_STATIC_LIBRARY=OFF'" - - os: osx - compiler: clang - env: - - MATRIX_EVAL="export CONFIG=Debug PYTHON=python3 LIBIGL_NUM_THREADS=1 CMAKE_EXTRA='-DLIBIGL_EIGEN_VERSION=3.3.7'"" - -install: -- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then export PATH="/usr/local/opt/ccache/libexec:$PATH"; fi -- eval "${MATRIX_EVAL}" -- ccache --max-size=5.0G -- ccache -V && ccache --show-stats && ccache --zero-stats - -script: -# Tutorials and tests -- mkdir build -- pushd build -- cmake ${CMAKE_EXTRA} - -DCMAKE_BUILD_TYPE=$CONFIG - -DLIBIGL_CHECK_UNDEFINED=ON - -DLIBIGL_WITH_CGAL=ON - ../ -- make -j 2 -- ctest --verbose -- popd -- pushd python/tutorial -- ${PYTHON} 101_FileIO.py -- popd -- rm -rf build -- ccache --show-stats diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d94d3f11..26583b97b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,4 +1,14 @@ cmake_minimum_required(VERSION 3.1) + +# Toggles the use of the hunter package manager +option(HUNTER_ENABLED "Enable Hunter package manager support" OFF) + +include("cmake/HunterGate.cmake") +HunterGate( + URL "https://github.com/ruslo/hunter/archive/v0.23.171.tar.gz" + SHA1 "5d68bcca78eee347239ca5f4d34f4b6c12683154" +) + project(libigl) # Detects whether this is a top-level project @@ -9,10 +19,9 @@ else() set(LIBIGL_TOPLEVEL_PROJECT OFF) endif() -# Build tests, tutorials and python bindings +# Build tests and tutorials option(LIBIGL_BUILD_TESTS "Build libigl unit test" ${LIBIGL_TOPLEVEL_PROJECT}) option(LIBIGL_BUILD_TUTORIALS "Build libigl tutorial" ${LIBIGL_TOPLEVEL_PROJECT}) -option(LIBIGL_BUILD_PYTHON "Build libigl python bindings" ${LIBIGL_TOPLEVEL_PROJECT}) option(LIBIGL_EXPORT_TARGETS "Export libigl CMake targets" ${LIBIGL_TOPLEVEL_PROJECT}) # USE_STATIC_LIBRARY speeds up the generation of multiple binaries, @@ -32,9 +41,13 @@ option(LIBIGL_WITH_TETGEN "Use Tetgen" ON) option(LIBIGL_WITH_TRIANGLE "Use Triangle" ON) option(LIBIGL_WITH_PREDICATES "Use exact predicates" ON) option(LIBIGL_WITH_XML "Use XML" ON) -option(LIBIGL_WITH_PYTHON "Use Python" ${LIBIGL_BUILD_PYTHON}) +option(LIBIGL_WITH_PYTHON "Use Python" OFF) ### End +if(${LIBIGL_WITH_PYTHON}) + message(FATAL_ERROR "Python binding are in the process of being redone. Please use the master branch or refer to https://github.com/geometryprocessing/libigl-python-bindings for the developement version or https://anaconda.org/conda-forge/igl for the stable version.") +endif() + set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}) @@ -55,6 +68,7 @@ if(LIBIGL_BUILD_TESTS) add_subdirectory(tests) endif() -if(LIBIGL_WITH_PYTHON) - add_subdirectory(python) +if(LIBIGL_TOPLEVEL_PROJECT) + # Set folders for Visual Studio/Xcode + igl_set_folders() endif() diff --git a/README.md b/README.md index 5f5e0bf5e..b257fc3e5 100644 --- a/README.md +++ b/README.md @@ -1,8 +1,8 @@ # libigl - A simple C++ geometry processing library -[![Build Status](https://travis-ci.org/libigl/libigl.svg?branch=master)](https://travis-ci.org/libigl/libigl) -[![Build status](https://ci.appveyor.com/api/projects/status/mf3t9rnhco0vhly8/branch/master?svg=true)](https://ci.appveyor.com/project/danielepanozzo/libigl-6hjk1/branch/master) -![](https://github.com/libigl/libigl-legacy/raw/5ff6387765fa85ca46f1a6222728e35e2b8b8961/libigl-teaser.png) +![](https://github.com/libigl/libigl/workflows/Build/badge.svg) +![](https://github.com/libigl/libigl/workflows/Daily/badge.svg) +[![](https://anaconda.org/conda-forge/igl/badges/installer/conda.svg)](https://conda.anaconda.org/conda-forge/igl) + +![](https://libigl.github.io/libigl-teaser.png) Documentation, tutorial, and instructions at . - -:exclamation: **On October 15, 2018, a new, cleaned-up history was pushed onto the main libigl repository. To learn more about the consequences of this, and troubleshooting, please read [this page](https://libigl.github.io/rewritten-history/).** diff --git a/cmake/HunterGate.cmake b/cmake/HunterGate.cmake new file mode 100644 index 000000000..887557a58 --- /dev/null +++ b/cmake/HunterGate.cmake @@ -0,0 +1,540 @@ +# Copyright (c) 2013-2018, Ruslan Baratov +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# * Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# * Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# 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. + +# This is a gate file to Hunter package manager. +# Include this file using `include` command and add package you need, example: +# +# cmake_minimum_required(VERSION 3.2) +# +# include("cmake/HunterGate.cmake") +# HunterGate( +# URL "https://github.com/path/to/hunter/archive.tar.gz" +# SHA1 "798501e983f14b28b10cda16afa4de69eee1da1d" +# ) +# +# project(MyProject) +# +# hunter_add_package(Foo) +# hunter_add_package(Boo COMPONENTS Bar Baz) +# +# Projects: +# * https://github.com/hunter-packages/gate/ +# * https://github.com/ruslo/hunter + +option(HUNTER_ENABLED "Enable Hunter package manager support" ON) + +if(HUNTER_ENABLED) + if(CMAKE_VERSION VERSION_LESS "3.2") + message( + FATAL_ERROR + "At least CMake version 3.2 required for Hunter dependency management." + " Update CMake or set HUNTER_ENABLED to OFF." + ) + endif() +endif() + +include(CMakeParseArguments) # cmake_parse_arguments + +option(HUNTER_STATUS_PRINT "Print working status" ON) +option(HUNTER_STATUS_DEBUG "Print a lot info" OFF) +option(HUNTER_TLS_VERIFY "Enable/disable TLS certificate checking on downloads" ON) + +set(HUNTER_WIKI "https://github.com/ruslo/hunter/wiki") + +function(hunter_gate_status_print) + if(HUNTER_STATUS_PRINT OR HUNTER_STATUS_DEBUG) + foreach(print_message ${ARGV}) + message(STATUS "[hunter] ${print_message}") + endforeach() + endif() +endfunction() + +function(hunter_gate_status_debug) + if(HUNTER_STATUS_DEBUG) + foreach(print_message ${ARGV}) + string(TIMESTAMP timestamp) + message(STATUS "[hunter *** DEBUG *** ${timestamp}] ${print_message}") + endforeach() + endif() +endfunction() + +function(hunter_gate_wiki wiki_page) + message("------------------------------ WIKI -------------------------------") + message(" ${HUNTER_WIKI}/${wiki_page}") + message("-------------------------------------------------------------------") + message("") + message(FATAL_ERROR "") +endfunction() + +function(hunter_gate_internal_error) + message("") + foreach(print_message ${ARGV}) + message("[hunter ** INTERNAL **] ${print_message}") + endforeach() + message("[hunter ** INTERNAL **] [Directory:${CMAKE_CURRENT_LIST_DIR}]") + message("") + hunter_gate_wiki("error.internal") +endfunction() + +function(hunter_gate_fatal_error) + cmake_parse_arguments(hunter "" "WIKI" "" "${ARGV}") + string(COMPARE EQUAL "${hunter_WIKI}" "" have_no_wiki) + if(have_no_wiki) + hunter_gate_internal_error("Expected wiki") + endif() + message("") + foreach(x ${hunter_UNPARSED_ARGUMENTS}) + message("[hunter ** FATAL ERROR **] ${x}") + endforeach() + message("[hunter ** FATAL ERROR **] [Directory:${CMAKE_CURRENT_LIST_DIR}]") + message("") + hunter_gate_wiki("${hunter_WIKI}") +endfunction() + +function(hunter_gate_user_error) + hunter_gate_fatal_error(${ARGV} WIKI "error.incorrect.input.data") +endfunction() + +function(hunter_gate_self root version sha1 result) + string(COMPARE EQUAL "${root}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("root is empty") + endif() + + string(COMPARE EQUAL "${version}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("version is empty") + endif() + + string(COMPARE EQUAL "${sha1}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("sha1 is empty") + endif() + + string(SUBSTRING "${sha1}" 0 7 archive_id) + + if(EXISTS "${root}/cmake/Hunter") + set(hunter_self "${root}") + else() + set( + hunter_self + "${root}/_Base/Download/Hunter/${version}/${archive_id}/Unpacked" + ) + endif() + + set("${result}" "${hunter_self}" PARENT_SCOPE) +endfunction() + +# Set HUNTER_GATE_ROOT cmake variable to suitable value. +function(hunter_gate_detect_root) + # Check CMake variable + string(COMPARE NOTEQUAL "${HUNTER_ROOT}" "" not_empty) + if(not_empty) + set(HUNTER_GATE_ROOT "${HUNTER_ROOT}" PARENT_SCOPE) + hunter_gate_status_debug("HUNTER_ROOT detected by cmake variable") + return() + endif() + + # Check environment variable + string(COMPARE NOTEQUAL "$ENV{HUNTER_ROOT}" "" not_empty) + if(not_empty) + set(HUNTER_GATE_ROOT "$ENV{HUNTER_ROOT}" PARENT_SCOPE) + hunter_gate_status_debug("HUNTER_ROOT detected by environment variable") + return() + endif() + + # Check HOME environment variable + string(COMPARE NOTEQUAL "$ENV{HOME}" "" result) + if(result) + set(HUNTER_GATE_ROOT "$ENV{HOME}/.hunter" PARENT_SCOPE) + hunter_gate_status_debug("HUNTER_ROOT set using HOME environment variable") + return() + endif() + + # Check SYSTEMDRIVE and USERPROFILE environment variable (windows only) + if(WIN32) + string(COMPARE NOTEQUAL "$ENV{SYSTEMDRIVE}" "" result) + if(result) + set(HUNTER_GATE_ROOT "$ENV{SYSTEMDRIVE}/.hunter" PARENT_SCOPE) + hunter_gate_status_debug( + "HUNTER_ROOT set using SYSTEMDRIVE environment variable" + ) + return() + endif() + + string(COMPARE NOTEQUAL "$ENV{USERPROFILE}" "" result) + if(result) + set(HUNTER_GATE_ROOT "$ENV{USERPROFILE}/.hunter" PARENT_SCOPE) + hunter_gate_status_debug( + "HUNTER_ROOT set using USERPROFILE environment variable" + ) + return() + endif() + endif() + + hunter_gate_fatal_error( + "Can't detect HUNTER_ROOT" + WIKI "error.detect.hunter.root" + ) +endfunction() + +function(hunter_gate_download dir) + string( + COMPARE + NOTEQUAL + "$ENV{HUNTER_DISABLE_AUTOINSTALL}" + "" + disable_autoinstall + ) + if(disable_autoinstall AND NOT HUNTER_RUN_INSTALL) + hunter_gate_fatal_error( + "Hunter not found in '${dir}'" + "Set HUNTER_RUN_INSTALL=ON to auto-install it from '${HUNTER_GATE_URL}'" + "Settings:" + " HUNTER_ROOT: ${HUNTER_GATE_ROOT}" + " HUNTER_SHA1: ${HUNTER_GATE_SHA1}" + WIKI "error.run.install" + ) + endif() + string(COMPARE EQUAL "${dir}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("Empty 'dir' argument") + endif() + + string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("HUNTER_GATE_SHA1 empty") + endif() + + string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" is_bad) + if(is_bad) + hunter_gate_internal_error("HUNTER_GATE_URL empty") + endif() + + set(done_location "${dir}/DONE") + set(sha1_location "${dir}/SHA1") + + set(build_dir "${dir}/Build") + set(cmakelists "${dir}/CMakeLists.txt") + + hunter_gate_status_debug("Locking directory: ${dir}") + file(LOCK "${dir}" DIRECTORY GUARD FUNCTION) + hunter_gate_status_debug("Lock done") + + if(EXISTS "${done_location}") + # while waiting for lock other instance can do all the job + hunter_gate_status_debug("File '${done_location}' found, skip install") + return() + endif() + + file(REMOVE_RECURSE "${build_dir}") + file(REMOVE_RECURSE "${cmakelists}") + + file(MAKE_DIRECTORY "${build_dir}") # check directory permissions + + # Disabling languages speeds up a little bit, reduces noise in the output + # and avoids path too long windows error + file( + WRITE + "${cmakelists}" + "cmake_minimum_required(VERSION 3.2)\n" + "project(HunterDownload LANGUAGES NONE)\n" + "include(ExternalProject)\n" + "ExternalProject_Add(\n" + " Hunter\n" + " URL\n" + " \"${HUNTER_GATE_URL}\"\n" + " URL_HASH\n" + " SHA1=${HUNTER_GATE_SHA1}\n" + " DOWNLOAD_DIR\n" + " \"${dir}\"\n" + " TLS_VERIFY\n" + " ${HUNTER_TLS_VERIFY}\n" + " SOURCE_DIR\n" + " \"${dir}/Unpacked\"\n" + " CONFIGURE_COMMAND\n" + " \"\"\n" + " BUILD_COMMAND\n" + " \"\"\n" + " INSTALL_COMMAND\n" + " \"\"\n" + ")\n" + ) + + if(HUNTER_STATUS_DEBUG) + set(logging_params "") + else() + set(logging_params OUTPUT_QUIET) + endif() + + hunter_gate_status_debug("Run generate") + + # Need to add toolchain file too. + # Otherwise on Visual Studio + MDD this will fail with error: + # "Could not find an appropriate version of the Windows 10 SDK installed on this machine" + if(EXISTS "${CMAKE_TOOLCHAIN_FILE}") + get_filename_component(absolute_CMAKE_TOOLCHAIN_FILE "${CMAKE_TOOLCHAIN_FILE}" ABSOLUTE) + set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=${absolute_CMAKE_TOOLCHAIN_FILE}") + else() + # 'toolchain_arg' can't be empty + set(toolchain_arg "-DCMAKE_TOOLCHAIN_FILE=") + endif() + + string(COMPARE EQUAL "${CMAKE_MAKE_PROGRAM}" "" no_make) + if(no_make) + set(make_arg "") + else() + # Test case: remove Ninja from PATH but set it via CMAKE_MAKE_PROGRAM + set(make_arg "-DCMAKE_MAKE_PROGRAM=${CMAKE_MAKE_PROGRAM}") + endif() + + execute_process( + COMMAND + "${CMAKE_COMMAND}" + "-H${dir}" + "-B${build_dir}" + "-G${CMAKE_GENERATOR}" + "${toolchain_arg}" + ${make_arg} + WORKING_DIRECTORY "${dir}" + RESULT_VARIABLE download_result + ${logging_params} + ) + + if(NOT download_result EQUAL 0) + hunter_gate_internal_error( + "Configure project failed." + "To reproduce the error run: ${CMAKE_COMMAND} -H${dir} -B${build_dir} -G${CMAKE_GENERATOR} ${toolchain_arg} ${make_arg}" + "In directory ${dir}" + ) + endif() + + hunter_gate_status_print( + "Initializing Hunter workspace (${HUNTER_GATE_SHA1})" + " ${HUNTER_GATE_URL}" + " -> ${dir}" + ) + execute_process( + COMMAND "${CMAKE_COMMAND}" --build "${build_dir}" + WORKING_DIRECTORY "${dir}" + RESULT_VARIABLE download_result + ${logging_params} + ) + + if(NOT download_result EQUAL 0) + hunter_gate_internal_error("Build project failed") + endif() + + file(REMOVE_RECURSE "${build_dir}") + file(REMOVE_RECURSE "${cmakelists}") + + file(WRITE "${sha1_location}" "${HUNTER_GATE_SHA1}") + file(WRITE "${done_location}" "DONE") + + hunter_gate_status_debug("Finished") +endfunction() + +# Must be a macro so master file 'cmake/Hunter' can +# apply all variables easily just by 'include' command +# (otherwise PARENT_SCOPE magic needed) +macro(HunterGate) + if(HUNTER_GATE_DONE) + # variable HUNTER_GATE_DONE set explicitly for external project + # (see `hunter_download`) + set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES) + endif() + + # First HunterGate command will init Hunter, others will be ignored + get_property(_hunter_gate_done GLOBAL PROPERTY HUNTER_GATE_DONE SET) + + if(NOT HUNTER_ENABLED) + # Empty function to avoid error "unknown function" + function(hunter_add_package) + endfunction() + + set( + _hunter_gate_disabled_mode_dir + "${CMAKE_CURRENT_LIST_DIR}/cmake/Hunter/disabled-mode" + ) + if(EXISTS "${_hunter_gate_disabled_mode_dir}") + hunter_gate_status_debug( + "Adding \"disabled-mode\" modules: ${_hunter_gate_disabled_mode_dir}" + ) + list(APPEND CMAKE_PREFIX_PATH "${_hunter_gate_disabled_mode_dir}") + endif() + elseif(_hunter_gate_done) + hunter_gate_status_debug("Secondary HunterGate (use old settings)") + hunter_gate_self( + "${HUNTER_CACHED_ROOT}" + "${HUNTER_VERSION}" + "${HUNTER_SHA1}" + _hunter_self + ) + include("${_hunter_self}/cmake/Hunter") + else() + set(HUNTER_GATE_LOCATION "${CMAKE_CURRENT_SOURCE_DIR}") + + string(COMPARE NOTEQUAL "${PROJECT_NAME}" "" _have_project_name) + if(_have_project_name) + hunter_gate_fatal_error( + "Please set HunterGate *before* 'project' command. " + "Detected project: ${PROJECT_NAME}" + WIKI "error.huntergate.before.project" + ) + endif() + + cmake_parse_arguments( + HUNTER_GATE "LOCAL" "URL;SHA1;GLOBAL;FILEPATH" "" ${ARGV} + ) + + string(COMPARE EQUAL "${HUNTER_GATE_SHA1}" "" _empty_sha1) + string(COMPARE EQUAL "${HUNTER_GATE_URL}" "" _empty_url) + string( + COMPARE + NOTEQUAL + "${HUNTER_GATE_UNPARSED_ARGUMENTS}" + "" + _have_unparsed + ) + string(COMPARE NOTEQUAL "${HUNTER_GATE_GLOBAL}" "" _have_global) + string(COMPARE NOTEQUAL "${HUNTER_GATE_FILEPATH}" "" _have_filepath) + + if(_have_unparsed) + hunter_gate_user_error( + "HunterGate unparsed arguments: ${HUNTER_GATE_UNPARSED_ARGUMENTS}" + ) + endif() + if(_empty_sha1) + hunter_gate_user_error("SHA1 suboption of HunterGate is mandatory") + endif() + if(_empty_url) + hunter_gate_user_error("URL suboption of HunterGate is mandatory") + endif() + if(_have_global) + if(HUNTER_GATE_LOCAL) + hunter_gate_user_error("Unexpected LOCAL (already has GLOBAL)") + endif() + if(_have_filepath) + hunter_gate_user_error("Unexpected FILEPATH (already has GLOBAL)") + endif() + endif() + if(HUNTER_GATE_LOCAL) + if(_have_global) + hunter_gate_user_error("Unexpected GLOBAL (already has LOCAL)") + endif() + if(_have_filepath) + hunter_gate_user_error("Unexpected FILEPATH (already has LOCAL)") + endif() + endif() + if(_have_filepath) + if(_have_global) + hunter_gate_user_error("Unexpected GLOBAL (already has FILEPATH)") + endif() + if(HUNTER_GATE_LOCAL) + hunter_gate_user_error("Unexpected LOCAL (already has FILEPATH)") + endif() + endif() + + hunter_gate_detect_root() # set HUNTER_GATE_ROOT + + # Beautify path, fix probable problems with windows path slashes + get_filename_component( + HUNTER_GATE_ROOT "${HUNTER_GATE_ROOT}" ABSOLUTE + ) + hunter_gate_status_debug("HUNTER_ROOT: ${HUNTER_GATE_ROOT}") + if(NOT HUNTER_ALLOW_SPACES_IN_PATH) + string(FIND "${HUNTER_GATE_ROOT}" " " _contain_spaces) + if(NOT _contain_spaces EQUAL -1) + hunter_gate_fatal_error( + "HUNTER_ROOT (${HUNTER_GATE_ROOT}) contains spaces." + "Set HUNTER_ALLOW_SPACES_IN_PATH=ON to skip this error" + "(Use at your own risk!)" + WIKI "error.spaces.in.hunter.root" + ) + endif() + endif() + + string( + REGEX + MATCH + "[0-9]+\\.[0-9]+\\.[0-9]+[-_a-z0-9]*" + HUNTER_GATE_VERSION + "${HUNTER_GATE_URL}" + ) + string(COMPARE EQUAL "${HUNTER_GATE_VERSION}" "" _is_empty) + if(_is_empty) + set(HUNTER_GATE_VERSION "unknown") + endif() + + hunter_gate_self( + "${HUNTER_GATE_ROOT}" + "${HUNTER_GATE_VERSION}" + "${HUNTER_GATE_SHA1}" + _hunter_self + ) + + set(_master_location "${_hunter_self}/cmake/Hunter") + if(EXISTS "${HUNTER_GATE_ROOT}/cmake/Hunter") + # Hunter downloaded manually (e.g. by 'git clone') + set(_unused "xxxxxxxxxx") + set(HUNTER_GATE_SHA1 "${_unused}") + set(HUNTER_GATE_VERSION "${_unused}") + else() + get_filename_component(_archive_id_location "${_hunter_self}/.." ABSOLUTE) + set(_done_location "${_archive_id_location}/DONE") + set(_sha1_location "${_archive_id_location}/SHA1") + + # Check Hunter already downloaded by HunterGate + if(NOT EXISTS "${_done_location}") + hunter_gate_download("${_archive_id_location}") + endif() + + if(NOT EXISTS "${_done_location}") + hunter_gate_internal_error("hunter_gate_download failed") + endif() + + if(NOT EXISTS "${_sha1_location}") + hunter_gate_internal_error("${_sha1_location} not found") + endif() + file(READ "${_sha1_location}" _sha1_value) + string(COMPARE EQUAL "${_sha1_value}" "${HUNTER_GATE_SHA1}" _is_equal) + if(NOT _is_equal) + hunter_gate_internal_error( + "Short SHA1 collision:" + " ${_sha1_value} (from ${_sha1_location})" + " ${HUNTER_GATE_SHA1} (HunterGate)" + ) + endif() + if(NOT EXISTS "${_master_location}") + hunter_gate_user_error( + "Master file not found:" + " ${_master_location}" + "try to update Hunter/HunterGate" + ) + endif() + endif() + include("${_master_location}") + set_property(GLOBAL PROPERTY HUNTER_GATE_DONE YES) + endif() +endmacro() diff --git a/cmake/LibiglDownloadExternal.cmake b/cmake/LibiglDownloadExternal.cmake index 41e119b42..7e37dcc8a 100644 --- a/cmake/LibiglDownloadExternal.cmake +++ b/cmake/LibiglDownloadExternal.cmake @@ -64,7 +64,7 @@ function(igl_download_cork) endfunction() ## Eigen -set(LIBIGL_EIGEN_VERSION 3.2.10 CACHE STRING "Default version of Eigen used by libigl.") +set(LIBIGL_EIGEN_VERSION 3.3.7 CACHE STRING "Default version of Eigen used by libigl.") function(igl_download_eigen) igl_download_project(eigen GIT_REPOSITORY https://github.com/eigenteam/eigen-git-mirror.git @@ -156,7 +156,7 @@ endfunction() function(igl_download_catch2) igl_download_project(catch2 GIT_REPOSITORY https://github.com/catchorg/Catch2.git - GIT_TAG 03d122a35c3f5c398c43095a87bc82ed44642516 + GIT_TAG v2.11.0 ) endfunction() @@ -164,7 +164,7 @@ endfunction() function(igl_download_predicates) igl_download_project(predicates GIT_REPOSITORY https://github.com/libigl/libigl-predicates.git - GIT_TAG 4c57c1d3f31646b010d1d58bfbe201e75c2b2ad8 + GIT_TAG 5a1d2194ec114bff51d5a33230586cafb83adc86 ) endfunction() @@ -175,7 +175,7 @@ function(igl_download_test_data) igl_download_project_aux(test_data "${LIBIGL_EXTERNAL}/../tests/data" GIT_REPOSITORY https://github.com/libigl/libigl-tests-data - GIT_TAG adc66cabf712a0bd68ac182b4e7f8b5ba009c3dd + GIT_TAG 5994ecdab65aebc6c218c4c6f35e7822acf6fe99 ) endfunction() diff --git a/cmake/LibiglFolders.cmake b/cmake/LibiglFolders.cmake new file mode 100644 index 000000000..24b1cfc93 --- /dev/null +++ b/cmake/LibiglFolders.cmake @@ -0,0 +1,116 @@ +# Sort projects inside the solution +set_property(GLOBAL PROPERTY USE_FOLDERS ON) + +function(igl_folder_targets FOLDER_NAME) + foreach(target IN ITEMS ${ARGN}) + if(TARGET ${target}) + get_target_property(TYPE ${target} TYPE) + if(NOT (TYPE STREQUAL "INTERFACE_LIBRARY")) + set_target_properties(${target} PROPERTIES FOLDER "${FOLDER_NAME}") + endif() + endif() + endforeach() +endfunction() + +function(igl_set_folders) + +igl_folder_targets("ThirdParty/Embree" + algorithms + embree + lexers + math + simd + sys + tasking +) + +igl_folder_targets("ThirdParty" + CoMISo + glad + glfw + imgui + predicates + tetgen + tinyxml2 + triangle +) + +igl_folder_targets("Libigl" + igl + igl_comiso + igl_embree + igl_opengl + igl_opengl_glfw + igl_opengl_glfw_imgui + igl_png + igl_predicates + igl_stb_image + igl_tetgen + igl_triangle + igl_xml +) + +igl_folder_targets("Unit Tests" + libigl_tests +) + +igl_folder_targets("Tutorials" + 101_FileIO_bin + 102_DrawMesh_bin + 103_Events_bin + 104_Colors_bin + 105_Overlays_bin + 106_ViewerMenu_bin + 107_MultipleMeshes_bin + 108_MultipleViews_bin + 201_Normals_bin + 202_GaussianCurvature_bin + 203_CurvatureDirections_bin + 204_Gradient_bin + 205_Laplacian_bin + 206_GeodesicDistance_bin + 301_Slice_bin + 302_Sort_bin + 303_LaplaceEquation_bin + 304_LinearEqualityConstraints_bin + 305_QuadraticProgramming_bin + 306_EigenDecomposition_bin + 401_BiharmonicDeformation_bin + 402_PolyharmonicDeformation_bin + 403_BoundedBiharmonicWeights_bin + 404_DualQuaternionSkinning_bin + 405_AsRigidAsPossible_bin + 406_FastAutomaticSkinningTransformations_bin + 407_BiharmonicCoordinates_bin + 501_HarmonicParam_bin + 502_LSCMParam_bin + 503_ARAPParam_bin + 504_NRosyDesign_bin + 505_MIQ_bin + 506_FrameField_bin + 507_Planarization_bin + 601_Serialization_bin + 604_Triangle_bin + 605_Tetgen_bin + 606_AmbientOcclusion_bin + 607_ScreenCapture_bin + 701_Statistics_bin + 702_WindingNumber_bin + 703_Decimation_bin + 704_SignedDistance_bin + 705_MarchingCubes_bin + 706_FacetOrientation_bin + 707_SweptVolume_bin + 708_Picking_bin + 709_SLIM_bin + 710_SCAF_bin + 711_Subdivision_bin + 712_DataSmoothing_bin + 713_ShapeUp_bin + 714_MarchingTets_bin + 715_MeshImplicitFunction_bin + 716_HeatGeodesics_bin + 718_IterativeClosestPoint_bin +) + +endfunction() diff --git a/cmake/LibiglWindows.cmake b/cmake/LibiglWindows.cmake index e52fadf8e..b98aa5580 100644 --- a/cmake/LibiglWindows.cmake +++ b/cmake/LibiglWindows.cmake @@ -1,8 +1,6 @@ if(MSVC) - if("${MSVC_RUNTIME}" STREQUAL "") - set(MSVC_RUNTIME "static") - endif() - if(${MSVC_RUNTIME} STREQUAL "static") + option(IGL_STATIC_RUNTIME "Use libigl with the static MSVC runtime." OFF) + if(IGL_STATIC_RUNTIME) message(STATUS "MSVC -> forcing use of statically-linked runtime.") foreach(config ${CMAKE_CONFIGURATION_TYPES}) string(TOUPPER ${config} config) @@ -19,4 +17,10 @@ if(MSVC) endforeach() string(REPLACE "/MTd" "/MDd" CMAKE_CXX_FLAGS_DEBUG ${CMAKE_CXX_FLAGS_DEBUG}) endif() + + # https://github.com/mozilla/sccache/issues/242 + if(CMAKE_CXX_COMPILER_LAUNCHER STREQUAL "sccache") + string(REGEX REPLACE "/Z[iI7]" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") + set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /Z7") + endif() endif() diff --git a/cmake/libigl-cgal.yml b/cmake/libigl-cgal.yml new file mode 100644 index 000000000..411f830dd --- /dev/null +++ b/cmake/libigl-cgal.yml @@ -0,0 +1,8 @@ +# This is a conda environment that can be used to compile libigl with CGAL on Windows +# Only boost is required to be installed on the system, CGAL is automatically downloaded +# by CMake and is built with libigl. +name: libigl-cgal +channels: + - conda-forge +dependencies: + - boost-cpp=1.65.0 diff --git a/cmake/libigl.cmake b/cmake/libigl.cmake index 7016cbfac..d07bbb317 100644 --- a/cmake/libigl.cmake +++ b/cmake/libigl.cmake @@ -34,10 +34,13 @@ option(LIBIGL_WITH_TETGEN "Use Tetgen" OFF) option(LIBIGL_WITH_TRIANGLE "Use Triangle" OFF) option(LIBIGL_WITH_PREDICATES "Use exact predicates" OFF) option(LIBIGL_WITH_XML "Use XML" OFF) -option(LIBIGL_WITH_PYTHON "Use Python" OFF) option(LIBIGL_WITHOUT_COPYLEFT "Disable Copyleft libraries" OFF) option(LIBIGL_EXPORT_TARGETS "Export libigl CMake targets" OFF) +if(LIBIGL_BUILD_PYTHON) + message(FATAL_ERROR "Python bindings have been removed in this version. Please use an older version of libigl, or wait for the new bindings to be released.") +endif() + ################################################################################ ### Configuration @@ -56,6 +59,9 @@ endif() list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}) include(LibiglDownloadExternal) +# Provides igl_set_folders() to set folders for Visual Studio/Xcode +include(LibiglFolders) + ################################################################################ ### IGL Common ################################################################################ @@ -82,7 +88,7 @@ if(MSVC) target_compile_definitions(igl_common INTERFACE -DNOMINMAX) endif() -### Set compiler flags for building the tests on Windows with Visual Studio +# Controls whether to use the static MSVC runtime or not include(LibiglWindows) if(BUILD_SHARED_LIBS) @@ -90,22 +96,28 @@ if(BUILD_SHARED_LIBS) set_target_properties(igl_common PROPERTIES INTERFACE_POSITION_INDEPENDENT_CODE ON) endif() -if(UNIX) +if(UNIX AND NOT HUNTER_ENABLED) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") endif() +if(HUNTER_ENABLED) + hunter_add_package(Eigen) + find_package(Eigen3 CONFIG REQUIRED) +endif() + # Eigen -if(TARGET Eigen3::Eigen) - # If an imported target already exists, use it - target_link_libraries(igl_common INTERFACE Eigen3::Eigen) -else() +if(NOT TARGET Eigen3::Eigen) igl_download_eigen() - target_include_directories(igl_common SYSTEM INTERFACE + add_library(igl_eigen INTERFACE) + target_include_directories(igl_eigen SYSTEM INTERFACE $ $ ) + set_property(TARGET igl_eigen PROPERTY EXPORT_NAME Eigen3::Eigen) + add_library(Eigen3::Eigen ALIAS igl_eigen) endif() +target_link_libraries(igl_common INTERFACE Eigen3::Eigen) # C++11 Thread library find_package(Threads REQUIRED) @@ -140,17 +152,32 @@ function(compile_igl_module module_dir) endif() if(LIBIGL_USE_STATIC_LIBRARY) file(GLOB SOURCES_IGL_${module_name} - "${LIBIGL_SOURCE_DIR}/igl/${module_dir}/*.cpp") + "${LIBIGL_SOURCE_DIR}/igl/${module_dir}/*.cpp" + "${LIBIGL_SOURCE_DIR}/igl/${module_dir}/*.h*" + ) if(NOT LIBIGL_WITHOUT_COPYLEFT) file(GLOB COPYLEFT_SOURCES_IGL_${module_name} - "${LIBIGL_SOURCE_DIR}/igl/copyleft/${module_dir}/*.cpp") + "${LIBIGL_SOURCE_DIR}/igl/copyleft/${module_dir}/*.cpp" + "${LIBIGL_SOURCE_DIR}/igl/copyleft/${module_dir}/*.h*" + ) list(APPEND SOURCES_IGL_${module_name} ${COPYLEFT_SOURCES_IGL_${module_name}}) endif() add_library(${module_libname} STATIC ${SOURCES_IGL_${module_name}} ${ARGN}) if(MSVC) - target_compile_options(${module_libname} PRIVATE /w) # disable all warnings (not ideal but...) - else() - #target_compile_options(${module_libname} PRIVATE -w) # disable all warnings (not ideal but...) + # Silencing some compile warnings + target_compile_options(${module_libname} PRIVATE + # Type conversion warnings. These can be fixed with some effort and possibly more verbose code. + /wd4267 # conversion from 'size_t' to 'type', possible loss of data + /wd4244 # conversion from 'type1' to 'type2', possible loss of data + /wd4018 # signed/unsigned mismatch + /wd4305 # truncation from 'double' to 'float' + # This one is from template instantiations generated by autoexplicit.sh: + /wd4667 # no function template defined that matches forced instantiation () + # This one is easy to fix, just need to switch to safe version of C functions + /wd4996 # this function or variable may be unsafe + # This one is when using bools in adjacency matrices + /wd4804 #'+=': unsafe use of type 'bool' in operation + ) endif() else() add_library(${module_libname} INTERFACE) @@ -175,14 +202,16 @@ endfunction() if(LIBIGL_USE_STATIC_LIBRARY) file(GLOB SOURCES_IGL "${LIBIGL_SOURCE_DIR}/igl/*.cpp" - "${LIBIGL_SOURCE_DIR}/igl/copyleft/*.cpp") + "${LIBIGL_SOURCE_DIR}/igl/*.h*" + "${LIBIGL_SOURCE_DIR}/igl/copyleft/*.cpp" + "${LIBIGL_SOURCE_DIR}/igl/copyleft/*.h*" + ) endif() compile_igl_module("core" ${SOURCES_IGL}) ################################################################################ ### Download the python part ### if(LIBIGL_WITH_PYTHON) - igl_download_pybind11() endif() ################################################################################ @@ -195,14 +224,12 @@ if(LIBIGL_WITH_CGAL) set(CGAL_DIR "${LIBIGL_EXTERNAL}/cgal") igl_download_cgal() igl_download_cgal_deps() + message("BOOST_ROOT: ${BOOST_ROOT}") if(EXISTS ${LIBIGL_EXTERNAL}/boost) set(BOOST_ROOT "${LIBIGL_EXTERNAL}/boost") endif() - if(LIBIGL_WITH_PYTHON) - option(CGAL_Boost_USE_STATIC_LIBS "Use static Boost libs with CGAL" OFF) - else() - option(CGAL_Boost_USE_STATIC_LIBS "Use static Boost libs with CGAL" ON) - endif() + option(CGAL_Boost_USE_STATIC_LIBS "Use static Boost libs with CGAL" ON) + find_package(CGAL CONFIG COMPONENTS Core PATHS ${CGAL_DIR} NO_DEFAULT_PATH) endif() @@ -211,7 +238,7 @@ if(LIBIGL_WITH_CGAL) compile_igl_module("cgal") target_link_libraries(igl_cgal ${IGL_SCOPE} CGAL::CGAL CGAL::CGAL_Core) else() - set(LIBIGL_WITH_CGAL OFF CACHE BOOL "" FORCE) + message(FATAL_ERROR "Could not define CGAL::CGAL and CGAL::CGAL_Core.") endif() endif() @@ -271,21 +298,20 @@ endif() if(LIBIGL_WITH_EMBREE) set(EMBREE_DIR "${LIBIGL_EXTERNAL}/embree") - set(EMBREE_TESTING_INTENSITY 0 CACHE STRING "" FORCE) - set(EMBREE_ISPC_SUPPORT OFF CACHE BOOL " " FORCE) - set(EMBREE_TASKING_SYSTEM "INTERNAL" CACHE BOOL " " FORCE) - set(EMBREE_TUTORIALS OFF CACHE BOOL " " FORCE) - set(EMBREE_MAX_ISA "SSE2" CACHE STRING " " FORCE) - set(EMBREE_STATIC_LIB ON CACHE BOOL " " FORCE) - if(MSVC) - set(EMBREE_STATIC_RUNTIME ON CACHE BOOL " " FORCE) - endif() - if(NOT TARGET embree) - # TODO: Should probably save/restore the CMAKE_CXX_FLAGS_*, since embree seems to be - # overriding them on Windows. But well... it works for now. igl_download_embree() - add_subdirectory("${EMBREE_DIR}" "embree") + + set(EMBREE_TESTING_INTENSITY 0 CACHE STRING "") + set(EMBREE_ISPC_SUPPORT OFF CACHE BOOL " ") + set(EMBREE_TASKING_SYSTEM "INTERNAL" CACHE BOOL " ") + set(EMBREE_TUTORIALS OFF CACHE BOOL " ") + set(EMBREE_MAX_ISA "SSE2" CACHE STRING " ") + set(EMBREE_STATIC_LIB ON CACHE BOOL " ") + if(MSVC) + set(EMBREE_STATIC_RUNTIME ${IGL_STATIC_RUNTIME} CACHE BOOL "Use the static version of the C/C++ runtime library.") + endif() + + add_subdirectory("${EMBREE_DIR}" "embree" EXCLUDE_FROM_ALL) endif() compile_igl_module("embree") @@ -346,11 +372,16 @@ if(LIBIGL_WITH_OPENGL_GLFW) # GLFW module compile_igl_module("opengl/glfw") if(NOT TARGET glfw) - set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL " " FORCE) - set(GLFW_BUILD_TESTS OFF CACHE BOOL " " FORCE) - set(GLFW_BUILD_DOCS OFF CACHE BOOL " " FORCE) - set(GLFW_INSTALL OFF CACHE BOOL " " FORCE) igl_download_glfw() + option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" OFF) + option(GLFW_BUILD_TESTS "Build the GLFW test programs" OFF) + option(GLFW_BUILD_DOCS "Build the GLFW documentation" OFF) + option(GLFW_INSTALL "Generate installation target" OFF) + if(IGL_STATIC_RUNTIME) + set(USE_MSVC_RUNTIME_LIBRARY_DLL OFF CACHE BOOL "Use MSVC runtime library DLL" FORCE) + else() + set(USE_MSVC_RUNTIME_LIBRARY_DLL ON CACHE BOOL "Use MSVC runtime library DLL" FORCE) + endif() add_subdirectory(${LIBIGL_EXTERNAL}/glfw glfw) endif() target_link_libraries(igl_opengl_glfw ${IGL_SCOPE} igl_opengl glfw) @@ -460,6 +491,7 @@ function(install_dir_files dir_name) file(GLOB public_headers ${CMAKE_CURRENT_SOURCE_DIR}/include/igl${subpath}/*.h + ${CMAKE_CURRENT_SOURCE_DIR}/include/igl${subpath}/*.hpp ) set(files_to_install ${public_headers}) @@ -483,21 +515,30 @@ endfunction() include(GNUInstallDirs) include(CMakePackageConfigHelpers) +if(TARGET igl_eigen) + set(IGL_EIGEN igl_eigen) +else() + set(IGL_EIGEN) + message(WARNING "Trying to export igl targets while using an imported target for Eigen.") +endif() + # Install and export core library install( - TARGETS - igl - igl_common - EXPORT igl-export - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + TARGETS + igl + igl_common + ${IGL_EIGEN} + EXPORT igl-export + PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ) export( TARGETS igl igl_common + ${IGL_EIGEN} FILE libigl-export.cmake ) diff --git a/include/igl/AABB.cpp b/include/igl/AABB.cpp index 1ba273a1e..a6cfd503d 100644 --- a/include/igl/AABB.cpp +++ b/include/igl/AABB.cpp @@ -1076,6 +1076,13 @@ template void igl::AABB, 3>::squared_di template void igl::AABB, 3>::squared_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&) const; template void igl::AABB, 2>::squared_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&) const; template void igl::AABB, 3>::squared_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&) const; + +template void igl::AABB, 2>::init >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); +template void igl::AABB, 3>::init >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); + +template void igl::AABB, 2>::squared_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&) const; +template void igl::AABB, 3>::squared_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&) const; +template std::vector > igl::AABB, 3>::find, Eigen::Block const, 1, -1, false> >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase const, 1, -1, false> > const&, bool) const; #ifdef WIN32 template void igl::AABB,2>::squared_distance,class Eigen::Matrix,class Eigen::Matrix,class Eigen::Matrix<__int64,-1,1,0,-1,1>,class Eigen::Matrix >(class Eigen::MatrixBase > const &,class Eigen::MatrixBase > const &,class Eigen::MatrixBase > const &,class Eigen::PlainObjectBase > &,class Eigen::PlainObjectBase > &,class Eigen::PlainObjectBase > &)const; template void igl::AABB,3>::squared_distance,class Eigen::Matrix,class Eigen::Matrix,class Eigen::Matrix<__int64,-1,1,0,-1,1>,class Eigen::Matrix >(class Eigen::MatrixBase > const &,class Eigen::MatrixBase > const &,class Eigen::MatrixBase > const &,class Eigen::PlainObjectBase > &,class Eigen::PlainObjectBase > &,class Eigen::PlainObjectBase > &)const; diff --git a/include/igl/EPS.h b/include/igl/EPS.h index 17f3b8c25..d65007a64 100644 --- a/include/igl/EPS.h +++ b/include/igl/EPS.h @@ -13,8 +13,8 @@ namespace igl // Define a standard value for double epsilon const double DOUBLE_EPS = 1.0e-14; const double DOUBLE_EPS_SQ = 1.0e-28; - const float FLOAT_EPS = 1.0e-7; - const float FLOAT_EPS_SQ = 1.0e-14; + const float FLOAT_EPS = 1.0e-7f; + const float FLOAT_EPS_SQ = 1.0e-14f; // Function returning EPS for corresponding type template IGL_INLINE S_type EPS(); template IGL_INLINE S_type EPS_SQ(); diff --git a/include/igl/FastWindingNumberForSoups.h b/include/igl/FastWindingNumberForSoups.h new file mode 100644 index 000000000..215735076 --- /dev/null +++ b/include/igl/FastWindingNumberForSoups.h @@ -0,0 +1,7400 @@ +// This header created by issuing: `echo "// This header created by issuing: \`$BASH_COMMAND\` $(echo "" | cat - LICENSE README.md | sed -e "s#^..*#\/\/ &#") $(echo "" | cat - SYS_Types.h SYS_Math.h VM_SSEFunc.h VM_SIMD.h UT_Array.h UT_ArrayImpl.h UT_SmallArray.h UT_FixedVector.h UT_ParallelUtil.h UT_BVH.h UT_BVHImpl.h UT_SolidAngle.h UT_Array.cpp UT_SolidAngle.cpp | sed -e "s/^#.*include *\".*$//g")" > ../FastWindingNumberForSoups.h` +// MIT License + +// Copyright (c) 2018 Side Effects Software Inc. + +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// # Fast Winding Numbers for Soups + +// https://github.com/alecjacobson/WindingNumber + +// Implementation of the _ACM SIGGRAPH_ 2018 paper, + +// "Fast Winding Numbers for Soups and Clouds" + +// Gavin Barill¹, Neil Dickson², Ryan Schmidt³, David I.W. Levin¹, Alec Jacobson¹ + +// ¹University of Toronto, ²SideFX, ³Gradient Space + + +// _Note: this implementation is for triangle soups only, not point clouds._ + +// This version does _not_ depend on Intel TBB. Instead it depends on +// [libigl](https://github.com/libigl/libigl)'s simpler `igl::parallel_for` (which +// uses `std::thread`) + +// This code, as written, depends on Intel's Threading Building Blocks (TBB) library for parallelism, but it should be fairly easy to change it to use any other means of threading, since it only uses parallel for loops with simple partitioning. + +// The main class of interest is UT_SolidAngle and its init and computeSolidAngle functions, which you can use by including UT_SolidAngle.h, and whose implementation is mostly in UT_SolidAngle.cpp, using a 4-way bounding volume hierarchy (BVH) implemented in the UT_BVH.h and UT_BVHImpl.h headers. The rest of the files are mostly various supporting code. UT_SubtendedAngle, for computing angles subtended by 2D curves, can also be found in UT_SolidAngle.h and UT_SolidAngle.cpp . + +// An example of very similar code and how to use it to create a geometry operator (SOP) in Houdini can be found in the HDK examples (toolkit/samples/SOP/SOP_WindingNumber) for Houdini 16.5.121 and later. Query points go in the first input and the mesh geometry goes in the second input. + + +// Create a single header using: + +// echo "// This header created by issuing: \`$BASH_COMMAND\` $(echo "" | cat - LICENSE README.md | sed -e "s#^..*#\/\/&#") $(echo "" | cat - SYS_Types.h SYS_Math.h VM_SSEFunc.h VM_SIMD.h UT_Array.h UT_ArrayImpl.h UT_SmallArray.h UT_FixedVector.h UT_ParallelUtil.h UT_BVH.h UT_BVHImpl.h UT_SolidAngle.h UT_Array.cpp UT_SolidAngle.cpp | sed -e "s/^#.*include *\".*$//g")" +/* + * Copyright (c) 2018 Side Effects Software Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * COMMENTS: + * Common type definitions. + */ + +#pragma once + +#ifndef __SYS_Types__ +#define __SYS_Types__ + +/* Include system types */ +#include +#include +#include +#include + +namespace igl { namespace FastWindingNumber { + +/* + * Integer types + */ +typedef signed char int8; +typedef unsigned char uint8; +typedef short int16; +typedef unsigned short uint16; +typedef int int32; +typedef unsigned int uint32; + +#ifndef MBSD +typedef unsigned int uint; +#endif + +/* + * Avoid using uint64. + * The extra bit of precision is NOT worth the cost in pain and suffering + * induced by use of unsigned. + */ +#if defined(_WIN32) + typedef __int64 int64; + typedef unsigned __int64 uint64; +#elif defined(MBSD) + // On MBSD, int64/uint64 are also defined in the system headers so we must + // declare these in the same way or else we get conflicts. + typedef int64_t int64; + typedef uint64_t uint64; +#elif defined(AMD64) + typedef long int64; + typedef unsigned long uint64; +#else + typedef long long int64; + typedef unsigned long long uint64; +#endif + +/// The problem with int64 is that it implies that it is a fixed 64-bit quantity +/// that is saved to disk. Therefore, we need another integral type for +/// indexing our arrays. +typedef int64 exint; + +/// Mark function to be inlined. If this is done, taking the address of such +/// a function is not allowed. +#if defined(__GNUC__) || defined(__clang__) +#define SYS_FORCE_INLINE __attribute__ ((always_inline)) inline +#elif defined(_MSC_VER) +#define SYS_FORCE_INLINE __forceinline +#else +#define SYS_FORCE_INLINE inline +#endif + +/// Floating Point Types +typedef float fpreal32; +typedef double fpreal64; + +/// SYS_FPRealUnionT for type-safe casting with integral types +template +union SYS_FPRealUnionT; + +template <> +union SYS_FPRealUnionT +{ + typedef int32 int_type; + typedef uint32 uint_type; + typedef fpreal32 fpreal_type; + + enum { + EXPONENT_BITS = 8, + MANTISSA_BITS = 23, + EXPONENT_BIAS = 127 }; + + int_type ival; + uint_type uval; + fpreal_type fval; + + struct + { + uint_type mantissa_val: 23; + uint_type exponent_val: 8; + uint_type sign_val: 1; + }; +}; + +template <> +union SYS_FPRealUnionT +{ + typedef int64 int_type; + typedef uint64 uint_type; + typedef fpreal64 fpreal_type; + + enum { + EXPONENT_BITS = 11, + MANTISSA_BITS = 52, + EXPONENT_BIAS = 1023 }; + + int_type ival; + uint_type uval; + fpreal_type fval; + + struct + { + uint_type mantissa_val: 52; + uint_type exponent_val: 11; + uint_type sign_val: 1; + }; +}; + +typedef union SYS_FPRealUnionT SYS_FPRealUnionF; +typedef union SYS_FPRealUnionT SYS_FPRealUnionD; + +/// Asserts are disabled +/// @{ +#define UT_ASSERT_P(ZZ) ((void)0) +#define UT_ASSERT(ZZ) ((void)0) +#define UT_ASSERT_MSG_P(ZZ, MM) ((void)0) +#define UT_ASSERT_MSG(ZZ, MM) ((void)0) +/// @} +}} + +#endif +/* + * Copyright (c) 2018 Side Effects Software Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * COMMENTS: + * Miscellaneous math functions. + */ + +#pragma once + +#ifndef __SYS_Math__ +#define __SYS_Math__ + + + +#include +#include +#include + +namespace igl { namespace FastWindingNumber { + +// NOTE: +// These have been carefully written so that in the case of equality +// we always return the first parameter. This is so that NANs in +// in the second parameter are suppressed. +#define h_min(a, b) (((a) > (b)) ? (b) : (a)) +#define h_max(a, b) (((a) < (b)) ? (b) : (a)) +// DO NOT CHANGE THE ABOVE WITHOUT READING THE COMMENT +#define h_abs(a) (((a) > 0) ? (a) : -(a)) + +static constexpr inline int16 SYSmin(int16 a, int16 b) { return h_min(a,b); } +static constexpr inline int16 SYSmax(int16 a, int16 b) { return h_max(a,b); } +static constexpr inline int16 SYSabs(int16 a) { return h_abs(a); } +static constexpr inline int32 SYSmin(int32 a, int32 b) { return h_min(a,b); } +static constexpr inline int32 SYSmax(int32 a, int32 b) { return h_max(a,b); } +static constexpr inline int32 SYSabs(int32 a) { return h_abs(a); } +static constexpr inline int64 SYSmin(int64 a, int64 b) { return h_min(a,b); } +static constexpr inline int64 SYSmax(int64 a, int64 b) { return h_max(a,b); } +static constexpr inline int64 SYSmin(int32 a, int64 b) { return h_min(a,b); } +static constexpr inline int64 SYSmax(int32 a, int64 b) { return h_max(a,b); } +static constexpr inline int64 SYSmin(int64 a, int32 b) { return h_min(a,b); } +static constexpr inline int64 SYSmax(int64 a, int32 b) { return h_max(a,b); } +static constexpr inline int64 SYSabs(int64 a) { return h_abs(a); } +static constexpr inline uint16 SYSmin(uint16 a, uint16 b) { return h_min(a,b); } +static constexpr inline uint16 SYSmax(uint16 a, uint16 b) { return h_max(a,b); } +static constexpr inline uint32 SYSmin(uint32 a, uint32 b) { return h_min(a,b); } +static constexpr inline uint32 SYSmax(uint32 a, uint32 b) { return h_max(a,b); } +static constexpr inline uint64 SYSmin(uint64 a, uint64 b) { return h_min(a,b); } +static constexpr inline uint64 SYSmax(uint64 a, uint64 b) { return h_max(a,b); } +static constexpr inline fpreal32 SYSmin(fpreal32 a, fpreal32 b) { return h_min(a,b); } +static constexpr inline fpreal32 SYSmax(fpreal32 a, fpreal32 b) { return h_max(a,b); } +static constexpr inline fpreal64 SYSmin(fpreal64 a, fpreal64 b) { return h_min(a,b); } +static constexpr inline fpreal64 SYSmax(fpreal64 a, fpreal64 b) { return h_max(a,b); } + +// Some systems have size_t as a seperate type from uint. Some don't. +#if (defined(LINUX) && defined(IA64)) || defined(MBSD) +static constexpr inline size_t SYSmin(size_t a, size_t b) { return h_min(a,b); } +static constexpr inline size_t SYSmax(size_t a, size_t b) { return h_max(a,b); } +#endif + +#undef h_min +#undef h_max +#undef h_abs + +#define h_clamp(val, min, max, tol) \ + ((val <= min+tol) ? min : ((val >= max-tol) ? max : val)) + + static constexpr inline int + SYSclamp(int v, int min, int max) + { return h_clamp(v, min, max, 0); } + + static constexpr inline uint + SYSclamp(uint v, uint min, uint max) + { return h_clamp(v, min, max, 0); } + + static constexpr inline int64 + SYSclamp(int64 v, int64 min, int64 max) + { return h_clamp(v, min, max, int64(0)); } + + static constexpr inline uint64 + SYSclamp(uint64 v, uint64 min, uint64 max) + { return h_clamp(v, min, max, uint64(0)); } + + static constexpr inline fpreal32 + SYSclamp(fpreal32 v, fpreal32 min, fpreal32 max, fpreal32 tol=(fpreal32)0) + { return h_clamp(v, min, max, tol); } + + static constexpr inline fpreal64 + SYSclamp(fpreal64 v, fpreal64 min, fpreal64 max, fpreal64 tol=(fpreal64)0) + { return h_clamp(v, min, max, tol); } + +#undef h_clamp + +static inline fpreal64 SYSsqrt(fpreal64 arg) +{ return ::sqrt(arg); } +static inline fpreal32 SYSsqrt(fpreal32 arg) +{ return ::sqrtf(arg); } +static inline fpreal64 SYSatan2(fpreal64 a, fpreal64 b) +{ return ::atan2(a, b); } +static inline fpreal32 SYSatan2(fpreal32 a, fpreal32 b) +{ return ::atan2(a, b); } + +static inline fpreal32 SYSabs(fpreal32 a) { return ::fabsf(a); } +static inline fpreal64 SYSabs(fpreal64 a) { return ::fabs(a); } + +}} + +#endif +/* + * Copyright (c) 2018 Side Effects Software Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * COMMENTS: + * SIMD wrapper functions for SSE instructions + */ + +#pragma once + +#ifndef __VM_SSEFunc__ +#define __VM_SSEFunc__ + + + +#if defined(_MSC_VER) + #pragma warning(push) + #pragma warning(disable:4799) +#endif + +#define CPU_HAS_SIMD_INSTR 1 +#define VM_SSE_STYLE 1 + +#include + +#if defined(__SSE4_1__) +#define VM_SSE41_STYLE 1 +#include +#endif + +#if defined(_MSC_VER) + #pragma warning(pop) +#endif + +namespace igl { namespace FastWindingNumber { + +typedef __m128 v4sf; +typedef __m128i v4si; + +// Plain casting (no conversion) +// MSVC has problems casting between __m128 and __m128i, so we implement a +// custom casting routine specifically for windows. + +#if defined(_MSC_VER) + +static SYS_FORCE_INLINE v4sf +vm_v4sf(const v4si &a) +{ + union { + v4si ival; + v4sf fval; + }; + ival = a; + return fval; +} + +static SYS_FORCE_INLINE v4si +vm_v4si(const v4sf &a) +{ + union { + v4si ival; + v4sf fval; + }; + fval = a; + return ival; +} + +#define V4SF(A) vm_v4sf(A) +#define V4SI(A) vm_v4si(A) + +#else + +#define V4SF(A) (v4sf)A +#define V4SI(A) (v4si)A + +#endif + +#define VM_SHUFFLE_MASK(a0,a1, b0,b1) ((b1)<<6|(b0)<<4 | (a1)<<2|(a0)) + +template +static SYS_FORCE_INLINE v4sf +vm_shuffle(const v4sf &a, const v4sf &b) +{ + return _mm_shuffle_ps(a, b, mask); +} + +template +static SYS_FORCE_INLINE v4si +vm_shuffle(const v4si &a, const v4si &b) +{ + return V4SI(_mm_shuffle_ps(V4SF(a), V4SF(b), mask)); +} + +template +static SYS_FORCE_INLINE T +vm_shuffle(const T &a, const T &b) +{ + return vm_shuffle(a, b); +} + +template +static SYS_FORCE_INLINE T +vm_shuffle(const T &a) +{ + return vm_shuffle(a, a); +} + +template +static SYS_FORCE_INLINE T +vm_shuffle(const T &a) +{ + return vm_shuffle(a, a); +} + +#if defined(VM_SSE41_STYLE) + +static SYS_FORCE_INLINE v4si +vm_insert(const v4si v, int32 a, int n) +{ + switch (n) + { + case 0: return _mm_insert_epi32(v, a, 0); + case 1: return _mm_insert_epi32(v, a, 1); + case 2: return _mm_insert_epi32(v, a, 2); + case 3: return _mm_insert_epi32(v, a, 3); + } + return v; +} + +static SYS_FORCE_INLINE v4sf +vm_insert(const v4sf v, float a, int n) +{ + switch (n) + { + case 0: return _mm_insert_ps(v, _mm_set_ss(a), _MM_MK_INSERTPS_NDX(0,0,0)); + case 1: return _mm_insert_ps(v, _mm_set_ss(a), _MM_MK_INSERTPS_NDX(0,1,0)); + case 2: return _mm_insert_ps(v, _mm_set_ss(a), _MM_MK_INSERTPS_NDX(0,2,0)); + case 3: return _mm_insert_ps(v, _mm_set_ss(a), _MM_MK_INSERTPS_NDX(0,3,0)); + } + return v; +} + +static SYS_FORCE_INLINE int +vm_extract(const v4si v, int n) +{ + switch (n) + { + case 0: return _mm_extract_epi32(v, 0); + case 1: return _mm_extract_epi32(v, 1); + case 2: return _mm_extract_epi32(v, 2); + case 3: return _mm_extract_epi32(v, 3); + } + return 0; +} + +static SYS_FORCE_INLINE float +vm_extract(const v4sf v, int n) +{ + SYS_FPRealUnionF tmp; + switch (n) + { + case 0: tmp.ival = _mm_extract_ps(v, 0); break; + case 1: tmp.ival = _mm_extract_ps(v, 1); break; + case 2: tmp.ival = _mm_extract_ps(v, 2); break; + case 3: tmp.ival = _mm_extract_ps(v, 3); break; + } + return tmp.fval; +} + +#else + +static SYS_FORCE_INLINE v4si +vm_insert(const v4si v, int32 a, int n) +{ + union { v4si vector; int32 comp[4]; }; + vector = v; + comp[n] = a; + return vector; +} + +static SYS_FORCE_INLINE v4sf +vm_insert(const v4sf v, float a, int n) +{ + union { v4sf vector; float comp[4]; }; + vector = v; + comp[n] = a; + return vector; +} + +static SYS_FORCE_INLINE int +vm_extract(const v4si v, int n) +{ + union { v4si vector; int32 comp[4]; }; + vector = v; + return comp[n]; +} + +static SYS_FORCE_INLINE float +vm_extract(const v4sf v, int n) +{ + union { v4sf vector; float comp[4]; }; + vector = v; + return comp[n]; +} + +#endif + +static SYS_FORCE_INLINE v4sf +vm_splats(float a) +{ + return _mm_set1_ps(a); +} + +static SYS_FORCE_INLINE v4si +vm_splats(uint32 a) +{ + SYS_FPRealUnionF tmp; + tmp.uval = a; + return V4SI(vm_splats(tmp.fval)); +} + +static SYS_FORCE_INLINE v4si +vm_splats(int32 a) +{ + SYS_FPRealUnionF tmp; + tmp.ival = a; + return V4SI(vm_splats(tmp.fval)); +} + +static SYS_FORCE_INLINE v4sf +vm_splats(float a, float b, float c, float d) +{ + return vm_shuffle<0,2,0,2>( + vm_shuffle<0>(_mm_set_ss(a), _mm_set_ss(b)), + vm_shuffle<0>(_mm_set_ss(c), _mm_set_ss(d))); +} + +static SYS_FORCE_INLINE v4si +vm_splats(uint32 a, uint32 b, uint32 c, uint32 d) +{ + SYS_FPRealUnionF af, bf, cf, df; + af.uval = a; + bf.uval = b; + cf.uval = c; + df.uval = d; + return V4SI(vm_splats(af.fval, bf.fval, cf.fval, df.fval)); +} + +static SYS_FORCE_INLINE v4si +vm_splats(int32 a, int32 b, int32 c, int32 d) +{ + SYS_FPRealUnionF af, bf, cf, df; + af.ival = a; + bf.ival = b; + cf.ival = c; + df.ival = d; + return V4SI(vm_splats(af.fval, bf.fval, cf.fval, df.fval)); +} + +static SYS_FORCE_INLINE v4si +vm_load(const int32 v[4]) +{ + return V4SI(_mm_loadu_ps((const float *)v)); +} + +static SYS_FORCE_INLINE v4sf +vm_load(const float v[4]) +{ + return _mm_loadu_ps(v); +} + +static SYS_FORCE_INLINE void +vm_store(float dst[4], v4sf value) +{ + _mm_storeu_ps(dst, value); +} + +static SYS_FORCE_INLINE v4sf +vm_negate(v4sf a) +{ + return _mm_sub_ps(_mm_setzero_ps(), a); +} + +static SYS_FORCE_INLINE v4sf +vm_abs(v4sf a) +{ + return _mm_max_ps(a, vm_negate(a)); +} + +static SYS_FORCE_INLINE v4sf +vm_fdiv(v4sf a, v4sf b) +{ + return _mm_mul_ps(a, _mm_rcp_ps(b)); +} + +static SYS_FORCE_INLINE v4sf +vm_fsqrt(v4sf a) +{ + return _mm_rcp_ps(_mm_rsqrt_ps(a)); +} + +static SYS_FORCE_INLINE v4sf +vm_madd(v4sf a, v4sf b, v4sf c) +{ + return _mm_add_ps(_mm_mul_ps(a, b), c); +} + +static const v4si theSSETrue = vm_splats(0xFFFFFFFF); + +static SYS_FORCE_INLINE bool +vm_allbits(const v4si &a) +{ + return _mm_movemask_ps(V4SF(_mm_cmpeq_epi32(a, theSSETrue))) == 0xF; +} + + +#define VM_EXTRACT vm_extract +#define VM_INSERT vm_insert +#define VM_SPLATS vm_splats +#define VM_LOAD vm_load +#define VM_STORE vm_store + +#define VM_CMPLT(A,B) V4SI(_mm_cmplt_ps(A,B)) +#define VM_CMPLE(A,B) V4SI(_mm_cmple_ps(A,B)) +#define VM_CMPGT(A,B) V4SI(_mm_cmpgt_ps(A,B)) +#define VM_CMPGE(A,B) V4SI(_mm_cmpge_ps(A,B)) +#define VM_CMPEQ(A,B) V4SI(_mm_cmpeq_ps(A,B)) +#define VM_CMPNE(A,B) V4SI(_mm_cmpneq_ps(A,B)) + +#define VM_ICMPLT _mm_cmplt_epi32 +#define VM_ICMPGT _mm_cmpgt_epi32 +#define VM_ICMPEQ _mm_cmpeq_epi32 + +#define VM_IADD _mm_add_epi32 +#define VM_ISUB _mm_sub_epi32 + +#define VM_ADD _mm_add_ps +#define VM_SUB _mm_sub_ps +#define VM_MUL _mm_mul_ps +#define VM_DIV _mm_div_ps +#define VM_SQRT _mm_sqrt_ps +#define VM_ISQRT _mm_rsqrt_ps +#define VM_INVERT _mm_rcp_ps +#define VM_ABS vm_abs + +#define VM_FDIV vm_fdiv +#define VM_NEG vm_negate +#define VM_FSQRT vm_fsqrt +#define VM_MADD vm_madd + +#define VM_MIN _mm_min_ps +#define VM_MAX _mm_max_ps + +#define VM_AND _mm_and_si128 +#define VM_ANDNOT _mm_andnot_si128 +#define VM_OR _mm_or_si128 +#define VM_XOR _mm_xor_si128 + +#define VM_ALLBITS vm_allbits + +#define VM_SHUFFLE vm_shuffle + +// Integer to float conversions +#define VM_SSE_ROUND_MASK 0x6000 +#define VM_SSE_ROUND_ZERO 0x6000 +#define VM_SSE_ROUND_UP 0x4000 +#define VM_SSE_ROUND_DOWN 0x2000 +#define VM_SSE_ROUND_NEAR 0x0000 + +#define GETROUND() (_mm_getcsr()&VM_SSE_ROUND_MASK) +#define SETROUND(x) (_mm_setcsr(x|(_mm_getcsr()&~VM_SSE_ROUND_MASK))) + +// The P functions must be invoked before FLOOR, the E functions invoked +// afterwards to reset the state. + +#define VM_P_FLOOR() uint rounding = GETROUND(); \ + SETROUND(VM_SSE_ROUND_DOWN); +#define VM_FLOOR _mm_cvtps_epi32 +#define VM_INT _mm_cvttps_epi32 +#define VM_E_FLOOR() SETROUND(rounding); + +// Float to integer conversion +#define VM_IFLOAT _mm_cvtepi32_ps +}} + +#endif +/* + * Copyright (c) 2018 Side Effects Software Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * COMMENTS: + * SIMD wrapper classes for 4 floats or 4 ints + */ + +#pragma once + +#ifndef __HDK_VM_SIMD__ +#define __HDK_VM_SIMD__ + + +#include + +//#define FORCE_NON_SIMD + + +namespace igl { namespace FastWindingNumber { + +class v4uf; + +class v4uu { +public: + SYS_FORCE_INLINE v4uu() {} + SYS_FORCE_INLINE v4uu(const v4si &v) : vector(v) {} + SYS_FORCE_INLINE v4uu(const v4uu &v) : vector(v.vector) {} + explicit SYS_FORCE_INLINE v4uu(int32 v) { vector = VM_SPLATS(v); } + explicit SYS_FORCE_INLINE v4uu(const int32 v[4]) + { vector = VM_LOAD(v); } + SYS_FORCE_INLINE v4uu(int32 a, int32 b, int32 c, int32 d) + { vector = VM_SPLATS(a, b, c, d); } + + // Assignment + SYS_FORCE_INLINE v4uu operator=(int32 v) + { vector = v4uu(v).vector; return *this; } + SYS_FORCE_INLINE v4uu operator=(v4si v) + { vector = v; return *this; } + SYS_FORCE_INLINE v4uu operator=(const v4uu &v) + { vector = v.vector; return *this; } + + SYS_FORCE_INLINE void condAssign(const v4uu &val, const v4uu &c) + { *this = (c & val) | ((!c) & *this); } + + // Comparison + SYS_FORCE_INLINE v4uu operator == (const v4uu &v) const + { return v4uu(VM_ICMPEQ(vector, v.vector)); } + SYS_FORCE_INLINE v4uu operator != (const v4uu &v) const + { return ~(*this == v); } + SYS_FORCE_INLINE v4uu operator > (const v4uu &v) const + { return v4uu(VM_ICMPGT(vector, v.vector)); } + SYS_FORCE_INLINE v4uu operator < (const v4uu &v) const + { return v4uu(VM_ICMPLT(vector, v.vector)); } + SYS_FORCE_INLINE v4uu operator >= (const v4uu &v) const + { return ~(*this < v); } + SYS_FORCE_INLINE v4uu operator <= (const v4uu &v) const + { return ~(*this > v); } + + SYS_FORCE_INLINE v4uu operator == (int32 v) const { return *this == v4uu(v); } + SYS_FORCE_INLINE v4uu operator != (int32 v) const { return *this != v4uu(v); } + SYS_FORCE_INLINE v4uu operator > (int32 v) const { return *this > v4uu(v); } + SYS_FORCE_INLINE v4uu operator < (int32 v) const { return *this < v4uu(v); } + SYS_FORCE_INLINE v4uu operator >= (int32 v) const { return *this >= v4uu(v); } + SYS_FORCE_INLINE v4uu operator <= (int32 v) const { return *this <= v4uu(v); } + + // Basic math + SYS_FORCE_INLINE v4uu operator+(const v4uu &r) const + { return v4uu(VM_IADD(vector, r.vector)); } + SYS_FORCE_INLINE v4uu operator-(const v4uu &r) const + { return v4uu(VM_ISUB(vector, r.vector)); } + SYS_FORCE_INLINE v4uu operator+=(const v4uu &r) { return (*this = *this + r); } + SYS_FORCE_INLINE v4uu operator-=(const v4uu &r) { return (*this = *this - r); } + SYS_FORCE_INLINE v4uu operator+(int32 r) const { return *this + v4uu(r); } + SYS_FORCE_INLINE v4uu operator-(int32 r) const { return *this - v4uu(r); } + SYS_FORCE_INLINE v4uu operator+=(int32 r) { return (*this = *this + r); } + SYS_FORCE_INLINE v4uu operator-=(int32 r) { return (*this = *this - r); } + + // logical/bitwise + + SYS_FORCE_INLINE v4uu operator||(const v4uu &r) const + { return v4uu(VM_OR(vector, r.vector)); } + SYS_FORCE_INLINE v4uu operator&&(const v4uu &r) const + { return v4uu(VM_AND(vector, r.vector)); } + SYS_FORCE_INLINE v4uu operator^(const v4uu &r) const + { return v4uu(VM_XOR(vector, r.vector)); } + SYS_FORCE_INLINE v4uu operator!() const + { return *this == v4uu(0); } + + SYS_FORCE_INLINE v4uu operator|(const v4uu &r) const { return *this || r; } + SYS_FORCE_INLINE v4uu operator&(const v4uu &r) const { return *this && r; } + SYS_FORCE_INLINE v4uu operator~() const + { return *this ^ v4uu(0xFFFFFFFF); } + + // component + SYS_FORCE_INLINE int32 operator[](int idx) const { return VM_EXTRACT(vector, idx); } + SYS_FORCE_INLINE void setComp(int idx, int32 v) { vector = VM_INSERT(vector, v, idx); } + + v4uf toFloat() const; + +public: + v4si vector; +}; + +class v4uf { +public: + SYS_FORCE_INLINE v4uf() {} + SYS_FORCE_INLINE v4uf(const v4sf &v) : vector(v) {} + SYS_FORCE_INLINE v4uf(const v4uf &v) : vector(v.vector) {} + explicit SYS_FORCE_INLINE v4uf(float v) { vector = VM_SPLATS(v); } + explicit SYS_FORCE_INLINE v4uf(const float v[4]) + { vector = VM_LOAD(v); } + SYS_FORCE_INLINE v4uf(float a, float b, float c, float d) + { vector = VM_SPLATS(a, b, c, d); } + + // Assignment + SYS_FORCE_INLINE v4uf operator=(float v) + { vector = v4uf(v).vector; return *this; } + SYS_FORCE_INLINE v4uf operator=(v4sf v) + { vector = v; return *this; } + SYS_FORCE_INLINE v4uf operator=(const v4uf &v) + { vector = v.vector; return *this; } + + SYS_FORCE_INLINE void condAssign(const v4uf &val, const v4uu &c) + { *this = (val & c) | (*this & ~c); } + + // Comparison + SYS_FORCE_INLINE v4uu operator == (const v4uf &v) const + { return v4uu(VM_CMPEQ(vector, v.vector)); } + SYS_FORCE_INLINE v4uu operator != (const v4uf &v) const + { return v4uu(VM_CMPNE(vector, v.vector)); } + SYS_FORCE_INLINE v4uu operator > (const v4uf &v) const + { return v4uu(VM_CMPGT(vector, v.vector)); } + SYS_FORCE_INLINE v4uu operator < (const v4uf &v) const + { return v4uu(VM_CMPLT(vector, v.vector)); } + SYS_FORCE_INLINE v4uu operator >= (const v4uf &v) const + { return v4uu(VM_CMPGE(vector, v.vector)); } + SYS_FORCE_INLINE v4uu operator <= (const v4uf &v) const + { return v4uu(VM_CMPLE(vector, v.vector)); } + + SYS_FORCE_INLINE v4uu operator == (float v) const { return *this == v4uf(v); } + SYS_FORCE_INLINE v4uu operator != (float v) const { return *this != v4uf(v); } + SYS_FORCE_INLINE v4uu operator > (float v) const { return *this > v4uf(v); } + SYS_FORCE_INLINE v4uu operator < (float v) const { return *this < v4uf(v); } + SYS_FORCE_INLINE v4uu operator >= (float v) const { return *this >= v4uf(v); } + SYS_FORCE_INLINE v4uu operator <= (float v) const { return *this <= v4uf(v); } + + + // Basic math + SYS_FORCE_INLINE v4uf operator+(const v4uf &r) const + { return v4uf(VM_ADD(vector, r.vector)); } + SYS_FORCE_INLINE v4uf operator-(const v4uf &r) const + { return v4uf(VM_SUB(vector, r.vector)); } + SYS_FORCE_INLINE v4uf operator-() const + { return v4uf(VM_NEG(vector)); } + SYS_FORCE_INLINE v4uf operator*(const v4uf &r) const + { return v4uf(VM_MUL(vector, r.vector)); } + SYS_FORCE_INLINE v4uf operator/(const v4uf &r) const + { return v4uf(VM_DIV(vector, r.vector)); } + + SYS_FORCE_INLINE v4uf operator+=(const v4uf &r) { return (*this = *this + r); } + SYS_FORCE_INLINE v4uf operator-=(const v4uf &r) { return (*this = *this - r); } + SYS_FORCE_INLINE v4uf operator*=(const v4uf &r) { return (*this = *this * r); } + SYS_FORCE_INLINE v4uf operator/=(const v4uf &r) { return (*this = *this / r); } + + SYS_FORCE_INLINE v4uf operator+(float r) const { return *this + v4uf(r); } + SYS_FORCE_INLINE v4uf operator-(float r) const { return *this - v4uf(r); } + SYS_FORCE_INLINE v4uf operator*(float r) const { return *this * v4uf(r); } + SYS_FORCE_INLINE v4uf operator/(float r) const { return *this / v4uf(r); } + SYS_FORCE_INLINE v4uf operator+=(float r) { return (*this = *this + r); } + SYS_FORCE_INLINE v4uf operator-=(float r) { return (*this = *this - r); } + SYS_FORCE_INLINE v4uf operator*=(float r) { return (*this = *this * r); } + SYS_FORCE_INLINE v4uf operator/=(float r) { return (*this = *this / r); } + + // logical/bitwise + + SYS_FORCE_INLINE v4uf operator||(const v4uu &r) const + { return v4uf(V4SF(VM_OR(V4SI(vector), r.vector))); } + SYS_FORCE_INLINE v4uf operator&&(const v4uu &r) const + { return v4uf(V4SF(VM_AND(V4SI(vector), r.vector))); } + SYS_FORCE_INLINE v4uf operator^(const v4uu &r) const + { return v4uf(V4SF(VM_XOR(V4SI(vector), r.vector))); } + SYS_FORCE_INLINE v4uf operator!() const + { return v4uf(V4SF((*this == v4uf(0.0F)).vector)); } + + SYS_FORCE_INLINE v4uf operator||(const v4uf &r) const + { return v4uf(V4SF(VM_OR(V4SI(vector), V4SI(r.vector)))); } + SYS_FORCE_INLINE v4uf operator&&(const v4uf &r) const + { return v4uf(V4SF(VM_AND(V4SI(vector), V4SI(r.vector)))); } + SYS_FORCE_INLINE v4uf operator^(const v4uf &r) const + { return v4uf(V4SF(VM_XOR(V4SI(vector), V4SI(r.vector)))); } + + SYS_FORCE_INLINE v4uf operator|(const v4uu &r) const { return *this || r; } + SYS_FORCE_INLINE v4uf operator&(const v4uu &r) const { return *this && r; } + SYS_FORCE_INLINE v4uf operator~() const + { return *this ^ v4uu(0xFFFFFFFF); } + + SYS_FORCE_INLINE v4uf operator|(const v4uf &r) const { return *this || r; } + SYS_FORCE_INLINE v4uf operator&(const v4uf &r) const { return *this && r; } + + // component + SYS_FORCE_INLINE float operator[](int idx) const { return VM_EXTRACT(vector, idx); } + SYS_FORCE_INLINE void setComp(int idx, float v) { vector = VM_INSERT(vector, v, idx); } + + // more math + SYS_FORCE_INLINE v4uf abs() const { return v4uf(VM_ABS(vector)); } + SYS_FORCE_INLINE v4uf clamp(const v4uf &low, const v4uf &high) const + { return v4uf( + VM_MIN(VM_MAX(vector, low.vector), high.vector)); } + SYS_FORCE_INLINE v4uf clamp(float low, float high) const + { return v4uf(VM_MIN(VM_MAX(vector, + v4uf(low).vector), v4uf(high).vector)); } + SYS_FORCE_INLINE v4uf recip() const { return v4uf(VM_INVERT(vector)); } + + /// This is a lie, it is a signed int. + SYS_FORCE_INLINE v4uu toUnsignedInt() const { return VM_INT(vector); } + SYS_FORCE_INLINE v4uu toSignedInt() const { return VM_INT(vector); } + + v4uu floor() const + { + VM_P_FLOOR(); + v4uu result = VM_FLOOR(vector); + VM_E_FLOOR(); + return result; + } + + /// Returns the integer part of this float, this becomes the + /// 0..1 fractional component. + v4uu splitFloat() + { + v4uu base = toSignedInt(); + *this -= base.toFloat(); + return base; + } + + template + SYS_FORCE_INLINE v4uf swizzle() const + { + return VM_SHUFFLE(vector); + } + + SYS_FORCE_INLINE v4uu isFinite() const + { + // If the exponent is the maximum value, it's either infinite or NaN. + const v4si mask = VM_SPLATS(0x7F800000); + return ~v4uu(VM_ICMPEQ(VM_AND(V4SI(vector), mask), mask)); + } + +public: + v4sf vector; +}; + +SYS_FORCE_INLINE v4uf +v4uu::toFloat() const +{ + return v4uf(VM_IFLOAT(vector)); +} + +// +// Custom vector operations +// + +static SYS_FORCE_INLINE v4uf +sqrt(const v4uf &a) +{ + return v4uf(VM_SQRT(a.vector)); +} + +static SYS_FORCE_INLINE v4uf +fabs(const v4uf &a) +{ + return a.abs(); +} + +// Use this operation to mask disabled values to 0 +// rval = !a ? b : 0; + +static SYS_FORCE_INLINE v4uf +andn(const v4uu &a, const v4uf &b) +{ + return v4uf(V4SF(VM_ANDNOT(a.vector, V4SI(b.vector)))); +} + +static SYS_FORCE_INLINE v4uu +andn(const v4uu &a, const v4uu &b) +{ + return v4uu(VM_ANDNOT(a.vector, b.vector)); +} + +// rval = a ? b : c; +static SYS_FORCE_INLINE v4uf +ternary(const v4uu &a, const v4uf &b, const v4uf &c) +{ + return (b & a) | andn(a, c); +} + +static SYS_FORCE_INLINE v4uu +ternary(const v4uu &a, const v4uu &b, const v4uu &c) +{ + return (b & a) | andn(a, c); +} + +// rval = !(a && b) +static SYS_FORCE_INLINE v4uu +nand(const v4uu &a, const v4uu &b) +{ + return !v4uu(VM_AND(a.vector, b.vector)); +} + +static SYS_FORCE_INLINE v4uf +vmin(const v4uf &a, const v4uf &b) +{ + return v4uf(VM_MIN(a.vector, b.vector)); +} + +static SYS_FORCE_INLINE v4uf +vmax(const v4uf &a, const v4uf &b) +{ + return v4uf(VM_MAX(a.vector, b.vector)); +} + +static SYS_FORCE_INLINE v4uf +clamp(const v4uf &a, const v4uf &b, const v4uf &c) +{ + return vmax(vmin(a, c), b); +} + +static SYS_FORCE_INLINE v4uf +clamp(const v4uf &a, float b, float c) +{ + return vmax(vmin(a, v4uf(c)), v4uf(b)); +} + +static SYS_FORCE_INLINE bool +allbits(const v4uu &a) +{ + return vm_allbits(a.vector); +} + +static SYS_FORCE_INLINE bool +anybits(const v4uu &a) +{ + return !allbits(~a); +} + +static SYS_FORCE_INLINE v4uf +madd(const v4uf &v, const v4uf &f, const v4uf &a) +{ + return v4uf(VM_MADD(v.vector, f.vector, a.vector)); +} + +static SYS_FORCE_INLINE v4uf +madd(const v4uf &v, float f, float a) +{ + return v4uf(VM_MADD(v.vector, v4uf(f).vector, v4uf(a).vector)); +} + +static SYS_FORCE_INLINE v4uf +madd(const v4uf &v, float f, const v4uf &a) +{ + return v4uf(VM_MADD(v.vector, v4uf(f).vector, a.vector)); +} + +static SYS_FORCE_INLINE v4uf +msub(const v4uf &v, const v4uf &f, const v4uf &s) +{ + return madd(v, f, -s); +} + +static SYS_FORCE_INLINE v4uf +msub(const v4uf &v, float f, float s) +{ + return madd(v, f, -s); +} + +static SYS_FORCE_INLINE v4uf +lerp(const v4uf &a, const v4uf &b, const v4uf &w) +{ + v4uf w1 = v4uf(1.0F) - w; + return madd(a, w1, b*w); +} + +static SYS_FORCE_INLINE v4uf +luminance(const v4uf &r, const v4uf &g, const v4uf &b, + float rw, float gw, float bw) +{ + return v4uf(madd(r, v4uf(rw), madd(g, v4uf(gw), b * bw))); +} + +static SYS_FORCE_INLINE float +dot3(const v4uf &a, const v4uf &b) +{ + v4uf res = a*b; + return res[0] + res[1] + res[2]; +} + +static SYS_FORCE_INLINE float +dot4(const v4uf &a, const v4uf &b) +{ + v4uf res = a*b; + return res[0] + res[1] + res[2] + res[3]; +} + +static SYS_FORCE_INLINE float +length(const v4uf &a) +{ + return SYSsqrt(dot3(a, a)); +} + +static SYS_FORCE_INLINE v4uf +normalize(const v4uf &a) +{ + return a / length(a); +} + +static SYS_FORCE_INLINE v4uf +cross(const v4uf &a, const v4uf &b) +{ + return v4uf(a[1]*b[2] - a[2]*b[1], + a[2]*b[0] - a[0]*b[2], + a[0]*b[1] - a[1]*b[0], 0); +} + +// Currently there is no specific support for signed integers +typedef v4uu v4ui; + +// Assuming that ptr is an array of elements of type STYPE, this operation +// will return the index of the first element that is aligned to (1< +#include +#include +#include + +namespace igl { namespace FastWindingNumber { + + /// This routine describes how to change the size of an array. + /// It must increase the current_size by at least one! + /// + /// Current expected sequence of small sizes: + /// 4, 8, 16, 32, 48, 64, 80, 96, 112, + /// 128, 256, 384, 512, 640, 768, 896, 1024, + /// (increases by approx factor of 1.125 each time after this) +template +static inline T +UTbumpAlloc(T current_size) +{ + // NOTE: These must be powers of two. See below. + constexpr T SMALL_ALLOC(16); + constexpr T BIG_ALLOC(128); + + // For small values, we increment by fixed amounts. For + // large values, we increment by one eighth of the current size. + // This prevents n^2 behaviour with allocation one element at a time. + // A factor of 1/8 will waste 1/16 the memory on average, and will + // double the size of the array in approximately 6 reallocations. + if (current_size < T(8)) + { + return (current_size < T(4)) ? T(4) : T(8); + } + if (current_size < T(BIG_ALLOC)) + { + // Snap up to next multiple of SMALL_ALLOC (must be power of 2) + return (current_size + T(SMALL_ALLOC)) & ~T(SMALL_ALLOC-1); + } + if (current_size < T(BIG_ALLOC * 8)) + { + // Snap up to next multiple of BIG_ALLOC (must be power of 2) + return (current_size + T(BIG_ALLOC)) & ~T(BIG_ALLOC-1); + } + + T bump = current_size >> 3; // Divided by 8. + current_size += bump; + return current_size; +} + +template +class UT_Array +{ +public: + typedef T value_type; + + typedef int (*Comparator)(const T *, const T *); + + /// Copy constructor. It duplicates the data. + /// It's marked explicit so that it's not accidentally passed by value. + /// You can always pass by reference and then copy it, if needed. + /// If you have a line like: + /// UT_Array a = otherarray; + /// and it really does need to copy instead of referencing, + /// you can rewrite it as: + /// UT_Array a(otherarray); + inline explicit UT_Array(const UT_Array &a); + + /// Move constructor. Steals the working data from the original. + inline UT_Array(UT_Array &&a) noexcept; + + /// Construct based on given capacity and size + UT_Array(exint capacity, exint size) + { + myData = capacity ? allocateCapacity(capacity) : NULL; + if (capacity < size) + size = capacity; + mySize = size; + myCapacity = capacity; + trivialConstructRange(myData, mySize); + } + + /// Construct based on given capacity with a size of 0 + explicit UT_Array(exint capacity = 0) : myCapacity(capacity), mySize(0) + { + myData = capacity ? allocateCapacity(capacity) : NULL; + } + + /// Construct with the contents of an initializer list + inline explicit UT_Array(std::initializer_list init); + + inline ~UT_Array(); + + inline void swap(UT_Array &other); + + /// Append an element to the current elements and return its index in the + /// array, or insert the element at a specified position; if necessary, + /// insert() grows the array to accommodate the element. The insert + /// methods use the assignment operator '=' to place the element into the + /// right spot; be aware that '=' works differently on objects and pointers. + /// The test for duplicates uses the logical equal operator '=='; as with + /// '=', the behaviour of the equality operator on pointers versus objects + /// is not the same. + /// Use the subscript operators instead of insert() if you are appending + /// to the array, or if you don't mind overwriting the element already + /// inserted at the given index. + exint append(void) { return insert(mySize); } + exint append(const T &t) { return appendImpl(t); } + exint append(T &&t) { return appendImpl(std::move(t)); } + inline void append(const T *pt, exint count); + inline void appendMultiple(const T &t, exint count); + inline exint insert(exint index); + exint insert(const T &t, exint i) + { return insertImpl(t, i); } + exint insert(T &&t, exint i) + { return insertImpl(std::move(t), i); } + + /// Adds a new element to the array (resizing if necessary) and forwards + /// the given arguments to T's constructor. + /// NOTE: Unlike append(), the arguments cannot reference any existing + /// elements in the array. Checking for and handling such cases would + /// remove most of the performance gain versus append(T(...)). Debug builds + /// will assert that the arguments are valid. + template + inline exint emplace_back(S&&... s); + + /// Takes another T array and concatenate it onto my end + inline exint concat(const UT_Array &a); + + /// Insert an element "count" times at the given index. Return the index. + inline exint multipleInsert(exint index, exint count); + + /// An alias for unique element insertion at a certain index. Also used by + /// the other insertion methods. + exint insertAt(const T &t, exint index) + { return insertImpl(t, index); } + + /// Return true if given index is valid. + bool isValidIndex(exint index) const + { return (index >= 0 && index < mySize); } + + /// Remove one element from the array given its + /// position in the list, and fill the gap by shifting the elements down + /// by one position. Return the index of the element removed or -1 if + /// the index was out of bounds. + exint removeIndex(exint index) + { + return isValidIndex(index) ? removeAt(index) : -1; + } + void removeLast() + { + if (mySize) removeAt(mySize-1); + } + + /// Remove the range [begin_i,end_i) of elements from the array. + inline void removeRange(exint begin_i, exint end_i); + + /// Remove the range [begin_i, end_i) of elements from this array and place + /// them in the dest array, shrinking/growing the dest array as necessary. + inline void extractRange(exint begin_i, exint end_i, + UT_Array& dest); + + /// Removes all matching elements from the list, shuffling down and changing + /// the size appropriately. + /// Returns the number of elements left. + template + inline exint removeIf(IsEqual is_equal); + + /// Remove all matching elements. Also sets the capacity of the array. + template + void collapseIf(IsEqual is_equal) + { + removeIf(is_equal); + setCapacity(size()); + } + + /// Move howMany objects starting at index srcIndex to destIndex; + /// This method will remove the elements at [srcIdx, srcIdx+howMany) and + /// then insert them at destIdx. This method can be used in place of + /// the old shift() operation. + inline void move(exint srcIdx, exint destIdx, exint howMany); + + /// Cyclically shifts the entire array by howMany + inline void cycle(exint howMany); + + /// Quickly set the array to a single value. + inline void constant(const T &v); + /// Zeros the array if a POD type, else trivial constructs if a class type. + inline void zero(); + + /// The fastest search possible, which does pointer arithmetic to find the + /// index of the element. WARNING: index() does no out-of-bounds checking. + exint index(const T &t) const { return &t - myData; } + exint safeIndex(const T &t) const + { + return (&t >= myData && &t < (myData + mySize)) + ? &t - myData : -1; + } + + /// Set the capacity of the array, i.e. grow it or shrink it. The + /// function copies the data after reallocating space for the array. + inline void setCapacity(exint newcapacity); + void setCapacityIfNeeded(exint mincapacity) + { + if (capacity() < mincapacity) + setCapacity(mincapacity); + } + /// If the capacity is smaller than mincapacity, expand the array + /// to at least mincapacity and to at least a constant factor of the + /// array's previous capacity, to avoid having a linear number of + /// reallocations in a linear number of calls to bumpCapacity. + void bumpCapacity(exint mincapacity) + { + if (capacity() >= mincapacity) + return; + // The following 4 lines are just + // SYSmax(mincapacity, UTbumpAlloc(capacity())), avoiding SYSmax + exint bumped = UTbumpAlloc(capacity()); + exint newcapacity = mincapacity; + if (bumped > mincapacity) + newcapacity = bumped; + setCapacity(newcapacity); + } + + /// First bumpCapacity to ensure that there's space for newsize, + /// expanding either not at all or by at least a constant factor + /// of the array's previous capacity, + /// then set the size to newsize. + void bumpSize(exint newsize) + { + bumpCapacity(newsize); + setSize(newsize); + } + /// NOTE: bumpEntries() will be deprecated in favour of bumpSize() in a + /// future version. + void bumpEntries(exint newsize) + { + bumpSize(newsize); + } + + /// Query the capacity, i.e. the allocated length of the array. + /// NOTE: capacity() >= size(). + exint capacity() const { return myCapacity; } + /// Query the size, i.e. the number of occupied elements in the array. + /// NOTE: capacity() >= size(). + exint size() const { return mySize; } + /// Alias of size(). size() is preferred. + exint entries() const { return mySize; } + /// Returns true iff there are no occupied elements in the array. + bool isEmpty() const { return mySize==0; } + + /// Set the size, the number of occupied elements in the array. + /// NOTE: This will not do bumpCapacity, so if you call this + /// n times to increase the size, it may take + /// n^2 time. + void setSize(exint newsize) + { + if (newsize < 0) + newsize = 0; + if (newsize == mySize) + return; + setCapacityIfNeeded(newsize); + if (mySize > newsize) + trivialDestructRange(myData + newsize, mySize - newsize); + else // newsize > mySize + trivialConstructRange(myData + mySize, newsize - mySize); + mySize = newsize; + } + /// Alias of setSize(). setSize() is preferred. + void entries(exint newsize) + { + setSize(newsize); + } + /// Set the size, but unlike setSize(newsize), this function + /// will not initialize new POD elements to zero. Non-POD data types + /// will still have their constructors called. + /// This function is faster than setSize(ne) if you intend to fill in + /// data for all elements. + void setSizeNoInit(exint newsize) + { + if (newsize < 0) + newsize = 0; + if (newsize == mySize) + return; + setCapacityIfNeeded(newsize); + if (mySize > newsize) + trivialDestructRange(myData + newsize, mySize - newsize); + else if (!isPOD()) // newsize > mySize + trivialConstructRange(myData + mySize, newsize - mySize); + mySize = newsize; + } + + /// Decreases, but never expands, to the given maxsize. + void truncate(exint maxsize) + { + if (maxsize >= 0 && size() > maxsize) + setSize(maxsize); + } + /// Resets list to an empty list. + void clear() { + // Don't call setSize(0) since that would require a valid default + // constructor. + trivialDestructRange(myData, mySize); + mySize = 0; + } + + /// Assign array a to this array by copying each of a's elements with + /// memcpy for POD types, and with copy construction for class types. + inline UT_Array & operator=(const UT_Array &a); + + /// Replace the contents with those from the initializer_list ilist + inline UT_Array & operator=(std::initializer_list ilist); + + /// Move the contents of array a to this array. + inline UT_Array & operator=(UT_Array &&a); + + /// Compare two array and return true if they are equal and false otherwise. + /// Two elements are checked against each other using operator '==' or + /// compare() respectively. + /// NOTE: The capacities of the arrays are not checked when + /// determining whether they are equal. + inline bool operator==(const UT_Array &a) const; + inline bool operator!=(const UT_Array &a) const; + + /// Subscript operator + /// NOTE: This does NOT do any bounds checking unless paranoid + /// asserts are enabled. + T & operator()(exint i) + { + UT_ASSERT_P(i >= 0 && i < mySize); + return myData[i]; + } + /// Const subscript operator + /// NOTE: This does NOT do any bounds checking unless paranoid + /// asserts are enabled. + const T & operator()(exint i) const + { + UT_ASSERT_P(i >= 0 && i < mySize); + return myData[i]; + } + + /// Subscript operator + /// NOTE: This does NOT do any bounds checking unless paranoid + /// asserts are enabled. + T & operator[](exint i) + { + UT_ASSERT_P(i >= 0 && i < mySize); + return myData[i]; + } + /// Const subscript operator + /// NOTE: This does NOT do any bounds checking unless paranoid + /// asserts are enabled. + const T & operator[](exint i) const + { + UT_ASSERT_P(i >= 0 && i < mySize); + return myData[i]; + } + + /// forcedRef(exint) will grow the array if necessary, initializing any + /// new elements to zero for POD types and default constructing for + /// class types. + T & forcedRef(exint i) + { + UT_ASSERT_P(i >= 0); + if (i >= mySize) + bumpSize(i+1); + return myData[i]; + } + + /// forcedGet(exint) does NOT grow the array, and will return default + /// objects for out of bound array indices. + T forcedGet(exint i) const + { + return (i >= 0 && i < mySize) ? myData[i] : T(); + } + + T & last() + { + UT_ASSERT_P(mySize); + return myData[mySize-1]; + } + const T & last() const + { + UT_ASSERT_P(mySize); + return myData[mySize-1]; + } + + T * getArray() const { return myData; } + const T * getRawArray() const { return myData; } + + T * array() { return myData; } + const T * array() const { return myData; } + + T * data() { return myData; } + const T * data() const { return myData; } + + /// This method allows you to swap in a new raw T array, which must be + /// the same size as myCapacity. Use caution with this method. + T * aliasArray(T *newdata) + { T *data = myData; myData = newdata; return data; } + + template + class base_iterator : + public std::iterator + { + public: + typedef IT& reference; + typedef IT* pointer; + + // Note: When we drop gcc 4.4 support and allow range-based for + // loops, we should also drop atEnd(), which means we can drop + // myEnd here. + base_iterator() : myCurrent(NULL), myEnd(NULL) {} + + // Allow iterator to const_iterator conversion + template + base_iterator(const base_iterator &src) + : myCurrent(src.myCurrent), myEnd(src.myEnd) {} + + pointer operator->() const + { return FORWARD ? myCurrent : myCurrent - 1; } + + reference operator*() const + { return FORWARD ? *myCurrent : myCurrent[-1]; } + + reference item() const + { return FORWARD ? *myCurrent : myCurrent[-1]; } + + reference operator[](exint n) const + { return FORWARD ? myCurrent[n] : myCurrent[-n - 1]; } + + /// Pre-increment operator + base_iterator &operator++() + { + if (FORWARD) ++myCurrent; else --myCurrent; + return *this; + } + /// Post-increment operator + base_iterator operator++(int) + { + base_iterator tmp = *this; + if (FORWARD) ++myCurrent; else --myCurrent; + return tmp; + } + /// Pre-decrement operator + base_iterator &operator--() + { + if (FORWARD) --myCurrent; else ++myCurrent; + return *this; + } + /// Post-decrement operator + base_iterator operator--(int) + { + base_iterator tmp = *this; + if (FORWARD) --myCurrent; else ++myCurrent; + return tmp; + } + + base_iterator &operator+=(exint n) + { + if (FORWARD) + myCurrent += n; + else + myCurrent -= n; + return *this; + } + base_iterator operator+(exint n) const + { + if (FORWARD) + return base_iterator(myCurrent + n, myEnd); + else + return base_iterator(myCurrent - n, myEnd); + } + + base_iterator &operator-=(exint n) + { return (*this) += (-n); } + base_iterator operator-(exint n) const + { return (*this) + (-n); } + + bool atEnd() const { return myCurrent == myEnd; } + void advance() { this->operator++(); } + + // Comparators + template + bool operator==(const base_iterator &r) const + { return myCurrent == r.myCurrent; } + + template + bool operator!=(const base_iterator &r) const + { return myCurrent != r.myCurrent; } + + template + bool operator<(const base_iterator &r) const + { + if (FORWARD) + return myCurrent < r.myCurrent; + else + return r.myCurrent < myCurrent; + } + + template + bool operator>(const base_iterator &r) const + { + if (FORWARD) + return myCurrent > r.myCurrent; + else + return r.myCurrent > myCurrent; + } + + template + bool operator<=(const base_iterator &r) const + { + if (FORWARD) + return myCurrent <= r.myCurrent; + else + return r.myCurrent <= myCurrent; + } + + template + bool operator>=(const base_iterator &r) const + { + if (FORWARD) + return myCurrent >= r.myCurrent; + else + return r.myCurrent >= myCurrent; + } + + // Difference operator for std::distance + template + exint operator-(const base_iterator &r) const + { + if (FORWARD) + return exint(myCurrent - r.myCurrent); + else + return exint(r.myCurrent - myCurrent); + } + + + protected: + friend class UT_Array; + base_iterator(IT *c, IT *e) : myCurrent(c), myEnd(e) {} + private: + + IT *myCurrent; + IT *myEnd; + }; + + typedef base_iterator iterator; + typedef base_iterator const_iterator; + typedef base_iterator reverse_iterator; + typedef base_iterator const_reverse_iterator; + typedef const_iterator traverser; // For backward compatibility + + /// Begin iterating over the array. The contents of the array may be + /// modified during the traversal. + iterator begin() + { + return iterator(myData, myData + mySize); + } + /// End iterator. + iterator end() + { + return iterator(myData + mySize, + myData + mySize); + } + + /// Begin iterating over the array. The array may not be modified during + /// the traversal. + const_iterator begin() const + { + return const_iterator(myData, myData + mySize); + } + /// End const iterator. Consider using it.atEnd() instead. + const_iterator end() const + { + return const_iterator(myData + mySize, + myData + mySize); + } + + /// Begin iterating over the array in reverse. + reverse_iterator rbegin() + { + return reverse_iterator(myData + mySize, + myData); + } + /// End reverse iterator. + reverse_iterator rend() + { + return reverse_iterator(myData, myData); + } + /// Begin iterating over the array in reverse. + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(myData + mySize, + myData); + } + /// End reverse iterator. Consider using it.atEnd() instead. + const_reverse_iterator rend() const + { + return const_reverse_iterator(myData, myData); + } + + /// Remove item specified by the reverse_iterator. + void removeItem(const reverse_iterator &it) + { + removeAt(&it.item() - myData); + } + + + /// Very dangerous methods to share arrays. + /// The array is not aware of the sharing, so ensure you clear + /// out the array prior a destructor or setCapacity operation. + void unsafeShareData(UT_Array &src) + { + myData = src.myData; + myCapacity = src.myCapacity; + mySize = src.mySize; + } + void unsafeShareData(T *src, exint srcsize) + { + myData = src; + myCapacity = srcsize; + mySize = srcsize; + } + void unsafeShareData(T *src, exint size, exint capacity) + { + myData = src; + mySize = size; + myCapacity = capacity; + } + void unsafeClearData() + { + myData = NULL; + myCapacity = 0; + mySize = 0; + } + + /// Returns true if the data used by the array was allocated on the heap. + inline bool isHeapBuffer() const + { + return (myData != (T *)(((char*)this) + sizeof(*this))); + } + inline bool isHeapBuffer(T* data) const + { + return (data != (T *)(((char*)this) + sizeof(*this))); + } + +protected: + // Check whether T may have a constructor, destructor, or copy + // constructor. This test is conservative in that some POD types will + // not be recognized as POD by this function. To mark your type as POD, + // use the SYS_DECLARE_IS_POD() macro in SYS_TypeDecorate.h. + static constexpr SYS_FORCE_INLINE bool isPOD() + { + return std::is_pod::value; + } + + /// Implements both append(const T &) and append(T &&) via perfect + /// forwarding. Unlike the variadic emplace_back(), its argument may be a + /// reference to another element in the array. + template + inline exint appendImpl(S &&s); + + /// Similar to appendImpl() but for insertion. + template + inline exint insertImpl(S &&s, exint index); + + // Construct the given type + template + static void construct(T &dst, S&&... s) + { + new (&dst) T(std::forward(s)...); + } + + // Copy construct the given type + static void copyConstruct(T &dst, const T &src) + { + if (isPOD()) + dst = src; + else + new (&dst) T(src); + } + static void copyConstructRange(T *dst, const T *src, exint n) + { + if (isPOD()) + { + if (n > 0) + { + ::memcpy((void *)dst, (const void *)src, + n * sizeof(T)); + } + } + else + { + for (exint i = 0; i < n; i++) + new (&dst[i]) T(src[i]); + } + } + + /// Element Constructor + static void trivialConstruct(T &dst) + { + if (!isPOD()) + new (&dst) T(); + else + memset((void *)&dst, 0, sizeof(T)); + } + static void trivialConstructRange(T *dst, exint n) + { + if (!isPOD()) + { + for (exint i = 0; i < n; i++) + new (&dst[i]) T(); + } + else if (n == 1) + { + // Special case for n == 1. If the size parameter + // passed to memset is known at compile time, this + // function call will be inlined. This results in + // much faster performance than a real memset + // function call which is required in the case + // below, where n is not known until runtime. + // This makes calls to append() much faster. + memset((void *)dst, 0, sizeof(T)); + } + else + memset((void *)dst, 0, sizeof(T) * n); + } + + /// Element Destructor + static void trivialDestruct(T &dst) + { + if (!isPOD()) + dst.~T(); + } + static void trivialDestructRange(T *dst, exint n) + { + if (!isPOD()) + { + for (exint i = 0; i < n; i++) + dst[i].~T(); + } + } + +private: + /// Pointer to the array of elements of type T + T *myData; + + /// The number of elements for which we have allocated memory + exint myCapacity; + + /// The actual number of valid elements in the array + exint mySize; + + // The guts of the remove() methods. + inline exint removeAt(exint index); + + inline T * allocateCapacity(exint num_items); +}; +}} + + + +#endif // __UT_ARRAY_H_INCLUDED__ +/* + * Copyright (c) 2018 Side Effects Software Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * COMMENTS: + * This is meant to be included by UT_Array.h and includes + * the template implementations needed by external code. + */ + +#pragma once + +#ifndef __UT_ARRAYIMPL_H_INCLUDED__ +#define __UT_ARRAYIMPL_H_INCLUDED__ + + + + +#include +#include +#include +#include + +namespace igl { namespace FastWindingNumber { + +// Implemented in UT_Array.C +extern void ut_ArrayImplFree(void *p); + + +template +inline UT_Array::UT_Array(const UT_Array &a) + : myCapacity(a.size()), mySize(a.size()) +{ + if (myCapacity) + { + myData = allocateCapacity(myCapacity); + copyConstructRange(myData, a.array(), mySize); + } + else + { + myData = nullptr; + } +} + +template +inline UT_Array::UT_Array(std::initializer_list init) + : myCapacity(init.size()), mySize(init.size()) +{ + if (myCapacity) + { + myData = allocateCapacity(myCapacity); + copyConstructRange(myData, init.begin(), mySize); + } + else + { + myData = nullptr; + } +} + +template +inline UT_Array::UT_Array(UT_Array &&a) noexcept +{ + if (!a.isHeapBuffer()) + { + myData = nullptr; + myCapacity = 0; + mySize = 0; + operator=(std::move(a)); + return; + } + + myCapacity = a.myCapacity; + mySize = a.mySize; + myData = a.myData; + a.myCapacity = a.mySize = 0; + a.myData = nullptr; +} + + +template +inline UT_Array::~UT_Array() +{ + // NOTE: We call setCapacity to ensure that we call trivialDestructRange, + // then call free on myData. + setCapacity(0); +} + +template +inline T * +UT_Array::allocateCapacity(exint capacity) +{ + T *data = (T *)malloc(capacity * sizeof(T)); + // Avoid degenerate case if we happen to be aliased the wrong way + if (!isHeapBuffer(data)) + { + T *prev = data; + data = (T *)malloc(capacity * sizeof(T)); + ut_ArrayImplFree(prev); + } + return data; +} + +template +inline void +UT_Array::swap( UT_Array &other ) +{ + std::swap( myData, other.myData ); + std::swap( myCapacity, other.myCapacity ); + std::swap( mySize, other.mySize ); +} + + +template +inline exint +UT_Array::insert(exint index) +{ + if (index >= mySize) + { + bumpCapacity(index + 1); + + trivialConstructRange(myData + mySize, index - mySize + 1); + + mySize = index+1; + return index; + } + bumpCapacity(mySize + 1); + + UT_ASSERT_P(index >= 0); + ::memmove((void *)&myData[index+1], (void *)&myData[index], + ((mySize-index)*sizeof(T))); + + trivialConstruct(myData[index]); + + mySize++; + return index; +} + +template +template +inline exint +UT_Array::appendImpl(S &&s) +{ + if (mySize == myCapacity) + { + exint idx = safeIndex(s); + + // NOTE: UTbumpAlloc always returns a strictly larger value. + setCapacity(UTbumpAlloc(myCapacity)); + if (idx >= 0) + construct(myData[mySize], std::forward(myData[idx])); + else + construct(myData[mySize], std::forward(s)); + } + else + { + construct(myData[mySize], std::forward(s)); + } + return mySize++; +} + +template +template +inline exint +UT_Array::emplace_back(S&&... s) +{ + if (mySize == myCapacity) + setCapacity(UTbumpAlloc(myCapacity)); + + construct(myData[mySize], std::forward(s)...); + return mySize++; +} + +template +inline void +UT_Array::append(const T *pt, exint count) +{ + bumpCapacity(mySize + count); + copyConstructRange(myData + mySize, pt, count); + mySize += count; +} + +template +inline void +UT_Array::appendMultiple(const T &t, exint count) +{ + UT_ASSERT_P(count >= 0); + if (count <= 0) + return; + if (mySize + count >= myCapacity) + { + exint tidx = safeIndex(t); + + bumpCapacity(mySize + count); + + for (exint i = 0; i < count; i++) + copyConstruct(myData[mySize+i], tidx >= 0 ? myData[tidx] : t); + } + else + { + for (exint i = 0; i < count; i++) + copyConstruct(myData[mySize+i], t); + } + mySize += count; +} + +template +inline exint +UT_Array::concat(const UT_Array &a) +{ + bumpCapacity(mySize + a.mySize); + copyConstructRange(myData + mySize, a.myData, a.mySize); + mySize += a.mySize; + + return mySize; +} + +template +inline exint +UT_Array::multipleInsert(exint beg_index, exint count) +{ + exint end_index = beg_index + count; + + if (beg_index >= mySize) + { + bumpCapacity(end_index); + + trivialConstructRange(myData + mySize, end_index - mySize); + + mySize = end_index; + return beg_index; + } + bumpCapacity(mySize+count); + + ::memmove((void *)&myData[end_index], (void *)&myData[beg_index], + ((mySize-beg_index)*sizeof(T))); + mySize += count; + + trivialConstructRange(myData + beg_index, count); + + return beg_index; +} + +template +template +inline exint +UT_Array::insertImpl(S &&s, exint index) +{ + if (index == mySize) + { + // This case avoids an extraneous call to trivialConstructRange() + // which the compiler may not optimize out. + (void) appendImpl(std::forward(s)); + } + else if (index > mySize) + { + exint src_i = safeIndex(s); + + bumpCapacity(index + 1); + + trivialConstructRange(myData + mySize, index - mySize); + + if (src_i >= 0) + construct(myData[index], std::forward(myData[src_i])); + else + construct(myData[index], std::forward(s)); + + mySize = index + 1; + } + else // (index < mySize) + { + exint src_i = safeIndex(s); + + bumpCapacity(mySize + 1); + + ::memmove((void *)&myData[index+1], (void *)&myData[index], + ((mySize-index)*sizeof(T))); + + if (src_i >= index) + ++src_i; + + if (src_i >= 0) + construct(myData[index], std::forward(myData[src_i])); + else + construct(myData[index], std::forward(s)); + + ++mySize; + } + + return index; +} + +template +inline exint +UT_Array::removeAt(exint idx) +{ + trivialDestruct(myData[idx]); + if (idx != --mySize) + { + ::memmove((void *)&myData[idx], (void *)&myData[idx+1], + ((mySize-idx)*sizeof(T))); + } + + return idx; +} + +template +inline void +UT_Array::removeRange(exint begin_i, exint end_i) +{ + UT_ASSERT(begin_i <= end_i); + UT_ASSERT(end_i <= size()); + if (end_i < size()) + { + trivialDestructRange(myData + begin_i, end_i - begin_i); + ::memmove((void *)&myData[begin_i], (void *)&myData[end_i], + (mySize - end_i)*sizeof(T)); + } + setSize(mySize - (end_i - begin_i)); +} + +template +inline void +UT_Array::extractRange(exint begin_i, exint end_i, UT_Array& dest) +{ + UT_ASSERT_P(begin_i >= 0); + UT_ASSERT_P(begin_i <= end_i); + UT_ASSERT_P(end_i <= size()); + UT_ASSERT(this != &dest); + + exint nelements = end_i - begin_i; + + // grow the raw array if necessary. + dest.setCapacityIfNeeded(nelements); + + ::memmove((void*)dest.myData, (void*)&myData[begin_i], + nelements * sizeof(T)); + dest.mySize = nelements; + + // we just asserted this was true, but just in case + if (this != &dest) + { + if (end_i < size()) + { + ::memmove((void*)&myData[begin_i], (void*)&myData[end_i], + (mySize - end_i) * sizeof(T)); + } + setSize(mySize - nelements); + } +} + +template +inline void +UT_Array::move(exint srcIdx, exint destIdx, exint howMany) +{ + // Make sure all the parameters are valid. + if( srcIdx < 0 ) + srcIdx = 0; + if( destIdx < 0 ) + destIdx = 0; + // If we are told to move a set of elements that would extend beyond the + // end of the current array, trim the group. + if( srcIdx + howMany > size() ) + howMany = size() - srcIdx; + // If the destIdx would have us move the source beyond the end of the + // current array, move the destIdx back. + if( destIdx + howMany > size() ) + destIdx = size() - howMany; + if( srcIdx != destIdx && howMany > 0 ) + { + void **tmp = 0; + exint savelen; + + savelen = SYSabs(srcIdx - destIdx); + tmp = (void **)::malloc(savelen*sizeof(T)); + if( srcIdx > destIdx && howMany > 0 ) + { + // We're moving the group backwards. Save all the stuff that + // we would overwrite, plus everything beyond that to the + // start of the source group. Then move the source group, then + // tack the saved data onto the end of the moved group. + ::memcpy(tmp, (void *)&myData[destIdx], (savelen*sizeof(T))); + ::memmove((void *)&myData[destIdx], (void *)&myData[srcIdx], + (howMany*sizeof(T))); + ::memcpy((void *)&myData[destIdx+howMany], tmp, (savelen*sizeof(T))); + } + if( srcIdx < destIdx && howMany > 0 ) + { + // We're moving the group forwards. Save from the end of the + // group being moved to the end of the where the destination + // group will end up. Then copy the source to the destination. + // Then move back up to the original source location and drop + // in our saved data. + ::memcpy(tmp, (void *)&myData[srcIdx+howMany], (savelen*sizeof(T))); + ::memmove((void *)&myData[destIdx], (void *)&myData[srcIdx], + (howMany*sizeof(T))); + ::memcpy((void *)&myData[srcIdx], tmp, (savelen*sizeof(T))); + } + ::free(tmp); + } +} + +template +template +inline exint +UT_Array::removeIf(IsEqual is_equal) +{ + // Move dst to the first element to remove. + exint dst; + for (dst = 0; dst < mySize; dst++) + { + if (is_equal(myData[dst])) + break; + } + // Now start looking at all the elements past the first one to remove. + for (exint idx = dst+1; idx < mySize; idx++) + { + if (!is_equal(myData[idx])) + { + UT_ASSERT(idx != dst); + myData[dst] = myData[idx]; + dst++; + } + // On match, ignore. + } + // New size + mySize = dst; + return mySize; +} + +template +inline void +UT_Array::cycle(exint howMany) +{ + char *tempPtr; + exint numShift; // The number of items we shift + exint remaining; // mySize - numShift + + if (howMany == 0 || mySize < 1) return; + + numShift = howMany % (exint)mySize; + if (numShift < 0) numShift += mySize; + remaining = mySize - numShift; + tempPtr = new char[numShift*sizeof(T)]; + + ::memmove(tempPtr, (void *)&myData[remaining], (numShift * sizeof(T))); + ::memmove((void *)&myData[numShift], (void *)&myData[0], (remaining * sizeof(T))); + ::memmove((void *)&myData[0], tempPtr, (numShift * sizeof(T))); + + delete [] tempPtr; +} + +template +inline void +UT_Array::constant(const T &value) +{ + for (exint i = 0; i < mySize; i++) + { + myData[i] = value; + } +} + +template +inline void +UT_Array::zero() +{ + if (isPOD()) + ::memset((void *)myData, 0, mySize*sizeof(T)); + else + trivialConstructRange(myData, mySize); +} + +template +inline void +UT_Array::setCapacity(exint capacity) +{ + // Do nothing when new capacity is the same as the current + if (capacity == myCapacity) + return; + + // Special case for non-heap buffers + if (!isHeapBuffer()) + { + if (capacity < mySize) + { + // Destroy the extra elements without changing myCapacity + trivialDestructRange(myData + capacity, mySize - capacity); + mySize = capacity; + } + else if (capacity > myCapacity) + { + T *prev = myData; + myData = (T *)malloc(sizeof(T) * capacity); + // myData is safe because we're already a stack buffer + UT_ASSERT_P(isHeapBuffer()); + if (mySize > 0) + memcpy((void *)myData, (void *)prev, sizeof(T) * mySize); + myCapacity = capacity; + } + else + { + // Keep myCapacity unchanged in this case + UT_ASSERT_P(capacity >= mySize && capacity <= myCapacity); + } + return; + } + + if (capacity == 0) + { + if (myData) + { + trivialDestructRange(myData, mySize); + free(myData); + } + myData = 0; + myCapacity = 0; + mySize = 0; + return; + } + + if (capacity < mySize) + { + trivialDestructRange(myData + capacity, mySize - capacity); + mySize = capacity; + } + + if (myData) + myData = (T *)realloc(myData, capacity*sizeof(T)); + else + myData = (T *)malloc(sizeof(T) * capacity); + + // Avoid degenerate case if we happen to be aliased the wrong way + if (!isHeapBuffer()) + { + T *prev = myData; + myData = (T *)malloc(sizeof(T) * capacity); + if (mySize > 0) + memcpy((void *)myData, (void *)prev, sizeof(T) * mySize); + ut_ArrayImplFree(prev); + } + + myCapacity = capacity; + UT_ASSERT(myData); +} + +template +inline UT_Array & +UT_Array::operator=(const UT_Array &a) +{ + if (this == &a) + return *this; + + // Grow the raw array if necessary. + setCapacityIfNeeded(a.size()); + + // Make sure destructors and constructors are called on all elements + // being removed/added. + trivialDestructRange(myData, mySize); + copyConstructRange(myData, a.myData, a.size()); + + mySize = a.size(); + + return *this; +} + +template +inline UT_Array & +UT_Array::operator=(std::initializer_list a) +{ + const exint new_size = a.size(); + + // Grow the raw array if necessary. + setCapacityIfNeeded(new_size); + + // Make sure destructors and constructors are called on all elements + // being removed/added. + trivialDestructRange(myData, mySize); + + copyConstructRange(myData, a.begin(), new_size); + + mySize = new_size; + + return *this; +} + +template +inline UT_Array & +UT_Array::operator=(UT_Array &&a) +{ + if (!a.isHeapBuffer()) + { + // Cannot steal from non-heap buffers + clear(); + const exint n = a.size(); + setCapacityIfNeeded(n); + if (isPOD()) + { + if (n > 0) + memcpy(myData, a.myData, n * sizeof(T)); + } + else + { + for (exint i = 0; i < n; ++i) + new (&myData[i]) T(std::move(a.myData[i])); + } + mySize = a.mySize; + a.mySize = 0; + return *this; + } + // else, just steal even if we're a small buffer + + // Destroy all the elements we're currently holding. + if (myData) + { + trivialDestructRange(myData, mySize); + if (isHeapBuffer()) + ::free(myData); + } + + // Move the contents of the other array to us and empty the other container + // so that it destructs cleanly. + myCapacity = a.myCapacity; + mySize = a.mySize; + myData = a.myData; + a.myCapacity = a.mySize = 0; + a.myData = nullptr; + + return *this; +} + + +template +inline bool +UT_Array::operator==(const UT_Array &a) const +{ + if (this == &a) return true; + if (mySize != a.size()) return false; + for (exint i = 0; i < mySize; i++) + if (!(myData[i] == a(i))) return false; + return true; +} + +template +inline bool +UT_Array::operator!=(const UT_Array &a) const +{ + return (!operator==(a)); +} + +}} + +#endif // __UT_ARRAYIMPL_H_INCLUDED__ +/* + * Copyright (c) 2018 Side Effects Software Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * COMMENTS: + * Special case for arrays that are usually small, + * to avoid a heap allocation when the array really is small. + */ + +#pragma once + +#ifndef __UT_SMALLARRAY_H_INCLUDED__ +#define __UT_SMALLARRAY_H_INCLUDED__ + + + +#include +#include +namespace igl { namespace FastWindingNumber { + +/// An array class with the small buffer optimization, making it ideal for +/// cases when you know it will only contain a few elements at the expense of +/// increasing the object size by MAX_BYTES (subject to alignment). +template +class UT_SmallArray : public UT_Array +{ + // As many elements that fit into MAX_BYTES with 1 item minimum + enum { MAX_ELEMS = MAX_BYTES/sizeof(T) < 1 ? 1 : MAX_BYTES/sizeof(T) }; + +public: + +// gcc falsely warns about our use of offsetof() on non-POD types. We can't +// easily suppress this because it has to be done in the caller at +// instantiation time. Instead, punt to a runtime check instead. +#if defined(__clang__) || defined(_MSC_VER) + #define UT_SMALL_ARRAY_SIZE_ASSERT() \ + using ThisT = UT_SmallArray; \ + static_assert(offsetof(ThisT, myBuffer) == sizeof(UT_Array), \ + "In order for UT_Array's checks for whether it needs to free the buffer to work, " \ + "the buffer must be exactly following the base class memory.") +#else + #define UT_SMALL_ARRAY_SIZE_ASSERT() \ + UT_ASSERT_P(!UT_Array::isHeapBuffer()); +#endif + + /// Default construction + UT_SmallArray() + : UT_Array(/*capacity*/0) + { + UT_Array::unsafeShareData((T*)myBuffer, 0, MAX_ELEMS); + UT_SMALL_ARRAY_SIZE_ASSERT(); + } + + /// Copy constructor + /// @{ + explicit UT_SmallArray(const UT_Array ©) + : UT_Array(/*capacity*/0) + { + UT_Array::unsafeShareData((T*)myBuffer, 0, MAX_ELEMS); + UT_SMALL_ARRAY_SIZE_ASSERT(); + UT_Array::operator=(copy); + } + explicit UT_SmallArray(const UT_SmallArray ©) + : UT_Array(/*capacity*/0) + { + UT_Array::unsafeShareData((T*)myBuffer, 0, MAX_ELEMS); + UT_SMALL_ARRAY_SIZE_ASSERT(); + UT_Array::operator=(copy); + } + /// @} + + /// Move constructor + /// @{ + UT_SmallArray(UT_Array &&movable) noexcept + { + UT_Array::unsafeShareData((T*)myBuffer, 0, MAX_ELEMS); + UT_SMALL_ARRAY_SIZE_ASSERT(); + UT_Array::operator=(std::move(movable)); + } + UT_SmallArray(UT_SmallArray &&movable) noexcept + { + UT_Array::unsafeShareData((T*)myBuffer, 0, MAX_ELEMS); + UT_SMALL_ARRAY_SIZE_ASSERT(); + UT_Array::operator=(std::move(movable)); + } + /// @} + + /// Initializer list constructor + explicit UT_SmallArray(std::initializer_list init) + { + UT_Array::unsafeShareData((T*)myBuffer, 0, MAX_ELEMS); + UT_SMALL_ARRAY_SIZE_ASSERT(); + UT_Array::operator=(init); + } + +#undef UT_SMALL_ARRAY_SIZE_ASSERT + + /// Assignment operator + /// @{ + UT_SmallArray & + operator=(const UT_SmallArray ©) + { + UT_Array::operator=(copy); + return *this; + } + UT_SmallArray & + operator=(const UT_Array ©) + { + UT_Array::operator=(copy); + return *this; + } + /// @} + + /// Move operator + /// @{ + UT_SmallArray & + operator=(UT_SmallArray &&movable) + { + UT_Array::operator=(std::move(movable)); + return *this; + } + UT_SmallArray & + operator=(UT_Array &&movable) + { + UT_Array::operator=(std::move(movable)); + return *this; + } + /// @} + + UT_SmallArray & + operator=(std::initializer_list src) + { + UT_Array::operator=(src); + return *this; + } +private: + alignas(T) char myBuffer[MAX_ELEMS*sizeof(T)]; +}; +}} + +#endif // __UT_SMALLARRAY_H_INCLUDED__ +/* + * Copyright (c) 2018 Side Effects Software Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * COMMENTS: + * A vector class templated on its size and data type. + */ + +#pragma once + +#ifndef __UT_FixedVector__ +#define __UT_FixedVector__ + + + + +namespace igl { namespace FastWindingNumber { + +template +class UT_FixedVector +{ +public: + typedef UT_FixedVector ThisType; + typedef T value_type; + typedef T theType; + static const exint theSize = SIZE; + + T vec[SIZE]; + + SYS_FORCE_INLINE UT_FixedVector() = default; + + /// Initializes every component to the same value + SYS_FORCE_INLINE explicit UT_FixedVector(T that) noexcept + { + for (exint i = 0; i < SIZE; ++i) + vec[i] = that; + } + + SYS_FORCE_INLINE UT_FixedVector(const ThisType &that) = default; + SYS_FORCE_INLINE UT_FixedVector(ThisType &&that) = default; + + /// Converts vector of S into vector of T, + /// or just copies if same type. + template + SYS_FORCE_INLINE UT_FixedVector(const UT_FixedVector &that) noexcept + { + for (exint i = 0; i < SIZE; ++i) + vec[i] = that[i]; + } + + template + SYS_FORCE_INLINE UT_FixedVector(const S that[SIZE]) noexcept + { + for (exint i = 0; i < SIZE; ++i) + vec[i] = that[i]; + } + + SYS_FORCE_INLINE const T &operator[](exint i) const noexcept + { + UT_ASSERT_P(i >= 0 && i < SIZE); + return vec[i]; + } + SYS_FORCE_INLINE T &operator[](exint i) noexcept + { + UT_ASSERT_P(i >= 0 && i < SIZE); + return vec[i]; + } + + SYS_FORCE_INLINE constexpr const T *data() const noexcept + { + return vec; + } + SYS_FORCE_INLINE T *data() noexcept + { + return vec; + } + + SYS_FORCE_INLINE ThisType &operator=(const ThisType &that) = default; + SYS_FORCE_INLINE ThisType &operator=(ThisType &&that) = default; + + template + SYS_FORCE_INLINE ThisType &operator=(const UT_FixedVector &that) noexcept + { + for (exint i = 0; i < SIZE; ++i) + vec[i] = that[i]; + return *this; + } + SYS_FORCE_INLINE const ThisType &operator=(T that) noexcept + { + for (exint i = 0; i < SIZE; ++i) + vec[i] = that; + return *this; + } + template + SYS_FORCE_INLINE void operator+=(const UT_FixedVector &that) + { + for (exint i = 0; i < SIZE; ++i) + vec[i] += that[i]; + } + SYS_FORCE_INLINE void operator+=(T that) + { + for (exint i = 0; i < SIZE; ++i) + vec[i] += that; + } + template + SYS_FORCE_INLINE auto operator+(const UT_FixedVector &that) const -> UT_FixedVector + { + using Type = decltype(vec[0]+that[0]); + UT_FixedVector result; + for (exint i = 0; i < SIZE; ++i) + result[i] = vec[i] + that[i]; + return result; + } + template + SYS_FORCE_INLINE void operator-=(const UT_FixedVector &that) + { + for (exint i = 0; i < SIZE; ++i) + vec[i] -= that[i]; + } + SYS_FORCE_INLINE void operator-=(T that) + { + for (exint i = 0; i < SIZE; ++i) + vec[i] -= that; + } + template + SYS_FORCE_INLINE auto operator-(const UT_FixedVector &that) const -> UT_FixedVector + { + using Type = decltype(vec[0]-that[0]); + UT_FixedVector result; + for (exint i = 0; i < SIZE; ++i) + result[i] = vec[i] - that[i]; + return result; + } + template + SYS_FORCE_INLINE void operator*=(const UT_FixedVector &that) + { + for (exint i = 0; i < SIZE; ++i) + vec[i] *= that[i]; + } + template + SYS_FORCE_INLINE auto operator*(const UT_FixedVector &that) const -> UT_FixedVector + { + using Type = decltype(vec[0]*that[0]); + UT_FixedVector result; + for (exint i = 0; i < SIZE; ++i) + result[i] = vec[i] * that[i]; + return result; + } + SYS_FORCE_INLINE void operator*=(T that) + { + for (exint i = 0; i < SIZE; ++i) + vec[i] *= that; + } + SYS_FORCE_INLINE UT_FixedVector operator*(T that) const + { + UT_FixedVector result; + for (exint i = 0; i < SIZE; ++i) + result[i] = vec[i] * that; + return result; + } + template + SYS_FORCE_INLINE void operator/=(const UT_FixedVector &that) + { + for (exint i = 0; i < SIZE; ++i) + vec[i] /= that[i]; + } + template + SYS_FORCE_INLINE auto operator/(const UT_FixedVector &that) const -> UT_FixedVector + { + using Type = decltype(vec[0]/that[0]); + UT_FixedVector result; + for (exint i = 0; i < SIZE; ++i) + result[i] = vec[i] / that[i]; + return result; + } + + SYS_FORCE_INLINE void operator/=(T that) + { + if (std::is_integral::value) + { + for (exint i = 0; i < SIZE; ++i) + vec[i] /= that; + } + else + { + that = 1/that; + for (exint i = 0; i < SIZE; ++i) + vec[i] *= that; + } + } + SYS_FORCE_INLINE UT_FixedVector operator/(T that) const + { + UT_FixedVector result; + if (std::is_integral::value) + { + for (exint i = 0; i < SIZE; ++i) + result[i] = vec[i] / that; + } + else + { + that = 1/that; + for (exint i = 0; i < SIZE; ++i) + result[i] = vec[i] * that; + } + return result; + } + SYS_FORCE_INLINE void negate() + { + for (exint i = 0; i < SIZE; ++i) + vec[i] = -vec[i]; + } + + SYS_FORCE_INLINE UT_FixedVector operator-() const + { + UT_FixedVector result; + for (exint i = 0; i < SIZE; ++i) + result[i] = -vec[i]; + return result; + } + + template + SYS_FORCE_INLINE bool operator==(const UT_FixedVector &that) const noexcept + { + for (exint i = 0; i < SIZE; ++i) + { + if (vec[i] != T(that[i])) + return false; + } + return true; + } + template + SYS_FORCE_INLINE bool operator!=(const UT_FixedVector &that) const noexcept + { + return !(*this==that); + } + SYS_FORCE_INLINE bool isZero() const noexcept + { + for (exint i = 0; i < SIZE; ++i) + { + if (vec[i] != T(0)) + return false; + } + return true; + } + SYS_FORCE_INLINE T maxComponent() const + { + T v = vec[0]; + for (exint i = 1; i < SIZE; ++i) + v = (vec[i] > v) ? vec[i] : v; + return v; + } + SYS_FORCE_INLINE T minComponent() const + { + T v = vec[0]; + for (exint i = 1; i < SIZE; ++i) + v = (vec[i] < v) ? vec[i] : v; + return v; + } + SYS_FORCE_INLINE T avgComponent() const + { + T v = vec[0]; + for (exint i = 1; i < SIZE; ++i) + v += vec[i]; + return v / SIZE; + } + + SYS_FORCE_INLINE T length2() const noexcept + { + T a0(vec[0]); + T result(a0*a0); + for (exint i = 1; i < SIZE; ++i) + { + T ai(vec[i]); + result += ai*ai; + } + return result; + } + SYS_FORCE_INLINE T length() const + { + T len2 = length2(); + return SYSsqrt(len2); + } + template + SYS_FORCE_INLINE auto dot(const UT_FixedVector &that) const -> decltype(vec[0]*that[0]) + { + using TheType = decltype(vec[0]*that.vec[0]); + TheType result(vec[0]*that[0]); + for (exint i = 1; i < SIZE; ++i) + result += vec[i]*that[i]; + return result; + } + template + SYS_FORCE_INLINE auto distance2(const UT_FixedVector &that) const -> decltype(vec[0]-that[0]) + { + using TheType = decltype(vec[0]-that[0]); + TheType v(vec[0] - that[0]); + TheType result(v*v); + for (exint i = 1; i < SIZE; ++i) + { + v = vec[i] - that[i]; + result += v*v; + } + return result; + } + template + SYS_FORCE_INLINE auto distance(const UT_FixedVector &that) const -> decltype(vec[0]-that[0]) + { + auto dist2 = distance2(that); + return SYSsqrt(dist2); + } + + SYS_FORCE_INLINE T normalize() + { + T len2 = length2(); + if (len2 == T(0)) + return T(0); + if (len2 == T(1)) + return T(1); + T len = SYSsqrt(len2); + // Check if the square root is equal 1. sqrt(1+dx) ~ 1+dx/2, + // so it may get rounded to 1 when it wasn't 1 before. + if (len != T(1)) + (*this) /= len; + return len; + } +}; + +/// NOTE: Strictly speaking, this should use decltype(that*a[0]), +/// but in the interests of avoiding accidental precision escalation, +/// it uses T. +template +SYS_FORCE_INLINE UT_FixedVector operator*(const S &that,const UT_FixedVector &a) +{ + T t(that); + UT_FixedVector result; + for (exint i = 0; i < SIZE; ++i) + result[i] = t * a[i]; + return result; +} + +template +SYS_FORCE_INLINE auto +dot(const UT_FixedVector &a, const UT_FixedVector &b) -> decltype(a[0]*b[0]) +{ + return a.dot(b); +} + +template +SYS_FORCE_INLINE auto +SYSmin(const UT_FixedVector &a, const UT_FixedVector &b) -> UT_FixedVector +{ + using Type = decltype(a[0]+b[1]); + UT_FixedVector result; + for (exint i = 0; i < SIZE; ++i) + result[i] = SYSmin(Type(a[i]), Type(b[i])); + return result; +} + +template +SYS_FORCE_INLINE auto +SYSmax(const UT_FixedVector &a, const UT_FixedVector &b) -> UT_FixedVector +{ + using Type = decltype(a[0]+b[1]); + UT_FixedVector result; + for (exint i = 0; i < SIZE; ++i) + result[i] = SYSmax(Type(a[i]), Type(b[i])); + return result; +} + +template +struct UT_FixedVectorTraits +{ + typedef UT_FixedVector FixedVectorType; + typedef T DataType; + static const exint TupleSize = 1; + static const bool isVectorType = false; +}; + +template +struct UT_FixedVectorTraits > +{ + typedef UT_FixedVector FixedVectorType; + typedef T DataType; + static const exint TupleSize = SIZE; + static const bool isVectorType = true; +}; +}} + +#endif +/* + * Copyright (c) 2018 Side Effects Software Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * COMMENTS: + * Simple wrappers on tbb interface + */ + +#ifndef __UT_ParallelUtil__ +#define __UT_ParallelUtil__ + + + +#include // This is just included for std::thread::hardware_concurrency() +namespace igl { namespace FastWindingNumber { +namespace UT_Thread { inline int getNumProcessors() { + return std::thread::hardware_concurrency(); +}} + +//#include "tbb/blocked_range.h" +//#include "tbb/parallel_for.h" +////namespace tbb { class split; } +// +///// Declare prior to use. +//template +//using UT_BlockedRange = tbb::blocked_range; +// +//// Default implementation that calls range.size() +//template< typename RANGE > +//struct UT_EstimatorNumItems +//{ +// UT_EstimatorNumItems() {} +// +// size_t operator()(const RANGE& range) const +// { +// return range.size(); +// } +//}; +// +///// This is needed by UT_CoarsenedRange +//template +//inline size_t UTestimatedNumItems(const RANGE& range) +//{ +// return UT_EstimatorNumItems()(range); +//} +// +///// UT_CoarsenedRange: This should be used only inside +///// UT_ParallelFor and UT_ParallelReduce +///// This class wraps an existing range with a new range. +///// This allows us to use simple_partitioner, rather than +///// auto_partitioner, which has disastrous performance with +///// the default grain size in ttb 4. +//template< typename RANGE > +//class UT_CoarsenedRange : public RANGE +//{ +//public: +// // Compiler-generated versions are fine: +// // ~UT_CoarsenedRange(); +// // UT_CoarsenedRange(const UT_CoarsenedRange&); +// +// // Split into two sub-ranges: +// UT_CoarsenedRange(UT_CoarsenedRange& range, tbb::split spl) : +// RANGE(range, spl), +// myGrainSize(range.myGrainSize) +// { +// } +// +// // Inherited: bool empty() const +// +// bool is_divisible() const +// { +// return +// RANGE::is_divisible() && +// (UTestimatedNumItems(static_cast(*this)) > myGrainSize); +// } +// +//private: +// size_t myGrainSize; +// +// UT_CoarsenedRange(const RANGE& base_range, const size_t grain_size) : +// RANGE(base_range), +// myGrainSize(grain_size) +// { +// } +// +// template +// friend void UTparallelFor( +// const Range &range, const Body &body, +// const int subscribe_ratio, const int min_grain_size +// ); +//}; +// +///// Run the @c body function over a range in parallel. +///// UTparallelFor attempts to spread the range out over at most +///// subscribe_ratio * num_processor tasks. +///// The factor subscribe_ratio can be used to help balance the load. +///// UTparallelFor() uses tbb for its implementation. +///// The used grain size is the maximum of min_grain_size and +///// if UTestimatedNumItems(range) / (subscribe_ratio * num_processor). +///// If subscribe_ratio == 0, then a grain size of min_grain_size will be used. +///// A range can be split only when UTestimatedNumItems(range) exceeds the +///// grain size the range is divisible. +// +///// +///// Requirements for the Range functor are: +///// - the requirements of the tbb Range Concept +///// - UT_estimatorNumItems must return the the estimated number of work items +///// for the range. When Range::size() is not the correct estimate, then a +///// (partial) specialization of UT_estimatorNumItemsimatorRange must be provided +///// for the type Range. +///// +///// Requirements for the Body function are: +///// - @code Body(const Body &); @endcode @n +///// Copy Constructor +///// - @code Body()::~Body(); @endcode @n +///// Destructor +///// - @code void Body::operator()(const Range &range) const; @endcode +///// Function call to perform operation on the range. Note the operator is +///// @b const. +///// +///// The requirements for a Range object are: +///// - @code Range::Range(const Range&); @endcode @n +///// Copy constructor +///// - @code Range::~Range(); @endcode @n +///// Destructor +///// - @code bool Range::is_divisible() const; @endcode @n +///// True if the range can be partitioned into two sub-ranges +///// - @code bool Range::empty() const; @endcode @n +///// True if the range is empty +///// - @code Range::Range(Range &r, UT_Split) const; @endcode @n +///// Split the range @c r into two sub-ranges (i.e. modify @c r and *this) +///// +///// Example: @code +///// class Square { +///// public: +///// Square(double *data) : myData(data) {} +///// ~Square(); +///// void operator()(const UT_BlockedRange &range) const +///// { +///// for (int64 i = range.begin(); i != range.end(); ++i) +///// myData[i] *= myData[i]; +///// } +///// double *myData; +///// }; +///// ... +///// +///// void +///// parallel_square(double *array, int64 length) +///// { +///// UTparallelFor(UT_BlockedRange(0, length), Square(array)); +///// } +///// @endcode +///// +///// @see UTparallelReduce(), UT_BlockedRange() +// +//template +//void UTparallelFor( +// const Range &range, const Body &body, +// const int subscribe_ratio = 2, +// const int min_grain_size = 1 +//) +//{ +// const size_t num_processors( UT_Thread::getNumProcessors() ); +// +// UT_ASSERT( num_processors >= 1 ); +// UT_ASSERT( min_grain_size >= 1 ); +// UT_ASSERT( subscribe_ratio >= 0 ); +// +// const size_t est_range_size( UTestimatedNumItems(range) ); +// +// // Don't run on an empty range! +// if (est_range_size == 0) +// return; +// +// // Avoid tbb overhead if entire range needs to be single threaded +// if (num_processors == 1 || est_range_size <= min_grain_size) +// { +// body(range); +// return; +// } +// +// size_t grain_size(min_grain_size); +// if( subscribe_ratio > 0 ) +// grain_size = std::max( +// grain_size, +// est_range_size / (subscribe_ratio * num_processors) +// ); +// +// UT_CoarsenedRange< Range > coarsened_range(range, grain_size); +// +// tbb::parallel_for(coarsened_range, body, tbb::simple_partitioner()); +//} +// +///// Version of UTparallelFor that is tuned for the case where the range +///// consists of lightweight items, for example, +///// float additions or matrix-vector multiplications. +//template +//void +//UTparallelForLightItems(const Range &range, const Body &body) +//{ +// UTparallelFor(range, body, 2, 1024); +//} +// +///// UTserialFor can be used as a debugging tool to quickly replace a parallel +///// for with a serial for. +//template +//void UTserialFor(const Range &range, const Body &body) +// { body(range); } +// +}} +#endif +/* + * Copyright (c) 2018 Side Effects Software Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * COMMENTS: + * Bounding Volume Hierarchy (BVH) implementation. + * To call functions not implemented here, also include UT_BVHImpl.h + */ + +#pragma once + +#ifndef __HDK_UT_BVH_h__ +#define __HDK_UT_BVH_h__ + + + + +#include +#include +namespace igl { namespace FastWindingNumber { + +template class UT_Array; +class v4uf; +class v4uu; + +namespace HDK_Sample { + +namespace UT { + +template +struct Box { + T vals[NAXES][2]; + + SYS_FORCE_INLINE Box() noexcept = default; + SYS_FORCE_INLINE constexpr Box(const Box &other) noexcept = default; + SYS_FORCE_INLINE constexpr Box(Box &&other) noexcept = default; + SYS_FORCE_INLINE Box& operator=(const Box &other) noexcept = default; + SYS_FORCE_INLINE Box& operator=(Box &&other) noexcept = default; + + template + SYS_FORCE_INLINE Box(const Box& other) noexcept { + static_assert((std::is_pod>::value) || !std::is_pod::value, + "UT::Box should be POD, for better performance in UT_Array, etc."); + + for (uint axis = 0; axis < NAXES; ++axis) { + vals[axis][0] = T(other.vals[axis][0]); + vals[axis][1] = T(other.vals[axis][1]); + } + } + template + SYS_FORCE_INLINE Box(const UT_FixedVector& pt) noexcept { + for (uint axis = 0; axis < NAXES; ++axis) { + vals[axis][0] = pt[axis]; + vals[axis][1] = pt[axis]; + } + } + template + SYS_FORCE_INLINE Box& operator=(const Box& other) noexcept { + for (uint axis = 0; axis < NAXES; ++axis) { + vals[axis][0] = T(other.vals[axis][0]); + vals[axis][1] = T(other.vals[axis][1]); + } + return *this; + } + + SYS_FORCE_INLINE const T* operator[](const size_t axis) const noexcept { + UT_ASSERT_P(axis < NAXES); + return vals[axis]; + } + SYS_FORCE_INLINE T* operator[](const size_t axis) noexcept { + UT_ASSERT_P(axis < NAXES); + return vals[axis]; + } + + SYS_FORCE_INLINE void initBounds() noexcept { + for (uint axis = 0; axis < NAXES; ++axis) { + vals[axis][0] = std::numeric_limits::max(); + vals[axis][1] = -std::numeric_limits::max(); + } + } + /// Copy the source box. + /// NOTE: This is so that in templated code that may have a Box or a + /// UT_FixedVector, it can call initBounds and still work. + SYS_FORCE_INLINE void initBounds(const Box& src) noexcept { + for (uint axis = 0; axis < NAXES; ++axis) { + vals[axis][0] = src.vals[axis][0]; + vals[axis][1] = src.vals[axis][1]; + } + } + /// Initialize with the union of the source boxes. + /// NOTE: This is so that in templated code that may have Box's or a + /// UT_FixedVector's, it can call initBounds and still work. + SYS_FORCE_INLINE void initBoundsUnordered(const Box& src0, const Box& src1) noexcept { + for (uint axis = 0; axis < NAXES; ++axis) { + vals[axis][0] = SYSmin(src0.vals[axis][0], src1.vals[axis][0]); + vals[axis][1] = SYSmax(src0.vals[axis][1], src1.vals[axis][1]); + } + } + SYS_FORCE_INLINE void combine(const Box& src) noexcept { + for (uint axis = 0; axis < NAXES; ++axis) { + T& minv = vals[axis][0]; + T& maxv = vals[axis][1]; + const T curminv = src.vals[axis][0]; + const T curmaxv = src.vals[axis][1]; + minv = (minv < curminv) ? minv : curminv; + maxv = (maxv > curmaxv) ? maxv : curmaxv; + } + } + SYS_FORCE_INLINE void enlargeBounds(const Box& src) noexcept { + combine(src); + } + + template + SYS_FORCE_INLINE + void initBounds(const UT_FixedVector& pt) noexcept { + for (uint axis = 0; axis < NAXES; ++axis) { + vals[axis][0] = pt[axis]; + vals[axis][1] = pt[axis]; + } + } + template + SYS_FORCE_INLINE + void initBounds(const UT_FixedVector& min, const UT_FixedVector& max) noexcept { + for (uint axis = 0; axis < NAXES; ++axis) { + vals[axis][0] = min[axis]; + vals[axis][1] = max[axis]; + } + } + template + SYS_FORCE_INLINE + void initBoundsUnordered(const UT_FixedVector& p0, const UT_FixedVector& p1) noexcept { + for (uint axis = 0; axis < NAXES; ++axis) { + vals[axis][0] = SYSmin(p0[axis], p1[axis]); + vals[axis][1] = SYSmax(p0[axis], p1[axis]); + } + } + template + SYS_FORCE_INLINE + void enlargeBounds(const UT_FixedVector& pt) noexcept { + for (uint axis = 0; axis < NAXES; ++axis) { + vals[axis][0] = SYSmin(vals[axis][0], pt[axis]); + vals[axis][1] = SYSmax(vals[axis][1], pt[axis]); + } + } + + SYS_FORCE_INLINE + UT_FixedVector getMin() const noexcept { + UT_FixedVector v; + for (uint axis = 0; axis < NAXES; ++axis) { + v[axis] = vals[axis][0]; + } + return v; + } + + SYS_FORCE_INLINE + UT_FixedVector getMax() const noexcept { + UT_FixedVector v; + for (uint axis = 0; axis < NAXES; ++axis) { + v[axis] = vals[axis][1]; + } + return v; + } + + T diameter2() const noexcept { + T diff = (vals[0][1]-vals[0][0]); + T sum = diff*diff; + for (uint axis = 1; axis < NAXES; ++axis) { + diff = (vals[axis][1]-vals[axis][0]); + sum += diff*diff; + } + return sum; + } + T volume() const noexcept { + T product = (vals[0][1]-vals[0][0]); + for (uint axis = 1; axis < NAXES; ++axis) { + product *= (vals[axis][1]-vals[axis][0]); + } + return product; + } + T half_surface_area() const noexcept { + if (NAXES==1) { + // NOTE: Although this should technically be 1, + // that doesn't make any sense as a heuristic, + // so we fall back to the "volume" of this box. + return (vals[0][1]-vals[0][0]); + } + if (NAXES==2) { + const T d0 = (vals[0][1]-vals[0][0]); + const T d1 = (vals[1][1]-vals[1][0]); + return d0 + d1; + } + if (NAXES==3) { + const T d0 = (vals[0][1]-vals[0][0]); + const T d1 = (vals[1][1]-vals[1][0]); + const T d2 = (vals[2][1]-vals[2][0]); + return d0*d1 + d1*d2 + d2*d0; + } + if (NAXES==4) { + const T d0 = (vals[0][1]-vals[0][0]); + const T d1 = (vals[1][1]-vals[1][0]); + const T d2 = (vals[2][1]-vals[2][0]); + const T d3 = (vals[3][1]-vals[3][0]); + // This is just d0d1d2 + d1d2d3 + d2d3d0 + d3d0d1 refactored. + const T d0d1 = d0*d1; + const T d2d3 = d2*d3; + return d0d1*(d2+d3) + d2d3*(d0+d1); + } + + T sum = 0; + for (uint skipped_axis = 0; skipped_axis < NAXES; ++skipped_axis) { + T product = 1; + for (uint axis = 0; axis < NAXES; ++axis) { + if (axis != skipped_axis) { + product *= (vals[axis][1]-vals[axis][0]); + } + } + sum += product; + } + return sum; + } + T axis_sum() const noexcept { + T sum = (vals[0][1]-vals[0][0]); + for (uint axis = 1; axis < NAXES; ++axis) { + sum += (vals[axis][1]-vals[axis][0]); + } + return sum; + } + template + SYS_FORCE_INLINE void intersect( + T &box_tmin, + T &box_tmax, + const UT_FixedVector &signs, + const UT_FixedVector &origin, + const UT_FixedVector &inverse_direction + ) const noexcept { + for (int axis = 0; axis < NAXES; ++axis) + { + uint sign = signs[axis]; + T t1 = (vals[axis][sign] - origin[axis]) * inverse_direction[axis]; + T t2 = (vals[axis][sign^1] - origin[axis]) * inverse_direction[axis]; + box_tmin = SYSmax(t1, box_tmin); + box_tmax = SYSmin(t2, box_tmax); + } + } + SYS_FORCE_INLINE void intersect(const Box& other, Box& dest) const noexcept { + for (int axis = 0; axis < NAXES; ++axis) + { + dest.vals[axis][0] = SYSmax(vals[axis][0], other.vals[axis][0]); + dest.vals[axis][1] = SYSmin(vals[axis][1], other.vals[axis][1]); + } + } + template + SYS_FORCE_INLINE T minDistance2( + const UT_FixedVector &p + ) const noexcept { + T diff = SYSmax(SYSmax(vals[0][0]-p[0], p[0]-vals[0][1]), T(0.0f)); + T d2 = diff*diff; + for (int axis = 1; axis < NAXES; ++axis) + { + diff = SYSmax(SYSmax(vals[axis][0]-p[axis], p[axis]-vals[axis][1]), T(0.0f)); + d2 += diff*diff; + } + return d2; + } + template + SYS_FORCE_INLINE T maxDistance2( + const UT_FixedVector &p + ) const noexcept { + T diff = SYSmax(p[0]-vals[0][0], vals[0][1]-p[0]); + T d2 = diff*diff; + for (int axis = 1; axis < NAXES; ++axis) + { + diff = SYSmax(p[axis]-vals[axis][0], vals[axis][1]-p[axis]); + d2 += diff*diff; + } + return d2; + } +}; + +/// Used by BVH::init to specify the heuristic to use for choosing between different box splits. +/// I tried putting this inside the BVH class, but I had difficulty getting it to compile. +enum class BVH_Heuristic { + /// Tries to minimize the sum of axis lengths of the boxes. + /// This is useful for applications where the probability of a box being applicable to a + /// query is proportional to the "length", e.g. the probability of a random infinite plane + /// intersecting the box. + BOX_PERIMETER, + + /// Tries to minimize the "surface area" of the boxes. + /// In 3D, uses the surface area; in 2D, uses the perimeter; in 1D, uses the axis length. + /// This is what most applications, e.g. ray tracing, should use, particularly when the + /// probability of a box being applicable to a query is proportional to the surface "area", + /// e.g. the probability of a random ray hitting the box. + /// + /// NOTE: USE THIS ONE IF YOU ARE UNSURE! + BOX_AREA, + + /// Tries to minimize the "volume" of the boxes. + /// Uses the product of all axis lengths as a heuristic, (volume in 3D, area in 2D, length in 1D). + /// This is useful for applications where the probability of a box being applicable to a + /// query is proportional to the "volume", e.g. the probability of a random point being inside the box. + BOX_VOLUME, + + /// Tries to minimize the "radii" of the boxes (i.e. the distance from the centre to a corner). + /// This is useful for applications where the probability of a box being applicable to a + /// query is proportional to the distance to the box centre, e.g. the probability of a random + /// infinite plane being within the "radius" of the centre. + BOX_RADIUS, + + /// Tries to minimize the squared "radii" of the boxes (i.e. the squared distance from the centre to a corner). + /// This is useful for applications where the probability of a box being applicable to a + /// query is proportional to the squared distance to the box centre, e.g. the probability of a random + /// ray passing within the "radius" of the centre. + BOX_RADIUS2, + + /// Tries to minimize the cubed "radii" of the boxes (i.e. the cubed distance from the centre to a corner). + /// This is useful for applications where the probability of a box being applicable to a + /// query is proportional to the cubed distance to the box centre, e.g. the probability of a random + /// point being within the "radius" of the centre. + BOX_RADIUS3, + + /// Tries to minimize the depth of the tree by primarily splitting at the median of the max axis. + /// It may fall back to minimizing the area, but the tree depth should be unaffected. + /// + /// FIXME: This is not fully implemented yet. + MEDIAN_MAX_AXIS +}; + +template +class BVH { +public: + using INT_TYPE = uint; + struct Node { + INT_TYPE child[N]; + + static constexpr INT_TYPE theN = N; + static constexpr INT_TYPE EMPTY = INT_TYPE(-1); + static constexpr INT_TYPE INTERNAL_BIT = (INT_TYPE(1)<<(sizeof(INT_TYPE)*8 - 1)); + SYS_FORCE_INLINE static INT_TYPE markInternal(INT_TYPE internal_node_num) noexcept { + return internal_node_num | INTERNAL_BIT; + } + SYS_FORCE_INLINE static bool isInternal(INT_TYPE node_int) noexcept { + return (node_int & INTERNAL_BIT) != 0; + } + SYS_FORCE_INLINE static INT_TYPE getInternalNum(INT_TYPE node_int) noexcept { + return node_int & ~INTERNAL_BIT; + } + }; +private: + struct FreeDeleter { + SYS_FORCE_INLINE void operator()(Node* p) const { + if (p) { + // The pointer was allocated with malloc by UT_Array, + // so it must be freed with free. + free(p); + } + } + }; + + std::unique_ptr myRoot; + INT_TYPE myNumNodes; +public: + SYS_FORCE_INLINE BVH() noexcept : myRoot(nullptr), myNumNodes(0) {} + + template + inline void init(const BOX_TYPE* boxes, const INT_TYPE nboxes, SRC_INT_TYPE* indices=nullptr, bool reorder_indices=false, INT_TYPE max_items_per_leaf=1) noexcept; + + template + inline void init(Box axes_minmax, const BOX_TYPE* boxes, INT_TYPE nboxes, SRC_INT_TYPE* indices=nullptr, bool reorder_indices=false, INT_TYPE max_items_per_leaf=1) noexcept; + + SYS_FORCE_INLINE + INT_TYPE getNumNodes() const noexcept + { + return myNumNodes; + } + SYS_FORCE_INLINE + const Node *getNodes() const noexcept + { + return myRoot.get(); + } + + SYS_FORCE_INLINE + void clear() noexcept { + myRoot.reset(); + myNumNodes = 0; + } + + /// For each node, this effectively does: + /// LOCAL_DATA local_data[MAX_ORDER]; + /// bool descend = functors.pre(nodei, parent_data); + /// if (!descend) + /// return; + /// for each child { + /// if (isitem(child)) + /// functors.item(getitemi(child), nodei, local_data[child]); + /// else if (isnode(child)) + /// recurse(getnodei(child), local_data); + /// } + /// functors.post(nodei, parent_nodei, data_for_parent, num_children, local_data); + template + inline void traverse( + FUNCTORS &functors, + LOCAL_DATA *data_for_parent=nullptr) const noexcept; + + /// This acts like the traverse function, except if the number of nodes in two subtrees + /// of a node contain at least parallel_threshold nodes, they may be executed in parallel. + /// If parallel_threshold is 0, even item_functor may be executed on items in parallel. + /// NOTE: Make sure that your functors don't depend on the order that they're executed in, + /// e.g. don't add values from sibling nodes together except in post functor, + /// else they might have nondeterministic roundoff or miss some values entirely. + template + inline void traverseParallel( + INT_TYPE parallel_threshold, + FUNCTORS &functors, + LOCAL_DATA *data_for_parent=nullptr) const noexcept; + + /// For each node, this effectively does: + /// LOCAL_DATA local_data[MAX_ORDER]; + /// uint descend = functors.pre(nodei, parent_data); + /// if (!descend) + /// return; + /// for each child { + /// if (!(descend & (1< + inline void traverseVector( + FUNCTORS &functors, + LOCAL_DATA *data_for_parent=nullptr) const noexcept; + + /// Prints a text representation of the tree to stdout. + inline void debugDump() const; + + template + static inline void createTrivialIndices(SRC_INT_TYPE* indices, const INT_TYPE n) noexcept; + +private: + template + inline void traverseHelper( + INT_TYPE nodei, + INT_TYPE parent_nodei, + FUNCTORS &functors, + LOCAL_DATA *data_for_parent=nullptr) const noexcept; + + template + inline void traverseParallelHelper( + INT_TYPE nodei, + INT_TYPE parent_nodei, + INT_TYPE parallel_threshold, + INT_TYPE next_node_id, + FUNCTORS &functors, + LOCAL_DATA *data_for_parent=nullptr) const noexcept; + + template + inline void traverseVectorHelper( + INT_TYPE nodei, + INT_TYPE parent_nodei, + FUNCTORS &functors, + LOCAL_DATA *data_for_parent=nullptr) const noexcept; + + template + static inline void computeFullBoundingBox(Box& axes_minmax, const BOX_TYPE* boxes, const INT_TYPE nboxes, SRC_INT_TYPE* indices) noexcept; + + template + static inline void initNode(UT_Array& nodes, Node &node, const Box& axes_minmax, const BOX_TYPE* boxes, SRC_INT_TYPE* indices, const INT_TYPE nboxes) noexcept; + + template + static inline void initNodeReorder(UT_Array& nodes, Node &node, const Box& axes_minmax, const BOX_TYPE* boxes, SRC_INT_TYPE* indices, const INT_TYPE nboxes, const INT_TYPE indices_offset, const INT_TYPE max_items_per_leaf) noexcept; + + template + static inline void multiSplit(const Box& axes_minmax, const BOX_TYPE* boxes, SRC_INT_TYPE* indices, INT_TYPE nboxes, SRC_INT_TYPE* sub_indices[N+1], Box sub_boxes[N]) noexcept; + + template + static inline void split(const Box& axes_minmax, const BOX_TYPE* boxes, SRC_INT_TYPE* indices, INT_TYPE nboxes, SRC_INT_TYPE*& split_indices, Box* split_boxes) noexcept; + + template + static inline void adjustParallelChildNodes(INT_TYPE nparallel, UT_Array& nodes, Node& node, UT_Array* parallel_nodes, SRC_INT_TYPE* sub_indices) noexcept; + + template + static inline void nthElement(const BOX_TYPE* boxes, SRC_INT_TYPE* indices, const SRC_INT_TYPE* indices_end, const uint axis, SRC_INT_TYPE*const nth) noexcept; + + template + static inline void partitionByCentre(const BOX_TYPE* boxes, SRC_INT_TYPE*const indices, const SRC_INT_TYPE*const indices_end, const uint axis, const T pivotx2, SRC_INT_TYPE*& ppivot_start, SRC_INT_TYPE*& ppivot_end) noexcept; + + /// An overestimate of the number of nodes needed. + /// At worst, we could have only 2 children in every leaf, and + /// then above that, we have a geometric series with r=1/N and a=(sub_nboxes/2)/N + /// The true worst case might be a little worst than this, but + /// it's probably fairly unlikely. + SYS_FORCE_INLINE static INT_TYPE nodeEstimate(const INT_TYPE nboxes) noexcept { + return nboxes/2 + nboxes/(2*(N-1)); + } + + template + SYS_FORCE_INLINE static T unweightedHeuristic(const Box& box) noexcept { + if (H == BVH_Heuristic::BOX_PERIMETER) { + return box.axis_sum(); + } + if (H == BVH_Heuristic::BOX_AREA) { + return box.half_surface_area(); + } + if (H == BVH_Heuristic::BOX_VOLUME) { + return box.volume(); + } + if (H == BVH_Heuristic::BOX_RADIUS) { + T diameter2 = box.diameter2(); + return SYSsqrt(diameter2); + } + if (H == BVH_Heuristic::BOX_RADIUS2) { + return box.diameter2(); + } + if (H == BVH_Heuristic::BOX_RADIUS3) { + T diameter2 = box.diameter2(); + return diameter2*SYSsqrt(diameter2); + } + UT_ASSERT_MSG(0, "BVH_Heuristic::MEDIAN_MAX_AXIS should be handled separately by caller!"); + return T(1); + } + + /// 16 equal-length spans (15 evenly-spaced splits) should be enough for a decent heuristic + static constexpr INT_TYPE NSPANS = 16; + static constexpr INT_TYPE NSPLITS = NSPANS-1; + + /// At least 1/16 of all boxes must be on each side, else we could end up with a very deep tree + static constexpr INT_TYPE MIN_FRACTION = 16; +}; + +} // UT namespace + +template +using UT_BVH = UT::BVH; + +} // End HDK_Sample namespace +}} +#endif +/* + * Copyright (c) 2018 Side Effects Software Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * COMMENTS: + * Bounding Volume Hierarchy (BVH) implementation. + * The main file is UT_BVH.h; this file is separate so that + * files that don't actually need to call functions on the BVH + * won't have unnecessary headers and functions included. + */ + +#pragma once + +#ifndef __HDK_UT_BVHImpl_h__ +#define __HDK_UT_BVHImpl_h__ + + + + + + + + +#include + +#include +#include + +namespace igl { namespace FastWindingNumber { +namespace HDK_Sample { + +namespace UT { + +template +SYS_FORCE_INLINE bool utBoxExclude(const UT::Box& box) noexcept { + bool has_nan_or_inf = !SYSisFinite(box[0][0]); + has_nan_or_inf |= !SYSisFinite(box[0][1]); + for (uint axis = 1; axis < NAXES; ++axis) + { + has_nan_or_inf |= !SYSisFinite(box[axis][0]); + has_nan_or_inf |= !SYSisFinite(box[axis][1]); + } + return has_nan_or_inf; +} +template +SYS_FORCE_INLINE bool utBoxExclude(const UT::Box& box) noexcept { + const int32 *pboxints = reinterpret_cast(&box); + // Fast check for NaN or infinity: check if exponent bits are 0xFF. + bool has_nan_or_inf = ((pboxints[0] & 0x7F800000) == 0x7F800000); + has_nan_or_inf |= ((pboxints[1] & 0x7F800000) == 0x7F800000); + for (uint axis = 1; axis < NAXES; ++axis) + { + has_nan_or_inf |= ((pboxints[2*axis] & 0x7F800000) == 0x7F800000); + has_nan_or_inf |= ((pboxints[2*axis + 1] & 0x7F800000) == 0x7F800000); + } + return has_nan_or_inf; +} +template +SYS_FORCE_INLINE T utBoxCenter(const UT::Box& box, uint axis) noexcept { + const T* v = box.vals[axis]; + return v[0] + v[1]; +} +template +struct ut_BoxCentre { + constexpr static uint scale = 2; +}; +template +SYS_FORCE_INLINE T utBoxExclude(const UT_FixedVector& position) noexcept { + bool has_nan_or_inf = !SYSisFinite(position[0]); + for (uint axis = 1; axis < NAXES; ++axis) + has_nan_or_inf |= !SYSisFinite(position[axis]); + return has_nan_or_inf; +} +template +SYS_FORCE_INLINE bool utBoxExclude(const UT_FixedVector& position) noexcept { + const int32 *ppositionints = reinterpret_cast(&position); + // Fast check for NaN or infinity: check if exponent bits are 0xFF. + bool has_nan_or_inf = ((ppositionints[0] & 0x7F800000) == 0x7F800000); + for (uint axis = 1; axis < NAXES; ++axis) + has_nan_or_inf |= ((ppositionints[axis] & 0x7F800000) == 0x7F800000); + return has_nan_or_inf; +} +template +SYS_FORCE_INLINE T utBoxCenter(const UT_FixedVector& position, uint axis) noexcept { + return position[axis]; +} +template +struct ut_BoxCentre> { + constexpr static uint scale = 1; +}; + +template +inline INT_TYPE utExcludeNaNInfBoxIndices(const BOX_TYPE* boxes, SRC_INT_TYPE* indices, INT_TYPE& nboxes) noexcept +{ + constexpr INT_TYPE PARALLEL_THRESHOLD = 65536; + INT_TYPE ntasks = 1; + //if (nboxes >= PARALLEL_THRESHOLD) + //{ + // INT_TYPE nprocessors = UT_Thread::getNumProcessors(); + // ntasks = (nprocessors > 1) ? SYSmin(4*nprocessors, nboxes/(PARALLEL_THRESHOLD/2)) : 1; + //} + //if (ntasks == 1) + { + // Serial: easy case; just loop through. + + const SRC_INT_TYPE* indices_end = indices + nboxes; + + // Loop through forward once + SRC_INT_TYPE* psrc_index = indices; + for (; psrc_index != indices_end; ++psrc_index) + { + const bool exclude = utBoxExclude(boxes[*psrc_index]); + if (exclude) + break; + } + if (psrc_index == indices_end) + return 0; + + // First NaN or infinite box + SRC_INT_TYPE* nan_start = psrc_index; + for (++psrc_index; psrc_index != indices_end; ++psrc_index) + { + const bool exclude = utBoxExclude(boxes[*psrc_index]); + if (!exclude) + { + *nan_start = *psrc_index; + ++nan_start; + } + } + nboxes = nan_start-indices; + return indices_end - nan_start; + } + +} + +template +template +inline void BVH::init(const BOX_TYPE* boxes, const INT_TYPE nboxes, SRC_INT_TYPE* indices, bool reorder_indices, INT_TYPE max_items_per_leaf) noexcept { + Box axes_minmax; + computeFullBoundingBox(axes_minmax, boxes, nboxes, indices); + + init(axes_minmax, boxes, nboxes, indices, reorder_indices, max_items_per_leaf); +} + +template +template +inline void BVH::init(Box axes_minmax, const BOX_TYPE* boxes, INT_TYPE nboxes, SRC_INT_TYPE* indices, bool reorder_indices, INT_TYPE max_items_per_leaf) noexcept { + // Clear the tree in advance to save memory. + myRoot.reset(); + + if (nboxes == 0) { + myNumNodes = 0; + return; + } + + UT_Array local_indices; + if (!indices) { + local_indices.setSizeNoInit(nboxes); + indices = local_indices.array(); + createTrivialIndices(indices, nboxes); + } + + // Exclude any boxes with NaNs or infinities by shifting down indices + // over the bad box indices and updating nboxes. + INT_TYPE nexcluded = utExcludeNaNInfBoxIndices(boxes, indices, nboxes); + if (nexcluded != 0) { + if (nboxes == 0) { + myNumNodes = 0; + return; + } + computeFullBoundingBox(axes_minmax, boxes, nboxes, indices); + } + + UT_Array nodes; + // Preallocate an overestimate of the number of nodes needed. + nodes.setCapacity(nodeEstimate(nboxes)); + nodes.setSize(1); + if (reorder_indices) + initNodeReorder(nodes, nodes[0], axes_minmax, boxes, indices, nboxes, 0, max_items_per_leaf); + else + initNode(nodes, nodes[0], axes_minmax, boxes, indices, nboxes); + + // If capacity is more than 12.5% over the size, rellocate. + if (8*nodes.capacity() > 9*nodes.size()) { + nodes.setCapacity(nodes.size()); + } + // Steal ownership of the array from the UT_Array + myRoot.reset(nodes.array()); + myNumNodes = nodes.size(); + nodes.unsafeClearData(); +} + +template +template +inline void BVH::traverse( + FUNCTORS &functors, + LOCAL_DATA* data_for_parent) const noexcept +{ + if (!myRoot) + return; + + // NOTE: The root is always index 0. + traverseHelper(0, INT_TYPE(-1), functors, data_for_parent); +} +template +template +inline void BVH::traverseHelper( + INT_TYPE nodei, + INT_TYPE parent_nodei, + FUNCTORS &functors, + LOCAL_DATA* data_for_parent) const noexcept +{ + const Node &node = myRoot[nodei]; + bool descend = functors.pre(nodei, data_for_parent); + if (!descend) + return; + LOCAL_DATA local_data[N]; + INT_TYPE s; + for (s = 0; s < N; ++s) { + const INT_TYPE node_int = node.child[s]; + if (Node::isInternal(node_int)) { + if (node_int == Node::EMPTY) { + // NOTE: Anything after this will be empty too, so we can break. + break; + } + traverseHelper(Node::getInternalNum(node_int), nodei, functors, &local_data[s]); + } + else { + functors.item(node_int, nodei, local_data[s]); + } + } + // NOTE: s is now the number of non-empty entries in this node. + functors.post(nodei, parent_nodei, data_for_parent, s, local_data); +} + +template +template +inline void BVH::traverseParallel( + INT_TYPE parallel_threshold, + FUNCTORS& functors, + LOCAL_DATA* data_for_parent) const noexcept +{ + if (!myRoot) + return; + + // NOTE: The root is always index 0. + traverseParallelHelper(0, INT_TYPE(-1), parallel_threshold, myNumNodes, functors, data_for_parent); +} +template +template +inline void BVH::traverseParallelHelper( + INT_TYPE nodei, + INT_TYPE parent_nodei, + INT_TYPE parallel_threshold, + INT_TYPE next_node_id, + FUNCTORS& functors, + LOCAL_DATA* data_for_parent) const noexcept +{ + const Node &node = myRoot[nodei]; + bool descend = functors.pre(nodei, data_for_parent); + if (!descend) + return; + + // To determine the number of nodes in a child's subtree, we take the next + // node ID minus the current child's node ID. + INT_TYPE next_nodes[N]; + INT_TYPE nnodes[N]; + INT_TYPE nchildren = N; + INT_TYPE nparallel = 0; + // s is currently unsigned, so we check s < N for bounds check. + // The s >= 0 check is in case s ever becomes signed, and should be + // automatically removed by the compiler for unsigned s. + for (INT_TYPE s = N-1; (std::is_signed::value ? (s >= 0) : (s < N)); --s) { + const INT_TYPE node_int = node.child[s]; + if (node_int == Node::EMPTY) { + --nchildren; + continue; + } + next_nodes[s] = next_node_id; + if (Node::isInternal(node_int)) { + // NOTE: This depends on BVH::initNode appending the child nodes + // in between their content, instead of all at once. + INT_TYPE child_node_id = Node::getInternalNum(node_int); + nnodes[s] = next_node_id - child_node_id; + next_node_id = child_node_id; + } + else { + nnodes[s] = 0; + } + nparallel += (nnodes[s] >= parallel_threshold); + } + + LOCAL_DATA local_data[N]; + if (nparallel >= 2) { + // Do any non-parallel ones first + if (nparallel < nchildren) { + for (INT_TYPE s = 0; s < N; ++s) { + if (nnodes[s] >= parallel_threshold) { + continue; + } + const INT_TYPE node_int = node.child[s]; + if (Node::isInternal(node_int)) { + if (node_int == Node::EMPTY) { + // NOTE: Anything after this will be empty too, so we can break. + break; + } + traverseHelper(Node::getInternalNum(node_int), nodei, functors, &local_data[s]); + } + else { + functors.item(node_int, nodei, local_data[s]); + } + } + } + // Now do the parallel ones + igl::parallel_for( + nparallel, + [this,nodei,&node,&nnodes,&next_nodes,¶llel_threshold,&functors,&local_data](int taski) + { + INT_TYPE parallel_count = 0; + // NOTE: The check for s < N is just so that the compiler can + // (hopefully) figure out that it can fully unroll the loop. + INT_TYPE s; + for (s = 0; s < N; ++s) { + if (nnodes[s] < parallel_threshold) { + continue; + } + if (parallel_count == taski) { + break; + } + ++parallel_count; + } + const INT_TYPE node_int = node.child[s]; + if (Node::isInternal(node_int)) { + UT_ASSERT_MSG_P(node_int != Node::EMPTY, "Empty entries should have been excluded above."); + traverseParallelHelper(Node::getInternalNum(node_int), nodei, parallel_threshold, next_nodes[s], functors, &local_data[s]); + } + else { + functors.item(node_int, nodei, local_data[s]); + } + }); + } + else { + // All in serial + for (INT_TYPE s = 0; s < N; ++s) { + const INT_TYPE node_int = node.child[s]; + if (Node::isInternal(node_int)) { + if (node_int == Node::EMPTY) { + // NOTE: Anything after this will be empty too, so we can break. + break; + } + traverseHelper(Node::getInternalNum(node_int), nodei, functors, &local_data[s]); + } + else { + functors.item(node_int, nodei, local_data[s]); + } + } + } + functors.post(nodei, parent_nodei, data_for_parent, nchildren, local_data); +} + +template +template +inline void BVH::traverseVector( + FUNCTORS &functors, + LOCAL_DATA* data_for_parent) const noexcept +{ + if (!myRoot) + return; + + // NOTE: The root is always index 0. + traverseVectorHelper(0, INT_TYPE(-1), functors, data_for_parent); +} +template +template +inline void BVH::traverseVectorHelper( + INT_TYPE nodei, + INT_TYPE parent_nodei, + FUNCTORS &functors, + LOCAL_DATA* data_for_parent) const noexcept +{ + const Node &node = myRoot[nodei]; + INT_TYPE descend = functors.pre(nodei, data_for_parent); + if (!descend) + return; + LOCAL_DATA local_data[N]; + INT_TYPE s; + for (s = 0; s < N; ++s) { + if ((descend>>s) & 1) { + const INT_TYPE node_int = node.child[s]; + if (Node::isInternal(node_int)) { + if (node_int == Node::EMPTY) { + // NOTE: Anything after this will be empty too, so we can break. + descend &= (INT_TYPE(1)< +template +inline void BVH::createTrivialIndices(SRC_INT_TYPE* indices, const INT_TYPE n) noexcept { + igl::parallel_for(n, [indices,n](INT_TYPE i) { indices[i] = i; }, 65536); +} + +template +template +inline void BVH::computeFullBoundingBox(Box& axes_minmax, const BOX_TYPE* boxes, const INT_TYPE nboxes, SRC_INT_TYPE* indices) noexcept { + if (!nboxes) { + axes_minmax.initBounds(); + return; + } + INT_TYPE ntasks = 1; + if (nboxes >= 2*4096) { + INT_TYPE nprocessors = UT_Thread::getNumProcessors(); + ntasks = (nprocessors > 1) ? SYSmin(4*nprocessors, nboxes/4096) : 1; + } + if (ntasks == 1) { + Box box; + if (indices) { + box.initBounds(boxes[indices[0]]); + for (INT_TYPE i = 1; i < nboxes; ++i) { + box.combine(boxes[indices[i]]); + } + } + else { + box.initBounds(boxes[0]); + for (INT_TYPE i = 1; i < nboxes; ++i) { + box.combine(boxes[i]); + } + } + axes_minmax = box; + } + else { + UT_SmallArray> parallel_boxes; + Box box; + igl::parallel_for( + nboxes, + [¶llel_boxes](int n){parallel_boxes.setSize(n);}, + [¶llel_boxes,indices,&boxes](int i, int t) + { + if(indices) + { + parallel_boxes[t].combine(boxes[indices[i]]); + }else + { + parallel_boxes[t].combine(boxes[i]); + } + }, + [¶llel_boxes,&box](int t) + { + if(t == 0) + { + box = parallel_boxes[0]; + }else + { + box.combine(parallel_boxes[t]); + } + }); + + axes_minmax = box; + } +} + +template +template +inline void BVH::initNode(UT_Array& nodes, Node &node, const Box& axes_minmax, const BOX_TYPE* boxes, SRC_INT_TYPE* indices, const INT_TYPE nboxes) noexcept { + if (nboxes <= N) { + // Fits in one node + for (INT_TYPE i = 0; i < nboxes; ++i) { + node.child[i] = indices[i]; + } + for (INT_TYPE i = nboxes; i < N; ++i) { + node.child[i] = Node::EMPTY; + } + return; + } + + SRC_INT_TYPE* sub_indices[N+1]; + Box sub_boxes[N]; + + if (N == 2) { + sub_indices[0] = indices; + sub_indices[2] = indices+nboxes; + split(axes_minmax, boxes, indices, nboxes, sub_indices[1], &sub_boxes[0]); + } + else { + multiSplit(axes_minmax, boxes, indices, nboxes, sub_indices, sub_boxes); + } + + // Count the number of nodes to run in parallel and fill in single items in this node + INT_TYPE nparallel = 0; + static constexpr INT_TYPE PARALLEL_THRESHOLD = 1024; + for (INT_TYPE i = 0; i < N; ++i) { + INT_TYPE sub_nboxes = sub_indices[i+1]-sub_indices[i]; + if (sub_nboxes == 1) { + node.child[i] = sub_indices[i][0]; + } + else if (sub_nboxes >= PARALLEL_THRESHOLD) { + ++nparallel; + } + } + + // NOTE: Child nodes of this node need to be placed just before the nodes in + // their corresponding subtree, in between the subtrees, because + // traverseParallel uses the difference between the child node IDs + // to determine the number of nodes in the subtree. + + // Recurse + if (nparallel >= 2) { + UT_SmallArray> parallel_nodes; + UT_SmallArray parallel_parent_nodes; + parallel_nodes.setSize(nparallel); + parallel_parent_nodes.setSize(nparallel); + igl::parallel_for( + nparallel, + [¶llel_nodes,¶llel_parent_nodes,&sub_indices,boxes,&sub_boxes](int taski) + { + // First, find which child this is + INT_TYPE counted_parallel = 0; + INT_TYPE sub_nboxes; + INT_TYPE childi; + for (childi = 0; childi < N; ++childi) { + sub_nboxes = sub_indices[childi+1]-sub_indices[childi]; + if (sub_nboxes >= PARALLEL_THRESHOLD) { + if (counted_parallel == taski) { + break; + } + ++counted_parallel; + } + } + UT_ASSERT_P(counted_parallel == taski); + + UT_Array& local_nodes = parallel_nodes[taski]; + // Preallocate an overestimate of the number of nodes needed. + // At worst, we could have only 2 children in every leaf, and + // then above that, we have a geometric series with r=1/N and a=(sub_nboxes/2)/N + // The true worst case might be a little worst than this, but + // it's probably fairly unlikely. + local_nodes.setCapacity(nodeEstimate(sub_nboxes)); + Node& parent_node = parallel_parent_nodes[taski]; + + // We'll have to fix the internal node numbers in parent_node and local_nodes later + initNode(local_nodes, parent_node, sub_boxes[childi], boxes, sub_indices[childi], sub_nboxes); + }); + + INT_TYPE counted_parallel = 0; + for (INT_TYPE i = 0; i < N; ++i) { + INT_TYPE sub_nboxes = sub_indices[i+1]-sub_indices[i]; + if (sub_nboxes != 1) { + INT_TYPE local_nodes_start = nodes.size(); + node.child[i] = Node::markInternal(local_nodes_start); + if (sub_nboxes >= PARALLEL_THRESHOLD) { + // First, adjust the root child node + Node child_node = parallel_parent_nodes[counted_parallel]; + ++local_nodes_start; + for (INT_TYPE childi = 0; childi < N; ++childi) { + INT_TYPE child_child = child_node.child[childi]; + if (Node::isInternal(child_child) && child_child != Node::EMPTY) { + child_child += local_nodes_start; + child_node.child[childi] = child_child; + } + } + + // Make space in the array for the sub-child nodes + const UT_Array& local_nodes = parallel_nodes[counted_parallel]; + ++counted_parallel; + INT_TYPE n = local_nodes.size(); + nodes.bumpCapacity(local_nodes_start + n); + nodes.setSizeNoInit(local_nodes_start + n); + nodes[local_nodes_start-1] = child_node; + } + else { + nodes.bumpCapacity(local_nodes_start + 1); + nodes.setSizeNoInit(local_nodes_start + 1); + initNode(nodes, nodes[local_nodes_start], sub_boxes[i], boxes, sub_indices[i], sub_nboxes); + } + } + } + + // Now, adjust and copy all sub-child nodes that were made in parallel + adjustParallelChildNodes(nparallel, nodes, node, parallel_nodes.array(), sub_indices); + } + else { + for (INT_TYPE i = 0; i < N; ++i) { + INT_TYPE sub_nboxes = sub_indices[i+1]-sub_indices[i]; + if (sub_nboxes != 1) { + INT_TYPE local_nodes_start = nodes.size(); + node.child[i] = Node::markInternal(local_nodes_start); + nodes.bumpCapacity(local_nodes_start + 1); + nodes.setSizeNoInit(local_nodes_start + 1); + initNode(nodes, nodes[local_nodes_start], sub_boxes[i], boxes, sub_indices[i], sub_nboxes); + } + } + } +} + +template +template +inline void BVH::initNodeReorder(UT_Array& nodes, Node &node, const Box& axes_minmax, const BOX_TYPE* boxes, SRC_INT_TYPE* indices, INT_TYPE nboxes, const INT_TYPE indices_offset, const INT_TYPE max_items_per_leaf) noexcept { + if (nboxes <= N) { + // Fits in one node + for (INT_TYPE i = 0; i < nboxes; ++i) { + node.child[i] = indices_offset+i; + } + for (INT_TYPE i = nboxes; i < N; ++i) { + node.child[i] = Node::EMPTY; + } + return; + } + + SRC_INT_TYPE* sub_indices[N+1]; + Box sub_boxes[N]; + + if (N == 2) { + sub_indices[0] = indices; + sub_indices[2] = indices+nboxes; + split(axes_minmax, boxes, indices, nboxes, sub_indices[1], &sub_boxes[0]); + } + else { + multiSplit(axes_minmax, boxes, indices, nboxes, sub_indices, sub_boxes); + } + + // Move any children with max_items_per_leaf or fewer indices before any children with more, + // for better cache coherence when we're accessing data in a corresponding array. + INT_TYPE nleaves = 0; + UT_SmallArray leaf_indices; + SRC_INT_TYPE leaf_sizes[N]; + INT_TYPE sub_nboxes0 = sub_indices[1]-sub_indices[0]; + if (sub_nboxes0 <= max_items_per_leaf) { + leaf_sizes[0] = sub_nboxes0; + for (int j = 0; j < sub_nboxes0; ++j) + leaf_indices.append(sub_indices[0][j]); + ++nleaves; + } + INT_TYPE sub_nboxes1 = sub_indices[2]-sub_indices[1]; + if (sub_nboxes1 <= max_items_per_leaf) { + leaf_sizes[nleaves] = sub_nboxes1; + for (int j = 0; j < sub_nboxes1; ++j) + leaf_indices.append(sub_indices[1][j]); + ++nleaves; + } + for (INT_TYPE i = 2; i < N; ++i) { + INT_TYPE sub_nboxes = sub_indices[i+1]-sub_indices[i]; + if (sub_nboxes <= max_items_per_leaf) { + leaf_sizes[nleaves] = sub_nboxes; + for (int j = 0; j < sub_nboxes; ++j) + leaf_indices.append(sub_indices[i][j]); + ++nleaves; + } + } + if (nleaves > 0) { + // NOTE: i < N condition is because INT_TYPE is unsigned. + // i >= 0 condition is in case INT_TYPE is changed to signed. + INT_TYPE move_distance = 0; + INT_TYPE index_move_distance = 0; + for (INT_TYPE i = N-1; (std::is_signed::value ? (i >= 0) : (i < N)); --i) { + INT_TYPE sub_nboxes = sub_indices[i+1]-sub_indices[i]; + if (sub_nboxes <= max_items_per_leaf) { + ++move_distance; + index_move_distance += sub_nboxes; + } + else if (move_distance > 0) { + SRC_INT_TYPE *start_src_index = sub_indices[i]; + for (SRC_INT_TYPE *src_index = sub_indices[i+1]-1; src_index >= start_src_index; --src_index) { + src_index[index_move_distance] = src_index[0]; + } + sub_indices[i+move_distance] = sub_indices[i]+index_move_distance; + } + } + index_move_distance = 0; + for (INT_TYPE i = 0; i < nleaves; ++i) { + INT_TYPE sub_nboxes = leaf_sizes[i]; + sub_indices[i] = indices+index_move_distance; + for (int j = 0; j < sub_nboxes; ++j) + indices[index_move_distance+j] = leaf_indices[index_move_distance+j]; + index_move_distance += sub_nboxes; + } + } + + // Count the number of nodes to run in parallel and fill in single items in this node + INT_TYPE nparallel = 0; + static constexpr INT_TYPE PARALLEL_THRESHOLD = 1024; + for (INT_TYPE i = 0; i < N; ++i) { + INT_TYPE sub_nboxes = sub_indices[i+1]-sub_indices[i]; + if (sub_nboxes <= max_items_per_leaf) { + node.child[i] = indices_offset+(sub_indices[i]-sub_indices[0]); + } + else if (sub_nboxes >= PARALLEL_THRESHOLD) { + ++nparallel; + } + } + + // NOTE: Child nodes of this node need to be placed just before the nodes in + // their corresponding subtree, in between the subtrees, because + // traverseParallel uses the difference between the child node IDs + // to determine the number of nodes in the subtree. + + // Recurse + if (nparallel >= 2 && false) { + assert(false && "Not implemented; should never get here"); + exit(1); + // // Do the parallel ones first, so that they can be inserted in the right place. + // // Although the choice may seem somewhat arbitrary, we need the results to be + // // identical whether we choose to parallelize or not, and in case we change the + // // threshold later. + // UT_SmallArray,4*sizeof(UT_Array)> parallel_nodes; + // parallel_nodes.setSize(nparallel); + // UT_SmallArray parallel_parent_nodes; + // parallel_parent_nodes.setSize(nparallel); + // UTparallelFor(UT_BlockedRange(0,nparallel), [¶llel_nodes,¶llel_parent_nodes,&sub_indices,boxes,&sub_boxes,indices_offset,max_items_per_leaf](const UT_BlockedRange& r) { + // for (INT_TYPE taski = r.begin(), end = r.end(); taski < end; ++taski) { + // // First, find which child this is + // INT_TYPE counted_parallel = 0; + // INT_TYPE sub_nboxes; + // INT_TYPE childi; + // for (childi = 0; childi < N; ++childi) { + // sub_nboxes = sub_indices[childi+1]-sub_indices[childi]; + // if (sub_nboxes >= PARALLEL_THRESHOLD) { + // if (counted_parallel == taski) { + // break; + // } + // ++counted_parallel; + // } + // } + // UT_ASSERT_P(counted_parallel == taski); + + // UT_Array& local_nodes = parallel_nodes[taski]; + // // Preallocate an overestimate of the number of nodes needed. + // // At worst, we could have only 2 children in every leaf, and + // // then above that, we have a geometric series with r=1/N and a=(sub_nboxes/2)/N + // // The true worst case might be a little worst than this, but + // // it's probably fairly unlikely. + // local_nodes.setCapacity(nodeEstimate(sub_nboxes)); + // Node& parent_node = parallel_parent_nodes[taski]; + + // // We'll have to fix the internal node numbers in parent_node and local_nodes later + // initNodeReorder(local_nodes, parent_node, sub_boxes[childi], boxes, sub_indices[childi], sub_nboxes, + // indices_offset+(sub_indices[childi]-sub_indices[0]), max_items_per_leaf); + // } + // }, 0, 1); + + // INT_TYPE counted_parallel = 0; + // for (INT_TYPE i = 0; i < N; ++i) { + // INT_TYPE sub_nboxes = sub_indices[i+1]-sub_indices[i]; + // if (sub_nboxes > max_items_per_leaf) { + // INT_TYPE local_nodes_start = nodes.size(); + // node.child[i] = Node::markInternal(local_nodes_start); + // if (sub_nboxes >= PARALLEL_THRESHOLD) { + // // First, adjust the root child node + // Node child_node = parallel_parent_nodes[counted_parallel]; + // ++local_nodes_start; + // for (INT_TYPE childi = 0; childi < N; ++childi) { + // INT_TYPE child_child = child_node.child[childi]; + // if (Node::isInternal(child_child) && child_child != Node::EMPTY) { + // child_child += local_nodes_start; + // child_node.child[childi] = child_child; + // } + // } + + // // Make space in the array for the sub-child nodes + // const UT_Array& local_nodes = parallel_nodes[counted_parallel]; + // ++counted_parallel; + // INT_TYPE n = local_nodes.size(); + // nodes.bumpCapacity(local_nodes_start + n); + // nodes.setSizeNoInit(local_nodes_start + n); + // nodes[local_nodes_start-1] = child_node; + // } + // else { + // nodes.bumpCapacity(local_nodes_start + 1); + // nodes.setSizeNoInit(local_nodes_start + 1); + // initNodeReorder(nodes, nodes[local_nodes_start], sub_boxes[i], boxes, sub_indices[i], sub_nboxes, + // indices_offset+(sub_indices[i]-sub_indices[0]), max_items_per_leaf); + // } + // } + // } + + // // Now, adjust and copy all sub-child nodes that were made in parallel + // adjustParallelChildNodes(nparallel, nodes, node, parallel_nodes.array(), sub_indices); + } + else { + for (INT_TYPE i = 0; i < N; ++i) { + INT_TYPE sub_nboxes = sub_indices[i+1]-sub_indices[i]; + if (sub_nboxes > max_items_per_leaf) { + INT_TYPE local_nodes_start = nodes.size(); + node.child[i] = Node::markInternal(local_nodes_start); + nodes.bumpCapacity(local_nodes_start + 1); + nodes.setSizeNoInit(local_nodes_start + 1); + initNodeReorder(nodes, nodes[local_nodes_start], sub_boxes[i], boxes, sub_indices[i], sub_nboxes, + indices_offset+(sub_indices[i]-sub_indices[0]), max_items_per_leaf); + } + } + } +} + +template +template +inline void BVH::multiSplit(const Box& axes_minmax, const BOX_TYPE* boxes, SRC_INT_TYPE* indices, INT_TYPE nboxes, SRC_INT_TYPE* sub_indices[N+1], Box sub_boxes[N]) noexcept { + sub_indices[0] = indices; + sub_indices[2] = indices+nboxes; + split(axes_minmax, boxes, indices, nboxes, sub_indices[1], &sub_boxes[0]); + + if (N == 2) { + return; + } + + if (H == BVH_Heuristic::MEDIAN_MAX_AXIS) { + SRC_INT_TYPE* sub_indices_startend[2*N]; + Box sub_boxes_unsorted[N]; + sub_boxes_unsorted[0] = sub_boxes[0]; + sub_boxes_unsorted[1] = sub_boxes[1]; + sub_indices_startend[0] = sub_indices[0]; + sub_indices_startend[1] = sub_indices[1]; + sub_indices_startend[2] = sub_indices[1]; + sub_indices_startend[3] = sub_indices[2]; + for (INT_TYPE nsub = 2; nsub < N; ++nsub) { + SRC_INT_TYPE* selected_start = sub_indices_startend[0]; + SRC_INT_TYPE* selected_end = sub_indices_startend[1]; + Box sub_box = sub_boxes_unsorted[0]; + + // Shift results back. + for (INT_TYPE i = 0; i < nsub-1; ++i) { + sub_indices_startend[2*i ] = sub_indices_startend[2*i+2]; + sub_indices_startend[2*i+1] = sub_indices_startend[2*i+3]; + } + for (INT_TYPE i = 0; i < nsub-1; ++i) { + sub_boxes_unsorted[i] = sub_boxes_unsorted[i-1]; + } + + // Do the split + split(sub_box, boxes, selected_start, selected_end-selected_start, sub_indices_startend[2*nsub-1], &sub_boxes_unsorted[nsub]); + sub_indices_startend[2*nsub-2] = selected_start; + sub_indices_startend[2*nsub] = sub_indices_startend[2*nsub-1]; + sub_indices_startend[2*nsub+1] = selected_end; + + // Sort pointers so that they're in the correct order + sub_indices[N] = indices+nboxes; + for (INT_TYPE i = 0; i < N; ++i) { + SRC_INT_TYPE* prev_pointer = (i != 0) ? sub_indices[i-1] : nullptr; + SRC_INT_TYPE* min_pointer = nullptr; + Box box; + for (INT_TYPE j = 0; j < N; ++j) { + SRC_INT_TYPE* cur_pointer = sub_indices_startend[2*j]; + if ((cur_pointer > prev_pointer) && (!min_pointer || (cur_pointer < min_pointer))) { + min_pointer = cur_pointer; + box = sub_boxes_unsorted[j]; + } + } + UT_ASSERT_P(min_pointer); + sub_indices[i] = min_pointer; + sub_boxes[i] = box; + } + } + } + else { + T sub_box_areas[N]; + sub_box_areas[0] = unweightedHeuristic(sub_boxes[0]); + sub_box_areas[1] = unweightedHeuristic(sub_boxes[1]); + for (INT_TYPE nsub = 2; nsub < N; ++nsub) { + // Choose which one to split + INT_TYPE split_choice = INT_TYPE(-1); + T max_heuristic; + for (INT_TYPE i = 0; i < nsub; ++i) { + const INT_TYPE index_count = (sub_indices[i+1]-sub_indices[i]); + if (index_count > 1) { + const T heuristic = sub_box_areas[i]*index_count; + if (split_choice == INT_TYPE(-1) || heuristic > max_heuristic) { + split_choice = i; + max_heuristic = heuristic; + } + } + } + UT_ASSERT_MSG_P(split_choice != INT_TYPE(-1), "There should always be at least one that can be split!"); + + SRC_INT_TYPE* selected_start = sub_indices[split_choice]; + SRC_INT_TYPE* selected_end = sub_indices[split_choice+1]; + + // Shift results over; we can skip the one we selected. + for (INT_TYPE i = nsub; i > split_choice; --i) { + sub_indices[i+1] = sub_indices[i]; + } + for (INT_TYPE i = nsub-1; i > split_choice; --i) { + sub_boxes[i+1] = sub_boxes[i]; + } + for (INT_TYPE i = nsub-1; i > split_choice; --i) { + sub_box_areas[i+1] = sub_box_areas[i]; + } + + // Do the split + split(sub_boxes[split_choice], boxes, selected_start, selected_end-selected_start, sub_indices[split_choice+1], &sub_boxes[split_choice]); + sub_box_areas[split_choice] = unweightedHeuristic(sub_boxes[split_choice]); + sub_box_areas[split_choice+1] = unweightedHeuristic(sub_boxes[split_choice+1]); + } + } +} + +template +template +inline void BVH::split(const Box& axes_minmax, const BOX_TYPE* boxes, SRC_INT_TYPE* indices, INT_TYPE nboxes, SRC_INT_TYPE*& split_indices, Box* split_boxes) noexcept { + if (nboxes == 2) { + split_boxes[0].initBounds(boxes[indices[0]]); + split_boxes[1].initBounds(boxes[indices[1]]); + split_indices = indices+1; + return; + } + UT_ASSERT_MSG_P(nboxes > 2, "Cases with less than 3 boxes should have already been handled!"); + + if (H == BVH_Heuristic::MEDIAN_MAX_AXIS) { + UT_ASSERT_MSG(0, "FIXME: Implement this!!!"); + } + + constexpr INT_TYPE SMALL_LIMIT = 6; + if (nboxes <= SMALL_LIMIT) { + // Special case for a small number of boxes: check all (2^(n-1))-1 partitions. + // Without loss of generality, we assume that box 0 is in partition 0, + // and that not all boxes are in partition 0. + Box local_boxes[SMALL_LIMIT]; + for (INT_TYPE box = 0; box < nboxes; ++box) { + local_boxes[box].initBounds(boxes[indices[box]]); + //printf("Box %u: (%f-%f)x(%f-%f)x(%f-%f)\n", uint(box), local_boxes[box].vals[0][0], local_boxes[box].vals[0][1], local_boxes[box].vals[1][0], local_boxes[box].vals[1][1], local_boxes[box].vals[2][0], local_boxes[box].vals[2][1]); + } + const INT_TYPE partition_limit = (INT_TYPE(1)<<(nboxes-1)); + INT_TYPE best_partition = INT_TYPE(-1); + T best_heuristic; + for (INT_TYPE partition_bits = 1; partition_bits < partition_limit; ++partition_bits) { + Box sub_boxes[2]; + sub_boxes[0] = local_boxes[0]; + sub_boxes[1].initBounds(); + INT_TYPE sub_counts[2] = {1,0}; + for (INT_TYPE bit = 0; bit < nboxes-1; ++bit) { + INT_TYPE dest = (partition_bits>>bit)&1; + sub_boxes[dest].combine(local_boxes[bit+1]); + ++sub_counts[dest]; + } + //printf("Partition bits %u: sub_box[0]: (%f-%f)x(%f-%f)x(%f-%f)\n", uint(partition_bits), sub_boxes[0].vals[0][0], sub_boxes[0].vals[0][1], sub_boxes[0].vals[1][0], sub_boxes[0].vals[1][1], sub_boxes[0].vals[2][0], sub_boxes[0].vals[2][1]); + //printf("Partition bits %u: sub_box[1]: (%f-%f)x(%f-%f)x(%f-%f)\n", uint(partition_bits), sub_boxes[1].vals[0][0], sub_boxes[1].vals[0][1], sub_boxes[1].vals[1][0], sub_boxes[1].vals[1][1], sub_boxes[1].vals[2][0], sub_boxes[1].vals[2][1]); + const T heuristic = + unweightedHeuristic(sub_boxes[0])*sub_counts[0] + + unweightedHeuristic(sub_boxes[1])*sub_counts[1]; + //printf("Partition bits %u: heuristic = %f (= %f*%u + %f*%u)\n",uint(partition_bits),heuristic, unweightedHeuristic(sub_boxes[0]), uint(sub_counts[0]), unweightedHeuristic(sub_boxes[1]), uint(sub_counts[1])); + if (best_partition == INT_TYPE(-1) || heuristic < best_heuristic) { + //printf(" New best\n"); + best_partition = partition_bits; + best_heuristic = heuristic; + split_boxes[0] = sub_boxes[0]; + split_boxes[1] = sub_boxes[1]; + } + } + +#if 0 // This isn't actually necessary with the current design, because I changed how the number of subtree nodes is determined. + // If best_partition is partition_limit-1, there's only 1 box + // in partition 0. We should instead put this in partition 1, + // so that we can help always have the internal node indices first + // in each node. That gets used to (fairly) quickly determine + // the number of nodes in a sub-tree. + if (best_partition == partition_limit - 1) { + // Put the first index last. + SRC_INT_TYPE last_index = indices[0]; + SRC_INT_TYPE* dest_indices = indices; + SRC_INT_TYPE* local_split_indices = indices + nboxes-1; + for (; dest_indices != local_split_indices; ++dest_indices) { + dest_indices[0] = dest_indices[1]; + } + *local_split_indices = last_index; + split_indices = local_split_indices; + + // Swap the boxes + const Box temp_box = sub_boxes[0]; + sub_boxes[0] = sub_boxes[1]; + sub_boxes[1] = temp_box; + return; + } +#endif + + // Reorder the indices. + // NOTE: Index 0 is always in partition 0, so can stay put. + SRC_INT_TYPE local_indices[SMALL_LIMIT-1]; + for (INT_TYPE box = 0; box < nboxes-1; ++box) { + local_indices[box] = indices[box+1]; + } + SRC_INT_TYPE* dest_indices = indices+1; + SRC_INT_TYPE* src_indices = local_indices; + // Copy partition 0 + for (INT_TYPE bit = 0; bit < nboxes-1; ++bit, ++src_indices) { + if (!((best_partition>>bit)&1)) { + //printf("Copying %u into partition 0\n",uint(*src_indices)); + *dest_indices = *src_indices; + ++dest_indices; + } + } + split_indices = dest_indices; + // Copy partition 1 + src_indices = local_indices; + for (INT_TYPE bit = 0; bit < nboxes-1; ++bit, ++src_indices) { + if ((best_partition>>bit)&1) { + //printf("Copying %u into partition 1\n",uint(*src_indices)); + *dest_indices = *src_indices; + ++dest_indices; + } + } + return; + } + + uint max_axis = 0; + T max_axis_length = axes_minmax.vals[0][1] - axes_minmax.vals[0][0]; + for (uint axis = 1; axis < NAXES; ++axis) { + const T axis_length = axes_minmax.vals[axis][1] - axes_minmax.vals[axis][0]; + if (axis_length > max_axis_length) { + max_axis = axis; + max_axis_length = axis_length; + } + } + + if (!(max_axis_length > T(0))) { + // All boxes are a single point or NaN. + // Pick an arbitrary split point. + split_indices = indices + nboxes/2; + split_boxes[0] = axes_minmax; + split_boxes[1] = axes_minmax; + return; + } + + const INT_TYPE axis = max_axis; + + constexpr INT_TYPE MID_LIMIT = 2*NSPANS; + if (nboxes <= MID_LIMIT) { + // Sort along axis, and try all possible splits. + +#if 1 + // First, compute midpoints + T midpointsx2[MID_LIMIT]; + for (INT_TYPE i = 0; i < nboxes; ++i) { + midpointsx2[i] = utBoxCenter(boxes[indices[i]], axis); + } + SRC_INT_TYPE local_indices[MID_LIMIT]; + for (INT_TYPE i = 0; i < nboxes; ++i) { + local_indices[i] = i; + } + + const INT_TYPE chunk_starts[5] = {0, nboxes/4, nboxes/2, INT_TYPE((3*uint64(nboxes))/4), nboxes}; + + // For sorting, insertion sort 4 chunks and merge them + for (INT_TYPE chunk = 0; chunk < 4; ++chunk) { + const INT_TYPE start = chunk_starts[chunk]; + const INT_TYPE end = chunk_starts[chunk+1]; + for (INT_TYPE i = start+1; i < end; ++i) { + SRC_INT_TYPE indexi = local_indices[i]; + T vi = midpointsx2[indexi]; + for (INT_TYPE j = start; j < i; ++j) { + SRC_INT_TYPE indexj = local_indices[j]; + T vj = midpointsx2[indexj]; + if (vi < vj) { + do { + local_indices[j] = indexi; + indexi = indexj; + ++j; + if (j == i) { + local_indices[j] = indexi; + break; + } + indexj = local_indices[j]; + } while (true); + break; + } + } + } + } + // Merge chunks into another buffer + SRC_INT_TYPE local_indices_temp[MID_LIMIT]; + std::merge(local_indices, local_indices+chunk_starts[1], + local_indices+chunk_starts[1], local_indices+chunk_starts[2], + local_indices_temp, [&midpointsx2](const SRC_INT_TYPE a, const SRC_INT_TYPE b)->bool { + return midpointsx2[a] < midpointsx2[b]; + }); + std::merge(local_indices+chunk_starts[2], local_indices+chunk_starts[3], + local_indices+chunk_starts[3], local_indices+chunk_starts[4], + local_indices_temp+chunk_starts[2], [&midpointsx2](const SRC_INT_TYPE a, const SRC_INT_TYPE b)->bool { + return midpointsx2[a] < midpointsx2[b]; + }); + std::merge(local_indices_temp, local_indices_temp+chunk_starts[2], + local_indices_temp+chunk_starts[2], local_indices_temp+chunk_starts[4], + local_indices, [&midpointsx2](const SRC_INT_TYPE a, const SRC_INT_TYPE b)->bool { + return midpointsx2[a] < midpointsx2[b]; + }); + + // Translate local_indices into indices + for (INT_TYPE i = 0; i < nboxes; ++i) { + local_indices[i] = indices[local_indices[i]]; + } + // Copy back + for (INT_TYPE i = 0; i < nboxes; ++i) { + indices[i] = local_indices[i]; + } +#else + std::stable_sort(indices, indices+nboxes, [boxes,max_axis](SRC_INT_TYPE a, SRC_INT_TYPE b)->bool { + return utBoxCenter(boxes[a], max_axis) < utBoxCenter(boxes[b], max_axis); + }); +#endif + + // Accumulate boxes + Box left_boxes[MID_LIMIT-1]; + Box right_boxes[MID_LIMIT-1]; + const INT_TYPE nsplits = nboxes-1; + Box box_accumulator(boxes[local_indices[0]]); + left_boxes[0] = box_accumulator; + for (INT_TYPE i = 1; i < nsplits; ++i) { + box_accumulator.combine(boxes[local_indices[i]]); + left_boxes[i] = box_accumulator; + } + box_accumulator.initBounds(boxes[local_indices[nsplits-1]]); + right_boxes[nsplits-1] = box_accumulator; + for (INT_TYPE i = nsplits-1; i > 0; --i) { + box_accumulator.combine(boxes[local_indices[i]]); + right_boxes[i-1] = box_accumulator; + } + + INT_TYPE best_split = 0; + T best_local_heuristic = + unweightedHeuristic(left_boxes[0]) + + unweightedHeuristic(right_boxes[0])*(nboxes-1); + for (INT_TYPE split = 1; split < nsplits; ++split) { + const T heuristic = + unweightedHeuristic(left_boxes[split])*(split+1) + + unweightedHeuristic(right_boxes[split])*(nboxes-(split+1)); + if (heuristic < best_local_heuristic) { + best_split = split; + best_local_heuristic = heuristic; + } + } + split_indices = indices+best_split+1; + split_boxes[0] = left_boxes[best_split]; + split_boxes[1] = right_boxes[best_split]; + return; + } + + const T axis_min = axes_minmax.vals[max_axis][0]; + const T axis_length = max_axis_length; + Box span_boxes[NSPANS]; + for (INT_TYPE i = 0; i < NSPANS; ++i) { + span_boxes[i].initBounds(); + } + INT_TYPE span_counts[NSPANS]; + for (INT_TYPE i = 0; i < NSPANS; ++i) { + span_counts[i] = 0; + } + + const T axis_min_x2 = ut_BoxCentre::scale*axis_min; + // NOTE: Factor of 0.5 is factored out of the average when using the average value to determine the span that a box lies in. + const T axis_index_scale = (T(1.0/ut_BoxCentre::scale)*NSPANS)/axis_length; + constexpr INT_TYPE BOX_SPANS_PARALLEL_THRESHOLD = 2048; + INT_TYPE ntasks = 1; + if (nboxes >= BOX_SPANS_PARALLEL_THRESHOLD) { + INT_TYPE nprocessors = UT_Thread::getNumProcessors(); + ntasks = (nprocessors > 1) ? SYSmin(4*nprocessors, nboxes/(BOX_SPANS_PARALLEL_THRESHOLD/2)) : 1; + } + if (ntasks == 1) { + for (INT_TYPE indexi = 0; indexi < nboxes; ++indexi) { + const auto& box = boxes[indices[indexi]]; + const T sum = utBoxCenter(box, axis); + const uint span_index = SYSclamp(int((sum-axis_min_x2)*axis_index_scale), int(0), int(NSPANS-1)); + ++span_counts[span_index]; + Box& span_box = span_boxes[span_index]; + span_box.combine(box); + } + } + else { + UT_SmallArray> parallel_boxes; + UT_SmallArray parallel_counts; + igl::parallel_for( + nboxes, + [¶llel_boxes,¶llel_counts](int n) + { + parallel_boxes.setSize( NSPANS*n); + parallel_counts.setSize(NSPANS*n); + for(int t = 0;t& span_box = parallel_boxes[t*NSPANS+span_index]; + span_box.combine(box); + }, + [¶llel_boxes,¶llel_counts,&span_boxes,&span_counts](int t) + { + for(int i = 0;i left_boxes[NSPLITS]; + // Spans 1 to NSPANS-1 + Box right_boxes[NSPLITS]; + + // Accumulate boxes + Box box_accumulator = span_boxes[0]; + left_boxes[0] = box_accumulator; + for (INT_TYPE i = 1; i < NSPLITS; ++i) { + box_accumulator.combine(span_boxes[i]); + left_boxes[i] = box_accumulator; + } + box_accumulator = span_boxes[NSPANS-1]; + right_boxes[NSPLITS-1] = box_accumulator; + for (INT_TYPE i = NSPLITS-1; i > 0; --i) { + box_accumulator.combine(span_boxes[i]); + right_boxes[i-1] = box_accumulator; + } + + INT_TYPE left_counts[NSPLITS]; + + // Accumulate counts + INT_TYPE count_accumulator = span_counts[0]; + left_counts[0] = count_accumulator; + for (INT_TYPE spliti = 1; spliti < NSPLITS; ++spliti) { + count_accumulator += span_counts[spliti]; + left_counts[spliti] = count_accumulator; + } + + // Check which split is optimal, making sure that at least 1/MIN_FRACTION of all boxes are on each side. + const INT_TYPE min_count = nboxes/MIN_FRACTION; + UT_ASSERT_MSG_P(min_count > 0, "MID_LIMIT above should have been large enough that nboxes would be > MIN_FRACTION"); + const INT_TYPE max_count = ((MIN_FRACTION-1)*uint64(nboxes))/MIN_FRACTION; + UT_ASSERT_MSG_P(max_count < nboxes, "I'm not sure how this could happen mathematically, but it needs to be checked."); + T smallest_heuristic = std::numeric_limits::infinity(); + INT_TYPE split_index = -1; + for (INT_TYPE spliti = 0; spliti < NSPLITS; ++spliti) { + const INT_TYPE left_count = left_counts[spliti]; + if (left_count < min_count || left_count > max_count) { + continue; + } + const INT_TYPE right_count = nboxes-left_count; + const T heuristic = + left_count*unweightedHeuristic(left_boxes[spliti]) + + right_count*unweightedHeuristic(right_boxes[spliti]); + if (heuristic < smallest_heuristic) { + smallest_heuristic = heuristic; + split_index = spliti; + } + } + + SRC_INT_TYPE*const indices_end = indices+nboxes; + + if (split_index == -1) { + // No split was anywhere close to balanced, so we fall back to searching for one. + + // First, find the span containing the "balance" point, namely where left_counts goes from + // being less than min_count to more than max_count. + // If that's span 0, use max_count as the ordered index to select, + // if it's span NSPANS-1, use min_count as the ordered index to select, + // else use nboxes/2 as the ordered index to select. + //T min_pivotx2 = -std::numeric_limits::infinity(); + //T max_pivotx2 = std::numeric_limits::infinity(); + SRC_INT_TYPE* nth_index; + if (left_counts[0] > max_count) { + // Search for max_count ordered index + nth_index = indices+max_count; + //max_pivotx2 = max_axis_min_x2 + max_axis_length/(NSPANS/ut_BoxCentre::scale); + } + else if (left_counts[NSPLITS-1] < min_count) { + // Search for min_count ordered index + nth_index = indices+min_count; + //min_pivotx2 = max_axis_min_x2 + max_axis_length - max_axis_length/(NSPANS/ut_BoxCentre::scale); + } + else { + // Search for nboxes/2 ordered index + nth_index = indices+nboxes/2; + //for (INT_TYPE spliti = 1; spliti < NSPLITS; ++spliti) { + // // The second condition should be redundant, but is just in case. + // if (left_counts[spliti] > max_count || spliti == NSPLITS-1) { + // min_pivotx2 = max_axis_min_x2 + spliti*max_axis_length/(NSPANS/ut_BoxCentre::scale); + // max_pivotx2 = max_axis_min_x2 + (spliti+1)*max_axis_length/(NSPANS/ut_BoxCentre::scale); + // break; + // } + //} + } + nthElement(boxes,indices,indices+nboxes,max_axis,nth_index);//,min_pivotx2,max_pivotx2); + + split_indices = nth_index; + Box left_box(boxes[indices[0]]); + for (SRC_INT_TYPE* left_indices = indices+1; left_indices < nth_index; ++left_indices) { + left_box.combine(boxes[*left_indices]); + } + Box right_box(boxes[nth_index[0]]); + for (SRC_INT_TYPE* right_indices = nth_index+1; right_indices < indices_end; ++right_indices) { + right_box.combine(boxes[*right_indices]); + } + split_boxes[0] = left_box; + split_boxes[1] = right_box; + } + else { + const T pivotx2 = axis_min_x2 + (split_index+1)*axis_length/(NSPANS/ut_BoxCentre::scale); + SRC_INT_TYPE* ppivot_start; + SRC_INT_TYPE* ppivot_end; + partitionByCentre(boxes,indices,indices+nboxes,max_axis,pivotx2,ppivot_start,ppivot_end); + + split_indices = indices + left_counts[split_index]; + + // Ignoring roundoff error, we would have + // split_indices >= ppivot_start && split_indices <= ppivot_end, + // but it may not always be in practice. + if (split_indices >= ppivot_start && split_indices <= ppivot_end) { + split_boxes[0] = left_boxes[split_index]; + split_boxes[1] = right_boxes[split_index]; + return; + } + + // Roundoff error changed the split, so we need to recompute the boxes. + if (split_indices < ppivot_start) { + split_indices = ppivot_start; + } + else {//(split_indices > ppivot_end) + split_indices = ppivot_end; + } + + // Emergency checks, just in case + if (split_indices == indices) { + ++split_indices; + } + else if (split_indices == indices_end) { + --split_indices; + } + + Box left_box(boxes[indices[0]]); + for (SRC_INT_TYPE* left_indices = indices+1; left_indices < split_indices; ++left_indices) { + left_box.combine(boxes[*left_indices]); + } + Box right_box(boxes[split_indices[0]]); + for (SRC_INT_TYPE* right_indices = split_indices+1; right_indices < indices_end; ++right_indices) { + right_box.combine(boxes[*right_indices]); + } + split_boxes[0] = left_box; + split_boxes[1] = right_box; + } +} + +template +template +inline void BVH::adjustParallelChildNodes(INT_TYPE nparallel, UT_Array& nodes, Node& node, UT_Array* parallel_nodes, SRC_INT_TYPE* sub_indices) noexcept +{ + // Alec: No need to parallelize this... + //UTparallelFor(UT_BlockedRange(0,nparallel), [&node,&nodes,¶llel_nodes,&sub_indices](const UT_BlockedRange& r) { + INT_TYPE counted_parallel = 0; + INT_TYPE childi = 0; + for(int taski = 0;taski < nparallel; taski++) + { + //for (INT_TYPE taski = r.begin(), end = r.end(); taski < end; ++taski) { + // First, find which child this is + INT_TYPE sub_nboxes; + for (; childi < N; ++childi) { + sub_nboxes = sub_indices[childi+1]-sub_indices[childi]; + if (sub_nboxes >= PARALLEL_THRESHOLD) { + if (counted_parallel == taski) { + break; + } + ++counted_parallel; + } + } + UT_ASSERT_P(counted_parallel == taski); + + const UT_Array& local_nodes = parallel_nodes[counted_parallel]; + INT_TYPE n = local_nodes.size(); + INT_TYPE local_nodes_start = Node::getInternalNum(node.child[childi])+1; + ++counted_parallel; + ++childi; + + for (INT_TYPE j = 0; j < n; ++j) { + Node local_node = local_nodes[j]; + for (INT_TYPE childj = 0; childj < N; ++childj) { + INT_TYPE local_child = local_node.child[childj]; + if (Node::isInternal(local_child) && local_child != Node::EMPTY) { + local_child += local_nodes_start; + local_node.child[childj] = local_child; + } + } + nodes[local_nodes_start+j] = local_node; + } + } +} + +template +template +void BVH::nthElement(const BOX_TYPE* boxes, SRC_INT_TYPE* indices, const SRC_INT_TYPE* indices_end, const uint axis, SRC_INT_TYPE*const nth) noexcept {//, const T min_pivotx2, const T max_pivotx2) noexcept { + while (true) { + // Choose median of first, middle, and last as the pivot + T pivots[3] = { + utBoxCenter(boxes[indices[0]], axis), + utBoxCenter(boxes[indices[(indices_end-indices)/2]], axis), + utBoxCenter(boxes[*(indices_end-1)], axis) + }; + if (pivots[0] < pivots[1]) { + const T temp = pivots[0]; + pivots[0] = pivots[1]; + pivots[1] = temp; + } + if (pivots[0] < pivots[2]) { + const T temp = pivots[0]; + pivots[0] = pivots[2]; + pivots[2] = temp; + } + if (pivots[1] < pivots[2]) { + const T temp = pivots[1]; + pivots[1] = pivots[2]; + pivots[2] = temp; + } + T mid_pivotx2 = pivots[1]; +#if 0 + // We limit the pivot, because we know that the true value is between min and max + if (mid_pivotx2 < min_pivotx2) { + mid_pivotx2 = min_pivotx2; + } + else if (mid_pivotx2 > max_pivotx2) { + mid_pivotx2 = max_pivotx2; + } +#endif + SRC_INT_TYPE* pivot_start; + SRC_INT_TYPE* pivot_end; + partitionByCentre(boxes,indices,indices_end,axis,mid_pivotx2,pivot_start,pivot_end); + if (nth < pivot_start) { + indices_end = pivot_start; + } + else if (nth < pivot_end) { + // nth is in the middle of the pivot range, + // which is in the right place, so we're done. + return; + } + else { + indices = pivot_end; + } + if (indices_end <= indices+1) { + return; + } + } +} + +template +template +void BVH::partitionByCentre(const BOX_TYPE* boxes, SRC_INT_TYPE*const indices, const SRC_INT_TYPE*const indices_end, const uint axis, const T pivotx2, SRC_INT_TYPE*& ppivot_start, SRC_INT_TYPE*& ppivot_end) noexcept { + // TODO: Consider parallelizing this! + + // First element >= pivot + SRC_INT_TYPE* pivot_start = indices; + // First element > pivot + SRC_INT_TYPE* pivot_end = indices; + + // Loop through forward once + for (SRC_INT_TYPE* psrc_index = indices; psrc_index != indices_end; ++psrc_index) { + const T srcsum = utBoxCenter(boxes[*psrc_index], axis); + if (srcsum < pivotx2) { + if (psrc_index != pivot_start) { + if (pivot_start == pivot_end) { + // Common case: nothing equal to the pivot + const SRC_INT_TYPE temp = *psrc_index; + *psrc_index = *pivot_start; + *pivot_start = temp; + } + else { + // Less common case: at least one thing equal to the pivot + const SRC_INT_TYPE temp = *psrc_index; + *psrc_index = *pivot_end; + *pivot_end = *pivot_start; + *pivot_start = temp; + } + } + ++pivot_start; + ++pivot_end; + } + else if (srcsum == pivotx2) { + // Add to the pivot area + if (psrc_index != pivot_end) { + const SRC_INT_TYPE temp = *psrc_index; + *psrc_index = *pivot_end; + *pivot_end = temp; + } + ++pivot_end; + } + } + ppivot_start = pivot_start; + ppivot_end = pivot_end; +} + +#if 0 +template +void BVH::debugDump() const { + printf("\nNode 0: {\n"); + UT_WorkBuffer indent; + indent.append(80, ' '); + UT_Array stack; + stack.append(0); + stack.append(0); + while (!stack.isEmpty()) { + int depth = stack.size()/2; + if (indent.length() < 4*depth) { + indent.append(4, ' '); + } + INT_TYPE cur_nodei = stack[stack.size()-2]; + INT_TYPE cur_i = stack[stack.size()-1]; + if (cur_i == N) { + printf(indent.buffer()+indent.length()-(4*(depth-1))); + printf("}\n"); + stack.removeLast(); + stack.removeLast(); + continue; + } + ++stack[stack.size()-1]; + Node& cur_node = myRoot[cur_nodei]; + INT_TYPE child_nodei = cur_node.child[cur_i]; + if (Node::isInternal(child_nodei)) { + if (child_nodei == Node::EMPTY) { + printf(indent.buffer()+indent.length()-(4*(depth-1))); + printf("}\n"); + stack.removeLast(); + stack.removeLast(); + continue; + } + INT_TYPE internal_node = Node::getInternalNum(child_nodei); + printf(indent.buffer()+indent.length()-(4*depth)); + printf("Node %u: {\n", uint(internal_node)); + stack.append(internal_node); + stack.append(0); + continue; + } + else { + printf(indent.buffer()+indent.length()-(4*depth)); + printf("Tri %u\n", uint(child_nodei)); + } + } +} +#endif + +} // UT namespace +} // End HDK_Sample namespace +}} +#endif +/* + * Copyright (c) 2018 Side Effects Software Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * COMMENTS: + * Functions and structures for computing solid angles. + */ + +#pragma once + +#ifndef __HDK_UT_SolidAngle_h__ +#define __HDK_UT_SolidAngle_h__ + + + + + +#include + +namespace igl { namespace FastWindingNumber { +namespace HDK_Sample { + +template +using UT_Vector2T = UT_FixedVector; +template +using UT_Vector3T = UT_FixedVector; + +template +SYS_FORCE_INLINE T cross(const UT_Vector2T &v1, const UT_Vector2T &v2) +{ + return v1[0]*v2[1] - v1[1]*v2[0]; +} + +template +SYS_FORCE_INLINE +UT_Vector3T cross(const UT_Vector3T &v1, const UT_Vector3T &v2) +{ + UT_Vector3T result; + // compute the cross product: + result[0] = v1[1]*v2[2] - v1[2]*v2[1]; + result[1] = v1[2]*v2[0] - v1[0]*v2[2]; + result[2] = v1[0]*v2[1] - v1[1]*v2[0]; + return result; +} + +/// Returns the signed solid angle subtended by triangle abc +/// from query point. +/// +/// WARNING: This uses the right-handed normal convention, whereas most of +/// Houdini uses the left-handed normal convention, so either +/// negate the output, or swap b and c if you want it to be +/// positive inside and negative outside. +template +inline T UTsignedSolidAngleTri( + const UT_Vector3T &a, + const UT_Vector3T &b, + const UT_Vector3T &c, + const UT_Vector3T &query) +{ + // Make a, b, and c relative to query + UT_Vector3T qa = a-query; + UT_Vector3T qb = b-query; + UT_Vector3T qc = c-query; + + const T alength = qa.length(); + const T blength = qb.length(); + const T clength = qc.length(); + + // If any triangle vertices are coincident with query, + // query is on the surface, which we treat as no solid angle. + if (alength == 0 || blength == 0 || clength == 0) + return T(0); + + // Normalize the vectors + qa /= alength; + qb /= blength; + qc /= clength; + + // The formula on Wikipedia has roughly dot(qa,cross(qb,qc)), + // but that's unstable when qa, qb, and qc are very close, + // (e.g. if the input triangle was very far away). + // This should be equivalent, but more stable. + const T numerator = dot(qa, cross(qb-qa, qc-qa)); + + // If numerator is 0, regardless of denominator, query is on the + // surface, which we treat as no solid angle. + if (numerator == 0) + return T(0); + + const T denominator = T(1) + dot(qa,qb) + dot(qa,qc) + dot(qb,qc); + + return T(2)*SYSatan2(numerator, denominator); +} + +template +inline T UTsignedSolidAngleQuad( + const UT_Vector3T &a, + const UT_Vector3T &b, + const UT_Vector3T &c, + const UT_Vector3T &d, + const UT_Vector3T &query) +{ + // Make a, b, c, and d relative to query + UT_Vector3T v[4] = { + a-query, + b-query, + c-query, + d-query + }; + + const T lengths[4] = { + v[0].length(), + v[1].length(), + v[2].length(), + v[3].length() + }; + + // If any quad vertices are coincident with query, + // query is on the surface, which we treat as no solid angle. + // We could add the contribution from the non-planar part, + // but in the context of a mesh, we'd still miss some, like + // we do in the triangle case. + if (lengths[0] == T(0) || lengths[1] == T(0) || lengths[2] == T(0) || lengths[3] == T(0)) + return T(0); + + // Normalize the vectors + v[0] /= lengths[0]; + v[1] /= lengths[1]; + v[2] /= lengths[2]; + v[3] /= lengths[3]; + + // Compute (unnormalized, but consistently-scaled) barycentric coordinates + // for the query point inside the tetrahedron of points. + // If 0 or 4 of the coordinates are positive, (or slightly negative), the + // query is (approximately) inside, so the choice of triangulation matters. + // Otherwise, the triangulation doesn't matter. + + const UT_Vector3T diag02 = v[2]-v[0]; + const UT_Vector3T diag13 = v[3]-v[1]; + const UT_Vector3T v01 = v[1]-v[0]; + const UT_Vector3T v23 = v[3]-v[2]; + + T bary[4]; + bary[0] = dot(v[3],cross(v23,diag13)); + bary[1] = -dot(v[2],cross(v23,diag02)); + bary[2] = -dot(v[1],cross(v01,diag13)); + bary[3] = dot(v[0],cross(v01,diag02)); + + const T dot01 = dot(v[0],v[1]); + const T dot12 = dot(v[1],v[2]); + const T dot23 = dot(v[2],v[3]); + const T dot30 = dot(v[3],v[0]); + + T omega = T(0); + + // Equation of a bilinear patch in barycentric coordinates of its + // tetrahedron is x0*x2 = x1*x3. Less is one side; greater is other. + if (bary[0]*bary[2] < bary[1]*bary[3]) + { + // Split 0-2: triangles 0,1,2 and 0,2,3 + const T numerator012 = bary[3]; + const T numerator023 = bary[1]; + const T dot02 = dot(v[0],v[2]); + + // If numerator is 0, regardless of denominator, query is on the + // surface, which we treat as no solid angle. + if (numerator012 != T(0)) + { + const T denominator012 = T(1) + dot01 + dot12 + dot02; + omega = SYSatan2(numerator012, denominator012); + } + if (numerator023 != T(0)) + { + const T denominator023 = T(1) + dot02 + dot23 + dot30; + omega += SYSatan2(numerator023, denominator023); + } + } + else + { + // Split 1-3: triangles 0,1,3 and 1,2,3 + const T numerator013 = -bary[2]; + const T numerator123 = -bary[0]; + const T dot13 = dot(v[1],v[3]); + + // If numerator is 0, regardless of denominator, query is on the + // surface, which we treat as no solid angle. + if (numerator013 != T(0)) + { + const T denominator013 = T(1) + dot01 + dot13 + dot30; + omega = SYSatan2(numerator013, denominator013); + } + if (numerator123 != T(0)) + { + const T denominator123 = T(1) + dot12 + dot23 + dot13; + omega += SYSatan2(numerator123, denominator123); + } + } + return T(2)*omega; +} + +/// Class for quickly approximating signed solid angle of a large mesh +/// from many query points. This is useful for computing the +/// generalized winding number at many points. +/// +/// NOTE: This is currently only instantiated for . +template +class UT_SolidAngle +{ +public: + /// This is outlined so that we don't need to include UT_BVHImpl.h + inline UT_SolidAngle(); + /// This is outlined so that we don't need to include UT_BVHImpl.h + inline ~UT_SolidAngle(); + + /// NOTE: This does not take ownership over triangle_points or positions, + /// but does keep pointers to them, so the caller must keep them in + /// scope for the lifetime of this structure. + UT_SolidAngle( + const int ntriangles, + const int *const triangle_points, + const int npoints, + const UT_Vector3T *const positions, + const int order = 2) + : UT_SolidAngle() + { init(ntriangles, triangle_points, npoints, positions, order); } + + /// Initialize the tree and data. + /// NOTE: It is safe to call init on a UT_SolidAngle that has had init + /// called on it before, to re-initialize it. + inline void init( + const int ntriangles, + const int *const triangle_points, + const int npoints, + const UT_Vector3T *const positions, + const int order = 2); + + /// Frees myTree and myData, and clears the rest. + inline void clear(); + + /// Returns true if this is clear + bool isClear() const + { return myNTriangles == 0; } + + /// Returns an approximation of the signed solid angle of the mesh from the specified query_point + /// accuracy_scale is the value of (maxP/q) beyond which the approximation of the box will be used. + inline T computeSolidAngle(const UT_Vector3T &query_point, const T accuracy_scale = T(2.0)) const; + +private: + struct BoxData; + + static constexpr uint BVH_N = 4; + UT_BVH myTree; + int myNBoxes; + int myOrder; + std::unique_ptr myData; + int myNTriangles; + const int *myTrianglePoints; + int myNPoints; + const UT_Vector3T *myPositions; +}; + +template +inline T UTsignedAngleSegment( + const UT_Vector2T &a, + const UT_Vector2T &b, + const UT_Vector2T &query) +{ + // Make a and b relative to query + UT_Vector2T qa = a-query; + UT_Vector2T qb = b-query; + + // If any segment vertices are coincident with query, + // query is on the segment, which we treat as no angle. + if (qa.isZero() || qb.isZero()) + return T(0); + + // numerator = |qa||qb|sin(theta) + const T numerator = cross(qa, qb); + + // If numerator is 0, regardless of denominator, query is on the + // surface, which we treat as no solid angle. + if (numerator == 0) + return T(0); + + // denominator = |qa||qb|cos(theta) + const T denominator = dot(qa,qb); + + // numerator/denominator = tan(theta) + return SYSatan2(numerator, denominator); +} + +/// Class for quickly approximating signed subtended angle of a large curve +/// from many query points. This is useful for computing the +/// generalized winding number at many points. +/// +/// NOTE: This is currently only instantiated for . +template +class UT_SubtendedAngle +{ +public: + /// This is outlined so that we don't need to include UT_BVHImpl.h + inline UT_SubtendedAngle(); + /// This is outlined so that we don't need to include UT_BVHImpl.h + inline ~UT_SubtendedAngle(); + + /// NOTE: This does not take ownership over segment_points or positions, + /// but does keep pointers to them, so the caller must keep them in + /// scope for the lifetime of this structure. + UT_SubtendedAngle( + const int nsegments, + const int *const segment_points, + const int npoints, + const UT_Vector2T *const positions, + const int order = 2) + : UT_SubtendedAngle() + { init(nsegments, segment_points, npoints, positions, order); } + + /// Initialize the tree and data. + /// NOTE: It is safe to call init on a UT_SolidAngle that has had init + /// called on it before, to re-initialize it. + inline void init( + const int nsegments, + const int *const segment_points, + const int npoints, + const UT_Vector2T *const positions, + const int order = 2); + + /// Frees myTree and myData, and clears the rest. + inline void clear(); + + /// Returns true if this is clear + bool isClear() const + { return myNSegments == 0; } + + /// Returns an approximation of the signed solid angle of the mesh from the specified query_point + /// accuracy_scale is the value of (maxP/q) beyond which the approximation of the box will be used. + inline T computeAngle(const UT_Vector2T &query_point, const T accuracy_scale = T(2.0)) const; + +private: + struct BoxData; + + static constexpr uint BVH_N = 4; + UT_BVH myTree; + int myNBoxes; + int myOrder; + std::unique_ptr myData; + int myNSegments; + const int *mySegmentPoints; + int myNPoints; + const UT_Vector2T *myPositions; +}; + +} // End HDK_Sample namespace +}} +#endif +/* + * Copyright (c) 2018 Side Effects Software Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * COMMENTS: + * A wrapper function for the "free" function, used by UT_(Small)Array + */ + + + +#include + +namespace igl { namespace FastWindingNumber { + +// This needs to be here or else the warning suppression doesn't work because +// the templated calling code won't otherwise be compiled until after we've +// already popped the warning.state. So we just always disable this at file +// scope here. +#if defined(__GNUC__) && !defined(__clang__) + _Pragma("GCC diagnostic push") + _Pragma("GCC diagnostic ignored \"-Wfree-nonheap-object\"") +#endif +inline void ut_ArrayImplFree(void *p) +{ + free(p); +} +#if defined(__GNUC__) && !defined(__clang__) + _Pragma("GCC diagnostic pop") +#endif +} } +/* + * Copyright (c) 2018 Side Effects Software Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + * COMMENTS: + * Functions and structures for computing solid angles. + */ + + + + + + + + +#include +#include +#include + +#define SOLID_ANGLE_TIME_PRECOMPUTE 0 + +#if SOLID_ANGLE_TIME_PRECOMPUTE +#include +#endif + +#define SOLID_ANGLE_DEBUG 0 +#if SOLID_ANGLE_DEBUG +#include +#endif + +#define TAYLOR_SERIES_ORDER 2 + +namespace igl { namespace FastWindingNumber { + +namespace HDK_Sample { + +template +struct UT_SolidAngle::BoxData +{ + void clear() + { + // Set everything to zero + memset(this,0,sizeof(*this)); + } + + using Type = typename std::conditional::value, v4uf, UT_FixedVector>::type; + using SType = typename std::conditional::value, v4uf, UT_FixedVector>::type; + + /// An upper bound on the squared distance from myAverageP to the farthest point in the box. + SType myMaxPDist2; + + /// Centre of mass of the mesh surface in this box + UT_FixedVector myAverageP; + + /// Unnormalized, area-weighted normal of the mesh in this box + UT_FixedVector myN; + +#if TAYLOR_SERIES_ORDER >= 1 + /// Values for Omega_1 + /// @{ + UT_FixedVector myNijDiag; // Nxx, Nyy, Nzz + Type myNxy_Nyx; // Nxy+Nyx + Type myNyz_Nzy; // Nyz+Nzy + Type myNzx_Nxz; // Nzx+Nxz + /// @} +#endif + +#if TAYLOR_SERIES_ORDER >= 2 + /// Values for Omega_2 + /// @{ + UT_FixedVector myNijkDiag; // Nxxx, Nyyy, Nzzz + Type mySumPermuteNxyz; // (Nxyz+Nxzy+Nyzx+Nyxz+Nzxy+Nzyx) = 2*(Nxyz+Nyzx+Nzxy) + Type my2Nxxy_Nyxx; // Nxxy+Nxyx+Nyxx = 2Nxxy+Nyxx + Type my2Nxxz_Nzxx; // Nxxz+Nxzx+Nzxx = 2Nxxz+Nzxx + Type my2Nyyz_Nzyy; // Nyyz+Nyzy+Nzyy = 2Nyyz+Nzyy + Type my2Nyyx_Nxyy; // Nyyx+Nyxy+Nxyy = 2Nyyx+Nxyy + Type my2Nzzx_Nxzz; // Nzzx+Nzxz+Nxzz = 2Nzzx+Nxzz + Type my2Nzzy_Nyzz; // Nzzy+Nzyz+Nyzz = 2Nzzy+Nyzz + /// @} +#endif +}; + +template +inline UT_SolidAngle::UT_SolidAngle() + : myTree() + , myNBoxes(0) + , myOrder(2) + , myData(nullptr) + , myNTriangles(0) + , myTrianglePoints(nullptr) + , myNPoints(0) + , myPositions(nullptr) +{} + +template +inline UT_SolidAngle::~UT_SolidAngle() +{ + // Default destruction works, but this needs to be outlined + // to avoid having to include UT_BVHImpl.h in the header, + // (for the UT_UniquePtr destructor.) +} + +template +inline void UT_SolidAngle::init( + const int ntriangles, + const int *const triangle_points, + const int npoints, + const UT_Vector3T *const positions, + const int order) +{ +#if SOLID_ANGLE_DEBUG + UTdebugFormat(""); + UTdebugFormat(""); + UTdebugFormat("Building BVH for {} ntriangles on {} points:", ntriangles, npoints); +#endif + myOrder = order; + myNTriangles = ntriangles; + myTrianglePoints = triangle_points; + myNPoints = npoints; + myPositions = positions; + +#if SOLID_ANGLE_TIME_PRECOMPUTE + UT_StopWatch timer; + timer.start(); +#endif + UT_SmallArray> triangle_boxes; + triangle_boxes.setSizeNoInit(ntriangles); + if (ntriangles < 16*1024) + { + const int *cur_triangle_points = triangle_points; + for (int i = 0; i < ntriangles; ++i, cur_triangle_points += 3) + { + UT::Box &box = triangle_boxes[i]; + box.initBounds(positions[cur_triangle_points[0]]); + box.enlargeBounds(positions[cur_triangle_points[1]]); + box.enlargeBounds(positions[cur_triangle_points[2]]); + } + } + else + { + igl::parallel_for(ntriangles, + [triangle_points,&triangle_boxes,positions](int i) + { + const int *cur_triangle_points = triangle_points + i*3; + UT::Box &box = triangle_boxes[i]; + box.initBounds(positions[cur_triangle_points[0]]); + box.enlargeBounds(positions[cur_triangle_points[1]]); + box.enlargeBounds(positions[cur_triangle_points[2]]); + }); + } +#if SOLID_ANGLE_TIME_PRECOMPUTE + double time = timer.stop(); + UTdebugFormat("{} s to create bounding boxes.", time); + timer.start(); +#endif + myTree.template init(triangle_boxes.array(), ntriangles); +#if SOLID_ANGLE_TIME_PRECOMPUTE + time = timer.stop(); + UTdebugFormat("{} s to initialize UT_BVH structure. {} nodes", time, myTree.getNumNodes()); +#endif + + //myTree.debugDump(); + + const int nnodes = myTree.getNumNodes(); + + myNBoxes = nnodes; + BoxData *box_data = new BoxData[nnodes]; + myData.reset(box_data); + + // Some data are only needed during initialization. + struct LocalData + { + // Bounding box + UT::Box myBox; + + // P and N are needed from each child for computing Nij. + UT_Vector3T myAverageP; + UT_Vector3T myAreaP; + UT_Vector3T myN; + + // Unsigned area is needed for computing the average position. + T myArea; + +#if TAYLOR_SERIES_ORDER >= 1 + // These are needed for computing Nijk. + UT_Vector3T myNijDiag; + T myNxy; T myNyx; + T myNyz; T myNzy; + T myNzx; T myNxz; +#endif + +#if TAYLOR_SERIES_ORDER >= 2 + UT_Vector3T myNijkDiag; // Nxxx, Nyyy, Nzzz + T mySumPermuteNxyz; // (Nxyz+Nxzy+Nyzx+Nyxz+Nzxy+Nzyx) = 2*(Nxyz+Nyzx+Nzxy) + T my2Nxxy_Nyxx; // Nxxy+Nxyx+Nyxx = 2Nxxy+Nyxx + T my2Nxxz_Nzxx; // Nxxz+Nxzx+Nzxx = 2Nxxz+Nzxx + T my2Nyyz_Nzyy; // Nyyz+Nyzy+Nzyy = 2Nyyz+Nzyy + T my2Nyyx_Nxyy; // Nyyx+Nyxy+Nxyy = 2Nyyx+Nxyy + T my2Nzzx_Nxzz; // Nzzx+Nzxz+Nxzz = 2Nzzx+Nxzz + T my2Nzzy_Nyzz; // Nzzy+Nzyz+Nyzz = 2Nzzy+Nyzz +#endif + }; + + struct PrecomputeFunctors + { + BoxData *const myBoxData; + const UT::Box *const myTriangleBoxes; + const int *const myTrianglePoints; + const UT_Vector3T *const myPositions; + const int myOrder; + + PrecomputeFunctors( + BoxData *box_data, + const UT::Box *triangle_boxes, + const int *triangle_points, + const UT_Vector3T *positions, + const int order) + : myBoxData(box_data) + , myTriangleBoxes(triangle_boxes) + , myTrianglePoints(triangle_points) + , myPositions(positions) + , myOrder(order) + {} + constexpr SYS_FORCE_INLINE bool pre(const int nodei, LocalData *data_for_parent) const + { + return true; + } + void item(const int itemi, const int parent_nodei, LocalData &data_for_parent) const + { + const UT_Vector3T *const positions = myPositions; + const int *const cur_triangle_points = myTrianglePoints + 3*itemi; + const UT_Vector3T a = positions[cur_triangle_points[0]]; + const UT_Vector3T b = positions[cur_triangle_points[1]]; + const UT_Vector3T c = positions[cur_triangle_points[2]]; + const UT_Vector3T ab = b-a; + const UT_Vector3T ac = c-a; + + const UT::Box &triangle_box = myTriangleBoxes[itemi]; + data_for_parent.myBox.initBounds(triangle_box.getMin(), triangle_box.getMax()); + + // Area-weighted normal (unnormalized) + const UT_Vector3T N = T(0.5)*cross(ab,ac); + const T area2 = N.length2(); + const T area = SYSsqrt(area2); + const UT_Vector3T P = (a+b+c)/3; + data_for_parent.myAverageP = P; + data_for_parent.myAreaP = P*area; + data_for_parent.myN = N; +#if SOLID_ANGLE_DEBUG + UTdebugFormat(""); + UTdebugFormat("Triangle {}: P = {}; N = {}; area = {}", itemi, P, N, area); + UTdebugFormat(" box = {}", data_for_parent.myBox); +#endif + + data_for_parent.myArea = area; +#if TAYLOR_SERIES_ORDER >= 1 + const int order = myOrder; + if (order < 1) + return; + + // NOTE: Due to P being at the centroid, triangles have Nij = 0 + // contributions to Nij. + data_for_parent.myNijDiag = T(0); + data_for_parent.myNxy = 0; data_for_parent.myNyx = 0; + data_for_parent.myNyz = 0; data_for_parent.myNzy = 0; + data_for_parent.myNzx = 0; data_for_parent.myNxz = 0; +#endif + +#if TAYLOR_SERIES_ORDER >= 2 + if (order < 2) + return; + + // If it's zero-length, the results are zero, so we can skip. + if (area == 0) + { + data_for_parent.myNijkDiag = T(0); + data_for_parent.mySumPermuteNxyz = 0; + data_for_parent.my2Nxxy_Nyxx = 0; + data_for_parent.my2Nxxz_Nzxx = 0; + data_for_parent.my2Nyyz_Nzyy = 0; + data_for_parent.my2Nyyx_Nxyy = 0; + data_for_parent.my2Nzzx_Nxzz = 0; + data_for_parent.my2Nzzy_Nyzz = 0; + return; + } + + // We need to use the NORMALIZED normal to multiply the integrals by. + UT_Vector3T n = N/area; + + // Figure out the order of a, b, and c in x, y, and z + // for use in computing the integrals for Nijk. + UT_Vector3T values[3] = {a, b, c}; + + int order_x[3] = {0,1,2}; + if (a[0] > b[0]) + std::swap(order_x[0],order_x[1]); + if (values[order_x[0]][0] > c[0]) + std::swap(order_x[0],order_x[2]); + if (values[order_x[1]][0] > values[order_x[2]][0]) + std::swap(order_x[1],order_x[2]); + T dx = values[order_x[2]][0] - values[order_x[0]][0]; + + int order_y[3] = {0,1,2}; + if (a[1] > b[1]) + std::swap(order_y[0],order_y[1]); + if (values[order_y[0]][1] > c[1]) + std::swap(order_y[0],order_y[2]); + if (values[order_y[1]][1] > values[order_y[2]][1]) + std::swap(order_y[1],order_y[2]); + T dy = values[order_y[2]][1] - values[order_y[0]][1]; + + int order_z[3] = {0,1,2}; + if (a[2] > b[2]) + std::swap(order_z[0],order_z[1]); + if (values[order_z[0]][2] > c[2]) + std::swap(order_z[0],order_z[2]); + if (values[order_z[1]][2] > values[order_z[2]][2]) + std::swap(order_z[1],order_z[2]); + T dz = values[order_z[2]][2] - values[order_z[0]][2]; + + auto &&compute_integrals = []( + const UT_Vector3T &a, + const UT_Vector3T &b, + const UT_Vector3T &c, + const UT_Vector3T &P, + T *integral_ii, + T *integral_ij, + T *integral_ik, + const int i) + { +#if SOLID_ANGLE_DEBUG + UTdebugFormat(" Splitting on {}; a = {}; b = {}; c = {}", char('x'+i), a, b, c); +#endif + // NOTE: a, b, and c must be in order of the i axis. + // We're splitting the triangle at the middle i coordinate. + const UT_Vector3T oab = b - a; + const UT_Vector3T oac = c - a; + const UT_Vector3T ocb = b - c; + UT_ASSERT_MSG_P(oac[i] > 0, "This should have been checked by the caller."); + const T t = oab[i]/oac[i]; + UT_ASSERT_MSG_P(t >= 0 && t <= 1, "Either sorting must have gone wrong, or there are input NaNs."); + + const int j = (i==2) ? 0 : (i+1); + const int k = (j==2) ? 0 : (j+1); + const T jdiff = t*oac[j] - oab[j]; + const T kdiff = t*oac[k] - oab[k]; + UT_Vector3T cross_a; + cross_a[0] = (jdiff*oab[k] - kdiff*oab[j]); + cross_a[1] = kdiff*oab[i]; + cross_a[2] = jdiff*oab[i]; + UT_Vector3T cross_c; + cross_c[0] = (jdiff*ocb[k] - kdiff*ocb[j]); + cross_c[1] = kdiff*ocb[i]; + cross_c[2] = jdiff*ocb[i]; + const T area_scale_a = cross_a.length(); + const T area_scale_c = cross_c.length(); + const T Pai = a[i] - P[i]; + const T Pci = c[i] - P[i]; + + // Integral over the area of the triangle of (pi^2)dA, + // by splitting the triangle into two at b, the a side + // and the c side. + const T int_ii_a = area_scale_a*(T(0.5)*Pai*Pai + T(2.0/3.0)*Pai*oab[i] + T(0.25)*oab[i]*oab[i]); + const T int_ii_c = area_scale_c*(T(0.5)*Pci*Pci + T(2.0/3.0)*Pci*ocb[i] + T(0.25)*ocb[i]*ocb[i]); + *integral_ii = int_ii_a + int_ii_c; +#if SOLID_ANGLE_DEBUG + UTdebugFormat(" integral_{}{}_a = {}; integral_{}{}_c = {}", char('x'+i), char('x'+i), int_ii_a, char('x'+i), char('x'+i), int_ii_c); +#endif + + int jk = j; + T *integral = integral_ij; + T diff = jdiff; + while (true) // This only does 2 iterations, one for j and one for k + { + if (integral) + { + T obmidj = b[jk] + T(0.5)*diff; + T oabmidj = obmidj - a[jk]; + T ocbmidj = obmidj - c[jk]; + T Paj = a[jk] - P[jk]; + T Pcj = c[jk] - P[jk]; + // Integral over the area of the triangle of (pi*pj)dA + const T int_ij_a = area_scale_a*(T(0.5)*Pai*Paj + T(1.0/3.0)*Pai*oabmidj + T(1.0/3.0)*Paj*oab[i] + T(0.25)*oab[i]*oabmidj); + const T int_ij_c = area_scale_c*(T(0.5)*Pci*Pcj + T(1.0/3.0)*Pci*ocbmidj + T(1.0/3.0)*Pcj*ocb[i] + T(0.25)*ocb[i]*ocbmidj); + *integral = int_ij_a + int_ij_c; +#if SOLID_ANGLE_DEBUG + UTdebugFormat(" integral_{}{}_a = {}; integral_{}{}_c = {}", char('x'+i), char('x'+jk), int_ij_a, char('x'+i), char('x'+jk), int_ij_c); +#endif + } + if (jk == k) + break; + jk = k; + integral = integral_ik; + diff = kdiff; + } + }; + + T integral_xx = 0; + T integral_xy = 0; + T integral_yy = 0; + T integral_yz = 0; + T integral_zz = 0; + T integral_zx = 0; + // Note that if the span of any axis is zero, the integral must be zero, + // since there's a factor of (p_i-P_i), i.e. value minus average, + // and every value must be equal to the average, giving zero. + if (dx > 0) + { + compute_integrals( + values[order_x[0]], values[order_x[1]], values[order_x[2]], P, + &integral_xx, ((dx >= dy && dy > 0) ? &integral_xy : nullptr), ((dx >= dz && dz > 0) ? &integral_zx : nullptr), 0); + } + if (dy > 0) + { + compute_integrals( + values[order_y[0]], values[order_y[1]], values[order_y[2]], P, + &integral_yy, ((dy >= dz && dz > 0) ? &integral_yz : nullptr), ((dx < dy && dx > 0) ? &integral_xy : nullptr), 1); + } + if (dz > 0) + { + compute_integrals( + values[order_z[0]], values[order_z[1]], values[order_z[2]], P, + &integral_zz, ((dx < dz && dx > 0) ? &integral_zx : nullptr), ((dy < dz && dy > 0) ? &integral_yz : nullptr), 2); + } + + UT_Vector3T Niii; + Niii[0] = integral_xx; + Niii[1] = integral_yy; + Niii[2] = integral_zz; + Niii *= n; + data_for_parent.myNijkDiag = Niii; + data_for_parent.mySumPermuteNxyz = 2*(n[0]*integral_yz + n[1]*integral_zx + n[2]*integral_xy); + T Nxxy = n[0]*integral_xy; + T Nxxz = n[0]*integral_zx; + T Nyyz = n[1]*integral_yz; + T Nyyx = n[1]*integral_xy; + T Nzzx = n[2]*integral_zx; + T Nzzy = n[2]*integral_yz; + data_for_parent.my2Nxxy_Nyxx = 2*Nxxy + n[1]*integral_xx; + data_for_parent.my2Nxxz_Nzxx = 2*Nxxz + n[2]*integral_xx; + data_for_parent.my2Nyyz_Nzyy = 2*Nyyz + n[2]*integral_yy; + data_for_parent.my2Nyyx_Nxyy = 2*Nyyx + n[0]*integral_yy; + data_for_parent.my2Nzzx_Nxzz = 2*Nzzx + n[0]*integral_zz; + data_for_parent.my2Nzzy_Nyzz = 2*Nzzy + n[1]*integral_zz; +#if SOLID_ANGLE_DEBUG + UTdebugFormat(" integral_xx = {}; yy = {}; zz = {}", integral_xx, integral_yy, integral_zz); + UTdebugFormat(" integral_xy = {}; yz = {}; zx = {}", integral_xy, integral_yz, integral_zx); +#endif +#endif + } + + void post(const int nodei, const int parent_nodei, LocalData *data_for_parent, const int nchildren, const LocalData *child_data_array) const + { + // NOTE: Although in the general case, data_for_parent may be null for the root call, + // this functor assumes that it's non-null, so the call below must pass a non-null pointer. + + BoxData ¤t_box_data = myBoxData[nodei]; + + UT_Vector3T N = child_data_array[0].myN; + ((T*)¤t_box_data.myN[0])[0] = N[0]; + ((T*)¤t_box_data.myN[1])[0] = N[1]; + ((T*)¤t_box_data.myN[2])[0] = N[2]; + UT_Vector3T areaP = child_data_array[0].myAreaP; + T area = child_data_array[0].myArea; + UT_Vector3T local_P = child_data_array[0].myAverageP; + ((T*)¤t_box_data.myAverageP[0])[0] = local_P[0]; + ((T*)¤t_box_data.myAverageP[1])[0] = local_P[1]; + ((T*)¤t_box_data.myAverageP[2])[0] = local_P[2]; + for (int i = 1; i < nchildren; ++i) + { + const UT_Vector3T local_N = child_data_array[i].myN; + N += local_N; + ((T*)¤t_box_data.myN[0])[i] = local_N[0]; + ((T*)¤t_box_data.myN[1])[i] = local_N[1]; + ((T*)¤t_box_data.myN[2])[i] = local_N[2]; + areaP += child_data_array[i].myAreaP; + area += child_data_array[i].myArea; + const UT_Vector3T local_P = child_data_array[i].myAverageP; + ((T*)¤t_box_data.myAverageP[0])[i] = local_P[0]; + ((T*)¤t_box_data.myAverageP[1])[i] = local_P[1]; + ((T*)¤t_box_data.myAverageP[2])[i] = local_P[2]; + } + for (int i = nchildren; i < BVH_N; ++i) + { + // Set to zero, just to avoid false positives for uses of uninitialized memory. + ((T*)¤t_box_data.myN[0])[i] = 0; + ((T*)¤t_box_data.myN[1])[i] = 0; + ((T*)¤t_box_data.myN[2])[i] = 0; + ((T*)¤t_box_data.myAverageP[0])[i] = 0; + ((T*)¤t_box_data.myAverageP[1])[i] = 0; + ((T*)¤t_box_data.myAverageP[2])[i] = 0; + } + data_for_parent->myN = N; + data_for_parent->myAreaP = areaP; + data_for_parent->myArea = area; + + UT::Box box(child_data_array[0].myBox); + for (int i = 1; i < nchildren; ++i) + box.enlargeBounds(child_data_array[i].myBox); + + // Normalize P + UT_Vector3T averageP; + if (area > 0) + averageP = areaP/area; + else + averageP = T(0.5)*(box.getMin() + box.getMax()); + data_for_parent->myAverageP = averageP; + + data_for_parent->myBox = box; + + for (int i = 0; i < nchildren; ++i) + { + const UT::Box &local_box(child_data_array[i].myBox); + const UT_Vector3T &local_P = child_data_array[i].myAverageP; + const UT_Vector3T maxPDiff = SYSmax(local_P-UT_Vector3T(local_box.getMin()), UT_Vector3T(local_box.getMax())-local_P); + ((T*)¤t_box_data.myMaxPDist2)[i] = maxPDiff.length2(); + } + for (int i = nchildren; i < BVH_N; ++i) + { + // This child is non-existent. If we set myMaxPDist2 to infinity, it will never + // use the approximation, and the traverseVector function can check for EMPTY. + ((T*)¤t_box_data.myMaxPDist2)[i] = std::numeric_limits::infinity(); + } + +#if TAYLOR_SERIES_ORDER >= 1 + const int order = myOrder; + if (order >= 1) + { + // We now have the current box's P, so we can adjust Nij and Nijk + data_for_parent->myNijDiag = child_data_array[0].myNijDiag; + data_for_parent->myNxy = 0; + data_for_parent->myNyx = 0; + data_for_parent->myNyz = 0; + data_for_parent->myNzy = 0; + data_for_parent->myNzx = 0; + data_for_parent->myNxz = 0; +#if TAYLOR_SERIES_ORDER >= 2 + data_for_parent->myNijkDiag = child_data_array[0].myNijkDiag; + data_for_parent->mySumPermuteNxyz = child_data_array[0].mySumPermuteNxyz; + data_for_parent->my2Nxxy_Nyxx = child_data_array[0].my2Nxxy_Nyxx; + data_for_parent->my2Nxxz_Nzxx = child_data_array[0].my2Nxxz_Nzxx; + data_for_parent->my2Nyyz_Nzyy = child_data_array[0].my2Nyyz_Nzyy; + data_for_parent->my2Nyyx_Nxyy = child_data_array[0].my2Nyyx_Nxyy; + data_for_parent->my2Nzzx_Nxzz = child_data_array[0].my2Nzzx_Nxzz; + data_for_parent->my2Nzzy_Nyzz = child_data_array[0].my2Nzzy_Nyzz; +#endif + + for (int i = 1; i < nchildren; ++i) + { + data_for_parent->myNijDiag += child_data_array[i].myNijDiag; +#if TAYLOR_SERIES_ORDER >= 2 + data_for_parent->myNijkDiag += child_data_array[i].myNijkDiag; + data_for_parent->mySumPermuteNxyz += child_data_array[i].mySumPermuteNxyz; + data_for_parent->my2Nxxy_Nyxx += child_data_array[i].my2Nxxy_Nyxx; + data_for_parent->my2Nxxz_Nzxx += child_data_array[i].my2Nxxz_Nzxx; + data_for_parent->my2Nyyz_Nzyy += child_data_array[i].my2Nyyz_Nzyy; + data_for_parent->my2Nyyx_Nxyy += child_data_array[i].my2Nyyx_Nxyy; + data_for_parent->my2Nzzx_Nxzz += child_data_array[i].my2Nzzx_Nxzz; + data_for_parent->my2Nzzy_Nyzz += child_data_array[i].my2Nzzy_Nyzz; +#endif + } + for (int j = 0; j < 3; ++j) + ((T*)¤t_box_data.myNijDiag[j])[0] = child_data_array[0].myNijDiag[j]; + ((T*)¤t_box_data.myNxy_Nyx)[0] = child_data_array[0].myNxy + child_data_array[0].myNyx; + ((T*)¤t_box_data.myNyz_Nzy)[0] = child_data_array[0].myNyz + child_data_array[0].myNzy; + ((T*)¤t_box_data.myNzx_Nxz)[0] = child_data_array[0].myNzx + child_data_array[0].myNxz; + for (int j = 0; j < 3; ++j) + ((T*)¤t_box_data.myNijkDiag[j])[0] = child_data_array[0].myNijkDiag[j]; + ((T*)¤t_box_data.mySumPermuteNxyz)[0] = child_data_array[0].mySumPermuteNxyz; + ((T*)¤t_box_data.my2Nxxy_Nyxx)[0] = child_data_array[0].my2Nxxy_Nyxx; + ((T*)¤t_box_data.my2Nxxz_Nzxx)[0] = child_data_array[0].my2Nxxz_Nzxx; + ((T*)¤t_box_data.my2Nyyz_Nzyy)[0] = child_data_array[0].my2Nyyz_Nzyy; + ((T*)¤t_box_data.my2Nyyx_Nxyy)[0] = child_data_array[0].my2Nyyx_Nxyy; + ((T*)¤t_box_data.my2Nzzx_Nxzz)[0] = child_data_array[0].my2Nzzx_Nxzz; + ((T*)¤t_box_data.my2Nzzy_Nyzz)[0] = child_data_array[0].my2Nzzy_Nyzz; + for (int i = 1; i < nchildren; ++i) + { + for (int j = 0; j < 3; ++j) + ((T*)¤t_box_data.myNijDiag[j])[i] = child_data_array[i].myNijDiag[j]; + ((T*)¤t_box_data.myNxy_Nyx)[i] = child_data_array[i].myNxy + child_data_array[i].myNyx; + ((T*)¤t_box_data.myNyz_Nzy)[i] = child_data_array[i].myNyz + child_data_array[i].myNzy; + ((T*)¤t_box_data.myNzx_Nxz)[i] = child_data_array[i].myNzx + child_data_array[i].myNxz; + for (int j = 0; j < 3; ++j) + ((T*)¤t_box_data.myNijkDiag[j])[i] = child_data_array[i].myNijkDiag[j]; + ((T*)¤t_box_data.mySumPermuteNxyz)[i] = child_data_array[i].mySumPermuteNxyz; + ((T*)¤t_box_data.my2Nxxy_Nyxx)[i] = child_data_array[i].my2Nxxy_Nyxx; + ((T*)¤t_box_data.my2Nxxz_Nzxx)[i] = child_data_array[i].my2Nxxz_Nzxx; + ((T*)¤t_box_data.my2Nyyz_Nzyy)[i] = child_data_array[i].my2Nyyz_Nzyy; + ((T*)¤t_box_data.my2Nyyx_Nxyy)[i] = child_data_array[i].my2Nyyx_Nxyy; + ((T*)¤t_box_data.my2Nzzx_Nxzz)[i] = child_data_array[i].my2Nzzx_Nxzz; + ((T*)¤t_box_data.my2Nzzy_Nyzz)[i] = child_data_array[i].my2Nzzy_Nyzz; + } + for (int i = nchildren; i < BVH_N; ++i) + { + // Set to zero, just to avoid false positives for uses of uninitialized memory. + for (int j = 0; j < 3; ++j) + ((T*)¤t_box_data.myNijDiag[j])[i] = 0; + ((T*)¤t_box_data.myNxy_Nyx)[i] = 0; + ((T*)¤t_box_data.myNyz_Nzy)[i] = 0; + ((T*)¤t_box_data.myNzx_Nxz)[i] = 0; + for (int j = 0; j < 3; ++j) + ((T*)¤t_box_data.myNijkDiag[j])[i] = 0; + ((T*)¤t_box_data.mySumPermuteNxyz)[i] = 0; + ((T*)¤t_box_data.my2Nxxy_Nyxx)[i] = 0; + ((T*)¤t_box_data.my2Nxxz_Nzxx)[i] = 0; + ((T*)¤t_box_data.my2Nyyz_Nzyy)[i] = 0; + ((T*)¤t_box_data.my2Nyyx_Nxyy)[i] = 0; + ((T*)¤t_box_data.my2Nzzx_Nxzz)[i] = 0; + ((T*)¤t_box_data.my2Nzzy_Nyzz)[i] = 0; + } + + for (int i = 0; i < nchildren; ++i) + { + const LocalData &child_data = child_data_array[i]; + UT_Vector3T displacement = child_data.myAverageP - UT_Vector3T(data_for_parent->myAverageP); + UT_Vector3T N = child_data.myN; + + // Adjust Nij for the change in centre P + data_for_parent->myNijDiag += N*displacement; + T Nxy = child_data.myNxy + N[0]*displacement[1]; + T Nyx = child_data.myNyx + N[1]*displacement[0]; + T Nyz = child_data.myNyz + N[1]*displacement[2]; + T Nzy = child_data.myNzy + N[2]*displacement[1]; + T Nzx = child_data.myNzx + N[2]*displacement[0]; + T Nxz = child_data.myNxz + N[0]*displacement[2]; + + data_for_parent->myNxy += Nxy; + data_for_parent->myNyx += Nyx; + data_for_parent->myNyz += Nyz; + data_for_parent->myNzy += Nzy; + data_for_parent->myNzx += Nzx; + data_for_parent->myNxz += Nxz; + +#if TAYLOR_SERIES_ORDER >= 2 + if (order >= 2) + { + // Adjust Nijk for the change in centre P + data_for_parent->myNijkDiag += T(2)*displacement*child_data.myNijDiag + displacement*displacement*child_data.myN; + data_for_parent->mySumPermuteNxyz += (displacement[0]*(Nyz+Nzy) + displacement[1]*(Nzx+Nxz) + displacement[2]*(Nxy+Nyx)); + data_for_parent->my2Nxxy_Nyxx += + 2*(displacement[1]*child_data.myNijDiag[0] + displacement[0]*child_data.myNxy + N[0]*displacement[0]*displacement[1]) + + 2*child_data.myNyx*displacement[0] + N[1]*displacement[0]*displacement[0]; + data_for_parent->my2Nxxz_Nzxx += + 2*(displacement[2]*child_data.myNijDiag[0] + displacement[0]*child_data.myNxz + N[0]*displacement[0]*displacement[2]) + + 2*child_data.myNzx*displacement[0] + N[2]*displacement[0]*displacement[0]; + data_for_parent->my2Nyyz_Nzyy += + 2*(displacement[2]*child_data.myNijDiag[1] + displacement[1]*child_data.myNyz + N[1]*displacement[1]*displacement[2]) + + 2*child_data.myNzy*displacement[1] + N[2]*displacement[1]*displacement[1]; + data_for_parent->my2Nyyx_Nxyy += + 2*(displacement[0]*child_data.myNijDiag[1] + displacement[1]*child_data.myNyx + N[1]*displacement[1]*displacement[0]) + + 2*child_data.myNxy*displacement[1] + N[0]*displacement[1]*displacement[1]; + data_for_parent->my2Nzzx_Nxzz += + 2*(displacement[0]*child_data.myNijDiag[2] + displacement[2]*child_data.myNzx + N[2]*displacement[2]*displacement[0]) + + 2*child_data.myNxz*displacement[2] + N[0]*displacement[2]*displacement[2]; + data_for_parent->my2Nzzy_Nyzz += + 2*(displacement[1]*child_data.myNijDiag[2] + displacement[2]*child_data.myNzy + N[2]*displacement[2]*displacement[1]) + + 2*child_data.myNyz*displacement[2] + N[1]*displacement[2]*displacement[2]; + } +#endif + } + } +#endif +#if SOLID_ANGLE_DEBUG + UTdebugFormat(""); + UTdebugFormat("Node {}: nchildren = {}; maxP = {}", nodei, nchildren, SYSsqrt(current_box_data.myMaxPDist2)); + UTdebugFormat(" P = {}; N = {}", current_box_data.myAverageP, current_box_data.myN); +#if TAYLOR_SERIES_ORDER >= 1 + UTdebugFormat(" Nii = {}", current_box_data.myNijDiag); + UTdebugFormat(" Nxy+Nyx = {}; Nyz+Nzy = {}; Nyz+Nzy = {}", current_box_data.myNxy_Nyx, current_box_data.myNyz_Nzy, current_box_data.myNzx_Nxz); +#if TAYLOR_SERIES_ORDER >= 2 + UTdebugFormat(" Niii = {}; 2(Nxyz+Nyzx+Nzxy) = {}", current_box_data.myNijkDiag, current_box_data.mySumPermuteNxyz); + UTdebugFormat(" 2Nxxy+Nyxx = {}; 2Nxxz+Nzxx = {}", current_box_data.my2Nxxy_Nyxx, current_box_data.my2Nxxz_Nzxx); + UTdebugFormat(" 2Nyyz+Nzyy = {}; 2Nyyx+Nxyy = {}", current_box_data.my2Nyyz_Nzyy, current_box_data.my2Nyyx_Nxyy); + UTdebugFormat(" 2Nzzx+Nxzz = {}; 2Nzzy+Nyzz = {}", current_box_data.my2Nzzx_Nxzz, current_box_data.my2Nzzy_Nyzz); +#endif +#endif +#endif + } + }; + +#if SOLID_ANGLE_TIME_PRECOMPUTE + timer.start(); +#endif + const PrecomputeFunctors functors(box_data, triangle_boxes.array(), triangle_points, positions, order); + // NOTE: post-functor relies on non-null data_for_parent, so we have to pass one. + LocalData local_data; + myTree.template traverseParallel(4096, functors, &local_data); + //myTree.template traverse(functors); +#if SOLID_ANGLE_TIME_PRECOMPUTE + time = timer.stop(); + UTdebugFormat("{} s to precompute coefficients.", time); +#endif +} + +template +inline void UT_SolidAngle::clear() +{ + myTree.clear(); + myNBoxes = 0; + myOrder = 2; + myData.reset(); + myNTriangles = 0; + myTrianglePoints = nullptr; + myNPoints = 0; + myPositions = nullptr; +} + +template +inline T UT_SolidAngle::computeSolidAngle(const UT_Vector3T &query_point, const T accuracy_scale) const +{ + const T accuracy_scale2 = accuracy_scale*accuracy_scale; + + struct SolidAngleFunctors + { + const BoxData *const myBoxData; + const UT_Vector3T myQueryPoint; + const T myAccuracyScale2; + const UT_Vector3T *const myPositions; + const int *const myTrianglePoints; + const int myOrder; + + SolidAngleFunctors( + const BoxData *const box_data, + const UT_Vector3T &query_point, + const T accuracy_scale2, + const int order, + const UT_Vector3T *const positions, + const int *const triangle_points) + : myBoxData(box_data) + , myQueryPoint(query_point) + , myAccuracyScale2(accuracy_scale2) + , myOrder(order) + , myPositions(positions) + , myTrianglePoints(triangle_points) + {} + uint pre(const int nodei, T *data_for_parent) const + { + const BoxData &data = myBoxData[nodei]; + const typename BoxData::Type maxP2 = data.myMaxPDist2; + UT_FixedVector q; + q[0] = typename BoxData::Type(myQueryPoint[0]); + q[1] = typename BoxData::Type(myQueryPoint[1]); + q[2] = typename BoxData::Type(myQueryPoint[2]); + q -= data.myAverageP; + const typename BoxData::Type qlength2 = q[0]*q[0] + q[1]*q[1] + q[2]*q[2]; + + // If the query point is within a factor of accuracy_scale of the box radius, + // it's assumed to be not a good enough approximation, so it needs to descend. + // TODO: Is there a way to estimate the error? + static_assert((std::is_same::value), "FIXME: Implement support for other tuple types!"); + v4uu descend_mask = (qlength2 <= maxP2*myAccuracyScale2); + uint descend_bitmask = _mm_movemask_ps(V4SF(descend_mask.vector)); + constexpr uint allchildbits = ((uint(1)<= 1 + const int order = myOrder; + if (order >= 1) + { + const UT_FixedVector q2 = q*q; + const typename BoxData::Type qlength_m3 = qlength_m2*qlength_m1; + const typename BoxData::Type Omega_1 = + qlength_m3*(data.myNijDiag[0] + data.myNijDiag[1] + data.myNijDiag[2] + -typename BoxData::Type(3.0)*(dot(q2,data.myNijDiag) + + q[0]*q[1]*data.myNxy_Nyx + + q[0]*q[2]*data.myNzx_Nxz + + q[1]*q[2]*data.myNyz_Nzy)); + Omega_approx += Omega_1; +#if TAYLOR_SERIES_ORDER >= 2 + if (order >= 2) + { + const UT_FixedVector q3 = q2*q; + const typename BoxData::Type qlength_m4 = qlength_m2*qlength_m2; + typename BoxData::Type temp0[3] = { + data.my2Nyyx_Nxyy+data.my2Nzzx_Nxzz, + data.my2Nzzy_Nyzz+data.my2Nxxy_Nyxx, + data.my2Nxxz_Nzxx+data.my2Nyyz_Nzyy + }; + typename BoxData::Type temp1[3] = { + q[1]*data.my2Nxxy_Nyxx + q[2]*data.my2Nxxz_Nzxx, + q[2]*data.my2Nyyz_Nzyy + q[0]*data.my2Nyyx_Nxyy, + q[0]*data.my2Nzzx_Nxzz + q[1]*data.my2Nzzy_Nyzz + }; + const typename BoxData::Type Omega_2 = + qlength_m4*(typename BoxData::Type(1.5)*dot(q, typename BoxData::Type(3)*data.myNijkDiag + UT_FixedVector(temp0)) + -typename BoxData::Type(7.5)*(dot(q3,data.myNijkDiag) + q[0]*q[1]*q[2]*data.mySumPermuteNxyz + dot(q2, UT_FixedVector(temp1)))); + Omega_approx += Omega_2; + } +#endif + } +#endif + + // If q is so small that we got NaNs and we just have a + // small bounding box, it needs to descend. + const v4uu mask = Omega_approx.isFinite() & ~descend_mask; + Omega_approx = Omega_approx & mask; + descend_bitmask = (~_mm_movemask_ps(V4SF(mask.vector))) & allchildbits; + + T sum = Omega_approx[0]; + for (int i = 1; i < BVH_N; ++i) + sum += Omega_approx[i]; + *data_for_parent = sum; + + return descend_bitmask; + } + void item(const int itemi, const int parent_nodei, T &data_for_parent) const + { + const UT_Vector3T *const positions = myPositions; + const int *const cur_triangle_points = myTrianglePoints + 3*itemi; + const UT_Vector3T a = positions[cur_triangle_points[0]]; + const UT_Vector3T b = positions[cur_triangle_points[1]]; + const UT_Vector3T c = positions[cur_triangle_points[2]]; + + data_for_parent = UTsignedSolidAngleTri(a, b, c, myQueryPoint); + } + SYS_FORCE_INLINE void post(const int nodei, const int parent_nodei, T *data_for_parent, const int nchildren, const T *child_data_array, const uint descend_bits) const + { + T sum = (descend_bits&1) ? child_data_array[0] : 0; + for (int i = 1; i < nchildren; ++i) + sum += ((descend_bits>>i)&1) ? child_data_array[i] : 0; + + *data_for_parent += sum; + } + }; + const SolidAngleFunctors functors(myData.get(), query_point, accuracy_scale2, myOrder, myPositions, myTrianglePoints); + + T sum; + myTree.traverseVector(functors, &sum); + return sum; +} + +template +struct UT_SubtendedAngle::BoxData +{ + void clear() + { + // Set everything to zero + memset(this,0,sizeof(*this)); + } + + using Type = typename std::conditional::value, v4uf, UT_FixedVector>::type; + using SType = typename std::conditional::value, v4uf, UT_FixedVector>::type; + + /// An upper bound on the squared distance from myAverageP to the farthest point in the box. + SType myMaxPDist2; + + /// Centre of mass of the mesh surface in this box + UT_FixedVector myAverageP; + + /// Unnormalized, area-weighted normal of the mesh in this box + UT_FixedVector myN; + + /// Values for Omega_1 + /// @{ + UT_FixedVector myNijDiag; // Nxx, Nyy + Type myNxy_Nyx; // Nxy+Nyx + /// @} + + /// Values for Omega_2 + /// @{ + UT_FixedVector myNijkDiag; // Nxxx, Nyyy + Type my2Nxxy_Nyxx; // Nxxy+Nxyx+Nyxx = 2Nxxy+Nyxx + Type my2Nyyx_Nxyy; // Nyyx+Nyxy+Nxyy = 2Nyyx+Nxyy + /// @} +}; + +template +inline UT_SubtendedAngle::UT_SubtendedAngle() + : myTree() + , myNBoxes(0) + , myOrder(2) + , myData(nullptr) + , myNSegments(0) + , mySegmentPoints(nullptr) + , myNPoints(0) + , myPositions(nullptr) +{} + +template +inline UT_SubtendedAngle::~UT_SubtendedAngle() +{ + // Default destruction works, but this needs to be outlined + // to avoid having to include UT_BVHImpl.h in the header, + // (for the UT_UniquePtr destructor.) +} + +template +inline void UT_SubtendedAngle::init( + const int nsegments, + const int *const segment_points, + const int npoints, + const UT_Vector2T *const positions, + const int order) +{ +#if SOLID_ANGLE_DEBUG + UTdebugFormat(""); + UTdebugFormat(""); + UTdebugFormat("Building BVH for {} segments on {} points:", nsegments, npoints); +#endif + myOrder = order; + myNSegments = nsegments; + mySegmentPoints = segment_points; + myNPoints = npoints; + myPositions = positions; + +#if SOLID_ANGLE_TIME_PRECOMPUTE + UT_StopWatch timer; + timer.start(); +#endif + UT_SmallArray> segment_boxes; + segment_boxes.setSizeNoInit(nsegments); + if (nsegments < 16*1024) + { + const int *cur_segment_points = segment_points; + for (int i = 0; i < nsegments; ++i, cur_segment_points += 2) + { + UT::Box &box = segment_boxes[i]; + box.initBounds(positions[cur_segment_points[0]]); + box.enlargeBounds(positions[cur_segment_points[1]]); + } + } + else + { + igl::parallel_for(nsegments, + [segment_points,&segment_boxes,positions](int i) + { + const int *cur_segment_points = segment_points + i*2; + UT::Box &box = segment_boxes[i]; + box.initBounds(positions[cur_segment_points[0]]); + box.enlargeBounds(positions[cur_segment_points[1]]); + }); + } +#if SOLID_ANGLE_TIME_PRECOMPUTE + double time = timer.stop(); + UTdebugFormat("{} s to create bounding boxes.", time); + timer.start(); +#endif + myTree.template init(segment_boxes.array(), nsegments); +#if SOLID_ANGLE_TIME_PRECOMPUTE + time = timer.stop(); + UTdebugFormat("{} s to initialize UT_BVH structure. {} nodes", time, myTree.getNumNodes()); +#endif + + //myTree.debugDump(); + + const int nnodes = myTree.getNumNodes(); + + myNBoxes = nnodes; + BoxData *box_data = new BoxData[nnodes]; + myData.reset(box_data); + + // Some data are only needed during initialization. + struct LocalData + { + // Bounding box + UT::Box myBox; + + // P and N are needed from each child for computing Nij. + UT_Vector2T myAverageP; + UT_Vector2T myLengthP; + UT_Vector2T myN; + + // Unsigned length is needed for computing the average position. + T myLength; + + // These are needed for computing Nijk. + UT_Vector2T myNijDiag; + T myNxy; T myNyx; + + UT_Vector2T myNijkDiag; // Nxxx, Nyyy + T my2Nxxy_Nyxx; // Nxxy+Nxyx+Nyxx = 2Nxxy+Nyxx + T my2Nyyx_Nxyy; // Nyyx+Nyxy+Nxyy = 2Nyyx+Nxyy + }; + + struct PrecomputeFunctors + { + BoxData *const myBoxData; + const UT::Box *const mySegmentBoxes; + const int *const mySegmentPoints; + const UT_Vector2T *const myPositions; + const int myOrder; + + PrecomputeFunctors( + BoxData *box_data, + const UT::Box *segment_boxes, + const int *segment_points, + const UT_Vector2T *positions, + const int order) + : myBoxData(box_data) + , mySegmentBoxes(segment_boxes) + , mySegmentPoints(segment_points) + , myPositions(positions) + , myOrder(order) + {} + constexpr SYS_FORCE_INLINE bool pre(const int nodei, LocalData *data_for_parent) const + { + return true; + } + void item(const int itemi, const int parent_nodei, LocalData &data_for_parent) const + { + const UT_Vector2T *const positions = myPositions; + const int *const cur_segment_points = mySegmentPoints + 2*itemi; + const UT_Vector2T a = positions[cur_segment_points[0]]; + const UT_Vector2T b = positions[cur_segment_points[1]]; + const UT_Vector2T ab = b-a; + + const UT::Box &segment_box = mySegmentBoxes[itemi]; + data_for_parent.myBox = segment_box; + + // Length-weighted normal (unnormalized) + UT_Vector2T N; + N[0] = ab[1]; + N[1] = -ab[0]; + const T length2 = ab.length2(); + const T length = SYSsqrt(length2); + const UT_Vector2T P = T(0.5)*(a+b); + data_for_parent.myAverageP = P; + data_for_parent.myLengthP = P*length; + data_for_parent.myN = N; +#if SOLID_ANGLE_DEBUG + UTdebugFormat(""); + UTdebugFormat("Triangle {}: P = {}; N = {}; length = {}", itemi, P, N, length); + UTdebugFormat(" box = {}", data_for_parent.myBox); +#endif + + data_for_parent.myLength = length; + const int order = myOrder; + if (order < 1) + return; + + // NOTE: Due to P being at the centroid, segments have Nij = 0 + // contributions to Nij. + data_for_parent.myNijDiag = T(0); + data_for_parent.myNxy = 0; data_for_parent.myNyx = 0; + + if (order < 2) + return; + + // If it's zero-length, the results are zero, so we can skip. + if (length == 0) + { + data_for_parent.myNijkDiag = T(0); + data_for_parent.my2Nxxy_Nyxx = 0; + data_for_parent.my2Nyyx_Nxyy = 0; + return; + } + + T integral_xx = ab[0]*ab[0]/T(12); + T integral_xy = ab[0]*ab[1]/T(12); + T integral_yy = ab[1]*ab[1]/T(12); + data_for_parent.myNijkDiag[0] = integral_xx*N[0]; + data_for_parent.myNijkDiag[1] = integral_yy*N[1]; + T Nxxy = N[0]*integral_xy; + T Nyxx = N[1]*integral_xx; + T Nyyx = N[1]*integral_xy; + T Nxyy = N[0]*integral_yy; + data_for_parent.my2Nxxy_Nyxx = 2*Nxxy + Nyxx; + data_for_parent.my2Nyyx_Nxyy = 2*Nyyx + Nxyy; +#if SOLID_ANGLE_DEBUG + UTdebugFormat(" integral_xx = {}; yy = {}", integral_xx, integral_yy); + UTdebugFormat(" integral_xy = {}", integral_xy); +#endif + } + + void post(const int nodei, const int parent_nodei, LocalData *data_for_parent, const int nchildren, const LocalData *child_data_array) const + { + // NOTE: Although in the general case, data_for_parent may be null for the root call, + // this functor assumes that it's non-null, so the call below must pass a non-null pointer. + + BoxData ¤t_box_data = myBoxData[nodei]; + + UT_Vector2T N = child_data_array[0].myN; + ((T*)¤t_box_data.myN[0])[0] = N[0]; + ((T*)¤t_box_data.myN[1])[0] = N[1]; + UT_Vector2T lengthP = child_data_array[0].myLengthP; + T length = child_data_array[0].myLength; + const UT_Vector2T local_P = child_data_array[0].myAverageP; + ((T*)¤t_box_data.myAverageP[0])[0] = local_P[0]; + ((T*)¤t_box_data.myAverageP[1])[0] = local_P[1]; + for (int i = 1; i < nchildren; ++i) + { + const UT_Vector2T local_N = child_data_array[i].myN; + N += local_N; + ((T*)¤t_box_data.myN[0])[i] = local_N[0]; + ((T*)¤t_box_data.myN[1])[i] = local_N[1]; + lengthP += child_data_array[i].myLengthP; + length += child_data_array[i].myLength; + const UT_Vector2T local_P = child_data_array[i].myAverageP; + ((T*)¤t_box_data.myAverageP[0])[i] = local_P[0]; + ((T*)¤t_box_data.myAverageP[1])[i] = local_P[1]; + } + for (int i = nchildren; i < BVH_N; ++i) + { + // Set to zero, just to avoid false positives for uses of uninitialized memory. + ((T*)¤t_box_data.myN[0])[i] = 0; + ((T*)¤t_box_data.myN[1])[i] = 0; + ((T*)¤t_box_data.myAverageP[0])[i] = 0; + ((T*)¤t_box_data.myAverageP[1])[i] = 0; + } + data_for_parent->myN = N; + data_for_parent->myLengthP = lengthP; + data_for_parent->myLength = length; + + UT::Box box(child_data_array[0].myBox); + for (int i = 1; i < nchildren; ++i) + box.combine(child_data_array[i].myBox); + + // Normalize P + UT_Vector2T averageP; + if (length > 0) + averageP = lengthP/length; + else + averageP = T(0.5)*(box.getMin() + box.getMax()); + data_for_parent->myAverageP = averageP; + + data_for_parent->myBox = box; + + for (int i = 0; i < nchildren; ++i) + { + const UT::Box &local_box(child_data_array[i].myBox); + const UT_Vector2T &local_P = child_data_array[i].myAverageP; + const UT_Vector2T maxPDiff = SYSmax(local_P-UT_Vector2T(local_box.getMin()), UT_Vector2T(local_box.getMax())-local_P); + ((T*)¤t_box_data.myMaxPDist2)[i] = maxPDiff.length2(); + } + for (int i = nchildren; i < BVH_N; ++i) + { + // This child is non-existent. If we set myMaxPDist2 to infinity, it will never + // use the approximation, and the traverseVector function can check for EMPTY. + ((T*)¤t_box_data.myMaxPDist2)[i] = std::numeric_limits::infinity(); + } + + const int order = myOrder; + if (order >= 1) + { + // We now have the current box's P, so we can adjust Nij and Nijk + data_for_parent->myNijDiag = child_data_array[0].myNijDiag; + data_for_parent->myNxy = 0; + data_for_parent->myNyx = 0; + data_for_parent->myNijkDiag = child_data_array[0].myNijkDiag; + data_for_parent->my2Nxxy_Nyxx = child_data_array[0].my2Nxxy_Nyxx; + data_for_parent->my2Nyyx_Nxyy = child_data_array[0].my2Nyyx_Nxyy; + + for (int i = 1; i < nchildren; ++i) + { + data_for_parent->myNijDiag += child_data_array[i].myNijDiag; + data_for_parent->myNijkDiag += child_data_array[i].myNijkDiag; + data_for_parent->my2Nxxy_Nyxx += child_data_array[i].my2Nxxy_Nyxx; + data_for_parent->my2Nyyx_Nxyy += child_data_array[i].my2Nyyx_Nxyy; + } + for (int j = 0; j < 2; ++j) + ((T*)¤t_box_data.myNijDiag[j])[0] = child_data_array[0].myNijDiag[j]; + ((T*)¤t_box_data.myNxy_Nyx)[0] = child_data_array[0].myNxy + child_data_array[0].myNyx; + for (int j = 0; j < 2; ++j) + ((T*)¤t_box_data.myNijkDiag[j])[0] = child_data_array[0].myNijkDiag[j]; + ((T*)¤t_box_data.my2Nxxy_Nyxx)[0] = child_data_array[0].my2Nxxy_Nyxx; + ((T*)¤t_box_data.my2Nyyx_Nxyy)[0] = child_data_array[0].my2Nyyx_Nxyy; + for (int i = 1; i < nchildren; ++i) + { + for (int j = 0; j < 2; ++j) + ((T*)¤t_box_data.myNijDiag[j])[i] = child_data_array[i].myNijDiag[j]; + ((T*)¤t_box_data.myNxy_Nyx)[i] = child_data_array[i].myNxy + child_data_array[i].myNyx; + for (int j = 0; j < 2; ++j) + ((T*)¤t_box_data.myNijkDiag[j])[i] = child_data_array[i].myNijkDiag[j]; + ((T*)¤t_box_data.my2Nxxy_Nyxx)[i] = child_data_array[i].my2Nxxy_Nyxx; + ((T*)¤t_box_data.my2Nyyx_Nxyy)[i] = child_data_array[i].my2Nyyx_Nxyy; + } + for (int i = nchildren; i < BVH_N; ++i) + { + // Set to zero, just to avoid false positives for uses of uninitialized memory. + for (int j = 0; j < 2; ++j) + ((T*)¤t_box_data.myNijDiag[j])[i] = 0; + ((T*)¤t_box_data.myNxy_Nyx)[i] = 0; + for (int j = 0; j < 2; ++j) + ((T*)¤t_box_data.myNijkDiag[j])[i] = 0; + ((T*)¤t_box_data.my2Nxxy_Nyxx)[i] = 0; + ((T*)¤t_box_data.my2Nyyx_Nxyy)[i] = 0; + } + + for (int i = 0; i < nchildren; ++i) + { + const LocalData &child_data = child_data_array[i]; + UT_Vector2T displacement = child_data.myAverageP - UT_Vector2T(data_for_parent->myAverageP); + UT_Vector2T N = child_data.myN; + + // Adjust Nij for the change in centre P + data_for_parent->myNijDiag += N*displacement; + T Nxy = child_data.myNxy + N[0]*displacement[1]; + T Nyx = child_data.myNyx + N[1]*displacement[0]; + + data_for_parent->myNxy += Nxy; + data_for_parent->myNyx += Nyx; + + if (order >= 2) + { + // Adjust Nijk for the change in centre P + data_for_parent->myNijkDiag += T(2)*displacement*child_data.myNijDiag + displacement*displacement*child_data.myN; + data_for_parent->my2Nxxy_Nyxx += + 2*(displacement[1]*child_data.myNijDiag[0] + displacement[0]*child_data.myNxy + N[0]*displacement[0]*displacement[1]) + + 2*child_data.myNyx*displacement[0] + N[1]*displacement[0]*displacement[0]; + data_for_parent->my2Nyyx_Nxyy += + 2*(displacement[0]*child_data.myNijDiag[1] + displacement[1]*child_data.myNyx + N[1]*displacement[1]*displacement[0]) + + 2*child_data.myNxy*displacement[1] + N[0]*displacement[1]*displacement[1]; + } + } + } +#if SOLID_ANGLE_DEBUG + UTdebugFormat(""); + UTdebugFormat("Node {}: nchildren = {}; maxP = {}", nodei, nchildren, SYSsqrt(current_box_data.myMaxPDist2)); + UTdebugFormat(" P = {}; N = {}", current_box_data.myAverageP, current_box_data.myN); + UTdebugFormat(" Nii = {}", current_box_data.myNijDiag); + UTdebugFormat(" Nxy+Nyx = {}", current_box_data.myNxy_Nyx); + UTdebugFormat(" Niii = {}", current_box_data.myNijkDiag); + UTdebugFormat(" 2Nxxy+Nyxx = {}; 2Nyyx+Nxyy = {}", current_box_data.my2Nxxy_Nyxx, current_box_data.my2Nyyx_Nxyy); +#endif + } + }; + +#if SOLID_ANGLE_TIME_PRECOMPUTE + timer.start(); +#endif + const PrecomputeFunctors functors(box_data, segment_boxes.array(), segment_points, positions, order); + // NOTE: post-functor relies on non-null data_for_parent, so we have to pass one. + LocalData local_data; + myTree.template traverseParallel(4096, functors, &local_data); + //myTree.template traverse(functors); +#if SOLID_ANGLE_TIME_PRECOMPUTE + time = timer.stop(); + UTdebugFormat("{} s to precompute coefficients.", time); +#endif +} + +template +inline void UT_SubtendedAngle::clear() +{ + myTree.clear(); + myNBoxes = 0; + myOrder = 2; + myData.reset(); + myNSegments = 0; + mySegmentPoints = nullptr; + myNPoints = 0; + myPositions = nullptr; +} + +template +inline T UT_SubtendedAngle::computeAngle(const UT_Vector2T &query_point, const T accuracy_scale) const +{ + const T accuracy_scale2 = accuracy_scale*accuracy_scale; + + struct AngleFunctors + { + const BoxData *const myBoxData; + const UT_Vector2T myQueryPoint; + const T myAccuracyScale2; + const UT_Vector2T *const myPositions; + const int *const mySegmentPoints; + const int myOrder; + + AngleFunctors( + const BoxData *const box_data, + const UT_Vector2T &query_point, + const T accuracy_scale2, + const int order, + const UT_Vector2T *const positions, + const int *const segment_points) + : myBoxData(box_data) + , myQueryPoint(query_point) + , myAccuracyScale2(accuracy_scale2) + , myOrder(order) + , myPositions(positions) + , mySegmentPoints(segment_points) + {} + uint pre(const int nodei, T *data_for_parent) const + { + const BoxData &data = myBoxData[nodei]; + const typename BoxData::Type maxP2 = data.myMaxPDist2; + UT_FixedVector q; + q[0] = typename BoxData::Type(myQueryPoint[0]); + q[1] = typename BoxData::Type(myQueryPoint[1]); + q -= data.myAverageP; + const typename BoxData::Type qlength2 = q[0]*q[0] + q[1]*q[1]; + + // If the query point is within a factor of accuracy_scale of the box radius, + // it's assumed to be not a good enough approximation, so it needs to descend. + // TODO: Is there a way to estimate the error? + static_assert((std::is_same::value), "FIXME: Implement support for other tuple types!"); + v4uu descend_mask = (qlength2 <= maxP2*myAccuracyScale2); + uint descend_bitmask = _mm_movemask_ps(V4SF(descend_mask.vector)); + constexpr uint allchildbits = ((uint(1)<= 1) + { + const UT_FixedVector q2 = q*q; + const typename BoxData::Type Omega_1 = + qlength_m2*(data.myNijDiag[0] + data.myNijDiag[1] + -typename BoxData::Type(2.0)*(dot(q2,data.myNijDiag) + + q[0]*q[1]*data.myNxy_Nyx)); + Omega_approx += Omega_1; + if (order >= 2) + { + const UT_FixedVector q3 = q2*q; + const typename BoxData::Type qlength_m3 = qlength_m2*qlength_m1; + typename BoxData::Type temp0[2] = { + data.my2Nyyx_Nxyy, + data.my2Nxxy_Nyxx + }; + typename BoxData::Type temp1[2] = { + q[1]*data.my2Nxxy_Nyxx, + q[0]*data.my2Nyyx_Nxyy + }; + const typename BoxData::Type Omega_2 = + qlength_m3*(dot(q, typename BoxData::Type(3)*data.myNijkDiag + UT_FixedVector(temp0)) + -typename BoxData::Type(4.0)*(dot(q3,data.myNijkDiag) + dot(q2, UT_FixedVector(temp1)))); + Omega_approx += Omega_2; + } + } + + // If q is so small that we got NaNs and we just have a + // small bounding box, it needs to descend. + const v4uu mask = Omega_approx.isFinite() & ~descend_mask; + Omega_approx = Omega_approx & mask; + descend_bitmask = (~_mm_movemask_ps(V4SF(mask.vector))) & allchildbits; + + T sum = Omega_approx[0]; + for (int i = 1; i < BVH_N; ++i) + sum += Omega_approx[i]; + *data_for_parent = sum; + + return descend_bitmask; + } + void item(const int itemi, const int parent_nodei, T &data_for_parent) const + { + const UT_Vector2T *const positions = myPositions; + const int *const cur_segment_points = mySegmentPoints + 2*itemi; + const UT_Vector2T a = positions[cur_segment_points[0]]; + const UT_Vector2T b = positions[cur_segment_points[1]]; + + data_for_parent = UTsignedAngleSegment(a, b, myQueryPoint); + } + SYS_FORCE_INLINE void post(const int nodei, const int parent_nodei, T *data_for_parent, const int nchildren, const T *child_data_array, const uint descend_bits) const + { + T sum = (descend_bits&1) ? child_data_array[0] : 0; + for (int i = 1; i < nchildren; ++i) + sum += ((descend_bits>>i)&1) ? child_data_array[i] : 0; + + *data_for_parent += sum; + } + }; + const AngleFunctors functors(myData.get(), query_point, accuracy_scale2, myOrder, myPositions, mySegmentPoints); + + T sum; + myTree.traverseVector(functors, &sum); + return sum; +} + +// Instantiate our templates. +//template class UT_SolidAngle; +// FIXME: The SIMD parts will need to be handled differently in order to support fpreal64. +//template class UT_SolidAngle; +//template class UT_SolidAngle; +//template class UT_SubtendedAngle; +//template class UT_SubtendedAngle; +//template class UT_SubtendedAngle; + +} // End HDK_Sample namespace +}} diff --git a/include/igl/HalfEdgeIterator.cpp b/include/igl/HalfEdgeIterator.cpp index 7c3b9a886..982c295f0 100644 --- a/include/igl/HalfEdgeIterator.cpp +++ b/include/igl/HalfEdgeIterator.cpp @@ -10,9 +10,9 @@ template IGL_INLINE igl::HalfEdgeIterator::HalfEdgeIterator( - const Eigen::PlainObjectBase& _F, - const Eigen::PlainObjectBase& _FF, - const Eigen::PlainObjectBase& _FFi, + const Eigen::MatrixBase& _F, + const Eigen::MatrixBase& _FF, + const Eigen::MatrixBase& _FFi, int _fi, int _ei, bool _reverse @@ -138,8 +138,8 @@ IGL_INLINE bool igl::HalfEdgeIterator::operator== #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template igl::HalfEdgeIterator ,Eigen::Matrix ,Eigen::Matrix >::HalfEdgeIterator(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, int, int, bool); -template igl::HalfEdgeIterator, Eigen::Matrix, Eigen::Matrix >::HalfEdgeIterator(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, int, int, bool); +template igl::HalfEdgeIterator ,Eigen::Matrix ,Eigen::Matrix >::HalfEdgeIterator(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, int, bool); +template igl::HalfEdgeIterator, Eigen::Matrix, Eigen::Matrix >::HalfEdgeIterator(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, int, bool); template bool igl::HalfEdgeIterator,Eigen::Matrix,Eigen::Matrix >::NextFE(); template int igl::HalfEdgeIterator,Eigen::Matrix,Eigen::Matrix >::Ei(); template int igl::HalfEdgeIterator ,Eigen::Matrix,Eigen::Matrix >::Ei(); @@ -147,12 +147,16 @@ template int igl::HalfEdgeIterator ,Eigen: template int igl::HalfEdgeIterator ,Eigen::Matrix ,Eigen::Matrix >::Fi(); template bool igl::HalfEdgeIterator ,Eigen::Matrix ,Eigen::Matrix >::NextFE(); template int igl::HalfEdgeIterator,Eigen::Matrix,Eigen::Matrix >::Vi(); -template igl::HalfEdgeIterator,Eigen::Matrix,Eigen::Matrix >::HalfEdgeIterator(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, int, int, bool); +template igl::HalfEdgeIterator,Eigen::Matrix,Eigen::Matrix >::HalfEdgeIterator(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, int, bool); template int igl::HalfEdgeIterator,Eigen::Matrix,Eigen::Matrix >::Fi(); template void igl::HalfEdgeIterator,Eigen::Matrix,Eigen::Matrix >::flipE(); +template void igl::HalfEdgeIterator, Eigen::Matrix, Eigen::Matrix >::flipE(); template void igl::HalfEdgeIterator,Eigen::Matrix,Eigen::Matrix >::flipF(); +template void igl::HalfEdgeIterator, Eigen::Matrix, Eigen::Matrix >::flipF(); template void igl::HalfEdgeIterator,Eigen::Matrix,Eigen::Matrix >::flipV(); template bool igl::HalfEdgeIterator,Eigen::Matrix,Eigen::Matrix >::operator==(igl::HalfEdgeIterator,Eigen::Matrix,Eigen::Matrix >&); template int igl::HalfEdgeIterator, Eigen::Matrix, Eigen::Matrix >::Fi(); template bool igl::HalfEdgeIterator, Eigen::Matrix, Eigen::Matrix >::NextFE(); +template bool igl::HalfEdgeIterator, Eigen::Matrix, Eigen::Matrix >::isBorder(); +template bool igl::HalfEdgeIterator, Eigen::Matrix, Eigen::Matrix >::isBorder(); #endif diff --git a/include/igl/HalfEdgeIterator.h b/include/igl/HalfEdgeIterator.h index 3c429e1d1..e1351e5f0 100644 --- a/include/igl/HalfEdgeIterator.h +++ b/include/igl/HalfEdgeIterator.h @@ -49,9 +49,9 @@ namespace igl public: // Init the HalfEdgeIterator by specifying Face,Edge Index and Orientation IGL_INLINE HalfEdgeIterator( - const Eigen::PlainObjectBase& _F, - const Eigen::PlainObjectBase& _FF, - const Eigen::PlainObjectBase& _FFi, + const Eigen::MatrixBase& _F, + const Eigen::MatrixBase& _FF, + const Eigen::MatrixBase& _FFi, int _fi, int _ei, bool _reverse = false @@ -100,9 +100,9 @@ namespace igl bool reverse; // All the same type? This is likely to break. - const Eigen::PlainObjectBase & F; - const Eigen::PlainObjectBase & FF; - const Eigen::PlainObjectBase & FFi; + const Eigen::MatrixBase & F; + const Eigen::MatrixBase & FF; + const Eigen::MatrixBase & FFi; }; } diff --git a/include/igl/MappingEnergyType.h b/include/igl/MappingEnergyType.h index acf2dc0e5..1eeeb778b 100644 --- a/include/igl/MappingEnergyType.h +++ b/include/igl/MappingEnergyType.h @@ -15,12 +15,13 @@ namespace igl enum MappingEnergyType { - ARAP, - LOG_ARAP, - SYMMETRIC_DIRICHLET, - CONFORMAL, - EXP_CONFORMAL, - EXP_SYMMETRIC_DIRICHLET + ARAP = 0, + LOG_ARAP = 1, + SYMMETRIC_DIRICHLET = 2, + CONFORMAL = 3, + EXP_CONFORMAL = 4, + EXP_SYMMETRIC_DIRICHLET = 5, + NUM_SLIM_ENERGY_TYPES = 6 }; } #endif diff --git a/include/igl/active_set.cpp b/include/igl/active_set.cpp index fd5dfba88..973ad0d91 100755 --- a/include/igl/active_set.cpp +++ b/include/igl/active_set.cpp @@ -223,7 +223,7 @@ IGL_INLINE igl::SolverStatus igl::active_set( } //cout< as_ieq_list(as_ieq_count,1); // Gather active constraints and resp. rhss DerivedBeq Beq_i; Beq_i.resize(Beq.rows()+as_ieq_count,1); diff --git a/include/igl/active_set.h b/include/igl/active_set.h index b82d0e52b..9f2676344 100644 --- a/include/igl/active_set.h +++ b/include/igl/active_set.h @@ -18,7 +18,7 @@ namespace igl struct active_set_params; // Known Bugs: rows of [Aeq;Aieq] **must** be linearly independent. Should be // using QR decomposition otherwise: - // http://www.okstate.edu/sas/v8/sashtml/ormp/chap5/sect32.htm + // https://v8doc.sas.com/sashtml/ormp/chap5/sect32.htm // // ACTIVE_SET Minimize quadratic energy // diff --git a/include/igl/all_edges.h b/include/igl/all_edges.h index d5fe13a9a..fd60130ac 100644 --- a/include/igl/all_edges.h +++ b/include/igl/all_edges.h @@ -8,6 +8,7 @@ #ifndef IGL_ALL_EDGES_H #define IGL_ALL_EDGES_H #include "igl_inline.h" +#include "deprecated.h" #include namespace igl { @@ -26,7 +27,7 @@ namespace igl // show up once for each direction and non-manifold edges may appear more than // once for each direction). template - IGL_INLINE void all_edges( + IGL_DEPRECATED IGL_INLINE void all_edges( const Eigen::MatrixBase & F, Eigen::PlainObjectBase & E); } diff --git a/include/igl/ambient_occlusion.cpp b/include/igl/ambient_occlusion.cpp index 343f8ae8a..70538e7f5 100644 --- a/include/igl/ambient_occlusion.cpp +++ b/include/igl/ambient_occlusion.cpp @@ -25,8 +25,8 @@ IGL_INLINE void igl::ambient_occlusion( const Eigen::Vector3f&, const Eigen::Vector3f&) > & shoot_ray, - const Eigen::PlainObjectBase & P, - const Eigen::PlainObjectBase & N, + const Eigen::MatrixBase & P, + const Eigen::MatrixBase & N, const int num_samples, Eigen::PlainObjectBase & S) { @@ -69,10 +69,10 @@ template < typename DerivedS > IGL_INLINE void igl::ambient_occlusion( const igl::AABB & aabb, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, - const Eigen::PlainObjectBase & P, - const Eigen::PlainObjectBase & N, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const Eigen::MatrixBase & P, + const Eigen::MatrixBase & N, const int num_samples, Eigen::PlainObjectBase & S) { @@ -100,10 +100,10 @@ template < typename DerivedN, typename DerivedS > IGL_INLINE void igl::ambient_occlusion( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, - const Eigen::PlainObjectBase & P, - const Eigen::PlainObjectBase & N, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const Eigen::MatrixBase & P, + const Eigen::MatrixBase & N, const int num_samples, Eigen::PlainObjectBase & S) { @@ -128,10 +128,10 @@ IGL_INLINE void igl::ambient_occlusion( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh -template void igl::ambient_occlusion, Eigen::Matrix, Eigen::Matrix >(std::function const&, Eigen::Matrix const&)> const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::ambient_occlusion, Eigen::Matrix, Eigen::Matrix >(std::function const&, Eigen::Matrix const&)> const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh -template void igl::ambient_occlusion, Eigen::Matrix, Eigen::Matrix >(std::function const&, Eigen::Matrix const&)> const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::ambient_occlusion, Eigen::Matrix, Eigen::Matrix >(std::function const&, Eigen::Matrix const&)> const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh -template void igl::ambient_occlusion, Eigen::Matrix, Eigen::Matrix >(std::function const&, Eigen::Matrix const&)> const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, int, Eigen::PlainObjectBase >&); -template void igl::ambient_occlusion, Eigen::Matrix, Eigen::Matrix >(std::function const&, Eigen::Matrix const&)> const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::ambient_occlusion, Eigen::Matrix, Eigen::Matrix >(std::function const&, Eigen::Matrix const&)> const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::ambient_occlusion, Eigen::Matrix, Eigen::Matrix >(std::function const&, Eigen::Matrix const&)> const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/ambient_occlusion.h b/include/igl/ambient_occlusion.h index 1c173121e..5e67ff598 100644 --- a/include/igl/ambient_occlusion.h +++ b/include/igl/ambient_occlusion.h @@ -34,8 +34,8 @@ namespace igl const Eigen::Vector3f&, const Eigen::Vector3f&) > & shoot_ray, - const Eigen::PlainObjectBase & P, - const Eigen::PlainObjectBase & N, + const Eigen::MatrixBase & P, + const Eigen::MatrixBase & N, const int num_samples, Eigen::PlainObjectBase & S); // Inputs: @@ -49,10 +49,10 @@ namespace igl typename DerivedS > IGL_INLINE void ambient_occlusion( const igl::AABB & aabb, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, - const Eigen::PlainObjectBase & P, - const Eigen::PlainObjectBase & N, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const Eigen::MatrixBase & P, + const Eigen::MatrixBase & N, const int num_samples, Eigen::PlainObjectBase & S); // Inputs: @@ -65,10 +65,10 @@ namespace igl typename DerivedN, typename DerivedS > IGL_INLINE void ambient_occlusion( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, - const Eigen::PlainObjectBase & P, - const Eigen::PlainObjectBase & N, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const Eigen::MatrixBase & P, + const Eigen::MatrixBase & N, const int num_samples, Eigen::PlainObjectBase & S); diff --git a/include/igl/arap_linear_block.cpp b/include/igl/arap_linear_block.cpp index 14886b2bc..7501721b6 100644 --- a/include/igl/arap_linear_block.cpp +++ b/include/igl/arap_linear_block.cpp @@ -10,13 +10,13 @@ #include "cotmatrix_entries.h" #include -template +template IGL_INLINE void igl::arap_linear_block( const MatV & V, const MatF & F, const int d, const igl::ARAPEnergyType energy, - Eigen::SparseMatrix & Kd) + MatK & Kd) { switch(energy) { @@ -36,13 +36,15 @@ IGL_INLINE void igl::arap_linear_block( } -template +template IGL_INLINE void igl::arap_linear_block_spokes( const MatV & V, const MatF & F, const int d, - Eigen::SparseMatrix & Kd) + MatK & Kd) { + typedef typename MatK::Scalar Scalar; + using namespace std; using namespace Eigen; // simplex size (3: triangles, 4: tetrahedra) @@ -101,13 +103,15 @@ IGL_INLINE void igl::arap_linear_block_spokes( Kd.makeCompressed(); } -template +template IGL_INLINE void igl::arap_linear_block_spokes_and_rims( const MatV & V, const MatF & F, const int d, - Eigen::SparseMatrix & Kd) + MatK & Kd) { + typedef typename MatK::Scalar Scalar; + using namespace std; using namespace Eigen; // simplex size (3: triangles, 4: tetrahedra) @@ -183,13 +187,14 @@ IGL_INLINE void igl::arap_linear_block_spokes_and_rims( Kd.makeCompressed(); } -template +template IGL_INLINE void igl::arap_linear_block_elements( const MatV & V, const MatF & F, const int d, - Eigen::SparseMatrix & Kd) + MatK & Kd) { + typedef typename MatK::Scalar Scalar; using namespace std; using namespace Eigen; // simplex size (3: triangles, 4: tetrahedra) @@ -249,5 +254,6 @@ IGL_INLINE void igl::arap_linear_block_elements( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template IGL_INLINE void igl::arap_linear_block, Eigen::Matrix, double>(Eigen::Matrix const&, Eigen::Matrix const&, int, igl::ARAPEnergyType, Eigen::SparseMatrix&); +template void igl::arap_linear_block >, Eigen::MatrixBase >, Eigen::SparseMatrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, igl::ARAPEnergyType, Eigen::SparseMatrix&); +template void igl::arap_linear_block, Eigen::Matrix, Eigen::SparseMatrix >(Eigen::Matrix const&, Eigen::Matrix const&, int, igl::ARAPEnergyType, Eigen::SparseMatrix&); #endif diff --git a/include/igl/arap_linear_block.h b/include/igl/arap_linear_block.h index 8dfb744f6..9983550aa 100644 --- a/include/igl/arap_linear_block.h +++ b/include/igl/arap_linear_block.h @@ -43,32 +43,32 @@ namespace igl // Kd #V by #V/#F block of the linear constructor matrix corresponding to // coordinate d // - template + template IGL_INLINE void arap_linear_block( const MatV & V, const MatF & F, const int d, const igl::ARAPEnergyType energy, - Eigen::SparseMatrix & Kd); + MatK & Kd); // Helper functions for each energy type - template + template IGL_INLINE void arap_linear_block_spokes( const MatV & V, const MatF & F, const int d, - Eigen::SparseMatrix & Kd); - template + MatK & Kd); + template IGL_INLINE void arap_linear_block_spokes_and_rims( const MatV & V, const MatF & F, const int d, - Eigen::SparseMatrix & Kd); - template + MatK & Kd); + template IGL_INLINE void arap_linear_block_elements( const MatV & V, const MatF & F, const int d, - Eigen::SparseMatrix & Kd); + MatK & Kd); } #ifndef IGL_STATIC_LIBRARY diff --git a/include/igl/arap_rhs.cpp b/include/igl/arap_rhs.cpp index b46462168..0a794e5f0 100644 --- a/include/igl/arap_rhs.cpp +++ b/include/igl/arap_rhs.cpp @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2013 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "arap_rhs.h" #include "arap_linear_block.h" @@ -12,12 +12,13 @@ #include "cat.h" #include +template IGL_INLINE void igl::arap_rhs( - const Eigen::MatrixXd & V, - const Eigen::MatrixXi & F, - const int dim, - const igl::ARAPEnergyType energy, - Eigen::SparseMatrix& K) + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const int dim, + const igl::ARAPEnergyType energy, + Eigen::SparseCompressedBase& K) { using namespace std; using namespace Eigen; @@ -48,7 +49,7 @@ IGL_INLINE void igl::arap_rhs( return; } - SparseMatrix KX,KY,KZ; + DerivedK KX,KY,KZ; arap_linear_block(V,F,0,energy,KX); arap_linear_block(V,F,1,energy,KY); if(Vdim == 2) @@ -62,7 +63,7 @@ IGL_INLINE void igl::arap_rhs( K = cat(2,cat(2,repdiag(KX,dim),repdiag(KY,dim)),repdiag(KZ,dim)); }else if(dim ==2) { - SparseMatrix ZZ(KX.rows()*2,KX.cols()); + DerivedK ZZ(KX.rows()*2,KX.cols()); K = cat(2,cat(2, cat(2,repdiag(KX,dim),ZZ), cat(2,repdiag(KY,dim),ZZ)), @@ -84,6 +85,11 @@ IGL_INLINE void igl::arap_rhs( Vdim); return; } - + } + + +#ifdef IGL_STATIC_LIBRARY +template void igl::arap_rhs(const Eigen::MatrixBase & V, const Eigen::MatrixBase & F,const int dim, const igl::ARAPEnergyType energy,Eigen::SparseCompressedBase>& K); +#endif \ No newline at end of file diff --git a/include/igl/arap_rhs.h b/include/igl/arap_rhs.h index 5a1c370c1..2d456f6bc 100644 --- a/include/igl/arap_rhs.h +++ b/include/igl/arap_rhs.h @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2013 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_ARAP_RHS_H #define IGL_ARAP_RHS_H @@ -25,16 +25,17 @@ namespace igl // energy igl::ARAPEnergyType enum value defining which energy is being // used. See igl::ARAPEnergyType.h for valid options and explanations. // Outputs: - // K #V*dim by #(F|V)*dim*dim matrix such that: + // K #V*dim by #(F|V)*dim*dim matrix such that: // b = K * reshape(permute(R,[3 1 2]),size(V|F,1)*size(V,2)*size(V,2),1); - // + // // See also: arap_linear_block + template IGL_INLINE void arap_rhs( - const Eigen::MatrixXd & V, - const Eigen::MatrixXi & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, const int dim, const igl::ARAPEnergyType energy, - Eigen::SparseMatrix& K); + Eigen::SparseCompressedBase& K); } #ifndef IGL_STATIC_LIBRARY #include "arap_rhs.cpp" diff --git a/include/igl/average_onto_vertices.cpp b/include/igl/average_onto_vertices.cpp index a30854edb..599460570 100644 --- a/include/igl/average_onto_vertices.cpp +++ b/include/igl/average_onto_vertices.cpp @@ -7,11 +7,11 @@ // obtain one at http://mozilla.org/MPL/2.0/. #include "average_onto_vertices.h" -template +template IGL_INLINE void igl::average_onto_vertices(const Eigen::MatrixBase &V, const Eigen::MatrixBase &F, const Eigen::MatrixBase &S, - Eigen::MatrixBase &SV) + Eigen::PlainObjectBase &SV) { SV = DerivedS::Zero(V.rows(),S.cols()); Eigen::Matrix COUNT(V.rows()); diff --git a/include/igl/average_onto_vertices.h b/include/igl/average_onto_vertices.h index e7fca6238..2cfbee0de 100644 --- a/include/igl/average_onto_vertices.h +++ b/include/igl/average_onto_vertices.h @@ -1,31 +1,31 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2013 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_AVERAGE_ONTO_VERTICES_H #define IGL_AVERAGE_ONTO_VERTICES_H #include "igl_inline.h" #include -namespace igl +namespace igl { - // average_onto_vertices + // average_onto_vertices // Move a scalar field defined on faces to vertices by averaging // // Input: // V,F: mesh // S: scalar field defined on faces, Fx1 - // + // // Output: // SV: scalar field defined on vertices - template + template IGL_INLINE void average_onto_vertices(const Eigen::MatrixBase &V, const Eigen::MatrixBase &F, const Eigen::MatrixBase &S, - Eigen::MatrixBase &SV); + Eigen::PlainObjectBase &SV); } #ifndef IGL_STATIC_LIBRARY diff --git a/include/igl/barycenter.cpp b/include/igl/barycenter.cpp index dcee7cdee..47ae2feaa 100644 --- a/include/igl/barycenter.cpp +++ b/include/igl/barycenter.cpp @@ -56,4 +56,6 @@ template void igl::barycenter, Eigen::Mat template void igl::barycenter, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); template void igl::barycenter, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); template void igl::barycenter, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::barycenter, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::barycenter, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/bfs.cpp b/include/igl/bfs.cpp index 8ff51c050..076c8a40b 100644 --- a/include/igl/bfs.cpp +++ b/include/igl/bfs.cpp @@ -59,7 +59,7 @@ template < typename DType, typename PType> IGL_INLINE void igl::bfs( - const Eigen::SparseMatrix & A, + const Eigen::SparseCompressedBase & A, const size_t s, std::vector & D, std::vector & P) @@ -83,7 +83,7 @@ IGL_INLINE void igl::bfs( D.push_back(f); P[f] = p; seen[f] = true; - for(typename Eigen::SparseMatrix::InnerIterator it (A,f); it; ++it) + for(typename AType::InnerIterator it (A,f); it; ++it) { if(it.value()) Q.push({it.index(),f}); } diff --git a/include/igl/bfs.h b/include/igl/bfs.h index 6f49e93eb..e1c761b38 100644 --- a/include/igl/bfs.h +++ b/include/igl/bfs.h @@ -42,7 +42,7 @@ namespace igl typename DType, typename PType> IGL_INLINE void bfs( - const Eigen::SparseMatrix & A, + const Eigen::SparseCompressedBase & A, const size_t s, std::vector & D, std::vector & P); diff --git a/include/igl/bfs_orient.cpp b/include/igl/bfs_orient.cpp index 23dd93a49..2a8c6f083 100644 --- a/include/igl/bfs_orient.cpp +++ b/include/igl/bfs_orient.cpp @@ -12,13 +12,13 @@ template IGL_INLINE void igl::bfs_orient( - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & FF, Eigen::PlainObjectBase & C) { using namespace Eigen; using namespace std; - SparseMatrix A; + SparseMatrix A; orientable_patches(F,C,A); // number of faces @@ -30,7 +30,7 @@ IGL_INLINE void igl::bfs_orient( // Edge sets const int ES[3][2] = {{1,2},{2,0},{0,1}}; - if(&FF != &F) + if(((void*)&FF) != ((void*)&F)) { FF = F; } @@ -38,7 +38,7 @@ IGL_INLINE void igl::bfs_orient( #pragma omp parallel for for(int c = 0;c Q; + queue Q; // find first member of patch c for(int f = 0;f 0) { @@ -59,7 +59,7 @@ IGL_INLINE void igl::bfs_orient( } seen(f)++; // loop over neighbors of f - for(typename SparseMatrix::InnerIterator it (A,f); it; ++it) + for(typename SparseMatrix::InnerIterator it (A,f); it; ++it) { // might be some lingering zeros, and skip self-adjacency if(it.value() != 0 && it.row() != f) @@ -96,5 +96,5 @@ IGL_INLINE void igl::bfs_orient( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::bfs_orient, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::bfs_orient, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/bfs_orient.h b/include/igl/bfs_orient.h index b37f397d8..6c08592ca 100644 --- a/include/igl/bfs_orient.h +++ b/include/igl/bfs_orient.h @@ -25,10 +25,10 @@ namespace igl // template IGL_INLINE void bfs_orient( - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & FF, Eigen::PlainObjectBase & C); -}; +} #ifndef IGL_STATIC_LIBRARY # include "bfs_orient.cpp" #endif diff --git a/include/igl/biharmonic_coordinates.cpp b/include/igl/biharmonic_coordinates.cpp index 686ecd5e4..e3b3a3a6a 100644 --- a/include/igl/biharmonic_coordinates.cpp +++ b/include/igl/biharmonic_coordinates.cpp @@ -22,8 +22,8 @@ template < typename SType, typename DerivedW> IGL_INLINE bool igl::biharmonic_coordinates( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & T, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & T, const std::vector > & S, Eigen::PlainObjectBase & W) { @@ -36,32 +36,36 @@ template < typename SType, typename DerivedW> IGL_INLINE bool igl::biharmonic_coordinates( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & T, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & T, const std::vector > & S, const int k, Eigen::PlainObjectBase & W) { using namespace Eigen; using namespace std; + + typedef typename DerivedV::Scalar Scalar; + typedef typename DerivedT::Scalar Integer; + // This is not the most efficient way to build A, but follows "Linear // Subspace Design for Real-Time Shape Deformation" [Wang et al. 2015]. - SparseMatrix A; + SparseMatrix A; { - DiagonalMatrix Minv; - SparseMatrix L,K; + DiagonalMatrix Minv; + SparseMatrix L, K; Array C; { Array I; on_boundary(T,I,C); } -#ifdef false +#ifdef false // Version described in paper is "wrong" // http://www.cs.toronto.edu/~jacobson/images/error-in-linear-subspace-design-for-real-time-shape-deformation-2017-wang-et-al.pdf - SparseMatrix N,Z,M; + SparseMatrix N, Z, M; normal_derivative(V,T,N); { - std::vector >ZIJV; + std::vector> ZIJV; for(int t =0;t)M.diagonal()).array().abs().maxCoeff(); Minv = - ((VectorXd)M.diagonal().array().inverse()).asDiagonal(); + ((Matrix)M.diagonal().array().inverse()).asDiagonal(); #else - Eigen::SparseMatrix M; - Eigen::MatrixXi E; - Eigen::VectorXi EMAP; + Eigen::SparseMatrix M; + Eigen::Matrix E; + Eigen::Matrix EMAP; crouzeix_raviart_massmatrix(V,T,M,E,EMAP); crouzeix_raviart_cotmatrix(V,T,E,EMAP,L); // Ad #E by #V facet-vertex incidence matrix - Eigen::SparseMatrix Ad(E.rows(),V.rows()); + Eigen::SparseMatrix Ad(E.rows(),V.rows()); { - std::vector > AIJV(E.size()); + std::vector> AIJV(E.size()); for(int e = 0;e(e,E(e,c),1); + AIJV[e + c * E.rows()] = Eigen::Triplet(e, E(e, c), 1); } } Ad.setFromTriplets(AIJV.begin(),AIJV.end()); } // Degrees - Eigen::VectorXd De; + Eigen::Matrix De; sum(Ad,2,De); - Eigen::DiagonalMatrix De_diag = + Eigen::DiagonalMatrix De_diag = De.array().inverse().matrix().asDiagonal(); K = L*(De_diag*Ad); // normalize - M /= ((VectorXd)M.diagonal()).array().abs().maxCoeff(); - Minv = ((VectorXd)M.diagonal().array().inverse()).asDiagonal(); + M /= ((Matrix)M.diagonal()).array().abs().maxCoeff(); + Minv = ((Matrix)M.diagonal().array().inverse()).asDiagonal(); // kill boundary edges for(int f = 0;f J = Matrix::Zero(mp+mr,mp+r*(dim+1)); + Matrix b(mp+mr); + Matrix H(mp+r*(dim+1),dim); { int v = 0; int c = 0; @@ -194,10 +198,10 @@ IGL_INLINE bool igl::biharmonic_coordinates( // minimize ½ W' A W' // subject to W(b,:) = J return min_quad_with_fixed( - A,VectorXd::Zero(A.rows()).eval(),b,J,SparseMatrix(),VectorXd(),true,W); + A,Matrix::Zero(A.rows()).eval(),b,J,SparseMatrix(),Matrix(),true,W); } #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template bool igl::biharmonic_coordinates, Eigen::Matrix, int, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, std::vector >, std::allocator > > > const&, int, Eigen::PlainObjectBase >&); +template bool igl::biharmonic_coordinates, Eigen::Matrix, int, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::vector >, std::allocator > > > const&, int, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/biharmonic_coordinates.h b/include/igl/biharmonic_coordinates.h index 26f67329a..583eee386 100644 --- a/include/igl/biharmonic_coordinates.h +++ b/include/igl/biharmonic_coordinates.h @@ -66,8 +66,8 @@ namespace igl typename SType, typename DerivedW> IGL_INLINE bool biharmonic_coordinates( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & T, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & T, const std::vector > & S, Eigen::PlainObjectBase & W); // k 2-->biharmonic, 3-->triharmonic @@ -77,8 +77,8 @@ namespace igl typename SType, typename DerivedW> IGL_INLINE bool biharmonic_coordinates( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & T, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & T, const std::vector > & S, const int k, Eigen::PlainObjectBase & W); diff --git a/include/igl/bijective_composite_harmonic_mapping.cpp b/include/igl/bijective_composite_harmonic_mapping.cpp index 517109c04..733618219 100644 --- a/include/igl/bijective_composite_harmonic_mapping.cpp +++ b/include/igl/bijective_composite_harmonic_mapping.cpp @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2017 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "bijective_composite_harmonic_mapping.h" @@ -51,11 +51,11 @@ IGL_INLINE bool igl::bijective_composite_harmonic_mapping( assert(F.cols() == 3 && "F should contain triangles"); int tries = 0; int nsteps = min_steps; - Derivedbc bc0; + Eigen::Matrix bc0; slice(V,b,1,bc0); // It's difficult to check for flips "robustly" in the sense that the input - // mesh might not have positive/consistent sign to begin with. + // mesh might not have positive/consistent sign to begin with. while(nsteps<=max_steps) { @@ -71,7 +71,7 @@ IGL_INLINE bool igl::bijective_composite_harmonic_mapping( // of the boundary conditions. Something like "Homotopic Morphing of // Planar Curves" [Dym et al. 2015] but also handling multiple connected // components. - Derivedbc bct = bc0 + t*(bc - bc0); + Eigen::Matrix bct = bc0 + t * (bc - bc0); // Compute dsicrete harmonic map using metric of previous step for(int iter = 0;iter(U), F, b, bct, 1, U); igl::slice(U,b,1,bct); nans = (U.array() != U.array()).count(); if(test_for_flips) diff --git a/include/igl/bone_parents.cpp b/include/igl/bone_parents.cpp index d5cd6ddfa..8434683e7 100644 --- a/include/igl/bone_parents.cpp +++ b/include/igl/bone_parents.cpp @@ -9,7 +9,7 @@ template IGL_INLINE void igl::bone_parents( - const Eigen::PlainObjectBase& BE, + const Eigen::MatrixBase& BE, Eigen::PlainObjectBase& P) { P.resize(BE.rows(),1); @@ -28,5 +28,5 @@ IGL_INLINE void igl::bone_parents( } #ifdef IGL_STATIC_LIBRARY -template void igl::bone_parents, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); +template void igl::bone_parents, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/bone_parents.h b/include/igl/bone_parents.h index e0091cdfc..ccad3f919 100644 --- a/include/igl/bone_parents.h +++ b/include/igl/bone_parents.h @@ -20,7 +20,7 @@ namespace igl // template IGL_INLINE void bone_parents( - const Eigen::PlainObjectBase& BE, + const Eigen::MatrixBase& BE, Eigen::PlainObjectBase& P); } diff --git a/include/igl/boundary_loop.cpp b/include/igl/boundary_loop.cpp index 243078e09..537a23d1c 100755 --- a/include/igl/boundary_loop.cpp +++ b/include/igl/boundary_loop.cpp @@ -24,12 +24,12 @@ IGL_INLINE void igl::boundary_loop( return; VectorXd Vdummy(F.maxCoeff()+1,1); - DerivedF TT,TTi; + Eigen::Matrix TT,TTi; vector > VF, VFi; triangle_triangle_adjacency(F,TT,TTi); vertex_triangle_adjacency(Vdummy,F,VF,VFi); - vector unvisited = is_border_vertex(Vdummy,F); + vector unvisited = is_border_vertex(F); set unseen; for (size_t i = 0; i < unvisited.size(); ++i) { @@ -142,7 +142,7 @@ IGL_INLINE void igl::boundary_loop( vector Lvec; boundary_loop(F,Lvec); - L.resize(Lvec.size()); + L.resize(Lvec.size(), 1); for (size_t i = 0; i < Lvec.size(); ++i) L(i) = Lvec[i]; } diff --git a/include/igl/bounding_box.cpp b/include/igl/bounding_box.cpp index e740b058f..4777d2511 100644 --- a/include/igl/bounding_box.cpp +++ b/include/igl/bounding_box.cpp @@ -30,7 +30,7 @@ IGL_INLINE void igl::bounding_box( const auto & minV = V.colwise().minCoeff().array()-pad; const auto & maxV = V.colwise().maxCoeff().array()+pad; // 2^n vertices - BV.resize((1< combos = @@ -93,6 +93,8 @@ IGL_INLINE void igl::bounding_box( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template void igl::bounding_box, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh template void igl::bounding_box, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template void igl::bounding_box, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::Matrix::Scalar, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); diff --git a/include/igl/bounding_box_diagonal.h b/include/igl/bounding_box_diagonal.h index d89025bd5..f11821d0d 100644 --- a/include/igl/bounding_box_diagonal.h +++ b/include/igl/bounding_box_diagonal.h @@ -15,8 +15,7 @@ namespace igl // box // // Inputs: - // V #V by 3 list of vertex positions - // F #F by 3 list of triangle indices into V + // V #V by 3 list of vertex/point positions // Returns length of bounding box diagonal IGL_INLINE double bounding_box_diagonal( const Eigen::MatrixXd & V); } diff --git a/include/igl/cat.cpp b/include/igl/cat.cpp index 08c9f616b..c5bc20671 100644 --- a/include/igl/cat.cpp +++ b/include/igl/cat.cpp @@ -313,6 +313,8 @@ IGL_INLINE void igl::cat(const int dim, const std::vector & A, Eigen::PlainOb #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template void igl::cat, Eigen::Matrix >(int, std::vector, std::allocator > > const&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh template Eigen::Matrix igl::cat >(int, Eigen::Matrix const&, Eigen::Matrix const&); // generated by autoexplicit.sh template Eigen::SparseMatrix igl::cat >(int, Eigen::SparseMatrix const&, Eigen::SparseMatrix const&); @@ -333,4 +335,6 @@ template void igl::cat, Eigen::Matrix, Eigen::Matrix >(int, std::vector, std::allocator > > const&, Eigen::PlainObjectBase >&); template void igl::cat, Eigen::Matrix >(int, std::vector, std::allocator > > const&, Eigen::PlainObjectBase >&); template void igl::cat, Eigen::Matrix >(int, std::vector, std::allocator > > const&, Eigen::PlainObjectBase >&); +template void igl::cat, Eigen::Matrix >(int, std::vector, std::allocator > > const&, Eigen::PlainObjectBase >&); +template void igl::cat, Eigen::Matrix >(int, std::vector, std::allocator > > const&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/centroid.cpp b/include/igl/centroid.cpp index 7587aeddd..588f0665e 100644 --- a/include/igl/centroid.cpp +++ b/include/igl/centroid.cpp @@ -62,6 +62,10 @@ IGL_INLINE void igl::centroid( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template void igl::centroid, Eigen::Matrix, Eigen::Matrix, float>(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, float&); +// generated by autoexplicit.sh +template void igl::centroid, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh template void igl::centroid, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); template void igl::centroid, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); template void igl::centroid, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); diff --git a/include/igl/circumradius.cpp b/include/igl/circumradius.cpp index 34424eae2..88fcbf39a 100644 --- a/include/igl/circumradius.cpp +++ b/include/igl/circumradius.cpp @@ -13,8 +13,8 @@ template < typename DerivedF, typename DerivedR> IGL_INLINE void igl::circumradius( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & R) { Eigen::Matrix l; @@ -24,3 +24,7 @@ IGL_INLINE void igl::circumradius( // use formula: R=abc/(4*area) to compute the circum radius R = l.col(0).array() * l.col(1).array() * l.col(2).array() / (2.0*A.array()); } + +#ifdef IGL_STATIC_LIBRARY +template void igl::circumradius, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +#endif diff --git a/include/igl/circumradius.h b/include/igl/circumradius.h index 12592ee3f..e8187cb04 100644 --- a/include/igl/circumradius.h +++ b/include/igl/circumradius.h @@ -17,15 +17,15 @@ namespace igl // V #V by dim list of mesh vertex positions // F #F by 3 list of triangle indices into V // Outputs: - // R #F list of circumradii + // R #F list of circumradius // template < typename DerivedV, typename DerivedF, typename DerivedR> IGL_INLINE void circumradius( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & R); } #ifndef IGL_STATIC_LIBRARY diff --git a/include/igl/colon.cpp b/include/igl/colon.cpp index 0bc2112f6..d7a5c8497 100644 --- a/include/igl/colon.cpp +++ b/include/igl/colon.cpp @@ -17,7 +17,7 @@ IGL_INLINE void igl::colon( const H hi, Eigen::Matrix & I) { - const int size = ((hi-low)/step)+1; + const H size = ((hi-low)/step)+1; I = igl::LinSpaced >(size,low,low+step*(size-1)); } @@ -43,26 +43,27 @@ IGL_INLINE Eigen::Matrix igl::colon( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh -template Eigen::Matrix igl::colon(int, int); -template Eigen::Matrix igl::colon(int,long); -template Eigen::Matrix igl::colon(int,long long int); +template Eigen::Matrix igl::colon(int, int); +template Eigen::Matrix igl::colon(int, long); +template Eigen::Matrix igl::colon(int, long long int); template Eigen::Matrix igl::colon(double, double); +template void igl::colon(int, long, Eigen::Matrix &); // generated by autoexplicit.sh -template void igl::colon(int, long, int, Eigen::Matrix&); -template void igl::colon(int, int, long, Eigen::Matrix&); -template void igl::colon(int, long, Eigen::Matrix&); -template void igl::colon(int, int, Eigen::Matrix&); -template void igl::colon(int,long long int,Eigen::Matrix &); -template void igl::colon(int, int, int, Eigen::Matrix&); -template void igl::colon(int, long, Eigen::Matrix&); -template void igl::colon(int, double, double, Eigen::Matrix&); -template void igl::colon(double, double, Eigen::Matrix&); -template void igl::colon(double, double, double, Eigen::Matrix&); -template void igl::colon(int, int, Eigen::Matrix&); -template void igl::colon(int, long, Eigen::Matrix&); +template void igl::colon(int, long, int, Eigen::Matrix &); +template void igl::colon(int, int, long, Eigen::Matrix &); +template void igl::colon(int, long, Eigen::Matrix &); +template void igl::colon(int, int, Eigen::Matrix &); +template void igl::colon(int, long long int, Eigen::Matrix &); +template void igl::colon(int, int, int, Eigen::Matrix &); +template void igl::colon(int, long, Eigen::Matrix &); +template void igl::colon(int, double, double, Eigen::Matrix &); +template void igl::colon(double, double, Eigen::Matrix &); +template void igl::colon(double, double, double, Eigen::Matrix &); +template void igl::colon(int, int, Eigen::Matrix &); +template void igl::colon(int, int, Eigen::Matrix &); #ifdef WIN32 -template void igl::colon(int, long long, class Eigen::Matrix &); +template void igl::colon(int, __int64, class Eigen::Matrix &); +template void igl::colon(int, long long, class Eigen::Matrix &); template void igl::colon(int, __int64, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> &); -template void igl::colon(int,__int64,class Eigen::Matrix &); -#endif #endif +#endif \ No newline at end of file diff --git a/include/igl/colormap.cpp b/include/igl/colormap.cpp index 560cbe6c0..ff9e433e4 100644 --- a/include/igl/colormap.cpp +++ b/include/igl/colormap.cpp @@ -6,7 +6,6 @@ // v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "colormap.h" -#include "jet.h" #include // One of the new matplotlib colormaps by Nathaniel J.Smith, Stefan van der Walt, and (in the case of viridis) Eric Firing. @@ -14,6 +13,266 @@ namespace igl { + +static double turbo_cm[256][3] = { + {0.18995,0.07176,0.23217}, + {0.19483,0.08339,0.26149}, + {0.19956,0.09498,0.29024}, + {0.20415,0.10652,0.31844}, + {0.20860,0.11802,0.34607}, + {0.21291,0.12947,0.37314}, + {0.21708,0.14087,0.39964}, + {0.22111,0.15223,0.42558}, + {0.22500,0.16354,0.45096}, + {0.22875,0.17481,0.47578}, + {0.23236,0.18603,0.50004}, + {0.23582,0.19720,0.52373}, + {0.23915,0.20833,0.54686}, + {0.24234,0.21941,0.56942}, + {0.24539,0.23044,0.59142}, + {0.24830,0.24143,0.61286}, + {0.25107,0.25237,0.63374}, + {0.25369,0.26327,0.65406}, + {0.25618,0.27412,0.67381}, + {0.25853,0.28492,0.69300}, + {0.26074,0.29568,0.71162}, + {0.26280,0.30639,0.72968}, + {0.26473,0.31706,0.74718}, + {0.26652,0.32768,0.76412}, + {0.26816,0.33825,0.78050}, + {0.26967,0.34878,0.79631}, + {0.27103,0.35926,0.81156}, + {0.27226,0.36970,0.82624}, + {0.27334,0.38008,0.84037}, + {0.27429,0.39043,0.85393}, + {0.27509,0.40072,0.86692}, + {0.27576,0.41097,0.87936}, + {0.27628,0.42118,0.89123}, + {0.27667,0.43134,0.90254}, + {0.27691,0.44145,0.91328}, + {0.27701,0.45152,0.92347}, + {0.27698,0.46153,0.93309}, + {0.27680,0.47151,0.94214}, + {0.27648,0.48144,0.95064}, + {0.27603,0.49132,0.95857}, + {0.27543,0.50115,0.96594}, + {0.27469,0.51094,0.97275}, + {0.27381,0.52069,0.97899}, + {0.27273,0.53040,0.98461}, + {0.27106,0.54015,0.98930}, + {0.26878,0.54995,0.99303}, + {0.26592,0.55979,0.99583}, + {0.26252,0.56967,0.99773}, + {0.25862,0.57958,0.99876}, + {0.25425,0.58950,0.99896}, + {0.24946,0.59943,0.99835}, + {0.24427,0.60937,0.99697}, + {0.23874,0.61931,0.99485}, + {0.23288,0.62923,0.99202}, + {0.22676,0.63913,0.98851}, + {0.22039,0.64901,0.98436}, + {0.21382,0.65886,0.97959}, + {0.20708,0.66866,0.97423}, + {0.20021,0.67842,0.96833}, + {0.19326,0.68812,0.96190}, + {0.18625,0.69775,0.95498}, + {0.17923,0.70732,0.94761}, + {0.17223,0.71680,0.93981}, + {0.16529,0.72620,0.93161}, + {0.15844,0.73551,0.92305}, + {0.15173,0.74472,0.91416}, + {0.14519,0.75381,0.90496}, + {0.13886,0.76279,0.89550}, + {0.13278,0.77165,0.88580}, + {0.12698,0.78037,0.87590}, + {0.12151,0.78896,0.86581}, + {0.11639,0.79740,0.85559}, + {0.11167,0.80569,0.84525}, + {0.10738,0.81381,0.83484}, + {0.10357,0.82177,0.82437}, + {0.10026,0.82955,0.81389}, + {0.09750,0.83714,0.80342}, + {0.09532,0.84455,0.79299}, + {0.09377,0.85175,0.78264}, + {0.09287,0.85875,0.77240}, + {0.09267,0.86554,0.76230}, + {0.09320,0.87211,0.75237}, + {0.09451,0.87844,0.74265}, + {0.09662,0.88454,0.73316}, + {0.09958,0.89040,0.72393}, + {0.10342,0.89600,0.71500}, + {0.10815,0.90142,0.70599}, + {0.11374,0.90673,0.69651}, + {0.12014,0.91193,0.68660}, + {0.12733,0.91701,0.67627}, + {0.13526,0.92197,0.66556}, + {0.14391,0.92680,0.65448}, + {0.15323,0.93151,0.64308}, + {0.16319,0.93609,0.63137}, + {0.17377,0.94053,0.61938}, + {0.18491,0.94484,0.60713}, + {0.19659,0.94901,0.59466}, + {0.20877,0.95304,0.58199}, + {0.22142,0.95692,0.56914}, + {0.23449,0.96065,0.55614}, + {0.24797,0.96423,0.54303}, + {0.26180,0.96765,0.52981}, + {0.27597,0.97092,0.51653}, + {0.29042,0.97403,0.50321}, + {0.30513,0.97697,0.48987}, + {0.32006,0.97974,0.47654}, + {0.33517,0.98234,0.46325}, + {0.35043,0.98477,0.45002}, + {0.36581,0.98702,0.43688}, + {0.38127,0.98909,0.42386}, + {0.39678,0.99098,0.41098}, + {0.41229,0.99268,0.39826}, + {0.42778,0.99419,0.38575}, + {0.44321,0.99551,0.37345}, + {0.45854,0.99663,0.36140}, + {0.47375,0.99755,0.34963}, + {0.48879,0.99828,0.33816}, + {0.50362,0.99879,0.32701}, + {0.51822,0.99910,0.31622}, + {0.53255,0.99919,0.30581}, + {0.54658,0.99907,0.29581}, + {0.56026,0.99873,0.28623}, + {0.57357,0.99817,0.27712}, + {0.58646,0.99739,0.26849}, + {0.59891,0.99638,0.26038}, + {0.61088,0.99514,0.25280}, + {0.62233,0.99366,0.24579}, + {0.63323,0.99195,0.23937}, + {0.64362,0.98999,0.23356}, + {0.65394,0.98775,0.22835}, + {0.66428,0.98524,0.22370}, + {0.67462,0.98246,0.21960}, + {0.68494,0.97941,0.21602}, + {0.69525,0.97610,0.21294}, + {0.70553,0.97255,0.21032}, + {0.71577,0.96875,0.20815}, + {0.72596,0.96470,0.20640}, + {0.73610,0.96043,0.20504}, + {0.74617,0.95593,0.20406}, + {0.75617,0.95121,0.20343}, + {0.76608,0.94627,0.20311}, + {0.77591,0.94113,0.20310}, + {0.78563,0.93579,0.20336}, + {0.79524,0.93025,0.20386}, + {0.80473,0.92452,0.20459}, + {0.81410,0.91861,0.20552}, + {0.82333,0.91253,0.20663}, + {0.83241,0.90627,0.20788}, + {0.84133,0.89986,0.20926}, + {0.85010,0.89328,0.21074}, + {0.85868,0.88655,0.21230}, + {0.86709,0.87968,0.21391}, + {0.87530,0.87267,0.21555}, + {0.88331,0.86553,0.21719}, + {0.89112,0.85826,0.21880}, + {0.89870,0.85087,0.22038}, + {0.90605,0.84337,0.22188}, + {0.91317,0.83576,0.22328}, + {0.92004,0.82806,0.22456}, + {0.92666,0.82025,0.22570}, + {0.93301,0.81236,0.22667}, + {0.93909,0.80439,0.22744}, + {0.94489,0.79634,0.22800}, + {0.95039,0.78823,0.22831}, + {0.95560,0.78005,0.22836}, + {0.96049,0.77181,0.22811}, + {0.96507,0.76352,0.22754}, + {0.96931,0.75519,0.22663}, + {0.97323,0.74682,0.22536}, + {0.97679,0.73842,0.22369}, + {0.98000,0.73000,0.22161}, + {0.98289,0.72140,0.21918}, + {0.98549,0.71250,0.21650}, + {0.98781,0.70330,0.21358}, + {0.98986,0.69382,0.21043}, + {0.99163,0.68408,0.20706}, + {0.99314,0.67408,0.20348}, + {0.99438,0.66386,0.19971}, + {0.99535,0.65341,0.19577}, + {0.99607,0.64277,0.19165}, + {0.99654,0.63193,0.18738}, + {0.99675,0.62093,0.18297}, + {0.99672,0.60977,0.17842}, + {0.99644,0.59846,0.17376}, + {0.99593,0.58703,0.16899}, + {0.99517,0.57549,0.16412}, + {0.99419,0.56386,0.15918}, + {0.99297,0.55214,0.15417}, + {0.99153,0.54036,0.14910}, + {0.98987,0.52854,0.14398}, + {0.98799,0.51667,0.13883}, + {0.98590,0.50479,0.13367}, + {0.98360,0.49291,0.12849}, + {0.98108,0.48104,0.12332}, + {0.97837,0.46920,0.11817}, + {0.97545,0.45740,0.11305}, + {0.97234,0.44565,0.10797}, + {0.96904,0.43399,0.10294}, + {0.96555,0.42241,0.09798}, + {0.96187,0.41093,0.09310}, + {0.95801,0.39958,0.08831}, + {0.95398,0.38836,0.08362}, + {0.94977,0.37729,0.07905}, + {0.94538,0.36638,0.07461}, + {0.94084,0.35566,0.07031}, + {0.93612,0.34513,0.06616}, + {0.93125,0.33482,0.06218}, + {0.92623,0.32473,0.05837}, + {0.92105,0.31489,0.05475}, + {0.91572,0.30530,0.05134}, + {0.91024,0.29599,0.04814}, + {0.90463,0.28696,0.04516}, + {0.89888,0.27824,0.04243}, + {0.89298,0.26981,0.03993}, + {0.88691,0.26152,0.03753}, + {0.88066,0.25334,0.03521}, + {0.87422,0.24526,0.03297}, + {0.86760,0.23730,0.03082}, + {0.86079,0.22945,0.02875}, + {0.85380,0.22170,0.02677}, + {0.84662,0.21407,0.02487}, + {0.83926,0.20654,0.02305}, + {0.83172,0.19912,0.02131}, + {0.82399,0.19182,0.01966}, + {0.81608,0.18462,0.01809}, + {0.80799,0.17753,0.01660}, + {0.79971,0.17055,0.01520}, + {0.79125,0.16368,0.01387}, + {0.78260,0.15693,0.01264}, + {0.77377,0.15028,0.01148}, + {0.76476,0.14374,0.01041}, + {0.75556,0.13731,0.00942}, + {0.74617,0.13098,0.00851}, + {0.73661,0.12477,0.00769}, + {0.72686,0.11867,0.00695}, + {0.71692,0.11268,0.00629}, + {0.70680,0.10680,0.00571}, + {0.69650,0.10102,0.00522}, + {0.68602,0.09536,0.00481}, + {0.67535,0.08980,0.00449}, + {0.66449,0.08436,0.00424}, + {0.65345,0.07902,0.00408}, + {0.64223,0.07380,0.00401}, + {0.63082,0.06868,0.00401}, + {0.61923,0.06367,0.00410}, + {0.60746,0.05878,0.00427}, + {0.59550,0.05399,0.00453}, + {0.58336,0.04931,0.00486}, + {0.57103,0.04474,0.00529}, + {0.55852,0.04028,0.00579}, + {0.54583,0.03593,0.00638}, + {0.53295,0.03169,0.00705}, + {0.51989,0.02756,0.00780}, + {0.50664,0.02354,0.00863}, + {0.49321,0.01963,0.00955}, + {0.47960,0.01583,0.01055} +}; + static double inferno_cm[256][3] = { { 0.001462, 0.000466, 0.013866 }, { 0.002267, 0.001270, 0.018570 }, @@ -1320,13 +1579,16 @@ template IGL_INLINE void igl::colormap( const ColorMapType cm, const T x_in, T & r, T & g, T & b) { - switch (cm) + switch (cm) { case COLOR_MAP_TYPE_INFERNO: colormap(inferno_cm, x_in, r, g, b); break; case COLOR_MAP_TYPE_JET: - jet(x_in, r, g, b); + // jet is bad so we use turbo instead + // https://ai.googleblog.com/2019/08/turbo-improved-rainbow-colormap-for.html + case COLOR_MAP_TYPE_TURBO: + colormap(turbo_cm, x_in, r, g, b); break; case COLOR_MAP_TYPE_MAGMA: colormap(magma_cm, x_in, r, g, b); @@ -1340,7 +1602,7 @@ IGL_INLINE void igl::colormap( case COLOR_MAP_TYPE_VIRIDIS: colormap(viridis_cm, x_in, r, g, b); break; - default: + default: throw std::invalid_argument("igl::colormap(): Selected colormap is unsupported!"); break; } @@ -1431,4 +1693,5 @@ template void igl::colormap, Eigen::Matri template void igl::colormap, Eigen::Matrix >(igl::ColorMapType, Eigen::MatrixBase > const&, bool, Eigen::PlainObjectBase >&); template void igl::colormap, Eigen::Matrix >(igl::ColorMapType, Eigen::MatrixBase > const&, bool, Eigen::PlainObjectBase >&); +template void igl::colormap(igl::ColorMapType, float, float&, float&, float&); #endif diff --git a/include/igl/colormap.h b/include/igl/colormap.h index 1d93d73b1..9ec1aa876 100644 --- a/include/igl/colormap.h +++ b/include/igl/colormap.h @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2017 Joe Graus , Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_COLORMAP_H @@ -22,7 +22,8 @@ namespace igl { COLOR_MAP_TYPE_PARULA = 3, COLOR_MAP_TYPE_PLASMA = 4, COLOR_MAP_TYPE_VIRIDIS = 5, - NUM_COLOR_MAP_TYPES = 6 + COLOR_MAP_TYPE_TURBO = 6, + NUM_COLOR_MAP_TYPES = 7 }; // Comput [r,g,b] values of the selected colormap for // a given factor f between 0 and 1 diff --git a/include/igl/comb_cross_field.cpp b/include/igl/comb_cross_field.cpp index 8feb6e0f1..f094ed43c 100644 --- a/include/igl/comb_cross_field.cpp +++ b/include/igl/comb_cross_field.cpp @@ -23,10 +23,10 @@ namespace igl { { public: - const Eigen::PlainObjectBase &V; - const Eigen::PlainObjectBase &F; - const Eigen::PlainObjectBase &PD1; - const Eigen::PlainObjectBase &PD2; + const Eigen::MatrixBase &V; + const Eigen::MatrixBase &F; + const Eigen::MatrixBase &PD1; + const Eigen::MatrixBase &PD2; DerivedV N; private: @@ -61,10 +61,10 @@ namespace igl { public: - inline Comb(const Eigen::PlainObjectBase &_V, - const Eigen::PlainObjectBase &_F, - const Eigen::PlainObjectBase &_PD1, - const Eigen::PlainObjectBase &_PD2 + inline Comb(const Eigen::MatrixBase &_V, + const Eigen::MatrixBase &_F, + const Eigen::MatrixBase &_PD1, + const Eigen::MatrixBase &_PD2 ): V(_V), F(_F), @@ -137,10 +137,10 @@ namespace igl { }; } template -IGL_INLINE void igl::comb_cross_field(const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, - const Eigen::PlainObjectBase &PD1, - const Eigen::PlainObjectBase &PD2, +IGL_INLINE void igl::comb_cross_field(const Eigen::MatrixBase &V, + const Eigen::MatrixBase &F, + const Eigen::MatrixBase &PD1, + const Eigen::MatrixBase &PD2, Eigen::PlainObjectBase &PD1out, Eigen::PlainObjectBase &PD2out) { @@ -150,6 +150,6 @@ IGL_INLINE void igl::comb_cross_field(const Eigen::PlainObjectBase &V, #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::comb_cross_field, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::comb_cross_field, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::comb_cross_field, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::comb_cross_field, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/comb_cross_field.h b/include/igl/comb_cross_field.h index fa3b57648..0cbacb7ab 100644 --- a/include/igl/comb_cross_field.h +++ b/include/igl/comb_cross_field.h @@ -27,10 +27,10 @@ namespace igl template - IGL_INLINE void comb_cross_field(const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, - const Eigen::PlainObjectBase &PD1in, - const Eigen::PlainObjectBase &PD2in, + IGL_INLINE void comb_cross_field(const Eigen::MatrixBase &V, + const Eigen::MatrixBase &F, + const Eigen::MatrixBase &PD1in, + const Eigen::MatrixBase &PD2in, Eigen::PlainObjectBase &PD1out, Eigen::PlainObjectBase &PD2out); } diff --git a/include/igl/comb_frame_field.cpp b/include/igl/comb_frame_field.cpp index d1fdb6bd7..85672c303 100644 --- a/include/igl/comb_frame_field.cpp +++ b/include/igl/comb_frame_field.cpp @@ -16,12 +16,12 @@ #include "PI.h" template -IGL_INLINE void igl::comb_frame_field(const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, - const Eigen::PlainObjectBase &PD1, - const Eigen::PlainObjectBase &PD2, - const Eigen::PlainObjectBase &BIS1_combed, - const Eigen::PlainObjectBase &BIS2_combed, +IGL_INLINE void igl::comb_frame_field(const Eigen::MatrixBase &V, + const Eigen::MatrixBase &F, + const Eigen::MatrixBase &PD1, + const Eigen::MatrixBase &PD2, + const Eigen::MatrixBase &BIS1_combed, + const Eigen::MatrixBase &BIS2_combed, Eigen::PlainObjectBase &PD1_combed, Eigen::PlainObjectBase &PD2_combed) { @@ -73,6 +73,6 @@ IGL_INLINE void igl::comb_frame_field(const Eigen::PlainObjectBase &V, #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::comb_frame_field, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::comb_frame_field, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::comb_frame_field, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::comb_frame_field, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/comb_frame_field.h b/include/igl/comb_frame_field.h index 4691dc19d..ab5a9e7e9 100644 --- a/include/igl/comb_frame_field.h +++ b/include/igl/comb_frame_field.h @@ -31,12 +31,12 @@ namespace igl template - IGL_INLINE void comb_frame_field(const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, - const Eigen::PlainObjectBase &PD1, - const Eigen::PlainObjectBase &PD2, - const Eigen::PlainObjectBase &BIS1_combed, - const Eigen::PlainObjectBase &BIS2_combed, + IGL_INLINE void comb_frame_field(const Eigen::MatrixBase &V, + const Eigen::MatrixBase &F, + const Eigen::MatrixBase &PD1, + const Eigen::MatrixBase &PD2, + const Eigen::MatrixBase &BIS1_combed, + const Eigen::MatrixBase &BIS2_combed, Eigen::PlainObjectBase &PD1_combed, Eigen::PlainObjectBase &PD2_combed); } diff --git a/include/igl/comb_line_field.cpp b/include/igl/comb_line_field.cpp index 66899319a..06a2a6406 100644 --- a/include/igl/comb_line_field.cpp +++ b/include/igl/comb_line_field.cpp @@ -22,9 +22,9 @@ class CombLine { public: - const Eigen::PlainObjectBase &V; - const Eigen::PlainObjectBase &F; - const Eigen::PlainObjectBase &PD1; + const Eigen::MatrixBase &V; + const Eigen::MatrixBase &F; + const Eigen::MatrixBase &PD1; DerivedV N; private: @@ -57,9 +57,9 @@ private: public: - inline CombLine(const Eigen::PlainObjectBase &_V, - const Eigen::PlainObjectBase &_F, - const Eigen::PlainObjectBase &_PD1): + inline CombLine(const Eigen::MatrixBase &_V, + const Eigen::MatrixBase &_F, + const Eigen::MatrixBase &_PD1): V(_V), F(_F), PD1(_PD1) @@ -118,9 +118,9 @@ public: } template -IGL_INLINE void igl::comb_line_field(const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, - const Eigen::PlainObjectBase &PD1, +IGL_INLINE void igl::comb_line_field(const Eigen::MatrixBase &V, + const Eigen::MatrixBase &F, + const Eigen::MatrixBase &PD1, Eigen::PlainObjectBase &PD1out) { igl::CombLine cmb(V, F, PD1); diff --git a/include/igl/comb_line_field.h b/include/igl/comb_line_field.h index e2f22b37f..6ec892016 100644 --- a/include/igl/comb_line_field.h +++ b/include/igl/comb_line_field.h @@ -19,17 +19,14 @@ namespace igl // V #V by 3 eigen Matrix of mesh vertex 3D positions // F #F by 4 eigen Matrix of face (quad) indices // PD1in #F by 3 eigen Matrix of the first per face cross field vector - // PD2in #F by 3 eigen Matrix of the second per face cross field vector // Output: // PD1out #F by 3 eigen Matrix of the first combed cross field vector - // PD2out #F by 3 eigen Matrix of the second combed cross field vector - // template - IGL_INLINE void comb_line_field(const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, - const Eigen::PlainObjectBase &PD1in, + IGL_INLINE void comb_line_field(const Eigen::MatrixBase &V, + const Eigen::MatrixBase &F, + const Eigen::MatrixBase &PD1in, Eigen::PlainObjectBase &PD1out); } #ifndef IGL_STATIC_LIBRARY diff --git a/include/igl/combine.cpp b/include/igl/combine.cpp index 4cbc3d076..d77bf3f54 100644 --- a/include/igl/combine.cpp +++ b/include/igl/combine.cpp @@ -88,11 +88,12 @@ IGL_INLINE void igl::combine( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation +// generated by autoexplicit.sh +template void igl::combine, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(std::vector, std::allocator > > const&, std::vector, std::allocator > > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::combine, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(std::vector, std::allocator > > const&, std::vector, std::allocator > > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::combine, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(std::vector, std::allocator > > const&, std::vector, std::allocator > > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::combine, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(std::vector, std::allocator > > const&, std::vector, std::allocator > > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #ifdef WIN32 template void igl::combine, Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix >(class std::vector,class std::allocator > > const &,class std::vector,class std::allocator > > const &,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &); -template void igl::combine, Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix >(class std::vector,class std::allocator > > const &,class std::vector,class std::allocator > > const &,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &); #endif #endif diff --git a/include/igl/compute_frame_field_bisectors.cpp b/include/igl/compute_frame_field_bisectors.cpp index 74b284d48..ceca66e5d 100644 --- a/include/igl/compute_frame_field_bisectors.cpp +++ b/include/igl/compute_frame_field_bisectors.cpp @@ -17,12 +17,12 @@ template IGL_INLINE void igl::compute_frame_field_bisectors( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, - const Eigen::PlainObjectBase& B1, - const Eigen::PlainObjectBase& B2, - const Eigen::PlainObjectBase& PD1, - const Eigen::PlainObjectBase& PD2, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& B1, + const Eigen::MatrixBase& B2, + const Eigen::MatrixBase& PD1, + const Eigen::MatrixBase& PD2, Eigen::PlainObjectBase& BIS1, Eigen::PlainObjectBase& BIS2) { @@ -64,10 +64,10 @@ IGL_INLINE void igl::compute_frame_field_bisectors( template IGL_INLINE void igl::compute_frame_field_bisectors( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, - const Eigen::PlainObjectBase& PD1, - const Eigen::PlainObjectBase& PD2, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& PD1, + const Eigen::MatrixBase& PD2, Eigen::PlainObjectBase& BIS1, Eigen::PlainObjectBase& BIS2) { @@ -80,7 +80,7 @@ IGL_INLINE void igl::compute_frame_field_bisectors( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::compute_frame_field_bisectors, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::compute_frame_field_bisectors, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::compute_frame_field_bisectors, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::compute_frame_field_bisectors, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::compute_frame_field_bisectors, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::compute_frame_field_bisectors, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/compute_frame_field_bisectors.h b/include/igl/compute_frame_field_bisectors.h index 4c853febf..f5cef3a11 100644 --- a/include/igl/compute_frame_field_bisectors.h +++ b/include/igl/compute_frame_field_bisectors.h @@ -26,22 +26,22 @@ namespace igl // template IGL_INLINE void compute_frame_field_bisectors( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, - const Eigen::PlainObjectBase& B1, - const Eigen::PlainObjectBase& B2, - const Eigen::PlainObjectBase& PD1, - const Eigen::PlainObjectBase& PD2, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& B1, + const Eigen::MatrixBase& B2, + const Eigen::MatrixBase& PD1, + const Eigen::MatrixBase& PD2, Eigen::PlainObjectBase& BIS1, Eigen::PlainObjectBase& BIS2); // Wrapper without given basis vectors. template IGL_INLINE void compute_frame_field_bisectors( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, - const Eigen::PlainObjectBase& PD1, - const Eigen::PlainObjectBase& PD2, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& PD1, + const Eigen::MatrixBase& PD2, Eigen::PlainObjectBase& BIS1, Eigen::PlainObjectBase& BIS2); } diff --git a/include/igl/connect_boundary_to_infinity.cpp b/include/igl/connect_boundary_to_infinity.cpp index 627b0b9b6..e0b7aec37 100644 --- a/include/igl/connect_boundary_to_infinity.cpp +++ b/include/igl/connect_boundary_to_infinity.cpp @@ -10,14 +10,14 @@ template IGL_INLINE void igl::connect_boundary_to_infinity( - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & FO) { return connect_boundary_to_infinity(F,F.maxCoeff(),FO); } template IGL_INLINE void igl::connect_boundary_to_infinity( - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & F, const typename DerivedF::Scalar inf_index, Eigen::PlainObjectBase & FO) { @@ -37,8 +37,8 @@ template < typename DerivedVO, typename DerivedFO> IGL_INLINE void igl::connect_boundary_to_infinity( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & VO, Eigen::PlainObjectBase & FO) { @@ -51,5 +51,5 @@ IGL_INLINE void igl::connect_boundary_to_infinity( } #ifdef IGL_STATIC_LIBRARY -template void igl::connect_boundary_to_infinity, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::connect_boundary_to_infinity, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/connect_boundary_to_infinity.h b/include/igl/connect_boundary_to_infinity.h index 2fa2783d6..3109fc952 100644 --- a/include/igl/connect_boundary_to_infinity.h +++ b/include/igl/connect_boundary_to_infinity.h @@ -22,13 +22,13 @@ namespace igl // edge-manifold). template IGL_INLINE void connect_boundary_to_infinity( - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & FO); // Inputs: // inf_index index of point at infinity (usually V.rows() or F.maxCoeff()) template IGL_INLINE void connect_boundary_to_infinity( - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & F, const typename DerivedF::Scalar inf_index, Eigen::PlainObjectBase & FO); // Inputs: @@ -45,8 +45,8 @@ namespace igl typename DerivedVO, typename DerivedFO> IGL_INLINE void connect_boundary_to_infinity( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & VO, Eigen::PlainObjectBase & FO); } diff --git a/include/igl/copyleft/cgal/assign.cpp b/include/igl/copyleft/cgal/assign.cpp index 0631b58a7..249ef0429 100644 --- a/include/igl/copyleft/cgal/assign.cpp +++ b/include/igl/copyleft/cgal/assign.cpp @@ -49,6 +49,12 @@ igl::copyleft::cgal::assign( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template void igl::copyleft::cgal::assign, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh +template void igl::copyleft::cgal::assign, Eigen::Matrix, -1, 3, 0, -1, 3> >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase, -1, 3, 0, -1, 3> >&); +// generated by autoexplicit.sh +template void igl::copyleft::cgal::assign, -1, -1, 0, -1, -1>, Eigen::Matrix >(Eigen::MatrixBase, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh template void igl::copyleft::cgal::assign, -1, -1, 1, -1, -1>, Eigen::Matrix >(Eigen::MatrixBase, -1, -1, 1, -1, -1> > const&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template void igl::copyleft::cgal::assign, Eigen::Matrix, -1, -1, 1, -1, -1> >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase, -1, -1, 1, -1, -1> >&); diff --git a/include/igl/copyleft/cgal/mesh_boolean.cpp b/include/igl/copyleft/cgal/mesh_boolean.cpp index 5d289f6c3..4997c3573 100644 --- a/include/igl/copyleft/cgal/mesh_boolean.cpp +++ b/include/igl/copyleft/cgal/mesh_boolean.cpp @@ -435,6 +435,8 @@ IGL_INLINE bool igl::copyleft::cgal::mesh_boolean( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template bool igl::copyleft::cgal::mesh_boolean, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, igl::MeshBooleanType const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh template bool igl::copyleft::cgal::mesh_boolean, 8, 3, 0, 8, 3>, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, -1, -1, 1, -1, -1>, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase, 8, 3, 0, 8, 3> > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, igl::MeshBooleanType const&, Eigen::PlainObjectBase, -1, -1, 1, -1, -1> >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template bool igl::copyleft::cgal::mesh_boolean, -1, -1, 1, -1, -1>, Eigen::Matrix, Eigen::Matrix, -1, -1, 1, -1, -1>, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase, -1, -1, 1, -1, -1> > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase, -1, -1, 1, -1, -1> > const&, Eigen::MatrixBase > const&, igl::MeshBooleanType const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); diff --git a/include/igl/copyleft/cgal/mesh_to_cgal_triangle_list.cpp b/include/igl/copyleft/cgal/mesh_to_cgal_triangle_list.cpp index 10e0b5966..815064a24 100644 --- a/include/igl/copyleft/cgal/mesh_to_cgal_triangle_list.cpp +++ b/include/igl/copyleft/cgal/mesh_to_cgal_triangle_list.cpp @@ -48,6 +48,10 @@ IGL_INLINE void igl::copyleft::cgal::mesh_to_cgal_triangle_list( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template void igl::copyleft::cgal::mesh_to_cgal_triangle_list, Eigen::Matrix, CGAL::Epick>(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::vector, std::allocator > >&); +// generated by autoexplicit.sh +template void igl::copyleft::cgal::mesh_to_cgal_triangle_list, Eigen::Matrix, CGAL::Epeck>(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::vector, std::allocator > >&); +// generated by autoexplicit.sh template void igl::copyleft::cgal::mesh_to_cgal_triangle_list, -1, 3, 0, -1, 3>, Eigen::Matrix, CGAL::Epick>(Eigen::MatrixBase, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase > const&, std::vector, std::allocator > >&); // generated by autoexplicit.sh template void igl::copyleft::cgal::mesh_to_cgal_triangle_list, -1, 3, 0, -1, 3>, Eigen::Matrix, CGAL::Epeck>(Eigen::MatrixBase, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase > const&, std::vector, std::allocator > >&); diff --git a/include/igl/copyleft/cgal/orient2D.h b/include/igl/copyleft/cgal/orient2D.h index d68bcce41..6f816aa66 100644 --- a/include/igl/copyleft/cgal/orient2D.h +++ b/include/igl/copyleft/cgal/orient2D.h @@ -21,7 +21,7 @@ namespace igl // pa,pb,pc 2D points. // Output: // 1 if pa,pb,pc are counterclockwise oriented. - // 0 if pa,pb,pc are counterclockwise oriented. + // 0 if pa,pb,pc are collinear. // -1 if pa,pb,pc are clockwise oriented. template IGL_INLINE short orient2D( diff --git a/include/igl/copyleft/cgal/point_areas.cpp b/include/igl/copyleft/cgal/point_areas.cpp index bb98bac3c..7b3f9be14 100644 --- a/include/igl/copyleft/cgal/point_areas.cpp +++ b/include/igl/copyleft/cgal/point_areas.cpp @@ -179,3 +179,8 @@ namespace igl { +#ifdef IGL_STATIC_LIBRARY +// Explicit template instantiation +// generated by autoexplicit.sh +template void igl::copyleft::cgal::point_areas, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +#endif diff --git a/include/igl/copyleft/cgal/point_areas.h b/include/igl/copyleft/cgal/point_areas.h index ec0366488..7614d3ecc 100644 --- a/include/igl/copyleft/cgal/point_areas.h +++ b/include/igl/copyleft/cgal/point_areas.h @@ -38,6 +38,8 @@ namespace igl // N #P by 3 list of point normals // Outputs: // A #P list of estimated areas + // + // See also: igl::knn template IGL_INLINE void point_areas( diff --git a/include/igl/copyleft/cgal/remesh_intersections.cpp b/include/igl/copyleft/cgal/remesh_intersections.cpp index 1846c31f8..019db2eef 100644 --- a/include/igl/copyleft/cgal/remesh_intersections.cpp +++ b/include/igl/copyleft/cgal/remesh_intersections.cpp @@ -483,6 +483,10 @@ IGL_INLINE void igl::copyleft::cgal::remesh_intersections( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template void igl::copyleft::cgal::remesh_intersections, Eigen::Matrix, CGAL::Epick, Eigen::Matrix, -1, -1, 0, -1, -1>, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::vector, std::allocator > > const&, std::map::Index, std::vector::Index, CGAL::Object>, std::allocator::Index, CGAL::Object> > >, std::less::Index>, std::allocator::Index const, std::vector::Index, CGAL::Object>, std::allocator::Index, CGAL::Object> > > > > > const&, bool, Eigen::PlainObjectBase, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh +template void igl::copyleft::cgal::remesh_intersections, Eigen::Matrix, CGAL::Epeck, Eigen::Matrix, -1, -1, 0, -1, -1>, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::vector, std::allocator > > const&, std::map::Index, std::vector::Index, CGAL::Object>, std::allocator::Index, CGAL::Object> > >, std::less::Index>, std::allocator::Index const, std::vector::Index, CGAL::Object>, std::allocator::Index, CGAL::Object> > > > > > const&, bool, Eigen::PlainObjectBase, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh template void igl::copyleft::cgal::remesh_intersections, -1, 3, 0, -1, 3>, Eigen::Matrix, CGAL::Epick, Eigen::Matrix, -1, -1, 1, -1, -1>, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase > const&, std::vector, std::allocator > > const&, std::map::Index, std::vector::Index, CGAL::Object>, std::allocator::Index, CGAL::Object> > >, std::less::Index>, std::allocator::Index const, std::vector::Index, CGAL::Object>, std::allocator::Index, CGAL::Object> > > > > > const&, bool, Eigen::PlainObjectBase, -1, -1, 1, -1, -1> >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template void igl::copyleft::cgal::remesh_intersections, -1, 3, 0, -1, 3>, Eigen::Matrix, CGAL::Epeck, Eigen::Matrix, -1, -1, 1, -1, -1>, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase > const&, std::vector, std::allocator > > const&, std::map::Index, std::vector::Index, CGAL::Object>, std::allocator::Index, CGAL::Object> > >, std::less::Index>, std::allocator::Index const, std::vector::Index, CGAL::Object>, std::allocator::Index, CGAL::Object> > > > > > const&, bool, Eigen::PlainObjectBase, -1, -1, 1, -1, -1> >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); @@ -527,6 +531,8 @@ template void igl::copyleft::cgal::remesh_intersections, Eigen::Matrix, CGAL::Epeck, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::vector, std::allocator > > const&, std::map::Index, std::vector::Index, CGAL::Object>, std::allocator::Index, CGAL::Object> > >, std::less::Index>, std::allocator::Index const, std::vector::Index, CGAL::Object>, std::allocator::Index, CGAL::Object> > > > > > const&, bool, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::copyleft::cgal::remesh_intersections, Eigen::Matrix, CGAL::Epick, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::vector, std::allocator > > const&, std::map::Index, std::vector::Index, CGAL::Object>, std::allocator::Index, CGAL::Object> > >, std::less::Index>, std::allocator::Index const, std::vector::Index, CGAL::Object>, std::allocator::Index, CGAL::Object> > > > > > const&, bool, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #ifdef WIN32 +template void igl::copyleft::cgal::remesh_intersections,class Eigen::Matrix,class CGAL::Epeck,class Eigen::Matrix,-1,-1,0,-1,-1>,class Eigen::Matrix,class Eigen::Matrix<__int64,-1,1,0,-1,1>,class Eigen::Matrix >(class Eigen::MatrixBase > const &,class Eigen::MatrixBase > const &,class std::vector,class std::allocator > > const &,class std::map<__int64,class std::vector,class std::allocator > >,struct std::less<__int64>,class std::allocator,class std::allocator > > > > > const &,bool,class Eigen::PlainObjectBase,-1,-1,0,-1,-1> > &,class Eigen::PlainObjectBase > &,class Eigen::PlainObjectBase > &,class Eigen::PlainObjectBase > &); +template void igl::copyleft::cgal::remesh_intersections,class Eigen::Matrix,class CGAL::Epick,class Eigen::Matrix,-1,-1,0,-1,-1>,class Eigen::Matrix,class Eigen::Matrix<__int64,-1,1,0,-1,1>,class Eigen::Matrix >(class Eigen::MatrixBase > const &,class Eigen::MatrixBase > const &,class std::vector,class std::allocator > > const &,class std::map<__int64,class std::vector,class std::allocator > >,struct std::less<__int64>,class std::allocator,class std::allocator > > > > > const &,bool,class Eigen::PlainObjectBase,-1,-1,0,-1,-1> > &,class Eigen::PlainObjectBase > &,class Eigen::PlainObjectBase > &,class Eigen::PlainObjectBase > &); template void igl::copyleft::cgal::remesh_intersections, class Eigen::Matrix, class CGAL::Epeck, class Eigen::Matrix, -1, -1, 0, -1, -1>, class Eigen::Matrix, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::Matrix>(class Eigen::MatrixBase> const &, class Eigen::MatrixBase> const &, class std::vector, class std::allocator>> const &, class std::map<__int64, class std::vector, class std::allocator>>, struct std::less<__int64>, class std::allocator, class std::allocator>>>>> const &, bool, class Eigen::PlainObjectBase, -1, -1, 0, -1, -1>> &, class Eigen::PlainObjectBase> &, class Eigen::PlainObjectBase> &, class Eigen::PlainObjectBase> &); template void igl::copyleft::cgal::remesh_intersections, class Eigen::Matrix, class CGAL::Epick, class Eigen::Matrix, -1, -1, 0, -1, -1>, class Eigen::Matrix, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::Matrix>(class Eigen::MatrixBase> const &, class Eigen::MatrixBase> const &, class std::vector, class std::allocator>> const &, class std::map<__int64, class std::vector, class std::allocator>>, struct std::less<__int64>, class std::allocator, class std::allocator>>>>> const &, bool, class Eigen::PlainObjectBase, -1, -1, 0, -1, -1>> &, class Eigen::PlainObjectBase> &, class Eigen::PlainObjectBase> &, class Eigen::PlainObjectBase> &); template void igl::copyleft::cgal::remesh_intersections, -1, 3, 0, -1, 3>, class Eigen::Matrix, class CGAL::Epeck, class Eigen::Matrix, -1, -1, 0, -1, -1>, class Eigen::Matrix, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::Matrix>(class Eigen::MatrixBase, -1, 3, 0, -1, 3>> const &, class Eigen::MatrixBase> const &, class std::vector, class std::allocator>> const &, class std::map<__int64, class std::vector, class std::allocator>>, struct std::less<__int64>, class std::allocator, class std::allocator>>>>> const &, bool, class Eigen::PlainObjectBase, -1, -1, 0, -1, -1>> &, class Eigen::PlainObjectBase> &, class Eigen::PlainObjectBase> &, class Eigen::PlainObjectBase> &); diff --git a/include/igl/copyleft/cgal/remesh_self_intersections.cpp b/include/igl/copyleft/cgal/remesh_self_intersections.cpp index 777edd1bb..4771e028f 100644 --- a/include/igl/copyleft/cgal/remesh_self_intersections.cpp +++ b/include/igl/copyleft/cgal/remesh_self_intersections.cpp @@ -83,6 +83,8 @@ IGL_INLINE void igl::copyleft::cgal::remesh_self_intersections( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template void igl::copyleft::cgal::remesh_self_intersections, Eigen::Matrix, Eigen::Matrix, -1, -1, 0, -1, -1>, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, igl::copyleft::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh template void igl::copyleft::cgal::remesh_self_intersections, -1, 3, 0, -1, 3>, Eigen::Matrix, Eigen::Matrix, -1, -1, 1, -1, -1>, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase > const&, igl::copyleft::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase, -1, -1, 1, -1, -1> >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template void igl::copyleft::cgal::remesh_self_intersections, -1, 3, 0, -1, 3>, Eigen::Matrix, Eigen::Matrix, -1, -1, 1, -1, -1>, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase > const&, igl::copyleft::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase, -1, -1, 1, -1, -1> >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); @@ -104,6 +106,7 @@ template void igl::copyleft::cgal::remesh_self_intersections, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, igl::copyleft::cgal::RemeshSelfIntersectionsParam const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #ifdef WIN32 template void igl::copyleft::cgal::remesh_self_intersections, class Eigen::Matrix, class Eigen::Matrix, -1, -1, 0, -1, -1>, class Eigen::Matrix, class Eigen::Matrix, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::Matrix>(class Eigen::MatrixBase> const &, class Eigen::MatrixBase> const &, struct igl::copyleft::cgal::RemeshSelfIntersectionsParam const &, class Eigen::PlainObjectBase, -1, -1, 0, -1, -1>> &, class Eigen::PlainObjectBase> &, class Eigen::PlainObjectBase> &, class Eigen::PlainObjectBase> &, class Eigen::PlainObjectBase> &); +template void igl::copyleft::cgal::remesh_self_intersections, class Eigen::Matrix, class Eigen::Matrix, -1, -1, 0, -1, -1>, class Eigen::Matrix, class Eigen::Matrix, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::Matrix >(class Eigen::MatrixBase > const &, class Eigen::MatrixBase > const &, struct igl::copyleft::cgal::RemeshSelfIntersectionsParam const &, class Eigen::PlainObjectBase, -1, -1, 0, -1, -1> > &, class Eigen::PlainObjectBase > &, class Eigen::PlainObjectBase > &, class Eigen::PlainObjectBase > &, class Eigen::PlainObjectBase > &); template void igl::copyleft::cgal::remesh_self_intersections, -1, 3, 0, -1, 3>, class Eigen::Matrix, class Eigen::Matrix, -1, -1, 0, -1, -1>, class Eigen::Matrix, class Eigen::Matrix, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::Matrix>(class Eigen::MatrixBase, -1, 3, 0, -1, 3>> const &, class Eigen::MatrixBase> const &, struct igl::copyleft::cgal::RemeshSelfIntersectionsParam const &, class Eigen::PlainObjectBase, -1, -1, 0, -1, -1>> &, class Eigen::PlainObjectBase> &, class Eigen::PlainObjectBase> &, class Eigen::PlainObjectBase> &, class Eigen::PlainObjectBase> &); #endif #endif diff --git a/include/igl/copyleft/comiso/nrosy.cpp b/include/igl/copyleft/comiso/nrosy.cpp index 271712c10..1b2c4d74e 100644 --- a/include/igl/copyleft/comiso/nrosy.cpp +++ b/include/igl/copyleft/comiso/nrosy.cpp @@ -482,7 +482,7 @@ void igl::copyleft::comiso::NRosyField::computek() // Map the two triangles in a new space where the common edge is the x axis and the N0 the z axis Eigen::MatrixXd P(3,3); Eigen::VectorXd o = V.row(F(fid0,fid0_vc)); - Eigen::VectorXd tmp = -N0.cross(common_edge); + Eigen::VectorXd tmp = N0.cross(common_edge); P << common_edge, tmp, N0; P.transposeInPlace(); @@ -494,9 +494,9 @@ void igl::copyleft::comiso::NRosyField::computek() V0 = (P*V0.transpose()).transpose(); - assert(V0(0,2) < 10e-10); - assert(V0(1,2) < 10e-10); - assert(V0(2,2) < 10e-10); + assert(V0(0,2) < 1e-10); + assert(V0(1,2) < 1e-10); + assert(V0(2,2) < 1e-10); Eigen::MatrixXd V1(3,3); V1.row(0) = V.row(F(fid1,0)).transpose() -o; @@ -504,22 +504,22 @@ void igl::copyleft::comiso::NRosyField::computek() V1.row(2) = V.row(F(fid1,2)).transpose() -o; V1 = (P*V1.transpose()).transpose(); - assert(V1(fid1_vc,2) < 10e-10); - assert(V1((fid1_vc+1)%3,2) < 10e-10); + assert(V1(fid1_vc,2) < 1e-10); + assert(V1((fid1_vc+1)%3,2) < 1e-10); // compute rotation R such that R * N1 = N0 // i.e. map both triangles to the same plane - double alpha = -std::atan2(V1((fid1_vc + 2) % 3, 2), V1((fid1_vc + 2) % 3, 1)); + double alpha = -std::atan2(-V1((fid1_vc + 2) % 3, 2), -V1((fid1_vc + 2) % 3, 1)); Eigen::MatrixXd R(3,3); R << 1, 0, 0, - 0, std::cos(alpha), -std::sin(alpha) , + 0, std::cos(alpha), -std::sin(alpha), 0, std::sin(alpha), std::cos(alpha); V1 = (R*V1.transpose()).transpose(); - assert(V1(0,2) < 10e-10); - assert(V1(1,2) < 10e-10); - assert(V1(2,2) < 10e-10); + assert(V1(0,2) < 1e-10); + assert(V1(1,2) < 1e-10); + assert(V1(2,2) < 1e-10); // measure the angle between the reference frames // k_ij is the angle between the triangle on the left and the one on the right @@ -528,17 +528,25 @@ void igl::copyleft::comiso::NRosyField::computek() ref0.normalize(); ref1.normalize(); - - double ktemp = std::atan2(ref1(1), ref1(0)) - std::atan2(ref0(1), ref0(0)); - + + double ktemp = - std::atan2(ref1(1), ref1(0)) + std::atan2(ref0(1), ref0(0)); + + // make sure kappa is in corret range + auto pos_fmod = [](double x, double y){ + return (0 == y) ? x : x - y * floor(x/y); + }; + ktemp = pos_fmod(ktemp, 2*igl::PI); + if (ktemp > igl::PI) + ktemp -= 2*igl::PI; + // just to be sure, rotate ref0 using angle ktemp... Eigen::MatrixXd R2(2,2); - R2 << std::cos(ktemp), -std::sin(ktemp), std::sin(ktemp), std::cos(ktemp); + R2 << std::cos(-ktemp), -std::sin(-ktemp), std::sin(-ktemp), std::cos(-ktemp); tmp = R2*ref0.head<2>(); - assert(tmp(0) - ref1(0) < 10^10); - assert(tmp(1) - ref1(1) < 10^10); + assert(tmp(0) - ref1(0) < 1e-10); + assert(tmp(1) - ref1(1) < 1e-10); k[eid] = ktemp; } @@ -637,7 +645,7 @@ Eigen::Vector3d igl::copyleft::comiso::NRosyField::convertLocalto3D(unsigned fid Eigen::VectorXd igl::copyleft::comiso::NRosyField::angleDefect() { - Eigen::VectorXd A = Eigen::VectorXd::Constant(V.rows(),-2*igl::PI); + Eigen::VectorXd A = Eigen::VectorXd::Constant(V.rows(), 2*igl::PI); for (unsigned int i = 0; i < F.rows(); ++i) { @@ -650,7 +658,7 @@ Eigen::VectorXd igl::copyleft::comiso::NRosyField::angleDefect() t /= (a.norm() * b.norm()); else throw std::runtime_error("igl::copyleft::comiso::NRosyField::angleDefect: Division by zero!"); - A(F(i, j)) += std::acos(std::max(std::min(t, 1.), -1.)); + A(F(i, j)) -= std::acos(std::max(std::min(t, 1.), -1.)); } } @@ -668,8 +676,8 @@ void igl::copyleft::comiso::NRosyField::findCones(int N) { if (!isBorderEdge[i]) { - singularityIndex(EV(i, 0)) -= k(i); - singularityIndex(EV(i, 1)) += k(i); + singularityIndex(EV(i, 0)) += k(i); + singularityIndex(EV(i, 1)) -= k(i); } } @@ -687,8 +695,8 @@ void igl::copyleft::comiso::NRosyField::findCones(int N) { if (!isBorderEdge[i]) { - singularityIndex(EV(i, 0)) -= double(p(i)) / double(N); - singularityIndex(EV(i, 1)) += double(p(i)) / double(N); + singularityIndex(EV(i, 0)) += double(p(i)) / double(N); + singularityIndex(EV(i, 1)) -= double(p(i)) / double(N); } } diff --git a/include/igl/copyleft/quadprog.cpp b/include/igl/copyleft/quadprog.cpp index 4c565a0c3..53692082d 100644 --- a/include/igl/copyleft/quadprog.cpp +++ b/include/igl/copyleft/quadprog.cpp @@ -139,7 +139,7 @@ IGL_INLINE bool igl::copyleft::quadprog( #ifdef TRACE_SOLVER std::cerr << "Add constraint " << iq << '/'; #endif - int i, j, k; + int j, k; double cc, ss, h, t1, t2, xny; /* we have to find the Givens rotation which will reduce the element @@ -284,7 +284,7 @@ IGL_INLINE bool igl::copyleft::quadprog( } }; - int i, j, k, l; /* indices */ + int i, k, l; /* indices */ int ip, me, mi; int n=g0.size(); int p=ce0.size(); int m=ci0.size(); MatrixXd R(G.rows(),G.cols()), J(G.rows(),G.cols()); diff --git a/include/igl/copyleft/tetgen/tetgenio_to_tetmesh.cpp b/include/igl/copyleft/tetgen/tetgenio_to_tetmesh.cpp index 2cccd6b30..21c6ecafa 100644 --- a/include/igl/copyleft/tetgen/tetgenio_to_tetmesh.cpp +++ b/include/igl/copyleft/tetgen/tetgenio_to_tetmesh.cpp @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2013 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "tetgenio_to_tetmesh.h" @@ -18,11 +18,11 @@ IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh( std::vector > & V, std::vector > & T, std::vector > & F, - std::vector >& R, + std::vector >& R, std::vector >& N, std::vector >& PT, std::vector >& FT, - size_t & nR ) + size_t & nR ) { using namespace std; // process points @@ -63,11 +63,11 @@ IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh( max_index = (max_index < index ? index : max_index); } } - + assert(min_index >= 0); assert(max_index >= 0); assert(max_index < (int)V.size()); - + cout<(4)); + // extract neighbor list + N.resize(out.numberoftetrahedra, vector(4)); for (size_t i = 0; i < out.numberoftetrahedra; i++) { for (size_t j = 0; j < 4; j++) N[i][j] = out.neighborlist[i * 4 + j]; - } - - // extract point 2 tetrahedron list + } + + // extract point 2 tetrahedron list PT.resize(out.numberofpoints, vector(1)); for (size_t i = 0; i < out.numberofpoints; i++) { - PT[i][0] = out.point2tetlist[i]; - } - + PT[i][0] = out.point2tetlist[i]; + } + //extract face to tetrahedron list - FT.resize(out.numberoftrifaces, vector(2)); + FT.resize(out.numberoftrifaces, vector(2)); int triface; - + for (size_t i = 0; i < out.numberoftrifaces; i++) { for (size_t j = 0; j < 2; j++) { - FT[i][j] = out.face2tetlist[0]; + FT[i][j] = out.face2tetlist[0]; } } @@ -129,7 +129,7 @@ IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh( IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh( const tetgenio & out, - std::vector > & V, + std::vector > & V, std::vector > & T, std::vector > & F) { @@ -182,7 +182,7 @@ IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh( // loop over tetrahedra for(int i = 0; i < out.numberoftrifaces; i++) { - if(out.trifacemarkerlist[i]>=0) + if (out.trifacemarkerlist && out.trifacemarkerlist[i] >= 0) { vector face(3); for(int j = 0; j<3; j++) @@ -198,7 +198,7 @@ IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh( IGL_INLINE bool igl::copyleft::tetgen::tetgenio_to_tetmesh( const tetgenio & out, - std::vector > & V, + std::vector > & V, std::vector > & T) { std::vector > F; diff --git a/include/igl/copyleft/tetgen/tetrahedralize.cpp b/include/igl/copyleft/tetgen/tetrahedralize.cpp index f670fd9a0..12f441677 100644 --- a/include/igl/copyleft/tetgen/tetrahedralize.cpp +++ b/include/igl/copyleft/tetgen/tetrahedralize.cpp @@ -78,10 +78,10 @@ template < typename DerivedTF, typename DerivedTR> IGL_INLINE int igl::copyleft::tetgen::tetrahedralize( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, - const Eigen::PlainObjectBase& H, - const Eigen::PlainObjectBase& R, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& H, + const Eigen::MatrixBase& R, const std::string switches, Eigen::PlainObjectBase& TV, Eigen::PlainObjectBase& TT, @@ -191,8 +191,8 @@ template < typename DerivedTT, typename DerivedTF> IGL_INLINE int igl::copyleft::tetgen::tetrahedralize( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, const std::string switches, Eigen::PlainObjectBase& TV, Eigen::PlainObjectBase& TT, @@ -235,10 +235,10 @@ template < typename DerivedTF, typename DerivedTM> IGL_INLINE int igl::copyleft::tetgen::tetrahedralize( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, - const Eigen::PlainObjectBase& VM, - const Eigen::PlainObjectBase& FM, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& VM, + const Eigen::MatrixBase& FM, const std::string switches, Eigen::PlainObjectBase& TV, Eigen::PlainObjectBase& TT, @@ -339,7 +339,7 @@ IGL_INLINE int igl::copyleft::tetgen::tetrahedralize( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template int igl::copyleft::tetgen::tetrahedralize, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template int igl::copyleft::tetgen::tetrahedralize,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix >(const Eigen::PlainObjectBase > &,const Eigen::PlainObjectBase > &,const Eigen::PlainObjectBase > &,const Eigen::PlainObjectBase > &,const std::basic_string, std::allocator >,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &, Eigen::PlainObjectBase > &); -template int igl::copyleft::tetgen::tetrahedralize, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template int igl::copyleft::tetgen::tetrahedralize, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template int igl::copyleft::tetgen::tetrahedralize,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix >(const Eigen::MatrixBase > &,const Eigen::MatrixBase > &,const Eigen::MatrixBase > &,const Eigen::MatrixBase > &,const std::basic_string, std::allocator >,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &, Eigen::PlainObjectBase > &); +template int igl::copyleft::tetgen::tetrahedralize, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/copyleft/tetgen/tetrahedralize.h b/include/igl/copyleft/tetgen/tetrahedralize.h index 7d9705068..39ca3bf4a 100644 --- a/include/igl/copyleft/tetgen/tetrahedralize.h +++ b/include/igl/copyleft/tetgen/tetrahedralize.h @@ -61,8 +61,8 @@ namespace igl typename DerivedTT, typename DerivedTF> IGL_INLINE int tetrahedralize( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, const std::string switches, Eigen::PlainObjectBase& TV, Eigen::PlainObjectBase& TT, @@ -114,10 +114,10 @@ namespace igl typename DerivedTF, typename DerivedTM> IGL_INLINE int tetrahedralize( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, - const Eigen::PlainObjectBase& VM, - const Eigen::PlainObjectBase& FM, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& VM, + const Eigen::MatrixBase& FM, const std::string switches, Eigen::PlainObjectBase& TV, Eigen::PlainObjectBase& TT, @@ -185,10 +185,10 @@ namespace igl typename DerivedTF, typename DerivedTR> IGL_INLINE int tetrahedralize( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, - const Eigen::PlainObjectBase& H, - const Eigen::PlainObjectBase& R, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& H, + const Eigen::MatrixBase& R, const std::string switches, Eigen::PlainObjectBase& TV, Eigen::PlainObjectBase& TT, diff --git a/include/igl/cross.cpp b/include/igl/cross.cpp index 04ee5340b..7b049c9bc 100644 --- a/include/igl/cross.cpp +++ b/include/igl/cross.cpp @@ -1,45 +1,47 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2013 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "cross.h" // http://www.antisphere.com/Wiki/tools:anttweakbar IGL_INLINE void igl::cross( - const double *a, - const double *b, - double *out) + const double *a, + const double *b, + double *out) { - out[0] = a[1]*b[2]-a[2]*b[1]; - out[1] = a[2]*b[0]-a[0]*b[2]; - out[2] = a[0]*b[1]-a[1]*b[0]; + out[0] = a[1] * b[2] - a[2] * b[1]; + out[1] = a[2] * b[0] - a[0] * b[2]; + out[2] = a[0] * b[1] - a[1] * b[0]; } template < - typename DerivedA, - typename DerivedB, - typename DerivedC> + typename DerivedA, + typename DerivedB, + typename DerivedC> IGL_INLINE void igl::cross( - const Eigen::PlainObjectBase & A, - const Eigen::PlainObjectBase & B, - Eigen::PlainObjectBase & C) + const Eigen::PlainObjectBase &A, + const Eigen::PlainObjectBase &B, + Eigen::PlainObjectBase &C) { assert(A.cols() == 3 && "#cols should be 3"); assert(B.cols() == 3 && "#cols should be 3"); assert(A.rows() == B.rows() && "#rows in A and B should be equal"); - C.resize(A.rows(),3); - for(int d = 0;d<3;d++) + C.resize(A.rows(), 3); + for (int d = 0; d < 3; d++) { - C.col(d) = - A.col((d+1)%3).array() * B.col((d+2)%3).array() - - A.col((d+2)%3).array() * B.col((d+1)%3).array(); + C.col(d) = + A.col((d + 1) % 3).array() * B.col((d + 2) % 3).array() - + A.col((d + 2) % 3).array() * B.col((d + 1) % 3).array(); } } #ifdef IGL_STATIC_LIBRARY -template void igl::cross, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); -template void igl::cross, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); -#endif +template void igl::cross, Eigen::Matrix, Eigen::Matrix>(Eigen::PlainObjectBase> const &, Eigen::PlainObjectBase> const &, Eigen::PlainObjectBase> &); +template void igl::cross, Eigen::Matrix, Eigen::Matrix>(Eigen::PlainObjectBase> const &, Eigen::PlainObjectBase> const &, Eigen::PlainObjectBase> &); +template void igl::cross, Eigen::Matrix, Eigen::Matrix>(Eigen::PlainObjectBase> const &, Eigen::PlainObjectBase> const &, Eigen::PlainObjectBase> &); +template void igl::cross, Eigen::Matrix, Eigen::Matrix>(Eigen::PlainObjectBase> const &, Eigen::PlainObjectBase> const &, Eigen::PlainObjectBase> &); +#endif \ No newline at end of file diff --git a/include/igl/cross_field_mismatch.cpp b/include/igl/cross_field_mismatch.cpp index 3c3265535..fa4df32af 100644 --- a/include/igl/cross_field_mismatch.cpp +++ b/include/igl/cross_field_mismatch.cpp @@ -25,10 +25,10 @@ namespace igl { { public: - const Eigen::PlainObjectBase &V; - const Eigen::PlainObjectBase &F; - const Eigen::PlainObjectBase &PD1; - const Eigen::PlainObjectBase &PD2; + const Eigen::MatrixBase &V; + const Eigen::MatrixBase &F; + const Eigen::MatrixBase &PD1; + const Eigen::MatrixBase &PD2; DerivedV N; @@ -69,17 +69,17 @@ namespace igl { public: - inline MismatchCalculator(const Eigen::PlainObjectBase &_V, - const Eigen::PlainObjectBase &_F, - const Eigen::PlainObjectBase &_PD1, - const Eigen::PlainObjectBase &_PD2): + inline MismatchCalculator(const Eigen::MatrixBase &_V, + const Eigen::MatrixBase &_F, + const Eigen::MatrixBase &_PD1, + const Eigen::MatrixBase &_PD2): V(_V), F(_F), PD1(_PD1), PD2(_PD2) { igl::per_face_normals(V,F,N); - V_border = igl::is_border_vertex(V,F); + V_border = igl::is_border_vertex(F); igl::vertex_triangle_adjacency(V,F,VF,VFi); igl::triangle_triangle_adjacency(F,TT,TTi); } @@ -102,10 +102,10 @@ public: }; } template -IGL_INLINE void igl::cross_field_mismatch(const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, - const Eigen::PlainObjectBase &PD1, - const Eigen::PlainObjectBase &PD2, +IGL_INLINE void igl::cross_field_mismatch(const Eigen::MatrixBase &V, + const Eigen::MatrixBase &F, + const Eigen::MatrixBase &PD1, + const Eigen::MatrixBase &PD2, const bool isCombed, Eigen::PlainObjectBase &mismatch) { @@ -125,8 +125,8 @@ IGL_INLINE void igl::cross_field_mismatch(const Eigen::PlainObjectBase #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::cross_field_mismatch, Eigen::Matrix >(Eigen::PlainObjectBase > const &, Eigen::PlainObjectBase > const &, Eigen::PlainObjectBase > const &, Eigen::PlainObjectBase > const &, const bool, Eigen::PlainObjectBase > &); -template void igl::cross_field_mismatch, Eigen::Matrix >( Eigen::PlainObjectBase > const &, Eigen::PlainObjectBase > const &, Eigen::PlainObjectBase > const &, Eigen::PlainObjectBase > const &, const bool, Eigen::PlainObjectBase > &); -template void igl::cross_field_mismatch, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const &, Eigen::PlainObjectBase > const &, Eigen::PlainObjectBase > const &, Eigen::PlainObjectBase > const &, const bool, Eigen::PlainObjectBase > &); +template void igl::cross_field_mismatch, Eigen::Matrix >(Eigen::MatrixBase > const &, Eigen::MatrixBase > const &, Eigen::MatrixBase > const &, Eigen::MatrixBase > const &, const bool, Eigen::PlainObjectBase > &); +template void igl::cross_field_mismatch, Eigen::Matrix >( Eigen::MatrixBase > const &, Eigen::MatrixBase > const &, Eigen::MatrixBase > const &, Eigen::MatrixBase > const &, const bool, Eigen::PlainObjectBase > &); +template void igl::cross_field_mismatch, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const &, Eigen::MatrixBase > const &, Eigen::MatrixBase > const &, Eigen::MatrixBase > const &, const bool, Eigen::PlainObjectBase > &); #endif diff --git a/include/igl/cross_field_mismatch.h b/include/igl/cross_field_mismatch.h index daf000e2d..5f15e9641 100644 --- a/include/igl/cross_field_mismatch.h +++ b/include/igl/cross_field_mismatch.h @@ -29,10 +29,10 @@ namespace igl // template - IGL_INLINE void cross_field_mismatch(const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, - const Eigen::PlainObjectBase &PD1, - const Eigen::PlainObjectBase &PD2, + IGL_INLINE void cross_field_mismatch(const Eigen::MatrixBase &V, + const Eigen::MatrixBase &F, + const Eigen::MatrixBase &PD1, + const Eigen::MatrixBase &PD2, const bool isCombed, Eigen::PlainObjectBase &mismatch); } diff --git a/include/igl/crouzeix_raviart_cotmatrix.cpp b/include/igl/crouzeix_raviart_cotmatrix.cpp index 2fc5f6d4a..57e67bd76 100644 --- a/include/igl/crouzeix_raviart_cotmatrix.cpp +++ b/include/igl/crouzeix_raviart_cotmatrix.cpp @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2017 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "crouzeix_raviart_cotmatrix.h" #include "unique_simplices.h" @@ -13,14 +13,14 @@ template void igl::crouzeix_raviart_cotmatrix( - const Eigen::MatrixBase & V, - const Eigen::MatrixBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, Eigen::SparseMatrix & L, Eigen::PlainObjectBase & E, Eigen::PlainObjectBase & EMAP) { // All occurrences of directed "facets" - Eigen::MatrixXi allE; + Eigen::Matrix allE; oriented_facets(F,allE); Eigen::VectorXi _1; unique_simplices(allE,E,_1,EMAP); @@ -29,8 +29,8 @@ void igl::crouzeix_raviart_cotmatrix( template void igl::crouzeix_raviart_cotmatrix( - const Eigen::MatrixBase & V, - const Eigen::MatrixBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, const Eigen::MatrixBase & E, const Eigen::MatrixBase & EMAP, Eigen::SparseMatrix & L) @@ -84,8 +84,8 @@ void igl::crouzeix_raviart_cotmatrix( for(int c = 0;c void igl::crouzeix_raviart_massmatrix( - const Eigen::MatrixBase & V, + const Eigen::MatrixBase & V, const Eigen::MatrixBase & F, Eigen::SparseMatrix & M, Eigen::PlainObjectBase & E, Eigen::PlainObjectBase & EMAP) { // All occurrences of directed "facets" - Eigen::MatrixXi allE; + Eigen::Matrix allE; oriented_facets(F,allE); - Eigen::VectorXi _1; + Eigen::Matrix _1; unique_simplices(allE,E,_1,EMAP); return crouzeix_raviart_massmatrix(V,F,E,EMAP,M); } @@ -69,7 +69,7 @@ void igl::crouzeix_raviart_massmatrix( { for(int c = 0;c(EMAP(f+m*c),EMAP(f+m*c),TA(f)/(double)(ss)); + MIJV[f+m*c] = Triplet(EMAP(f+m*c, 0),EMAP(f+m*c, 0),TA(f)/(double)(ss)); } } M.resize(E.rows(),E.rows()); diff --git a/include/igl/cumsum.cpp b/include/igl/cumsum.cpp index eeda49cec..a4d962ddc 100644 --- a/include/igl/cumsum.cpp +++ b/include/igl/cumsum.cpp @@ -60,6 +60,8 @@ IGL_INLINE void igl::cumsum( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template void igl::cumsum, Eigen::Matrix >(Eigen::MatrixBase > const&, int, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh template void igl::cumsum, Eigen::Matrix >(Eigen::MatrixBase > const&, int, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template void igl::cumsum, Eigen::Matrix >(Eigen::MatrixBase > const&, int, Eigen::PlainObjectBase >&); diff --git a/include/igl/cut_mesh.cpp b/include/igl/cut_mesh.cpp index 33a25ce93..fa35c3c24 100644 --- a/include/igl/cut_mesh.cpp +++ b/include/igl/cut_mesh.cpp @@ -1,330 +1,149 @@ // This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2016 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// Copyright (C) 2019 Hanxiao Shen +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include -#include #include -#include #include -#include +#include -// This file violates many of the libigl style guidelines. - -namespace igl { - - - template - class MeshCutterMini - { - public: - // Input - //mesh - const Eigen::PlainObjectBase &V; - const Eigen::PlainObjectBase &F; - // TT is the same type as TTi? This is likely to break at some point - const Eigen::PlainObjectBase &TT; - const Eigen::PlainObjectBase &TTi; - const std::vector >& VF; - const std::vector >& VFi; - const std::vector &V_border; // bool - //edges to cut - const Eigen::PlainObjectBase &Handle_Seams; // 3 bool - - // total number of scalar variables - int num_scalar_variables; - - // per face indexes of vertex in the solver - DerivedF HandleS_Index; - - // per vertex variable indexes - std::vector > HandleV_Integer; - - IGL_INLINE MeshCutterMini( - const Eigen::PlainObjectBase &_V, - const Eigen::PlainObjectBase &_F, - const Eigen::PlainObjectBase &_TT, - const Eigen::PlainObjectBase &_TTi, - const std::vector > &_VF, - const std::vector > &_VFi, - const std::vector &_V_border, - const Eigen::PlainObjectBase &_Handle_Seams); - - // vertex to variable mapping - // initialize the mapping for a given sampled mesh - IGL_INLINE void InitMappingSeam(); - - private: - - IGL_INLINE void FirstPos(const int v, int &f, int &edge); - - IGL_INLINE int AddNewIndex(const int v0); - - IGL_INLINE bool IsSeam(const int f0, const int f1); - - // find initial position of the pos to - // assing face to vert inxex correctly - IGL_INLINE void FindInitialPos(const int vert, int &edge, int &face); - - - // initialize the mapping given an initial pos - // whih must be initialized with FindInitialPos - IGL_INLINE void MapIndexes(const int vert, const int edge_init, const int f_init); - - // initialize the mapping for a given vertex - IGL_INLINE void InitMappingSeam(const int vert); - - }; -} - - -template -IGL_INLINE igl::MeshCutterMini:: -MeshCutterMini( - const Eigen::PlainObjectBase &_V, - const Eigen::PlainObjectBase &_F, - const Eigen::PlainObjectBase &_TT, - const Eigen::PlainObjectBase &_TTi, - const std::vector > &_VF, - const std::vector > &_VFi, - const std::vector &_V_border, - const Eigen::PlainObjectBase &_Handle_Seams): - V(_V), - F(_F), - TT(_TT), - TTi(_TTi), - VF(_VF), - VFi(_VFi), - V_border(_V_border), - Handle_Seams(_Handle_Seams) -{ - num_scalar_variables=0; - HandleS_Index.setConstant(F.rows(),3,-1); - HandleV_Integer.resize(V.rows()); -} - - -template -IGL_INLINE void igl::MeshCutterMini:: -FirstPos(const int v, int &f, int &edge) -{ - f = VF[v][0]; // f=v->cVFp(); - edge = VFi[v][0]; // edge=v->cVFi(); -} - -template -IGL_INLINE int igl::MeshCutterMini:: -AddNewIndex(const int v0) -{ - num_scalar_variables++; - HandleV_Integer[v0].push_back(num_scalar_variables); - return num_scalar_variables; -} - -template -IGL_INLINE bool igl::MeshCutterMini:: -IsSeam(const int f0, const int f1) -{ - for (int i=0;i<3;i++) - { - int f_clos = TT(f0,i); - - if (f_clos == -1) - continue; ///border - - if (f_clos == f1) - return(Handle_Seams(f0,i)); - } - assert(0); - return false; -} - -///find initial position of the pos to -// assing face to vert inxex correctly -template -IGL_INLINE void igl::MeshCutterMini:: -FindInitialPos(const int vert, - int &edge, - int &face) -{ - int f_init; - int edge_init; - FirstPos(vert,f_init,edge_init); // todo manually the function - igl::HalfEdgeIterator VFI(F,TT,TTi,f_init,edge_init); - - bool vertexB = V_border[vert]; - bool possible_split=false; - bool complete_turn=false; - do - { - int curr_f = VFI.Fi(); - int curr_edge=VFI.Ei(); - VFI.NextFE(); - int next_f=VFI.Fi(); - ///test if I've just crossed a border - bool on_border=(TT(curr_f,curr_edge)==-1); - //bool mismatch=false; - bool seam=false; - - ///or if I've just crossed a seam - ///if I'm on a border I MUST start from the one next t othe border - if (!vertexB) - //seam=curr_f->IsSeam(next_f); - seam=IsSeam(curr_f,next_f); - // if (vertexB) - // assert(!Handle_Singular(vert)); - // ; - //assert(!vert->IsSingular()); - possible_split=((on_border)||(seam)); - complete_turn = next_f == f_init; - } while ((!possible_split)&&(!complete_turn)); - face=VFI.Fi(); - edge=VFI.Ei(); -} - - - -///initialize the mapping given an initial pos -///whih must be initialized with FindInitialPos -template -IGL_INLINE void igl::MeshCutterMini:: -MapIndexes(const int vert, - const int edge_init, - const int f_init) -{ - ///check that is not on border.. - ///in such case maybe it's non manyfold - ///insert an initial index - int curr_index=AddNewIndex(vert); - ///and initialize the jumping pos - igl::HalfEdgeIterator VFI(F,TT,TTi,f_init,edge_init); - bool complete_turn=false; - do - { - int curr_f = VFI.Fi(); - int curr_edge = VFI.Ei(); - ///assing the current index - HandleS_Index(curr_f,curr_edge) = curr_index; - VFI.NextFE(); - int next_f = VFI.Fi(); - ///test if I've finiseh with the face exploration - complete_turn = (next_f==f_init); - ///or if I've just crossed a mismatch - if (!complete_turn) - { - bool seam=false; - //seam=curr_f->IsSeam(next_f); - seam=IsSeam(curr_f,next_f); - if (seam) - { - ///then add a new index - curr_index=AddNewIndex(vert); - } - } - } while (!complete_turn); -} - -///initialize the mapping for a given vertex -template -IGL_INLINE void igl::MeshCutterMini:: -InitMappingSeam(const int vert) -{ - ///first rotate until find the first pos after a mismatch - ///or a border or return to the first position... - int f_init = VF[vert][0]; - int indexE = VFi[vert][0]; - - igl::HalfEdgeIterator VFI(F,TT,TTi,f_init,indexE); - - int edge_init; - int face_init; - FindInitialPos(vert,edge_init,face_init); - MapIndexes(vert,edge_init,face_init); -} - -///vertex to variable mapping -///initialize the mapping for a given sampled mesh -template -IGL_INLINE void igl::MeshCutterMini:: -InitMappingSeam() -{ - num_scalar_variables=-1; - for (unsigned int i=0;i0); -} - - -template -IGL_INLINE void igl::cut_mesh( - const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, - const std::vector >& VF, - const std::vector >& VFi, - const Eigen::PlainObjectBase& TT, - const Eigen::PlainObjectBase& TTi, - const std::vector &V_border, - const Eigen::PlainObjectBase &cuts, - Eigen::PlainObjectBase &Vcut, - Eigen::PlainObjectBase &Fcut) -{ - //finding the cuts is done, now we need to actually generate a cut mesh - igl::MeshCutterMini mc(V, F, TT, TTi, VF, VFi, V_border, cuts); - mc.InitMappingSeam(); - - Fcut = mc.HandleS_Index; - //we have the faces, we need the vertices; - int newNumV = Fcut.maxCoeff()+1; - Vcut.setZero(newNumV,3); - for (int vi=0; vi IGL_INLINE void igl::cut_mesh( - const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, - const Eigen::PlainObjectBase &cuts, - Eigen::PlainObjectBase &Vcut, - Eigen::PlainObjectBase &Fcut) -{ - std::vector > VF, VFi; - igl::vertex_triangle_adjacency(V,F,VF,VFi); - // Alec: Cast? Why? This is likely to break. - Eigen::MatrixXd Vt = V; - Eigen::MatrixXi Ft = F; - Eigen::MatrixXi TT, TTi; - igl::triangle_triangle_adjacency(Ft,TT,TTi); - std::vector V_border = igl::is_border_vertex(V,F); - igl::cut_mesh(V, F, VF, VFi, TT, TTi, V_border, cuts, Vcut, Fcut); + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& C, + Eigen::PlainObjectBase& Vn, + Eigen::PlainObjectBase& Fn +){ + Vn = V; + Fn = F; + typedef typename DerivedF::Scalar Index; + Eigen::Matrix _I; + cut_mesh(Vn,Fn,C,_I); } +template +IGL_INLINE void igl::cut_mesh( + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& C, + Eigen::PlainObjectBase& Vn, + Eigen::PlainObjectBase& Fn, + Eigen::PlainObjectBase& I +){ + Vn = V; + Fn = F; + cut_mesh(Vn,Fn,C,I); +} + +template +IGL_INLINE void igl::cut_mesh( + Eigen::PlainObjectBase& V, + Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& C, + Eigen::PlainObjectBase& I +){ + typedef typename DerivedF::Scalar Index; + DerivedF FF, FFi; + igl::triangle_triangle_adjacency(F,FF,FFi); + igl::cut_mesh(V,F,FF,FFi,C,I); +} + +template +IGL_INLINE void igl::cut_mesh( + Eigen::PlainObjectBase& V, + Eigen::PlainObjectBase& F, + Eigen::MatrixBase& FF, + Eigen::MatrixBase& FFi, + const Eigen::MatrixBase& C, + Eigen::PlainObjectBase& I +){ + + typedef typename DerivedF::Scalar Index; + + // store current number of occurance of each vertex as the alg proceed + Eigen::Matrix occurence(V.rows()); + occurence.setConstant(1); + + // set eventual number of occurance of each vertex expected + Eigen::Matrix eventual(V.rows()); + eventual.setZero(); + for(Index i=0;i 0) ? eventual(i)-1 : 0); + V.conservativeResize(n_v+n_new,Eigen::NoChange); + I = DerivedI::LinSpaced(V.rows(),0,V.rows()); + + // pointing to the current bottom of V + Index pos = n_v; + for(Index f=0;f= n_v) continue; // ignore new vertices + if(C(f,k) == 1 && occurence(v0) != eventual(v0)){ + igl::HalfEdgeIterator he(F,FF,FFi,f,k); + + // rotate clock-wise around v0 until hit another cut + std::vector fan; + Index fi = he.Fi(); + Index ei = he.Ei(); + do{ + fan.push_back(fi); + he.flipE(); + he.flipF(); + fi = he.Fi(); + ei = he.Ei(); + }while(C(fi,ei) == 0 && !he.isBorder()); + + // make a copy + V.row(pos) << V.row(v0); + I(pos) = v0; + // add one occurance to v0 + occurence(v0) += 1; + + // replace old v0 + for(Index f0: fan) + for(Index j=0;j<3;j++) + if(F(f0,j) == v0) + F(f0,j) = pos; + + // mark cuts as boundary + FF(f,k) = -1; + FF(fi,ei) = -1; + + pos++; + } + } + } + +} + + #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::cut_mesh, Eigen::Matrix, int, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, std::vector >, std::allocator > > > const&, std::vector >, std::allocator > > > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, std::vector > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::cut_mesh, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::cut_mesh, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::cut_mesh, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::cut_mesh, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::cut_mesh, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::cut_mesh, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::cut_mesh, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/cut_mesh.h b/include/igl/cut_mesh.h index e49a3e38b..1b175c8ae 100644 --- a/include/igl/cut_mesh.h +++ b/include/igl/cut_mesh.h @@ -1,78 +1,79 @@ // This file is part of libigl, a simple c++ geometry processing library. // -// Copyright (C) 2015 Olga Diamanti +// Copyright (C) 2019 Hanxiao Shen // // This Source Code Form is subject to the terms of the Mozilla Public License // v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. -#ifndef IGL_CUT_MESH -#define IGL_CUT_MESH +#ifndef IGL_CUT_MESH_H +#define IGL_CUT_MESH_H #include "igl_inline.h" #include -#include namespace igl { // Given a mesh and a list of edges that are to be cut, the function // generates a new disk-topology mesh that has the cuts at its boundary. // - // Todo: this combinatorial operation should not depend on the vertex - // positions V. // // Known issues: Assumes mesh is edge-manifold. // // Inputs: // V #V by 3 list of the vertex positions - // F #F by 3 list of the faces (must be triangles) - // VF #V list of lists of incident faces (adjacency list), e.g. as - // returned by igl::vertex_triangle_adjacency - // VFi #V list of lists of index of incidence within incident faces listed - // in VF, e.g. as returned by igl::vertex_triangle_adjacency - // TT #F by 3 triangle to triangle adjacent matrix (e.g. computed via - // igl:triangle_triangle_adjacency) - // TTi #F by 3 adjacent matrix, the element i,j is the id of edge of the - // triangle TT(i,j) that is adjacent with triangle i (e.g. computed via - // igl:triangle_triangle_adjacency) - // V_border #V by 1 list of booleans, indicating if the corresponging - // vertex is at the mesh boundary, e.g. as returned by - // igl::is_border_vertex + // F #F by 3 list of the faces // cuts #F by 3 list of boolean flags, indicating the edges that need to // be cut (has 1 at the face edges that are to be cut, 0 otherwise) // Outputs: - // Vcut #V by 3 list of the vertex positions of the cut mesh. This matrix + // Vn #V by 3 list of the vertex positions of the cut mesh. This matrix // will be similar to the original vertices except some rows will be // duplicated. - // Fcut #F by 3 list of the faces of the cut mesh(must be triangles). This + // Fn #F by 3 list of the faces of the cut mesh(must be triangles). This // matrix will be similar to the original face matrix except some indices // will be redirected to point to the newly duplicated vertices. - // - template < - typename DerivedV, - typename DerivedF, - typename VFType, - typename DerivedTT, - typename DerivedC> + // I #V by 1 list of the map between Vn to original V index. + + // In place mesh cut + template IGL_INLINE void cut_mesh( - const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, - const std::vector >& VF, - const std::vector >& VFi, - const Eigen::PlainObjectBase& TT, - const Eigen::PlainObjectBase& TTi, - const std::vector &V_border, - const Eigen::PlainObjectBase &cuts, - Eigen::PlainObjectBase &Vcut, - Eigen::PlainObjectBase &Fcut); - //Wrapper of the above with only vertices and faces as mesh input + Eigen::PlainObjectBase& V, + Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& cuts, + Eigen::PlainObjectBase& I + ); + + template + IGL_INLINE void cut_mesh( + Eigen::PlainObjectBase& V, + Eigen::PlainObjectBase& F, + Eigen::MatrixBase& FF, + Eigen::MatrixBase& FFi, + const Eigen::MatrixBase& C, + Eigen::PlainObjectBase& I + ); + template IGL_INLINE void cut_mesh( - const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, - const Eigen::PlainObjectBase &cuts, - Eigen::PlainObjectBase &Vcut, - Eigen::PlainObjectBase &Fcut); -}; + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& cuts, + Eigen::PlainObjectBase& Vn, + Eigen::PlainObjectBase& Fn + ); + + template + IGL_INLINE void cut_mesh( + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& cuts, + Eigen::PlainObjectBase& Vn, + Eigen::PlainObjectBase& Fn, + Eigen::PlainObjectBase& I + ); + + + +} #ifndef IGL_STATIC_LIBRARY diff --git a/include/igl/cut_mesh_from_singularities.cpp b/include/igl/cut_mesh_from_singularities.cpp index 382f2e063..5f6150da5 100644 --- a/include/igl/cut_mesh_from_singularities.cpp +++ b/include/igl/cut_mesh_from_singularities.cpp @@ -25,9 +25,9 @@ namespace igl { class MeshCutter { protected: - const Eigen::PlainObjectBase &V; - const Eigen::PlainObjectBase &F; - const Eigen::PlainObjectBase &Handle_MMatch; + const Eigen::MatrixBase &V; + const Eigen::MatrixBase &F; + const Eigen::MatrixBase &Handle_MMatch; Eigen::VectorXi F_visited; DerivedF TT; @@ -140,9 +140,9 @@ namespace igl { public: - inline MeshCutter(const Eigen::PlainObjectBase &V_, - const Eigen::PlainObjectBase &F_, - const Eigen::PlainObjectBase &Handle_MMatch_): + inline MeshCutter(const Eigen::MatrixBase &V_, + const Eigen::MatrixBase &F_, + const Eigen::MatrixBase &Handle_MMatch_): V(V_), F(F_), Handle_MMatch(Handle_MMatch_) @@ -184,9 +184,9 @@ template -IGL_INLINE void igl::cut_mesh_from_singularities(const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, - const Eigen::PlainObjectBase &Handle_MMatch, +IGL_INLINE void igl::cut_mesh_from_singularities(const Eigen::MatrixBase &V, + const Eigen::MatrixBase &F, + const Eigen::MatrixBase &Handle_MMatch, Eigen::PlainObjectBase &Handle_Seams) { igl::MeshCutter< DerivedV, DerivedF, DerivedM, DerivedO> mc(V, F, Handle_MMatch); @@ -195,11 +195,11 @@ IGL_INLINE void igl::cut_mesh_from_singularities(const Eigen::PlainObjectBase, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); -template void igl::cut_mesh_from_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); -template void igl::cut_mesh_from_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); -template void igl::cut_mesh_from_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); -template void igl::cut_mesh_from_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); -template void igl::cut_mesh_from_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); -template void igl::cut_mesh_from_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); +template void igl::cut_mesh_from_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::cut_mesh_from_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::cut_mesh_from_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::cut_mesh_from_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::cut_mesh_from_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::cut_mesh_from_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::cut_mesh_from_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/cut_mesh_from_singularities.h b/include/igl/cut_mesh_from_singularities.h index fb45383d3..c95adaade 100644 --- a/include/igl/cut_mesh_from_singularities.h +++ b/include/igl/cut_mesh_from_singularities.h @@ -30,9 +30,9 @@ namespace igl typename DerivedM, typename DerivedO> IGL_INLINE void cut_mesh_from_singularities( - const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, - const Eigen::PlainObjectBase &MMatch, + const Eigen::MatrixBase &V, + const Eigen::MatrixBase &F, + const Eigen::MatrixBase &MMatch, Eigen::PlainObjectBase &seams); } #ifndef IGL_STATIC_LIBRARY diff --git a/include/igl/delaunay_triangulation.cpp b/include/igl/delaunay_triangulation.cpp index dfa625d1c..0d09cc642 100644 --- a/include/igl/delaunay_triangulation.cpp +++ b/include/igl/delaunay_triangulation.cpp @@ -60,7 +60,4 @@ IGL_INLINE void igl::delaunay_triangulation( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation template void igl::delaunay_triangulation, short (*)(double const*, double const*, double const*), short (*)(double const*, double const*, double const*, double const*), Eigen::Matrix >(Eigen::MatrixBase > const&, short (*)(double const*, double const*, double const*), short (*)(double const*, double const*, double const*, double const*), Eigen::PlainObjectBase >&); -#ifdef WIN32 -template void igl::delaunay_triangulation, short(*)(double const *, double const *, double const *), short(*)(double const *, double const *, double const *, double const *), class Eigen::Matrix>(class Eigen::MatrixBase> const &, short(*const)(double const *, double const *, double const *), short(*const)(double const *, double const *, double const *, double const *), class Eigen::PlainObjectBase> &); -#endif #endif diff --git a/include/igl/deprecated.h b/include/igl/deprecated.h index 52c72ba79..6820dd320 100644 --- a/include/igl/deprecated.h +++ b/include/igl/deprecated.h @@ -8,21 +8,44 @@ #ifndef IGL_DEPRECATED_H #define IGL_DEPRECATED_H // Macro for marking a function as deprecated. -// -// http://stackoverflow.com/a/295229/148668 -#ifdef __GNUC__ -#define IGL_DEPRECATED(func) func __attribute__ ((deprecated)) -#elif defined(_MSC_VER) -#define IGL_DEPRECATED(func) __declspec(deprecated) func +// Use C++14 feature [[deprecated]] if available. +// See also https://stackoverflow.com/questions/295120/c-mark-as-deprecated/21265197#21265197 + +#ifdef __has_cpp_attribute +# define IGL_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) #else -#pragma message("WARNING: You need to implement IGL_DEPRECATED for this compiler") -#define IGL_DEPRECATED(func) func +# define IGL_HAS_CPP_ATTRIBUTE(x) 0 #endif + +#ifdef _MSC_VER +# define IGL_MSC_VER _MSC_VER +#else +# define IGL_MSC_VER 0 +#endif + +#ifndef IGL_DEPRECATED +# if (IGL_HAS_CPP_ATTRIBUTE(deprecated) && __cplusplus >= 201402L) || \ + IGL_MSC_VER >= 1900 +# define IGL_DEPRECATED [[deprecated]] +# else +# if defined(__GNUC__) || defined(__clang__) +# define IGL_DEPRECATED __attribute__((deprecated)) +# elif IGL_MSC_VER +# define IGL_DEPRECATED __declspec(deprecated) +# else +# pragma message("WARNING: You need to implement IGL_DEPRECATED for this compiler") +# define IGL_DEPRECATED /* deprecated */ +# endif +# endif +#endif + // Usage: // -// template IGL_INLINE void my_func(Arg1 a); +// template +// IGL_INLINE void my_func(Arg1 a); // -// becomes +// becomes // -// template IGL_INLINE IGL_DEPRECATED(void my_func(Arg1 a)); +// template +// IGL_DEPRECATED IGL_INLINE void my_func(Arg1 a); #endif diff --git a/include/igl/dihedral_angles.cpp b/include/igl/dihedral_angles.cpp index c4a096562..68427fdc0 100644 --- a/include/igl/dihedral_angles.cpp +++ b/include/igl/dihedral_angles.cpp @@ -17,8 +17,8 @@ template < typename Derivedtheta, typename Derivedcos_theta> IGL_INLINE void igl::dihedral_angles( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& T, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& T, Eigen::PlainObjectBase& theta, Eigen::PlainObjectBase& cos_theta) { @@ -37,8 +37,8 @@ template < typename Derivedtheta, typename Derivedcos_theta> IGL_INLINE void igl::dihedral_angles_intrinsic( - const Eigen::PlainObjectBase& L, - const Eigen::PlainObjectBase& A, + const Eigen::MatrixBase& L, + const Eigen::MatrixBase& A, Eigen::PlainObjectBase& theta, Eigen::PlainObjectBase& cos_theta) { @@ -93,6 +93,6 @@ IGL_INLINE void igl::dihedral_angles_intrinsic( } #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::dihedral_angles_intrinsic< Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(const Eigen::PlainObjectBase >&, const Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::dihedral_angles, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::dihedral_angles_intrinsic< Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(const Eigen::MatrixBase >&, const Eigen::MatrixBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::dihedral_angles, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/dihedral_angles.h b/include/igl/dihedral_angles.h index b84c9d7a6..c4fc3bc19 100644 --- a/include/igl/dihedral_angles.h +++ b/include/igl/dihedral_angles.h @@ -30,8 +30,8 @@ namespace igl typename Derivedtheta, typename Derivedcos_theta> IGL_INLINE void dihedral_angles( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& T, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& T, Eigen::PlainObjectBase& theta, Eigen::PlainObjectBase& cos_theta); template < @@ -40,8 +40,8 @@ namespace igl typename Derivedtheta, typename Derivedcos_theta> IGL_INLINE void dihedral_angles_intrinsic( - const Eigen::PlainObjectBase& L, - const Eigen::PlainObjectBase& A, + const Eigen::MatrixBase& L, + const Eigen::MatrixBase& A, Eigen::PlainObjectBase& theta, Eigen::PlainObjectBase& cos_theta); diff --git a/include/igl/dijkstra.cpp b/include/igl/dijkstra.cpp index 5c49936a1..168d817df 100644 --- a/include/igl/dijkstra.cpp +++ b/include/igl/dijkstra.cpp @@ -79,8 +79,59 @@ IGL_INLINE void igl::dijkstra( path.push_back(source); } + +template +IGL_INLINE int igl::dijkstra( + const Eigen::MatrixBase &V, + const std::vector >& VV, + const IndexType &source, + const std::set &targets, + Eigen::PlainObjectBase &min_distance, + Eigen::PlainObjectBase &previous) +{ + int numV = VV.size(); + + min_distance.setConstant(numV, 1, std::numeric_limits::infinity()); + min_distance[source] = 0; + previous.setConstant(numV, 1, -1); + std::set > vertex_queue; + vertex_queue.insert(std::make_pair(min_distance[source], source)); + + while (!vertex_queue.empty()) + { + typename DerivedD::Scalar dist = vertex_queue.begin()->first; + IndexType u = vertex_queue.begin()->second; + vertex_queue.erase(vertex_queue.begin()); + + if (targets.find(u)!= targets.end()) + return u; + + // Visit each edge exiting u + const std::vector &neighbors = VV[u]; + for (std::vector::const_iterator neighbor_iter = neighbors.begin(); + neighbor_iter != neighbors.end(); + neighbor_iter++) + { + IndexType v = *neighbor_iter; + typename DerivedD::Scalar distance_through_u = dist + (V.row(u) - V.row(v)).norm(); + if (distance_through_u < min_distance[v]) { + vertex_queue.erase(std::make_pair(min_distance[v], v)); + + min_distance[v] = distance_through_u; + previous[v] = u; + vertex_queue.insert(std::make_pair(min_distance[v], v)); + + } + + } + } + return -1; +} + #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation template int igl::dijkstra, Eigen::Matrix >(int const&, std::set, std::allocator > const&, std::vector >, std::allocator > > > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::dijkstra >(int const&, Eigen::MatrixBase > const&, std::vector >&); +template int igl::dijkstra, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, std::vector >, std::allocator > > > const&, int const&, std::set, std::allocator > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/dijkstra.h b/include/igl/dijkstra.h index 933b426ce..f2fd0c0e1 100644 --- a/include/igl/dijkstra.h +++ b/include/igl/dijkstra.h @@ -67,16 +67,40 @@ namespace igl { // previous #V by 1 list of the previous visited vertices (for each vertex) - result of Dijkstra's algorithm // // Output: - // path #P by 1 list of vertex indices in the shortest path from source to vertex + // path #P by 1 list of vertex indices in the shortest path from vertex to source // template IGL_INLINE void dijkstra( const IndexType &vertex, const Eigen::MatrixBase &previous, std::vector &path); -}; + // Dijkstra's algorithm for shortest paths on a mesh, with multiple targets, using edge length + // + // Inputs: + // V #V by 3 list of vertex positions + // VV #V list of lists of incident vertices (adjacency list), e.g. + // as returned by igl::adjacency_list, will be generated if empty. + // source index of source vertex + // targets target vector set + // + // Output: + // min_distance #V by 1 list of the minimum distances from source to all vertices + // previous #V by 1 list of the previous visited vertices (for each vertex) - used for backtracking + // + template + IGL_INLINE int dijkstra( + const Eigen::MatrixBase &V, + const std::vector >& VV, + const IndexType &source, + const std::set &targets, + Eigen::PlainObjectBase &min_distance, + Eigen::PlainObjectBase &previous); + +} + #ifndef IGL_STATIC_LIBRARY #include "dijkstra.cpp" #endif diff --git a/include/igl/directed_edge_orientations.cpp b/include/igl/directed_edge_orientations.cpp index a3308bc98..03b8a44a9 100644 --- a/include/igl/directed_edge_orientations.cpp +++ b/include/igl/directed_edge_orientations.cpp @@ -1,16 +1,16 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2015 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "directed_edge_orientations.h" template IGL_INLINE void igl::directed_edge_orientations( - const Eigen::PlainObjectBase & C, - const Eigen::PlainObjectBase & E, + const Eigen::MatrixBase & C, + const Eigen::MatrixBase & E, std::vector< Eigen::Quaterniond,Eigen::aligned_allocator > & Q) { @@ -25,5 +25,5 @@ IGL_INLINE void igl::directed_edge_orientations( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::directed_edge_orientations, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, std::vector, Eigen::aligned_allocator > >&); +template void igl::directed_edge_orientations, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::vector, Eigen::aligned_allocator > >&); #endif diff --git a/include/igl/directed_edge_orientations.h b/include/igl/directed_edge_orientations.h index b6f047147..9a8ce05bd 100644 --- a/include/igl/directed_edge_orientations.h +++ b/include/igl/directed_edge_orientations.h @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2014 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_DIRECTED_EDGE_ORIENTATIONS_H #define IGL_DIRECTED_EDGE_ORIENTATIONS_H @@ -23,12 +23,12 @@ namespace igl // C #C by 3 list of edge vertex positions // E #E by 2 list of directed edges // Outputs: - // Q #E list of quaternions + // Q #E list of quaternions // template IGL_INLINE void directed_edge_orientations( - const Eigen::PlainObjectBase & C, - const Eigen::PlainObjectBase & E, + const Eigen::MatrixBase & C, + const Eigen::MatrixBase & E, std::vector< Eigen::Quaterniond,Eigen::aligned_allocator > & Q); } diff --git a/include/igl/directed_edge_parents.cpp b/include/igl/directed_edge_parents.cpp index 52e6a41a4..b8180023c 100644 --- a/include/igl/directed_edge_parents.cpp +++ b/include/igl/directed_edge_parents.cpp @@ -14,21 +14,23 @@ template IGL_INLINE void igl::directed_edge_parents( - const Eigen::PlainObjectBase & E, + const Eigen::MatrixBase & E, Eigen::PlainObjectBase & P) { using namespace Eigen; using namespace std; - VectorXi I = VectorXi::Constant(E.maxCoeff()+1,1,-1); + typedef Eigen::Matrix VectorT; + + VectorT I = VectorT::Constant(E.maxCoeff()+1,1,-1); //I(E.col(1)) = 0:E.rows()-1 - slice_into(colon(0,E.rows()-1),E.col(1).eval(),I); - VectorXi roots,_; + slice_into(colon(0, E.rows()-1), E.col(1).eval(), I); + VectorT roots,_; setdiff(E.col(0).eval(),E.col(1).eval(),roots,_); - std::for_each(roots.data(),roots.data()+roots.size(),[&](int r){I(r)=-1;}); + std::for_each(roots.data(),roots.data()+roots.size(),[&](typename VectorT::Scalar r){I(r)=-1;}); slice(I,E.col(0).eval(),P); } #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::directed_edge_parents, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); +template void igl::directed_edge_parents, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/directed_edge_parents.h b/include/igl/directed_edge_parents.h index bf42ab8f8..5edc9dc32 100644 --- a/include/igl/directed_edge_parents.h +++ b/include/igl/directed_edge_parents.h @@ -22,7 +22,7 @@ namespace igl // template IGL_INLINE void directed_edge_parents( - const Eigen::PlainObjectBase & E, + const Eigen::MatrixBase & E, Eigen::PlainObjectBase & P); } diff --git a/include/igl/doublearea.cpp b/include/igl/doublearea.cpp index 3147c91b7..9d59a4c8e 100644 --- a/include/igl/doublearea.cpp +++ b/include/igl/doublearea.cpp @@ -231,6 +231,8 @@ IGL_INLINE void igl::doublearea_quad( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation +// generated by autoexplicit.sh +template void igl::doublearea, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); template void igl::doublearea, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::Matrix::Scalar, Eigen::PlainObjectBase >&); template void igl::doublearea, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); template void igl::doublearea, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::Matrix::Scalar, Eigen::PlainObjectBase >&); diff --git a/include/igl/dqs.cpp b/include/igl/dqs.cpp index aab3c6532..56090ef47 100644 --- a/include/igl/dqs.cpp +++ b/include/igl/dqs.cpp @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2014 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "dqs.h" #include @@ -15,8 +15,8 @@ template < typename T, typename DerivedU> IGL_INLINE void igl::dqs( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & W, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & W, const std::vector & vQ, const std::vector & vT, Eigen::PlainObjectBase & U) @@ -70,5 +70,5 @@ IGL_INLINE void igl::dqs( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::dqs, Eigen::Matrix, Eigen::Quaternion, Eigen::aligned_allocator >, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, std::vector, Eigen::aligned_allocator > > const&, std::vector, std::allocator > > const&, Eigen::PlainObjectBase >&); +template void igl::dqs, Eigen::Matrix, Eigen::Quaternion, Eigen::aligned_allocator >, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::vector, Eigen::aligned_allocator > > const&, std::vector, std::allocator > > const&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/dqs.h b/include/igl/dqs.h index 9b53ae1c7..288d308fd 100644 --- a/include/igl/dqs.h +++ b/include/igl/dqs.h @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2014 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_DQS_H #define IGL_DQS_H @@ -17,7 +17,7 @@ namespace igl // Inputs: // V #V by 3 list of rest positions // W #W by #C list of weights - // vQ #C list of rotation quaternions + // vQ #C list of rotation quaternions // vT #C list of translation vectors // Outputs: // U #V by 3 list of new positions @@ -29,8 +29,8 @@ namespace igl typename T, typename DerivedU> IGL_INLINE void dqs( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & W, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & W, const std::vector & vQ, const std::vector & vT, Eigen::PlainObjectBase & U); diff --git a/include/igl/ears.cpp b/include/igl/ears.cpp index 81576c321..428ba161b 100644 --- a/include/igl/ears.cpp +++ b/include/igl/ears.cpp @@ -15,15 +15,15 @@ IGL_INLINE void igl::ears( Eigen::PlainObjectBase & ear_opp) { assert(F.cols() == 3 && "F should contain triangles"); - Eigen::Array B; + Eigen::Array B; { - Eigen::Array I; + Eigen::Array I; on_boundary(F,I,B); } - find(B.rowwise().count() == 2,ear); - Eigen::Array Bear; - slice(B,ear,1,Bear); - Eigen::Array M; + find(B.rowwise().count() == 2, ear); + Eigen::Array Bear; + slice(B, ear, 1, Bear); + Eigen::Array M; mat_min(Bear,2,M,ear_opp); } diff --git a/include/igl/edge_lengths.cpp b/include/igl/edge_lengths.cpp index f32d4799a..6a3995646 100644 --- a/include/igl/edge_lengths.cpp +++ b/include/igl/edge_lengths.cpp @@ -22,6 +22,8 @@ IGL_INLINE void igl::edge_lengths( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template void igl::edge_lengths, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh template void igl::edge_lengths, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template void igl::edge_lengths, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); diff --git a/include/igl/edge_topology.cpp b/include/igl/edge_topology.cpp index 78147d056..1f2f66639 100644 --- a/include/igl/edge_topology.cpp +++ b/include/igl/edge_topology.cpp @@ -9,24 +9,24 @@ #include "is_edge_manifold.h" #include -template +template IGL_INLINE void igl::edge_topology( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, - Eigen::MatrixXi& EV, - Eigen::MatrixXi& FE, - Eigen::MatrixXi& EF) + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + Eigen::PlainObjectBase& EV, + Eigen::PlainObjectBase& FE, + Eigen::PlainObjectBase& EF) { // Only needs to be edge-manifold if (V.rows() ==0 || F.rows()==0) { - EV = Eigen::MatrixXi::Constant(0,2,-1); - FE = Eigen::MatrixXi::Constant(0,3,-1); - EF = Eigen::MatrixXi::Constant(0,2,-1); + EV = Eigen::PlainObjectBase::Constant(0,2,-1); + FE = Eigen::PlainObjectBase::Constant(0,3,-1); + EF = Eigen::PlainObjectBase::Constant(0,2,-1); return; } assert(igl::is_edge_manifold(F)); - std::vector > ETT; + std::vector > ETT; for(int f=0;f v2) std::swap(v1,v2); - std::vector r(4); + std::vector r(4); r[0] = v1; r[1] = v2; r[2] = f; r[3] = i; ETT.push_back(r); @@ -47,9 +47,9 @@ IGL_INLINE void igl::edge_topology( if (!((ETT[i][0] == ETT[i+1][0]) && (ETT[i][1] == ETT[i+1][1]))) ++En; - EV = Eigen::MatrixXi::Constant((int)(En),2,-1); - FE = Eigen::MatrixXi::Constant((int)(F.rows()),3,-1); - EF = Eigen::MatrixXi::Constant((int)(En),2,-1); + EV = DerivedE::Constant((int)(En),2,-1); + FE = DerivedE::Constant((int)(F.rows()),3,-1); + EF = DerivedE::Constant((int)(En),2,-1); En = 0; for(unsigned i=0;i& r1 = ETT[i]; + std::vector& r1 = ETT[i]; EV(En,0) = r1[0]; EV(En,1) = r1[1]; EF(En,0) = r1[2]; @@ -67,8 +67,8 @@ IGL_INLINE void igl::edge_topology( } else { - std::vector& r1 = ETT[i]; - std::vector& r2 = ETT[i+1]; + std::vector& r1 = ETT[i]; + std::vector& r2 = ETT[i+1]; EV(En,0) = r1[0]; EV(En,1) = r1[1]; EF(En,0) = r1[2]; @@ -84,7 +84,7 @@ IGL_INLINE void igl::edge_topology( // the first one is the face on the left of the edge for(unsigned i=0; i, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::Matrix&, Eigen::Matrix&, Eigen::Matrix&); -template void igl::edge_topology, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::Matrix&, Eigen::Matrix&, Eigen::Matrix&); +template void igl::edge_topology, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase>&, Eigen::PlainObjectBase>&, Eigen::PlainObjectBase>&); +template void igl::edge_topology, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase>&, Eigen::PlainObjectBase>&, Eigen::PlainObjectBase>&); #endif diff --git a/include/igl/edge_topology.h b/include/igl/edge_topology.h index b7a41c597..eab31aa8a 100644 --- a/include/igl/edge_topology.h +++ b/include/igl/edge_topology.h @@ -34,13 +34,13 @@ namespace igl // - FE uses non-standard and ambiguous order: FE(f,c) is merely an edge // incident on corner c of face f. In contrast, edge_flaps's EMAP(f,c) // reveals the edge _opposite_ corner c of face f -template +template IGL_INLINE void edge_topology( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, - Eigen::MatrixXi& EV, - Eigen::MatrixXi& FE, - Eigen::MatrixXi& EF); + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + Eigen::PlainObjectBase& EV, + Eigen::PlainObjectBase& FE, + Eigen::PlainObjectBase& EF); } #ifndef IGL_STATIC_LIBRARY diff --git a/include/igl/eigs.cpp b/include/igl/eigs.cpp index 1fd440ddd..766242694 100755 --- a/include/igl/eigs.cpp +++ b/include/igl/eigs.cpp @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2016 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "eigs.h" @@ -135,7 +135,7 @@ IGL_INLINE bool igl::eigs( return false; } if( - i==0 || + i==0 || (S.head(i).array()-sigma).abs().maxCoeff()>1e-14 || ((U.leftCols(i).transpose()*B*x).array().abs()<=1e-7).all() ) @@ -170,7 +170,4 @@ IGL_INLINE bool igl::eigs( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation template bool igl::eigs, Eigen::Matrix >(Eigen::SparseMatrix const&, Eigen::SparseMatrix const&, const size_t, igl::EigsType, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -#ifdef WIN32 -template bool igl::eigs, Eigen::Matrix >(Eigen::SparseMatrix const &,Eigen::SparseMatrix const &, const size_t, igl::EigsType, Eigen::PlainObjectBase< Eigen::Matrix > &, Eigen::PlainObjectBase > &); -#endif #endif diff --git a/include/igl/embree/Embree_convenience.h b/include/igl/embree/Embree_convenience.h deleted file mode 100644 index d654fb786..000000000 --- a/include/igl/embree/Embree_convenience.h +++ /dev/null @@ -1,37 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2013 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -#ifndef IGL_EMBREE_EMBREE_CONVENIENCE_H -#define IGL_EMBREE_EMBREE_CONVENIENCE_H - -#undef interface -#undef near -#undef far -// Why are these in quotes? isn't that a bad idea? -#ifdef __GNUC__ -// This is how it should be done -# if __GNUC__ >= 4 -# if __GNUC_MINOR__ >= 6 -# pragma GCC diagnostic push -# pragma GCC diagnostic ignored "-Weffc++" -# endif -# endif -// This is a hack -# pragma GCC system_header -#endif -#include -#include -#include -#ifdef __GNUC__ -# if __GNUC__ >= 4 -# if __GNUC_MINOR__ >= 6 -# pragma GCC diagnostic pop -# endif -# endif -#endif - -#endif diff --git a/include/igl/euler_characteristic.cpp b/include/igl/euler_characteristic.cpp index ab7eba22b..c3ca6303b 100644 --- a/include/igl/euler_characteristic.cpp +++ b/include/igl/euler_characteristic.cpp @@ -12,8 +12,8 @@ template IGL_INLINE int igl::euler_characteristic( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F) + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F) { int euler_v = V.rows(); @@ -41,6 +41,6 @@ IGL_INLINE int igl::euler_characteristic( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template int igl::euler_characteristic, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); +template int igl::euler_characteristic, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); template int igl::euler_characteristic >(Eigen::MatrixBase > const&); #endif diff --git a/include/igl/euler_characteristic.h b/include/igl/euler_characteristic.h index f4c0c0a0f..9a2f33edc 100644 --- a/include/igl/euler_characteristic.h +++ b/include/igl/euler_characteristic.h @@ -34,8 +34,8 @@ namespace igl // Returns An int containing the Euler characteristic template IGL_INLINE int euler_characteristic( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F); + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F); } diff --git a/include/igl/exact_geodesic.cpp b/include/igl/exact_geodesic.cpp index d962df24e..dbc50fd71 100644 --- a/include/igl/exact_geodesic.cpp +++ b/include/igl/exact_geodesic.cpp @@ -3193,20 +3193,20 @@ IGL_INLINE void igl::exact_geodesic( std::vector target(VT.rows() + FT.rows()); for (int i = 0; i < VS.rows(); i++) { - source[i] = (igl::geodesic::SurfacePoint(&mesh.vertices()[VS(i)])); + source[i] = (igl::geodesic::SurfacePoint(&mesh.vertices()[VS(i, 0)])); } for (int i = 0; i < FS.rows(); i++) { - source[i] = (igl::geodesic::SurfacePoint(&mesh.faces()[FS(i)])); + source[i] = (igl::geodesic::SurfacePoint(&mesh.faces()[FS(i, 0)])); } for (int i = 0; i < VT.rows(); i++) { - target[i] = (igl::geodesic::SurfacePoint(&mesh.vertices()[VT(i)])); + target[i] = (igl::geodesic::SurfacePoint(&mesh.vertices()[VT(i, 0)])); } for (int i = 0; i < FT.rows(); i++) { - target[i] = (igl::geodesic::SurfacePoint(&mesh.faces()[FT(i)])); + target[i] = (igl::geodesic::SurfacePoint(&mesh.faces()[FT(i, 0)])); } exact_algorithm.propagate(source); diff --git a/include/igl/extract_manifold_patches.cpp b/include/igl/extract_manifold_patches.cpp index 92269e2c8..d71ce655a 100644 --- a/include/igl/extract_manifold_patches.cpp +++ b/include/igl/extract_manifold_patches.cpp @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2016 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "extract_manifold_patches.h" #include "unique_edge_map.h" @@ -17,8 +17,8 @@ template< typename uE2EType, typename DerivedP> IGL_INLINE size_t igl::extract_manifold_patches( - const Eigen::PlainObjectBase& F, - const Eigen::PlainObjectBase& EMAP, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& EMAP, const std::vector >& uE2E, Eigen::PlainObjectBase& P) { @@ -76,12 +76,12 @@ IGL_INLINE size_t igl::extract_manifold_patches( return num_patches; } -template< - typename DerivedF, - typename DerivedP> +template < + typename DerivedF, + typename DerivedP> IGL_INLINE size_t igl::extract_manifold_patches( - const Eigen::PlainObjectBase& F, - Eigen::PlainObjectBase& P) + const Eigen::MatrixBase &F, + Eigen::PlainObjectBase &P) { Eigen::MatrixXi E, uE; Eigen::VectorXi EMAP; @@ -93,11 +93,11 @@ IGL_INLINE size_t igl::extract_manifold_patches( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh -template unsigned long igl::extract_manifold_patches, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); -template size_t igl::extract_manifold_patches, Eigen::Matrix, unsigned long, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, std::vector >, std::allocator > > > const&, Eigen::PlainObjectBase >&); -template unsigned long igl::extract_manifold_patches, Eigen::Matrix, unsigned long, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, std::vector >, std::allocator > > > const&, Eigen::PlainObjectBase >&); +template unsigned long igl::extract_manifold_patches, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template size_t igl::extract_manifold_patches, Eigen::Matrix, unsigned long, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::vector >, std::allocator > > > const&, Eigen::PlainObjectBase >&); +template unsigned long igl::extract_manifold_patches, Eigen::Matrix, unsigned long, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::vector >, std::allocator > > > const&, Eigen::PlainObjectBase >&); #ifdef WIN32 -template unsigned __int64 igl::extract_manifold_patches, class Eigen::Matrix, unsigned __int64, class Eigen::Matrix>(class Eigen::PlainObjectBase> const &, class Eigen::PlainObjectBase> const &, class std::vector>, class std::allocator>>> const &, class Eigen::PlainObjectBase> &); -template unsigned __int64 igl::extract_manifold_patches, class Eigen::Matrix, unsigned __int64, class Eigen::Matrix>(class Eigen::PlainObjectBase> const &, class Eigen::PlainObjectBase> const &, class std::vector>, class std::allocator>>> const &, class Eigen::PlainObjectBase> &); +template unsigned __int64 igl::extract_manifold_patches, class Eigen::Matrix, unsigned __int64, class Eigen::Matrix>(class Eigen::MatrixBase> const &, class Eigen::MatrixBase> const &, class std::vector>, class std::allocator>>> const &, class Eigen::PlainObjectBase> &); +template unsigned __int64 igl::extract_manifold_patches, class Eigen::Matrix, unsigned __int64, class Eigen::Matrix>(class Eigen::MatrixBase> const &, class Eigen::MatrixBase> const &, class std::vector>, class std::allocator>>> const &, class Eigen::PlainObjectBase> &); #endif #endif diff --git a/include/igl/extract_manifold_patches.h b/include/igl/extract_manifold_patches.h index 6bc25d537..c9467014b 100644 --- a/include/igl/extract_manifold_patches.h +++ b/include/igl/extract_manifold_patches.h @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2016 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_EXTRACT_MANIFOLD_PATCHES #define IGL_EXTRACT_MANIFOLD_PATCHES @@ -33,16 +33,16 @@ namespace igl { typename uE2EType, typename DerivedP> IGL_INLINE size_t extract_manifold_patches( - const Eigen::PlainObjectBase& F, - const Eigen::PlainObjectBase& EMAP, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& EMAP, const std::vector >& uE2E, Eigen::PlainObjectBase& P); template < - typename DerivedF, - typename DerivedP> + typename DerivedF, + typename DerivedP> IGL_INLINE size_t extract_manifold_patches( - const Eigen::PlainObjectBase& F, - Eigen::PlainObjectBase& P); + const Eigen::MatrixBase &F, + Eigen::PlainObjectBase &P); } #ifndef IGL_STATIC_LIBRARY # include "extract_manifold_patches.cpp" diff --git a/include/igl/face_occurrences.cpp b/include/igl/face_occurrences.cpp index bdaaa8ffd..29d07bf10 100644 --- a/include/igl/face_occurrences.cpp +++ b/include/igl/face_occurrences.cpp @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2013 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "face_occurrences.h" #include "list_to_matrix.h" @@ -60,7 +60,7 @@ IGL_INLINE void igl::face_occurrences( // Should really just rewrite using Eigen+libigl ... std::vector > vF; matrix_to_list(F,vF); - std::vector > vC; + std::vector vC; igl::face_occurrences(vF,vC); list_to_matrix(vC,C); } diff --git a/include/igl/facet_components.cpp b/include/igl/facet_components.cpp index 6397d3574..3716e41dd 100644 --- a/include/igl/facet_components.cpp +++ b/include/igl/facet_components.cpp @@ -11,7 +11,7 @@ #include template IGL_INLINE void igl::facet_components( - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & C) { using namespace std; @@ -88,7 +88,7 @@ IGL_INLINE void igl::facet_components( // Explicit template instantiation template void igl::facet_components, Eigen::Matrix >(std::vector >, std::allocator > > >, std::allocator >, std::allocator > > > > > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::facet_components, Eigen::Matrix >(std::vector >, std::allocator > > >, std::allocator >, std::allocator > > > > > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::facet_components, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); +template void igl::facet_components, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #ifdef WIN32 template void igl::facet_components<__int64,class Eigen::Matrix<__int64,-1,1,0,-1,1>,class Eigen::Matrix<__int64,-1,1,0,-1,1> >(class std::vector >,class std::allocator > > >,class std::allocator >,class std::allocator > > > > > const &,class Eigen::PlainObjectBase > &,class Eigen::PlainObjectBase > &); #endif diff --git a/include/igl/facet_components.h b/include/igl/facet_components.h index b64254c29..df09e91a3 100644 --- a/include/igl/facet_components.h +++ b/include/igl/facet_components.h @@ -22,7 +22,7 @@ namespace igl // C #F list of connected component ids template IGL_INLINE void facet_components( - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & C); // Compute connected components of facets based on edge-edge adjacency. diff --git a/include/igl/fast_winding_number.cpp b/include/igl/fast_winding_number.cpp index a69785feb..ae59fa089 100644 --- a/include/igl/fast_winding_number.cpp +++ b/include/igl/fast_winding_number.cpp @@ -4,321 +4,455 @@ #include "parallel_for.h" #include "PI.h" #include +#include -namespace igl { - template - IGL_INLINE void fast_winding_number(const Eigen::MatrixBase& P, - const Eigen::MatrixBase& N, - const Eigen::MatrixBase& A, - const std::vector > & point_indices, - const Eigen::MatrixBase& CH, - const int expansion_order, - Eigen::PlainObjectBase& CM, - Eigen::PlainObjectBase& R, - Eigen::PlainObjectBase& EC) +IGL_INLINE void igl::fast_winding_number( + const Eigen::MatrixBase& P, + const Eigen::MatrixBase& N, + const Eigen::MatrixBase& A, + const std::vector > & point_indices, + const Eigen::MatrixBase& CH, + const int expansion_order, + Eigen::PlainObjectBase& CM, + Eigen::PlainObjectBase& R, + Eigen::PlainObjectBase& EC) +{ + typedef typename DerivedP::Scalar real_p; + typedef typename DerivedN::Scalar real_n; + typedef typename DerivedA::Scalar real_a; + typedef typename DerivedCM::Scalar real_cm; + typedef typename DerivedR::Scalar real_r; + typedef typename DerivedEC::Scalar real_ec; + + typedef Eigen::Matrix RowVec3p; + + int m = CH.size(); + int num_terms; + + assert(expansion_order < 3 && expansion_order >= 0 && "m must be less than n"); + if(expansion_order == 0){ + num_terms = 3; + } else if(expansion_order ==1){ + num_terms = 3 + 9; + } else if(expansion_order == 2){ + num_terms = 3 + 9 + 27; + } + + R.resize(m); + CM.resize(m,3); + EC.resize(m,num_terms); + EC.setZero(m,num_terms); + std::function< void(const int) > helper; + helper = [&helper, + &P,&N,&A,&expansion_order,&point_indices,&CH,&EC,&R,&CM] + (const int index)-> void { - typedef typename DerivedP::Scalar real_p; - typedef typename DerivedN::Scalar real_n; - typedef typename DerivedA::Scalar real_a; - typedef typename DerivedCM::Scalar real_cm; - typedef typename DerivedR::Scalar real_r; - typedef typename DerivedEC::Scalar real_ec; - - typedef Eigen::Matrix RowVec3p; - - int m = CH.size(); - int num_terms; - - assert(expansion_order < 3 && expansion_order >= 0 && "m must be less than n"); - if(expansion_order == 0){ - num_terms = 3; - } else if(expansion_order ==1){ - num_terms = 3 + 9; - } else if(expansion_order == 2){ - num_terms = 3 + 9 + 27; - } - - R.resize(m); - CM.resize(m,3); - EC.resize(m,num_terms); - EC.setZero(m,num_terms); - std::function< void(const int) > helper; - helper = [&helper, - &P,&N,&A,&expansion_order,&point_indices,&CH,&EC,&R,&CM] - (const int index)-> void - { - Eigen::Matrix masscenter; - masscenter << 0,0,0; - Eigen::Matrix zeroth_expansion; - zeroth_expansion << 0,0,0; - real_p areatotal = 0.0; - for(int j = 0; j < point_indices.at(index).size(); j++){ - int curr_point_index = point_indices.at(index).at(j); - - areatotal += A(curr_point_index); - masscenter += A(curr_point_index)*P.row(curr_point_index); - zeroth_expansion += A(curr_point_index)*N.row(curr_point_index); - } - - masscenter = masscenter/areatotal; - CM.row(index) = masscenter; - EC.block(index,0,1,3) = zeroth_expansion; - - real_r max_norm = 0; - real_r curr_norm; - - for(int i = 0; i < point_indices.at(index).size(); i++){ - //Get max distance from center of mass: - int curr_point_index = point_indices.at(index).at(i); - Eigen::Matrix point = - P.row(curr_point_index)-masscenter; - curr_norm = point.norm(); - if(curr_norm > max_norm){ - max_norm = curr_norm; - } - - //Calculate higher order terms if necessary - Eigen::Matrix TempCoeffs; - if(EC.cols() >= (3+9)){ - TempCoeffs = A(curr_point_index)*point.transpose()* - N.row(curr_point_index); - EC.block(index,3,1,9) += - Eigen::Map >(TempCoeffs.data(), - TempCoeffs.size()); - } - - if(EC.cols() == (3+9+27)){ - for(int k = 0; k < 3; k++){ - TempCoeffs = 0.5 * point(k) * (A(curr_point_index)* - point.transpose()*N.row(curr_point_index)); - EC.block(index,12+9*k,1,9) += Eigen::Map< - Eigen::Matrix >(TempCoeffs.data(), - TempCoeffs.size()); - } - } - } - - R(index) = max_norm; - if(CH(index,0) != -1) - { - for(int i = 0; i < 8; i++){ - int child = CH(index,i); - helper(child); - } - } - }; - helper(0); - } - - template - IGL_INLINE void fast_winding_number(const Eigen::MatrixBase& P, - const Eigen::MatrixBase& N, - const Eigen::MatrixBase& A, - const std::vector > & point_indices, - const Eigen::MatrixBase& CH, - const Eigen::MatrixBase& CM, - const Eigen::MatrixBase& R, - const Eigen::MatrixBase& EC, - const Eigen::MatrixBase& Q, - const BetaType beta, - Eigen::PlainObjectBase& WN){ - - typedef typename DerivedP::Scalar real_p; - typedef typename DerivedN::Scalar real_n; - typedef typename DerivedA::Scalar real_a; - typedef typename DerivedCM::Scalar real_cm; - typedef typename DerivedR::Scalar real_r; - typedef typename DerivedEC::Scalar real_ec; - typedef typename DerivedQ::Scalar real_q; - typedef typename DerivedWN::Scalar real_wn; - - typedef Eigen::Matrix RowVec; - typedef Eigen::Matrix EC_3by3; - - auto direct_eval = [](const RowVec & loc, - const Eigen::Matrix & anorm){ - real_wn wn = (loc(0)*anorm(0)+loc(1)*anorm(1)+loc(2)*anorm(2)) - /(4.0*igl::PI*std::pow(loc.norm(),3)); - if(std::isnan(wn)){ - return 0.5; - }else{ - return wn; - } - }; - - auto expansion_eval = [&direct_eval](const RowVec & loc, - const Eigen::RowVectorXd & EC){ - real_wn wn = direct_eval(loc,EC.head<3>()); - double r = loc.norm(); - if(EC.size()>3){ - Eigen::Matrix SecondDerivative = - Eigen::Matrix::Identity()/(4.0*igl::PI*std::pow(r,3)); - SecondDerivative += -3.0*loc.transpose()*loc/(4.0*igl::PI*std::pow(r,5)); - Eigen::Matrix derivative_vector = - Eigen::Map >(SecondDerivative.data(), - SecondDerivative.size()); - wn += derivative_vector.cwiseProduct(EC.segment<9>(3)).sum(); + Eigen::Matrix masscenter; + masscenter << 0,0,0; + Eigen::Matrix zeroth_expansion; + zeroth_expansion << 0,0,0; + real_p areatotal = 0.0; + for(int j = 0; j < point_indices[index].size(); j++){ + int curr_point_index = point_indices[index][j]; + + areatotal += A(curr_point_index); + masscenter += A(curr_point_index)*P.row(curr_point_index); + zeroth_expansion += A(curr_point_index)*N.row(curr_point_index); } - if(EC.size()>3+9){ - Eigen::Matrix ThirdDerivative; - for(int i = 0; i < 3; i++){ - ThirdDerivative = - 15.0*loc(i)*loc.transpose()*loc/(4.0*igl::PI*std::pow(r,7)); - Eigen::Matrix Diagonal; - Diagonal << loc(i), 0, 0, - 0, loc(i), 0, - 0, 0, loc(i); - Eigen::Matrix RowCol; - RowCol.setZero(3,3); - RowCol.row(i) = loc; - Eigen::Matrix RowColT = RowCol.transpose(); - RowCol = RowCol + RowColT; - ThirdDerivative += - -3.0/(4.0*igl::PI*std::pow(r,5))*(RowCol+Diagonal); - Eigen::Matrix derivative_vector = - Eigen::Map >(ThirdDerivative.data(), - ThirdDerivative.size()); - wn += derivative_vector.cwiseProduct( - EC.segment<9>(12 + i*9)).sum(); - } - } - return wn; - }; - - int m = Q.rows(); - WN.resize(m,1); - - std::function< real_wn(const RowVec, const std::vector) > helper; - helper = [&helper, - &P,&N,&A, - &point_indices,&CH, - &CM,&R,&EC,&beta, - &direct_eval,&expansion_eval] - (const RowVec query, const std::vector near_indices)-> real_wn - { - std::vector new_near_indices; - real_wn wn = 0; - for(int i = 0; i < near_indices.size(); i++){ - int index = near_indices.at(i); - //Leaf Case, Brute force - if(CH(index,0) == -1){ - for(int j = 0; j < point_indices.at(index).size(); j++){ - int curr_row = point_indices.at(index).at(j); - wn += direct_eval(P.row(curr_row)-query, - N.row(curr_row)*A(curr_row)); - } - } - //Non-Leaf Case - else { - for(int child = 0; child < 8; child++){ - int child_index = CH(index,child); - if(point_indices.at(child_index).size() > 0){ - if((CM.row(child_index)-query).norm() > beta*R(child_index)){ - if(CH(child_index,0) == -1){ - for(int j=0;j 0){ - wn += helper(query,new_near_indices); - } - return wn; - }; - - - if(beta > 0){ - std::vector near_indices_start = {0}; - igl::parallel_for(m,[&](int iter){ - WN(iter) = helper(Q.row(iter),near_indices_start); - },1000); - } else { - igl::parallel_for(m,[&](int iter){ - double wn = 0; - for(int j = 0; j - IGL_INLINE void fast_winding_number(const Eigen::MatrixBase& P, - const Eigen::MatrixBase& N, - const Eigen::MatrixBase& A, - const Eigen::MatrixBase& Q, - const int expansion_order, - const BetaType beta, - Eigen::PlainObjectBase& WN - ){ - typedef typename DerivedWN::Scalar real; - std::vector > point_indices; - Eigen::Matrix CH; - Eigen::Matrix CN; - Eigen::Matrix W; - - octree(P,point_indices,CH,CN,W); - - Eigen::Matrix EC; - Eigen::Matrix CM; - Eigen::Matrix R; - - fast_winding_number(P,N,A,point_indices,CH,expansion_order,CM,R,EC); - fast_winding_number(P,N,A,point_indices,CH,CM,R,EC,Q,beta,WN); - } - - template - IGL_INLINE void fast_winding_number(const Eigen::MatrixBase& P, - const Eigen::MatrixBase& N, - const Eigen::MatrixBase& A, - const Eigen::MatrixBase& Q, - Eigen::PlainObjectBase& WN - ){ - fast_winding_number(P,N,A,Q,2,2.0,WN); + masscenter = masscenter/areatotal; + CM.row(index) = masscenter; + EC.block(index,0,1,3) = zeroth_expansion; + + real_r max_norm = 0; + real_r curr_norm; + + for(int i = 0; i < point_indices[index].size(); i++){ + //Get max distance from center of mass: + int curr_point_index = point_indices[index][i]; + Eigen::Matrix point = + P.row(curr_point_index)-masscenter; + curr_norm = point.norm(); + if(curr_norm > max_norm){ + max_norm = curr_norm; + } + + //Calculate higher order terms if necessary + Eigen::Matrix TempCoeffs; + if(EC.cols() >= (3+9)){ + TempCoeffs = A(curr_point_index)*point.transpose()* + N.row(curr_point_index); + EC.block(index,3,1,9) += + Eigen::Map >(TempCoeffs.data(), + TempCoeffs.size()); + } + + if(EC.cols() == (3+9+27)){ + for(int k = 0; k < 3; k++){ + TempCoeffs = 0.5 * point(k) * (A(curr_point_index)* + point.transpose()*N.row(curr_point_index)); + EC.block(index,12+9*k,1,9) += Eigen::Map< + Eigen::Matrix >(TempCoeffs.data(), + TempCoeffs.size()); + } + } + } + + R(index) = max_norm; + if(CH(index,0) != -1) + { + for(int i = 0; i < 8; i++){ + int child = CH(index,i); + helper(child); + } + } + }; + helper(0); +} + +template < + typename DerivedP, + typename DerivedA, + typename DerivedN, + typename Index, + typename DerivedCH, + typename DerivedCM, + typename DerivedR, + typename DerivedEC, + typename DerivedQ, + typename BetaType, + typename DerivedWN> +IGL_INLINE void igl::fast_winding_number( + const Eigen::MatrixBase& P, + const Eigen::MatrixBase& N, + const Eigen::MatrixBase& A, + const std::vector > & point_indices, + const Eigen::MatrixBase& CH, + const Eigen::MatrixBase& CM, + const Eigen::MatrixBase& R, + const Eigen::MatrixBase& EC, + const Eigen::MatrixBase& Q, + const BetaType beta, + Eigen::PlainObjectBase& WN) +{ + + typedef typename DerivedP::Scalar real_p; + typedef typename DerivedN::Scalar real_n; + typedef typename DerivedA::Scalar real_a; + typedef typename DerivedCM::Scalar real_cm; + typedef typename DerivedR::Scalar real_r; + typedef typename DerivedEC::Scalar real_ec; + typedef typename DerivedQ::Scalar real_q; + typedef typename DerivedWN::Scalar real_wn; + const real_wn PI_4 = 4.0*igl::PI; + + typedef Eigen::Matrix< + typename DerivedEC::Scalar, + 1, + DerivedEC::ColsAtCompileTime> ECRow; + + typedef Eigen::Matrix RowVec; + typedef Eigen::Matrix EC_3by3; + + auto direct_eval = [&PI_4]( + const RowVec & loc, + const Eigen::Matrix & anorm)->real_wn + { + const typename RowVec::Scalar loc_norm = loc.norm(); + if(loc_norm == 0) + { + return 0.5; + }else + { + return (loc(0)*anorm(0)+loc(1)*anorm(1)+loc(2)*anorm(2)) + /(PI_4*(loc_norm*loc_norm*loc_norm)); + } + }; + + auto expansion_eval = + [&direct_eval,&EC,&PI_4]( + const RowVec & loc, + const int & child_index)->real_wn + { + real_wn wn; + wn = direct_eval(loc,EC.row(child_index).template head<3>()); + real_wn r = loc.norm(); + real_wn PI_4_r3; + real_wn PI_4_r5; + real_wn PI_4_r7; + if(EC.row(child_index).size()>3) + { + PI_4_r3 = PI_4*r*r*r; + PI_4_r5 = PI_4_r3*r*r; + const real_ec d = 1.0/(PI_4_r3); + Eigen::Matrix SecondDerivative = + loc.transpose()*loc*(-3.0/(PI_4_r5)); + SecondDerivative(0,0) += d; + SecondDerivative(1,1) += d; + SecondDerivative(2,2) += d; + wn += + Eigen::Map >( + SecondDerivative.data(), + SecondDerivative.size()).dot( + EC.row(child_index).template segment<9>(3)); + } + if(EC.row(child_index).size()>3+9) + { + PI_4_r7 = PI_4_r5*r*r; + const Eigen::Matrix locTloc = loc.transpose()*(loc/(PI_4_r7)); + for(int i = 0; i < 3; i++) + { + Eigen::Matrix RowCol_Diagonal = + Eigen::Matrix::Zero(3,3); + for(int u = 0;u<3;u++) + { + for(int v = 0;v<3;v++) + { + if(u==v) RowCol_Diagonal(u,v) += loc(i); + if(u==i) RowCol_Diagonal(u,v) += loc(v); + if(v==i) RowCol_Diagonal(u,v) += loc(u); + } + } + Eigen::Matrix ThirdDerivative = + 15.0*loc(i)*locTloc + (-3.0/(PI_4_r5))*(RowCol_Diagonal); + + wn += Eigen::Map >( + ThirdDerivative.data(), + ThirdDerivative.size()).dot( + EC.row(child_index).template segment<9>(12 + i*9)); + } + } + return wn; + }; + + int m = Q.rows(); + WN.resize(m,1); + + std::function< real_wn(const RowVec & , const std::vector &) > helper; + helper = [&helper, + &P,&N,&A, + &point_indices,&CH, + &CM,&R,&EC,&beta, + &direct_eval,&expansion_eval] + (const RowVec & query, const std::vector & near_indices)-> real_wn + { + real_wn wn = 0; + std::vector new_near_indices; + new_near_indices.reserve(8); + for(int i = 0; i < near_indices.size(); i++) + { + int index = near_indices[i]; + //Leaf Case, Brute force + if(CH(index,0) == -1) + { + for(int j = 0; j < point_indices[index].size(); j++) + { + int curr_row = point_indices[index][j]; + wn += direct_eval(P.row(curr_row)-query, + N.row(curr_row)*A(curr_row)); + } + } + //Non-Leaf Case + else + { + for(int child = 0; child < 8; child++) + { + int child_index = CH(index,child); + if(point_indices[child_index].size() > 0) + { + const RowVec CMciq = (CM.row(child_index)-query); + if(CMciq.norm() > beta*R(child_index)) + { + if(CH(child_index,0) == -1) + { + for(int j=0;j 0) + { + wn += helper(query,new_near_indices); + } + return wn; + }; + + if(beta > 0) + { + const std::vector near_indices_start = {0}; + igl::parallel_for(m,[&](int iter){ + WN(iter) = helper(Q.row(iter).eval(),near_indices_start); + },1000); + } else + { + igl::parallel_for(m,[&](int iter){ + double wn = 0; + for(int j = 0; j +IGL_INLINE void igl::fast_winding_number( + const Eigen::MatrixBase& P, + const Eigen::MatrixBase& N, + const Eigen::MatrixBase& A, + const Eigen::MatrixBase& Q, + const int expansion_order, + const BetaType beta, + Eigen::PlainObjectBase& WN) +{ + typedef typename DerivedWN::Scalar real; + + std::vector > point_indices; + Eigen::Matrix CH; + Eigen::Matrix CN; + Eigen::Matrix W; + + octree(P,point_indices,CH,CN,W); + + Eigen::Matrix EC; + Eigen::Matrix CM; + Eigen::Matrix R; + + fast_winding_number(P,N,A,point_indices,CH,expansion_order,CM,R,EC); + fast_winding_number(P,N,A,point_indices,CH,CM,R,EC,Q,beta,WN); +} + +template < + typename DerivedP, + typename DerivedA, + typename DerivedN, + typename DerivedQ, + typename DerivedWN> +IGL_INLINE void igl::fast_winding_number( + const Eigen::MatrixBase& P, + const Eigen::MatrixBase& N, + const Eigen::MatrixBase& A, + const Eigen::MatrixBase& Q, + Eigen::PlainObjectBase& WN) +{ + fast_winding_number(P,N,A,Q,2,2.0,WN); +} + +template < + typename DerivedV, + typename DerivedF, + typename DerivedQ, + typename DerivedW> +IGL_INLINE void igl::fast_winding_number( + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const Eigen::MatrixBase & Q, + Eigen::PlainObjectBase & W) +{ + igl::FastWindingNumberBVH fwn_bvh; + int order = 2; + igl::fast_winding_number(V,F,order,fwn_bvh); + float accuracy_scale = 2; + igl::fast_winding_number(fwn_bvh,accuracy_scale,Q,W); +} + +template < + typename DerivedV, + typename DerivedF> +IGL_INLINE void igl::fast_winding_number( + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const int order, + FastWindingNumberBVH & fwn_bvh) +{ + assert(V.cols() == 3 && "V should be 3D"); + assert(F.cols() == 3 && "F should contain triangles"); + // Extra copies. Usuually this won't be the bottleneck. + fwn_bvh.U.resize(V.rows()); + for(int i = 0;i +IGL_INLINE void igl::fast_winding_number( + const FastWindingNumberBVH & fwn_bvh, + const float accuracy_scale, + const Eigen::MatrixBase & Q, + Eigen::PlainObjectBase & W) +{ + assert(Q.cols() == 3 && "Q should be 3D"); + W.resize(Q.rows(),1); + igl::parallel_for(Q.rows(),[&](int p) + { + FastWindingNumber::HDK_Sample::UT_Vector3TQp; + Qp[0] = Q(p,0); + Qp[1] = Q(p,1); + Qp[2] = Q(p,2); + W(p) = fwn_bvh.ut_solid_angle.computeSolidAngle( + Qp, + accuracy_scale) + / (4.0*igl::PI); + },1000); +} - - - - - - - - - - - - - - - - - - - - - - +#ifdef IGL_STATIC_LIBRARY +// Explicit template instantiation +template void igl::fast_winding_number, Eigen::Matrix, Eigen::Matrix, int, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, int, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::vector >, std::allocator > > > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::fast_winding_number, Eigen::Matrix, Eigen::Matrix, int, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::vector >, std::allocator > > > const&, Eigen::MatrixBase > const&, int, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::fast_winding_number, Eigen::Matrix >(igl::FastWindingNumberBVH const&, float, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::fast_winding_number, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, igl::FastWindingNumberBVH&); +template void igl::fast_winding_number, Eigen::Matrix >(igl::FastWindingNumberBVH const&, float, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::fast_winding_number, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, igl::FastWindingNumberBVH&); +#endif diff --git a/include/igl/fast_winding_number.h b/include/igl/fast_winding_number.h index dc2c002ca..845483432 100644 --- a/include/igl/fast_winding_number.h +++ b/include/igl/fast_winding_number.h @@ -1,6 +1,7 @@ #ifndef IGL_FAST_WINDING_NUMBER #define IGL_FAST_WINDING_NUMBER #include "igl_inline.h" +#include "FastWindingNumberForSoups.h" #include #include namespace igl @@ -12,8 +13,8 @@ namespace igl // data, and an expansion order, we define a taylor series expansion at each // octree cell. // - // The octree data is designed to come from igl::octree, and the areas - // (if not obtained at scan time), may be calculated using + // The octree data is designed to come from igl::octree, and the areas (if not + // obtained at scan time), may be calculated using // igl::copyleft::cgal::point_areas. // // Inputs: @@ -32,19 +33,26 @@ namespace igl // EC #OctreeCells by #TaylorCoefficients list of expansion coefficients. // (Note that #TaylorCoefficients = ∑_{i=1}^{expansion_order} 3^i) // - template - IGL_INLINE void fast_winding_number(const Eigen::MatrixBase& P, - const Eigen::MatrixBase& N, - const Eigen::MatrixBase& A, - const std::vector > & point_indices, - const Eigen::MatrixBase& CH, - const int expansion_order, - Eigen::PlainObjectBase& CM, - Eigen::PlainObjectBase& R, - Eigen::PlainObjectBase& EC); - + IGL_INLINE void fast_winding_number( + const Eigen::MatrixBase& P, + const Eigen::MatrixBase& N, + const Eigen::MatrixBase& A, + const std::vector > & point_indices, + const Eigen::MatrixBase& CH, + const int expansion_order, + Eigen::PlainObjectBase& CM, + Eigen::PlainObjectBase& R, + Eigen::PlainObjectBase& EC); // Evaluate the fast winding number for point data, having already done the // the precomputation // @@ -70,22 +78,45 @@ namespace igl // Outputs: // WN #Q by 1 list of windinng number values at each query point // - template - IGL_INLINE void fast_winding_number(const Eigen::MatrixBase& P, - const Eigen::MatrixBase& N, - const Eigen::MatrixBase& A, - const std::vector > & point_indices, - const Eigen::MatrixBase& CH, - const Eigen::MatrixBase& CM, - const Eigen::MatrixBase& R, - const Eigen::MatrixBase& EC, - const Eigen::MatrixBase& Q, - const BetaType beta, - Eigen::PlainObjectBase& WN); - + IGL_INLINE void fast_winding_number( + const Eigen::MatrixBase& P, + const Eigen::MatrixBase& N, + const Eigen::MatrixBase& A, + const std::vector > & point_indices, + const Eigen::MatrixBase& CH, + const Eigen::MatrixBase& CM, + const Eigen::MatrixBase& R, + const Eigen::MatrixBase& EC, + const Eigen::MatrixBase& Q, + const BetaType beta, + Eigen::PlainObjectBase& WN); + template < + typename DerivedP, + typename DerivedA, + typename DerivedN, + typename DerivedQ, + typename BetaType, + typename DerivedWN> + IGL_INLINE void fast_winding_number( + const Eigen::MatrixBase& P, + const Eigen::MatrixBase& N, + const Eigen::MatrixBase& A, + const Eigen::MatrixBase& Q, + const int expansion_order, + const BetaType beta, + Eigen::PlainObjectBase& WN); // Evaluate the fast winding number for point data, with default expansion // order and beta (both are set to 2). // @@ -101,14 +132,80 @@ namespace igl // Outputs: // WN #Q by 1 list of windinng number values at each query point // - template - IGL_INLINE void fast_winding_number(const Eigen::MatrixBase& P, - const Eigen::MatrixBase& N, - const Eigen::MatrixBase& A, - const Eigen::MatrixBase& Q, - Eigen::PlainObjectBase& WN - ); + template < + typename DerivedP, + typename DerivedA, + typename DerivedN, + typename DerivedQ, + typename DerivedWN> + IGL_INLINE void fast_winding_number( + const Eigen::MatrixBase& P, + const Eigen::MatrixBase& N, + const Eigen::MatrixBase& A, + const Eigen::MatrixBase& Q, + Eigen::PlainObjectBase& WN); + // Class declaration + namespace FastWindingNumber { namespace HDK_Sample{ template class UT_SolidAngle;} } + struct FastWindingNumberBVH { + FastWindingNumber::HDK_Sample::UT_SolidAngle ut_solid_angle; + // Need copies of these so they stay alive between calls. + std::vector > U; + std::vector F; + }; + // Compute approximate winding number of a triangle soup mesh according to + // "Fast Winding Numbers for Soups and Clouds" [Barill et al. 2018]. + // + // Inputs: + // V #V by 3 list of mesh vertex positions + // F #F by 3 list of triangle mesh indices into rows of V + // Q #Q by 3 list of query positions + // Outputs: + // W #Q list of winding number values + template < + typename DerivedV, + typename DerivedF, + typename DerivedQ, + typename DerivedW> + IGL_INLINE void fast_winding_number( + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const Eigen::MatrixBase & Q, + Eigen::PlainObjectBase & W); + // Precomputation for computing approximate winding numbers of a triangle + // soup. + // + // Inputs: + // V #V by 3 list of mesh vertex positions + // F #F by 3 list of triangle mesh indices into rows of V + // order Taylor series expansion order to use (e.g., 2) + // Outputs: + // fwn_bvh Precomputed bounding volume hierarchy + // + template < + typename DerivedV, + typename DerivedF> + IGL_INLINE void fast_winding_number( + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const int order, + FastWindingNumberBVH & fwn_bvh); + // After precomputation, compute winding number at a each of many points in a + // list. + // + // Inputs: + // fwn_bvh Precomputed bounding volume hierarchy + // accuracy_scale parameter controlling accuracy (e.g., 2) + // Q #Q by 3 list of query positions + // Outputs: + // W #Q list of winding number values + template < + typename DerivedQ, + typename DerivedW> + IGL_INLINE void fast_winding_number( + const FastWindingNumberBVH & fwn_bvh, + const float accuracy_scale, + const Eigen::MatrixBase & Q, + Eigen::PlainObjectBase & W); } #ifndef IGL_STATIC_LIBRARY # include "fast_winding_number.cpp" diff --git a/include/igl/file_dialog_open.cpp b/include/igl/file_dialog_open.cpp index 66c2aca0e..fcfe73ff2 100644 --- a/include/igl/file_dialog_open.cpp +++ b/include/igl/file_dialog_open.cpp @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2014 Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "file_dialog_open.h" #include @@ -13,7 +13,7 @@ #include #undef max #undef min - + #include #endif @@ -21,7 +21,9 @@ IGL_INLINE std::string igl::file_dialog_open() { const int FILE_DIALOG_MAX_BUFFER = 1024; char buffer[FILE_DIALOG_MAX_BUFFER]; - + buffer[0] = '\0'; + buffer[FILE_DIALOG_MAX_BUFFER - 1] = 'x'; // Initialize last character with a char != '\0' + #ifdef __APPLE__ // For apple use applescript hack FILE * output = popen( @@ -32,11 +34,22 @@ IGL_INLINE std::string igl::file_dialog_open() " end tell\n" " set existing_file_path to (POSIX path of (existing_file))\n" "\" 2>/dev/null | tr -d '\n' ","r"); - while ( fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) != NULL ) + if (output) { + auto ret = fgets(buffer, FILE_DIALOG_MAX_BUFFER, output); + if (ret == NULL || ferror(output)) + { + // I/O error + buffer[0] = '\0'; + } + if (buffer[FILE_DIALOG_MAX_BUFFER - 1] == '\0') + { + // File name too long, buffer has been filled, so we return empty string instead + buffer[0] = '\0'; + } } #elif defined _WIN32 - + // Use native windows file dialog box // (code contributed by Tino Weinkauf) @@ -48,7 +61,7 @@ IGL_INLINE std::string igl::file_dialog_open() ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = NULL; ofn.lpstrFile = new char[100]; - // Set lpstrFile[0] to '\0' so that GetOpenFileName does not + // Set lpstrFile[0] to '\0' so that GetOpenFileName does not // use the contents of szFile to initialize itself. ofn.lpstrFile[0] = '\0'; ofn.nMaxFile = sizeof(szFile); @@ -59,7 +72,7 @@ IGL_INLINE std::string igl::file_dialog_open() ofn.lpstrInitialDir = NULL; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; - // Display the Open dialog box. + // Display the Open dialog box. int pos = 0; if (GetOpenFileName(&ofn)==TRUE) { @@ -68,20 +81,33 @@ IGL_INLINE std::string igl::file_dialog_open() buffer[pos] = (char)ofn.lpstrFile[pos]; pos++; } - } + } buffer[pos] = 0; #else - + // For linux use zenity FILE * output = popen("/usr/bin/zenity --file-selection","r"); - while ( fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) != NULL ) + if (output) { + auto ret = fgets(buffer, FILE_DIALOG_MAX_BUFFER, output); + if (ret == NULL || ferror(output)) + { + // I/O error + buffer[0] = '\0'; + } + if (buffer[FILE_DIALOG_MAX_BUFFER - 1] == '\0') + { + // File name too long, buffer has been filled, so we return empty string instead + buffer[0] = '\0'; + } } - - if (strlen(buffer) > 0) + + // Replace last '\n' by '\0' + if(strlen(buffer) > 0) { - buffer[strlen(buffer)-1] = 0; + buffer[strlen(buffer)-1] = '\0'; } + #endif return std::string(buffer); } diff --git a/include/igl/file_dialog_save.cpp b/include/igl/file_dialog_save.cpp index 90687fa5c..008b772e4 100644 --- a/include/igl/file_dialog_save.cpp +++ b/include/igl/file_dialog_save.cpp @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2014 Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "file_dialog_save.h" #include @@ -18,6 +18,9 @@ IGL_INLINE std::string igl::file_dialog_save() { const int FILE_DIALOG_MAX_BUFFER = 1024; char buffer[FILE_DIALOG_MAX_BUFFER]; + buffer[0] = '\0'; + buffer[FILE_DIALOG_MAX_BUFFER - 1] = 'x'; // Initialize last character with a char != '\0' + #ifdef __APPLE__ // For apple use applescript hack // There is currently a bug in Applescript that strips extensions off @@ -31,8 +34,19 @@ IGL_INLINE std::string igl::file_dialog_save() " end tell\n" " set existing_file_path to (POSIX path of (existing_file))\n" "\" 2>/dev/null | tr -d '\n' ","r"); - while ( fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) != NULL ) + if (output) { + auto ret = fgets(buffer, FILE_DIALOG_MAX_BUFFER, output); + if (ret == NULL || ferror(output)) + { + // I/O error + buffer[0] = '\0'; + } + if (buffer[FILE_DIALOG_MAX_BUFFER - 1] == '\0') + { + // File name too long, buffer has been filled, so we return empty string instead + buffer[0] = '\0'; + } } #elif defined _WIN32 @@ -47,7 +61,7 @@ IGL_INLINE std::string igl::file_dialog_save() ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = NULL;//hwnd; ofn.lpstrFile = new char[100]; - // Set lpstrFile[0] to '\0' so that GetOpenFileName does not + // Set lpstrFile[0] to '\0' so that GetOpenFileName does not // use the contents of szFile to initialize itself. ofn.lpstrFile[0] = '\0'; ofn.nMaxFile = sizeof(szFile); @@ -58,7 +72,7 @@ IGL_INLINE std::string igl::file_dialog_save() ofn.lpstrInitialDir = NULL; ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST; - // Display the Open dialog box. + // Display the Open dialog box. int pos = 0; if (GetSaveFileName(&ofn)==TRUE) { @@ -73,14 +87,27 @@ IGL_INLINE std::string igl::file_dialog_save() #else // For every other machine type use zenity FILE * output = popen("/usr/bin/zenity --file-selection --save","r"); - while ( fgets(buffer, FILE_DIALOG_MAX_BUFFER, output) != NULL ) + if (output) { + auto ret = fgets(buffer, FILE_DIALOG_MAX_BUFFER, output); + if (ret == NULL || ferror(output)) + { + // I/O error + buffer[0] = '\0'; + } + if (buffer[FILE_DIALOG_MAX_BUFFER - 1] == '\0') + { + // File name too long, buffer has been filled, so we return empty string instead + buffer[0] = '\0'; + } } - - if (strlen(buffer) > 0) + + // Replace last '\n' by '\0' + if(strlen(buffer) > 0) { - buffer[strlen(buffer)-1] = 0; + buffer[strlen(buffer)-1] = '\0'; } + #endif return std::string(buffer); } diff --git a/include/igl/find.cpp b/include/igl/find.cpp index 6beb91c52..6bef11139 100644 --- a/include/igl/find.cpp +++ b/include/igl/find.cpp @@ -132,8 +132,6 @@ template void igl::find, Eigen::Mat template void igl::find, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); #if EIGEN_VERSION_AT_LEAST(3,3,0) #else -template void igl::find, Eigen::PartialReduxExpr, Eigen::internal::member_count, 1> const, Eigen::CwiseNullaryOp, Eigen::Array > const>, Eigen::Matrix >(Eigen::DenseBase, Eigen::PartialReduxExpr, Eigen::internal::member_count, 1> const, Eigen::CwiseNullaryOp, Eigen::Array > const> > const&, Eigen::PlainObjectBase >&); -template void igl::find, Eigen::Array const, Eigen::CwiseNullaryOp, Eigen::Array > const>, Eigen::Matrix >(Eigen::DenseBase, Eigen::Array const, Eigen::CwiseNullaryOp, Eigen::Array > const> > const&, Eigen::PlainObjectBase >&); #endif #endif diff --git a/include/igl/find_cross_field_singularities.cpp b/include/igl/find_cross_field_singularities.cpp index 12222ca20..f3e3f491d 100644 --- a/include/igl/find_cross_field_singularities.cpp +++ b/include/igl/find_cross_field_singularities.cpp @@ -16,13 +16,13 @@ template -IGL_INLINE void igl::find_cross_field_singularities(const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, - const Eigen::PlainObjectBase &Handle_MMatch, +IGL_INLINE void igl::find_cross_field_singularities(const Eigen::MatrixBase &V, + const Eigen::MatrixBase &F, + const Eigen::MatrixBase &Handle_MMatch, Eigen::PlainObjectBase &isSingularity, Eigen::PlainObjectBase &singularityIndex) { - std::vector V_border = igl::is_border_vertex(V,F); + std::vector V_border = igl::is_border_vertex(F); std::vector > VF; std::vector > VFi; @@ -59,10 +59,10 @@ IGL_INLINE void igl::find_cross_field_singularities(const Eigen::PlainObjectBase } template -IGL_INLINE void igl::find_cross_field_singularities(const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, - const Eigen::PlainObjectBase &PD1, - const Eigen::PlainObjectBase &PD2, +IGL_INLINE void igl::find_cross_field_singularities(const Eigen::MatrixBase &V, + const Eigen::MatrixBase &F, + const Eigen::MatrixBase &PD1, + const Eigen::MatrixBase &PD2, Eigen::PlainObjectBase &isSingularity, Eigen::PlainObjectBase &singularityIndex, bool isCombed) @@ -75,11 +75,11 @@ IGL_INLINE void igl::find_cross_field_singularities(const Eigen::PlainObjectBase #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::find_cross_field_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::find_cross_field_singularities, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, -Eigen::PlainObjectBase >&, bool); -template void igl::find_cross_field_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::find_cross_field_singularities, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, bool); -template void igl::find_cross_field_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::find_cross_field_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::find_cross_field_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::find_cross_field_singularities, Eigen::Matrix, Eigen::Matrix>(Eigen::MatrixBase> const &, Eigen::MatrixBase> const &, Eigen::MatrixBase> const &, Eigen::MatrixBase> const &, Eigen::PlainObjectBase> &, + Eigen::PlainObjectBase> &, bool); +template void igl::find_cross_field_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::find_cross_field_singularities, Eigen::Matrix, Eigen::Matrix>(Eigen::MatrixBase> const &, Eigen::MatrixBase> const &, Eigen::MatrixBase> const &, Eigen::MatrixBase> const &, Eigen::PlainObjectBase> &, Eigen::PlainObjectBase> &, bool); +template void igl::find_cross_field_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::find_cross_field_singularities, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/find_cross_field_singularities.h b/include/igl/find_cross_field_singularities.h index 66cdca586..94581d30e 100644 --- a/include/igl/find_cross_field_singularities.h +++ b/include/igl/find_cross_field_singularities.h @@ -25,9 +25,9 @@ namespace igl // singularityIndex #V by 1 integer eigen Vector containing the singularity indices // template - IGL_INLINE void find_cross_field_singularities(const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, - const Eigen::PlainObjectBase &mismatch, + IGL_INLINE void find_cross_field_singularities(const Eigen::MatrixBase &V, + const Eigen::MatrixBase &F, + const Eigen::MatrixBase &mismatch, Eigen::PlainObjectBase &isSingularity, Eigen::PlainObjectBase &singularityIndex); @@ -43,10 +43,10 @@ namespace igl // singularityIndex #V by 1 integer eigen Vector containing the singularity indices // template - IGL_INLINE void find_cross_field_singularities(const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, - const Eigen::PlainObjectBase &PD1, - const Eigen::PlainObjectBase &PD2, + IGL_INLINE void find_cross_field_singularities(const Eigen::MatrixBase &V, + const Eigen::MatrixBase &F, + const Eigen::MatrixBase &PD1, + const Eigen::MatrixBase &PD2, Eigen::PlainObjectBase &isSingularity, Eigen::PlainObjectBase &singularityIndex, bool isCombed = false); diff --git a/include/igl/flipped_triangles.cpp b/include/igl/flipped_triangles.cpp index ea76e5c84..775366e79 100644 --- a/include/igl/flipped_triangles.cpp +++ b/include/igl/flipped_triangles.cpp @@ -11,8 +11,8 @@ #include template IGL_INLINE void igl::flipped_triangles( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & X) { assert(V.cols() == 2 && "V should contain 2D positions"); @@ -40,8 +40,8 @@ IGL_INLINE void igl::flipped_triangles( template IGL_INLINE Eigen::VectorXi igl::flipped_triangles( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F) + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F) { Eigen::VectorXi X; flipped_triangles(V,F,X); @@ -50,6 +50,6 @@ IGL_INLINE Eigen::VectorXi igl::flipped_triangles( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::flipped_triangles, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); -template Eigen::Matrix igl::flipped_triangles, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); +template void igl::flipped_triangles, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template Eigen::Matrix igl::flipped_triangles, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); #endif diff --git a/include/igl/flipped_triangles.h b/include/igl/flipped_triangles.h index b06d9329b..2d119921f 100644 --- a/include/igl/flipped_triangles.h +++ b/include/igl/flipped_triangles.h @@ -22,13 +22,13 @@ namespace igl // Wrapper with return type template IGL_INLINE void flipped_triangles( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & X); template IGL_INLINE Eigen::VectorXi flipped_triangles( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F); + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F); } diff --git a/include/igl/gaussian_curvature.cpp b/include/igl/gaussian_curvature.cpp index ca05129df..9a0a1f871 100644 --- a/include/igl/gaussian_curvature.cpp +++ b/include/igl/gaussian_curvature.cpp @@ -11,8 +11,8 @@ #include template IGL_INLINE void igl::gaussian_curvature( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, Eigen::PlainObjectBase & K) { using namespace Eigen; @@ -51,6 +51,6 @@ IGL_INLINE void igl::gaussian_curvature( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::gaussian_curvature, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); -template void igl::gaussian_curvature, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); +template void igl::gaussian_curvature, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::gaussian_curvature, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/gaussian_curvature.h b/include/igl/gaussian_curvature.h index d8ddbc8ad..e9313cc3d 100644 --- a/include/igl/gaussian_curvature.h +++ b/include/igl/gaussian_curvature.h @@ -22,8 +22,8 @@ namespace igl // template IGL_INLINE void gaussian_curvature( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, Eigen::PlainObjectBase & K); } diff --git a/include/igl/grid.cpp b/include/igl/grid.cpp index 38cf103f6..2e7df459a 100644 --- a/include/igl/grid.cpp +++ b/include/igl/grid.cpp @@ -48,6 +48,8 @@ IGL_INLINE void igl::grid( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template void igl::grid, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh template void igl::grid, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template void igl::grid, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); diff --git a/include/igl/grid.h b/include/igl/grid.h index fe5eff05e..766c3cb8d 100644 --- a/include/igl/grid.h +++ b/include/igl/grid.h @@ -16,10 +16,12 @@ namespace igl // `igl::marching_cubes` // // Inputs: - // res #res list of number of vertices along each dimension + // res #res list of number of vertices along each dimension filling a unit + // #res-cube // Outputs: // GV res.array().prod() by #res list of mesh vertex positions. // + // See also: triangulated_grid, quad_grid template < typename Derivedres, typename DerivedGV> diff --git a/include/igl/harmonic.cpp b/include/igl/harmonic.cpp index aa07245a1..677d01550 100644 --- a/include/igl/harmonic.cpp +++ b/include/igl/harmonic.cpp @@ -77,8 +77,8 @@ template < typename Derivedbc, typename DerivedW> IGL_INLINE bool igl::harmonic( - const Eigen::SparseMatrix & L, - const Eigen::SparseMatrix & M, + const Eigen::SparseCompressedBase & L, + const Eigen::SparseCompressedBase & M, const Eigen::MatrixBase & b, const Eigen::MatrixBase & bc, const int k, @@ -89,15 +89,16 @@ IGL_INLINE bool igl::harmonic( assert((k==1 || n == M.cols() ) && "M must be same size as L"); assert((k==1 || n == M.rows() ) && "M must be square"); assert((k==1 || igl::isdiag(M)) && "Mass matrix should be diagonal"); + typedef typename DerivedL::Scalar Scalar; - Eigen::SparseMatrix Q; + Eigen::SparseMatrix Q; igl::harmonic(L,M,k,Q); - typedef DerivedL Scalar; + min_quad_with_fixed_data data; min_quad_with_fixed_precompute(Q,b,Eigen::SparseMatrix(),true,data); W.resize(n,bc.cols()); - typedef Eigen::Matrix VectorXS; + typedef Eigen::Matrix VectorXS; const VectorXS B = VectorXS::Zero(n,1); for(int w = 0;w IGL_INLINE void igl::harmonic( - const Eigen::SparseMatrix & L, - const Eigen::SparseMatrix & M, + const Eigen::SparseCompressedBase & L, + const Eigen::SparseCompressedBase & M, const int k, - Eigen::SparseMatrix & Q) + DerivedQ & Q) { assert(L.rows() == L.cols()&&"L should be square"); Q = -L; if(k == 1) return; assert(L.rows() == M.rows()&&"L should match M's dimensions"); assert(M.rows() == M.cols()&&"M should be square"); - Eigen::SparseMatrix Mi; + Eigen::SparseMatrix Mi; invert_diag(M,Mi); // This is **not** robust for k>2. See KKT system in [Jacobson et al. 2010] // of the kharmonic function in gptoolbox @@ -146,9 +147,9 @@ IGL_INLINE void igl::harmonic( const Eigen::MatrixBase & V, const Eigen::MatrixBase & F, const int k, - Eigen::SparseMatrix & Q) + DerivedQ & Q) { - Eigen::SparseMatrix L,M; + DerivedQ L,M; cotmatrix(V,F,L); if(k>1) { @@ -166,7 +167,7 @@ template bool igl::harmonic, Eigen::Mat // generated by autoexplicit.sh template bool igl::harmonic, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh -template void igl::harmonic, Eigen::Matrix, double>(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, Eigen::SparseMatrix&); +template void igl::harmonic, Eigen::Matrix, Eigen::SparseMatrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, Eigen::SparseMatrix&); // generated by autoexplicit.sh template bool igl::harmonic, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh diff --git a/include/igl/harmonic.h b/include/igl/harmonic.h index 1a48ecfb5..76d699efc 100644 --- a/include/igl/harmonic.h +++ b/include/igl/harmonic.h @@ -75,8 +75,8 @@ namespace igl typename Derivedbc, typename DerivedW> IGL_INLINE bool harmonic( - const Eigen::SparseMatrix & L, - const Eigen::SparseMatrix & M, + const Eigen::SparseCompressedBase & L, + const Eigen::SparseCompressedBase & M, const Eigen::MatrixBase & b, const Eigen::MatrixBase & bc, const int k, @@ -95,10 +95,10 @@ namespace igl typename DerivedM, typename DerivedQ> IGL_INLINE void harmonic( - const Eigen::SparseMatrix & L, - const Eigen::SparseMatrix & M, + const Eigen::SparseCompressedBase & L, + const Eigen::SparseCompressedBase & M, const int k, - Eigen::SparseMatrix & Q); + DerivedQ & Q); // Inputs: // V #V by dim vertex positions // F #F by simplex-size list of element indices @@ -113,7 +113,7 @@ namespace igl const Eigen::MatrixBase & V, const Eigen::MatrixBase & F, const int k, - Eigen::SparseMatrix & Q); + DerivedQ & Q); }; #ifndef IGL_STATIC_LIBRARY diff --git a/include/igl/hausdorff.cpp b/include/igl/hausdorff.cpp index 654aee25a..9a6058cb7 100644 --- a/include/igl/hausdorff.cpp +++ b/include/igl/hausdorff.cpp @@ -1,24 +1,24 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2015 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "hausdorff.h" #include "point_mesh_squared_distance.h" template < - typename DerivedVA, + typename DerivedVA, typename DerivedFA, typename DerivedVB, typename DerivedFB, typename Scalar> IGL_INLINE void igl::hausdorff( - const Eigen::PlainObjectBase & VA, - const Eigen::PlainObjectBase & FA, - const Eigen::PlainObjectBase & VB, - const Eigen::PlainObjectBase & FB, + const Eigen::MatrixBase & VA, + const Eigen::MatrixBase & FA, + const Eigen::MatrixBase & VB, + const Eigen::MatrixBase & FB, Scalar & d) { using namespace Eigen; @@ -26,7 +26,7 @@ IGL_INLINE void igl::hausdorff( assert(FA.cols() == 3 && "FA should contain triangles"); assert(VB.cols() == 3 && "VB should contain 3d points"); assert(FB.cols() == 3 && "FB should contain triangles"); - Matrix sqr_DBA,sqr_DAB; + Matrix sqr_DBA, sqr_DAB; Matrix I; Matrix C; point_mesh_squared_distance(VB,VA,FA,sqr_DBA,I,C); @@ -73,18 +73,18 @@ IGL_INLINE void igl::hausdorff( d(i) = dist_to_B(V(i,0),V(i,1),V(i,2)); // Lower bound is simply the max over vertex distances l = std::max(d(i),l); - // u1 is the minimum of corner distances + maximum adjacent edge + // u1 is the minimum of corner distances + maximum adjacent edge u1 = std::min(u1,d(i) + std::max(e((i+1)%3),e((i+2)%3))); // u2 first takes the maximum over corner distances u2 = std::max(u2,d(i)); } // u2 is the distance from the circumcenter/midpoint of obtuse edge plus the - // largest corner distance + // largest corner distance u2 += (s-r>2.*R ? R : 0.5*e_max); u = std::min(u1,u2); } #ifdef IGL_STATIC_LIBRARY -template void igl::hausdorff, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, double>(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, double&); +template void igl::hausdorff, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, double>(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, double&); template void igl::hausdorff, double>(Eigen::MatrixBase > const&, std::function const&, double&, double&); #endif diff --git a/include/igl/hausdorff.h b/include/igl/hausdorff.h index a9411ecaf..7672f33f9 100644 --- a/include/igl/hausdorff.h +++ b/include/igl/hausdorff.h @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2015 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_HAUSDORFF_H #define IGL_HAUSDORFF_H @@ -12,10 +12,10 @@ #include #include -namespace igl +namespace igl { // HAUSDORFF compute the Hausdorff distance between mesh (VA,FA) and mesh - // (VB,FB). This is the + // (VB,FB). This is the // // d(A,B) = max ( max min d(a,b) , max min d(b,a) ) // a∈A b∈B b∈B a∈A @@ -29,7 +29,7 @@ namespace igl // the midpoint in the middle of the segment across the concavity and some // non-vertex point _on the edge_ of the V. // Known issue: due to the issue above, this also means that unreferenced - // vertices can give unexpected results. Therefore, we assume the inputs have + // vertices can give unexpected results. Therefore, we assume the inputs have // no unreferenced vertices. // // Inputs: @@ -43,16 +43,16 @@ namespace igl // // and pair(2,:) is from B // template < - typename DerivedVA, + typename DerivedVA, typename DerivedFA, typename DerivedVB, typename DerivedFB, typename Scalar> IGL_INLINE void hausdorff( - const Eigen::PlainObjectBase & VA, - const Eigen::PlainObjectBase & FA, - const Eigen::PlainObjectBase & VB, - const Eigen::PlainObjectBase & FB, + const Eigen::MatrixBase & VA, + const Eigen::MatrixBase & FA, + const Eigen::MatrixBase & VB, + const Eigen::MatrixBase & FB, Scalar & d); // Compute lower and upper bounds (l,u) on the Hausdorff distance between a triangle // (V) and a pointset (e.g., mesh, triangle soup) given by a distance function @@ -64,7 +64,7 @@ namespace igl // dist_to_B function taking the x,y,z coordinate of a query position and // outputting the closest-point distance to some point-set B // Outputs: - // l lower bound on Hausdorff distance + // l lower bound on Hausdorff distance // u upper bound on Hausdorff distance // template < diff --git a/include/igl/heat_geodesics.cpp b/include/igl/heat_geodesics.cpp index 9e24fba6d..2b174c69c 100644 --- a/include/igl/heat_geodesics.cpp +++ b/include/igl/heat_geodesics.cpp @@ -84,7 +84,8 @@ IGL_INLINE bool igl::heat_geodesics_precompute( return false; } } - const Eigen::SparseMatrix Aeq = M.diagonal().transpose().sparseView(); + const DerivedV M_diag_tr = M.diagonal().transpose(); + const Eigen::SparseMatrix Aeq = M_diag_tr.sparseView(); L *= -0.5; if(!igl::min_quad_with_fixed_precompute( L,Eigen::VectorXi(),Aeq,true,data.Poisson)) @@ -126,13 +127,22 @@ IGL_INLINE void igl::heat_geodesics_solve( const int m = data.Grad.rows()/data.ng; for(int i = 0;i > bdryLoop; - igl::boundary_loop(DerivedF(F),bdryLoop); + igl::boundary_loop(F,bdryLoop); for(const std::vector& loop : bdryLoop) for(const int& bdryVert : loop) Mint(bdryVert) = 0.; diff --git a/include/igl/histc.cpp b/include/igl/histc.cpp index 3f967b3be..2d67fa968 100644 --- a/include/igl/histc.cpp +++ b/include/igl/histc.cpp @@ -100,11 +100,14 @@ IGL_INLINE void igl::histc( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template void igl::histc, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh template void igl::histc, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::histc, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::histc, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::histc, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); template void igl::histc, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::histc, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #if EIGEN_VERSION_AT_LEAST(3,3,0) #else template void igl::histc, Eigen::Matrix >, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase, Eigen::Matrix > > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); diff --git a/include/igl/hsv_to_rgb.cpp b/include/igl/hsv_to_rgb.cpp index a1727ff50..62d4f5a84 100644 --- a/include/igl/hsv_to_rgb.cpp +++ b/include/igl/hsv_to_rgb.cpp @@ -25,7 +25,8 @@ IGL_INLINE void igl::hsv_to_rgb( // From medit double f,p,q,t,hh; int i; - hh = ((int)h % 360) / 60.; + // shift the hue to the range [0, 360] before performing calculations + hh = ((360 + ((int)h % 360)) % 360) / 60.; i = (int)std::floor(hh); /* largest int <= h */ f = hh - i; /* fractional part of h */ p = v * (1.0 - s); diff --git a/include/igl/hsv_to_rgb.h b/include/igl/hsv_to_rgb.h index aeb64d9d3..2abc07a92 100644 --- a/include/igl/hsv_to_rgb.h +++ b/include/igl/hsv_to_rgb.h @@ -14,7 +14,7 @@ namespace igl // Convert RGB to HSV // // Inputs: - // h hue value (degrees: [0,360]) + // h hue value (degrees: [0,360]. Values outside this range will be mapped periodically to [0,360].) // s saturation value ([0,1]) // v value value ([0,1]) // Outputs: diff --git a/include/igl/in_element.cpp b/include/igl/in_element.cpp index dcdfd8a89..ea7638d01 100644 --- a/include/igl/in_element.cpp +++ b/include/igl/in_element.cpp @@ -9,9 +9,9 @@ template IGL_INLINE void igl::in_element( - const Eigen::PlainObjectBase & V, + const Eigen::MatrixBase & V, const Eigen::MatrixXi & Ele, - const Eigen::PlainObjectBase & Q, + const Eigen::MatrixBase & Q, const AABB & aabb, Eigen::VectorXi & I) { @@ -33,9 +33,9 @@ IGL_INLINE void igl::in_element( template IGL_INLINE void igl::in_element( - const Eigen::PlainObjectBase & V, + const Eigen::MatrixBase & V, const Eigen::MatrixXi & Ele, - const Eigen::PlainObjectBase & Q, + const Eigen::MatrixBase & Q, const AABB & aabb, Eigen::SparseMatrix & I) { @@ -60,6 +60,6 @@ IGL_INLINE void igl::in_element( } #ifdef IGL_STATIC_LIBRARY -template void igl::in_element, Eigen::Matrix, 2>(Eigen::PlainObjectBase > const&, Eigen::Matrix const&, Eigen::PlainObjectBase > const&, igl::AABB, 2> const&, Eigen::Matrix&); -template void igl::in_element, Eigen::Matrix, 3>(Eigen::PlainObjectBase > const&, Eigen::Matrix const&, Eigen::PlainObjectBase > const&, igl::AABB, 3> const&, Eigen::Matrix&); +template void igl::in_element, Eigen::Matrix, 2>(Eigen::MatrixBase > const&, Eigen::Matrix const&, Eigen::MatrixBase > const&, igl::AABB, 2> const&, Eigen::Matrix&); +template void igl::in_element, Eigen::Matrix, 3>(Eigen::MatrixBase > const&, Eigen::Matrix const&, Eigen::MatrixBase > const&, igl::AABB, 3> const&, Eigen::Matrix&); #endif diff --git a/include/igl/in_element.h b/include/igl/in_element.h index dcbc03aa6..c438f62ee 100644 --- a/include/igl/in_element.h +++ b/include/igl/in_element.h @@ -30,9 +30,9 @@ namespace igl // containing element) template IGL_INLINE void in_element( - const Eigen::PlainObjectBase & V, + const Eigen::MatrixBase & V, const Eigen::MatrixXi & Ele, - const Eigen::PlainObjectBase & Q, + const Eigen::MatrixBase & Q, const AABB & aabb, Eigen::VectorXi & I); // Outputs: @@ -40,9 +40,9 @@ namespace igl // point: I(q,e) means point q is in element e template IGL_INLINE void in_element( - const Eigen::PlainObjectBase & V, + const Eigen::MatrixBase & V, const Eigen::MatrixXi & Ele, - const Eigen::PlainObjectBase & Q, + const Eigen::MatrixBase & Q, const AABB & aabb, Eigen::SparseMatrix & I); }; diff --git a/include/igl/inradius.cpp b/include/igl/inradius.cpp index d5a06ab50..947b16409 100644 --- a/include/igl/inradius.cpp +++ b/include/igl/inradius.cpp @@ -1,27 +1,27 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2016 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "inradius.h" #include "edge_lengths.h" #include "doublearea.h" template < - typename DerivedV, + typename DerivedV, typename DerivedF, typename DerivedR> IGL_INLINE void igl::inradius( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & r) { Eigen::Matrix l; Eigen::Matrix R; igl::edge_lengths(V,F,l); - // If R is the circumradius, + // If R is the circumradius, // R*r = (abc)/(2*(a+b+c)) // R = abc/(4*area) // r(abc/(4*area)) = (abc)/(2*(a+b+c)) diff --git a/include/igl/inradius.h b/include/igl/inradius.h index 07166b4b9..e831f7de3 100644 --- a/include/igl/inradius.h +++ b/include/igl/inradius.h @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2016 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_INRADIUS_H #define IGL_INRADIUS_H @@ -20,12 +20,12 @@ namespace igl // R #F list of inradii // template < - typename DerivedV, + typename DerivedV, typename DerivedF, typename DerivedR> IGL_INLINE void inradius( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & R); } #ifndef IGL_STATIC_LIBRARY diff --git a/include/igl/internal_angles.h b/include/igl/internal_angles.h index 1dd990ed4..ff6ea92c9 100644 --- a/include/igl/internal_angles.h +++ b/include/igl/internal_angles.h @@ -8,6 +8,7 @@ #ifndef IGL_INTERNAL_ANGLES_H #define IGL_INTERNAL_ANGLES_H #include "igl_inline.h" +#include "deprecated.h" #include namespace igl { @@ -49,9 +50,10 @@ namespace igl // Usage of internal_angles_using_squared_edge_lengths is preferred to internal_angles_using_squared_edge_lengths // This function is deprecated and probably will be removed in future versions template - IGL_INLINE void internal_angles_using_edge_lengths( + IGL_DEPRECATED IGL_INLINE void internal_angles_using_edge_lengths( const Eigen::MatrixBase& L, - Eigen::PlainObjectBase & K);} + Eigen::PlainObjectBase & K); +} #ifndef IGL_STATIC_LIBRARY # include "internal_angles.cpp" diff --git a/include/igl/invert_diag.cpp b/include/igl/invert_diag.cpp index b87a8d5b4..6be06786a 100644 --- a/include/igl/invert_diag.cpp +++ b/include/igl/invert_diag.cpp @@ -7,18 +7,22 @@ // obtain one at http://mozilla.org/MPL/2.0/. #include "invert_diag.h" -template +template IGL_INLINE void igl::invert_diag( - const Eigen::SparseMatrix& X, - Eigen::SparseMatrix& Y) + const Eigen::SparseCompressedBase& X, + MatY& Y) { + typedef typename DerivedX::Scalar Scalar; #ifndef NDEBUG - typename Eigen::SparseVector dX = X.diagonal().sparseView(); + Eigen::SparseMatrix tmp = X; + Eigen::SparseVector dX = tmp.diagonal().sparseView(); // Check that there are no zeros along the diagonal assert(dX.nonZeros() == dX.size()); #endif // http://www.alecjacobson.com/weblog/?p=2552 - if(&Y != &X) + + + if((void *)&Y != (void *)&X) { Y = X; } @@ -26,13 +30,13 @@ IGL_INLINE void igl::invert_diag( for(int k=0; k::InnerIterator it (Y,k); it; ++it) + for(typename MatY::InnerIterator it (Y,k); it; ++it) { if(it.col() == it.row()) { - T v = it.value(); + Scalar v = it.value(); assert(v != 0); - v = ((T)1.0)/v; + v = ((Scalar)1.0)/v; Y.coeffRef(it.row(),it.col()) = v; } } @@ -41,6 +45,6 @@ IGL_INLINE void igl::invert_diag( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::invert_diag(Eigen::SparseMatrix const&, Eigen::SparseMatrix&); -template void igl::invert_diag(Eigen::SparseMatrix const&, Eigen::SparseMatrix&); +template void igl::invert_diag, Eigen::SparseMatrix >(Eigen::SparseCompressedBase> const&, Eigen::SparseMatrix&); +template void igl::invert_diag, Eigen::SparseMatrix >(Eigen::SparseCompressedBase> const&, Eigen::SparseMatrix&); #endif diff --git a/include/igl/invert_diag.h b/include/igl/invert_diag.h index 2194b3f14..4dd5b7389 100644 --- a/include/igl/invert_diag.h +++ b/include/igl/invert_diag.h @@ -22,10 +22,10 @@ namespace igl // X an m by n sparse matrix // Outputs: // Y an m by n sparse matrix - template + template IGL_INLINE void invert_diag( - const Eigen::SparseMatrix& X, - Eigen::SparseMatrix& Y); + const Eigen::SparseCompressedBase& X, + MatY& Y); } #ifndef IGL_STATIC_LIBRARY diff --git a/include/igl/is_border_vertex.cpp b/include/igl/is_border_vertex.cpp index 858441566..10ddd4ae5 100644 --- a/include/igl/is_border_vertex.cpp +++ b/include/igl/is_border_vertex.cpp @@ -14,7 +14,7 @@ template IGL_INLINE std::vector igl::is_border_vertex( const Eigen::MatrixBase &F) { - DerivedF FF; + Eigen::Matrix FF; igl::triangle_triangle_adjacency(F,FF); std::vector ret(F.maxCoeff()+1); for(unsigned i=0; i #include @@ -29,7 +29,7 @@ namespace igl const Eigen::MatrixBase &F); // Deprecated: template - IGL_INLINE std::vector is_border_vertex( + IGL_DEPRECATED IGL_INLINE std::vector is_border_vertex( const Eigen::MatrixBase &V, const Eigen::MatrixBase &F); } diff --git a/include/igl/is_edge_manifold.h b/include/igl/is_edge_manifold.h index 5832806ac..1887dc083 100644 --- a/include/igl/is_edge_manifold.h +++ b/include/igl/is_edge_manifold.h @@ -16,7 +16,6 @@ namespace igl // check if the mesh is edge-manifold // // Inputs: - // V #V by dim list of mesh vertex positions **unneeded** // F #F by 3 list of triangle indices // Returns whether mesh is edge manifold. // diff --git a/include/igl/is_irregular_vertex.cpp b/include/igl/is_irregular_vertex.cpp index 34665d66f..edd91b057 100644 --- a/include/igl/is_irregular_vertex.cpp +++ b/include/igl/is_irregular_vertex.cpp @@ -11,9 +11,9 @@ #include "is_border_vertex.h" template -IGL_INLINE std::vector igl::is_irregular_vertex(const Eigen::PlainObjectBase &V, const Eigen::PlainObjectBase &F) +IGL_INLINE std::vector igl::is_irregular_vertex(const Eigen::MatrixBase &V, const Eigen::MatrixBase &F) { - Eigen::VectorXi count = Eigen::VectorXi::Zero(F.maxCoeff()); + Eigen::VectorXi count = Eigen::VectorXi::Zero(F.maxCoeff()+1); for(unsigned i=0; i igl::is_irregular_vertex(const Eigen::PlainObjectBa } } - std::vector border = is_border_vertex(V,F); + std::vector border = is_border_vertex(F); std::vector res(count.size()); @@ -39,6 +39,6 @@ IGL_INLINE std::vector igl::is_irregular_vertex(const Eigen::PlainObjectBa #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template std::vector > igl::is_irregular_vertex, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); -template std::vector > igl::is_irregular_vertex, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); +template std::vector > igl::is_irregular_vertex, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); +template std::vector > igl::is_irregular_vertex, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); #endif diff --git a/include/igl/is_irregular_vertex.h b/include/igl/is_irregular_vertex.h index e07e5ab70..d46fe07a9 100644 --- a/include/igl/is_irregular_vertex.h +++ b/include/igl/is_irregular_vertex.h @@ -23,7 +23,7 @@ namespace igl // Returns #V vector of bools revealing whether vertices are singular // template - IGL_INLINE std::vector is_irregular_vertex(const Eigen::PlainObjectBase &V, const Eigen::PlainObjectBase &F); + IGL_INLINE std::vector is_irregular_vertex(const Eigen::MatrixBase &V, const Eigen::MatrixBase &F); } #ifndef IGL_STATIC_LIBRARY diff --git a/include/igl/isdiag.cpp b/include/igl/isdiag.cpp index 452341bf8..b7e343ee6 100644 --- a/include/igl/isdiag.cpp +++ b/include/igl/isdiag.cpp @@ -7,14 +7,14 @@ // obtain one at http://mozilla.org/MPL/2.0/. #include "isdiag.h" -template -IGL_INLINE bool igl::isdiag(const Eigen::SparseMatrix & A) +template +IGL_INLINE bool igl::isdiag(const Eigen::SparseCompressedBase & A) { // Iterate over outside of A for(int k=0; k::InnerIterator it (A,k); it; ++it) + for(typename Derived::InnerIterator it (A,k); it; ++it) { if(it.row() != it.col() && it.value()!=0) { @@ -28,5 +28,5 @@ IGL_INLINE bool igl::isdiag(const Eigen::SparseMatrix & A) #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template bool igl::isdiag(class Eigen::SparseMatrix const &); +template bool igl::isdiag>(Eigen::SparseCompressedBase> const &); #endif diff --git a/include/igl/isdiag.h b/include/igl/isdiag.h index 2bd555fa3..48b359245 100644 --- a/include/igl/isdiag.h +++ b/include/igl/isdiag.h @@ -17,8 +17,8 @@ namespace igl // Inputs: // A m by n sparse matrix // Returns true iff and only if the matrix is diagonal. - template - IGL_INLINE bool isdiag(const Eigen::SparseMatrix & A); + template + IGL_INLINE bool isdiag(const Eigen::SparseCompressedBase & A); }; #ifndef IGL_STATIC_LIBRARY # include "isdiag.cpp" diff --git a/include/igl/isolines.cpp b/include/igl/isolines.cpp index 6d4f87e32..e2fd69873 100644 --- a/include/igl/isolines.cpp +++ b/include/igl/isolines.cpp @@ -38,21 +38,21 @@ IGL_INLINE void igl::isolines( const int nFaces = F.rows(); const int np1 = n+1; const double min = z.minCoeff(), max = z.maxCoeff(); - - + + //Following http://www.alecjacobson.com/weblog/?p=2529 typedef typename DerivedZ::Scalar Scalar; typedef Eigen::Matrix Vec; Vec iso(np1); for(int i=0; i Matrix; std::array t{{Matrix(nFaces, np1), Matrix(nFaces, np1), Matrix(nFaces, np1)}}; for(int i=0; i1) @@ -60,7 +60,7 @@ IGL_INLINE void igl::isolines( } } } - + std::array,3> Fij, Iij; for(int i=0; i + +template < + typename DerivedCM, + typename Derivediso_color, + typename DerivedICM + > +IGL_INLINE void igl::isolines_map( + const Eigen::MatrixBase & CM, + const Eigen::MatrixBase & iso_color, + const int interval_thickness, + const int iso_thickness, + Eigen::PlainObjectBase & ICM) +{ + ICM.resize(CM.rows()*interval_thickness+(CM.rows()-1)*iso_thickness,3); + { + int k = 0; + for(int c = 0;c +IGL_INLINE void igl::isolines_map( + const Eigen::MatrixBase & CM, + Eigen::PlainObjectBase & ICM) +{ + return isolines_map( + CM, Eigen::Matrix(0,0,0), 10, 1, ICM); +} + +#ifdef IGL_STATIC_LIBRARY +// Explicit template instantiation +template void igl::isolines_map, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +#endif diff --git a/include/igl/isolines_map.h b/include/igl/isolines_map.h new file mode 100644 index 000000000..2b6f1ac7c --- /dev/null +++ b/include/igl/isolines_map.h @@ -0,0 +1,41 @@ +#ifndef IGL_ISOLINES_MAP_H +#define IGL_ISOLINES_MAP_H +#include "igl_inline.h" +#include + +namespace igl +{ + // Inject a given colormap with evenly spaced isolines. + // + // Inputs: + // CM #CM by 3 list of colors + // ico_color 1 by 3 isoline color + // interval_thickness number of times to repeat intervals (original colors) + // iso_thickness number of times to repeat isoline color (in between + // intervals) + // Outputs: + // ICM #CM*interval_thickness + (#CM-1)*iso_thickness by 3 list of outputs + // colors + template < + typename DerivedCM, + typename Derivediso_color, + typename DerivedICM > + IGL_INLINE void isolines_map( + const Eigen::MatrixBase & CM, + const Eigen::MatrixBase & iso_color, + const int interval_thickness, + const int iso_thickness, + Eigen::PlainObjectBase & ICM); + template < + typename DerivedCM, + typename DerivedICM> + IGL_INLINE void isolines_map( + const Eigen::MatrixBase & CM, + Eigen::PlainObjectBase & ICM); +} + +#ifndef IGL_STATIC_LIBRARY +# include "isolines_map.cpp" +#endif + +#endif diff --git a/include/igl/iterative_closest_point.cpp b/include/igl/iterative_closest_point.cpp new file mode 100644 index 000000000..0d2a674eb --- /dev/null +++ b/include/igl/iterative_closest_point.cpp @@ -0,0 +1,123 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2019 Alec Jacobson +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// obtain one at http://mozilla.org/MPL/2.0/. +#include "iterative_closest_point.h" +#include "AABB.h" +#include "per_face_normals.h" +#include "matlab_format.h" +#include "slice.h" +#include "random_points_on_mesh.h" +#include "rigid_alignment.h" +#include "writeOBJ.h" +#include "writeDMAT.h" +#include +#include + +template < + typename DerivedVX, + typename DerivedFX, + typename DerivedVY, + typename DerivedFY, + typename DerivedR, + typename Derivedt + > +IGL_INLINE void igl::iterative_closest_point( + const Eigen::MatrixBase & VX, + const Eigen::MatrixBase & FX, + const Eigen::MatrixBase & VY, + const Eigen::MatrixBase & FY, + const int num_samples, + const int max_iters, + Eigen::PlainObjectBase & R, + Eigen::PlainObjectBase & t) +{ + + assert(VX.cols() == 3 && "X should be a mesh in 3D"); + assert(VY.cols() == 3 && "Y should be a mesh in 3D"); + + typedef typename DerivedVX::Scalar Scalar; + typedef Eigen::Matrix MatrixXS; + typedef Eigen::Matrix VectorXS; + typedef Eigen::Matrix Matrix3S; + typedef Eigen::Matrix RowVector3S; + + // Precompute BVH on Y + AABB Ytree; + Ytree.init(VY,FY); + MatrixXS NY; + per_face_normals(VY,FY,NY); + return iterative_closest_point( + VX,FX,VY,FY,Ytree,NY,num_samples,max_iters,R,t); +} + +template < + typename DerivedVX, + typename DerivedFX, + typename DerivedVY, + typename DerivedFY, + typename DerivedNY, + typename DerivedR, + typename Derivedt + > +IGL_INLINE void igl::iterative_closest_point( + const Eigen::MatrixBase & VX, + const Eigen::MatrixBase & FX, + const Eigen::MatrixBase & VY, + const Eigen::MatrixBase & FY, + const igl::AABB & Ytree, + const Eigen::MatrixBase & NY, + const int num_samples, + const int max_iters, + Eigen::PlainObjectBase & R, + Eigen::PlainObjectBase & t) +{ + typedef typename DerivedVX::Scalar Scalar; + typedef Eigen::Matrix MatrixXS; + typedef Eigen::Matrix VectorXS; + typedef Eigen::Matrix Matrix3S; + typedef Eigen::Matrix RowVector3S; + R.setIdentity(3,3); + t.setConstant(1,3,0); + + for(int iter = 0;iter, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, int, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +#endif diff --git a/include/igl/iterative_closest_point.h b/include/igl/iterative_closest_point.h new file mode 100644 index 000000000..0065c8923 --- /dev/null +++ b/include/igl/iterative_closest_point.h @@ -0,0 +1,83 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2019 Alec Jacobson +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// obtain one at http://mozilla.org/MPL/2.0/. +#ifndef IGL_ITERATIVE_CLOSEST_POINT_H +#define IGL_ITERATIVE_CLOSEST_POINT_H +#include "igl_inline.h" +#include +#include "AABB.h" + +namespace igl +{ + // Solve for the rigid transformation that places mesh X onto mesh Y using the + // iterative closest point method. In particular, optimize: + // + // min ∫_X inf ‖x*R+t - y‖² dx + // R∈SO(3) y∈Y + // t∈R³ + // + // Typically optimization strategies include using Gauss Newton + // ("point-to-plane" linearization) and stochastic descent (sparse random + // sampling each iteration). + // + // Inputs: + // VX #VX by 3 list of mesh X vertices + // FX #FX by 3 list of mesh X triangle indices into rows of VX + // VY #VY by 3 list of mesh Y vertices + // FY #FY by 3 list of mesh Y triangle indices into rows of VY + // num_samples number of random samples to use (larger --> more accurate, + // but also more suceptible to sticking to local minimum) + // Outputs: + // R 3x3 rotation matrix so that (VX*R+t,FX) ~~ (VY,FY) + // t 1x3 translation row vector + template < + typename DerivedVX, + typename DerivedFX, + typename DerivedVY, + typename DerivedFY, + typename DerivedR, + typename Derivedt + > + IGL_INLINE void iterative_closest_point( + const Eigen::MatrixBase & VX, + const Eigen::MatrixBase & FX, + const Eigen::MatrixBase & VY, + const Eigen::MatrixBase & FY, + const int num_samples, + const int max_iters, + Eigen::PlainObjectBase & R, + Eigen::PlainObjectBase & t); + // Inputs: + // Ytree precomputed AABB tree for accelerating closest point queries + // NY #FY by 3 list of precomputed unit face normals + template < + typename DerivedVX, + typename DerivedFX, + typename DerivedVY, + typename DerivedFY, + typename DerivedNY, + typename DerivedR, + typename Derivedt + > + IGL_INLINE void iterative_closest_point( + const Eigen::MatrixBase & VX, + const Eigen::MatrixBase & FX, + const Eigen::MatrixBase & VY, + const Eigen::MatrixBase & FY, + const igl::AABB & Ytree, + const Eigen::MatrixBase & NY, + const int num_samples, + const int max_iters, + Eigen::PlainObjectBase & R, + Eigen::PlainObjectBase & t); +} + +#ifndef IGL_STATIC_LIBRARY +# include "iterative_closest_point.cpp" +#endif + +#endif diff --git a/include/igl/jet.cpp b/include/igl/jet.cpp index 373f23bcb..ec74bcd79 100644 --- a/include/igl/jet.cpp +++ b/include/igl/jet.cpp @@ -11,48 +11,13 @@ template IGL_INLINE void igl::jet(const T x, T * rgb) { - igl::colormap(igl::COLOR_MAP_TYPE_JET, x, rgb); + igl::colormap(igl::COLOR_MAP_TYPE_JET,x, rgb); } template -IGL_INLINE void igl::jet(const T x_in, T & r, T & g, T & b) +IGL_INLINE void igl::jet(const T f, T & r, T & g, T & b) { - // Only important if the number of colors is small. In which case the rest is - // still wrong anyway - // x = linspace(0,1,jj)' * (1-1/jj) + 1/jj; - // - const double rone = 0.8; - const double gone = 1.0; - const double bone = 1.0; - T x = x_in; - x = (x_in<0 ? 0 : (x>1 ? 1 : x)); - - if (x<1. / 8.) - { - r = 0; - g = 0; - b = bone*(0.5 + (x) / (1. / 8.)*0.5); - } else if (x<3. / 8.) - { - r = 0; - g = gone*(x - 1. / 8.) / (3. / 8. - 1. / 8.); - b = bone; - } else if (x<5. / 8.) - { - r = rone*(x - 3. / 8.) / (5. / 8. - 3. / 8.); - g = gone; - b = (bone - (x - 3. / 8.) / (5. / 8. - 3. / 8.)); - } else if (x<7. / 8.) - { - r = rone; - g = (gone - (x - 5. / 8.) / (7. / 8. - 5. / 8.)); - b = 0; - } else - { - r = (rone - (x - 7. / 8.) / (1. - 7. / 8.)*0.5); - g = 0; - b = 0; - } + igl::colormap(igl::COLOR_MAP_TYPE_JET, f, r, g, b); } template diff --git a/include/igl/jet.h b/include/igl/jet.h index 411b53af3..a681ca295 100644 --- a/include/igl/jet.h +++ b/include/igl/jet.h @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2013 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_JET_H #define IGL_JET_H @@ -13,10 +13,13 @@ //#endif namespace igl { - // JET like MATLAB's jet + // JET like MATLAB's jet. + // + // Note that we actually use the Turbo colormap instead, since jet is a bad colormap: + // https://ai.googleblog.com/2019/08/turbo-improved-rainbow-colormap-for.html // // Inputs: - // m number of colors + // m number of colors // Outputs: // J m by list of RGB colors between 0 and 1 // diff --git a/include/igl/knn.cpp b/include/igl/knn.cpp index 33a990eea..c87ec0f95 100644 --- a/include/igl/knn.cpp +++ b/include/igl/knn.cpp @@ -103,6 +103,8 @@ namespace igl { #ifdef IGL_STATIC_LIBRARY +// Explicit template instantiation +// generated by autoexplicit.sh +template void igl::knn, int, int, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, int const&, std::vector >, std::allocator > > > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); template void igl::knn, int, int, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, int const&, std::vector >, std::allocator > > > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #endif - diff --git a/include/igl/launch_medit.cpp b/include/igl/launch_medit.cpp index 151af8e5b..f336dd7d0 100644 --- a/include/igl/launch_medit.cpp +++ b/include/igl/launch_medit.cpp @@ -56,6 +56,7 @@ IGL_INLINE int igl::launch_medit( return system(command.str().c_str()); }catch(int e) { + (void)e; cerr<<"^"<<__FUNCTION__<<": Calling to medit crashed..."< > & V,Eige int m = V.size(); if(m == 0) { - M.resize(0,0); + M.resize( + Derived::RowsAtCompileTime>=0?Derived::RowsAtCompileTime:0 + , + Derived::ColsAtCompileTime>=0?Derived::ColsAtCompileTime:0 + ); return true; } // number of columns @@ -119,6 +123,12 @@ IGL_INLINE bool igl::list_to_matrix(const std::vector & V,Eigen::PlainObject #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template bool igl::list_to_matrix >(std::vector >, std::allocator > > > const&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh +template bool igl::list_to_matrix >(std::vector >, std::allocator > > > const&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh +template bool igl::list_to_matrix >(std::vector >, std::allocator > > > const&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh template bool igl::list_to_matrix >(std::vector >, std::allocator > > > const&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh // generated by autoexplicit.sh diff --git a/include/igl/local_basis.cpp b/include/igl/local_basis.cpp index 599eca739..1b40ba0dc 100644 --- a/include/igl/local_basis.cpp +++ b/include/igl/local_basis.cpp @@ -17,8 +17,8 @@ template IGL_INLINE void igl::local_basis( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, Eigen::PlainObjectBase& B1, Eigen::PlainObjectBase& B2, Eigen::PlainObjectBase& B3 @@ -46,6 +46,6 @@ IGL_INLINE void igl::local_basis( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh -template void igl::local_basis, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::local_basis, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::local_basis, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::local_basis, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/local_basis.h b/include/igl/local_basis.h index 392796c34..5eb2cabaf 100644 --- a/include/igl/local_basis.h +++ b/include/igl/local_basis.h @@ -30,8 +30,8 @@ namespace igl // See also: adjacency_matrix template IGL_INLINE void local_basis( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, Eigen::PlainObjectBase& B1, Eigen::PlainObjectBase& B2, Eigen::PlainObjectBase& B3 diff --git a/include/igl/loop.cpp b/include/igl/loop.cpp index b4233ca67..e353e4643 100644 --- a/include/igl/loop.cpp +++ b/include/igl/loop.cpp @@ -20,21 +20,21 @@ template < typename DerivedNF> IGL_INLINE void igl::loop( const int n_verts, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & F, Eigen::SparseMatrix& S, Eigen::PlainObjectBase & NF) { typedef Eigen::SparseMatrix SparseMat; typedef Eigen::Triplet Triplet_t; - + //Ref. https://graphics.stanford.edu/~mdfisher/subdivision.html //Heavily borrowing from igl::upsample - - DerivedF FF, FFi; + + Eigen::Matrix FF, FFi; triangle_triangle_adjacency(F, FF, FFi); std::vector> adjacencyList; adjacency_list(F, adjacencyList, true); - + //Compute the number and positions of the vertices to insert (on edges) Eigen::MatrixXi NI = Eigen::MatrixXi::Constant(FF.rows(), FF.cols(), -1); Eigen::MatrixXi NIdoubles = Eigen::MatrixXi::Zero(FF.rows(), FF.cols()); @@ -48,12 +48,12 @@ IGL_INLINE void igl::loop( { NI(i,j) = counter; NIdoubles(i,j) = 0; - if (FF(i,j) != -1) + if (FF(i,j) != -1) { //If it is not a boundary NI(FF(i,j), FFi(i,j)) = counter; NIdoubles(i,j) = 1; - } else + } else { //Mark boundary vertices for later vertIsOnBdry(F(i,j)) = 1; @@ -63,24 +63,24 @@ IGL_INLINE void igl::loop( } } } - + const int& n_odd = n_verts; const int& n_even = counter; const int n_newverts = n_odd + n_even; - + //Construct vertex positions std::vector tripletList; - for(int i=0; i& localAdjList = adjacencyList[i]; - if(vertIsOnBdry(i)==1) + const auto& localAdjList = adjacencyList[i]; + if(vertIsOnBdry(i)==1) { //Boundary vertex tripletList.emplace_back(i, localAdjList.front(), 1./8.); tripletList.emplace_back(i, localAdjList.back(), 1./8.); tripletList.emplace_back(i, i, 3./4.); - } else + } else { const int n = localAdjList.size(); const SType dn = n; @@ -99,19 +99,19 @@ IGL_INLINE void igl::loop( tripletList.emplace_back(i, i, 1.-dn*beta); } } - for(int i=0; i VI(6); VI << F(i,0), F(i,1), F(i,2), NI(i,0) + n_odd, NI(i,1) + n_odd, NI(i,2) + n_odd; - - Eigen::VectorXi f0(3), f1(3), f2(3), f3(3); + + Eigen::Matrix f0(3), f1(3), f2(3), f3(3); f0 << VI(0), VI(3), VI(5); f1 << VI(1), VI(4), VI(3); f2 << VI(3), VI(4), VI(5); f3 << VI(4), VI(2), VI(5); - + NF.row((i*4)+0) = f0; NF.row((i*4)+1) = f1; NF.row((i*4)+2) = f2; @@ -145,20 +145,20 @@ IGL_INLINE void igl::loop( } template < - typename DerivedV, + typename DerivedV, typename DerivedF, typename DerivedNV, typename DerivedNF> IGL_INLINE void igl::loop( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, Eigen::PlainObjectBase& NV, Eigen::PlainObjectBase& NF, const int number_of_subdivs) { NV = V; NF = F; - for(int i=0; i S; @@ -169,5 +169,5 @@ IGL_INLINE void igl::loop( } #ifdef IGL_STATIC_LIBRARY -template void igl::loop, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, int); +template void igl::loop, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix>(Eigen::MatrixBase> const &, Eigen::MatrixBase> const &, Eigen::PlainObjectBase> &, Eigen::PlainObjectBase> &, int); #endif diff --git a/include/igl/loop.h b/include/igl/loop.h index bc1616891..8e70a40b1 100644 --- a/include/igl/loop.h +++ b/include/igl/loop.h @@ -31,7 +31,7 @@ namespace igl typename DerivedNF> IGL_INLINE void loop( const int n_verts, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & F, Eigen::SparseMatrix& S, Eigen::PlainObjectBase & NF); // LOOP Given the triangle mesh [V, F], computes number_of_subdivs steps of loop subdivision and outputs the new mesh [newV, newF] @@ -44,13 +44,13 @@ namespace igl // NV a matrix containing the new vertices // NF a matrix containing the new faces template < - typename DerivedV, + typename DerivedV, typename DerivedF, typename DerivedNV, typename DerivedNF> IGL_INLINE void loop( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, Eigen::PlainObjectBase& NV, Eigen::PlainObjectBase& NF, const int number_of_subdivs = 1); diff --git a/include/igl/marching_tets.cpp b/include/igl/marching_tets.cpp index 02fabb014..08b22711b 100644 --- a/include/igl/marching_tets.cpp +++ b/include/igl/marching_tets.cpp @@ -22,9 +22,9 @@ template void igl::marching_tets( - const Eigen::PlainObjectBase& TV, - const Eigen::PlainObjectBase& TT, - const Eigen::PlainObjectBase& isovals, + const Eigen::MatrixBase& TV, + const Eigen::MatrixBase& TT, + const Eigen::MatrixBase& isovals, double isovalue, Eigen::PlainObjectBase& outV, Eigen::PlainObjectBase& outF, @@ -94,7 +94,7 @@ void igl::marching_tets( for (int v = 0; v < 4; v++) { const int vid = TT(i, v); - const uint8_t flag = isovals[vid] > isovalue; + const uint8_t flag = isovals(vid, 0) > isovalue; key |= flag << v; } @@ -147,10 +147,13 @@ void igl::marching_tets( for (int f = 0; f < faces.size(); f++) { + const int ti = faces[f].second; + assert(ti>=0); + assert(ti edge = edge_table[vi]; const int64_t key = make_edge_key(edge); auto it = emap.find(key); @@ -160,8 +163,8 @@ void igl::marching_tets( typedef Eigen::Matrix RowVector; const RowVector v1 = TV.row(edge.first); const RowVector v2 = TV.row(edge.second); - const double a = fabs(isovals[edge.first] - isovalue); - const double b = fabs(isovals[edge.second] - isovalue); + const double a = fabs(isovals(edge.first, 0) - isovalue); + const double b = fabs(isovals(edge.second, 0) - isovalue); const double w = a / (a+b); // Create a casted copy in case BCType is a float and we need to downcast @@ -173,7 +176,6 @@ void igl::marching_tets( const typename DerivedTV::Scalar v_w = static_cast(w); outV.row(num_unique) = (1-v_w)*v1 + v_w*v2; outF(f, v) = num_unique; - J[f] = ti; emap.emplace(key, num_unique); num_unique += 1; @@ -183,12 +185,11 @@ void igl::marching_tets( } } outV.conservativeResize(num_unique, 3); - J.conservativeResize(num_unique, 1); BC.resize(num_unique, TV.rows()); BC.setFromTriplets(bc_triplets.begin(), bc_triplets.end()); } #ifdef IGL_STATIC_LIBRARY -template void igl::marching_tets, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, double>(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, double, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::SparseMatrix&); +template void igl::marching_tets, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, double>(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, double, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::SparseMatrix&); #endif // IGL_STATIC_LIBRARY diff --git a/include/igl/marching_tets.h b/include/igl/marching_tets.h index 9f3fa5435..19df54482 100644 --- a/include/igl/marching_tets.h +++ b/include/igl/marching_tets.h @@ -40,9 +40,9 @@ namespace igl { typename DerivedJ, typename BCType> IGL_INLINE void marching_tets( - const Eigen::PlainObjectBase& TV, - const Eigen::PlainObjectBase& TT, - const Eigen::PlainObjectBase& S, + const Eigen::MatrixBase& TV, + const Eigen::MatrixBase& TT, + const Eigen::MatrixBase& S, double isovalue, Eigen::PlainObjectBase& SV, Eigen::PlainObjectBase& SF, @@ -74,9 +74,9 @@ namespace igl { typename DerivedJ, typename BCType> IGL_INLINE void marching_tets( - const Eigen::PlainObjectBase& TV, - const Eigen::PlainObjectBase& TT, - const Eigen::PlainObjectBase& S, + const Eigen::MatrixBase& TV, + const Eigen::MatrixBase& TT, + const Eigen::MatrixBase& S, Eigen::PlainObjectBase& SV, Eigen::PlainObjectBase& SF, Eigen::PlainObjectBase& J, @@ -108,9 +108,9 @@ namespace igl { typename DerivedSF, typename DerivedJ> IGL_INLINE void marching_tets( - const Eigen::PlainObjectBase& TV, - const Eigen::PlainObjectBase& TT, - const Eigen::PlainObjectBase& S, + const Eigen::MatrixBase& TV, + const Eigen::MatrixBase& TT, + const Eigen::MatrixBase& S, double isovalue, Eigen::PlainObjectBase& SV, Eigen::PlainObjectBase& SF, @@ -143,9 +143,9 @@ namespace igl { typename DerivedSF, typename BCType> IGL_INLINE void marching_tets( - const Eigen::PlainObjectBase& TV, - const Eigen::PlainObjectBase& TT, - const Eigen::PlainObjectBase& S, + const Eigen::MatrixBase& TV, + const Eigen::MatrixBase& TT, + const Eigen::MatrixBase& S, double isovalue, Eigen::PlainObjectBase& SV, Eigen::PlainObjectBase& SF, @@ -176,9 +176,9 @@ namespace igl { typename DerivedSV, typename DerivedSF> IGL_INLINE void marching_tets( - const Eigen::PlainObjectBase& TV, - const Eigen::PlainObjectBase& TT, - const Eigen::PlainObjectBase& S, + const Eigen::MatrixBase& TV, + const Eigen::MatrixBase& TT, + const Eigen::MatrixBase& S, double isovalue, Eigen::PlainObjectBase& SV, Eigen::PlainObjectBase& SF) { diff --git a/include/igl/massmatrix.cpp b/include/igl/massmatrix.cpp index e926205d8..aa334a079 100644 --- a/include/igl/massmatrix.cpp +++ b/include/igl/massmatrix.cpp @@ -48,8 +48,8 @@ IGL_INLINE void igl::massmatrix( return massmatrix_intrinsic(l,F,type,M); }else if(simplex_size == 4) { - Matrix MI; - Matrix MJ; + Matrix MI; + Matrix MJ; Matrix MV; assert(V.cols() == 3); assert(eff_type == MASSMATRIX_TYPE_BARYCENTRIC); diff --git a/include/igl/massmatrix_intrinsic.cpp b/include/igl/massmatrix_intrinsic.cpp index 695ae2b09..fe34873ab 100644 --- a/include/igl/massmatrix_intrinsic.cpp +++ b/include/igl/massmatrix_intrinsic.cpp @@ -47,8 +47,8 @@ IGL_INLINE void igl::massmatrix_intrinsic( assert(F.cols() == 3 && "only triangles supported"); Matrix dblA; doublearea(l,0.,dblA); - Matrix MI; - Matrix MJ; + Matrix MI; + Matrix MJ; Matrix MV; switch(eff_type) diff --git a/include/igl/mat_min.cpp b/include/igl/mat_min.cpp index ad50c7014..c34e993fe 100644 --- a/include/igl/mat_min.cpp +++ b/include/igl/mat_min.cpp @@ -19,8 +19,8 @@ IGL_INLINE void igl::mat_min( // output size int n = (dim==1?X.cols():X.rows()); // resize output - Y.resize(n); - I.resize(n); + Y.resize(n,1); + I.resize(n,1); // loop over dimension opposite of dim for(int j = 0;j IGL_INLINE void igl::matrix_to_list( - const Eigen::DenseBase & M, + const Eigen::MatrixBase & M, std::vector > & V) { using namespace std; @@ -29,7 +29,7 @@ IGL_INLINE void igl::matrix_to_list( template IGL_INLINE void igl::matrix_to_list( - const Eigen::DenseBase & M, + const Eigen::MatrixBase & M, std::vector & V) { using namespace std; @@ -46,7 +46,7 @@ IGL_INLINE void igl::matrix_to_list( template IGL_INLINE std::vector igl::matrix_to_list( - const Eigen::DenseBase & M) + const Eigen::MatrixBase & M) { std::vector V; matrix_to_list(M,V); @@ -56,26 +56,24 @@ IGL_INLINE std::vector igl::matrix_to_list( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh -template void igl::matrix_to_list, -1, 1, true> >(Eigen::DenseBase, -1, 1, true> > const&, std::vector, -1, 1, true>::Scalar, std::allocator, -1, 1, true>::Scalar> >&); +template void igl::matrix_to_list, -1, 1, true> >(Eigen::MatrixBase, -1, 1, true> > const&, std::vector, -1, 1, true>::Scalar, std::allocator, -1, 1, true>::Scalar> >&); // generated by autoexplicit.sh -template void igl::matrix_to_list, -1, 1, true> >(Eigen::DenseBase, -1, 1, true> > const&, std::vector, -1, 1, true>::Scalar, std::allocator, -1, 1, true>::Scalar> >&); +template void igl::matrix_to_list, -1, 1, true> >(Eigen::MatrixBase, -1, 1, true> > const&, std::vector, -1, 1, true>::Scalar, std::allocator, -1, 1, true>::Scalar> >&); // generated by autoexplicit.sh -template void igl::matrix_to_list >(Eigen::DenseBase > const&, std::vector::Scalar, std::allocator::Scalar> >&); +template void igl::matrix_to_list >(Eigen::MatrixBase > const&, std::vector::Scalar, std::allocator::Scalar> >&); // generated by autoexplicit.sh -template std::vector::Scalar, std::allocator::Scalar> > igl::matrix_to_list >(Eigen::DenseBase > const&); +template std::vector::Scalar, std::allocator::Scalar> > igl::matrix_to_list >(Eigen::MatrixBase > const&); // generated by autoexplicit.sh -template std::vector::Scalar, std::allocator::Scalar> > igl::matrix_to_list >(Eigen::DenseBase > const&); +template std::vector::Scalar, std::allocator::Scalar> > igl::matrix_to_list >(Eigen::MatrixBase > const&); //template void igl::matrix_to_list >, double>(Eigen::PlainObjectBase > const&, std::vector >, std::allocator > > >&); //template void igl::matrix_to_list >, int>(Eigen::PlainObjectBase > const&, std::vector >, std::allocator > > >&); -template void igl::matrix_to_list >(Eigen::DenseBase > const&, std::vector::Scalar, std::allocator::Scalar> >, std::allocator::Scalar, std::allocator::Scalar> > > >&); -template void igl::matrix_to_list >(Eigen::DenseBase > const&, std::vector::Scalar, std::allocator::Scalar> >, std::allocator::Scalar, std::allocator::Scalar> > > >&); -template void igl::matrix_to_list >(Eigen::DenseBase > const&, std::vector::Scalar, std::allocator::Scalar> >&); -template void igl::matrix_to_list >(Eigen::DenseBase > const&, std::vector::Scalar, std::allocator::Scalar> >&); -template void igl::matrix_to_list >(Eigen::DenseBase > const&, std::vector::Scalar, std::allocator::Scalar> >&); -template void igl::matrix_to_list >(Eigen::DenseBase > const&, std::vector::Scalar, std::allocator::Scalar> >, std::allocator::Scalar, std::allocator::Scalar> > > >&); -template void igl::matrix_to_list >(Eigen::DenseBase > const&, std::vector::Scalar, std::allocator::Scalar> >&); -template void igl::matrix_to_list >(Eigen::DenseBase > const&, std::vector::Scalar, std::allocator::Scalar> >&); -template std::vector::Scalar, std::allocator::Scalar> > igl::matrix_to_list >(Eigen::DenseBase > const&); -template void igl::matrix_to_list, 1, -1, false> >(Eigen::DenseBase, 1, -1, false> > const&, std::vector, 1, -1, false>::Scalar, std::allocator, 1, -1, false>::Scalar> >&); -template std::vector, 1, -1, false>::Scalar, std::allocator, 1, -1, false>::Scalar> > igl::matrix_to_list, 1, -1, false> >(Eigen::DenseBase, 1, -1, false> > const&); +template void igl::matrix_to_list >(Eigen::MatrixBase > const&, std::vector::Scalar, std::allocator::Scalar> >, std::allocator::Scalar, std::allocator::Scalar> > > >&); +template void igl::matrix_to_list >(Eigen::MatrixBase > const&, std::vector::Scalar, std::allocator::Scalar> >, std::allocator::Scalar, std::allocator::Scalar> > > >&); +template void igl::matrix_to_list >(Eigen::MatrixBase > const&, std::vector::Scalar, std::allocator::Scalar> >&); +template void igl::matrix_to_list >(Eigen::MatrixBase > const&, std::vector::Scalar, std::allocator::Scalar> >&); +template void igl::matrix_to_list >(Eigen::MatrixBase > const&, std::vector::Scalar, std::allocator::Scalar> >&); +template void igl::matrix_to_list >(Eigen::MatrixBase > const&, std::vector::Scalar, std::allocator::Scalar> >, std::allocator::Scalar, std::allocator::Scalar> > > >&); +template void igl::matrix_to_list >(Eigen::MatrixBase > const&, std::vector::Scalar, std::allocator::Scalar> >&); +template void igl::matrix_to_list >(Eigen::MatrixBase > const&, std::vector::Scalar, std::allocator::Scalar> >&); +template std::vector::Scalar, std::allocator::Scalar> > igl::matrix_to_list >(Eigen::MatrixBase > const&); #endif diff --git a/include/igl/matrix_to_list.h b/include/igl/matrix_to_list.h index a84281127..92ebf6b49 100644 --- a/include/igl/matrix_to_list.h +++ b/include/igl/matrix_to_list.h @@ -28,7 +28,7 @@ namespace igl // See also: list_to_matrix template IGL_INLINE void matrix_to_list( - const Eigen::DenseBase & M, + const Eigen::MatrixBase & M, std::vector > & V); // Convert a matrix to a list (std::vector) of elements in column-major // ordering. @@ -39,12 +39,12 @@ namespace igl // V an m*n list of elements template IGL_INLINE void matrix_to_list( - const Eigen::DenseBase & M, + const Eigen::MatrixBase & M, std::vector & V); // Return wrapper template IGL_INLINE std::vector matrix_to_list( - const Eigen::DenseBase & M); + const Eigen::MatrixBase & M); } #ifndef IGL_STATIC_LIBRARY diff --git a/include/igl/min_quad_with_fixed.cpp b/include/igl/min_quad_with_fixed.cpp index e1acd81ff..37b9c4728 100644 --- a/include/igl/min_quad_with_fixed.cpp +++ b/include/igl/min_quad_with_fixed.cpp @@ -51,6 +51,7 @@ IGL_INLINE bool igl::min_quad_with_fixed_precompute( assert(n == Aeq.cols() && "#Aeq.cols() should match A.rows()"); } + assert(known.cols() == 1 && "known should be a vector"); assert(A.rows() == n && "A should be square"); assert(A.cols() == n && "A should be square"); @@ -63,14 +64,16 @@ IGL_INLINE bool igl::min_quad_with_fixed_precompute( // cache known - data.known = known; + // FIXME: This is *NOT* generic and introduces a copy. + data.known = known.template cast(); + // get list of unknown indices data.unknown.resize(n-kr); std::vector unknown_mask; unknown_mask.resize(n,true); for(int i = 0;i #include diff --git a/include/igl/normal_derivative.cpp b/include/igl/normal_derivative.cpp index d943fe0e2..49a332d05 100644 --- a/include/igl/normal_derivative.cpp +++ b/include/igl/normal_derivative.cpp @@ -16,8 +16,8 @@ template < typename DerivedEle, typename Scalar> IGL_INLINE void igl::normal_derivative( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & Ele, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & Ele, Eigen::SparseMatrix& DD) { using namespace Eigen; @@ -114,5 +114,5 @@ IGL_INLINE void igl::normal_derivative( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::normal_derivative, Eigen::Matrix, double>(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::SparseMatrix&); +template void igl::normal_derivative, Eigen::Matrix, double>(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::SparseMatrix&); #endif diff --git a/include/igl/normal_derivative.h b/include/igl/normal_derivative.h index 861b55555..4718d321f 100644 --- a/include/igl/normal_derivative.h +++ b/include/igl/normal_derivative.h @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2015 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_NORMAL_DERIVATIVE_H #define IGL_NORMAL_DERIVATIVE_H @@ -11,7 +11,7 @@ #include #include -namespace igl +namespace igl { // NORMAL_DERIVATIVE Computes the directional derivative **normal** to // **all** (half-)edges of a triangle mesh (not just boundary edges). These @@ -27,12 +27,12 @@ namespace igl // directional derivative with respect to each facet of each element. // template < - typename DerivedV, - typename DerivedEle, + typename DerivedV, + typename DerivedEle, typename Scalar> IGL_INLINE void normal_derivative( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & Ele, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & Ele, Eigen::SparseMatrix& DD); } diff --git a/include/igl/null.cpp b/include/igl/null.cpp index b2291f454..971149266 100644 --- a/include/igl/null.cpp +++ b/include/igl/null.cpp @@ -19,3 +19,7 @@ IGL_INLINE void igl::null( svd.setThreshold(A.cols() * svd.singularValues().maxCoeff() * EPS()); N = svd.matrixV().rightCols(A.cols()-svd.rank()); } + +#ifdef IGL_STATIC_LIBRARY +template void igl::null, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); +#endif diff --git a/include/igl/octree.cpp b/include/igl/octree.cpp index 6bddf0243..3c69d406b 100644 --- a/include/igl/octree.cpp +++ b/include/igl/octree.cpp @@ -176,5 +176,7 @@ namespace igl { #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation +// generated by autoexplicit.sh +template void igl::octree, int, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, std::vector >, std::allocator > > >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::octree, int, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, std::vector >, std::allocator > > >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/opengl/MeshGL.cpp b/include/igl/opengl/MeshGL.cpp index f49924324..621f10fea 100644 --- a/include/igl/opengl/MeshGL.cpp +++ b/include/igl/opengl/MeshGL.cpp @@ -12,6 +12,12 @@ #include "destroy_shader_program.h" #include +IGL_INLINE igl::opengl::MeshGL::MeshGL(): + tex_filter(GL_LINEAR), + tex_wrap(GL_REPEAT) +{ +} + IGL_INLINE void igl::opengl::MeshGL::init_buffers() { // Mesh: Vertex Array Object & Buffer objects @@ -88,10 +94,10 @@ IGL_INLINE void igl::opengl::MeshGL::bind_mesh() glBindTexture(GL_TEXTURE_2D, vbo_tex); if (dirty & MeshGL::DIRTY_TEXTURE) { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, tex_wrap); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, tex_wrap); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, tex_filter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, tex_filter); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, tex_u, tex_v, 0, GL_RGBA, GL_UNSIGNED_BYTE, tex.data()); } diff --git a/include/igl/opengl/MeshGL.h b/include/igl/opengl/MeshGL.h index 74c358903..e5ecc76c5 100644 --- a/include/igl/opengl/MeshGL.h +++ b/include/igl/opengl/MeshGL.h @@ -24,6 +24,7 @@ class MeshGL { public: typedef unsigned int GLuint; + typedef unsigned int GLint; enum DirtyFlags { @@ -82,6 +83,8 @@ public: int tex_u; int tex_v; + GLint tex_filter; + GLint tex_wrap; Eigen::Matrix tex; Eigen::Matrix F_vbo; @@ -91,6 +94,8 @@ public: // Marks dirty buffers that need to be uploaded to OpenGL uint32_t dirty; + IGL_INLINE MeshGL(); + // Initialize shaders and buffers IGL_INLINE void init(); diff --git a/include/igl/opengl/ViewerCore.cpp b/include/igl/opengl/ViewerCore.cpp index b85785f35..47ee35c65 100644 --- a/include/igl/opengl/ViewerCore.cpp +++ b/include/igl/opengl/ViewerCore.cpp @@ -387,6 +387,7 @@ IGL_INLINE igl::opengl::ViewerCore::ViewerCore() // Default trackball trackball_angle = Eigen::Quaternionf::Identity(); + rotation_type = ViewerCore::ROTATION_TYPE_TRACKBALL; set_rotation_type(ViewerCore::ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP); // Camera parameters diff --git a/include/igl/opengl/ViewerData.cpp b/include/igl/opengl/ViewerData.cpp index 8ee13210a..8cfd8693c 100644 --- a/include/igl/opengl/ViewerData.cpp +++ b/include/igl/opengl/ViewerData.cpp @@ -11,29 +11,32 @@ #include "../per_face_normals.h" #include "../material_colors.h" -#include "../parula.h" #include "../per_vertex_normals.h" +// Really? Just for GL_NEAREST? +#include "gl.h" + #include IGL_INLINE igl::opengl::ViewerData::ViewerData() : dirty(MeshGL::DIRTY_ALL), - show_faces(true), - show_lines(true), - invert_normals(false), - show_overlay(true), - show_overlay_depth(true), - show_vertid(false), - show_faceid(false), - show_texture(false), + show_faces (~unsigned(0)), + show_lines (~unsigned(0)), + invert_normals (false), + show_overlay (~unsigned(0)), + show_overlay_depth(~unsigned(0)), + show_vertid (false), + show_faceid (false), + show_labels (false), + show_texture (false), point_size(30), line_width(0.5f), line_color(0,0,0,1), label_color(0,0,0.04,1), shininess(35.0f), id(-1), - is_visible(1) + is_visible (~unsigned(0)) { clear(); }; @@ -136,11 +139,12 @@ IGL_INLINE void igl::opengl::ViewerData::set_colors(const Eigen::MatrixXd &C) { using namespace std; using namespace Eigen; + // This Gouraud coloring should be deprecated in favor of Phong coloring in + // set-data if(C.rows()>0 && C.cols() == 1) { - Eigen::MatrixXd C3; - igl::parula(C,true,C3); - return set_colors(C3); + assert(false && "deprecated: call set_data directly instead"); + return set_data(C); } // Ambient color should be darker color const auto ambient = [](const MatrixXd & C)->MatrixXd @@ -208,7 +212,7 @@ IGL_INLINE void igl::opengl::ViewerData::set_colors(const Eigen::MatrixXd &C) } else cerr << "ERROR (set_colors): Please provide a single color, or a color per face or per vertex."< R = + (CM.col(0)*255.0).cast(); + const Eigen::Matrix G = + (CM.col(1)*255.0).cast(); + const Eigen::Matrix B = + (CM.col(2)*255.0).cast(); + set_colors(Eigen::RowVector3d(1,1,1)); + set_texture(R,G,B); + show_texture = true; + meshgl.tex_filter = GL_NEAREST; + meshgl.tex_wrap = GL_CLAMP_TO_EDGE; +} + IGL_INLINE void igl::opengl::ViewerData::set_points( const Eigen::MatrixXd& P, const Eigen::MatrixXd& C) @@ -288,6 +332,11 @@ IGL_INLINE void igl::opengl::ViewerData::add_points(const Eigen::MatrixXd& P, c dirty |= MeshGL::DIRTY_OVERLAY_POINTS; } +IGL_INLINE void igl::opengl::ViewerData::clear_points() +{ + points.resize(0, 6); +} + IGL_INLINE void igl::opengl::ViewerData::set_edges( const Eigen::MatrixXd& P, const Eigen::MatrixXi& E, @@ -337,6 +386,11 @@ IGL_INLINE void igl::opengl::ViewerData::add_edges(const Eigen::MatrixXd& P1, co dirty |= MeshGL::DIRTY_OVERLAY_LINES; } +IGL_INLINE void igl::opengl::ViewerData::clear_edges() +{ + lines.resize(0, 9); +} + IGL_INLINE void igl::opengl::ViewerData::add_label(const Eigen::VectorXd& P, const std::string& str) { Eigen::RowVectorXd P_temp; @@ -356,6 +410,14 @@ IGL_INLINE void igl::opengl::ViewerData::add_label(const Eigen::VectorXd& P, co labels_strings.push_back(str); } +IGL_INLINE void igl::opengl::ViewerData::set_labels(const Eigen::MatrixXd& P, const std::vector& str) +{ + assert(P.rows() == str.size() && "position # and label # do not match!"); + assert(P.cols() == 3 && "dimension of label positions incorrect!"); + labels_positions = P; + labels_strings = str; +} + IGL_INLINE void igl::opengl::ViewerData::clear_labels() { labels_positions.resize(0,3); @@ -387,6 +449,7 @@ IGL_INLINE void igl::opengl::ViewerData::clear() labels_strings.clear(); face_based = false; + show_texture = false; } IGL_INLINE void igl::opengl::ViewerData::compute_normals() diff --git a/include/igl/opengl/ViewerData.h b/include/igl/opengl/ViewerData.h index cd053bfb7..a84988846 100644 --- a/include/igl/opengl/ViewerData.h +++ b/include/igl/opengl/ViewerData.h @@ -8,8 +8,9 @@ #ifndef IGL_VIEWERDATA_H #define IGL_VIEWERDATA_H -#include "../igl_inline.h" #include "MeshGL.h" +#include +#include #include #include #include @@ -60,17 +61,20 @@ public: // Inputs: // C #V|#F|1 by 3 list of colors IGL_INLINE void set_colors(const Eigen::MatrixXd &C); + // Set per-vertex UV coordinates // // Inputs: // UV #V by 2 list of UV coordinates (indexed by F) IGL_INLINE void set_uv(const Eigen::MatrixXd& UV); + // Set per-corner UV coordinates // // Inputs: // UV_V #UV by 2 list of UV coordinates // UV_F #F by 3 list of UV indices into UV_V IGL_INLINE void set_uv(const Eigen::MatrixXd& UV_V, const Eigen::MatrixXi& UV_F); + // Set the texture associated with the mesh. // // Inputs: @@ -97,7 +101,36 @@ public: const Eigen::Matrix& B, const Eigen::Matrix& A); - // Sets points given a list of point vertices. In constrast to `set_points` + // Set pseudo-colorable scalar data associated with the mesh. + // + // Inputs: + // caxis_min caxis minimum bound + // caxis_max caxis maximum bound + // D #V by 1 list of scalar values + // cmap colormap type + // num_steps number of intervals to discretize the colormap + // + // To-do: support #F by 1 per-face data + IGL_INLINE void set_data( + const Eigen::VectorXd & D, + double caxis_min, + double caxis_max, + igl::ColorMapType cmap = igl::COLOR_MAP_TYPE_VIRIDIS, + int num_steps = 21); + + // Use min(D) and max(D) to set caxis. + IGL_INLINE void set_data(const Eigen::VectorXd & D, + igl::ColorMapType cmap = igl::COLOR_MAP_TYPE_VIRIDIS, + int num_steps = 21); + + // Not to be confused with set_colors, this creates a _texture_ that will be + // referenced to pseudocolor according to the scalar field passed to set_data. + // + // Inputs: + // CM #CM by 3 list of colors + IGL_INLINE void set_colormap(const Eigen::MatrixXd & CM); + + // Sets points given a list of point vertices. In constrast to `add_points` // this will (purposefully) clober existing points. // // Inputs: @@ -107,6 +140,10 @@ public: const Eigen::MatrixXd& P, const Eigen::MatrixXd& C); IGL_INLINE void add_points(const Eigen::MatrixXd& P, const Eigen::MatrixXd& C); + + // Clear the point data + IGL_INLINE void clear_points(); + // Sets edges given a list of edge vertices and edge indices. In constrast // to `add_edges` this will (purposefully) clober existing edges. // @@ -114,14 +151,20 @@ public: // P #P by 3 list of vertex positions // E #E by 2 list of edge indices into P // C #E|1 by 3 color(s) + IGL_INLINE void set_edges (const Eigen::MatrixXd& P, const Eigen::MatrixXi& E, const Eigen::MatrixXd& C); // Alec: This is very confusing. Why does add_edges have a different API from // set_edges? IGL_INLINE void add_edges (const Eigen::MatrixXd& P1, const Eigen::MatrixXd& P2, const Eigen::MatrixXd& C); - // Adds text labels at the given positions in 3D. + // Clear the edge data + IGL_INLINE void clear_edges(); + + // Sets / Adds text labels at the given positions in 3D. // Note: This requires the ImGui viewer plugin to display text labels. IGL_INLINE void add_label (const Eigen::VectorXd& P, const std::string& str); + IGL_INLINE void set_labels (const Eigen::MatrixXd& P, const std::vector& str); + // Clear the label data IGL_INLINE void clear_labels (); @@ -211,6 +254,7 @@ public: unsigned int show_lines; bool show_vertid; // shared across viewports for now bool show_faceid; // shared across viewports for now + bool show_labels; // shared across viewports for now // Point size / line width float point_size; @@ -275,6 +319,7 @@ namespace igl SERIALIZE_MEMBER(show_overlay_depth); SERIALIZE_MEMBER(show_vertid); SERIALIZE_MEMBER(show_faceid); + SERIALIZE_MEMBER(show_labels); SERIALIZE_MEMBER(show_texture); SERIALIZE_MEMBER(point_size); SERIALIZE_MEMBER(line_width); diff --git a/include/igl/opengl/glfw/Viewer.cpp b/include/igl/opengl/glfw/Viewer.cpp index 59b71419c..57b66d9fe 100644 --- a/include/igl/opengl/glfw/Viewer.cpp +++ b/include/igl/opengl/glfw/Viewer.cpp @@ -159,12 +159,12 @@ namespace glfw else { // Set default windows width - if (windowWidth <= 0 & core_list.size() == 1 && core().viewport[2] > 0) + if (windowWidth <= 0 && core_list.size() == 1 && core().viewport[2] > 0) windowWidth = core().viewport[2]; else if (windowWidth <= 0) windowWidth = 1280; // Set default windows height - if (windowHeight <= 0 & core_list.size() == 1 && core().viewport[3] > 0) + if (windowHeight <= 0 && core_list.size() == 1 && core().viewport[3] > 0) windowHeight = core().viewport[3]; else if (windowHeight <= 0) windowHeight = 800; @@ -211,7 +211,10 @@ namespace glfw highdpi = windowWidth/width_window; glfw_window_size(window,width_window,height_window); //opengl.init(); - core().align_camera_center(data().V,data().F); + for(int i=0;idata().show_faces); ImGui::Checkbox("Show vertex labels", &(viewer->data().show_vertid)); ImGui::Checkbox("Show faces labels", &(viewer->data().show_faceid)); + ImGui::Checkbox("Show extra labels", &(viewer->data().show_labels)); } } @@ -334,6 +335,7 @@ IGL_INLINE void ImGuiMenu::draw_labels_window() IGL_INLINE void ImGuiMenu::draw_labels(const igl::opengl::ViewerData &data) { + // Alec: How can we get these to respect (optionally) the depth of the scene? if (data.show_vertid) { for (int i = 0; i < data.V.rows(); ++i) @@ -365,7 +367,7 @@ IGL_INLINE void ImGuiMenu::draw_labels(const igl::opengl::ViewerData &data) } } - if (data.labels_positions.rows() > 0) + if (data.show_labels) { for (int i = 0; i < data.labels_positions.rows(); ++i) { diff --git a/include/igl/opengl/glfw/imgui/ImGuiTraits.h b/include/igl/opengl/glfw/imgui/ImGuiTraits.h index fbc892f34..7dae22a78 100644 --- a/include/igl/opengl/glfw/imgui/ImGuiTraits.h +++ b/include/igl/opengl/glfw/imgui/ImGuiTraits.h @@ -26,42 +26,42 @@ template<> class ImGuiDataTypeTraits { static constexpr ImGuiDataType value = ImGuiDataType_S32; - static constexpr char format [] = "%d"; + static constexpr const char *format = "%d"; }; template<> class ImGuiDataTypeTraits { static constexpr ImGuiDataType value = ImGuiDataType_U32; - static constexpr char format [] = "%u"; + static constexpr const char *format = "%u"; }; template<> class ImGuiDataTypeTraits { static constexpr ImGuiDataType value = ImGuiDataType_S64; - static constexpr char format [] = "%lld"; + static constexpr const char *format = "%lld"; }; template<> class ImGuiDataTypeTraits { static constexpr ImGuiDataType value = ImGuiDataType_U64; - static constexpr char format [] = "%llu"; + static constexpr const char *format = "%llu"; }; template<> class ImGuiDataTypeTraits { static constexpr ImGuiDataType value = ImGuiDataType_Float; - static constexpr char format [] = "%.3f"; + static constexpr const char *format = "%.3f"; }; template<> class ImGuiDataTypeTraits { static constexpr ImGuiDataType value = ImGuiDataType_Double; - static constexpr char format [] = "%.6f"; + static constexpr const char *format = "%.6f"; }; } // namespace ImGui diff --git a/include/igl/orient_outward.cpp b/include/igl/orient_outward.cpp index 522745bc4..0c422e615 100644 --- a/include/igl/orient_outward.cpp +++ b/include/igl/orient_outward.cpp @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2013 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "orient_outward.h" #include "per_face_normals.h" @@ -12,15 +12,15 @@ #include template < - typename DerivedV, - typename DerivedF, - typename DerivedC, - typename DerivedFF, + typename DerivedV, + typename DerivedF, + typename DerivedC, + typename DerivedFF, typename DerivedI> IGL_INLINE void igl::orient_outward( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, - const Eigen::PlainObjectBase & C, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const Eigen::MatrixBase & C, Eigen::PlainObjectBase & FF, Eigen::PlainObjectBase & I) { @@ -90,6 +90,7 @@ IGL_INLINE void igl::orient_outward( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::orient_outward, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::orient_outward, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::orient_outward, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/orient_outward.h b/include/igl/orient_outward.h index 197c8b950..5f4fdc31f 100644 --- a/include/igl/orient_outward.h +++ b/include/igl/orient_outward.h @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2013 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_ORIENT_OUTWARD_H #define IGL_ORIENT_OUTWARD_H @@ -23,15 +23,15 @@ namespace igl // FF(I,:) = fliplr(F(I,:)) (OK if &FF = &F) // I max(C)+1 list of whether face has been flipped template < - typename DerivedV, - typename DerivedF, - typename DerivedC, - typename DerivedFF, + typename DerivedV, + typename DerivedF, + typename DerivedC, + typename DerivedFF, typename DerivedI> IGL_INLINE void orient_outward( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, - const Eigen::PlainObjectBase & C, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const Eigen::MatrixBase & C, Eigen::PlainObjectBase & FF, Eigen::PlainObjectBase & I); }; diff --git a/include/igl/orientable_patches.cpp b/include/igl/orientable_patches.cpp index 0e3114835..441f25937 100644 --- a/include/igl/orientable_patches.cpp +++ b/include/igl/orientable_patches.cpp @@ -14,7 +14,7 @@ template IGL_INLINE void igl::orientable_patches( - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & C, Eigen::SparseMatrix & A) { @@ -27,7 +27,7 @@ IGL_INLINE void igl::orientable_patches( // List of all "half"-edges: 3*#F by 2 Matrix allE,sortallE,uE; allE.resize(F.rows()*3,2); - Matrix IX; + Matrix IX; VectorXi IA,IC; allE.block(0*F.rows(),0,F.rows(),1) = F.col(1); allE.block(0*F.rows(),1,F.rows(),1) = F.col(2); @@ -91,7 +91,7 @@ IGL_INLINE void igl::orientable_patches( template IGL_INLINE void igl::orientable_patches( - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & C) { Eigen::SparseMatrix A; @@ -100,6 +100,6 @@ IGL_INLINE void igl::orientable_patches( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::orientable_patches, Eigen::Matrix, int>(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::SparseMatrix&); -template void igl::orientable_patches, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); +template void igl::orientable_patches, Eigen::Matrix, int>(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::SparseMatrix&); +template void igl::orientable_patches, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/orientable_patches.h b/include/igl/orientable_patches.h index a74284ac5..a77cf3cb8 100644 --- a/include/igl/orientable_patches.h +++ b/include/igl/orientable_patches.h @@ -27,12 +27,12 @@ namespace igl // template IGL_INLINE void orientable_patches( - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & C, Eigen::SparseMatrix & A); template IGL_INLINE void orientable_patches( - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & C); }; #ifndef IGL_STATIC_LIBRARY diff --git a/include/igl/parula.cpp b/include/igl/parula.cpp index b3daaa5e7..42d12ac20 100644 --- a/include/igl/parula.cpp +++ b/include/igl/parula.cpp @@ -20,7 +20,6 @@ IGL_INLINE void igl::parula(const T f, T & r, T & g, T & b) igl::colormap(igl::COLOR_MAP_TYPE_PARULA, f, r, g, b); } - template IGL_INLINE void igl::parula( const Eigen::MatrixBase & Z, diff --git a/include/igl/path_to_edges.cpp b/include/igl/path_to_edges.cpp new file mode 100644 index 000000000..97112e4af --- /dev/null +++ b/include/igl/path_to_edges.cpp @@ -0,0 +1,42 @@ +#include "path_to_edges.h" + +template +IGL_INLINE void igl::path_to_edges( + const Eigen::MatrixBase & I, + Eigen::PlainObjectBase & E, + bool make_loop) +{ + // Check that I is 1 dimensional + assert(I.size() == I.rows() || I.size() == I.cols()); + + if(make_loop) { + E.conservativeResize(I.size(), 2); + for(int i = 0; i < I.size() - 1; i++) { + E(i, 0) = I(i); + E(i, 1) = I(i + 1); + } + E(I.size() - 1, 0) = I(I.size() - 1); + E(I.size() - 1, 1) = I(0); + } else { + E.conservativeResize(I.size()-1, 2); + for(int i = 0; i < I.size()-1; i++) { + E(i, 0) = I(i); + E(i, 1) = I(i+1); + } + } +} + +template +IGL_INLINE void igl::path_to_edges( + const std::vector & I, + Eigen::PlainObjectBase & E, + bool make_loop) +{ + igl::path_to_edges(Eigen::Map>(I.data(), I.size()), E, make_loop); +} + +#ifdef IGL_STATIC_LIBRARY +template void igl::path_to_edges, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, bool); +template void igl::path_to_edges >(std::vector > const&, Eigen::PlainObjectBase >&, bool); +#endif + \ No newline at end of file diff --git a/include/igl/path_to_edges.h b/include/igl/path_to_edges.h new file mode 100644 index 000000000..81b03eee7 --- /dev/null +++ b/include/igl/path_to_edges.h @@ -0,0 +1,45 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2019 Lawson Fulton lawsonfulton@gmail.com +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// obtain one at http://mozilla.org/MPL/2.0/ +#ifndef IGL_PATH_TO_EDGES_H +#define IGL_PATH_TO_EDGES_H + +#include "igl_inline.h" + +#include + +#include + +namespace igl +{ + // Given a path as an ordered list of N>=2 vertex indices I[0], I[1], ..., I[N-1] + // construct a list of edges [[I[0],I[1]], [I[1],I[2]], ..., [I[N-2], I[N-1]]] + // connecting each sequential pair of vertices. + // + // Inputs: + // I #I list of vertex indices + // make_loop bool If true, include an edge connecting I[N-1] to I[0] + // Outputs: + // E #I-1 by 2 list of edges + // + template + IGL_INLINE void path_to_edges( + const Eigen::MatrixBase & I, + Eigen::PlainObjectBase & E, + bool make_loop=false); + + template + IGL_INLINE void path_to_edges( + const std::vector & I, + Eigen::PlainObjectBase & E, + bool make_loop=false); + +} +#ifndef IGL_STATIC_LIBRARY +# include "path_to_edges.cpp" +#endif +#endif diff --git a/include/igl/path_to_executable.cpp b/include/igl/path_to_executable.cpp index 509a763d6..fb42a79ba 100644 --- a/include/igl/path_to_executable.cpp +++ b/include/igl/path_to_executable.cpp @@ -11,8 +11,11 @@ #endif #if defined(_WIN32) # include +#else + #include #endif #include + IGL_INLINE std::string igl::path_to_executable() { // http://pastebin.com/ffzzxPzi @@ -28,10 +31,11 @@ IGL_INLINE std::string igl::path_to_executable() { path = buffer; } -#elif defined(UNIX) - if (readlink("/proc/self/exe", buffer, sizeof(buffer)) == -1) +#elif defined(UNIX) || defined(unix) || defined(__unix) || defined(__unix__) + int byte_count = readlink("/proc/self/exe", buffer, size); + if (byte_count != -1) { - path = buffer; + path = std::string(buffer, byte_count); } #elif defined(__FreeBSD__) int mib[4]; diff --git a/include/igl/per_edge_normals.cpp b/include/igl/per_edge_normals.cpp index 8aa71791d..394d25cf3 100644 --- a/include/igl/per_edge_normals.cpp +++ b/include/igl/per_edge_normals.cpp @@ -36,10 +36,10 @@ IGL_INLINE void igl::per_edge_normals( // number of faces const int m = F.rows(); // All occurrences of directed edges - MatrixXi allE; + Matrix allE; oriented_facets(F,allE); // Find unique undirected edges and mapping - VectorXi _; + Matrix _; unique_simplices(allE,E,_,EMAP); // now sort(allE,2) == E(EMAP,:), that is, if EMAP(i) = j, then E.row(j) is // the undirected edge corresponding to the directed edge allE.row(i). @@ -67,10 +67,10 @@ IGL_INLINE void igl::per_edge_normals( { if(weighting == PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM) { - N.row(EMAP(f+c*m)) += FN.row(f); + N.row(EMAP(f+c*m, 0)) += FN.row(f); }else { - N.row(EMAP(f+c*m)) += W(f) * FN.row(f); + N.row(EMAP(f+c*m, 0)) += W(f) * FN.row(f); } } } diff --git a/include/igl/per_vertex_attribute_smoothing.cpp b/include/igl/per_vertex_attribute_smoothing.cpp index ecf2b4e82..91021a309 100644 --- a/include/igl/per_vertex_attribute_smoothing.cpp +++ b/include/igl/per_vertex_attribute_smoothing.cpp @@ -10,8 +10,8 @@ template IGL_INLINE void igl::per_vertex_attribute_smoothing( - const Eigen::PlainObjectBase& Ain, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& Ain, + const Eigen::MatrixBase& F, Eigen::PlainObjectBase & Aout) { std::vector denominator(Ain.rows(), 0); @@ -29,5 +29,5 @@ IGL_INLINE void igl::per_vertex_attribute_smoothing( } #ifdef IGL_STATIC_LIBRARY -template void igl::per_vertex_attribute_smoothing, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); +template void igl::per_vertex_attribute_smoothing, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/per_vertex_attribute_smoothing.h b/include/igl/per_vertex_attribute_smoothing.h index 662810236..819c145f5 100644 --- a/include/igl/per_vertex_attribute_smoothing.h +++ b/include/igl/per_vertex_attribute_smoothing.h @@ -20,8 +20,8 @@ namespace igl // Aout #V by #A eigen Matrix of mesh vertex attributes template IGL_INLINE void per_vertex_attribute_smoothing( - const Eigen::PlainObjectBase& Ain, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& Ain, + const Eigen::MatrixBase& F, Eigen::PlainObjectBase & Aout); } diff --git a/include/igl/planarize_quad_mesh.cpp b/include/igl/planarize_quad_mesh.cpp index d3c06be62..24687e9a7 100644 --- a/include/igl/planarize_quad_mesh.cpp +++ b/include/igl/planarize_quad_mesh.cpp @@ -20,8 +20,8 @@ namespace igl // number of faces, number of vertices long numV, numF; // references to the input faces and vertices - const Eigen::PlainObjectBase &Vin; - const Eigen::PlainObjectBase &Fin; + const Eigen::MatrixBase &Vin; + const Eigen::MatrixBase &Fin; // vector consisting of the vertex positions stacked: [x;y;z;x;y;z...] // vector consisting of a weight per face (currently all set to 1) @@ -50,8 +50,8 @@ namespace igl public: // Init - assemble stacked vector and lhs matrix, factorize - inline PlanarizerShapeUp(const Eigen::PlainObjectBase &V_, - const Eigen::PlainObjectBase &F_, + inline PlanarizerShapeUp(const Eigen::MatrixBase &V_, + const Eigen::MatrixBase &F_, const int maxIter_, const double &threshold_); // Planarization - output to Vout @@ -62,8 +62,8 @@ namespace igl //Implementation template -inline igl::PlanarizerShapeUp::PlanarizerShapeUp(const Eigen::PlainObjectBase &V_, - const Eigen::PlainObjectBase &F_, +inline igl::PlanarizerShapeUp::PlanarizerShapeUp(const Eigen::MatrixBase &V_, + const Eigen::MatrixBase &F_, const int maxIter_, const double &threshold_): numV(V_.rows()), @@ -229,8 +229,8 @@ inline void igl::PlanarizerShapeUp::planarize(Eigen::PlainOb template -IGL_INLINE void igl::planarize_quad_mesh(const Eigen::PlainObjectBase &Vin, - const Eigen::PlainObjectBase &Fin, +IGL_INLINE void igl::planarize_quad_mesh(const Eigen::MatrixBase &Vin, + const Eigen::MatrixBase &Fin, const int maxIter, const double &threshold, Eigen::PlainObjectBase &Vout) @@ -241,5 +241,5 @@ IGL_INLINE void igl::planarize_quad_mesh(const Eigen::PlainObjectBase #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::planarize_quad_mesh, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, int, double const&, Eigen::PlainObjectBase >&); +template void igl::planarize_quad_mesh, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, double const&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/planarize_quad_mesh.h b/include/igl/planarize_quad_mesh.h index 0de7bf389..3d257da8a 100644 --- a/include/igl/planarize_quad_mesh.h +++ b/include/igl/planarize_quad_mesh.h @@ -33,8 +33,8 @@ namespace igl // template - IGL_INLINE void planarize_quad_mesh(const Eigen::PlainObjectBase &Vin, - const Eigen::PlainObjectBase &F, + IGL_INLINE void planarize_quad_mesh(const Eigen::MatrixBase &Vin, + const Eigen::MatrixBase &F, const int maxIter, const double &threshold, Eigen::PlainObjectBase &Vout); diff --git a/include/igl/point_mesh_squared_distance.cpp b/include/igl/point_mesh_squared_distance.cpp index 67ee634a4..70658f64e 100644 --- a/include/igl/point_mesh_squared_distance.cpp +++ b/include/igl/point_mesh_squared_distance.cpp @@ -12,13 +12,14 @@ template < typename DerivedP, typename DerivedV, + typename DerivedEle, typename DerivedsqrD, typename DerivedI, typename DerivedC> IGL_INLINE void igl::point_mesh_squared_distance( - const Eigen::PlainObjectBase & P, - const Eigen::PlainObjectBase & V, - const Eigen::MatrixXi & Ele, + const Eigen::MatrixBase & P, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & Ele, Eigen::PlainObjectBase & sqrD, Eigen::PlainObjectBase & I, Eigen::PlainObjectBase & C) @@ -48,11 +49,14 @@ IGL_INLINE void igl::point_mesh_squared_distance( } #ifdef IGL_STATIC_LIBRARY -template void igl::point_mesh_squared_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::Matrix const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::point_mesh_squared_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::Matrix const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::point_mesh_squared_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::Matrix const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::point_mesh_squared_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::Matrix const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::point_mesh_squared_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix>(Eigen::MatrixBase> const &, Eigen::MatrixBase> const &, Eigen::MatrixBase> const &, Eigen::PlainObjectBase> &, Eigen::PlainObjectBase> &, Eigen::PlainObjectBase> &); +template void igl::point_mesh_squared_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase> const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::point_mesh_squared_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase> const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::point_mesh_squared_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase> const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::point_mesh_squared_distance, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); + #ifdef WIN32 -template void igl::point_mesh_squared_distance,class Eigen::Matrix,class Eigen::Matrix,class Eigen::Matrix<__int64,-1,1,0,-1,1>,class Eigen::Matrix >(class Eigen::PlainObjectBase > const &,class Eigen::PlainObjectBase > const &,class Eigen::Matrix const &,class Eigen::PlainObjectBase > &,class Eigen::PlainObjectBase > &,class Eigen::PlainObjectBase > &); +template void igl::point_mesh_squared_distance, class Eigen::Matrix, class Eigen::Matrix, Eigen::Matrix, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::Matrix>(class Eigen::MatrixBase> const &, class Eigen::MatrixBase> const &, class Eigen::MatrixBase> const &, class Eigen::PlainObjectBase> &, class Eigen::PlainObjectBase> &, class Eigen::PlainObjectBase> &); +template void igl::point_mesh_squared_distance, class Eigen::Matrix, class Eigen::Matrix, class Eigen::Matrix, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::Matrix>(class Eigen::MatrixBase> const &, class Eigen::MatrixBase> const &, class Eigen::MatrixBase> const &, class Eigen::PlainObjectBase> &, class Eigen::PlainObjectBase> &, class Eigen::PlainObjectBase> &); #endif #endif diff --git a/include/igl/point_mesh_squared_distance.h b/include/igl/point_mesh_squared_distance.h index 0635288a3..e26486122 100644 --- a/include/igl/point_mesh_squared_distance.h +++ b/include/igl/point_mesh_squared_distance.h @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2014 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_POINT_MESH_SQUARED_DISTANCE_H #define IGL_POINT_MESH_SQUARED_DISTANCE_H @@ -30,19 +30,20 @@ namespace igl // triangle [1 1 1] is treated as a point. So one _could_ add extra // combinatorially degenerate rows to Ele for all unreferenced vertices to // also get distances to points. - template < +template < typename DerivedP, typename DerivedV, + typename DerivedEle, typename DerivedsqrD, typename DerivedI, typename DerivedC> - IGL_INLINE void point_mesh_squared_distance( - const Eigen::PlainObjectBase & P, - const Eigen::PlainObjectBase & V, - const Eigen::MatrixXi & Ele, - Eigen::PlainObjectBase & sqrD, - Eigen::PlainObjectBase & I, - Eigen::PlainObjectBase & C); +IGL_INLINE void point_mesh_squared_distance( + const Eigen::MatrixBase &P, + const Eigen::MatrixBase &V, + const Eigen::MatrixBase &Ele, + Eigen::PlainObjectBase &sqrD, + Eigen::PlainObjectBase &I, + Eigen::PlainObjectBase &C); } #ifndef IGL_STATIC_LIBRARY diff --git a/include/igl/point_simplex_squared_distance.cpp b/include/igl/point_simplex_squared_distance.cpp index 2b98bd285..e34cfb322 100644 --- a/include/igl/point_simplex_squared_distance.cpp +++ b/include/igl/point_simplex_squared_distance.cpp @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2016 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "point_simplex_squared_distance.h" #include "project_to_line_segment.h" @@ -42,8 +42,8 @@ IGL_INLINE void igl::point_simplex_squared_distance( return a.dot(b); }; // Real-time collision detection, Ericson, Chapter 5 - const auto & ClosestBaryPtPointTriangle = - [&Dot](Point p, Point a, Point b, Point c, BaryPoint& bary_out )->Point + const auto & ClosestBaryPtPointTriangle = + [&Dot](Point p, Point a, Point b, Point c, BaryPoint& bary_out )->Point { // Check if P in vertex region outside A Vector ab = b - a; @@ -178,4 +178,6 @@ template void igl::point_simplex_squared_distance<3, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, double, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::Matrix::Index, double&, Eigen::MatrixBase >&, Eigen::PlainObjectBase >&); template void igl::point_simplex_squared_distance<2, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, double, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::Matrix::Index, double&, Eigen::MatrixBase >&, Eigen::PlainObjectBase >&); template void igl::point_simplex_squared_distance<2, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, double, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::Matrix::Index, double&, Eigen::MatrixBase >&, Eigen::PlainObjectBase >&); +template void igl::point_simplex_squared_distance<2, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, double, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::Matrix::Index, double&, Eigen::MatrixBase >&); +template void igl::point_simplex_squared_distance<3, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, double, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::Matrix::Index, double&, Eigen::MatrixBase >&); #endif diff --git a/include/igl/polar_svd.cpp b/include/igl/polar_svd.cpp index 962a754fb..adf50e8fc 100644 --- a/include/igl/polar_svd.cpp +++ b/include/igl/polar_svd.cpp @@ -16,12 +16,17 @@ template < typename DerivedR, typename DerivedT> IGL_INLINE void igl::polar_svd( - const Eigen::PlainObjectBase & A, + const Eigen::MatrixBase & A, Eigen::PlainObjectBase & R, Eigen::PlainObjectBase & T) { - DerivedA U; - DerivedA V; + typedef + Eigen::Matrix + MatA; + MatA U; + MatA V; Eigen::Matrix S; return igl::polar_svd(A,R,T,U,S,V); } @@ -34,7 +39,7 @@ template < typename DerivedS, typename DerivedV> IGL_INLINE void igl::polar_svd( - const Eigen::PlainObjectBase & A, + const Eigen::MatrixBase & A, Eigen::PlainObjectBase & R, Eigen::PlainObjectBase & T, Eigen::PlainObjectBase & U, @@ -42,7 +47,12 @@ IGL_INLINE void igl::polar_svd( Eigen::PlainObjectBase & V) { using namespace std; - Eigen::JacobiSVD svd; + typedef + Eigen::Matrix + MatA; + Eigen::JacobiSVD svd; svd.compute(A, Eigen::ComputeFullU | Eigen::ComputeFullV ); U = svd.matrixU(); V = svd.matrixV(); @@ -65,16 +75,18 @@ IGL_INLINE void igl::polar_svd( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::polar_svd,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix >(Eigen::PlainObjectBase > const &,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase >&); -template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh +template void igl::polar_svd >, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::polar_svd,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix >(Eigen::MatrixBase > const &,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase > &,Eigen::PlainObjectBase >&); +template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::polar_svd, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/polar_svd.h b/include/igl/polar_svd.h index 13d3f3873..f0f38e7a1 100644 --- a/include/igl/polar_svd.h +++ b/include/igl/polar_svd.h @@ -33,7 +33,7 @@ namespace igl typename DerivedS, typename DerivedV> IGL_INLINE void polar_svd( - const Eigen::PlainObjectBase & A, + const Eigen::MatrixBase & A, Eigen::PlainObjectBase & R, Eigen::PlainObjectBase & T, Eigen::PlainObjectBase & U, @@ -44,7 +44,7 @@ namespace igl typename DerivedR, typename DerivedT> IGL_INLINE void polar_svd( - const Eigen::PlainObjectBase & A, + const Eigen::MatrixBase & A, Eigen::PlainObjectBase & R, Eigen::PlainObjectBase & T); } diff --git a/include/igl/predicates/ear_clipping.cpp b/include/igl/predicates/ear_clipping.cpp new file mode 100644 index 000000000..fc3cd1b79 --- /dev/null +++ b/include/igl/predicates/ear_clipping.cpp @@ -0,0 +1,124 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2019 Hanxiao Shen +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// obtain one at http://mozilla.org/MPL/2.0/. + +#include +#include "ear_clipping.h" +#include "point_inside_convex_polygon.h" +#include "predicates.h" + +template +IGL_INLINE void igl::predicates::ear_clipping( + const Eigen::MatrixBase& P, + const Eigen::MatrixBase& RT, + Eigen::PlainObjectBase& I, + Eigen::PlainObjectBase& eF, + Eigen::PlainObjectBase& nP +){ + typedef typename DerivedF::Scalar Index; + typedef typename DerivedP::Scalar Scalar; + static_assert(std::is_same::value, + "index type should be consistent"); + + // check whether vertex i is an ear + auto is_ear = []( + const Eigen::MatrixBase& P, + const Eigen::MatrixBase& RT, + const Eigen::Matrix& L, + const Eigen::Matrix& R, + const Index i + ){ + + Index a = L(i), b = R(i); + if(RT(i) != 0 || RT(a) != 0 || RT(b) != 0) return false; + Eigen::Matrix pa = P.row(a); + Eigen::Matrix pb = P.row(b); + Eigen::Matrix pi = P.row(i); + auto r = igl::predicates::orient2d(pa,pi,pb); + if(r == igl::predicates::Orientation::NEGATIVE || + r == igl::predicates::Orientation::COLLINEAR) return false; + + // check if any vertex is lying inside triangle (a,b,i); + Index k=R(b); + while(k!=a){ + Eigen::Matrix T(3,2); + T< q=P.row(k); + if(igl::predicates::point_inside_convex_polygon(T,q)) + return false; + k=R(k); + } + return true; + }; + + Eigen::Matrix L(P.rows()); + Eigen::Matrix R(P.rows()); + for(int i=0;i ears; // mark ears + Eigen::Matrix X; // clipped vertices + ears.setZero(P.rows()); + X.setZero(P.rows()); + + // initialize ears + for(int i=0;i, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +#endif diff --git a/include/igl/predicates/ear_clipping.h b/include/igl/predicates/ear_clipping.h new file mode 100644 index 000000000..79e6f9fe0 --- /dev/null +++ b/include/igl/predicates/ear_clipping.h @@ -0,0 +1,51 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2019 Hanxiao Shen +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef IGL_PREDICATES_EAR_CLIPPING_H +#define IGL_PREDICATES_EAR_CLIPPING_H + +#include +#include "../igl_inline.h" + +namespace igl +{ + namespace predicates + { + + // Implementation of ear clipping triangulation algorithm for a 2D polygon. + // https://www.geometrictools.com/Documentation/TriangulationByEarClipping.pdf + // If the polygon is simple, all vertices will be clipped and the result mesh is (P,eF) + // Otherwise, the function will try to clip as many ears as possible. + // + // Input: + // P : n*2, size n 2D polygon + // RT: n*1, preserved vertices (do not clip) marked as 1, otherwise 0 + // Output: + // I : size #nP vector, maps index from nP to P, e.g. nP's ith vertex is origianlly I(i) in P + // eF: clipped ears, in original index of P + // nP: leftover vertices after clipping + + template + IGL_INLINE void ear_clipping( + const Eigen::MatrixBase& P, + const Eigen::MatrixBase& RT, + Eigen::PlainObjectBase& I, + Eigen::PlainObjectBase& eF, + Eigen::PlainObjectBase& nP + ); + + } +} + +#ifndef IGL_STATIC_LIBRARY +# include "ear_clipping.cpp" +#endif + + +#endif diff --git a/include/igl/predicates/point_inside_convex_polygon.cpp b/include/igl/predicates/point_inside_convex_polygon.cpp new file mode 100644 index 000000000..cfec83e91 --- /dev/null +++ b/include/igl/predicates/point_inside_convex_polygon.cpp @@ -0,0 +1,33 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2019 Hanxiao Shen +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// obtain one at http://mozilla.org/MPL/2.0/. + +#include "point_inside_convex_polygon.h" + +template +IGL_INLINE bool igl::predicates::point_inside_convex_polygon( + const Eigen::MatrixBase& P, + const Eigen::MatrixBase& q +){ + EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(DerivedP, Eigen::Dynamic, 2); + EIGEN_STATIC_ASSERT_MATRIX_SPECIFIC_SIZE(DerivedQ, 1, 2); + typedef typename DerivedP::Scalar Scalar; + for(int i=0;i a = P.row(i); + Eigen::Matrix b = P.row(i_1); + auto r = igl::predicates::orient2d(a,b,q); + if(r == igl::predicates::Orientation::COLLINEAR || + r == igl::predicates::Orientation::NEGATIVE) + return false; + } + return true; +} + +#ifdef IGL_STATIC_LIBRARY +template bool igl::predicates::point_inside_convex_polygon, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); +#endif diff --git a/include/igl/predicates/point_inside_convex_polygon.h b/include/igl/predicates/point_inside_convex_polygon.h new file mode 100644 index 000000000..58b69aeca --- /dev/null +++ b/include/igl/predicates/point_inside_convex_polygon.h @@ -0,0 +1,39 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2019 Hanxiao Shen +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef IGL_PREDICATES_POINT_INSIDE_CONVEX_POLYGON_H +#define IGL_PREDICATES_POINT_INSIDE_CONVEX_POLYGON_H + + + +#include "../igl_inline.h" +#include +#include "predicates.h" + +namespace igl +{ + namespace predicates + { + // check whether 2d point lies inside 2d convex polygon + // Inputs: + // P: n*2 polygon, n >= 3 + // q: 2d query point + // Returns true if point is inside polygon + template + IGL_INLINE bool point_inside_convex_polygon( + const Eigen::MatrixBase& P, + const Eigen::MatrixBase& q + ); + } +} + +#ifndef IGL_STATIC_LIBRARY +# include "point_inside_convex_polygon.cpp" +#endif + +#endif diff --git a/include/igl/predicates/predicates.cpp b/include/igl/predicates/predicates.cpp index 0c8e00dee..ca38d76bd 100644 --- a/include/igl/predicates/predicates.cpp +++ b/include/igl/predicates/predicates.cpp @@ -28,11 +28,17 @@ using REAL = IGL_PREDICATES_REAL; #endif IGL_INLINE void exactinit() { - static bool initialized = false; - if (! initialized) { - ::exactinit(); - initialized = true; - } + // Thread-safe initialization using Meyers' singleton + class MySingleton { + public: + static MySingleton& instance() { + static MySingleton instance; + return instance; + } + private: + MySingleton() { ::exactinit(); } + }; + MySingleton::instance(); } template diff --git a/include/igl/predicates/predicates.h b/include/igl/predicates/predicates.h index bc3be1e6d..353088694 100644 --- a/include/igl/predicates/predicates.h +++ b/include/igl/predicates/predicates.h @@ -2,8 +2,8 @@ // // Copyright (C) 2019 Qingnan Zhou // -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #pragma once #ifndef IGL_PREDICATES_PREDICATES_H @@ -20,8 +20,9 @@ namespace igl { COLLINEAR=0, COPLANAR=0, COCIRCULAR=0, COSPHERICAL=0, DEGENERATE=0 }; - // Initialize internal variable used by predciates. Must be called before - // using exact predicates. + // Initialize internal variable used by predciates. Must be called before + // using exact predicates. It is safe to call this function from multiple + // threads. IGL_INLINE void exactinit(); // Compute the orientation of the triangle formed by pa, pb, pc. diff --git a/include/igl/predicates/segment_segment_intersect.cpp b/include/igl/predicates/segment_segment_intersect.cpp new file mode 100644 index 000000000..acf97cfbe --- /dev/null +++ b/include/igl/predicates/segment_segment_intersect.cpp @@ -0,0 +1,52 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2019 Hanxiao Shen +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// obtain one at http://mozilla.org/MPL/2.0/. + +#include "segment_segment_intersect.h" + +// https://www.geeksforgeeks.org/check-if-two-given-line-segments-intersect/ +template +IGL_INLINE bool igl::predicates::segment_segment_intersect( + const Eigen::MatrixBase& a, + const Eigen::MatrixBase& b, + const Eigen::MatrixBase& c, + const Eigen::MatrixBase& d +) +{ + typename DerivedP::Scalar Scalar; + + auto t1 = igl::predicates::orient2d(a,b,c); + auto t2 = igl::predicates::orient2d(b,c,d); + auto t3 = igl::predicates::orient2d(a,b,d); + auto t4 = igl::predicates::orient2d(a,c,d); + + // assume m,n,p are colinear, check whether p is in range [m,n] + auto on_segment = []( + const Eigen::MatrixBase& m, + const Eigen::MatrixBase& n, + const Eigen::MatrixBase& p + ){ + return ((p(0) >= std::min(m(0),n(0))) && + (p(0) <= std::max(m(0),n(0))) && + (p(1) >= std::min(m(1),n(1))) && + (p(1) <= std::max(m(1),n(1)))); + }; + + // colinear case + if((t1 == igl::predicates::Orientation::COLLINEAR && on_segment(a,b,c)) || + (t2 == igl::predicates::Orientation::COLLINEAR && on_segment(c,d,b)) || + (t3 == igl::predicates::Orientation::COLLINEAR && on_segment(a,b,d)) || + (t4 == igl::predicates::Orientation::COLLINEAR && on_segment(c,d,a))) + return true; + + // ordinary case + return (t1 != t3 && t2 != t4); +} + +#ifdef IGL_STATIC_LIBRARY +template bool igl::predicates::segment_segment_intersect >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); +#endif diff --git a/include/igl/predicates/segment_segment_intersect.h b/include/igl/predicates/segment_segment_intersect.h new file mode 100644 index 000000000..4c1ac1ee1 --- /dev/null +++ b/include/igl/predicates/segment_segment_intersect.h @@ -0,0 +1,44 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2019 Hanxiao Shen +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef IGL_PREDICATES_SEGMENT_SEGMENT_INTERSECT_H +#define IGL_PREDICATES_SEGMENT_SEGMENT_INTERSECT_H + +#include +#include +#include "predicates.h" +namespace igl +{ + namespace predicates + { + + // Given two segments in 2d test whether they intersect each other + // using predicates orient2d + // + // Inputs: + // A: 1st endpoint of segment 1 + // B: 2st endpoint of segment 1 + // C: 1st endpoint of segment 2 + // D: 2st endpoint of segment 2 + // Returns true if they intersect + + template + IGL_INLINE bool segment_segment_intersect( + // input: + const Eigen::MatrixBase& A, + const Eigen::MatrixBase& B, + const Eigen::MatrixBase& C, + const Eigen::MatrixBase& D + ); + + } +} +#ifndef IGL_STATIC_LIBRARY +# include "segment_segment_intersect.cpp" +#endif +#endif //IGL_PREDICATES_SEGMENT_SEGMENT_INTERSECT_H diff --git a/include/igl/principal_curvature.cpp b/include/igl/principal_curvature.cpp index c84abe3a3..ae2760dd0 100644 --- a/include/igl/principal_curvature.cpp +++ b/include/igl/principal_curvature.cpp @@ -777,8 +777,8 @@ template < typename DerivedPV2, typename Index> IGL_INLINE void igl::principal_curvature( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, Eigen::PlainObjectBase& PD1, Eigen::PlainObjectBase& PD2, Eigen::PlainObjectBase& PV1, @@ -862,8 +862,8 @@ template < typename DerivedPV1, typename DerivedPV2> IGL_INLINE void igl::principal_curvature( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, Eigen::PlainObjectBase& PD1, Eigen::PlainObjectBase& PD2, Eigen::PlainObjectBase& PV1, @@ -929,8 +929,8 @@ IGL_INLINE void igl::principal_curvature( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh -template void igl::principal_curvature, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, unsigned int, bool); -template void igl::principal_curvature, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, unsigned int, bool); -template void igl::principal_curvature, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, unsigned int, bool); -template void igl::principal_curvature, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, int>(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, std::vector >&, unsigned int, bool); +template void igl::principal_curvature, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, unsigned int, bool); +template void igl::principal_curvature, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, unsigned int, bool); +template void igl::principal_curvature, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, unsigned int, bool); +template void igl::principal_curvature, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, int>(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, std::vector >&, unsigned int, bool); #endif diff --git a/include/igl/principal_curvature.h b/include/igl/principal_curvature.h index ab2ab7daf..d8b49b4b7 100644 --- a/include/igl/principal_curvature.h +++ b/include/igl/principal_curvature.h @@ -55,8 +55,8 @@ template < typename DerivedPV1, typename DerivedPV2> IGL_INLINE void principal_curvature( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, Eigen::PlainObjectBase& PD1, Eigen::PlainObjectBase& PD2, Eigen::PlainObjectBase& PV1, @@ -73,8 +73,8 @@ template < typename DerivedPV2, typename Index> IGL_INLINE void principal_curvature( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, Eigen::PlainObjectBase& PD1, Eigen::PlainObjectBase& PD2, Eigen::PlainObjectBase& PV1, diff --git a/include/igl/procrustes.cpp b/include/igl/procrustes.cpp index 659eea340..b82d1552b 100644 --- a/include/igl/procrustes.cpp +++ b/include/igl/procrustes.cpp @@ -16,8 +16,8 @@ template < typename DerivedR, typename DerivedT> IGL_INLINE void igl::procrustes( - const Eigen::PlainObjectBase& X, - const Eigen::PlainObjectBase& Y, + const Eigen::MatrixBase& X, + const Eigen::MatrixBase& Y, bool includeScaling, bool includeReflections, Scalar& scale, @@ -29,10 +29,12 @@ IGL_INLINE void igl::procrustes( assert(X.cols() == Y.cols() && "Points have same dimensions"); // Center data - const VectorXd Xmean = X.colwise().mean(); - const VectorXd Ymean = Y.colwise().mean(); - MatrixXd XC = X.rowwise() - Xmean.transpose(); - MatrixXd YC = Y.rowwise() - Ymean.transpose(); + const Matrix Xmean = X.colwise().mean(); + const Matrix Ymean = Y.colwise().mean(); + Matrix XC + = X.rowwise() - Xmean.transpose(); + Matrix YC + = Y.rowwise() - Ymean.transpose(); // Scale scale = 1.; @@ -46,8 +48,8 @@ IGL_INLINE void igl::procrustes( } // Rotation - MatrixXd S = XC.transpose() * YC; - MatrixXd T; + Matrix S = XC.transpose() * YC; + Matrix T; if (includeReflections) { polar_dec(S,R,T); @@ -69,8 +71,8 @@ template < int DIM, int TType> IGL_INLINE void igl::procrustes( - const Eigen::PlainObjectBase& X, - const Eigen::PlainObjectBase& Y, + const Eigen::MatrixBase& X, + const Eigen::MatrixBase& Y, bool includeScaling, bool includeReflections, Eigen::Transform& T) @@ -91,8 +93,8 @@ template < typename DerivedR, typename DerivedT> IGL_INLINE void igl::procrustes( - const Eigen::PlainObjectBase& X, - const Eigen::PlainObjectBase& Y, + const Eigen::MatrixBase& X, + const Eigen::MatrixBase& Y, bool includeScaling, bool includeReflections, Eigen::PlainObjectBase& S, @@ -109,8 +111,8 @@ template < typename DerivedR, typename DerivedT> IGL_INLINE void igl::procrustes( - const Eigen::PlainObjectBase& X, - const Eigen::PlainObjectBase& Y, + const Eigen::MatrixBase& X, + const Eigen::MatrixBase& Y, Eigen::PlainObjectBase& R, Eigen::PlainObjectBase& t) { @@ -123,8 +125,8 @@ template < typename Scalar, typename DerivedT> IGL_INLINE void igl::procrustes( - const Eigen::PlainObjectBase& X, - const Eigen::PlainObjectBase& Y, + const Eigen::MatrixBase& X, + const Eigen::MatrixBase& Y, Eigen::Rotation2D& R, Eigen::PlainObjectBase& t) { @@ -136,5 +138,5 @@ IGL_INLINE void igl::procrustes( } #ifdef IGL_STATIC_LIBRARY -template void igl::procrustes, Eigen::Matrix, double, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, bool, bool, double&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::procrustes, Eigen::Matrix, double, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, bool, bool, double&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/procrustes.h b/include/igl/procrustes.h index 5ce00db49..8cacf2171 100644 --- a/include/igl/procrustes.h +++ b/include/igl/procrustes.h @@ -49,8 +49,8 @@ namespace igl typename DerivedR, typename DerivedT> IGL_INLINE void procrustes( - const Eigen::PlainObjectBase& X, - const Eigen::PlainObjectBase& Y, + const Eigen::MatrixBase& X, + const Eigen::MatrixBase& Y, bool includeScaling, bool includeReflections, Scalar& scale, @@ -84,8 +84,8 @@ namespace igl int DIM, int TType> IGL_INLINE void procrustes( - const Eigen::PlainObjectBase& X, - const Eigen::PlainObjectBase& Y, + const Eigen::MatrixBase& X, + const Eigen::MatrixBase& Y, bool includeScaling, bool includeReflections, Eigen::Transform& T); @@ -98,8 +98,8 @@ namespace igl typename DerivedR, typename DerivedT> IGL_INLINE void procrustes( - const Eigen::PlainObjectBase& X, - const Eigen::PlainObjectBase& Y, + const Eigen::MatrixBase& X, + const Eigen::MatrixBase& Y, bool includeScaling, bool includeReflections, Eigen::PlainObjectBase& S, @@ -112,8 +112,8 @@ namespace igl typename DerivedR, typename DerivedT> IGL_INLINE void procrustes( - const Eigen::PlainObjectBase& X, - const Eigen::PlainObjectBase& Y, + const Eigen::MatrixBase& X, + const Eigen::MatrixBase& Y, Eigen::PlainObjectBase& R, Eigen::PlainObjectBase& t); @@ -124,8 +124,8 @@ namespace igl typename Scalar, typename DerivedT> IGL_INLINE void procrustes( - const Eigen::PlainObjectBase& X, - const Eigen::PlainObjectBase& Y, + const Eigen::MatrixBase& X, + const Eigen::MatrixBase& Y, Eigen::Rotation2D& R, Eigen::PlainObjectBase& t); } diff --git a/include/igl/project.cpp b/include/igl/project.cpp index b1c980b2c..b70a2f722 100644 --- a/include/igl/project.cpp +++ b/include/igl/project.cpp @@ -56,4 +56,6 @@ template Eigen::Matrix igl::project(Eigen::Matrix template Eigen::Matrix igl::project(Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&); template void igl::project, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix>(const Eigen::MatrixBase>&, const Eigen::MatrixBase>&, const Eigen::MatrixBase>&, const Eigen::MatrixBase>&, Eigen::PlainObjectBase>&); template void igl::project, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix>(const Eigen::MatrixBase>&, const Eigen::MatrixBase>&, const Eigen::MatrixBase>&, const Eigen::MatrixBase>&, Eigen::PlainObjectBase>&); +template void igl::project, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::project, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/project.h b/include/igl/project.h index dbb0675e4..4586054d5 100644 --- a/include/igl/project.h +++ b/include/igl/project.h @@ -32,6 +32,10 @@ namespace igl // viewport viewport vector // Outputs: // P #V by 3 list of screen space points + // + // Known issue: + // The compiler will not complain if V and P are Vector3d, but the result + // will be incorrect. template IGL_INLINE void project( const Eigen::MatrixBase& V, diff --git a/include/igl/projection_constraint.cpp b/include/igl/projection_constraint.cpp new file mode 100644 index 000000000..fb05398f9 --- /dev/null +++ b/include/igl/projection_constraint.cpp @@ -0,0 +1,50 @@ +#include "projection_constraint.h" + +template < + typename DerivedUV, + typename DerivedM, + typename DerivedVP, + typename DerivedA, + typename DerivedB> +void igl::projection_constraint( + const Eigen::MatrixBase & UV, + const Eigen::MatrixBase & _M, + const Eigen::MatrixBase & VP, + Eigen::PlainObjectBase & A, + Eigen::PlainObjectBase & B) +{ + typedef typename DerivedA::Scalar Scalar; + const Scalar u = UV(0); + const Scalar v = UV(1); + const Scalar cu = VP(0); + const Scalar cv = VP(1); + const Scalar w = VP(2); + const Scalar h = VP(3); + // u = cu + w*(0.5 + 0.5*((M.row(0)*X) / (M.row(3)*X) )) + // u-cu = w*(0.5 + 0.5*((M.row(0)*X) / (M.row(3)*X) )) + // (u-cu)/w = 0.5 + 0.5*((M.row(0)*X) / (M.row(3)*X) ) + // (u-cu)/w - 0.5 = 0.5*((M.row(0)*X) / (M.row(3)*X) ) + // 2.*(u-cu)/w - 1 = ((M.row(0)*X) / (M.row(3)*X) ) + // (2.*(u - cu)/w - 1) * M.row(3)*X = M.row(0)*X + // (2.*(u - cu)/w - 1) * M.row(3)*X - M.row(0)*X = 0 + // (2.*(u - cu)/w - 1) * (M.block(3,0,1,3)*x + M(3,3)) - M.block(0,0,1,3)*x - M(0,3) = 0 + // (2.*(u - cu)/w - 1) * (M.block(3,0,1,3)*x + M(3,3)) - M.block(0,0,1,3)*x = M(0,3) + // ((2.*(u - cu)/w - 1) * M.block(3,0,1,3) - M.block(0,0,1,3))*x = M(0,3) - (2.*(u - cu)/w - 1)*M(3,3) + Eigen::Matrix M = _M.template cast(); + A.resize(2,3); + A<< + ((2.*(u - cu)/w - 1.) * M.block(3,0,1,3) - M.block(0,0,1,3)), + ((2.*(v - cv)/h - 1.) * M.block(3,0,1,3) - M.block(1,0,1,3)); + B.resize(2,1); + B<< + M(0,3) - (2.*(u - cu)/w - 1.)*M(3,3), + M(1,3) - (2.*(v - cv)/h - 1.)*M(3,3); +} + +#ifdef IGL_STATIC_LIBRARY +// Explicit template instantiation +// generated by autoexplicit.sh +template void igl::projection_constraint, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh +template void igl::projection_constraint, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +#endif diff --git a/include/igl/projection_constraint.h b/include/igl/projection_constraint.h new file mode 100644 index 000000000..4db366d1b --- /dev/null +++ b/include/igl/projection_constraint.h @@ -0,0 +1,43 @@ +#ifndef IGL_PROJECTION_CONSTRAINT_H +#define IGL_PROJECTION_CONSTRAINT_H + +#include + +namespace igl +{ + // Construct two constraint equations of the form: + // + // A z = B + // + // with A 2x3 and B 2x1, where z is the 3d position of point in the scene, + // given the current projection matrix (e.g. gl_proj * gl_modelview), viewport + // (corner u/v and width/height) and screen space point x,y. Satisfying this + // equation means that z projects to screen space point (x,y). + // + // Inputs: + // UV 2-long uv-coordinates of screen space point + // M 4 by 4 projection matrix + // VP 4-long viewport: (corner_u, corner_v, width, height) + // Outputs: + // A 2 by 3 system matrix + // B 2 by 1 right-hand side + template < + typename DerivedUV, + typename DerivedM, + typename DerivedVP, + typename DerivedA, + typename DerivedB> + void projection_constraint( + const Eigen::MatrixBase & UV, + const Eigen::MatrixBase & M, + const Eigen::MatrixBase & VP, + Eigen::PlainObjectBase & A, + Eigen::PlainObjectBase & B); +} + +#ifndef IGL_STATIC_LIBRARY +# include "projection_constraint.cpp" +#endif + +#endif + diff --git a/include/igl/quad_grid.cpp b/include/igl/quad_grid.cpp new file mode 100644 index 000000000..4aa403461 --- /dev/null +++ b/include/igl/quad_grid.cpp @@ -0,0 +1,97 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2019 Alec Jacobson +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// obtain one at http://mozilla.org/MPL/2.0/. +#include "quad_grid.h" +#include "grid.h" + +template< + typename DerivedV, + typename DerivedQ, + typename DerivedE> +IGL_INLINE void igl::quad_grid( + const int nx, + const int ny, + Eigen::PlainObjectBase & V, + Eigen::PlainObjectBase & Q, + Eigen::PlainObjectBase & E) +{ + grid(Eigen::Vector2i(nx,ny),V); + return igl::quad_grid(nx,ny,Q,E); +} + +template< + typename DerivedQ, + typename DerivedE> +IGL_INLINE void igl::quad_grid( + const int nx, + const int ny, + Eigen::PlainObjectBase & Q, + Eigen::PlainObjectBase & E) +{ + Eigen::MatrixXi I(nx,ny); + Q.resize( (nx-1)*(ny-1),4); + E.resize((nx-1)*ny + (ny-1)*nx,2); + { + int v = 0; + int q = 0; + int e = 0; + // Ordered to match igl::grid + for(int y = 0;y0) + { + E(e,0) = I(x,y); + E(e,1) = I(x,y-1); + e++; + } + // Add a horizontal edge + if(x>0) + { + E(e,0) = I(x,y); + E(e,1) = I(x-1,y); + e++; + } + // Add two triangles + if(x>0 && y>0) + { + // -1,0----0,0 + // | / | + // | / | + // | / | + // | / | + // -1,-1---0,-1 + Q(q,0) = I(x-0,y-0); + Q(q,1) = I(x-1,y-0); + Q(q,2) = I(x-1,y-1); + Q(q,3) = I(x-0,y-1); + q++; + //F(f,2) = I(x-0,y-0); + //F(f,1) = I(x-1,y-0); + //F(f,0) = I(x-1,y-1); + //f++; + //F(f,2) = I(x-0,y-0); + //F(f,1) = I(x-1,y-1); + //F(f,0) = I(x-0,y-1); + //f++; + } + } + } + } +} + +#ifdef IGL_STATIC_LIBRARY +// Explicit template instantiation +template void igl::quad_grid, Eigen::Matrix, Eigen::Matrix >(int, int, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +#endif diff --git a/include/igl/quad_grid.h b/include/igl/quad_grid.h new file mode 100644 index 000000000..db9592e4d --- /dev/null +++ b/include/igl/quad_grid.h @@ -0,0 +1,50 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2019 Alec Jacobson +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// obtain one at http://mozilla.org/MPL/2.0/. +#ifndef IGL_QUAD_GRID_H +#define IGL_QUAD_GRID_H + +#include +#include + +namespace igl +{ + // Generate a quad mesh over a regular grid. + // + // Inputs: + // nx number of vertices in the x direction + // ny number of vertices in the y direction + // Outputs: + // V nx*ny by 2 list of vertex positions + // Q (nx-1)*(ny-1) by 4 list of quad indices into V + // E (nx-1)*ny+(ny-1)*nx by 2 list of undirected quad edge indices into V + // + // See also: grid, triangulated_grid + template< + typename DerivedV, + typename DerivedQ, + typename DerivedE> + IGL_INLINE void quad_grid( + const int nx, + const int ny, + Eigen::PlainObjectBase & V, + Eigen::PlainObjectBase & Q, + Eigen::PlainObjectBase & E); + template< + typename DerivedQ, + typename DerivedE> + IGL_INLINE void quad_grid( + const int nx, + const int ny, + Eigen::PlainObjectBase & Q, + Eigen::PlainObjectBase & E); +} + +#ifndef IGL_STATIC_LIBRARY +# include "quad_grid.cpp" +#endif +#endif diff --git a/include/igl/quad_planarity.cpp b/include/igl/quad_planarity.cpp index 2e0e4773e..17b67dd12 100644 --- a/include/igl/quad_planarity.cpp +++ b/include/igl/quad_planarity.cpp @@ -10,8 +10,8 @@ template IGL_INLINE void igl::quad_planarity( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, Eigen::PlainObjectBase & P) { int nf = F.rows(); @@ -27,13 +27,13 @@ IGL_INLINE void igl::quad_planarity( diagCross.norm()*(((v3-v1).norm()+(v4-v2).norm())/2); if (fabs(denom)<1e-8) //degenerate quad is still planar - P[i] = 0; + P(i) = 0; else - P[i] = (diagCross.dot(v2-v1)/denom); + P(i) = (diagCross.dot(v2-v1)/denom); } } #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::quad_planarity, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); +template void igl::quad_planarity, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/quad_planarity.h b/include/igl/quad_planarity.h index 0d78b4e35..b6a535c7b 100644 --- a/include/igl/quad_planarity.h +++ b/include/igl/quad_planarity.h @@ -20,8 +20,8 @@ namespace igl // template IGL_INLINE void quad_planarity( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, Eigen::PlainObjectBase & P); } diff --git a/include/igl/ramer_douglas_peucker.cpp b/include/igl/ramer_douglas_peucker.cpp index 0dd1a40a3..4f09a1bea 100644 --- a/include/igl/ramer_douglas_peucker.cpp +++ b/include/igl/ramer_douglas_peucker.cpp @@ -110,7 +110,7 @@ IGL_INLINE void igl::ramer_douglas_peucker( // Find index in original list of "start" vertices slice(J,B,s); // Find index in original list of "destination" vertices - slice(J,(B.array()+1).eval(),d); + slice(J,(B.array()+1).matrix().eval(),d); // Parameter between start and destination is linear in arc-length VectorXS Ts,Td; slice(T,s,Ts); diff --git a/include/igl/random_points_on_mesh.cpp b/include/igl/random_points_on_mesh.cpp index b28135ad1..ae0c0e953 100644 --- a/include/igl/random_points_on_mesh.cpp +++ b/include/igl/random_points_on_mesh.cpp @@ -15,8 +15,8 @@ template IGL_INLINE void igl::random_points_on_mesh( const int n, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & B, Eigen::PlainObjectBase & FI) { @@ -26,7 +26,6 @@ IGL_INLINE void igl::random_points_on_mesh( typedef Matrix VectorXs; VectorXs A; doublearea(V,F,A); - A /= A.array().sum(); // Should be traingle mesh. Although Turk's method 1 generalizes... assert(F.cols() == 3); VectorXs C; @@ -35,6 +34,10 @@ IGL_INLINE void igl::random_points_on_mesh( A0.bottomRightCorner(A.size(),1) = A; // Even faster would be to use the "Alias Table Method" cumsum(A0,1,C); + const Scalar Cmax = C(C.size()-1); + assert(Cmax > 0 && "Total surface area should be positive"); + // Why is this more accurate than `C /= C(C.size()-1)` ? + for(int i = 0;i= 0); assert(R.maxCoeff() <= 1); @@ -47,11 +50,36 @@ IGL_INLINE void igl::random_points_on_mesh( B.col(2) = S.array() * T.array().sqrt(); } +template < + typename DerivedV, + typename DerivedF, + typename DerivedB, + typename DerivedFI, + typename DerivedX> +IGL_INLINE void igl::random_points_on_mesh( + const int n, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + Eigen::PlainObjectBase & B, + Eigen::PlainObjectBase & FI, + Eigen::PlainObjectBase & X) +{ + random_points_on_mesh(n,V,F,B,FI); + X = DerivedX::Zero(B.rows(),V.cols()); + for(int x = 0;x IGL_INLINE void igl::random_points_on_mesh( const int n, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, Eigen::SparseMatrix & B, Eigen::PlainObjectBase & FI) { @@ -78,6 +106,10 @@ IGL_INLINE void igl::random_points_on_mesh( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::random_points_on_mesh, Eigen::Matrix, double, Eigen::Matrix >(int, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::SparseMatrix&, Eigen::PlainObjectBase >&); -template void igl::random_points_on_mesh, Eigen::Matrix, double, Eigen::Matrix >(int, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::SparseMatrix&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh +template void igl::random_points_on_mesh, Eigen::Matrix, float, Eigen::Matrix >(int, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::SparseMatrix&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh +template void igl::random_points_on_mesh, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(int, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::random_points_on_mesh, Eigen::Matrix, double, Eigen::Matrix >(int, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::SparseMatrix&, Eigen::PlainObjectBase >&); +template void igl::random_points_on_mesh, Eigen::Matrix, double, Eigen::Matrix >(int, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::SparseMatrix&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/random_points_on_mesh.h b/include/igl/random_points_on_mesh.h index 7cde24f3c..b3e96d4c9 100644 --- a/include/igl/random_points_on_mesh.h +++ b/include/igl/random_points_on_mesh.h @@ -28,17 +28,32 @@ namespace igl template IGL_INLINE void random_points_on_mesh( const int n, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & B, Eigen::PlainObjectBase & FI); // Outputs: + // X n by dim list of sample positions. + template < + typename DerivedV, + typename DerivedF, + typename DerivedB, + typename DerivedFI, + typename DerivedX> + IGL_INLINE void random_points_on_mesh( + const int n, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + Eigen::PlainObjectBase & B, + Eigen::PlainObjectBase & FI, + Eigen::PlainObjectBase & X); + // Outputs: // B n by #V sparse matrix so that B*V produces a list of sample points template IGL_INLINE void random_points_on_mesh( const int n, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, Eigen::SparseMatrix & B, Eigen::PlainObjectBase & FI); } @@ -48,5 +63,3 @@ namespace igl #endif #endif - - diff --git a/include/igl/ray_box_intersect.cpp b/include/igl/ray_box_intersect.cpp index 4a88b89ed..95a9daaa7 100644 --- a/include/igl/ray_box_intersect.cpp +++ b/include/igl/ray_box_intersect.cpp @@ -6,7 +6,7 @@ // v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "ray_box_intersect.h" -#include +#include template < typename Derivedsource, @@ -101,11 +101,11 @@ IGL_INLINE bool igl::ray_box_intersect( // This should be precomputed and provided as input typedef Matrix RowVector3S; const RowVector3S inv_dir( 1./dir(0),1./dir(1),1./dir(2)); - const std::vector sign = { inv_dir(0)<0, inv_dir(1)<0, inv_dir(2)<0}; + const std::array sign = { inv_dir(0)<0, inv_dir(1)<0, inv_dir(2)<0}; // http://people.csail.mit.edu/amy/papers/box-jgt.pdf // "An Efficient and Robust Ray–Box Intersection Algorithm" Scalar tymin, tymax, tzmin, tzmax; - std::vector bounds = {box.min(),box.max()}; + std::array bounds = {box.min(),box.max()}; tmin = ( bounds[sign[0]](0) - origin(0)) * inv_dir(0); tmax = ( bounds[1-sign[0]](0) - origin(0)) * inv_dir(0); tymin = (bounds[sign[1]](1) - origin(1)) * inv_dir(1); diff --git a/include/igl/ray_mesh_intersect.cpp b/include/igl/ray_mesh_intersect.cpp index 9a70a22be..444ee8322 100644 --- a/include/igl/ray_mesh_intersect.cpp +++ b/include/igl/ray_mesh_intersect.cpp @@ -30,6 +30,8 @@ IGL_INLINE bool igl::ray_mesh_intersect( Vector3d s_d = s.template cast(); Vector3d dir_d = dir.template cast(); hits.clear(); + hits.reserve(F.rows()); + // loop over all triangles for(int f = 0;f, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::vector >&); template bool igl::ray_mesh_intersect, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, std::vector >&); template bool igl::ray_mesh_intersect, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, igl::Hit&); template bool igl::ray_mesh_intersect, Eigen::Matrix, Eigen::Matrix, Eigen::Block const, 1, -1, false> >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase const, 1, -1, false> > const&, igl::Hit&); diff --git a/include/igl/readMESH.cpp b/include/igl/readMESH.cpp index bc912e11b..a63dac022 100644 --- a/include/igl/readMESH.cpp +++ b/include/igl/readMESH.cpp @@ -488,17 +488,12 @@ IGL_INLINE bool igl::readMESH( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -// generated by autoexplicit.sh +template bool igl::readMESH, Eigen::Matrix, Eigen::Matrix >(FILE*, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template bool igl::readMESH, Eigen::Matrix, Eigen::Matrix >(FILE*, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh template bool igl::readMESH, Eigen::Matrix, Eigen::Matrix >(FILE*, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh template bool igl::readMESH, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh template bool igl::readMESH, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh template bool igl::readMESH, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh template bool igl::readMESH, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template bool igl::readMESH, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template bool igl::readMESH(std::basic_string, std::allocator >, std::vector >, std::allocator > > >&, std::vector >, std::allocator > > >&, std::vector >, std::allocator > > >&); diff --git a/include/igl/readOBJ.cpp b/include/igl/readOBJ.cpp index aac74a08b..e769aeab5 100644 --- a/include/igl/readOBJ.cpp +++ b/include/igl/readOBJ.cpp @@ -35,7 +35,30 @@ IGL_INLINE bool igl::readOBJ( obj_file_name.c_str()); return false; } - return igl::readOBJ(obj_file,V,TC,N,F,FTC,FN); + std::vector> FM; + return igl::readOBJ(obj_file,V,TC,N,F,FTC,FN, FM); +} + +template +IGL_INLINE bool igl::readOBJ( + const std::string obj_file_name, + std::vector > & V, + std::vector > & TC, + std::vector > & N, + std::vector > & F, + std::vector > & FTC, + std::vector > & FN, + std::vector> &FM) +{ + // Open file, and check for error + FILE * obj_file = fopen(obj_file_name.c_str(),"r"); + if(NULL==obj_file) + { + fprintf(stderr,"IOError: %s could not be opened...\n", + obj_file_name.c_str()); + return false; + } + return igl::readOBJ(obj_file,V,TC,N,F,FTC,FN,FM); } template @@ -46,7 +69,8 @@ IGL_INLINE bool igl::readOBJ( std::vector > & N, std::vector > & F, std::vector > & FTC, - std::vector > & FN) + std::vector > & FN, + std::vector> &FM) { // File open was successful so clear outputs V.clear(); @@ -65,10 +89,16 @@ IGL_INLINE bool igl::readOBJ( std::string tic_tac_toe("#"); #ifndef IGL_LINE_MAX # define IGL_LINE_MAX 2048 +#endif + +#ifndef MATERIAL_LINE_MAX +# define MATERIAL_LINE_MAX 2048 #endif char line[IGL_LINE_MAX]; - int line_no = 1; + char currentmaterialref[MATERIAL_LINE_MAX] = ""; + bool FMwasinit = false; + int line_no = 1, previous_face_no=0, current_face_no = 0; while (fgets(line, IGL_LINE_MAX, obj_file) != NULL) { char type[IGL_LINE_MAX]; @@ -193,6 +223,7 @@ IGL_INLINE bool igl::readOBJ( F.push_back(f); FTC.push_back(ftc); FN.push_back(fn); + current_face_no++; }else { fprintf(stderr, @@ -200,10 +231,20 @@ IGL_INLINE bool igl::readOBJ( fclose(obj_file); return false; } - }else if(strlen(type) >= 1 && (type[0] == '#' || + }else if(strlen(type) >= 1 && strcmp("usemtl",type)==0 ) + { + if(FMwasinit){ + FM.push_back(std::make_tuple(currentmaterialref,previous_face_no,current_face_no-1)); + previous_face_no = current_face_no; + } + else{ + FMwasinit=true; + } + sscanf(l, "%s\n", ¤tmaterialref); + } + else if(strlen(type) >= 1 && (type[0] == '#' || type[0] == 'g' || type[0] == 's' || - strcmp("usemtl",type)==0 || strcmp("mtllib",type)==0)) { //ignore comments or other shit @@ -221,6 +262,8 @@ IGL_INLINE bool igl::readOBJ( } line_no++; } + if(strcmp(currentmaterialref,"")!=0) + FM.push_back(std::make_tuple(currentmaterialref,previous_face_no,current_face_no-1)); fclose(obj_file); assert(F.size() == FN.size()); @@ -237,6 +280,8 @@ IGL_INLINE bool igl::readOBJ( { std::vector > TC,N; std::vector > FTC,FN; + std::vector> FM; + return readOBJ(obj_file_name,V,TC,N,F,FTC,FN); } @@ -351,13 +396,16 @@ IGL_INLINE bool igl::readOBJ( return true; } + #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template bool igl::readOBJ, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh template bool igl::readOBJ, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template bool igl::readOBJ, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template bool igl::readOBJ, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template bool igl::readOBJ, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template bool igl::readOBJ(std::basic_string, std::allocator >, std::vector >, std::allocator > > >&, std::vector >, std::allocator > > >&, std::vector >, std::allocator > > >&, std::vector >, std::allocator > > >&, std::vector >, std::allocator > > >&, std::vector >, std::allocator > > >&); -template bool igl::readOBJ(std::basic_string, std::allocator >, std::vector >, std::allocator > > >&, std::vector >, std::allocator > > >&); +template bool igl::readOBJ(std::basic_string, std::allocator >, std::vector >, std::allocator > > >&, std::vector >, std::allocator > > >&, std::vector >, std::allocator > > >&, std::vector >, std::allocator > > >&, std::vector >, std::allocator > > >&, std::vector >, std::allocator > > >&, std::vector, std::allocator >, int, int>, std::allocator, std::allocator >, int, int> > >&); #endif diff --git a/include/igl/readOBJ.h b/include/igl/readOBJ.h index 443b6fc8e..9094adc8f 100644 --- a/include/igl/readOBJ.h +++ b/include/igl/readOBJ.h @@ -8,7 +8,6 @@ #ifndef IGL_READOBJ_H #define IGL_READOBJ_H #include "igl_inline.h" -#include "deprecated.h" // History: // return type changed from void to bool Alec 18 Sept 2011 // added pure vector of vectors version that has much more support Alec 31 Oct @@ -49,6 +48,36 @@ namespace igl std::vector > & F, std::vector > & FTC, std::vector > & FN); + // Read a mesh from an ascii obj file, filling in vertex positions, normals + // and texture coordinates. Mesh may have faces of any number of degree + // + // Templates: + // Scalar type for positions and vectors (will be read as double and cast + // to Scalar) + // Index type for indices (will be read as int and cast to Index) + // Inputs: + // str path to .obj file + // Outputs: + // V double matrix of vertex positions #V by 3 + // TC double matrix of texture coordinats #TC by 2 + // N double matrix of corner normals #N by 3 + // F #F list of face indices into vertex positions + // FTC #F list of face indices into vertex texture coordinates + // FN #F list of face indices into vertex normals + // FM #tuple list containing (vertex index, normal index, texture coordinates index, material) + // Returns true on success, false on errors + template + IGL_INLINE bool readOBJ( + const std::string obj_file_name, + std::vector > & V, + std::vector > & TC, + std::vector > & N, + std::vector > & F, + std::vector > & FTC, + std::vector > & FN, + std::vector> &FM + ); + // Inputs: // obj_file pointer to already opened .obj file // Outputs: @@ -61,7 +90,8 @@ namespace igl std::vector > & N, std::vector > & F, std::vector > & FTC, - std::vector > & FN); + std::vector > & FN, + std::vector> &FM); // Just V and F template IGL_INLINE bool readOBJ( diff --git a/include/igl/readSTL.cpp b/include/igl/readSTL.cpp index fcdeddcdd..ddcd70dd8 100644 --- a/include/igl/readSTL.cpp +++ b/include/igl/readSTL.cpp @@ -85,14 +85,14 @@ IGL_INLINE bool igl::readSTL( // Specifically 80 character header char header[80]; - char solid[80]; + char solid[80] = {0}; bool is_ascii = true; if(fread(header,1,80,stl_file) != 80) { cerr<<"IOError: too short (1)."< > vV,vN,vTC,vC; vector > vF,vFTC,vFN; + vector> FM; + if(ext == "mesh") { // Convert extension to lower case @@ -119,7 +121,7 @@ IGL_INLINE bool igl::read_triangle_mesh( } }else if(ext == "obj") { - if(!readOBJ(fp,vV,vTC,vN,vF,vFTC,vFN)) + if(!readOBJ(fp,vV,vTC,vN,vF,vFTC,vFN,FM)) { return false; } @@ -174,6 +176,8 @@ IGL_INLINE bool igl::read_triangle_mesh( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template bool igl::read_triangle_mesh, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh template bool igl::read_triangle_mesh, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template bool igl::read_triangle_mesh, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); diff --git a/include/igl/remove_duplicate_vertices.cpp b/include/igl/remove_duplicate_vertices.cpp index 815ee51f8..e0473c443 100644 --- a/include/igl/remove_duplicate_vertices.cpp +++ b/include/igl/remove_duplicate_vertices.cpp @@ -29,7 +29,7 @@ IGL_INLINE void igl::remove_duplicate_vertices( DerivedV rV,rSV; round((V/(10.0*epsilon)).eval(),rV); unique_rows(rV,rSV,SVI,SVJ); - slice(V,SVI,colon(0,V.cols()-1),SV); + slice(V,SVI,colon(0,V.cols()-1),SV); }else { unique_rows(V,SV,SVI,SVJ); @@ -68,6 +68,8 @@ IGL_INLINE void igl::remove_duplicate_vertices( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template void igl::remove_duplicate_vertices, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, double, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh template void igl::remove_duplicate_vertices, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, double, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template void igl::remove_duplicate_vertices, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, double, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); diff --git a/include/igl/remove_duplicates.cpp b/include/igl/remove_duplicates.cpp index 3e97a39e1..aeec90c95 100644 --- a/include/igl/remove_duplicates.cpp +++ b/include/igl/remove_duplicates.cpp @@ -18,8 +18,8 @@ // const double epsilon) template IGL_INLINE void igl::remove_duplicates( - const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, + const Eigen::MatrixBase &V, + const Eigen::MatrixBase &F, Eigen::PlainObjectBase &NV, Eigen::PlainObjectBase &NF, Eigen::Matrix &I, @@ -83,6 +83,6 @@ IGL_INLINE void igl::remove_duplicates( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::remove_duplicates, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::Matrix::Scalar, -1, 1, 0, -1, 1>&, double); -template void igl::remove_duplicates, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::Matrix::Scalar, -1, 1, 0, -1, 1>&, double); +template void igl::remove_duplicates, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::Matrix::Scalar, -1, 1, 0, -1, 1>&, double); +template void igl::remove_duplicates, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::Matrix::Scalar, -1, 1, 0, -1, 1>&, double); #endif diff --git a/include/igl/remove_duplicates.h b/include/igl/remove_duplicates.h index 0e1249ce9..35fce60d6 100644 --- a/include/igl/remove_duplicates.h +++ b/include/igl/remove_duplicates.h @@ -8,6 +8,7 @@ #ifndef IGL_REMOVE_DUPLICATES_H #define IGL_REMOVE_DUPLICATES_H #include "igl_inline.h" +#include "deprecated.h" #include namespace igl @@ -32,9 +33,9 @@ namespace igl // const double epsilon = 2.2204e-15); template - IGL_INLINE void remove_duplicates( - const Eigen::PlainObjectBase &V, - const Eigen::PlainObjectBase &F, + IGL_DEPRECATED IGL_INLINE void remove_duplicates( + const Eigen::MatrixBase &V, + const Eigen::MatrixBase &F, Eigen::PlainObjectBase &NV, Eigen::PlainObjectBase &NF, Eigen::Matrix &I, diff --git a/include/igl/remove_unreferenced.cpp b/include/igl/remove_unreferenced.cpp index af2f81dc3..98ed8fcf5 100644 --- a/include/igl/remove_unreferenced.cpp +++ b/include/igl/remove_unreferenced.cpp @@ -100,6 +100,10 @@ IGL_INLINE void igl::remove_unreferenced( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template void igl::remove_unreferenced, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh +template void igl::remove_unreferenced, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh template void igl::remove_unreferenced, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template void igl::remove_unreferenced, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); diff --git a/include/igl/resolve_duplicated_faces.cpp b/include/igl/resolve_duplicated_faces.cpp index 3b26b8ecc..d55e01dd8 100644 --- a/include/igl/resolve_duplicated_faces.cpp +++ b/include/igl/resolve_duplicated_faces.cpp @@ -17,12 +17,12 @@ template< typename DerivedF2, typename DerivedJ > IGL_INLINE void igl::resolve_duplicated_faces( - const Eigen::PlainObjectBase& F1, + const Eigen::MatrixBase& F1, Eigen::PlainObjectBase& F2, Eigen::PlainObjectBase& J) { //typedef typename DerivedF1::Scalar Index; - Eigen::VectorXi IA,IC; + Eigen::Matrix IA,IC; DerivedF1 uF; igl::unique_simplices(F1,uF,IA,IC); @@ -86,11 +86,11 @@ IGL_INLINE void igl::resolve_duplicated_faces( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh -template void igl::resolve_duplicated_faces, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::resolve_duplicated_faces, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::resolve_duplicated_faces, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::resolve_duplicated_faces, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::resolve_duplicated_faces, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::resolve_duplicated_faces, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::resolve_duplicated_faces, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::resolve_duplicated_faces, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #ifdef WIN32 -template void igl::resolve_duplicated_faces, class Eigen::Matrix, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>>(class Eigen::PlainObjectBase> const &, class Eigen::PlainObjectBase> &, class Eigen::PlainObjectBase> &); +template void igl::resolve_duplicated_faces, class Eigen::Matrix, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>>(class Eigen::MatrixBase> const &, class Eigen::PlainObjectBase> &, class Eigen::PlainObjectBase> &); #endif #endif diff --git a/include/igl/resolve_duplicated_faces.h b/include/igl/resolve_duplicated_faces.h index 03ea3d6e6..e3861fa8c 100644 --- a/include/igl/resolve_duplicated_faces.h +++ b/include/igl/resolve_duplicated_faces.h @@ -39,7 +39,7 @@ namespace igl { typename DerivedF2, typename DerivedJ > IGL_INLINE void resolve_duplicated_faces( - const Eigen::PlainObjectBase& F1, + const Eigen::MatrixBase& F1, Eigen::PlainObjectBase& F2, Eigen::PlainObjectBase& J); diff --git a/include/igl/rigid_alignment.cpp b/include/igl/rigid_alignment.cpp new file mode 100644 index 000000000..cc9f224c1 --- /dev/null +++ b/include/igl/rigid_alignment.cpp @@ -0,0 +1,98 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2019 Alec Jacobson +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// obtain one at http://mozilla.org/MPL/2.0/. +#include "rigid_alignment.h" +#include "polar_svd.h" +#include "matlab_format.h" +#include +#include +#include +#include + +template < + typename DerivedX, + typename DerivedP, + typename DerivedN, + typename DerivedR, + typename Derivedt +> +IGL_INLINE void igl::rigid_alignment( + const Eigen::MatrixBase & _X, + const Eigen::MatrixBase & P, + const Eigen::MatrixBase & N, + Eigen::PlainObjectBase & R, + Eigen::PlainObjectBase & t) +{ + typedef typename DerivedX::Scalar Scalar; + typedef Eigen::Matrix MatrixXS; + typedef Eigen::Matrix VectorXS; + typedef Eigen::Matrix Matrix3S; + const int k = _X.rows(); + VectorXS Z = VectorXS::Zero(k,1); + VectorXS I = VectorXS::Ones(k,1); + + DerivedX X = _X; + R = DerivedR::Identity(3,3); + t = Derivedt::Zero(1,3); + // See gptoolbox, each iter could be O(1) instead of O(k) + const int max_iters = 5; + for(int iters = 0;iters > NNIJV; + for(int i = 0;i NN(k,k*3); + NN.setFromTriplets(NNIJV.begin(),NNIJV.end()); + A = (NN * A).eval(); + B = (NN * B).eval(); + VectorXS u = (A.transpose() * A).ldlt().solve(A.transpose() * B); + Derivedt ti = u.tail(3).transpose(); + + Matrix3S W; + W<< + 0, u(2),-u(1), + -u(2), 0, u(0), + u(1),-u(0), 0; + // strayed from a perfect rotation. Correct it. + const double x = u.head(3).stableNorm(); + DerivedR Ri; + if(x == 0) + { + Ri = DerivedR::Identity(3,3); + }else + { + Ri = + DerivedR::Identity(3,3) + + sin(x)/x*W + + (1.0-cos(x))/(x*x)*W*W; + } + + R = (R*Ri).eval(); + t = (t*Ri + ti).eval(); + X = ((_X*R).rowwise()+t).eval(); + } +} + +#ifdef IGL_STATIC_LIBRARY +// Explicit template instantiation +template void igl::rigid_alignment, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +#endif diff --git a/include/igl/rigid_alignment.h b/include/igl/rigid_alignment.h new file mode 100644 index 000000000..6727b7433 --- /dev/null +++ b/include/igl/rigid_alignment.h @@ -0,0 +1,50 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2019 Alec Jacobson +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// obtain one at http://mozilla.org/MPL/2.0/. +#ifndef RIGID_ALIGNMENT_H +#define RIGID_ALIGNMENT_H +#include "igl_inline.h" +#include + +namespace igl +{ + // Find the rigid transformation that best aligns the 3D points X to their + // corresponding points P with associated normals N. + // + // min ‖(X*R+t-P)'N‖² + // R∈SO(3) + // t∈R³ + // + // Inputs: + // X #X by 3 list of query points + // P #X by 3 list of corresponding (e.g., closest) points + // N #X by 3 list of unit normals for each row in P + // Outputs: + // R 3 by 3 rotation matrix + // t 1 by 3 translation vector + // + // See also: icp + template < + typename DerivedX, + typename DerivedP, + typename DerivedN, + typename DerivedR, + typename Derivedt + > + IGL_INLINE void rigid_alignment( + const Eigen::MatrixBase & X, + const Eigen::MatrixBase & P, + const Eigen::MatrixBase & N, + Eigen::PlainObjectBase & R, + Eigen::PlainObjectBase & t); +} + +#ifndef IGL_STATIC_LIBRARY +# include "rigid_alignment.cpp" +#endif + +#endif diff --git a/include/igl/segment_segment_intersect.cpp b/include/igl/segment_segment_intersect.cpp index 3481e8a36..ebc2c6b9d 100644 --- a/include/igl/segment_segment_intersect.cpp +++ b/include/igl/segment_segment_intersect.cpp @@ -11,10 +11,10 @@ template IGL_INLINE bool igl::segment_segment_intersect( - const Eigen::PlainObjectBase &p, - const Eigen::PlainObjectBase &r, - const Eigen::PlainObjectBase &q, - const Eigen::PlainObjectBase &s, + const Eigen::MatrixBase &p, + const Eigen::MatrixBase &r, + const Eigen::MatrixBase &q, + const Eigen::MatrixBase &s, double &a_t, double &a_u, double eps @@ -30,7 +30,7 @@ IGL_INLINE bool igl::segment_segment_intersect( // t = (q - p) x s / (r x s) // (r x s) ~ 0 --> directions are parallel, they will never cross - Eigen::RowVector3d rxs = r.cross(s); + Eigen::Matrix rxs = r.cross(s); if (rxs.norm() <= eps) return false; @@ -38,14 +38,14 @@ IGL_INLINE bool igl::segment_segment_intersect( double u; // u = (q − p) × r / (r × s) - Eigen::RowVector3d u1 = (q - p).cross(r); + Eigen::Matrix u1 = (q - p).cross(r); sign = ((u1.dot(rxs)) > 0) ? 1 : -1; u = u1.norm() / rxs.norm(); u = u * sign; double t; // t = (q - p) x s / (r x s) - Eigen::RowVector3d t1 = (q - p).cross(s); + Eigen::Matrix t1 = (q - p).cross(s); sign = ((t1.dot(rxs)) > 0) ? 1 : -1; t = t1.norm() / rxs.norm(); t = t * sign; @@ -63,5 +63,5 @@ IGL_INLINE bool igl::segment_segment_intersect( }; #ifdef IGL_STATIC_LIBRARY -template bool igl::segment_segment_intersect, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, double&, double&, double); +template bool igl::segment_segment_intersect, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, double&, double&, double); #endif diff --git a/include/igl/segment_segment_intersect.h b/include/igl/segment_segment_intersect.h index 7d383d164..77e89c320 100644 --- a/include/igl/segment_segment_intersect.h +++ b/include/igl/segment_segment_intersect.h @@ -30,10 +30,10 @@ namespace igl // Returns true if intersection template IGL_INLINE bool segment_segment_intersect( - const Eigen::PlainObjectBase &p, - const Eigen::PlainObjectBase &r, - const Eigen::PlainObjectBase &q, - const Eigen::PlainObjectBase &s, + const Eigen::MatrixBase &p, + const Eigen::MatrixBase &r, + const Eigen::MatrixBase &q, + const Eigen::MatrixBase &s, double &t, double &u, double eps = 1e-6 diff --git a/include/igl/setdiff.cpp b/include/igl/setdiff.cpp index 82c3c2e79..0d5980c62 100644 --- a/include/igl/setdiff.cpp +++ b/include/igl/setdiff.cpp @@ -17,8 +17,8 @@ template < typename DerivedC, typename DerivedIA> IGL_INLINE void igl::setdiff( - const Eigen::DenseBase & A, - const Eigen::DenseBase & B, + const Eigen::MatrixBase & A, + const Eigen::MatrixBase & B, Eigen::PlainObjectBase & C, Eigen::PlainObjectBase & IA) { @@ -76,9 +76,9 @@ IGL_INLINE void igl::setdiff( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh -template void igl::setdiff, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::setdiff, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::setdiff, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::setdiff, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::setdiff, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::setdiff, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::setdiff, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::setdiff, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::setdiff, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::setdiff, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/setdiff.h b/include/igl/setdiff.h index 20e8d6485..a8f9e0775 100644 --- a/include/igl/setdiff.h +++ b/include/igl/setdiff.h @@ -26,8 +26,8 @@ namespace igl typename DerivedC, typename DerivedIA> IGL_INLINE void setdiff( - const Eigen::DenseBase & A, - const Eigen::DenseBase & B, + const Eigen::MatrixBase & A, + const Eigen::MatrixBase & B, Eigen::PlainObjectBase & C, Eigen::PlainObjectBase & IA); } diff --git a/include/igl/setxor.cpp b/include/igl/setxor.cpp index abbbb7571..dde66f207 100644 --- a/include/igl/setxor.cpp +++ b/include/igl/setxor.cpp @@ -10,8 +10,8 @@ template < typename DerivedIA, typename DerivedIB> IGL_INLINE void igl::setxor( - const Eigen::DenseBase & A, - const Eigen::DenseBase & B, + const Eigen::MatrixBase & A, + const Eigen::MatrixBase & B, Eigen::PlainObjectBase & C, Eigen::PlainObjectBase & IA, Eigen::PlainObjectBase & IB) @@ -28,6 +28,6 @@ IGL_INLINE void igl::setxor( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh -template void igl::setxor, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::setxor, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::setxor, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::setxor, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/setxor.h b/include/igl/setxor.h index bbd1089fa..0abc13156 100644 --- a/include/igl/setxor.h +++ b/include/igl/setxor.h @@ -29,8 +29,8 @@ namespace igl typename DerivedIA, typename DerivedIB> IGL_INLINE void setxor( - const Eigen::DenseBase & A, - const Eigen::DenseBase & B, + const Eigen::MatrixBase & A, + const Eigen::MatrixBase & B, Eigen::PlainObjectBase & C, Eigen::PlainObjectBase & IA, Eigen::PlainObjectBase & IB); diff --git a/include/igl/shape_diameter_function.cpp b/include/igl/shape_diameter_function.cpp index db061fe39..4c611fb94 100644 --- a/include/igl/shape_diameter_function.cpp +++ b/include/igl/shape_diameter_function.cpp @@ -28,8 +28,8 @@ IGL_INLINE void igl::shape_diameter_function( const Eigen::Vector3f&, const Eigen::Vector3f&) > & shoot_ray, - const Eigen::PlainObjectBase & P, - const Eigen::PlainObjectBase & N, + const Eigen::MatrixBase & P, + const Eigen::MatrixBase & N, const int num_samples, Eigen::PlainObjectBase & S) { @@ -76,10 +76,10 @@ template < typename DerivedS > IGL_INLINE void igl::shape_diameter_function( const igl::AABB & aabb, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, - const Eigen::PlainObjectBase & P, - const Eigen::PlainObjectBase & N, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const Eigen::MatrixBase & P, + const Eigen::MatrixBase & N, const int num_samples, Eigen::PlainObjectBase & S) { @@ -113,10 +113,10 @@ template < typename DerivedN, typename DerivedS > IGL_INLINE void igl::shape_diameter_function( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, - const Eigen::PlainObjectBase & P, - const Eigen::PlainObjectBase & N, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const Eigen::MatrixBase & P, + const Eigen::MatrixBase & N, const int num_samples, Eigen::PlainObjectBase & S) { @@ -149,8 +149,8 @@ template < typename DerivedF, typename DerivedS> IGL_INLINE void igl::shape_diameter_function( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, const bool per_face, const int num_samples, Eigen::PlainObjectBase & S) @@ -173,10 +173,10 @@ IGL_INLINE void igl::shape_diameter_function( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::shape_diameter_function, Eigen::Matrix, Eigen::Matrix >(std::function const&, Eigen::Matrix const&)> const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, int, Eigen::PlainObjectBase >&); -template void igl::shape_diameter_function, Eigen::Matrix, Eigen::Matrix >(std::function const&, Eigen::Matrix const&)> const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, int, Eigen::PlainObjectBase >&); -template void igl::shape_diameter_function, Eigen::Matrix, Eigen::Matrix >(std::function const&, Eigen::Matrix const&)> const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, int, Eigen::PlainObjectBase >&); -template void igl::shape_diameter_function, Eigen::Matrix, Eigen::Matrix >(std::function const&, Eigen::Matrix const&)> const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, int, Eigen::PlainObjectBase >&); -template void igl::shape_diameter_function, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, bool, int, Eigen::PlainObjectBase >&); +template void igl::shape_diameter_function, Eigen::Matrix, Eigen::Matrix >(std::function const&, Eigen::Matrix const&)> const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::shape_diameter_function, Eigen::Matrix, Eigen::Matrix >(std::function const&, Eigen::Matrix const&)> const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::shape_diameter_function, Eigen::Matrix, Eigen::Matrix >(std::function const&, Eigen::Matrix const&)> const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::shape_diameter_function, Eigen::Matrix, Eigen::Matrix >(std::function const&, Eigen::Matrix const&)> const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::shape_diameter_function, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, bool, int, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/shape_diameter_function.h b/include/igl/shape_diameter_function.h index 5460cda7b..01e5c5b7a 100644 --- a/include/igl/shape_diameter_function.h +++ b/include/igl/shape_diameter_function.h @@ -37,8 +37,8 @@ namespace igl const Eigen::Vector3f&, const Eigen::Vector3f&) > & shoot_ray, - const Eigen::PlainObjectBase & P, - const Eigen::PlainObjectBase & N, + const Eigen::MatrixBase & P, + const Eigen::MatrixBase & N, const int num_samples, Eigen::PlainObjectBase & S); // Inputs: @@ -52,10 +52,10 @@ namespace igl typename DerivedS > IGL_INLINE void shape_diameter_function( const igl::AABB & aabb, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, - const Eigen::PlainObjectBase & P, - const Eigen::PlainObjectBase & N, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const Eigen::MatrixBase & P, + const Eigen::MatrixBase & N, const int num_samples, Eigen::PlainObjectBase & S); // Inputs: @@ -68,10 +68,10 @@ namespace igl typename DerivedN, typename DerivedS > IGL_INLINE void shape_diameter_function( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, - const Eigen::PlainObjectBase & P, - const Eigen::PlainObjectBase & N, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const Eigen::MatrixBase & P, + const Eigen::MatrixBase & N, const int num_samples, Eigen::PlainObjectBase & S); // per_face whether to compute per face (S is #F by 1) or per vertex (S is @@ -81,8 +81,8 @@ namespace igl typename DerivedF, typename DerivedS> IGL_INLINE void shape_diameter_function( - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, const bool per_face, const int num_samples, Eigen::PlainObjectBase & S); diff --git a/include/igl/sharp_edges.cpp b/include/igl/sharp_edges.cpp new file mode 100644 index 000000000..33e90699c --- /dev/null +++ b/include/igl/sharp_edges.cpp @@ -0,0 +1,108 @@ +#include "sharp_edges.h" +#include +#include +#include +#include + +template < + typename DerivedV, + typename DerivedF, + typename DerivedSE, + typename DerivedE, + typename DeriveduE, + typename DerivedEMAP, + typename uE2Etype, + typename sharptype> +IGL_INLINE void igl::sharp_edges( + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const typename DerivedV::Scalar angle, + Eigen::PlainObjectBase & SE, + Eigen::PlainObjectBase & E, + Eigen::PlainObjectBase & uE, + Eigen::PlainObjectBase & EMAP, + std::vector > & uE2E, + std::vector< sharptype > & sharp) +{ + typedef typename DerivedSE::Scalar Index; + typedef typename DerivedV::Scalar Scalar; + typedef Eigen::Matrix MatrixX2I; + typedef Eigen::Matrix MatrixX3S; + typedef Eigen::Matrix RowVector3S; + typedef Eigen::Matrix VectorXI; + + unique_edge_map(F,E,uE,EMAP,uE2E); + MatrixX3S N; + per_face_normals(V,F,N); + // number of faces + const Index m = F.rows(); + // Dihedral angles + //std::vector > DIJV; + sharp.clear(); + // Loop over each unique edge + for(int u = 0;u angle) + { + u_is_sharp = true; + } + } + if(u_is_sharp) + { + sharp.push_back(u); + } + } + SE.resize(sharp.size(),2); + for(int i = 0;i +IGL_INLINE void igl::sharp_edges( + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const typename DerivedV::Scalar angle, + Eigen::PlainObjectBase & SE + ) +{ + typedef typename DerivedSE::Scalar Index; + typedef typename DerivedV::Scalar Scalar; + typedef Eigen::Matrix MatrixX2I; + typedef Eigen::Matrix MatrixX3S; + typedef Eigen::Matrix RowVector3S; + typedef Eigen::Matrix VectorXI; + MatrixX2I E,uE; + VectorXI EMAP; + std::vector > uE2E; + std::vector sharp; + return sharp_edges(V,F,angle,SE,E,uE,EMAP,uE2E,sharp); +} + +#ifdef IGL_STATIC_LIBRARY +// Explicit template instantiation +template void igl::sharp_edges, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::Matrix::Scalar, Eigen::PlainObjectBase >&); +template void igl::sharp_edges, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, int, int>(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::Matrix::Scalar, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, std::vector >, std::allocator > > >&, std::vector >&); +#endif diff --git a/include/igl/sharp_edges.h b/include/igl/sharp_edges.h new file mode 100644 index 000000000..6f939bfc2 --- /dev/null +++ b/include/igl/sharp_edges.h @@ -0,0 +1,61 @@ +#ifndef IGL_SHARP_EDGES_H +#define IGL_SHARP_EDGES_H + +#include +#include +#include + +namespace igl +{ + // SHARP_EDGES Given a mesh, compute sharp edges. + // + // Inputs: + // V #V by 3 list of vertex positions + // F #F by 3 list of triangle mesh indices into V + // angle dihedral angle considered to sharp (e.g., igl::PI * 0.11) + // Outputs: + // SE #SE by 2 list of edge indices into V + // uE #uE by 2 list of unique undirected edges + // EMAP #F*3 list of indices into uE, mapping each directed edge to unique + // undirected edge so that uE(EMAP(f+#F*c)) is the unique edge + // corresponding to E.row(f+#F*c) + // uE2E #uE list of lists of indices into E of coexisting edges, so that + // E.row(uE2E[i][j]) corresponds to uE.row(i) for all j in + // 0..uE2E[i].size()-1. + // sharp #SE list of indices into uE revealing sharp undirected edges + template < + typename DerivedV, + typename DerivedF, + typename DerivedSE, + typename DerivedE, + typename DeriveduE, + typename DerivedEMAP, + typename uE2Etype, + typename sharptype> + IGL_INLINE void sharp_edges( + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const typename DerivedV::Scalar angle, + Eigen::PlainObjectBase & SE, + Eigen::PlainObjectBase & E, + Eigen::PlainObjectBase & uE, + Eigen::PlainObjectBase & EMAP, + std::vector > & uE2E, + std::vector< sharptype > & sharp); + template < + typename DerivedV, + typename DerivedF, + typename DerivedSE> + IGL_INLINE void sharp_edges( + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const typename DerivedV::Scalar angle, + Eigen::PlainObjectBase & SE + ); +} + +#ifndef IGL_STATIC_LIBRARY +# include "sharp_edges.cpp" +#endif + +#endif diff --git a/include/igl/signed_distance.cpp b/include/igl/signed_distance.cpp index ed9f64a15..a1007aa17 100644 --- a/include/igl/signed_distance.cpp +++ b/include/igl/signed_distance.cpp @@ -148,14 +148,14 @@ IGL_INLINE void igl::signed_distance( } typename DerivedV::Scalar s=1,sqrd=0; Eigen::Matrix c; - RowVector3S c3; + Eigen::Matrix c3; Eigen::Matrix c2; int i=-1; // in all cases compute squared unsiged distances sqrd = dim==3? tree3.squared_distance(V,F,q3,low_sqr_d,up_sqr_d,i,c3): tree2.squared_distance(V,F,q2,low_sqr_d,up_sqr_d,i,c2); - if(sqrd >= up_sqr_d || sqrd <= low_sqr_d) + if(sqrd >= up_sqr_d || sqrd < low_sqr_d) { // Out of bounds gets a nan (nans on grids can be flood filled later using // igl::flood_fill) @@ -193,15 +193,15 @@ IGL_INLINE void igl::signed_distance( dim==3 ? pseudonormal_test(V,F,FN,VN,EN,EMAP,q3,i,c3,s,n3): pseudonormal_test(V,E,EN,VN,q2,i,c2,s,n2); - Eigen::Matrix n; - (dim==3 ? n = n3 : n = n2); - N.row(p) = n; + Eigen::Matrix n; + (dim==3 ? n = n3.template cast() : n = n2.template cast()); + N.row(p) = n.template cast(); break; } } I(p) = i; S(p) = s*sqrt(sqrd); - C.row(p) = (dim==3 ? c=c3 : c=c2); + C.row(p) = (dim==3 ? c=c3 : c=c2).template cast(); } } ,10000); diff --git a/include/igl/slice.cpp b/include/igl/slice.cpp index e2b7a8060..8b0fb3843 100644 --- a/include/igl/slice.cpp +++ b/include/igl/slice.cpp @@ -9,25 +9,27 @@ #include "colon.h" #include -#include -template +template < + typename TX, + typename TY, + typename DerivedR, + typename DerivedC> IGL_INLINE void igl::slice( - const Eigen::SparseMatrix& X, - const Eigen::Matrix & R, - const Eigen::Matrix & C, - Eigen::SparseMatrix& Y) + const Eigen::SparseMatrix &X, + const Eigen::DenseBase &R, + const Eigen::DenseBase &C, + Eigen::SparseMatrix &Y) { -#if 1 int xm = X.rows(); int xn = X.cols(); int ym = R.size(); int yn = C.size(); // special case when R or C is empty - if(ym == 0 || yn == 0) + if (ym == 0 || yn == 0) { - Y.resize(ym,yn); + Y.resize(ym, yn); return; } @@ -36,148 +38,88 @@ IGL_INLINE void igl::slice( assert(C.minCoeff() >= 0); assert(C.maxCoeff() < xn); - // Build reindexing maps for columns and rows, -1 means not in map - std::vector > RI; + // Build reindexing maps for columns and rows + std::vector> RI; RI.resize(xm); - for(int i = 0;i > CI; + std::vector> CI; CI.resize(xn); - // initialize to -1 - for(int i = 0;i dyn_Y(ym,yn); + // Take a guess at the number of nonzeros (this assumes uniform distribution // not banded or heavily diagonal) - dyn_Y.reserve((X.nonZeros()/(X.rows()*X.cols())) * (ym*yn)); + std::vector> entries; + entries.reserve((X.nonZeros()/(X.rows()*X.cols())) * (ym*yn)); + // Iterate over outside - for(int k=0; k::InnerIterator it (X,k); it; ++it) + for (typename Eigen::SparseMatrix::InnerIterator it(X, k); it; ++it) { - std::vector::iterator rit, cit; - for(rit = RI[it.row()].begin();rit != RI[it.row()].end(); rit++) + for (auto rit = RI[it.row()].begin(); rit != RI[it.row()].end(); rit++) { - for(cit = CI[it.col()].begin();cit != CI[it.col()].end(); cit++) + for (auto cit = CI[it.col()].begin(); cit != CI[it.col()].end(); cit++) { - dyn_Y.coeffRef(*rit,*cit) = it.value(); + entries.emplace_back(*rit, *cit, it.value()); } } } } - Y = Eigen::SparseMatrix(dyn_Y); -#else - - // Alec: This is _not_ valid for arbitrary R,C since they don't necessary - // representation a strict permutation of the rows and columns: rows or - // columns could be removed or replicated. The removal of rows seems to be - // handled here (although it's not clear if there is a performance gain when - // the #removals >> #remains). If this is sufficiently faster than the - // correct code above, one could test whether all entries in R and C are - // unique and apply the permutation version if appropriate. - // - - int xm = X.rows(); - int xn = X.cols(); - int ym = R.size(); - int yn = C.size(); - - // special case when R or C is empty - if(ym == 0 || yn == 0) - { - Y.resize(ym,yn); - return; - } - - assert(R.minCoeff() >= 0); - assert(R.maxCoeff() < xm); - assert(C.minCoeff() >= 0); - assert(C.maxCoeff() < xn); - - // initialize row and col permutation vectors - Eigen::VectorXi rowIndexVec = igl::LinSpaced(xm,0,xm-1); - Eigen::VectorXi rowPermVec = igl::LinSpaced(xm,0,xm-1); - for(int i=0;i rowPerm(rowIndexVec); - - Eigen::VectorXi colIndexVec = igl::LinSpaced(xn,0,xn-1); - Eigen::VectorXi colPermVec = igl::LinSpaced(xn,0,xn-1); - for(int i=0;i colPerm(colPermVec); - - Eigen::SparseMatrix M = (rowPerm * X); - Y = (M * colPerm).block(0,0,ym,yn); -#endif + Y.resize(ym, yn); + Y.setFromTriplets(entries.begin(), entries.end()); } template IGL_INLINE void igl::slice( - const MatX& X, - const Eigen::DenseBase & R, - const int dim, - MatY& Y) + const MatX &X, + const Eigen::DenseBase &R, + const int dim, + MatY &Y) { - Eigen::Matrix C; - switch(dim) + Eigen::Matrix C; + switch (dim) { - case 1: - // boring base case - if(X.cols() == 0) - { - Y.resize(R.size(),0); - return; - } - igl::colon(0,X.cols()-1,C); - return slice(X,R,C,Y); - case 2: - // boring base case - if(X.rows() == 0) - { - Y.resize(0,R.size()); - return; - } - igl::colon(0,X.rows()-1,C); - return slice(X,C,R,Y); - default: - assert(false && "Unsupported dimension"); + case 1: + // boring base case + if (X.cols() == 0) + { + Y.resize(R.size(), 0); return; + } + igl::colon(0, X.cols() - 1, C); + return slice(X, R, C, Y); + case 2: + // boring base case + if (X.rows() == 0) + { + Y.resize(0, R.size()); + return; + } + igl::colon(0, X.rows() - 1, C); + return slice(X, C, R, Y); + default: + assert(false && "Unsupported dimension"); + return; } } template < - typename DerivedX, - typename DerivedR, - typename DerivedC, - typename DerivedY> + typename DerivedX, + typename DerivedR, + typename DerivedC, + typename DerivedY> IGL_INLINE void igl::slice( - const Eigen::DenseBase & X, - const Eigen::DenseBase & R, - const Eigen::DenseBase & C, - Eigen::PlainObjectBase & Y) + const Eigen::DenseBase &X, + const Eigen::DenseBase &R, + const Eigen::DenseBase &C, + Eigen::PlainObjectBase &Y) { #ifndef NDEBUG int xm = X.rows(); @@ -187,9 +129,9 @@ IGL_INLINE void igl::slice( int yn = C.size(); // special case when R or C is empty - if(ym == 0 || yn == 0) + if (ym == 0 || yn == 0) { - Y.resize(ym,yn); + Y.resize(ym, yn); return; } @@ -199,175 +141,107 @@ IGL_INLINE void igl::slice( assert(C.maxCoeff() < xn); // Resize output - Y.resize(ym,yn); + Y.resize(ym, yn); // loop over output rows, then columns - for(int i = 0;i +template IGL_INLINE void igl::slice( - const Eigen::DenseBase & X, - const Eigen::Matrix & R, - Eigen::PlainObjectBase & Y) + const Eigen::DenseBase &X, + const Eigen::DenseBase &R, + Eigen::PlainObjectBase &Y) { // phony column indices - Eigen::Matrix C; + Eigen::Matrix C; C.resize(1); C(0) = 0; - return igl::slice(X,R,C,Y); + return igl::slice(X, R, C, Y); } -template +template IGL_INLINE DerivedX igl::slice( - const Eigen::DenseBase & X, - const Eigen::Matrix & R) + const Eigen::DenseBase &X, + const Eigen::DenseBase &R) { DerivedX Y; - igl::slice(X,R,Y); + igl::slice(X, R, Y); return Y; } -template +template IGL_INLINE DerivedX igl::slice( - const Eigen::DenseBase& X, - const Eigen::Matrix & R, - const int dim) + const Eigen::DenseBase &X, + const Eigen::DenseBase &R, + const int dim) { DerivedX Y; - igl::slice(X,R,dim,Y); + igl::slice(X, R, dim, Y); return Y; } #ifdef IGL_STATIC_LIBRARY -// Explicit template instantiation -#if EIGEN_VERSION_AT_LEAST(3,3,0) -#else -// generated by autoexplicit.sh -template void igl::slice, Eigen::Matrix const> >, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase, Eigen::Matrix const> > const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -#endif -// generated by autoexplicit.sh -template void igl::slice, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh -template void igl::slice, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh -template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh -template void igl::slice, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh -template void igl::slice, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh -template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::PlainObjectBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh -template void igl::slice, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh -template Eigen::Matrix igl::slice >(Eigen::DenseBase > const&, Eigen::Matrix const&, int); -// generated by autoexplicit.sh -template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh -template void igl::slice >, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -// generated by autoexplicit.sh -template void igl::slice >, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -// generated by autoexplicit.sh -template void igl::slice, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::Matrix const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh -template void igl::slice, Eigen::Matrix, Eigen::Matrix >(Eigen::Matrix const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -// generated by autoexplicit.sh -template void igl::slice, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh -template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh -template void igl::slice, Eigen::Matrix, Eigen::Matrix >(Eigen::Matrix const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -// generated by autoexplicit.sh -template void igl::slice, Eigen::Matrix, Eigen::Matrix >(Eigen::Matrix const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -// generated by autoexplicit.sh -template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh -template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh -template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh -template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh -template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh -template void igl::slice, Eigen::Matrix, Eigen::Array >(Eigen::Array const&, Eigen::DenseBase > const&, int, Eigen::Array&); -// generated by autoexplicit.sh -template void igl::slice >, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -// generated by autoexplicit.sh -template void igl::slice >, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -// generated by autoexplicit.sh -template void igl::slice, Eigen::Matrix, Eigen::Matrix >(Eigen::Matrix const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -// generated by autoexplicit.sh -template void igl::slice, Eigen::Matrix, Eigen::Matrix >(Eigen::Array const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -// generated by autoexplicit.sh -template void igl::slice, Eigen::Matrix, Eigen::Array >(Eigen::Array const&, Eigen::DenseBase > const&, int, Eigen::Array&); -// generated by autoexplicit.sh -template void igl::slice >, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -// generated by autoexplicit.sh -template void igl::slice >, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -// generated by autoexplicit.sh -template void igl::slice, Eigen::Matrix, Eigen::SparseMatrix >(Eigen::SparseMatrix const&, Eigen::DenseBase > const&, int, Eigen::SparseMatrix&); -// generated by autoexplicit.sh -template void igl::slice >, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -// generated by autoexplicit.sh -template void igl::slice >, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -// generated by autoexplicit.sh -template void igl::slice, Eigen::Matrix, Eigen::Matrix >(Eigen::Matrix const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -// generated by autoexplicit.sh -template void igl::slice, Eigen::Matrix, Eigen::Matrix >(Eigen::Matrix const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -// generated by autoexplicit.sh -template Eigen::Matrix igl::slice >(Eigen::DenseBase > const&, Eigen::Matrix const&); -// generated by autoexplicit.sh -template void igl::slice, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); -template void igl::slice, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::Matrix const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -template void igl::slice, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::Matrix const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -template void igl::slice, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::Matrix const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::PlainObjectBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::PlainObjectBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::PlainObjectBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -template Eigen::Matrix igl::slice >(Eigen::DenseBase > const&, Eigen::Matrix const&, int); -template Eigen::Matrix igl::slice >(Eigen::DenseBase > const&, Eigen::Matrix const&); -template Eigen::Matrix igl::slice >(Eigen::DenseBase > const&, Eigen::Matrix const&, int); -template void igl::slice, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); -template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::PlainObjectBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::PlainObjectBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::PlainObjectBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::PlainObjectBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -template void igl::slice, Eigen::Matrix, Eigen::Matrix >(Eigen::Matrix const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -template void igl::slice, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::Matrix const&, Eigen::PlainObjectBase >&); -template void igl::slice, std::complex >(Eigen::SparseMatrix, 0, int> const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::SparseMatrix, 0, int>&); -template Eigen::Matrix igl::slice >(Eigen::DenseBase > const&, Eigen::Matrix const&, int); -template void igl::slice, Eigen::Matrix, Eigen::SparseMatrix >(Eigen::SparseMatrix const&, Eigen::DenseBase > const&, int, Eigen::SparseMatrix&); -template void igl::slice(Eigen::SparseMatrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::SparseMatrix&); -template void igl::slice, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::Matrix const&, Eigen::PlainObjectBase >&); -template void igl::slice, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::Matrix const&, Eigen::PlainObjectBase >&); -template void igl::slice, Eigen::Matrix, Eigen::SparseMatrix >(Eigen::SparseMatrix const&, Eigen::DenseBase > const&, int, Eigen::SparseMatrix&); -template void igl::slice, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::Matrix const&, Eigen::PlainObjectBase >&); -template void igl::slice, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); -template void igl::slice, Eigen::Matrix, Eigen::SparseMatrix >(Eigen::SparseMatrix const&, Eigen::DenseBase > const&, int, Eigen::SparseMatrix&); -template void igl::slice, Eigen::Matrix, Eigen::Matrix >(Eigen::Matrix const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -template void igl::slice, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); -template void igl::slice(Eigen::SparseMatrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::SparseMatrix&); -template void igl::slice, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::Matrix const&, Eigen::PlainObjectBase >&); -template Eigen::Matrix igl::slice >(Eigen::DenseBase > const&, Eigen::Matrix const&); -template void igl::slice >, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -template void igl::slice, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); -template void igl::slice(Eigen::SparseMatrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::SparseMatrix&); -template void igl::slice, Eigen::Array, Eigen::SparseMatrix >(Eigen::SparseMatrix const&, Eigen::DenseBase > const&, int, Eigen::SparseMatrix&); -template void igl::slice, Eigen::Block const, -1, 1, true>, Eigen::Matrix >(Eigen::Matrix const&, Eigen::DenseBase const, -1, 1, true> > const&, int, Eigen::Matrix&); -template void igl::slice, Eigen::Block const, -1, 1, true>, Eigen::Matrix >(Eigen::Matrix const&, Eigen::DenseBase const, -1, 1, true> > const&, int, Eigen::Matrix&); + +template Eigen::Matrix igl::slice, Eigen::Matrix>(Eigen::DenseBase> const &, Eigen::DenseBase> const &, int); +template Eigen::Matrix igl::slice, Eigen::Matrix>(Eigen::DenseBase> const &, Eigen::DenseBase> const &); +template void igl::slice, Eigen::Matrix, Eigen::Matrix>(Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::PlainObjectBase> &); +template void igl::slice, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix>(Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::PlainObjectBase> &); +template void igl::slice, Eigen::Matrix, Eigen::Matrix>(Eigen::Matrix const &, Eigen::DenseBase> const &, int, Eigen::Matrix &); +template void igl::slice, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix>(Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::PlainObjectBase> &); +template void igl::slice, Eigen::Matrix, Eigen::PlainObjectBase>>(Eigen::Matrix const &, Eigen::DenseBase> const &, int, Eigen::PlainObjectBase> &); +template void igl::slice, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix>(Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::PlainObjectBase> &); +template void igl::slice, Eigen::Matrix, Eigen::Matrix>(Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::PlainObjectBase> &); +template void igl::slice, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix>(Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::PlainObjectBase> &); +template void igl::slice, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix>(Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::PlainObjectBase> &); +template void igl::slice, Eigen::Matrix, Eigen::Matrix>(Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::PlainObjectBase> &); +template void igl::slice, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix>(Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::PlainObjectBase> &); +template void igl::slice, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix>(Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::PlainObjectBase> &); +template void igl::slice, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix>(Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::PlainObjectBase> &); +template void igl::slice, Eigen::Matrix, Eigen::PlainObjectBase>>(Eigen::Matrix const &, Eigen::DenseBase> const &, int, Eigen::PlainObjectBase> &); +template void igl::slice, Eigen::Matrix, Eigen::Block const, -1, 1, true>>(Eigen::DenseBase> const &, Eigen::DenseBase const, -1, 1, true>> const &, Eigen::PlainObjectBase> &); +template void igl::slice, Eigen::Matrix, Eigen::Matrix>(Eigen::DenseBase> const &, Eigen::DenseBase> const &, Eigen::PlainObjectBase> &); +template void igl::slice, Eigen::Matrix, Eigen::Matrix>(Eigen::Matrix const &, Eigen::DenseBase> const &, int, Eigen::Matrix &); +template void igl::slice, Eigen::Matrix, Eigen::PlainObjectBase>>(Eigen::Matrix const &, Eigen::DenseBase> const &, int, Eigen::PlainObjectBase> &); +template void igl::slice, Eigen::Matrix, Eigen::PlainObjectBase>>(Eigen::Matrix const &, Eigen::DenseBase> const &, int, Eigen::PlainObjectBase> &); +template void igl::slice >, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); -template void igl::slice, Eigen::Matrix, Eigen::Matrix >(Eigen::Matrix const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); -template void igl::slice, Eigen::Block, -1, 1, true>, Eigen::Matrix >(Eigen::Matrix const&, Eigen::DenseBase, -1, 1, true> > const&, int, Eigen::Matrix&); +template void igl::slice >, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); +template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::slice >, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::Matrix&); +template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::slice >, Eigen::Matrix, Eigen::PlainObjectBase > >(Eigen::MatrixBase > const&, Eigen::DenseBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::slice>, Eigen::Matrix, Eigen::PlainObjectBase>>(Eigen::PlainObjectBase> const &, Eigen::DenseBase> const &, int, Eigen::PlainObjectBase> &); +template void igl::slice>, Eigen::Matrix, Eigen::PlainObjectBase>>(Eigen::PlainObjectBase> const &, Eigen::DenseBase> const &, int, Eigen::PlainObjectBase> &); +template void igl::slice>, Eigen::Matrix, Eigen::PlainObjectBase>>(Eigen::PlainObjectBase> const &, Eigen::DenseBase> const &, int, Eigen::PlainObjectBase> &); +template void igl::slice>, Eigen::Matrix, Eigen::PlainObjectBase>>(Eigen::PlainObjectBase> const &, Eigen::DenseBase> const &, int, Eigen::PlainObjectBase> &); +template void igl::slice, Eigen::Matrix, Eigen::SparseMatrix>(Eigen::SparseMatrix const &, Eigen::DenseBase> const &, int, Eigen::SparseMatrix &); +template void igl::slice, Eigen::Array, Eigen::SparseMatrix >(Eigen::SparseMatrix const&, Eigen::DenseBase > const&, int, Eigen::SparseMatrix&); +template void igl::slice, Eigen::Matrix, Eigen::SparseMatrix>(Eigen::SparseMatrix const &, Eigen::DenseBase> const &, int, Eigen::SparseMatrix &); +template void igl::slice, Eigen::Matrix, Eigen::SparseMatrix>(Eigen::SparseMatrix const &, Eigen::DenseBase> const &, int, Eigen::SparseMatrix &); +template void igl::slice, Eigen::Matrix, Eigen::SparseMatrix>(Eigen::SparseMatrix const &, Eigen::DenseBase> const &, int, Eigen::SparseMatrix &); + #ifdef WIN32 -template void igl::slice, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::PlainObjectBase>>(class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> const &, class Eigen::DenseBase> const &, int, class Eigen::PlainObjectBase> &); -template void igl::slice>, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::PlainObjectBase>>(class Eigen::PlainObjectBase> const &, class Eigen::DenseBase> const &, int, class Eigen::PlainObjectBase> &); +template void igl::slice >,class Eigen::Matrix<__int64,-1,1,0,-1,1>,class Eigen::PlainObjectBase > >(class Eigen::DenseBase > const &,class Eigen::DenseBase > const &,int,class Eigen::PlainObjectBase > &); +template void igl::slice >,class Eigen::Matrix<__int64,-1,1,0,-1,1>,class Eigen::PlainObjectBase > >(class Eigen::MatrixBase > const &,class Eigen::DenseBase > const &,int,class Eigen::PlainObjectBase > &); +template void igl::slice, Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase>>(Eigen::Matrix<__int64, -1, 1, 0, -1, 1> const &, Eigen::DenseBase> const &, int, Eigen::PlainObjectBase> &); +template void igl::slice>, Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, Eigen::PlainObjectBase>>(Eigen::PlainObjectBase> const &, Eigen::DenseBase> const &, int, Eigen::PlainObjectBase> &); #endif + #endif diff --git a/include/igl/slice.h b/include/igl/slice.h index a25dfa411..fcb6bbbeb 100644 --- a/include/igl/slice.h +++ b/include/igl/slice.h @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2013 Alec Jacobson // -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_SLICE_H #define IGL_SLICE_H @@ -14,7 +14,7 @@ namespace igl { // Act like the matlab X(row_indices,col_indices) operator, where // row_indices, col_indices are non-negative integer indices. - // + // // Inputs: // X m by n matrix // R list of row indices @@ -24,13 +24,16 @@ namespace igl // // See also: slice_mask template < - typename TX, - typename TY> + typename TX, + typename TY, + typename DerivedR, + typename DerivedC> IGL_INLINE void slice( const Eigen::SparseMatrix& X, - const Eigen::Matrix & R, - const Eigen::Matrix & C, + const Eigen::DenseBase & R, + const Eigen::DenseBase & C, Eigen::SparseMatrix& Y); + // Wrapper to only slice in one direction // // Inputs: @@ -38,7 +41,7 @@ namespace igl // // Note: For now this is just a cheap wrapper. template < - typename MatX, + typename MatX, typename DerivedR, typename MatY> IGL_INLINE void slice( @@ -46,10 +49,11 @@ namespace igl const Eigen::DenseBase & R, const int dim, MatY& Y); + template < - typename DerivedX, - typename DerivedR, - typename DerivedC, + typename DerivedX, + typename DerivedR, + typename DerivedC, typename DerivedY> IGL_INLINE void slice( const Eigen::DenseBase & X, @@ -57,25 +61,26 @@ namespace igl const Eigen::DenseBase & C, Eigen::PlainObjectBase & Y); - template + template IGL_INLINE void slice( const Eigen::DenseBase & X, - const Eigen::Matrix & R, + const Eigen::DenseBase & R, Eigen::PlainObjectBase & Y); + // VectorXi Y = slice(X,R); // // This templating is bad because the return type might not have the same // size as `DerivedX`. This will probably only work if DerivedX has Dynamic // as it's non-trivial sizes or if the number of rows in R happens to equal // the number of rows in `DerivedX`. - template + template IGL_INLINE DerivedX slice( const Eigen::DenseBase & X, - const Eigen::Matrix & R); - template + const Eigen::DenseBase & R); + template IGL_INLINE DerivedX slice( const Eigen::DenseBase& X, - const Eigen::Matrix & R, + const Eigen::DenseBase & R, const int dim); } diff --git a/include/igl/slice_into.cpp b/include/igl/slice_into.cpp index 7348beaad..92f5210e6 100644 --- a/include/igl/slice_into.cpp +++ b/include/igl/slice_into.cpp @@ -12,11 +12,11 @@ #include #include -template +template IGL_INLINE void igl::slice_into( const Eigen::SparseMatrix& X, - const Eigen::Matrix & R, - const Eigen::Matrix & C, + const Eigen::MatrixBase & R, + const Eigen::MatrixBase & C, Eigen::SparseMatrix& Y) { @@ -34,7 +34,7 @@ IGL_INLINE void igl::slice_into( #endif // create temporary dynamic sparse matrix - Eigen::DynamicSparseMatrix dyn_Y(Y); + Eigen::DynamicSparseMatrix dyn_Y(Y); // Iterate over outside for(int k=0; k(dyn_Y); } -template +template IGL_INLINE void igl::slice_into( - const Eigen::DenseBase & X, - const Eigen::Matrix & R, - const Eigen::Matrix & C, + const Eigen::MatrixBase & X, + const Eigen::MatrixBase & R, + const Eigen::MatrixBase & C, Eigen::PlainObjectBase & Y) { @@ -69,7 +69,7 @@ IGL_INLINE void igl::slice_into( #endif // Build reindexing maps for columns and rows, -1 means not in map - Eigen::Matrix RI; + Eigen::Matrix RI; RI.resize(xm); for(int i = 0;i +template IGL_INLINE void igl::slice_into( - const MatX& X, - const Eigen::Matrix & R, + const MatX & X, + const Eigen::MatrixBase & R, const int dim, MatY& Y) { - Eigen::VectorXi C; + Eigen::Matrix C; switch(dim) { case 1: @@ -114,40 +114,28 @@ IGL_INLINE void igl::slice_into( } } -template +template IGL_INLINE void igl::slice_into( - const Eigen::DenseBase & X, - const Eigen::Matrix & R, + const Eigen::MatrixBase & X, + const Eigen::MatrixBase & R, Eigen::PlainObjectBase & Y) { // phony column indices - Eigen::Matrix C; + Eigen::Matrix C; C.resize(1); C(0) = 0; return igl::slice_into(X,R,C,Y); } #ifdef IGL_STATIC_LIBRARY -// Explicit template instantiation -// generated by autoexplicit.sh -template void igl::slice_into, Eigen::Matrix >(Eigen::Matrix const&, Eigen::Matrix const&, int, Eigen::Matrix&); -// generated by autoexplicit.sh -template void igl::slice_into, Eigen::PlainObjectBase > >(Eigen::Matrix const&, Eigen::Matrix const&, int, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh -template void igl::slice_into, -1, -1, true>, Eigen::PlainObjectBase > >(Eigen::Block, -1, -1, true> const&, Eigen::Matrix const&, int, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh -template void igl::slice_into, Eigen::PlainObjectBase > >(Eigen::Matrix const&, Eigen::Matrix const&, int, Eigen::PlainObjectBase >&); -// generated by autoexplicit.sh -template void igl::slice_into, Eigen::PlainObjectBase > >(Eigen::Matrix const&, Eigen::Matrix const&, int, Eigen::PlainObjectBase >&); -template void igl::slice_into(Eigen::SparseMatrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::SparseMatrix&); -template void igl::slice_into, Eigen::Matrix >(Eigen::Matrix const&, Eigen::Matrix const&, int, Eigen::Matrix&); -template void igl::slice_into, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::Matrix const&, Eigen::PlainObjectBase >&); -template void igl::slice_into, Eigen::Matrix >(Eigen::Matrix const&, Eigen::Matrix const&, int, Eigen::Matrix&); -template void igl::slice_into, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::Matrix const&, Eigen::PlainObjectBase >&); -template void igl::slice_into, Eigen::SparseMatrix >(Eigen::SparseMatrix const&, Eigen::Matrix const&, int, Eigen::SparseMatrix&); -template void igl::slice_into(Eigen::SparseMatrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::SparseMatrix&); -template void igl::slice_into, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::Matrix const&, Eigen::PlainObjectBase >&); -template void igl::slice_into, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::PlainObjectBase >&); -template void igl::slice_into, Eigen::Matrix >(Eigen::Matrix const&, Eigen::Matrix const&, int, Eigen::Matrix&); -template void igl::slice_into, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::Matrix const&, Eigen::PlainObjectBase >&); +template void igl::slice_into, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::slice_into, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::slice_into >(Eigen::SparseMatrix const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::SparseMatrix&); +template void igl::slice_into, Eigen::PlainObjectBase >, Eigen::Matrix >(Eigen::Matrix const&, Eigen::MatrixBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::slice_into, Eigen::PlainObjectBase >, Eigen::Matrix >(Eigen::Matrix const&, Eigen::MatrixBase > const&, int, Eigen::PlainObjectBase >&); +template void igl::slice_into, Eigen::Matrix, Eigen::Matrix >(Eigen::Matrix const&, Eigen::MatrixBase > const&, int, Eigen::Matrix&); +template void igl::slice_into, Eigen::Matrix, Eigen::Matrix >(Eigen::Matrix const&, Eigen::MatrixBase > const&, int, Eigen::Matrix&); +template void igl::slice_into, Eigen::SparseMatrix, Eigen::Matrix >(Eigen::SparseMatrix const&, Eigen::MatrixBase > const&, int, Eigen::SparseMatrix&); +template void igl::slice_into, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::slice_into, Eigen::Matrix, Eigen::MatrixWrapper > >(Eigen::Matrix const&, Eigen::MatrixBase > > const&, int, Eigen::Matrix&); #endif diff --git a/include/igl/slice_into.h b/include/igl/slice_into.h index 83bd8f523..5971d97ee 100644 --- a/include/igl/slice_into.h +++ b/include/igl/slice_into.h @@ -23,18 +23,18 @@ namespace igl // Y ym by yn lhs matrix // Output: // Y ym by yn lhs matrix, same as input but Y(R,C) = X - template + template IGL_INLINE void slice_into( const Eigen::SparseMatrix& X, - const Eigen::Matrix & R, - const Eigen::Matrix & C, + const Eigen::MatrixBase & R, + const Eigen::MatrixBase & C, Eigen::SparseMatrix& Y); - template + template IGL_INLINE void slice_into( - const Eigen::DenseBase & X, - const Eigen::Matrix & R, - const Eigen::Matrix & C, + const Eigen::MatrixBase & X, + const Eigen::MatrixBase & R, + const Eigen::MatrixBase & C, Eigen::PlainObjectBase & Y); // Wrapper to only slice in one direction // @@ -42,18 +42,18 @@ namespace igl // dim dimension to slice in 1 or 2, dim=1 --> X(R,:), dim=2 --> X(:,R) // // Note: For now this is just a cheap wrapper. - template + template IGL_INLINE void slice_into( const MatX & X, - const Eigen::Matrix & R, + const Eigen::MatrixBase & R, const int dim, MatY& Y); - template + template IGL_INLINE void slice_into( - const Eigen::DenseBase & X, - const Eigen::Matrix & R, - Eigen::PlainObjectBase & Y); + const Eigen::MatrixBase& X, + const Eigen::MatrixBase& R, + Eigen::PlainObjectBase& Y); } #ifndef IGL_STATIC_LIBRARY diff --git a/include/igl/slice_mask.cpp b/include/igl/slice_mask.cpp index b0327556f..9fd5b45db 100644 --- a/include/igl/slice_mask.cpp +++ b/include/igl/slice_mask.cpp @@ -1,12 +1,13 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2015 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "slice_mask.h" #include "slice.h" +#include "slice_sorted.h" #include "find.h" #include @@ -143,7 +144,7 @@ IGL_INLINE void igl::slice_mask( find(R,Ri); Eigen::VectorXi Ci; find(C,Ci); - return slice(X,Ri,Ci,Y); + return slice_sorted(X,Ri,Ci,Y); } #ifdef IGL_STATIC_LIBRARY @@ -166,4 +167,5 @@ template void igl::slice_mask >(Eigen:: template void igl::slice_mask >(Eigen::DenseBase > const&, Eigen::Array const&, Eigen::Array const&, Eigen::PlainObjectBase >&); template void igl::slice_mask >(Eigen::DenseBase > const&, Eigen::Array const&, int, Eigen::PlainObjectBase >&); template void igl::slice_mask, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::Array const&, int, Eigen::PlainObjectBase >&); +template Eigen::Matrix igl::slice_mask >(Eigen::DenseBase > const&, Eigen::Array const&, int); #endif diff --git a/include/igl/slice_sorted.cpp b/include/igl/slice_sorted.cpp new file mode 100644 index 000000000..000a20aa9 --- /dev/null +++ b/include/igl/slice_sorted.cpp @@ -0,0 +1,88 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2013 Alec Jacobson +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// obtain one at http://mozilla.org/MPL/2.0/. +#include "slice_sorted.h" + +#include + +// TODO: Write a version that works for row-major sparse matrices as well. +template +IGL_INLINE void igl::slice_sorted(const Eigen::SparseMatrix &X, + const Eigen::DenseBase &R, + const Eigen::DenseBase &C, + Eigen::SparseMatrix &Y) +{ + int xm = X.rows(); + int xn = X.cols(); + int ym = R.size(); + int yn = C.size(); + + // Special case when R or C is empty + if (ym == 0 || yn == 0) + { + Y.resize(ym, yn); + return; + } + + assert(R.minCoeff() >= 0); + assert(R.maxCoeff() < xm); + assert(C.minCoeff() >= 0); + assert(C.maxCoeff() < xn); + + // Multiplicity count for each row/col + using RowIndexType = typename DerivedR::Scalar; + using ColIndexType = typename DerivedC::Scalar; + std::vector slicedRowStart(xm); + std::vector rowRepeat(xm, 0); + for (int i = 0; i < ym; ++i) + { + if (rowRepeat[R(i)] == 0) + { + slicedRowStart[R(i)] = i; + } + rowRepeat[R(i)]++; + } + std::vector columnRepeat(xn, 0); + for (int i = 0; i < yn; i++) + { + columnRepeat[C(i)]++; + } + // Count number of nnz per outer row/col + Eigen::VectorXi nnz(yn); + for (int k = 0, c = 0; k < X.outerSize(); ++k) + { + int cnt = 0; + for (typename Eigen::SparseMatrix::InnerIterator it(X, k); it; ++it) + { + cnt += rowRepeat[it.row()]; + } + for (int i = 0; i < columnRepeat[k]; ++i, ++c) + { + nnz(c) = cnt; + } + } + Y.resize(ym, yn); + Y.reserve(nnz); + // Insert values + for (int k = 0, c = 0; k < X.outerSize(); ++k) + { + for (int i = 0; i < columnRepeat[k]; ++i, ++c) + { + for (typename Eigen::SparseMatrix::InnerIterator it(X, k); it; ++it) + { + for (int j = 0, r = slicedRowStart[it.row()]; j < rowRepeat[it.row()]; ++j, ++r) + { + Y.insert(r, c) = it.value(); + } + } + } + } +} + +#ifdef IGL_STATIC_LIBRARY +template void igl::slice_sorted, Eigen::Matrix >(Eigen::SparseMatrix const&, Eigen::DenseBase > const&, Eigen::DenseBase > const&, Eigen::SparseMatrix&); +#endif diff --git a/include/igl/slice_sorted.h b/include/igl/slice_sorted.h new file mode 100644 index 000000000..47826b927 --- /dev/null +++ b/include/igl/slice_sorted.h @@ -0,0 +1,42 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2019 Jérémie Dumas +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// obtain one at http://mozilla.org/MPL/2.0/. + +#ifndef IGL_SLICE_SORTED_H +#define IGL_SLICE_SORTED_H + +#include "igl_inline.h" +#include +#include + +namespace igl +{ + // Act like the matlab X(row_indices,col_indices) operator, where row_indices, + // col_indices are non-negative integer indices. This version is about 2x faster + // than igl::slice, but it assumes that the indices to slice with are already sorted. + // + // Inputs: + // X m by n matrix + // R list of row indices + // C list of column indices + // + // Output: + // Y #R by #C matrix + // + template + IGL_INLINE void slice_sorted(const Eigen::SparseMatrix &X, + const Eigen::DenseBase &R, + const Eigen::DenseBase &C, + Eigen::SparseMatrix &Y); + +} // namespace igl + +#ifndef IGL_STATIC_LIBRARY +#include "slice_sorted.cpp" +#endif + +#endif diff --git a/include/igl/slim.cpp b/include/igl/slim.cpp index b1d0f4dba..e42348733 100644 --- a/include/igl/slim.cpp +++ b/include/igl/slim.cpp @@ -747,8 +747,8 @@ IGL_INLINE void igl::slim_precompute( const Eigen::MatrixXd &V_init, igl::SLIMData &data, igl::MappingEnergyType slim_energy, - Eigen::VectorXi &b, - Eigen::MatrixXd &bc, + const Eigen::VectorXi &b, + const Eigen::MatrixXd &bc, double soft_p) { diff --git a/include/igl/slim.h b/include/igl/slim.h index aebfb2688..5661ec63a 100644 --- a/include/igl/slim.h +++ b/include/igl/slim.h @@ -85,8 +85,8 @@ IGL_INLINE void slim_precompute( const Eigen::MatrixXd& V_init, SLIMData& data, MappingEnergyType slim_energy, - Eigen::VectorXi& b, - Eigen::MatrixXd& bc, + const Eigen::VectorXi& b, + const Eigen::MatrixXd& bc, double soft_p); // Run iter_num iterations of SLIM diff --git a/include/igl/snap_points.cpp b/include/igl/snap_points.cpp index 938c2251f..3e586aa00 100644 --- a/include/igl/snap_points.cpp +++ b/include/igl/snap_points.cpp @@ -1,23 +1,23 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2013 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "snap_points.h" #include #include template < - typename DerivedC, - typename DerivedV, - typename DerivedI, - typename DerivedminD, + typename DerivedC, + typename DerivedV, + typename DerivedI, + typename DerivedminD, typename DerivedVI> IGL_INLINE void igl::snap_points( - const Eigen::PlainObjectBase & C, - const Eigen::PlainObjectBase & V, + const Eigen::MatrixBase & C, + const Eigen::MatrixBase & V, Eigen::PlainObjectBase & I, Eigen::PlainObjectBase & minD, Eigen::PlainObjectBase & VI) @@ -32,13 +32,13 @@ IGL_INLINE void igl::snap_points( } template < - typename DerivedC, - typename DerivedV, - typename DerivedI, + typename DerivedC, + typename DerivedV, + typename DerivedI, typename DerivedminD> IGL_INLINE void igl::snap_points( - const Eigen::PlainObjectBase & C, - const Eigen::PlainObjectBase & V, + const Eigen::MatrixBase & C, + const Eigen::MatrixBase & V, Eigen::PlainObjectBase & I, Eigen::PlainObjectBase & minD) { @@ -68,12 +68,12 @@ IGL_INLINE void igl::snap_points( } template < - typename DerivedC, - typename DerivedV, + typename DerivedC, + typename DerivedV, typename DerivedI> IGL_INLINE void igl::snap_points( - const Eigen::PlainObjectBase & C, - const Eigen::PlainObjectBase & V, + const Eigen::MatrixBase & C, + const Eigen::MatrixBase & V, Eigen::PlainObjectBase & I) { Eigen::Matrix minD; @@ -83,8 +83,8 @@ IGL_INLINE void igl::snap_points( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::snap_points, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::snap_points, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); -template void igl::snap_points, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); +template void igl::snap_points, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::snap_points, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::snap_points, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/snap_points.h b/include/igl/snap_points.h index dbb850a79..21ad448b5 100644 --- a/include/igl/snap_points.h +++ b/include/igl/snap_points.h @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2013 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_SNAP_POINTS_H #define IGL_SNAP_POINTS_H @@ -16,7 +16,7 @@ namespace igl // SNAP_POINTS snap list of points C to closest of another list of points V // // [I,minD,VI] = snap_points(C,V) - // + // // Inputs: // C #C by dim list of query point positions // V #V by dim list of data point positions @@ -25,34 +25,34 @@ namespace igl // minD #C list of squared (^p) distances to closest points // VI #C by dim list of new point positions, VI = V(I,:) template < - typename DerivedC, - typename DerivedV, - typename DerivedI, - typename DerivedminD, + typename DerivedC, + typename DerivedV, + typename DerivedI, + typename DerivedminD, typename DerivedVI> IGL_INLINE void snap_points( - const Eigen::PlainObjectBase & C, - const Eigen::PlainObjectBase & V, + const Eigen::MatrixBase & C, + const Eigen::MatrixBase & V, Eigen::PlainObjectBase & I, Eigen::PlainObjectBase & minD, Eigen::PlainObjectBase & VI); template < - typename DerivedC, - typename DerivedV, - typename DerivedI, + typename DerivedC, + typename DerivedV, + typename DerivedI, typename DerivedminD> IGL_INLINE void snap_points( - const Eigen::PlainObjectBase & C, - const Eigen::PlainObjectBase & V, + const Eigen::MatrixBase & C, + const Eigen::MatrixBase & V, Eigen::PlainObjectBase & I, Eigen::PlainObjectBase & minD); template < - typename DerivedC, - typename DerivedV, + typename DerivedC, + typename DerivedV, typename DerivedI > IGL_INLINE void snap_points( - const Eigen::PlainObjectBase & C, - const Eigen::PlainObjectBase & V, + const Eigen::MatrixBase & C, + const Eigen::MatrixBase & V, Eigen::PlainObjectBase & I); } diff --git a/include/igl/sort_angles.cpp b/include/igl/sort_angles.cpp index 486f621ea..a030eb006 100644 --- a/include/igl/sort_angles.cpp +++ b/include/igl/sort_angles.cpp @@ -11,7 +11,7 @@ template IGL_INLINE void igl::sort_angles( - const Eigen::PlainObjectBase& M, + const Eigen::MatrixBase& M, Eigen::PlainObjectBase& R) { const size_t num_rows = M.rows(); const size_t num_cols = M.cols(); @@ -110,5 +110,5 @@ IGL_INLINE void igl::sort_angles( } #ifdef IGL_STATIC_LIBRARY -template void igl::sort_angles, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); +template void igl::sort_angles, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/sort_angles.h b/include/igl/sort_angles.h index 4763c981e..d7e6e3c4d 100644 --- a/include/igl/sort_angles.h +++ b/include/igl/sort_angles.h @@ -24,7 +24,7 @@ namespace igl { // angle. template IGL_INLINE void sort_angles( - const Eigen::PlainObjectBase& M, + const Eigen::MatrixBase& M, Eigen::PlainObjectBase& R); } diff --git a/include/igl/sortrows.cpp b/include/igl/sortrows.cpp index 7c2407fc8..7e659e262 100644 --- a/include/igl/sortrows.cpp +++ b/include/igl/sortrows.cpp @@ -118,6 +118,8 @@ IGL_INLINE void igl::sortrows( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template void igl::sortrows, Eigen::Matrix >(Eigen::DenseBase > const&, bool, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh template void igl::sortrows, Eigen::Matrix >(Eigen::DenseBase > const&, bool, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template void igl::sortrows, Eigen::Matrix >(Eigen::DenseBase > const&, bool, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); diff --git a/include/igl/sparse_voxel_grid.cpp b/include/igl/sparse_voxel_grid.cpp index 234da9922..a46177e22 100644 --- a/include/igl/sparse_voxel_grid.cpp +++ b/include/igl/sparse_voxel_grid.cpp @@ -134,7 +134,7 @@ IGL_INLINE void igl::sparse_voxel_grid(const Eigen::MatrixBase& p0, CV.row(i) = CV_vector[i]; } for (int i = 0; i < CS_vector.size(); i++) { - CS[i] = CS_vector[i]; + CS(i) = CS_vector[i]; } for (int i = 0; i < CI_vector.size(); i++) { CI.row(i) = CI_vector[i]; @@ -145,4 +145,5 @@ IGL_INLINE void igl::sparse_voxel_grid(const Eigen::MatrixBase& p0, #ifdef IGL_STATIC_LIBRARY template void igl::sparse_voxel_grid, class std::function const &)>, class Eigen::Matrix, class Eigen::Matrix, class Eigen::Matrix >(class Eigen::MatrixBase > const &, class std::function const &)> const &, double, int, class Eigen::PlainObjectBase > &, class Eigen::PlainObjectBase > &, class Eigen::PlainObjectBase > &); template void igl::sparse_voxel_grid, std::function const&)>, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, std::function const&)> const&, double, int, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::sparse_voxel_grid, std::function const&)>, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, std::function const&)> const&, double, int, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/squared_edge_lengths.cpp b/include/igl/squared_edge_lengths.cpp index f83d56a79..043b0b5db 100644 --- a/include/igl/squared_edge_lengths.cpp +++ b/include/igl/squared_edge_lengths.cpp @@ -73,6 +73,8 @@ IGL_INLINE void igl::squared_edge_lengths( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template void igl::squared_edge_lengths, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh template void igl::squared_edge_lengths, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); // generated by autoexplicit.sh template void igl::squared_edge_lengths, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); diff --git a/include/igl/triangle_triangle_adjacency.cpp b/include/igl/triangle_triangle_adjacency.cpp index 62e8fbe1c..901d2e12f 100644 --- a/include/igl/triangle_triangle_adjacency.cpp +++ b/include/igl/triangle_triangle_adjacency.cpp @@ -262,6 +262,7 @@ template void igl::triangle_triangle_adjacency, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); template void igl::triangle_triangle_adjacency, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::triangle_triangle_adjacency, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); template void igl::triangle_triangle_adjacency, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::triangle_triangle_adjacency, long, long>(Eigen::MatrixBase > const&, std::vector >, std::allocator > > >, std::allocator >, std::allocator > > > > >&, std::vector >, std::allocator > > >, std::allocator >, std::allocator > > > > >&); template void igl::triangle_triangle_adjacency, int>(Eigen::MatrixBase > const&, std::vector >, std::allocator > > >, std::allocator >, std::allocator > > > > >&); diff --git a/include/igl/triangulated_grid.cpp b/include/igl/triangulated_grid.cpp index 2a11625cb..8c84f9e37 100644 --- a/include/igl/triangulated_grid.cpp +++ b/include/igl/triangulated_grid.cpp @@ -23,6 +23,18 @@ IGL_INLINE void igl::triangulated_grid( using namespace Eigen; Eigen::Matrix res(nx,ny); igl::grid(res,GV); + return igl::triangulated_grid(nx,ny,GF); +}; + +template < + typename XType, + typename YType, + typename DerivedGF> +IGL_INLINE void igl::triangulated_grid( + const XType & nx, + const YType & ny, + Eigen::PlainObjectBase & GF) +{ GF.resize((nx-1)*(ny-1)*2,3); for(int y = 0;y & GV, Eigen::PlainObjectBase & GF); + template < + typename XType, + typename YType, + typename DerivedGF> + IGL_INLINE void triangulated_grid( + const XType & nx, + const YType & ny, + Eigen::PlainObjectBase & GF); } #ifndef IGL_STATIC_LIBRARY # include "triangulated_grid.cpp" diff --git a/include/igl/unique.cpp b/include/igl/unique.cpp index 8d99a0e75..5420e44aa 100644 --- a/include/igl/unique.cpp +++ b/include/igl/unique.cpp @@ -77,7 +77,7 @@ template < typename DerivedIA, typename DerivedIC> IGL_INLINE void igl::unique( - const Eigen::DenseBase & A, + const Eigen::MatrixBase & A, Eigen::PlainObjectBase & C, Eigen::PlainObjectBase & IA, Eigen::PlainObjectBase & IC) @@ -99,7 +99,7 @@ template < typename DerivedC > IGL_INLINE void igl::unique( - const Eigen::DenseBase & A, + const Eigen::MatrixBase & A, Eigen::PlainObjectBase & C) { using namespace std; @@ -201,23 +201,23 @@ IGL_INLINE void igl::unique( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh -template void igl::unique, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); -template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::unique, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); -template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::unique, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); -template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::unique, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&); -template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); -template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::unique, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::unique, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::unique, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::unique, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::unique, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::unique(std::vector > const&, std::vector >&); template void igl::unique(std::vector > const&, std::vector >&); template void igl::unique(std::vector > const&, std::vector >&, std::vector >&, std::vector >&); template void igl::unique(std::vector > const&, std::vector >&, std::vector >&, std::vector >&); #ifdef WIN32 -template void igl::unique,class Eigen::Matrix,class Eigen::Matrix<__int64,-1,1,0,-1,1>,class Eigen::Matrix<__int64,-1,1,0,-1,1> >(class Eigen::DenseBase > const &,class Eigen::PlainObjectBase > &,class Eigen::PlainObjectBase > &,class Eigen::PlainObjectBase > &); +template void igl::unique,class Eigen::Matrix,class Eigen::Matrix<__int64,-1,1,0,-1,1>,class Eigen::Matrix<__int64,-1,1,0,-1,1> >(class Eigen::MatrixBase > const &,class Eigen::PlainObjectBase > &,class Eigen::PlainObjectBase > &,class Eigen::PlainObjectBase > &); template void igl::unique<__int64>(class std::vector<__int64,class std::allocator<__int64> > const &,class std::vector<__int64,class std::allocator<__int64> > &,class std::vector > &,class std::vector > &); #endif #endif diff --git a/include/igl/unique.h b/include/igl/unique.h index 8618da15e..0e5061d46 100644 --- a/include/igl/unique.h +++ b/include/igl/unique.h @@ -39,7 +39,7 @@ namespace igl typename DerivedIA, typename DerivedIC> IGL_INLINE void unique( - const Eigen::DenseBase & A, + const Eigen::MatrixBase & A, Eigen::PlainObjectBase & C, Eigen::PlainObjectBase & IA, Eigen::PlainObjectBase & IC); @@ -47,7 +47,7 @@ namespace igl typename DerivedA, typename DerivedC> IGL_INLINE void unique( - const Eigen::DenseBase & A, + const Eigen::MatrixBase & A, Eigen::PlainObjectBase & C); } diff --git a/include/igl/unique_rows.cpp b/include/igl/unique_rows.cpp index 47910af77..93096ddab 100644 --- a/include/igl/unique_rows.cpp +++ b/include/igl/unique_rows.cpp @@ -107,6 +107,7 @@ template void igl::unique_rows,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix >(Eigen::DenseBase > const&,Eigen::PlainObjectBase >&,Eigen::PlainObjectBase >&,Eigen::PlainObjectBase >&); template void igl::unique_rows,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix >(Eigen::DenseBase > const&,Eigen::PlainObjectBase >&,Eigen::PlainObjectBase >&,Eigen::PlainObjectBase >&); template void igl::unique_rows,Eigen::Matrix,Eigen::Matrix,Eigen::Matrix >(Eigen::DenseBase > const&,Eigen::PlainObjectBase >&,Eigen::PlainObjectBase >&,Eigen::PlainObjectBase >&); +template void igl::unique_rows, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::DenseBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #ifdef WIN32 template void igl::unique_rows, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> >(class Eigen::DenseBase > const &, class Eigen::PlainObjectBase > &, class Eigen::PlainObjectBase > &, class Eigen::PlainObjectBase > &); template void igl::unique_rows,class Eigen::Matrix,class Eigen::Matrix<__int64,-1,1,0,-1,1>,class Eigen::Matrix<__int64,-1,1,0,-1,1> >(class Eigen::DenseBase > const &,class Eigen::PlainObjectBase > &,class Eigen::PlainObjectBase > &,class Eigen::PlainObjectBase > &); diff --git a/include/igl/unique_simplices.cpp b/include/igl/unique_simplices.cpp index 463459866..f732142b1 100644 --- a/include/igl/unique_simplices.cpp +++ b/include/igl/unique_simplices.cpp @@ -58,6 +58,7 @@ template void igl::unique_simplices, Eigen:: template void igl::unique_simplices, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::unique_simplices, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::unique_simplices, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::unique_simplices, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #ifdef WIN32 template void igl::unique_simplices, class Eigen::Matrix, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1>, class Eigen::Matrix<__int64, -1, 1, 0, -1, 1> >(class Eigen::MatrixBase > const &, class Eigen::PlainObjectBase > &, class Eigen::PlainObjectBase > &, class Eigen::PlainObjectBase > &); #endif diff --git a/include/igl/unproject.cpp b/include/igl/unproject.cpp index 702d77fee..60fc73fe5 100644 --- a/include/igl/unproject.cpp +++ b/include/igl/unproject.cpp @@ -38,13 +38,13 @@ IGL_INLINE void igl::unproject( for(int i = 0;i Inverse = + Eigen::Matrix Inverse = (proj.template cast() * model.template cast()).inverse(); Eigen::Matrix tmp; tmp << win.row(i).head(3).transpose(), 1; - tmp(0) = (tmp(0) - viewport(0)) / viewport(2); - tmp(1) = (tmp(1) - viewport(1)) / viewport(3); + tmp(0) = (tmp(0) - viewport(0, 0)) / viewport(2, 0); + tmp(1) = (tmp(1) - viewport(1, 0)) / viewport(3, 0); tmp = tmp.array() * 2.0f - 1.0f; Eigen::Matrix obj = Inverse * tmp; @@ -71,4 +71,5 @@ template Eigen::Matrix igl::unproject(Eigen::Matrix template Eigen::Matrix igl::unproject(Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&); template void igl::unproject, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); template void igl::unproject, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::unproject, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/unproject.h b/include/igl/unproject.h index f34e87513..72b4808cf 100644 --- a/include/igl/unproject.h +++ b/include/igl/unproject.h @@ -20,6 +20,10 @@ namespace igl // viewport 4-long viewport vector // Outputs: // scene #P by 3 or 3-vector (#P=1) the unprojected x, y, and z coordinates + // + // Known issue: + // The compiler will not complain if V and P are Vector3d, but the result + // will be incorrect. template < typename Derivedwin, typename Derivedmodel, diff --git a/include/igl/unproject_in_mesh.cpp b/include/igl/unproject_in_mesh.cpp index 6238aaf2a..a16e0b6a1 100644 --- a/include/igl/unproject_in_mesh.cpp +++ b/include/igl/unproject_in_mesh.cpp @@ -59,8 +59,8 @@ template < typename DerivedV, typename DerivedF, typename Derivedobj> const Eigen::Matrix4f& model, const Eigen::Matrix4f& proj, const Eigen::Vector4f& viewport, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & obj, std::vector & hits) { @@ -82,16 +82,19 @@ template < typename DerivedV, typename DerivedF, typename Derivedobj> const Eigen::Matrix4f& model, const Eigen::Matrix4f& proj, const Eigen::Vector4f& viewport, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & obj) { std::vector hits; return unproject_in_mesh(pos,model,proj,viewport,V,F,obj,hits); } #ifdef IGL_STATIC_LIBRARY +// Explicit template instantiation +// generated by autoexplicit.sh +template int igl::unproject_in_mesh, Eigen::Matrix, Eigen::Matrix >(Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, std::vector >&); template int igl::unproject_in_mesh >(Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, std::function const&, Eigen::Matrix const&, std::vector >&)> const&, Eigen::PlainObjectBase >&, std::vector >&); template int igl::unproject_in_mesh >(Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, std::function const&, Eigen::Matrix const&, std::vector >&)> const&, Eigen::PlainObjectBase >&, std::vector >&); template int igl::unproject_in_mesh >(Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, std::function const&, Eigen::Matrix const&, std::vector >&)> const&, Eigen::PlainObjectBase >&, std::vector >&); -template int igl::unproject_in_mesh, Eigen::Matrix, Eigen::Matrix >(Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&); +template int igl::unproject_in_mesh, Eigen::Matrix, Eigen::Matrix >(Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/unproject_in_mesh.h b/include/igl/unproject_in_mesh.h index edb1a0e65..02c392004 100644 --- a/include/igl/unproject_in_mesh.h +++ b/include/igl/unproject_in_mesh.h @@ -39,8 +39,8 @@ namespace igl const Eigen::Matrix4f& model, const Eigen::Matrix4f& proj, const Eigen::Vector4f& viewport, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & obj, std::vector & hits); // @@ -77,8 +77,8 @@ namespace igl const Eigen::Matrix4f& model, const Eigen::Matrix4f& proj, const Eigen::Vector4f& viewport, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, Eigen::PlainObjectBase & obj); } #ifndef IGL_STATIC_LIBRARY diff --git a/include/igl/unproject_on_line.cpp b/include/igl/unproject_on_line.cpp new file mode 100644 index 000000000..37a952c8b --- /dev/null +++ b/include/igl/unproject_on_line.cpp @@ -0,0 +1,63 @@ +#include "unproject_on_line.h" +#include "projection_constraint.h" + +template < + typename DerivedUV, + typename DerivedM, + typename DerivedVP, + typename Derivedorigin, + typename Deriveddir> +void igl::unproject_on_line( + const Eigen::MatrixBase & UV, + const Eigen::MatrixBase & M, + const Eigen::MatrixBase & VP, + const Eigen::MatrixBase & origin, + const Eigen::MatrixBase & dir, + typename DerivedUV::Scalar & t) +{ + using namespace Eigen; + typedef typename DerivedUV::Scalar Scalar; + Matrix A; + Matrix B; + projection_constraint(UV,M,VP,A,B); + // min_z,t ‖Az - B‖² subject to z = origin + t*dir + // min_t ‖A(origin + t*dir) - B‖² + // min_t ‖A*t*dir + A*origin - B‖² + // min_t ‖D*t + C‖² + // t = -(D'D)\(D'*C) + Matrix C = A*origin.template cast() - B; + Matrix D = A*dir.template cast(); + // Solve least squares system directly + const Matrix t_mat = D.jacobiSvd(ComputeFullU | ComputeFullV).solve(-C); + t = t_mat(0,0); +} + +template < + typename DerivedUV, + typename DerivedM, + typename DerivedVP, + typename Derivedorigin, + typename Deriveddir, + typename DerivedZ> +void igl::unproject_on_line( + const Eigen::MatrixBase & UV, + const Eigen::MatrixBase & M, + const Eigen::MatrixBase & VP, + const Eigen::MatrixBase & origin, + const Eigen::MatrixBase & dir, + Eigen::PlainObjectBase & Z) +{ + typedef typename DerivedZ::Scalar Scalar; + typename DerivedUV::Scalar t; + unproject_on_line(UV,M,VP,origin,dir,t); + Z = origin + dir*Scalar(t); +} + +#ifdef IGL_STATIC_LIBRARY +// Explicit template instantiation +// generated by autoexplicit.sh +template void igl::unproject_on_line, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh +template void igl::unproject_on_line, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +template void igl::unproject_on_line, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::Matrix::Scalar&); +#endif diff --git a/include/igl/unproject_on_line.h b/include/igl/unproject_on_line.h new file mode 100644 index 000000000..9dbb39eb0 --- /dev/null +++ b/include/igl/unproject_on_line.h @@ -0,0 +1,56 @@ +#ifndef IGL_UNPROJECT_ON_LINE_H +#define IGL_UNPROJECT_ON_LINE_H + +#include + +namespace igl +{ + // Given a screen space point (u,v) and the current projection matrix (e.g. + // gl_proj * gl_modelview) and viewport, _unproject_ the point into the scene + // so that it lies on given line (origin and dir) and projects as closely as + // possible to the given screen space point. + // + // Inputs: + // UV 2-long uv-coordinates of screen space point + // M 4 by 4 projection matrix + // VP 4-long viewport: (corner_u, corner_v, width, height) + // origin point on line + // dir vector parallel to line + // Output: + // t line parameter so that closest poin on line to viewer ray through UV + // lies at origin+t*dir + template < + typename DerivedUV, + typename DerivedM, + typename DerivedVP, + typename Derivedorigin, + typename Deriveddir> + void unproject_on_line( + const Eigen::MatrixBase & UV, + const Eigen::MatrixBase & M, + const Eigen::MatrixBase & VP, + const Eigen::MatrixBase & origin, + const Eigen::MatrixBase & dir, + typename DerivedUV::Scalar & t); + // Z 3d position of closest point on line to viewing ray through UV + template < + typename DerivedUV, + typename DerivedM, + typename DerivedVP, + typename Derivedorigin, + typename Deriveddir, + typename DerivedZ> + void unproject_on_line( + const Eigen::MatrixBase & UV, + const Eigen::MatrixBase & M, + const Eigen::MatrixBase & VP, + const Eigen::MatrixBase & origin, + const Eigen::MatrixBase & dir, + Eigen::PlainObjectBase & Z); +} + +#ifndef IGL_STATIC_LIBRARY +# include "unproject_on_line.cpp" +#endif + +#endif diff --git a/include/igl/unproject_on_plane.cpp b/include/igl/unproject_on_plane.cpp new file mode 100644 index 000000000..a5b935404 --- /dev/null +++ b/include/igl/unproject_on_plane.cpp @@ -0,0 +1,36 @@ +#include "unproject_on_plane.h" +#include "projection_constraint.h" +#include + +template < + typename DerivedUV, + typename DerivedM, + typename DerivedVP, + typename DerivedP, + typename DerivedZ> +void igl::unproject_on_plane( + const Eigen::MatrixBase & UV, + const Eigen::MatrixBase & M, + const Eigen::MatrixBase & VP, + const Eigen::MatrixBase & P, + Eigen::PlainObjectBase & Z) +{ + using namespace Eigen; + typedef typename DerivedZ::Scalar Scalar; + Matrix A; + Matrix B; + projection_constraint(UV,M,VP,A,B); + Matrix AA; + AA.topRows(2) = A.template cast(); + AA.row(2) = P.head(3).template cast(); + Matrix BB; + BB.head(2) = B.template cast(); + BB(2) = -P(3); + Z = AA.fullPivHouseholderQr().solve(BB); +} + +#ifdef IGL_STATIC_LIBRARY +// Explicit template instantiation +// generated by autoexplicit.sh +template void igl::unproject_on_plane, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); +#endif diff --git a/include/igl/unproject_on_plane.h b/include/igl/unproject_on_plane.h new file mode 100644 index 000000000..edc8ba4c5 --- /dev/null +++ b/include/igl/unproject_on_plane.h @@ -0,0 +1,37 @@ +#ifndef IGL_UNPROJECT_ON_PLANE_H +#define IGL_UNPROJECT_ON_PLANE_H + +#include + +namespace igl +{ + // Given a screen space point (u,v) and the current projection matrix (e.g. + // gl_proj * gl_modelview) and viewport, _unproject_ the point into the scene + // so that it lies on given plane. + // + // Inputs: + // UV 2-long uv-coordinates of screen space point + // M 4 by 4 projection matrix + // VP 4-long viewport: (corner_u, corner_v, width, height) + // P 4-long plane equation coefficients: P*(X 1) = 0 + // Outputs: + // Z 3-long world coordinate + template < + typename DerivedUV, + typename DerivedM, + typename DerivedVP, + typename DerivedP, + typename DerivedZ> + void unproject_on_plane( + const Eigen::MatrixBase & UV, + const Eigen::MatrixBase & M, + const Eigen::MatrixBase & VP, + const Eigen::MatrixBase & P, + Eigen::PlainObjectBase & Z); +} + +#ifndef IGL_STATIC_LIBRARY +# include "unproject_on_plane.cpp" +#endif + +#endif diff --git a/include/igl/unproject_onto_mesh.cpp b/include/igl/unproject_onto_mesh.cpp index 897d206c1..dda7e6ae1 100644 --- a/include/igl/unproject_onto_mesh.cpp +++ b/include/igl/unproject_onto_mesh.cpp @@ -17,8 +17,8 @@ IGL_INLINE bool igl::unproject_onto_mesh( const Eigen::Matrix4f& model, const Eigen::Matrix4f& proj, const Eigen::Vector4f& viewport, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, int & fid, Eigen::PlainObjectBase & bc) { @@ -64,7 +64,7 @@ IGL_INLINE bool igl::unproject_onto_mesh( { return false; } - bc.resize(3); + bc.resize(3, 1); bc << 1.0-hit.u-hit.v, hit.u, hit.v; fid = hit.id; return true; @@ -72,7 +72,8 @@ IGL_INLINE bool igl::unproject_onto_mesh( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template bool igl::unproject_onto_mesh, Eigen::Matrix, Eigen::Matrix >(Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, int&, Eigen::PlainObjectBase >&); -template bool igl::unproject_onto_mesh, Eigen::Matrix, Eigen::Matrix >(Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, int&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh +template bool igl::unproject_onto_mesh, Eigen::Matrix, Eigen::Matrix >(Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int&, Eigen::PlainObjectBase >&); +template bool igl::unproject_onto_mesh, Eigen::Matrix, Eigen::Matrix >(Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int&, Eigen::PlainObjectBase >&); +template bool igl::unproject_onto_mesh, Eigen::Matrix, Eigen::Matrix >(Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::Matrix const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, int&, Eigen::PlainObjectBase >&); #endif - diff --git a/include/igl/unproject_onto_mesh.h b/include/igl/unproject_onto_mesh.h index 57252f99b..07d947ef8 100644 --- a/include/igl/unproject_onto_mesh.h +++ b/include/igl/unproject_onto_mesh.h @@ -35,8 +35,8 @@ namespace igl const Eigen::Matrix4f& model, const Eigen::Matrix4f& proj, const Eigen::Vector4f& viewport, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, int & fid, Eigen::PlainObjectBase & bc); // diff --git a/include/igl/unproject_ray.cpp b/include/igl/unproject_ray.cpp index f6eb7ebdd..07bc84f6e 100644 --- a/include/igl/unproject_ray.cpp +++ b/include/igl/unproject_ray.cpp @@ -16,10 +16,10 @@ template < typename Deriveds, typename Deriveddir> IGL_INLINE void igl::unproject_ray( - const Eigen::PlainObjectBase & pos, - const Eigen::PlainObjectBase & model, - const Eigen::PlainObjectBase & proj, - const Eigen::PlainObjectBase & viewport, + const Eigen::MatrixBase & pos, + const Eigen::MatrixBase & model, + const Eigen::MatrixBase & proj, + const Eigen::MatrixBase & viewport, Eigen::PlainObjectBase & s, Eigen::PlainObjectBase & dir) { @@ -27,8 +27,8 @@ IGL_INLINE void igl::unproject_ray( using namespace Eigen; // Source and direction on screen typedef Eigen::Matrix Vec3; - Vec3 win_s(pos(0),pos(1),0); - Vec3 win_d(pos(0),pos(1),1); + Vec3 win_s(pos(0, 0),pos(1, 0),0); + Vec3 win_d(pos(0, 0),pos(1, 0),1); // Source, destination and direction in world Vec3 d; igl::unproject(win_s,model,proj,viewport,s); @@ -37,5 +37,5 @@ IGL_INLINE void igl::unproject_ray( } #ifdef IGL_STATIC_LIBRARY -template void igl::unproject_ray, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::unproject_ray, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/unproject_ray.h b/include/igl/unproject_ray.h index 4ef66f266..2bca6151c 100644 --- a/include/igl/unproject_ray.h +++ b/include/igl/unproject_ray.h @@ -31,10 +31,10 @@ namespace igl typename Deriveds, typename Deriveddir> IGL_INLINE void unproject_ray( - const Eigen::PlainObjectBase & pos, - const Eigen::PlainObjectBase & model, - const Eigen::PlainObjectBase & proj, - const Eigen::PlainObjectBase & viewport, + const Eigen::MatrixBase & pos, + const Eigen::MatrixBase & model, + const Eigen::MatrixBase & proj, + const Eigen::MatrixBase & viewport, Eigen::PlainObjectBase & s, Eigen::PlainObjectBase & dir); } diff --git a/include/igl/upsample.cpp b/include/igl/upsample.cpp index 8b5e3da24..483b814f7 100644 --- a/include/igl/upsample.cpp +++ b/include/igl/upsample.cpp @@ -16,7 +16,7 @@ template < typename DerivedNF> IGL_INLINE void igl::upsample( const int n_verts, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& F, Eigen::SparseMatrix& S, Eigen::PlainObjectBase& NF) { @@ -84,10 +84,10 @@ IGL_INLINE void igl::upsample( NF.resize(F.rows()*4,3); for(int i=0; i VI(6); VI << F(i,0), F(i,1), F(i,2), NI(i,0) + n_odd, NI(i,1) + n_odd, NI(i,2) + n_odd; - VectorXi f0(3), f1(3), f2(3), f3(3); + Eigen::Matrix f0(3), f1(3), f2(3), f3(3); f0 << VI(0), VI(3), VI(5); f1 << VI(1), VI(4), VI(3); f2 << VI(3), VI(4), VI(5); @@ -106,15 +106,15 @@ template < typename DerivedNV, typename DerivedNF> IGL_INLINE void igl::upsample( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, Eigen::PlainObjectBase& NV, Eigen::PlainObjectBase& NF, const int number_of_subdivs) { NV = V; NF = F; - for(int i=0; iS; @@ -139,7 +139,7 @@ IGL_INLINE void igl::upsample( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::upsample, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, int); -template void igl::upsample, double, Eigen::Matrix >(int, Eigen::PlainObjectBase > const&, Eigen::SparseMatrix&, Eigen::PlainObjectBase >&); +template void igl::upsample, Eigen::Matrix, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&, int); +template void igl::upsample, double, Eigen::Matrix >(int, Eigen::MatrixBase > const&, Eigen::SparseMatrix&, Eigen::PlainObjectBase >&); template void igl::upsample, Eigen::Matrix >(Eigen::Matrix&, Eigen::Matrix&, int); #endif diff --git a/include/igl/upsample.h b/include/igl/upsample.h index 51608aef6..588f3c5ba 100644 --- a/include/igl/upsample.h +++ b/include/igl/upsample.h @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2013 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_UPSAMPLE_H #define IGL_UPSAMPLE_H @@ -32,12 +32,12 @@ namespace igl typename DerivedNF> IGL_INLINE void upsample( const int n_verts, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& F, Eigen::SparseMatrix& S, Eigen::PlainObjectBase& NF); // Subdivide a mesh without moving vertices: loop subdivision but odd // vertices stay put and even vertices are just edge midpoints - // + // // Templates: // MatV matrix for vertex positions, e.g. MatrixXd // MatF matrix for vertex positions, e.g. MatrixXi @@ -54,20 +54,20 @@ namespace igl // Known issues: // - assumes (V,F) is edge-manifold. template < - typename DerivedV, + typename DerivedV, typename DerivedF, typename DerivedNV, typename DerivedNF> IGL_INLINE void upsample( - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, Eigen::PlainObjectBase& NV, Eigen::PlainObjectBase& NF, const int number_of_subdivs = 1); // Virtually in place wrapper template < - typename MatV, + typename MatV, typename MatF> IGL_INLINE void upsample( MatV& V, diff --git a/include/igl/vector_area_matrix.cpp b/include/igl/vector_area_matrix.cpp index 5438aa9dd..6bafb8871 100644 --- a/include/igl/vector_area_matrix.cpp +++ b/include/igl/vector_area_matrix.cpp @@ -15,7 +15,7 @@ template IGL_INLINE void igl::vector_area_matrix( - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & F, Eigen::SparseMatrix& A) { using namespace Eigen; @@ -48,5 +48,5 @@ IGL_INLINE void igl::vector_area_matrix( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation -template void igl::vector_area_matrix, double>(Eigen::PlainObjectBase > const&, Eigen::SparseMatrix&); +template void igl::vector_area_matrix, double>(Eigen::MatrixBase > const&, Eigen::SparseMatrix&); #endif diff --git a/include/igl/vector_area_matrix.h b/include/igl/vector_area_matrix.h index 6d385329c..4a42ea5af 100644 --- a/include/igl/vector_area_matrix.h +++ b/include/igl/vector_area_matrix.h @@ -30,7 +30,7 @@ namespace igl // template IGL_INLINE void vector_area_matrix( - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & F, Eigen::SparseMatrix& A); } diff --git a/include/igl/vertex_components.cpp b/include/igl/vertex_components.cpp index b08b17491..44d41cf17 100644 --- a/include/igl/vertex_components.cpp +++ b/include/igl/vertex_components.cpp @@ -10,9 +10,9 @@ #include #include -template +template IGL_INLINE void igl::vertex_components( - const Eigen::SparseMatrix & A, + const Eigen::SparseCompressedBase & A, Eigen::PlainObjectBase & C, Eigen::PlainObjectBase & counts) { @@ -46,7 +46,7 @@ IGL_INLINE void igl::vertex_components( C(f,0) = id; vcounts[id]++; // Iterate over inside - for(typename SparseMatrix::InnerIterator it (A,f); it; ++it) + for(typename DerivedA::InnerIterator it (A,f); it; ++it) { const int g = it.index(); if(!seen(g) && it.value()) @@ -67,9 +67,9 @@ IGL_INLINE void igl::vertex_components( } } -template +template IGL_INLINE void igl::vertex_components( - const Eigen::SparseMatrix & A, + const Eigen::SparseCompressedBase & A, Eigen::PlainObjectBase & C) { Eigen::VectorXi counts; @@ -89,10 +89,10 @@ IGL_INLINE void igl::vertex_components( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh -template void igl::vertex_components >(Eigen::SparseMatrix const&, Eigen::PlainObjectBase >&); +template void igl::vertex_components, Eigen::Array >(Eigen::SparseCompressedBase> const&, Eigen::PlainObjectBase >&); template void igl::vertex_components, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); -template void igl::vertex_components >(Eigen::SparseMatrix const&, Eigen::PlainObjectBase >&); -template void igl::vertex_components >(Eigen::SparseMatrix const&, Eigen::PlainObjectBase >&); -template void igl::vertex_components, Eigen::Matrix >(Eigen::SparseMatrix const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +template void igl::vertex_components, Eigen::Matrix >(Eigen::SparseCompressedBase> const&, Eigen::PlainObjectBase >&); +template void igl::vertex_components, Eigen::Matrix >(Eigen::SparseCompressedBase> const&, Eigen::PlainObjectBase >&); +template void igl::vertex_components, Eigen::Matrix, Eigen::Matrix >(Eigen::SparseCompressedBase> const&, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::vertex_components, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); #endif diff --git a/include/igl/vertex_components.h b/include/igl/vertex_components.h index 376e60c56..f744fa8b4 100644 --- a/include/igl/vertex_components.h +++ b/include/igl/vertex_components.h @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2015 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #ifndef IGL_COMPONENTS_H #define IGL_COMPONENTS_H @@ -23,15 +23,15 @@ namespace igl // C n list of component ids (starting with 0) // counts #components list of counts for each component // - template + template IGL_INLINE void vertex_components( - const Eigen::SparseMatrix & A, + const Eigen::SparseCompressedBase & A, Eigen::PlainObjectBase & C, Eigen::PlainObjectBase & counts); - template + template IGL_INLINE void vertex_components( - const Eigen::SparseMatrix & A, + const Eigen::SparseCompressedBase & A, Eigen::PlainObjectBase & C); // Compute the connected components for a mesh given its faces. diff --git a/include/igl/vertex_triangle_adjacency.cpp b/include/igl/vertex_triangle_adjacency.cpp index 864f9eb19..1c3208982 100644 --- a/include/igl/vertex_triangle_adjacency.cpp +++ b/include/igl/vertex_triangle_adjacency.cpp @@ -70,7 +70,7 @@ IGL_INLINE void igl::vertex_triangle_adjacency( // vfd now acts as a counter vfd = NI; - VF.derived()= Eigen::VectorXi(3*F.rows()); + VF.derived()= Eigen::Matrix(3*F.rows(), 1); for (int i = 0; i < F.rows(); i++) { for (int j = 0; j < 3; j++) diff --git a/include/igl/volume.cpp b/include/igl/volume.cpp index d1e5e077d..d44f25fc2 100644 --- a/include/igl/volume.cpp +++ b/include/igl/volume.cpp @@ -47,7 +47,7 @@ IGL_INLINE void igl::volume( const auto & AmD = A-D; const auto & BmD = B-D; const auto & CmD = C-D; - DerivedA BmDxCmD; + Eigen::Matrix BmDxCmD; cross(BmD.eval(),CmD.eval(),BmDxCmD); const auto & AmDdx = (AmD.array() * BmDxCmD.array()).rowwise().sum(); vol = -AmDdx/6.; @@ -109,6 +109,8 @@ IGL_INLINE void igl::volume( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation +// generated by autoexplicit.sh +template void igl::volume, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&); // Nonsense template namespace igl{ template<> void volume, Eigen::Matrix, Eigen::Matrix >(Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::PlainObjectBase >&){} } // generated by autoexplicit.sh diff --git a/include/igl/volume.h b/include/igl/volume.h index 2dee7cc95..960d95f41 100644 --- a/include/igl/volume.h +++ b/include/igl/volume.h @@ -20,7 +20,7 @@ namespace igl // V #V by dim list of vertex positions // T #V by 4 list of tet indices // Outputs: - // vol #T list of dihedral angles (in radians) + // vol #T list of tetrahedron volumes // template < typename DerivedV, diff --git a/include/igl/voxel_grid.cpp b/include/igl/voxel_grid.cpp index 388e58af4..15b4cfb44 100644 --- a/include/igl/voxel_grid.cpp +++ b/include/igl/voxel_grid.cpp @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2016 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "voxel_grid.h" #include "grid.h" @@ -13,7 +13,7 @@ template < typename DerivedGV, typename Derivedside> IGL_INLINE void igl::voxel_grid( - const Eigen::AlignedBox & box, + const Eigen::AlignedBox & box, const int in_s, const int pad_count, Eigen::PlainObjectBase & GV, @@ -22,6 +22,7 @@ IGL_INLINE void igl::voxel_grid( using namespace Eigen; using namespace std; typename DerivedGV::Index si = -1; + side.resize(1, 3); box.diagonal().maxCoeff(&si); //DerivedGV::Index si = 0; //assert(si>=0); @@ -45,7 +46,7 @@ IGL_INLINE void igl::voxel_grid( // A * (1-p/s) - A * p/s = max-min // A * (1-2p/s) = max-min // A = (max-min)/(1-2p/s) - const Array ps= + const Array ps= (Scalar)(pad_count)/(side.transpose().template cast().array()-1.); const Array A = box.diagonal().array()/(1.0-2.*ps); //// This would result in an "anamorphic", but perfectly fit grid: @@ -55,7 +56,7 @@ IGL_INLINE void igl::voxel_grid( // Instead scale by largest factor and move to match center typename Array::Index ai = -1; Scalar a = A.maxCoeff(&ai); - const Array ratio = + const Array ratio = a*(side.template cast().array()-1.0)/(Scalar)(side(ai)-1.0); GV.array().rowwise() *= ratio; const Eigen::Matrix offset = (box.center().transpose()-GV.colwise().mean()).eval(); @@ -65,6 +66,8 @@ IGL_INLINE void igl::voxel_grid( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh +template void igl::voxel_grid, Eigen::Matrix >(Eigen::AlignedBox const&, int, int, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); +// generated by autoexplicit.sh template void igl::voxel_grid, Eigen::Matrix >(Eigen::AlignedBox const&, int, int, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::voxel_grid, Eigen::Matrix >(Eigen::AlignedBox const&, int, int, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); template void igl::voxel_grid, Eigen::Matrix >(Eigen::AlignedBox const&, int, int, Eigen::PlainObjectBase >&, Eigen::PlainObjectBase >&); diff --git a/include/igl/writeDMAT.cpp b/include/igl/writeDMAT.cpp index 656dae693..24fdb97a7 100644 --- a/include/igl/writeDMAT.cpp +++ b/include/igl/writeDMAT.cpp @@ -84,6 +84,14 @@ IGL_INLINE bool igl::writeDMAT( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation +// generated by autoexplicit.sh +template bool igl::writeDMAT >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, bool); +// generated by autoexplicit.sh +template bool igl::writeDMAT >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, bool); +// generated by autoexplicit.sh +template bool igl::writeDMAT >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, bool); +// generated by autoexplicit.sh +template bool igl::writeDMAT >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, bool); template bool igl::writeDMAT >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, bool); template bool igl::writeDMAT >(std::string, Eigen::MatrixBase > const&, bool); template bool igl::writeDMAT >(std::string, Eigen::MatrixBase > const&, bool); diff --git a/include/igl/writeMESH.cpp b/include/igl/writeMESH.cpp index 27b0123cb..6b2e929ef 100644 --- a/include/igl/writeMESH.cpp +++ b/include/igl/writeMESH.cpp @@ -47,9 +47,9 @@ IGL_INLINE bool igl::writeMESH( template IGL_INLINE bool igl::writeMESH( const std::string str, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & T, - const Eigen::PlainObjectBase & F) + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & T, + const Eigen::MatrixBase & F) { using namespace std; using namespace Eigen; @@ -137,16 +137,16 @@ IGL_INLINE bool igl::writeMESH( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh -template bool igl::writeMESH, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); +template bool igl::writeMESH, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); // generated by autoexplicit.sh -template bool igl::writeMESH, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); +template bool igl::writeMESH, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); // generated by autoexplicit.sh -template bool igl::writeMESH, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); +template bool igl::writeMESH, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); // generated by autoexplicit.sh -template bool igl::writeMESH, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); +template bool igl::writeMESH, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); //template bool igl::writeMESH, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); -template bool igl::writeMESH, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); +template bool igl::writeMESH, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); -template bool igl::writeMESH, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); +template bool igl::writeMESH, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); template bool igl::writeMESH(std::basic_string, std::allocator >, std::vector >, std::allocator > > > const&, std::vector >, std::allocator > > > const&, std::vector >, std::allocator > > > const&); #endif diff --git a/include/igl/writeMESH.h b/include/igl/writeMESH.h index 4bb51418e..feae1f0ff 100644 --- a/include/igl/writeMESH.h +++ b/include/igl/writeMESH.h @@ -46,9 +46,9 @@ namespace igl template IGL_INLINE bool writeMESH( const std::string str, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & T, - const Eigen::PlainObjectBase & F); + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & T, + const Eigen::MatrixBase & F); } #ifndef IGL_STATIC_LIBRARY diff --git a/include/igl/writeOFF.cpp b/include/igl/writeOFF.cpp index 9222d76a0..c86508624 100644 --- a/include/igl/writeOFF.cpp +++ b/include/igl/writeOFF.cpp @@ -13,8 +13,8 @@ template IGL_INLINE bool igl::writeOFF( const std::string fname, - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F) + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F) { using namespace std; using namespace Eigen; @@ -37,9 +37,9 @@ IGL_INLINE bool igl::writeOFF( template IGL_INLINE bool igl::writeOFF( const std::string fname, - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, - const Eigen::PlainObjectBase& C) + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& C) { using namespace std; using namespace Eigen; @@ -63,7 +63,7 @@ IGL_INLINE bool igl::writeOFF( int rgbScale = (C.maxCoeff() <= 1.0)?255:1; // Use RGB_Array instead of RGB because of clash with mingw macro // (https://github.com/libigl/libigl/pull/679) - Eigen::MatrixXd RGB_Array = rgbScale * C; + Eigen::Matrix RGB_Array = rgbScale * C; s<< "COFF\n"<, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); +template bool igl::writeOFF, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); // generated by autoexplicit.sh -template bool igl::writeOFF, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); +template bool igl::writeOFF, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); // generated by autoexplicit.sh -template bool igl::writeOFF, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); -template bool igl::writeOFF, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); -template bool igl::writeOFF, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); -template bool igl::writeOFF, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); -template bool igl::writeOFF, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); -template bool igl::writeOFF, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); -template bool igl::writeOFF, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); -template bool igl::writeOFF, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); +template bool igl::writeOFF, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); +template bool igl::writeOFF, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); +template bool igl::writeOFF, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); +template bool igl::writeOFF, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); +template bool igl::writeOFF, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); +template bool igl::writeOFF, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); +template bool igl::writeOFF, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); +template bool igl::writeOFF, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); #endif diff --git a/include/igl/writeOFF.h b/include/igl/writeOFF.h index 754c18a53..a7312373d 100644 --- a/include/igl/writeOFF.h +++ b/include/igl/writeOFF.h @@ -32,15 +32,15 @@ namespace igl template IGL_INLINE bool writeOFF( const std::string str, - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, - const Eigen::PlainObjectBase& C); + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, + const Eigen::MatrixBase& C); template IGL_INLINE bool writeOFF( const std::string str, - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F); + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F); } #ifndef IGL_STATIC_LIBRARY diff --git a/include/igl/writeSTL.cpp b/include/igl/writeSTL.cpp index d95f2a8d7..52120d0d6 100644 --- a/include/igl/writeSTL.cpp +++ b/include/igl/writeSTL.cpp @@ -1,9 +1,9 @@ // This file is part of libigl, a simple c++ geometry processing library. -// +// // Copyright (C) 2014 Alec Jacobson -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can // obtain one at http://mozilla.org/MPL/2.0/. #include "writeSTL.h" #include @@ -11,9 +11,9 @@ template IGL_INLINE bool igl::writeSTL( const std::string & filename, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, - const Eigen::PlainObjectBase & N, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const Eigen::MatrixBase & N, const bool ascii) { using namespace std; @@ -101,21 +101,23 @@ IGL_INLINE bool igl::writeSTL( template IGL_INLINE bool igl::writeSTL( const std::string & filename, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, const bool ascii) { - return writeSTL(filename,V,F, DerivedV(), ascii); + return writeSTL(filename,V,F, Eigen::Matrix(), ascii); } #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh -template bool igl::writeSTL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, bool); +template bool igl::writeSTL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, bool); // generated by autoexplicit.sh -template bool igl::writeSTL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, bool); +template bool igl::writeSTL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, bool); // generated by autoexplicit.sh -template bool igl::writeSTL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, bool); -template bool igl::writeSTL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, bool); -template bool igl::writeSTL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, bool); +template bool igl::writeSTL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, bool); +// generated by autoexplicit.sh +template bool igl::writeSTL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, bool); +template bool igl::writeSTL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, bool); +template bool igl::writeSTL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, bool); #endif diff --git a/include/igl/writeSTL.h b/include/igl/writeSTL.h index 1ffd20281..adacc1b14 100644 --- a/include/igl/writeSTL.h +++ b/include/igl/writeSTL.h @@ -33,15 +33,15 @@ namespace igl template IGL_INLINE bool writeSTL( const std::string & filename, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, - const Eigen::PlainObjectBase & N, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const Eigen::MatrixBase & N, const bool ascii=true); template IGL_INLINE bool writeSTL( const std::string & filename, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, const bool ascii=true); } diff --git a/include/igl/writeWRL.cpp b/include/igl/writeWRL.cpp index 2740d1c2f..76dfb9088 100644 --- a/include/igl/writeWRL.cpp +++ b/include/igl/writeWRL.cpp @@ -11,8 +11,8 @@ template IGL_INLINE bool igl::writeWRL( const std::string & str, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F) + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F) { using namespace std; using namespace Eigen; @@ -57,9 +57,9 @@ ccw TRUE template IGL_INLINE bool igl::writeWRL( const std::string & str, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, - const Eigen::PlainObjectBase & C) + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const Eigen::MatrixBase & C) { using namespace std; using namespace Eigen; @@ -114,13 +114,13 @@ ccw TRUE #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh -template bool igl::writeWRL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); +template bool igl::writeWRL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); // generated by autoexplicit.sh -template bool igl::writeWRL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); +template bool igl::writeWRL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); // generated by autoexplicit.sh -template bool igl::writeWRL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); +template bool igl::writeWRL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); // generated by autoexplicit.sh -template bool igl::writeWRL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); -template bool igl::writeWRL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); -template bool igl::writeWRL, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&); +template bool igl::writeWRL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); +template bool igl::writeWRL, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); +template bool igl::writeWRL, Eigen::Matrix, Eigen::Matrix >(std::basic_string, std::allocator > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&); #endif diff --git a/include/igl/writeWRL.h b/include/igl/writeWRL.h index 5ff6a25ed..3b01c277f 100644 --- a/include/igl/writeWRL.h +++ b/include/igl/writeWRL.h @@ -22,8 +22,8 @@ namespace igl template IGL_INLINE bool writeWRL( const std::string & str, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F); + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F); // Write mesh to a .wrl file // @@ -36,9 +36,9 @@ namespace igl template IGL_INLINE bool writeWRL( const std::string & str, - const Eigen::PlainObjectBase & V, - const Eigen::PlainObjectBase & F, - const Eigen::PlainObjectBase & C); + const Eigen::MatrixBase & V, + const Eigen::MatrixBase & F, + const Eigen::MatrixBase & C); } #ifndef IGL_STATIC_LIBRARY #include "writeWRL.cpp" diff --git a/include/igl/write_triangle_mesh.cpp b/include/igl/write_triangle_mesh.cpp index 3699009f5..6fdcb4d77 100644 --- a/include/igl/write_triangle_mesh.cpp +++ b/include/igl/write_triangle_mesh.cpp @@ -19,8 +19,8 @@ template IGL_INLINE bool igl::write_triangle_mesh( const std::string str, - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, const bool force_ascii) { using namespace std; @@ -59,12 +59,12 @@ IGL_INLINE bool igl::write_triangle_mesh( #ifdef IGL_STATIC_LIBRARY // Explicit template instantiation // generated by autoexplicit.sh -template bool igl::write_triangle_mesh, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, bool); +template bool igl::write_triangle_mesh, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, bool); // generated by autoexplicit.sh -template bool igl::write_triangle_mesh, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, bool); +template bool igl::write_triangle_mesh, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, bool); // generated by autoexplicit.sh -template bool igl::write_triangle_mesh, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, bool); +template bool igl::write_triangle_mesh, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, bool); // generated by autoexplicit.sh -template bool igl::write_triangle_mesh, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, const bool); -template bool igl::write_triangle_mesh, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::PlainObjectBase > const&, Eigen::PlainObjectBase > const&, bool); +template bool igl::write_triangle_mesh, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, const bool); +template bool igl::write_triangle_mesh, Eigen::Matrix >(std::basic_string, std::allocator >, Eigen::MatrixBase > const&, Eigen::MatrixBase > const&, bool); #endif diff --git a/include/igl/write_triangle_mesh.h b/include/igl/write_triangle_mesh.h index 6a7241628..d5e83f8a3 100644 --- a/include/igl/write_triangle_mesh.h +++ b/include/igl/write_triangle_mesh.h @@ -15,8 +15,8 @@ namespace igl { // write mesh to a file with automatic detection of file format. supported: - // obj, off, stl, wrl, ply, mesh). - // + // obj, off, stl, wrl, ply, mesh). + // // Templates: // Scalar type for positions and vectors (will be read as double and cast // to Scalar) @@ -25,13 +25,13 @@ namespace igl // str path to file // V eigen double matrix #V by 3 // F eigen int matrix #F by 3 - // force_ascii force ascii format even if binary is available + // force_ascii force ascii format even if binary is available // Returns true iff success template IGL_INLINE bool write_triangle_mesh( const std::string str, - const Eigen::PlainObjectBase& V, - const Eigen::PlainObjectBase& F, + const Eigen::MatrixBase& V, + const Eigen::MatrixBase& F, const bool force_ascii = true); } diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt deleted file mode 100644 index 7a1477545..000000000 --- a/python/CMakeLists.txt +++ /dev/null @@ -1,165 +0,0 @@ -cmake_minimum_required(VERSION 2.8.12) -project(pyigl) - -### Adding libIGL: choose the path to your local copy libIGL -if(NOT TARGET igl::core) - ### Prefer header-only mode for compiling Python bindings - if(NOT LIBIGL_WITH_PYTHON OR NOT LIBIGL_USE_STATIC_LIBRARY) - message(FATAL_ERROR - "Trying to compile Python bindings without -DLIBIGL_WITH_PYTHON=ON. " - "Either enable manually all the necessary options, or compile from " - "the root folder with -DLIBIGL_USE_STATIC_LIBRARY=OFF") - endif() - list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/../cmake") - include(libigl) -endif() - -# Force a specific python version -# set(PYTHON_LIBRARIES "D:/Python34/libs/python34.lib") -# set(PYTHON_INCLUDE_DIR "D:/Python34/include") - -# Force a specific python version -# set(PYTHON_LIBRARIES "/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/lib/libpython3.5m.dylib") -# set(PYTHON_INCLUDE_DIR "/usr/local/Cellar/python3/3.5.0/Frameworks/Python.framework/Versions/3.5/include/python3.5m") - -set(Python_ADDITIONAL_VERSIONS 3.4 3.5 3.6 3.7) -find_package(PythonInterp 3.4 REQUIRED) -find_package(PythonLibs 3.4 REQUIRED) - -## libigl -if(NOT TARGET igl::core) - list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/../cmake") - include(libigl) -endif() - -string(TOUPPER "${CMAKE_BUILD_TYPE}" U_CMAKE_BUILD_TYPE) -if(UNIX) - if(NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -flto") - endif() -endif() - -## include pybind -set(PYBIND11_DIR ${PROJECT_SOURCE_DIR}/../external/pybind11 CACHE PATH "Path to pybind11") -add_subdirectory(${PYBIND11_DIR} pybind11) - -## Prepare the python library -pybind11_add_module(pyigl - python_shared.cpp - modules/py_vector.cpp - py_igl.cpp - py_doc.cpp -) - -## Add dependencies -target_link_libraries(pyigl PUBLIC igl::core) - -## Optional modules -if(LIBIGL_WITH_OPENGL_GLFW) - target_sources(pyigl PRIVATE "modules/py_igl_opengl_glfw.cpp") - target_compile_definitions(pyigl PUBLIC -DPY_GLFW) - target_link_libraries(pyigl PUBLIC igl::opengl igl::opengl_glfw) -endif() - -if(LIBIGL_WITH_COMISO) - target_sources(pyigl PRIVATE "modules/copyleft/py_igl_comiso.cpp") - target_compile_definitions(pyigl PUBLIC -DPY_COMISO) - target_link_libraries(pyigl PUBLIC igl::comiso) -endif() - -if(LIBIGL_WITH_TETGEN) - target_sources(pyigl PRIVATE "modules/copyleft/py_igl_tetgen.cpp") - target_compile_definitions(pyigl PUBLIC -DPY_TETGEN) - target_link_libraries(pyigl PUBLIC igl::tetgen) -endif() - -if(LIBIGL_WITH_EMBREE) - target_sources(pyigl PRIVATE "modules/py_igl_embree.cpp") - target_compile_definitions(pyigl PUBLIC -DPY_EMBREE) - target_link_libraries(pyigl PUBLIC igl::embree) -endif() - -if(LIBIGL_WITH_TRIANGLE) - target_sources(pyigl PRIVATE "modules/py_igl_triangle.cpp") - target_compile_definitions(pyigl PUBLIC -DPY_TRIANGLE) - target_link_libraries(pyigl PUBLIC igl::triangle) -endif() - -if(LIBIGL_WITH_CGAL) - target_sources(pyigl PRIVATE "modules/copyleft/py_igl_cgal.cpp") - target_compile_definitions(pyigl PUBLIC -DPY_CGAL) - target_link_libraries(pyigl PUBLIC igl::cgal) -endif() - -if(NOT LIBIGL_WITHOUT_COPYLEFT) - target_sources(pyigl PRIVATE "modules/copyleft/py_igl_copyleft.cpp") - target_compile_definitions(pyigl PUBLIC -DPY_COPYLEFT) -endif() - -if(LIBIGL_WITH_PNG) - target_sources(pyigl PRIVATE "modules/py_igl_png.cpp") - target_compile_definitions(pyigl PUBLIC -DPY_PNG) - target_link_libraries(pyigl PUBLIC igl::png) -endif() - -set_target_properties(pyigl PROPERTIES PREFIX "") -set_target_properties(pyigl PROPERTIES LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}) - -if(WIN32) - if(MSVC) - # Enforce size-based optimization and link time code generation on MSVC (~30% smaller binaries in experiments) - set_target_properties(pyigl PROPERTIES COMPILE_FLAGS "/Os /GL") - set_target_properties(pyigl PROPERTIES LINK_FLAGS "/LTCG") - endif() - - # .PYD file extension on Windows - set_target_properties(pyigl PROPERTIES SUFFIX ".pyd") - - # Link against the Python shared library - # message(FATAL_ERROR ${PYTHON_LIBRARY}) - # target_link_libraries(igl ${PYTHON_LIBRARY}) - target_link_libraries(pyigl PRIVATE ${PYTHON_LIBRARIES}) - -elseif(UNIX) - # It's quite common to have multiple copies of the same Python version - # installed on one's system. E.g.: one copy from the OS and another copy - # that's statically linked into an application like Blender or Maya. - # If we link our plugin library against the OS Python here and import it - # into Blender or Maya later on, this will cause segfaults when multiple - # conflicting Python instances are active at the same time. - - # Windows does not seem to be affected by this issue. The solution for Linux - # and Mac OS is simple: we just don't link against the Python library. The - # resulting shared library will have missing symbols, but that's perfectly - # fine -- they will be resolved at import time. - - # .SO file extension on Linux/Mac OS - set_target_properties(pyigl PROPERTIES SUFFIX ".so") - - # Enable flag if undefined symbols appear on pyigl module import to get notified about the missing symbols at link time - option(LIBIGL_CHECK_UNDEFINED "Check for undefined symbols" OFF) - - # Strip unnecessary sections of the binary on Linux/Mac OS - if(APPLE) - set_target_properties(pyigl PROPERTIES MACOSX_RPATH ".") - - if(NOT LIBIGL_CHECK_UNDEFINED) - set_target_properties(pyigl PROPERTIES LINK_FLAGS "-undefined dynamic_lookup -dead_strip") - endif() - - if(NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG) - add_custom_command(TARGET pyigl POST_BUILD COMMAND strip -u -r ${PROJECT_SOURCE_DIR}/pyigl.so) - endif() - else() - - if(LIBIGL_CHECK_UNDEFINED) - target_link_libraries(pyigl PRIVATE ${PYTHON_LIBRARIES}) - set_target_properties(pyigl PROPERTIES LINK_FLAGS "-Wl,--no-undefined") - endif() - - if(NOT ${U_CMAKE_BUILD_TYPE} MATCHES DEBUG) - add_custom_command(TARGET pyigl POST_BUILD COMMAND strip ${PROJECT_SOURCE_DIR}/pyigl.so) - endif() - endif() -endif() - diff --git a/python/iglhelpers.py b/python/iglhelpers.py deleted file mode 100644 index 0695bb533..000000000 --- a/python/iglhelpers.py +++ /dev/null @@ -1,64 +0,0 @@ -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import numpy as np -import scipy.sparse as sparse -import pyigl as igl - -def p2e(m): - if isinstance(m, np.ndarray): - if not (m.flags['C_CONTIGUOUS'] or m.flags['F_CONTIGUOUS']): - raise TypeError('p2e support either c-order or f-order') - if m.dtype.type in [np.int32, np.int64]: - return igl.eigen.MatrixXi(m.astype(np.int32)) - elif m.dtype.type in [np.float64, np.float32]: - return igl.eigen.MatrixXd(m.astype(np.float64)) - elif m.dtype.type == np.bool: - return igl.eigen.MatrixXb(m) - raise TypeError("p2e only support dtype float64/32, int64/32 and bool") - if sparse.issparse(m): - # convert in a dense matrix with triples - coo = m.tocoo() - triplets = np.vstack((coo.row, coo.col, coo.data)).T - - triples_eigen_wrapper = igl.eigen.MatrixXd(triplets) - - if m.dtype.type == np.int32: - t = igl.eigen.SparseMatrixi() - t.fromcoo(triples_eigen_wrapper) - return t - elif m.dtype.type == np.float64: - t = igl.eigen.SparseMatrixd() - t.fromCOO(triples_eigen_wrapper) - return t - - - raise TypeError("p2e only support numpy.array or scipy.sparse") - - -def e2p(m): - if isinstance(m, igl.eigen.MatrixXd): - return np.array(m, dtype='float64', order='C') - elif isinstance(m, igl.eigen.MatrixXi): - return np.array(m, dtype='int32', order='C') - elif isinstance(m, igl.eigen.MatrixXb): - return np.array(m, dtype='bool', order='C') - elif isinstance(m, igl.eigen.SparseMatrixd): - coo = np.array(m.toCOO()) - I = coo[:, 0] - J = coo[:, 1] - V = coo[:, 2] - return sparse.coo_matrix((V,(I,J)), shape=(m.rows(),m.cols()), dtype='float64') - elif isinstance(m, igl.eigen.SparseMatrixi): - coo = np.array(m.toCOO()) - I = coo[:, 0] - J = coo[:, 1] - V = coo[:, 2] - return sparse.coo_matrix((V,(I,J)), shape=(m.rows(),m.cols()), dtype='int32') - -def printMatrixSizes(x,xn): - print(xn + " (" + str(x.rows()) + "," + str(x.cols()) + ")") diff --git a/python/matlab/example1.m b/python/matlab/example1.m deleted file mode 100644 index ce66343f1..000000000 --- a/python/matlab/example1.m +++ /dev/null @@ -1,18 +0,0 @@ -%% Launch the external viewer -launch_viewer; - -%% Load a mesh in OFF format -V = py.igl.eigen.MatrixXd(); -F = py.igl.eigen.MatrixXi(); -py.igl.readOFF('../tutorial/shared/beetle.off', V, F); - -%% Scale the x coordinate in matlab -V = p2m(V); -V(:,1) = V(:,1) * 2; -V = m2p(V); - -%% Plot the mesh -viewer = py.tcpviewer_single.TCPViewer(); -viewer.data.set_mesh(V, F); -viewer.launch(); - diff --git a/python/matlab/example2.m b/python/matlab/example2.m deleted file mode 100644 index 5be77cf22..000000000 --- a/python/matlab/example2.m +++ /dev/null @@ -1,60 +0,0 @@ -% Launch the external viewer -launch_viewer; - -V = py.igl.eigen.MatrixXd(); -F = py.igl.eigen.MatrixXi(); -py.igl.read_triangle_mesh('../tutorial/shared/fertility.off', V, F); - -% Alternative discrete mean curvature -HN = py.igl.eigen.MatrixXd(); -L = py.igl.eigen.SparseMatrixd(); -M = py.igl.eigen.SparseMatrixd(); -Minv = py.igl.eigen.SparseMatrixd(); - - -py.igl.cotmatrix(V,F,L); -py.igl.massmatrix(V,F,py.igl.MASSMATRIX_TYPE_VORONOI,M); - -py.igl.invert_diag(M,Minv); - -% Laplace-Beltrami of position -HN = -Minv*(L*V); - -% Extract magnitude as mean curvature -H = HN.rowwiseNorm(); - -% Compute curvature directions via quadric fitting -PD1 = py.igl.eigen.MatrixXd(); -PD2 = py.igl.eigen.MatrixXd(); - -PV1 = py.igl.eigen.MatrixXd(); -PV2 = py.igl.eigen.MatrixXd(); - -py.igl.principal_curvature(V,F,PD1,PD2,PV1,PV2); - -% Mean curvature -H = 0.5*(PV1+PV2); - -viewer = py.tcpviewer_single.TCPViewer(); -viewer.data.set_mesh(V, F); - -% Compute pseudocolor -C = py.igl.eigen.MatrixXd(); -py.igl.parula(H,true,C); - -viewer.data.set_colors(C); - -% Average edge length for sizing -avg = py.igl.avg_edge_length(V,F); - -% Draw a blue segment parallel to the minimal curvature direction -red = m2p([0.8,0.2,0.2]); -blue = m2p([0.2,0.2,0.8]); - -viewer.data.add_edges(V + PD1*avg, V - PD1*avg, blue); - -% Draw a red segment parallel to the maximal curvature direction -viewer.data.add_edges(V + PD2*avg, V - PD2*avg, red); - -% Plot -viewer.launch() diff --git a/python/matlab/launch_viewer.m b/python/matlab/launch_viewer.m deleted file mode 100644 index b76e1e176..000000000 --- a/python/matlab/launch_viewer.m +++ /dev/null @@ -1,3 +0,0 @@ -system('python tcpviewer_single.py&'); - -pause(0.1) % Wait a bit for the viewer to start \ No newline at end of file diff --git a/python/matlab/m2p.m b/python/matlab/m2p.m deleted file mode 100644 index e76548533..000000000 --- a/python/matlab/m2p.m +++ /dev/null @@ -1,19 +0,0 @@ -% Converts a Matlab matrix to a python-wrapped Eigen Matrix -function [ P ] = m2p( M ) - if (isa(M, 'double')) - % Convert the matrix to a python 1D array - a = py.array.array('d',reshape(M,1,numel(M))); - % Then convert it to a eigen type - t = py.igl.eigen.MatrixXd(a.tolist()); - % Finally reshape it back - P = t.MapMatrix(uint16(size(M,1)),uint16(size(M,2))); - elseif (isa(M, 'integer')) - % Convert the matrix to a python 1D array - a = py.array.array('i',reshape(M,1,numel(M))); - % Then convert it to a eigen type - t = py.igl.eigen.MatrixXi(a.tolist()); - % Finally reshape it back - P = t.MapMatrix(uint16(size(M,1)),uint16(size(M,2))); - else - error('Unsupported numerical type.'); - end diff --git a/python/matlab/p2m.m b/python/matlab/p2m.m deleted file mode 100644 index bfaf79f15..000000000 --- a/python/matlab/p2m.m +++ /dev/null @@ -1,17 +0,0 @@ -% Converts a python-wrapped Eigen Matrix to a Matlab matrix -function [ M ] = p2m( P ) - if py.repr(py.type(P)) == '' - % Convert it to a python array first - t = py.array.array('d',P); - % Reshape it - M = reshape(double(t),P.rows(),P.cols()); - elseif py.repr(py.type(P)) == '' - % Convert it to a python array first - t = py.array.array('i',P); - % Reshape it - M = reshape(int32(t),P.rows(),P.cols()); - else - error('Unsupported numerical type.'); - end -end - diff --git a/python/modules/copyleft/py_igl_cgal.cpp b/python/modules/copyleft/py_igl_cgal.cpp deleted file mode 100644 index 2ea3372dc..000000000 --- a/python/modules/copyleft/py_igl_cgal.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -//#include -//#include -//#include - - -#include "../../python_shared.h" - -#include -#include -#include - - -void python_export_igl_cgal(py::module &me) { - - py::module m = me.def_submodule( - "cgal", "Wrappers for libigl functions that use cgal"); - - #include "../../py_igl/copyleft/cgal/py_mesh_boolean.cpp" - #include "../../py_igl/copyleft/cgal/py_remesh_self_intersections.cpp" - #include "../../py_igl/copyleft/cgal/py_RemeshSelfIntersectionsParam.cpp" - -} diff --git a/python/modules/copyleft/py_igl_comiso.cpp b/python/modules/copyleft/py_igl_comiso.cpp deleted file mode 100644 index 59d331b52..000000000 --- a/python/modules/copyleft/py_igl_comiso.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -#include -#include -#include - - -#include "../../python_shared.h" - -#include -#include - -void python_export_igl_comiso(py::module &me) { - - py::module m = me.def_submodule( - "comiso", "Wrappers for libigl functions that use comiso"); - - #include "../../py_igl/copyleft/comiso/py_nrosy.cpp" - #include "../../py_igl/copyleft/comiso/py_miq.cpp" - -} diff --git a/python/modules/copyleft/py_igl_copyleft.cpp b/python/modules/copyleft/py_igl_copyleft.cpp deleted file mode 100644 index 8443a1482..000000000 --- a/python/modules/copyleft/py_igl_copyleft.cpp +++ /dev/null @@ -1,27 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -//#include -//#include -//#include - - -#include "../../python_shared.h" - -#include -#include - - -void python_export_igl_copyleft(py::module &me) { - - py::module m = me.def_submodule( - "copyleft", "Wrappers for libigl functions that are copyleft"); - - #include "../../py_igl/copyleft/py_marching_cubes.cpp" - #include "../../py_igl/copyleft/py_swept_volume.cpp" - -} diff --git a/python/modules/copyleft/py_igl_tetgen.cpp b/python/modules/copyleft/py_igl_tetgen.cpp deleted file mode 100644 index ac2dc3850..000000000 --- a/python/modules/copyleft/py_igl_tetgen.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -//#include -//#include -//#include - - -#include "../../python_shared.h" - -#include - - -void python_export_igl_tetgen(py::module &me) { - - py::module m = me.def_submodule( - "tetgen", "Wrappers for libigl functions that use tetgen"); - - #include "../../py_igl/copyleft/tetgen/py_tetrahedralize.cpp" - -} diff --git a/python/modules/py_igl_embree.cpp b/python/modules/py_igl_embree.cpp deleted file mode 100644 index 3b7fac76a..000000000 --- a/python/modules/py_igl_embree.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -//#include -//#include -//#include - - -#include "../python_shared.h" - -#include -#include -#include - - -void python_export_igl_embree(py::module &me) { - - py::module m = me.def_submodule( - "embree", "Wrappers for libigl functions that use embree"); - - #include "../py_igl/embree/py_ambient_occlusion.cpp" - #include "../py_igl/embree/py_reorient_facets_raycast.cpp" - #include "../py_igl/embree/py_line_mesh_intersection.cpp" - -} diff --git a/python/modules/py_igl_opengl_glfw.cpp b/python/modules/py_igl_opengl_glfw.cpp deleted file mode 100644 index 2f5a3fa70..000000000 --- a/python/modules/py_igl_opengl_glfw.cpp +++ /dev/null @@ -1,452 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -#include -#include - -#include "../python_shared.h" -#include -#include -#include -#include -#include -#ifdef IGL_VIEWER_WITH_NANOGUI -#include "../../../external/nanogui/include/nanogui/formhelper.h" -#include "../../../external/nanogui/include/nanogui/screen.h" -#endif - -void python_export_igl_glfw(py::module &m) -{ - - py::module me = m.def_submodule( - "glfw", "GLFW Mesh viewer"); - -/////////////////////// DATA - -py::class_ viewerdata_class(me, "ViewerData"); - -py::enum_(viewerdata_class, "DirtyFlags") - .value("DIRTY_NONE", igl::opengl::MeshGL::DIRTY_NONE) - .value("DIRTY_POSITION", igl::opengl::MeshGL::DIRTY_POSITION) - .value("DIRTY_UV", igl::opengl::MeshGL::DIRTY_UV) - .value("DIRTY_NORMAL", igl::opengl::MeshGL::DIRTY_NORMAL) - .value("DIRTY_AMBIENT", igl::opengl::MeshGL::DIRTY_AMBIENT) - .value("DIRTY_DIFFUSE", igl::opengl::MeshGL::DIRTY_DIFFUSE) - .value("DIRTY_SPECULAR", igl::opengl::MeshGL::DIRTY_SPECULAR) - .value("DIRTY_TEXTURE", igl::opengl::MeshGL::DIRTY_TEXTURE) - .value("DIRTY_FACE", igl::opengl::MeshGL::DIRTY_FACE) - .value("DIRTY_MESH", igl::opengl::MeshGL::DIRTY_MESH) - .value("DIRTY_OVERLAY_LINES", igl::opengl::MeshGL::DIRTY_OVERLAY_LINES) - .value("DIRTY_OVERLAY_POINTS", igl::opengl::MeshGL::DIRTY_OVERLAY_POINTS) - .value("DIRTY_ALL", igl::opengl::MeshGL::DIRTY_ALL) - .export_values(); - - - viewerdata_class - .def(py::init<>()) - .def("set_mesh", &igl::opengl::ViewerData::set_mesh) - .def("set_colors", &igl::opengl::ViewerData::set_colors) - .def("clear", &igl::opengl::ViewerData::clear) - .def("set_face_based", &igl::opengl::ViewerData::set_face_based) - - .def("set_vertices", &igl::opengl::ViewerData::set_vertices) - .def("set_normals", &igl::opengl::ViewerData::set_normals) - - .def("set_uv", - (void (igl::opengl::ViewerData::*) (const Eigen::MatrixXd &)) &igl::opengl::ViewerData::set_uv - ) - - .def("set_uv", - (void (igl::opengl::ViewerData::*) (const Eigen::MatrixXd &, const Eigen::MatrixXi&)) &igl::opengl::ViewerData::set_uv - ) - - .def("set_texture", - (void (igl::opengl::ViewerData::*) ( - const Eigen::Matrix&, - const Eigen::Matrix&, - const Eigen::Matrix&) - ) &igl::opengl::ViewerData::set_texture - ) - - .def("set_texture", - (void (igl::opengl::ViewerData::*) ( - const Eigen::Matrix&, - const Eigen::Matrix&, - const Eigen::Matrix&, - const Eigen::Matrix&) - ) &igl::opengl::ViewerData::set_texture - ) - - .def("set_points", &igl::opengl::ViewerData::set_points) - .def("add_points", &igl::opengl::ViewerData::add_points) - .def("set_edges", &igl::opengl::ViewerData::set_edges) - .def("add_edges", &igl::opengl::ViewerData::add_edges) - - .def("add_label", [] (igl::opengl::ViewerData& data, const Eigen::MatrixXd& P, const std::string& str) - { - assert_is_VectorX("P",P); - data.add_label(P,str); - }) - - .def("compute_normals", &igl::opengl::ViewerData::compute_normals) - - .def("uniform_colors", [] (igl::opengl::ViewerData& data, const Eigen::MatrixXd& ambient, const Eigen::MatrixXd& diffuse, const Eigen::MatrixXd& specular) - { - if (ambient.cols() == 3) - { - assert_is_Vector3("ambient",ambient); - assert_is_Vector3("diffuse",diffuse); - assert_is_Vector3("specular",specular); - Eigen::Vector3d vambient = ambient; - Eigen::Vector3d vdiffuse = diffuse; - Eigen::Vector3d vspecular = specular; - data.uniform_colors(vambient,vdiffuse, vspecular); - } - - if (ambient.cols() == 4) - { - assert_is_Vector4("ambient",ambient); - assert_is_Vector4("diffuse",diffuse); - assert_is_Vector4("specular",specular); - Eigen::Vector4d vambient = ambient; - Eigen::Vector4d vdiffuse = diffuse; - Eigen::Vector4d vspecular = specular; - data.uniform_colors(vambient,vdiffuse,vspecular); - } - - }) - - .def("grid_texture", &igl::opengl::ViewerData::grid_texture) - - .def_readwrite("V", &igl::opengl::ViewerData::V) - .def_readwrite("F", &igl::opengl::ViewerData::F) - - .def_readwrite("F_normals", &igl::opengl::ViewerData::F_normals) - .def_readwrite("F_material_ambient", &igl::opengl::ViewerData::F_material_ambient) - .def_readwrite("F_material_diffuse", &igl::opengl::ViewerData::F_material_diffuse) - .def_readwrite("F_material_specular", &igl::opengl::ViewerData::F_material_specular) - - .def_readwrite("V_normals", &igl::opengl::ViewerData::V_normals) - .def_readwrite("V_material_ambient", &igl::opengl::ViewerData::V_material_ambient) - .def_readwrite("V_material_diffuse", &igl::opengl::ViewerData::V_material_diffuse) - .def_readwrite("V_material_specular", &igl::opengl::ViewerData::V_material_specular) - - .def_readwrite("V_uv", &igl::opengl::ViewerData::V_uv) - .def_readwrite("F_uv", &igl::opengl::ViewerData::F_uv) - - .def_readwrite("texture_R", &igl::opengl::ViewerData::texture_R) - .def_readwrite("texture_G", &igl::opengl::ViewerData::texture_G) - .def_readwrite("texture_B", &igl::opengl::ViewerData::texture_B) - - .def_readwrite("lines", &igl::opengl::ViewerData::lines) - .def_readwrite("points", &igl::opengl::ViewerData::points) - .def_readwrite("labels_positions", &igl::opengl::ViewerData::labels_positions) - .def_readwrite("labels_strings", &igl::opengl::ViewerData::labels_strings) - // .def_readwrite("dirty", &igl::opengl::MeshGL::dirty) - .def_readwrite("face_based", &igl::opengl::ViewerData::face_based) - .def("serialize", [](igl::opengl::ViewerData& data) - { - std::vector a; - igl::serialize(data,"Data",a); - return a; - }) - - .def("deserialize", [](igl::opengl::ViewerData& data, const std::vector& a) - { - igl::deserialize(data,"Data",a); - return; - }) - - .def_readwrite("shininess",&igl::opengl::ViewerData::shininess) - - .def_property("line_color", - [](const igl::opengl::ViewerData& data) {return Eigen::MatrixXd(data.line_color.cast());}, - [](igl::opengl::ViewerData& data, const Eigen::MatrixXd& v) - { - assert_is_Vector4("line_color",v); - data.line_color = Eigen::Vector4f(v.cast()); - }) - - .def_readwrite("show_overlay",&igl::opengl::ViewerData::show_overlay) - .def_readwrite("show_overlay_depth",&igl::opengl::ViewerData::show_overlay_depth) - .def_readwrite("show_texture",&igl::opengl::ViewerData::show_texture) - .def_readwrite("show_faces",&igl::opengl::ViewerData::show_faces) - - .def_readwrite("show_lines",&igl::opengl::ViewerData::show_lines) - .def_readwrite("show_vertid",&igl::opengl::ViewerData::show_vertid) - .def_readwrite("show_faceid",&igl::opengl::ViewerData::show_faceid) - .def_readwrite("invert_normals",&igl::opengl::ViewerData::invert_normals) - - .def_readwrite("point_size",&igl::opengl::ViewerData::point_size) - .def_readwrite("line_width",&igl::opengl::ViewerData::line_width) - - ; - -//////////////////////// OPENGL_State - -// py::class_ opengl_state_class(me, "OpenGL_state"); - -// opengl_state_class -// .def(py::init<>()) -// .def("init", &igl::opengl::State::init) - -// ; - -//////////////////////// CORE - -py::class_ viewercore_class(me, "ViewerCore"); - - py::enum_(viewercore_class, "RotationType") - .value("ROTATION_TYPE_TRACKBALL", igl::opengl::ViewerCore::ROTATION_TYPE_TRACKBALL) - .value("ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP", igl::opengl::ViewerCore::ROTATION_TYPE_TWO_AXIS_VALUATOR_FIXED_UP) - .value("NUM_ROTATION_TYPES", igl::opengl::ViewerCore::NUM_ROTATION_TYPES) - .export_values(); - - viewercore_class - .def(py::init<>()) - //.def("align_camera_center", [](igl::opengl::ViewerCore& core, const Eigen::MatrixXd& V, const Eigen::MatrixXi& F){return core.align_camera_center(V,F);}) - .def("init", &igl::opengl::ViewerCore::init) - .def("shut", &igl::opengl::ViewerCore::shut) - //.def("InitSerialization", &igl::opengl::ViewerCore::InitSerialization) - .def("align_camera_center", - (void (igl::opengl::ViewerCore::*) (const Eigen::MatrixXd &, const Eigen::MatrixXi &)) &igl::opengl::ViewerCore::align_camera_center - ) - - .def("align_camera_center", - (void (igl::opengl::ViewerCore::*) (const Eigen::MatrixXd &)) &igl::opengl::ViewerCore::align_camera_center - ) - - .def("clear_framebuffers",&igl::opengl::ViewerCore::clear_framebuffers) - .def("draw",&igl::opengl::ViewerCore::draw) - .def("draw_buffer",&igl::opengl::ViewerCore::draw_buffer) - - .def_property("background_color", - [](const igl::opengl::ViewerCore& core) {return Eigen::MatrixXd(core.background_color.cast());}, - [](igl::opengl::ViewerCore& core, const Eigen::MatrixXd& v) - { - assert_is_Vector4("background_color",v); - core.background_color << Eigen::Vector4f(v.cast()); - }) - - .def_property("light_position", - [](const igl::opengl::ViewerCore& core) {return Eigen::MatrixXd(core.light_position.cast());}, - [](igl::opengl::ViewerCore& core, const Eigen::MatrixXd& v) - { - assert_is_Vector3("light_position",v); - core.light_position = Eigen::Vector3f(v.cast()); - }) - - .def_readwrite("lighting_factor",&igl::opengl::ViewerCore::lighting_factor) - - .def_property("trackball_angle", - [](const igl::opengl::ViewerCore& core) {return Eigen::Quaterniond(core.trackball_angle.cast());}, - [](igl::opengl::ViewerCore& core, const Eigen::Quaterniond& q) - { - core.trackball_angle = Eigen::Quaternionf(q.cast()); - }) - - .def_property("camera_base_translation", - [](const igl::opengl::ViewerCore& core) {return Eigen::MatrixXd(core.camera_base_translation.cast());}, - [](igl::opengl::ViewerCore& core, const Eigen::MatrixXd& v) - { - assert_is_Vector3("camera_base_translation",v); - core.camera_base_translation = Eigen::Vector3f(v.cast()); - }) - - .def_property("camera_translation", - [](const igl::opengl::ViewerCore& core) {return Eigen::MatrixXd(core.camera_translation.cast());}, - [](igl::opengl::ViewerCore& core, const Eigen::MatrixXd& v) - { - assert_is_Vector3("camera_translation",v); - core.camera_translation = Eigen::Vector3f(v.cast()); - }) - - .def_readwrite("camera_base_zoom",&igl::opengl::ViewerCore::camera_base_zoom) - .def_readwrite("camera_zoom",&igl::opengl::ViewerCore::camera_zoom) - .def_readwrite("orthographic",&igl::opengl::ViewerCore::orthographic) - - .def_property("camera_eye", - [](const igl::opengl::ViewerCore& core) {return Eigen::MatrixXd(core.camera_eye.cast());}, - [](igl::opengl::ViewerCore& core, const Eigen::MatrixXd& v) - { - assert_is_Vector3("camera_eye",v); - core.camera_eye = Eigen::Vector3f(v.cast()); - }) - - .def_property("camera_up", - [](const igl::opengl::ViewerCore& core) {return Eigen::MatrixXd(core.camera_up.cast());}, - [](igl::opengl::ViewerCore& core, const Eigen::MatrixXd& v) - { - assert_is_Vector3("camera_up",v); - core.camera_up = Eigen::Vector3f(v.cast()); - }) - - .def_property("camera_center", - [](const igl::opengl::ViewerCore& core) {return Eigen::MatrixXd(core.camera_center.cast());}, - [](igl::opengl::ViewerCore& core, const Eigen::MatrixXd& v) - { - assert_is_Vector3("camera_center",v); - core.camera_center = Eigen::Vector3f(v.cast()); - }) - - .def_readwrite("camera_view_angle",&igl::opengl::ViewerCore::camera_view_angle) - - .def_readwrite("camera_dnear",&igl::opengl::ViewerCore::camera_dnear) - .def_readwrite("camera_dfar",&igl::opengl::ViewerCore::camera_dfar) - - .def_readwrite("depth_test",&igl::opengl::ViewerCore::depth_test) - - .def_readwrite("is_animating",&igl::opengl::ViewerCore::is_animating) - .def_readwrite("animation_max_fps",&igl::opengl::ViewerCore::animation_max_fps) - - .def_readwrite("object_scale",&igl::opengl::ViewerCore::object_scale) - - .def_property("viewport", - [](const igl::opengl::ViewerCore& core) {return Eigen::MatrixXd(core.viewport.cast());}, - [](igl::opengl::ViewerCore& core, const Eigen::MatrixXd& v) - { - assert_is_Vector4("viewport",v); - core.viewport = Eigen::Vector4f(v.cast()); - }) - - .def_property("view", - [](const igl::opengl::ViewerCore& core) {return Eigen::MatrixXd(core.view.cast());}, - [](igl::opengl::ViewerCore& core, const Eigen::MatrixXd& v) - { - assert_is_Matrix4("view",v); - core.view = Eigen::Matrix4f(v.cast()); - }) - - .def_property("proj", - [](const igl::opengl::ViewerCore& core) {return Eigen::MatrixXd(core.proj.cast());}, - [](igl::opengl::ViewerCore& core, const Eigen::MatrixXd& v) - { - assert_is_Matrix4("proj",v); - core.proj = Eigen::Matrix4f(v.cast()); - }) - - .def_readwrite("rotation_type",&igl::opengl::ViewerCore::rotation_type) - - .def("serialize", [](igl::opengl::ViewerCore& core) - { - std::vector a; - igl::serialize(core,"Core",a); - return a; - }) - - .def("deserialize", [](igl::opengl::ViewerCore& core, const std::vector& a) - { - igl::deserialize(core,"Core",a); - return; - }) - - // TODO: wrap this! - // Eigen::Quaternionf trackball_angle; - ; - -///////////////////////// VIEWER - -// UI Enumerations - py::class_ viewer_class(me, "Viewer"); - - py::enum_(viewer_class, "MouseButton") - .value("Left", igl::opengl::glfw::Viewer::MouseButton::Left) - .value("Middle", igl::opengl::glfw::Viewer::MouseButton::Middle) - .value("Right", igl::opengl::glfw::Viewer::MouseButton::Right) - .export_values(); - - viewer_class - .def(py::init<>()) - //.def_readwrite("data", &igl::opengl::glfw::Viewer::data) - - // .def_property("data", - // [](igl::opengl::glfw::Viewer& viewer) {return viewer.data();}, - // [](igl::opengl::glfw::Viewer& viewer, const igl::opengl::ViewerData& data) - // { - // viewer.data() = data; - // }) - - .def("data", (igl::opengl::ViewerData & (igl::opengl::glfw::Viewer::*)(int)) &igl::opengl::glfw::Viewer::data,pybind11::return_value_policy::reference) - // .def("data", (const igl::opengl::ViewerData & (igl::opengl::glfw::Viewer::*)(int) const) &igl::opengl::glfw::Viewer::data,pybind11::return_value_policy::reference) - - //.def_readwrite("core", &igl::opengl::glfw::Viewer::core) - //.def_readwrite("opengl", &igl::opengl::glfw::Viewer::opengl) - - .def("launch", &igl::opengl::glfw::Viewer::launch, py::arg("resizable") = true, - py::arg("fullscreen") = false, py::arg("name") = "libigl viewer", - py::arg("windowWidth") = 1280, py::arg("windowHeight") = 800) - .def("launch_init", &igl::opengl::glfw::Viewer::launch_init, py::arg("resizable") = true, - py::arg("fullscreen") = false, py::arg("name") = "libigl viewer", - py::arg("windowWidth") = 1280, py::arg("windowHeight") = 800) - .def("launch_rendering", &igl::opengl::glfw::Viewer::launch_rendering, py::arg("loop") = true) - .def("launch_shut", &igl::opengl::glfw::Viewer::launch_shut) - .def("init", &igl::opengl::glfw::Viewer::init) - .def("serialize", [](igl::opengl::glfw::Viewer& viewer) - { - std::vector a; - //igl::serialize(viewer.core,"Core",a); - //igl::serialize(viewer.data,"Data",a); TODO - - return a; - }) - - .def("deserialize", [](igl::opengl::glfw::Viewer& viewer, const std::vector& a) - { - //igl::deserialize(viewer.core,"Core",a); - //igl::deserialize(viewer.data,"Data",a); - return; - }) - - // Scene IO - .def("load_scene", [](igl::opengl::glfw::Viewer& viewer) - { - viewer.load_scene(); - }) - - .def("load_scene", [](igl::opengl::glfw::Viewer& viewer, std::string str) - { - viewer.load_scene(str); - }) - - .def("save_scene", [](igl::opengl::glfw::Viewer& viewer) - { - viewer.save_scene(); - }) - - .def("save_scene", [](igl::opengl::glfw::Viewer& viewer, std::string str) - { - viewer.save_scene(str); - }) - - // Draw everything - .def("draw", &igl::opengl::glfw::Viewer::draw) - - // OpenGL context resize - .def("resize", &igl::opengl::glfw::Viewer::resize) - - // Helper functions - .def("snap_to_canonical_quaternion", &igl::opengl::glfw::Viewer::snap_to_canonical_quaternion) - .def("open_dialog_load_mesh", &igl::opengl::glfw::Viewer::open_dialog_load_mesh) - .def("open_dialog_save_mesh", &igl::opengl::glfw::Viewer::open_dialog_save_mesh) - - // Input handling - .def_readwrite("current_mouse_x", &igl::opengl::glfw::Viewer::current_mouse_x) - .def_readwrite("current_mouse_y", &igl::opengl::glfw::Viewer::current_mouse_y) - - // Callbacks - .def_readwrite("callback_init", &igl::opengl::glfw::Viewer::callback_init) - .def_readwrite("callback_pre_draw", &igl::opengl::glfw::Viewer::callback_pre_draw) - .def_readwrite("callback_post_draw", &igl::opengl::glfw::Viewer::callback_post_draw) - .def_readwrite("callback_mouse_down", &igl::opengl::glfw::Viewer::callback_mouse_down) - .def_readwrite("callback_mouse_up", &igl::opengl::glfw::Viewer::callback_mouse_up) - .def_readwrite("callback_mouse_move", &igl::opengl::glfw::Viewer::callback_mouse_move) - .def_readwrite("callback_mouse_scroll", &igl::opengl::glfw::Viewer::callback_mouse_scroll) - .def_readwrite("callback_key_pressed", &igl::opengl::glfw::Viewer::callback_key_pressed) - .def_readwrite("callback_key_down", &igl::opengl::glfw::Viewer::callback_key_down) - .def_readwrite("callback_key_up", &igl::opengl::glfw::Viewer::callback_key_up) - ; -} diff --git a/python/modules/py_igl_png.cpp b/python/modules/py_igl_png.cpp deleted file mode 100644 index 33429c0b0..000000000 --- a/python/modules/py_igl_png.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - -#include "../python_shared.h" - -#include -#include - - -void python_export_igl_png(py::module &me) { - - py::module m = me.def_submodule( - "png", "Wrappers for libigl functions that use png"); - - #include "../py_igl/png/py_readPNG.cpp" - #include "../py_igl/png/py_writePNG.cpp" - -} diff --git a/python/modules/py_igl_triangle.cpp b/python/modules/py_igl_triangle.cpp deleted file mode 100644 index 87026a156..000000000 --- a/python/modules/py_igl_triangle.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -//#include -//#include -//#include - - -#include "../python_shared.h" - -#include - - -void python_export_igl_triangle(py::module &me) { - - py::module m = me.def_submodule( - "triangle", "Wrappers for libigl functions that use triangle"); - - #include "../py_igl/triangle/py_triangulate.cpp" - -} diff --git a/python/modules/py_typedefs.cpp b/python/modules/py_typedefs.cpp deleted file mode 100644 index 2ccf2122c..000000000 --- a/python/modules/py_typedefs.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -py::class_(m, "RotationList") - .def(py::init<>()) - .def(py::init()) - .def("pop_back", &RotationList::pop_back) - /* There are multiple versions of push_back(), etc. Select the right ones. */ - .def("append", (void (RotationList::*)(const Eigen::Quaterniond &)) &RotationList::push_back) - .def("back", (Eigen::Quaterniond &(RotationList::*)()) &RotationList::back) - .def("__len__", [](const RotationList &v) { return v.size(); }) - .def("__getitem__", [](const RotationList &v, int b) { return v.at(b); }) - .def("__setitem__", [](RotationList &v, int b, Eigen::Quaterniond &c) { return v.at(b) = c; }) - .def("__iter__", [](RotationList &v) { - return py::make_iterator(v.begin(), v.end()); -}, py::keep_alive<0, 1>()); - - -py::bind_vector>(m, "VectorInt"); -py::bind_vector>>(m, "VectorVectorInt"); - - diff --git a/python/modules/py_typedefs.h b/python/modules/py_typedefs.h deleted file mode 100644 index 4023ad429..000000000 --- a/python/modules/py_typedefs.h +++ /dev/null @@ -1,23 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -#include -#include -#include -#include -#include -#include - -typedef std::vector > RotationList; -PYBIND11_MAKE_OPAQUE(RotationList) - -//typedef std::vector TranslationList; -//PYBIND11_MAKE_OPAQUE(TranslationList); - -PYBIND11_MAKE_OPAQUE(std::vector) -PYBIND11_MAKE_OPAQUE(std::vector>) - diff --git a/python/modules/py_vector.cpp b/python/modules/py_vector.cpp deleted file mode 100644 index 6d2da692c..000000000 --- a/python/modules/py_vector.cpp +++ /dev/null @@ -1,777 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -#include -#include -#include - - -#include "../python_shared.h" - -/// Creates Python bindings for a dynamic Eigen matrix -template -py::class_ bind_eigen_2(py::module &m, const char *name) { - typedef typename Type::Scalar Scalar; - - /* Many Eigen functions are templated and can't easily be referenced using - a function pointer, thus a big portion of the binding code below - instantiates Eigen code using small anonymous wrapper functions */ - py::class_ matrix(m, name, py::buffer_protocol()); - - matrix - /* Constructors */ - .def(py::init<>()) - .def(py::init()) - .def("__init__", [](Type &m, Scalar f) { - new (&m) Type(1, 1); - m(0, 0) = f; - }) - .def("__init__", [](Type &m, py::buffer b) { - py::buffer_info info = b.request(); - if (info.format != py::format_descriptor::format()) - throw std::runtime_error("Incompatible buffer format!"); - if (info.ndim == 1) { - new (&m) Type(info.shape[0], 1); - memcpy(m.data(), info.ptr, sizeof(Scalar) * m.size()); - } else if (info.ndim == 2) { - if (info.strides[0] == sizeof(Scalar)) { - new (&m) Type(info.shape[0], info.shape[1]); - memcpy(m.data(), info.ptr, sizeof(Scalar) * m.size()); - } else { - new (&m) Type(info.shape[1], info.shape[0]); - memcpy(m.data(), info.ptr, sizeof(Scalar) * m.size()); - m.transposeInPlace(); - } - } else { - throw std::runtime_error("Incompatible buffer dimension!"); - } - }) - .def("__init__", [](Type &m, std::vector >& b) { - if (b.size() == 0) - { - new (&m) Type(0, 0); - return; - } - - // Size checks - unsigned rows = b.size(); - unsigned cols = b[0].size(); - for (unsigned i=0;i& b) { - if (b.size() == 0) - { - new (&m) Type(0, 0); - return; - } - - // Size checks - unsigned rows = b.size(); - unsigned cols = 1; - - new (&m) Type(rows, cols); - - m.resize(rows,cols); - for (unsigned i=0;i(m.rows(), m.cols()); }) - - /* Extract rows and columns */ - .def("col", [](const Type &m, int i) { - if (i<0 || i>=m.cols()) - throw std::runtime_error("Column index out of bound."); - return Eigen::Matrix(m.col(i)); - }) - .def("row", [](const Type &m, int i) { - if (i<0 || i>=m.rows()) - throw std::runtime_error("Row index out of bound."); - return Eigen::Matrix(m.row(i)); - }) - - - /* Initialization */ - .def("setZero", [](Type &m) { m.setZero(); }) - .def("setIdentity", [](Type &m) { m.setIdentity(); }) - .def("setConstant", [](Type &m, Scalar value) { m.setConstant(value); }) - .def("setRandom", [](Type &m) { m.setRandom(); }) - - .def("setZero", [](Type &m, const int& r, const int& c) { m.setZero(r,c); }) - .def("setIdentity", [](Type &m, const int& r, const int& c) { m.setIdentity(r,c); }) - .def("setConstant", [](Type &m, const int& r, const int& c, Scalar value) { m.setConstant(r,c,value); }) - .def("setRandom", [](Type &m, const int& r, const int& c) { m.setRandom(r,c); }) - - .def("setCol", [](Type &m, int i, const Type& v) { m.col(i) = v; }) - .def("setRow", [](Type &m, int i, const Type& v) { m.row(i) = v; }) - - .def("setBlock", [](Type &m, int i, int j, int p, int q, const Type& v) { m.block(i,j,p,q) = v; }) - .def("block", [](Type &m, int i, int j, int p, int q) { return Type(m.block(i,j,p,q)); }) - - .def("rightCols", [](Type &m, const int& k) { return Type(m.rightCols(k)); }) - .def("leftCols", [](Type &m, const int& k) { return Type(m.leftCols(k)); }) - - .def("setLeftCols", [](Type &m, const int& k, const Type& v) { return Type(m.leftCols(k) = v); }) - .def("setRightCols", [](Type &m, const int& k, const Type& v) { return Type(m.rightCols(k) = v); }) - - .def("topRows", [](Type &m, const int& k) { return Type(m.topRows(k)); }) - .def("bottomRows", [](Type &m, const int& k) { return Type(m.bottomRows(k)); }) - - .def("setTopRows", [](Type &m, const int& k, const Type& v) { return Type(m.topRows(k) = v); }) - .def("setBottomRows", [](Type &m, const int& k, const Type& v) { return Type(m.bottomRows(k) = v); }) - - .def("topLeftCorner", [](Type &m, const int& p, const int&q) { return Type(m.topLeftCorner(p,q)); }) - .def("bottomLeftCorner", [](Type &m, const int& p, const int&q) { return Type(m.bottomLeftCorner(p,q)); }) - .def("topRightCorner", [](Type &m, const int& p, const int&q) { return Type(m.topRightCorner(p,q)); }) - .def("bottomRightCorner", [](Type &m, const int& p, const int&q) { return Type(m.bottomRightCorner(p,q)); }) - - /* Resizing */ - .def("resize", [](Type &m, size_t s0, size_t s1) { m.resize(s0, s1); }) - .def("resizeLike", [](Type &m, const Type &m2) { m.resizeLike(m2); }) - .def("conservativeResize", [](Type &m, size_t s0, size_t s1) { m.conservativeResize(s0, s1); }) - - - .def("mean", [](const Type &m) {return m.mean();}) - - .def("sum", [](const Type &m) {return m.sum();}) - .def("prod", [](const Type &m) {return m.prod();}) - .def("trace", [](const Type &m) {return m.trace();}) - .def("norm", [](const Type &m) {return m.norm();}) - .def("squaredNorm", [](const Type &m) {return m.squaredNorm();}) - .def("squaredMean", [](const Type &m) {return m.array().square().mean();}) - - .def("minCoeff", [](const Type &m) {return m.minCoeff();} ) - .def("maxCoeff", [](const Type &m) {return m.maxCoeff();} ) - - .def("castdouble", [](const Type &m) {return Eigen::MatrixXd(m.template cast());}) - .def("castint", [](const Type &m) {return Eigen::MatrixXi(m.template cast());}) - - /* Component-wise operations */ - .def("cwiseAbs", &Type::cwiseAbs) - .def("cwiseAbs2", &Type::cwiseAbs2) - .def("cwiseSqrt", &Type::cwiseSqrt) - .def("cwiseInverse", &Type::cwiseInverse) - .def("cwiseMin", [](const Type &m1, const Type &m2) -> Type { return m1.cwiseMin(m2); }) - .def("cwiseMax", [](const Type &m1, const Type &m2) -> Type { return m1.cwiseMax(m2); }) - .def("cwiseMin", [](const Type &m1, Scalar s) -> Type { return m1.cwiseMin(s); }) - .def("cwiseMax", [](const Type &m1, Scalar s) -> Type { return m1.cwiseMax(s); }) - .def("cwiseProduct", [](const Type &m1, const Type &m2) -> Type { return m1.cwiseProduct(m2); }) - .def("cwiseQuotient", [](const Type &m1, const Type &m2) -> Type { return m1.cwiseQuotient(m2); }) - - /* Row and column-wise operations */ - .def("rowwiseSet", [](Type &m, const Type &m2) {return Type(m.rowwise() = Eigen::Matrix(m2));} ) - .def("rowwiseSum", [](const Type &m) {return Type(m.rowwise().sum());} ) - .def("rowwiseProd", [](const Type &m) {return Type(m.rowwise().prod());} ) - .def("rowwiseMean", [](const Type &m) {return Type(m.rowwise().mean());} ) - .def("rowwiseNorm", [](const Type &m) {return Type(m.rowwise().norm());} ) - .def("rowwiseNormalized", [](const Type &m) {return Type(m.rowwise().normalized());} ) - .def("rowwiseReverse", [](const Type &m) {return Type(m.rowwise().reverse());} ) - .def("rowwiseMinCoeff", [](const Type &m) {return Type(m.rowwise().minCoeff());} ) - .def("rowwiseMaxCoeff", [](const Type &m) {return Type(m.rowwise().maxCoeff());} ) - - .def("colwiseSet", [](Type &m, const Type &m2) {return Type(m.colwise() = Eigen::Matrix(m2));} ) - .def("colwiseSum", [](const Type &m) {return Type(m.colwise().sum());} ) - .def("colwiseProd", [](const Type &m) {return Type(m.colwise().prod());} ) - .def("colwiseMean", [](const Type &m) {return Type(m.colwise().mean());} ) - .def("colwiseNorm", [](const Type &m) {return Type(m.colwise().norm());} ) - .def("colwiseNormalized", [](const Type &m) {return Type(m.colwise().normalized());} ) - .def("colwiseReverse", [](const Type &m) {return Type(m.colwise().reverse());} ) - .def("colwiseMinCoeff", [](const Type &m) {return Type(m.colwise().minCoeff());} ) - .def("colwiseMaxCoeff", [](const Type &m) {return Type(m.colwise().maxCoeff());} ) - - .def("replicate", [](const Type &m, const int& r, const int& c) {return Type(m.replicate(r,c));} ) - .def("asDiagonal", [](const Type &m) {return Eigen::DiagonalMatrix(m.asDiagonal());} ) - - .def("sparseView", [](Type &m) { return Eigen::SparseMatrix(m.sparseView()); }) - - /* Arithmetic operators (def_cast forcefully casts the result back to a - Type to avoid type issues with Eigen's crazy expression templates) */ - .def_cast(-py::self) - .def_cast(py::self + py::self) - .def_cast(py::self - py::self) - .def_cast(py::self * py::self) - // .def_cast(py::self - Scalar()) - // .def_cast(py::self * Scalar()) - // .def_cast(py::self / Scalar()) - - .def("__mul__", [] - (const Type &a, const Scalar& b) - { - return Eigen::Matrix(a * b); - }) - .def("__rmul__", [](const Type& a, const Scalar& b) - { - return Eigen::Matrix(b * a); - }) - - .def("__add__", [] - (const Type &a, const Scalar& b) - { - return Eigen::Matrix(a.array() + b); - }) - .def("__radd__", [](const Type& a, const Scalar& b) - { - return Eigen::Matrix(b + a.array()); - }) - - .def("__sub__", [] - (const Type &a, const Scalar& b) - { - return Eigen::Matrix(a.array() - b); - }) - .def("__rsub__", [](const Type& a, const Scalar& b) - { - return Eigen::Matrix(b - a.array()); - }) - - .def("__div__", [] - (const Type &a, const Scalar& b) - { - return Eigen::Matrix(a / b); - }) - - .def("__truediv__", [] - (const Type &a, const Scalar& b) - { - return Eigen::Matrix(a / b); - }) - - /* Arithmetic in-place operators */ - .def_cast(py::self += py::self) - .def_cast(py::self -= py::self) - .def_cast(py::self *= py::self) - .def_cast(py::self *= Scalar()) - .def_cast(py::self /= Scalar()) - - /* Comparison operators */ - .def(py::self == py::self) - .def(py::self != py::self) - .def("__lt__", [] - (const Type &a, const Scalar& b) -> Eigen::Matrix - { - return Eigen::Matrix(a.array() < b); - }) - .def("__gt__", [] - (const Type &a, const Scalar& b) -> Eigen::Matrix - { - return Eigen::Matrix(a.array() > b); - }) - .def("__le__", [] - (const Type &a, const Scalar& b) -> Eigen::Matrix - { - return Eigen::Matrix(a.array() <= b); - }) - .def("__ge__", [] - (const Type &a, const Scalar& b) -> Eigen::Matrix - { - return Eigen::Matrix(a.array() >= b); - }) - - .def("transposeInPlace", [](Type &m) { m.transposeInPlace(); }) - /* Other transformations */ - .def("transpose", [](Type &m) -> Type { return m.transpose(); }) - /* Python protocol implementations */ - .def("__repr__", [](const Type &v) { - std::ostringstream oss; - oss << v; - return oss.str(); - }) - .def("__getitem__", [](const Type &m, std::pair i) { - if (i.first >= (size_t) m.rows() || i.second >= (size_t) m.cols()) - throw py::index_error(); - return m(i.first, i.second); - }) - .def("__setitem__", [](Type &m, std::pair i, Scalar v) { - if (i.first >= (size_t) m.rows() || i.second >= (size_t) m.cols()) - throw py::index_error(); - m(i.first, i.second) = v; - }) - - .def("__getitem__", [](const Type &m, size_t i) { - if (i >= (size_t) m.size()) - throw py::index_error(); - return m(i); - }) - .def("__setitem__", [](Type &m, size_t i, Scalar v) { - if (i >= (size_t) m.size()) - throw py::index_error(); - m(i) = v; - }) - - /* Buffer access for interacting with NumPy */ - .def_buffer([](Type &m) -> py::buffer_info { - return py::buffer_info( - m.data(), /* Pointer to buffer */ - sizeof(Scalar), /* Size of one scalar */ - /* Python struct-style format descriptor */ - py::format_descriptor::format(), - 2, /* Number of dimensions */ - { (size_t) m.rows(), /* Buffer dimensions */ - (size_t) m.cols() }, - { sizeof(Scalar), /* Strides (in bytes) for each index */ - sizeof(Scalar) * m.rows() } - ); - }) - - /* Static initializers */ - .def_static("Zero", [](size_t n, size_t m) { return Type(Type::Zero(n, m)); }) - .def_static("Random", [](size_t n, size_t m) { return Type(Type::Random(n, m)); }) - .def_static("Ones", [](size_t n, size_t m) { return Type(Type::Ones(n, m)); }) - .def_static("Constant", [](size_t n, size_t m, Scalar value) { return Type(Type::Constant(n, m, value)); }) - .def_static("Identity", [](size_t n, size_t m) { return Type(Type::Identity(n, m)); }) - .def("MapMatrix", [](const Type& m, size_t r, size_t c) - { - return Eigen::Matrix(Eigen::Map>(m.data(),r,c)); - }) - - .def("copy", [](const Type &m) { return Type(m); }) - - ; - return matrix; -} - -/// Creates Python bindings for a dynamic Eigen sparse order-2 tensor (i.e. a matrix) -template -py::class_ bind_eigen_sparse_2(py::module &m, const char *name) { - typedef typename Type::Scalar Scalar; - - /* Many Eigen functions are templated and can't easily be referenced using - a function pointer, thus a big portion of the binding code below - instantiates Eigen code using small anonymous wrapper functions */ - py::class_ matrix(m, name, py::buffer_protocol()); - - matrix - /* Constructors */ - .def(py::init<>()) - .def(py::init()) - // .def("__init__", [](Type &m, Scalar f) { - // new (&m) Type(1, 1); - // m(0, 0) = f; - // }) - // .def("__init__", [](Type &m, py::buffer b) { - // py::buffer_info info = b.request(); - // if (info.format != py::format_descriptor::value()) - // throw std::runtime_error("Incompatible buffer format!"); - // if (info.ndim == 1) { - // new (&m) Type(info.shape[0], 1); - // memcpy(m.data(), info.ptr, sizeof(Scalar) * m.size()); - // } else if (info.ndim == 2) { - // if (info.strides[0] == sizeof(Scalar)) { - // new (&m) Type(info.shape[0], info.shape[1]); - // memcpy(m.data(), info.ptr, sizeof(Scalar) * m.size()); - // } else { - // new (&m) Type(info.shape[1], info.shape[0]); - // memcpy(m.data(), info.ptr, sizeof(Scalar) * m.size()); - // m.transposeInPlace(); - // } - // } else { - // throw std::runtime_error("Incompatible buffer dimension!"); - // } - // }) - - /* Size query functions */ - .def("size", [](const Type &m) { return m.size(); }) - .def("cols", [](const Type &m) { return m.cols(); }) - .def("rows", [](const Type &m) { return m.rows(); }) - .def("shape", [](const Type &m) { return std::tuple(m.rows(), m.cols()); }) - - - /* Initialization */ - .def("setZero", [](Type &m) { m.setZero(); }) - .def("setIdentity", [](Type &m) { m.setIdentity(); }) - - .def("transpose", [](Type &m) { return Type(m.transpose()); }) - .def("norm", [](Type &m) { return m.norm(); }) - - /* Resizing */ - // .def("resize", [](Type &m, size_t s0, size_t s1) { m.resize(s0, s1); }) - // .def("resizeLike", [](Type &m, const Type &m2) { m.resizeLike(m2); }) - // .def("conservativeResize", [](Type &m, size_t s0, size_t s1) { m.conservativeResize(s0, s1); }) - - /* Component-wise operations */ - // .def("cwiseAbs", &Type::cwiseAbs) - // .def("cwiseAbs2", &Type::cwiseAbs2) - // .def("cwiseSqrt", &Type::cwiseSqrt) - // .def("cwiseInverse", &Type::cwiseInverse) - // .def("cwiseMin", [](const Type &m1, const Type &m2) -> Type { return m1.cwiseMin(m2); }) - // .def("cwiseMax", [](const Type &m1, const Type &m2) -> Type { return m1.cwiseMax(m2); }) - // .def("cwiseMin", [](const Type &m1, Scalar s) -> Type { return m1.cwiseMin(s); }) - // .def("cwiseMax", [](const Type &m1, Scalar s) -> Type { return m1.cwiseMax(s); }) - // .def("cwiseProduct", [](const Type &m1, const Type &m2) -> Type { return m1.cwiseProduct(m2); }) - // .def("cwiseQuotient", [](const Type &m1, const Type &m2) -> Type { return m1.cwiseQuotient(m2); }) - - /* Arithmetic operators (def_cast forcefully casts the result back to a - Type to avoid type issues with Eigen's crazy expression templates) */ - .def_cast(-py::self) - .def_cast(py::self + py::self) - .def_cast(py::self - py::self) - .def_cast(py::self * py::self) - .def_cast(py::self * Scalar()) - .def_cast(Scalar() * py::self) - // Special case, sparse * dense produces a dense matrix - - // .def("__mul__", [] - // (const Type &a, const Scalar& b) - // { - // return Type(a * b); - // }) - // .def("__rmul__", [](const Type& a, const Scalar& b) - // { - // return Type(b * a); - // }) - - .def("__mul__", [] - (const Type &a, const Eigen::Matrix& b) - { - return Eigen::Matrix(a * b); - }) - .def("__rmul__", [](const Type& a, const Eigen::Matrix& b) - { - return Eigen::Matrix(b * a); - }) - - .def("__mul__", [] - (const Type &a, const Eigen::DiagonalMatrix& b) - { - return Type(a * b); - }) - .def("__rmul__", [](const Type& a, const Eigen::DiagonalMatrix& b) - { - return Type(b * a); - }) - - //.def(py::self * Eigen::Matrix()) -// .def_cast(py::self / Scalar()) - - /* Arithmetic in-place operators */ - // .def_cast(py::self += py::self) - // .def_cast(py::self -= py::self) - // .def_cast(py::self *= py::self) - // .def_cast(py::self *= Scalar()) - // .def_cast(py::self /= Scalar()) - - /* Comparison operators */ - // .def(py::self == py::self) - // .def(py::self != py::self) - - // .def("transposeInPlace", [](Type &m) { m.transposeInPlace(); }) - // /* Other transformations */ - // .def("transpose", [](Type &m) -> Type { return m.transpose(); }) - - /* Python protocol implementations */ - .def("__repr__", [](const Type &v) { - std::ostringstream oss; - oss << v; - return oss.str(); - }) - - /* Static initializers */ - // .def_static("Zero", [](size_t n, size_t m) { return Type(Type::Zero(n, m)); }) - // .def_static("Ones", [](size_t n, size_t m) { return Type(Type::Ones(n, m)); }) - // .def_static("Constant", [](size_t n, size_t m, Scalar value) { return Type(Type::Constant(n, m, value)); }) - // .def_static("Identity", [](size_t n, size_t m) { return Type(Type::Identity(n, m)); }) - .def("toCOO",[](const Type& m) - { - Eigen::Matrix t(m.nonZeros(),3); - int count = 0; - for (int k=0; k& t, int rows, int cols) - { - typedef Eigen::Triplet T; - std::vector tripletList; - tripletList.reserve(t.rows()); - for(unsigned i=0;i(m.diagonal());} ) - - ; - return matrix; -} - -/// Creates Python bindings for a diagonal Eigen sparse order-2 tensor (i.e. a matrix) -template -py::class_ bind_eigen_diagonal_2(py::module &m, const char *name) { - typedef typename Type::Scalar Scalar; - - /* Many Eigen functions are templated and can't easily be referenced using - a function pointer, thus a big portion of the binding code below - instantiates Eigen code using small anonymous wrapper functions */ - py::class_ matrix(m, name, py::buffer_protocol()); - - matrix - /* Constructors */ - .def(py::init<>()) - //.def(py::init()) - - /* Size query functions */ - .def("size", [](const Type &m) { return m.size(); }) - .def("cols", [](const Type &m) { return m.cols(); }) - .def("rows", [](const Type &m) { return m.rows(); }) - .def("shape", [](const Type &m) { return std::tuple(m.rows(), m.cols()); }) - - /* Initialization */ - .def("setZero", [](Type &m) { m.setZero(); }) - .def("setIdentity", [](Type &m) { m.setIdentity(); }) - - /* Arithmetic operators (def_cast forcefully casts the result back to a - Type to avoid type issues with Eigen's crazy expression templates) */ - // .def_cast(-py::self) - // .def_cast(py::self + py::self) - // .def_cast(py::self - py::self) - // .def_cast(py::self * py::self) - .def_cast(py::self * Scalar()) - .def_cast(Scalar() * py::self) - - // // Special case, sparse * dense produces a dense matrix - // .def("__mul__", [] - // (const Type &a, const Eigen::Matrix& b) - // { - // return Eigen::Matrix(a * b); - // }) - // .def("__rmul__", [](const Type& a, const Eigen::Matrix& b) - // { - // return Eigen::Matrix(b * a); - // }) - - .def("__mul__", [] - (const Type &a, const Eigen::Matrix& b) - { - return Eigen::Matrix(a * b); - }) - .def("__rmul__", [](const Type& a, const Eigen::Matrix& b) - { - return Eigen::Matrix(b * a); - }) - - .def("__mul__", [] - (const Type &a, const Eigen::SparseMatrix& b) - { - return Eigen::SparseMatrix(a * b); - }) - .def("__rmul__", [](const Type& a, const Eigen::SparseMatrix& b) - { - return Eigen::SparseMatrix(b * a); - }) - - /* Python protocol implementations */ - .def("__repr__", [](const Type &/*v*/) { - std::ostringstream oss; - oss << "<< operator undefined for diagonal matrices"; - return oss.str(); - }) - - /* Other transformations */ - - ; - return matrix; -} - - -void python_export_vector(py::module &m) { - - py::module me = m.def_submodule( - "eigen", "Wrappers for Eigen types"); - - /* Bindings for VectorXd */ - // bind_eigen_1 (me, "VectorXd"); - // py::implicitly_convertible(); - // py::implicitly_convertible(); - - /* Bindings for VectorXi */ - // bind_eigen_1 (me, "VectorXi"); - // py::implicitly_convertible(); - // py::implicitly_convertible(); - - /* Bindings for MatrixXd */ - bind_eigen_2 (me, "MatrixXd"); - //py::implicitly_convertible(); - //py::implicitly_convertible(); - - /* Bindings for MatrixXi */ - bind_eigen_2 (me, "MatrixXi"); - //py::implicitly_convertible(); - //py::implicitly_convertible(); - - /* Bindings for MatrixXb */ - #if EIGEN_VERSION_AT_LEAST(3,3,0) - // Temporarily disabled with Eigen 3.3 - #else - bind_eigen_2 > (me, "MatrixXb"); - #endif - - /* Bindings for MatrixXuc */ - bind_eigen_2 > (me, "MatrixXuc"); - // py::implicitly_convertible >(); - // py::implicitly_convertible >(); - - // /* Bindings for Vector3d */ - // auto vector3 = bind_eigen_1_3(me, "Vector3d"); - // vector3 - // .def("norm", [](const Eigen::Vector3d &v) { return v.norm(); }) - // .def("squaredNorm", [](const Eigen::Vector3d &v) { return v.squaredNorm(); }) - // .def("normalize", [](Eigen::Vector3d &v) { v.normalize(); }) - // .def("normalized", [](const Eigen::Vector3d &v) -> Eigen::Vector3d { return v.normalized(); }) - // .def("dot", [](const Eigen::Vector3d &v1, const Eigen::Vector3d &v2) { return v1.dot(v2); }) - // .def("cross", [](const Eigen::Vector3d &v1, const Eigen::Vector3d &v2) -> Eigen::Vector3d { return v1.cross(v2); }) - // .def_property("x", [](const Eigen::Vector3d &v) -> double { return v.x(); }, - // [](Eigen::Vector3d &v, double x) { v.x() = x; }, "X coordinate") - // .def_property("y", [](const Eigen::Vector3d &v) -> double { return v.y(); }, - // [](Eigen::Vector3d &v, double y) { v.y() = y; }, "Y coordinate") - // .def_property("z", [](const Eigen::Vector3d &v) -> double { return v.z(); }, - // [](Eigen::Vector3d &v, double z) { v.z() = z; }, "Z coordinate"); - // - // py::implicitly_convertible(); - // py::implicitly_convertible(); - - /* Bindings for SparseMatrix */ - bind_eigen_sparse_2< Eigen::SparseMatrix > (me, "SparseMatrixd"); - - /* Bindings for SparseMatrix */ - bind_eigen_sparse_2< Eigen::SparseMatrix > (me, "SparseMatrixi"); - - /* Bindings for DiagonalMatrix */ - bind_eigen_diagonal_2< Eigen::DiagonalMatrix > (me, "DiagonalMatrixd"); - - /* Bindings for DiagonalMatrix */ - bind_eigen_diagonal_2< Eigen::DiagonalMatrix > (me, "DiagonalMatrixi"); - - /* Bindings for SimplicialLLT*/ - py::class_ >> simpliciallltsparse(me, "SimplicialLLTsparse"); - - simpliciallltsparse - .def(py::init<>()) - .def(py::init>()) - .def("info",[](const Eigen::SimplicialLLT >& s) - { - if (s.info() == Eigen::Success) - return "Success"; - else - return "Numerical Issue"; - }) - .def("analyzePattern",[](Eigen::SimplicialLLT >& s, const Eigen::SparseMatrix& a) { return s.analyzePattern(a); }) - .def("factorize",[](Eigen::SimplicialLLT >& s, const Eigen::SparseMatrix& a) { return s.factorize(a); }) - .def("solve",[](const Eigen::SimplicialLLT >& s, const Eigen::MatrixXd& rhs) { return Eigen::MatrixXd(s.solve(rhs)); }) - ; - - // Bindings for Affine3d - py::class_ affine3d(me, "Affine3d"); - - affine3d - .def(py::init<>()) - .def_static("Identity", []() { return Eigen::Affine3d::Identity(); }) - .def("setIdentity",[](Eigen::Affine3d& a){ - return a.setIdentity(); - }) - .def("rotate",[](Eigen::Affine3d& a, double angle, Eigen::MatrixXd axis) { - assert_is_Vector3("axis", axis); - return a.rotate(Eigen::AngleAxisd(angle, Eigen::Vector3d(axis))); - }) - .def("rotate",[](Eigen::Affine3d& a, Eigen::Quaterniond quat) { - return a.rotate(quat); - }) - .def("translate",[](Eigen::Affine3d& a, Eigen::MatrixXd offset) { - assert_is_Vector3("offset", offset); - return a.translate(Eigen::Vector3d(offset)); - }) - .def("matrix", [](Eigen::Affine3d& a) -> Eigen::MatrixXd { - return Eigen::MatrixXd(a.matrix()); - }) - ; - // Bindings for Quaterniond - py::class_ quaterniond(me, "Quaterniond"); - - quaterniond - .def(py::init<>()) - .def(py::init()) - .def("__init__", [](Eigen::Quaterniond &q, double angle, Eigen::MatrixXd axis) { - assert_is_Vector3("axis", axis); - new (&q) Eigen::Quaterniond(Eigen::AngleAxisd(angle, Eigen::Vector3d(axis))); - }) - .def_static("Identity", []() { return Eigen::Quaterniond::Identity(); }) - .def("__repr__", [](const Eigen::Quaterniond &v) { - std::ostringstream oss; - oss << "(" << v.w() << ", " << v.x() << ", " << v.y() << ", " << v.z() << ")"; - return oss.str(); - }) - .def("conjugate",[](Eigen::Quaterniond& q) { - return q.conjugate(); - }) - .def("normalize",[](Eigen::Quaterniond& q) { - return q.normalize(); - }) - .def("slerp",[](Eigen::Quaterniond& q, double & t, Eigen::Quaterniond other) { - return q.slerp(t, other); - }) -// .def_cast(-py::self) -// .def_cast(py::self + py::self) -// .def_cast(py::self - py::self) - .def_cast(py::self * py::self) - // .def_cast(py::self - Scalar()) - // .def_cast(py::self * Scalar()) - // .def_cast(py::self / Scalar()) - -// .def("__mul__", [] -// (const Type &a, const Scalar& b) -// { -// return Eigen::Matrix(a * b); -// }) -// .def("__rmul__", [](const Type& a, const Scalar& b) -// { -// return Eigen::Matrix(b * a); -// }) - ; - - - - - - -} diff --git a/python/py_doc.cpp b/python/py_doc.cpp deleted file mode 100644 index f2018357e..000000000 --- a/python/py_doc.cpp +++ /dev/null @@ -1,1530 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -const char *__doc_igl_active_set = R"igl_Qu8mg5v7(// Known Bugs: rows of [Aeq;Aieq] **must** be linearly independent. Should be - // using QR decomposition otherwise: - // http://www.okstate.edu/sas/v8/sashtml/ormp/chap5/sect32.htm - // - // ACTIVE_SET Minimize quadratic energy - // - // 0.5*Z'*A*Z + Z'*B + C with constraints - // - // that Z(known) = Y, optionally also subject to the constraints Aeq*Z = Beq, - // and further optionally subject to the linear inequality constraints that - // Aieq*Z <= Bieq and constant inequality constraints lx <= x <= ux - // - // Inputs: - // A n by n matrix of quadratic coefficients - // B n by 1 column of linear coefficients - // known list of indices to known rows in Z - // Y list of fixed values corresponding to known rows in Z - // Aeq meq by n list of linear equality constraint coefficients - // Beq meq by 1 list of linear equality constraint constant values - // Aieq mieq by n list of linear inequality constraint coefficients - // Bieq mieq by 1 list of linear inequality constraint constant values - // lx n by 1 list of lower bounds [] implies -Inf - // ux n by 1 list of upper bounds [] implies Inf - // params struct of additional parameters (see below) - // Z if not empty, is taken to be an n by 1 list of initial guess values - // (see output) - // Outputs: - // Z n by 1 list of solution values - // Returns true on success, false on error - // - // Benchmark: For a harmonic solve on a mesh with 325K facets, matlab 2.2 - // secs, igl/min_quad_with_fixed.h 7.1 secs - //)igl_Qu8mg5v7"; -const char *__doc_igl_adjacency_list = R"igl_Qu8mg5v7(// Constructs the graph adjacency list of a given mesh (V,F) - // Templates: - // T should be a eigen sparse matrix primitive type like int or double - // Inputs: - // F #F by dim list of mesh faces (must be triangles) - // sorted flag that indicates if the list should be sorted counter-clockwise - // Outputs: - // A vector > containing at row i the adjacent vertices of vertex i - // - // Example: - // // Mesh in (V,F) - // vector > A; - // adjacency_list(F,A); - // - // See also: edges, cotmatrix, diag)igl_Qu8mg5v7"; -const char *__doc_igl_arap_precomputation = R"igl_Qu8mg5v7(// Compute necessary information to start using an ARAP deformation - // - // Inputs: - // V #V by dim list of mesh positions - // F #F by simplex-size list of triangle|tet indices into V - // dim dimension being used at solve time. For deformation usually dim = - // V.cols(), for surface parameterization V.cols() = 3 and dim = 2 - // b #b list of "boundary" fixed vertex indices into V - // Outputs: - // data struct containing necessary precomputation)igl_Qu8mg5v7"; -const char *__doc_igl_arap_solve = R"igl_Qu8mg5v7(// Inputs: - // bc #b by dim list of boundary conditions - // data struct containing necessary precomputation and parameters - // U #V by dim initial guess)igl_Qu8mg5v7"; -const char *__doc_igl_avg_edge_length = R"igl_Qu8mg5v7(// Compute the average edge length for the given triangle mesh - // Templates: - // DerivedV derived from vertex positions matrix type: i.e. MatrixXd - // DerivedF derived from face indices matrix type: i.e. MatrixXi - // DerivedL derived from edge lengths matrix type: i.e. MatrixXd - // Inputs: - // V eigen matrix #V by 3 - // F #F by simplex-size list of mesh faces (must be simplex) - // Outputs: - // l average edge length - // - // See also: adjacency_matrix)igl_Qu8mg5v7"; -const char *__doc_igl_barycenter = R"igl_Qu8mg5v7(// Computes the barycenter of every simplex - // - // Inputs: - // V #V x dim matrix of vertex coordinates - // F #F x simplex_size matrix of indices of simplex corners into V - // Output: - // BC #F x dim matrix of 3d vertices - //)igl_Qu8mg5v7"; -const char *__doc_igl_barycentric_coordinates = R"igl_Qu8mg5v7(// Compute barycentric coordinates in a tet - // - // Inputs: - // P #P by 3 Query points in 3d - // A #P by 3 Tet corners in 3d - // B #P by 3 Tet corners in 3d - // C #P by 3 Tet corners in 3d - // D #P by 3 Tet corners in 3d - // Outputs: - // L #P by 4 list of barycentric coordinates - // )igl_Qu8mg5v7"; -const char *__doc_igl_barycentric_to_global = R"igl_Qu8mg5v7(// Converts barycentric coordinates in the embree form to 3D coordinates - // Embree stores barycentric coordinates as triples: fid, bc1, bc2 - // fid is the id of a face, bc1 is the displacement of the point wrt the - // first vertex v0 and the edge v1-v0. Similarly, bc2 is the displacement - // wrt v2-v0. - // - // Input: - // V: #Vx3 Vertices of the mesh - // F: #Fxe Faces of the mesh - // bc: #Xx3 Barycentric coordinates, one row per point - // - // Output: - // #X: #Xx3 3D coordinates of all points in bc)igl_Qu8mg5v7"; - -const char *__doc_igl_bbw = R"igl_Qu8mg5v7(// Compute Bounded Biharmonic Weights on a given domain (V,Ele) with a given - // set of boundary conditions - // - // Templates - // DerivedV derived type of eigen matrix for V (e.g. MatrixXd) - // DerivedF derived type of eigen matrix for F (e.g. MatrixXi) - // Derivedb derived type of eigen matrix for b (e.g. VectorXi) - // Derivedbc derived type of eigen matrix for bc (e.g. MatrixXd) - // DerivedW derived type of eigen matrix for W (e.g. MatrixXd) - // Inputs: - // V #V by dim vertex positions - // Ele #Elements by simplex-size list of element indices - // b #b boundary indices into V - // bc #b by #W list of boundary values - // data object containing options, initial guess --> solution and results - // Outputs: - // W #V by #W list of *unnormalized* weights to normalize use - // igl::normalize_row_sums(W,W); - // Returns true on success, false on failure)igl_Qu8mg5v7"; -const char *__doc_igl_boundary_conditions = R"igl_Qu8mg5v7(// Compute boundary conditions for automatic weights computation. This - // function expects that the given mesh (V,Ele) has sufficient samples - // (vertices) exactly at point handle locations and exactly along bone and - // cage edges. - // - // Inputs: - // V #V by dim list of domain vertices - // Ele #Ele by simplex-size list of simplex indices - // C #C by dim list of handle positions - // P #P by 1 list of point handle indices into C - // BE #BE by 2 list of bone edge indices into C - // CE #CE by 2 list of cage edge indices into *P* - // Outputs: - // b #b list of boundary indices (indices into V of vertices which have - // known, fixed values) - // bc #b by #weights list of known/fixed values for boundary vertices - // (notice the #b != #weights in general because #b will include all the - // intermediary samples along each bone, etc.. The ordering of the - // weights corresponds to [P;BE] - // Returns false if boundary conditions are suspicious: - // P and BE are empty - // bc is empty - // some column of bc doesn't have a 0 (assuming bc has >1 columns) - // some column of bc doesn't have a 1 (assuming bc has >1 columns))igl_Qu8mg5v7"; -const char *__doc_igl_boundary_facets = R"igl_Qu8mg5v7(// BOUNDARY_FACETS Determine boundary faces (edges) of tetrahedra (triangles) - // stored in T (analogous to qptoolbox's `outline` and `boundary_faces`). - // - // Templates: - // IntegerT integer-value: e.g. int - // IntegerF integer-value: e.g. int - // Input: - // T tetrahedron (triangle) index list, m by 4 (3), where m is the number of tetrahedra - // Output: - // F list of boundary faces, n by 3 (2), where n is the number of boundary faces - // - //)igl_Qu8mg5v7"; -const char *__doc_igl_boundary_loop = R"igl_Qu8mg5v7(// Compute list of ordered boundary loops for a manifold mesh. - // - // Templates: - // Index index type - // Inputs: - // F #V by dim list of mesh faces - // Outputs: - // L list of loops where L[i] = ordered list of boundary vertices in loop i - //)igl_Qu8mg5v7"; -const char *__doc_igl_cat = R"igl_Qu8mg5v7(// Perform concatenation of a two matrices along a single dimension - // If dim == 1, then C = [A;B]. If dim == 2 then C = [A B] - // - // Template: - // Scalar scalar data type for sparse matrices like double or int - // Mat matrix type for all matrices (e.g. MatrixXd, SparseMatrix) - // MatC matrix type for output matrix (e.g. MatrixXd) needs to support - // resize - // Inputs: - // A first input matrix - // B second input matrix - // dim dimension along which to concatenate, 1 or 2 - // Outputs: - // C output matrix - // )igl_Qu8mg5v7"; -const char *__doc_igl_collapse_edge = R"igl_Qu8mg5v7(See collapse_edge for the documentation.)igl_Qu8mg5v7"; -const char *__doc_igl_colon = R"igl_Qu8mg5v7(// Colon operator like matlab's colon operator. Enumerats values between low - // and hi with step step. - // Templates: - // L should be a eigen matrix primitive type like int or double - // S should be a eigen matrix primitive type like int or double - // H should be a eigen matrix primitive type like int or double - // T should be a eigen matrix primitive type like int or double - // Inputs: - // low starting value if step is valid then this is *always* the first - // element of I - // step step difference between sequential elements returned in I, - // remember this will be cast to template T at compile time. If lowhi then step must be negative. - // Otherwise I will be set to empty. - // hi ending value, if (hi-low)%step is zero then this will be the last - // element in I. If step is positive there will be no elements greater - // than hi, vice versa if hi smoothness only, 1->constraints only) - // Outputs: - // R #F by 3 the representative vectors of the interpolated field - // S #V by 1 the singularity index for each vertex (0 = regular))igl_Qu8mg5v7"; -const char *__doc_igl_copyleft_marching_cubes = R"igl_Qu8mg5v7(// marching_cubes( values, points, x_res, y_res, z_res, vertices, faces ) - // - // performs marching cubes reconstruction on the grid defined by values, and - // points, and generates vertices and faces - // - // Input: - // values #number_of_grid_points x 1 array -- the scalar values of an - // implicit function defined on the grid points (<0 in the inside of the - // surface, 0 on the border, >0 outside) - // points #number_of_grid_points x 3 array -- 3-D positions of the grid - // points, ordered in x,y,z order: - // points[index] = the point at (x,y,z) where : - // x = (index % (xres -1), - // y = (index / (xres-1)) %(yres-1), - // z = index / (xres -1) / (yres -1) ). - // where x,y,z index x, y, z dimensions - // i.e. index = x + y*xres + z*xres*yres - // xres resolutions of the grid in x dimension - // yres resolutions of the grid in y dimension - // zres resolutions of the grid in z dimension - // Output: - // vertices #V by 3 list of mesh vertex positions - // faces #F by 3 list of mesh triangle indices - //)igl_Qu8mg5v7"; -const char *__doc_igl_copyleft_swept_volume = R"igl_Qu8mg5v7(// Compute the surface of the swept volume of a solid object with surface - // (V,F) mesh under going rigid motion. - // - // Inputs: - // V #V by 3 list of mesh positions in reference pose - // F #F by 3 list of mesh indices into V - // transform function handle so that transform(t) returns the rigid - // transformation at time t∈[0,1] - // steps number of time steps: steps=3 --> t∈{0,0.5,1} - // grid_res number of grid cells on the longest side containing the - // motion (isolevel+1 cells will also be added on each side as padding) - // isolevel distance level to be contoured as swept volume - // Outputs: - // SV #SV by 3 list of mesh positions of the swept surface - // SF #SF by 3 list of mesh faces into SV)igl_Qu8mg5v7"; -const char *__doc_igl_copyleft_tetgen_tetrahedralize = R"igl_Qu8mg5v7(// Mesh the interior of a surface mesh (V,F) using tetgen - // - // Inputs: - // V #V by 3 vertex position list - // F #F list of polygon face indices into V (0-indexed) - // switches string of tetgen options (See tetgen documentation) e.g. - // "pq1.414a0.01" tries to mesh the interior of a given surface with - // quality and area constraints - // "" will mesh the convex hull constrained to pass through V (ignores F) - // Outputs: - // TV #V by 3 vertex position list - // TT #T by 4 list of tet face indices - // TF #F by 3 list of triangle face indices - // Returns status: - // 0 success - // 1 tetgen threw exception - // 2 tetgen did not crash but could not create any tets (probably there are - // holes, duplicate faces etc.) - // -1 other error)igl_Qu8mg5v7"; -const char *__doc_igl_cotmatrix = R"igl_Qu8mg5v7(// Constructs the cotangent stiffness matrix (discrete laplacian) for a given - // mesh (V,F). - // - // Templates: - // DerivedV derived type of eigen matrix for V (e.g. derived from - // MatrixXd) - // DerivedF derived type of eigen matrix for F (e.g. derived from - // MatrixXi) - // Scalar scalar type for eigen sparse matrix (e.g. double) - // Inputs: - // V #V by dim list of mesh vertex positions - // F #F by simplex_size list of mesh faces (must be triangles) - // Outputs: - // L #V by #V cotangent matrix, each row i corresponding to V(i,:) - // - // See also: adjacency_matrix - // - // Note: This Laplacian uses the convention that diagonal entries are - // **minus** the sum of off-diagonal entries. The diagonal entries are - // therefore in general negative and the matrix is **negative** semi-definite - // (immediately, -L is **positive** semi-definite) - //)igl_Qu8mg5v7"; -const char *__doc_igl_covariance_scatter_matrix = R"igl_Qu8mg5v7(// Construct the covariance scatter matrix for a given arap energy - // Inputs: - // V #V by Vdim list of initial domain positions - // F #F by 3 list of triangle indices into V - // energy ARAPEnergyType enum value defining which energy is being used. - // See ARAPEnergyType.h for valid options and explanations. - // Outputs: - // CSM dim*#V/#F by dim*#V sparse matrix containing special laplacians along - // the diagonal so that when multiplied by V gives covariance matrix - // elements, can be used to speed up covariance matrix computation)igl_Qu8mg5v7"; -const char *__doc_igl_cross_field_mismatch = R"igl_Qu8mg5v7(// Inputs: - // V #V by 3 eigen Matrix of mesh vertex 3D positions - // F #F by 3 eigen Matrix of face (quad) indices - // PD1 #F by 3 eigen Matrix of the first per face cross field vector - // PD2 #F by 3 eigen Matrix of the second per face cross field vector - // isCombed boolean, specifying whether the field is combed (i.e. matching has been precomputed. - // If not, the field is combed first. - // Output: - // Handle_MMatch #F by 3 eigen Matrix containing the integer mismatch of the cross field - // across all face edges - //)igl_Qu8mg5v7"; -const char *__doc_igl_cut_mesh_from_singularities = R"igl_Qu8mg5v7(// Given a mesh (V,F) and the integer mismatch of a cross field per edge - // (mismatch), finds the cut_graph connecting the singularities (seams) and the - // degree of the singularities singularity_index - // - // Input: - // V #V by 3 list of mesh vertex positions - // F #F by 3 list of faces - // mismatch #F by 3 list of per corner integer mismatch - // Outputs: - // seams #F by 3 list of per corner booleans that denotes if an edge is a - // seam or not - //)igl_Qu8mg5v7"; -const char *__doc_igl_deform_skeleton = R"igl_Qu8mg5v7(// Deform a skeleton. - // - // Inputs: - // C #C by 3 list of joint positions - // BE #BE by 2 list of bone edge indices - // vA #BE list of bone transformations - // Outputs - // CT #BE*2 by 3 list of deformed joint positions - // BET #BE by 2 list of bone edge indices (maintains order) - //)igl_Qu8mg5v7"; -const char *__doc_igl_directed_edge_orientations = R"igl_Qu8mg5v7(// Determine rotations that take each edge from the x-axis to its given rest - // orientation. - // - // Inputs: - // C #C by 3 list of edge vertex positions - // E #E by 2 list of directed edges - // Outputs: - // Q #E list of quaternions - //)igl_Qu8mg5v7"; -const char *__doc_igl_directed_edge_parents = R"igl_Qu8mg5v7(// Recover "parents" (preceding edges) in a tree given just directed edges. - // - // Inputs: - // E #E by 2 list of directed edges - // Outputs: - // P #E list of parent indices into E (-1) means root - //)igl_Qu8mg5v7"; -const char *__doc_igl_doublearea = R"igl_Qu8mg5v7(// DOUBLEAREA computes twice the area for each input triangle[quad] - // - // Templates: - // DerivedV derived type of eigen matrix for V (e.g. derived from - // MatrixXd) - // DerivedF derived type of eigen matrix for F (e.g. derived from - // MatrixXi) - // DeriveddblA derived type of eigen matrix for dblA (e.g. derived from - // MatrixXd) - // Inputs: - // V #V by dim list of mesh vertex positions - // F #F by simplex_size list of mesh faces (must be triangles or quads) - // Outputs: - // dblA #F list of triangle[quad] double areas (SIGNED only for 2D input) - // - // Known bug: For dim==3 complexity is O(#V + #F)!! Not just O(#F). This is a big deal - // if you have 1million unreferenced vertices and 1 face)igl_Qu8mg5v7"; -const char *__doc_igl_doublearea_single = R"igl_Qu8mg5v7(// Single triangle in 2D! - // - // This should handle streams of corners not just single corners)igl_Qu8mg5v7"; -const char *__doc_igl_doublearea_quad = R"igl_Qu8mg5v7(// DOUBLEAREA_QUAD computes twice the area for each input quadrilateral - // - // Inputs: - // V #V by dim list of mesh vertex positions - // F #F by simplex_size list of mesh faces (must be quadrilaterals) - // Outputs: - // dblA #F list of quadrilateral double areas - //)igl_Qu8mg5v7"; -const char *__doc_igl_dqs = R"igl_Qu8mg5v7(// Dual quaternion skinning - // - // Inputs: - // V #V by 3 list of rest positions - // W #W by #C list of weights - // vQ #C list of rotation quaternions - // vT #C list of translation vectors - // Outputs: - // U #V by 3 list of new positions)igl_Qu8mg5v7"; -const char *__doc_igl_edge_lengths = R"igl_Qu8mg5v7(// Constructs a list of lengths of edges opposite each index in a face - // (triangle/tet) list - // - // Templates: - // DerivedV derived from vertex positions matrix type: i.e. MatrixXd - // DerivedF derived from face indices matrix type: i.e. MatrixXi - // DerivedL derived from edge lengths matrix type: i.e. MatrixXd - // Inputs: - // V eigen matrix #V by 3 - // F #F by 2 list of mesh edges - // or - // F #F by 3 list of mesh faces (must be triangles) - // or - // T #T by 4 list of mesh elements (must be tets) - // Outputs: - // L #F by {1|3|6} list of edge lengths - // for edges, column of lengths - // for triangles, columns correspond to edges [1,2],[2,0],[0,1] - // for tets, columns correspond to edges - // [3 0],[3 1],[3 2],[1 2],[2 0],[0 1] - //)igl_Qu8mg5v7"; -const char *__doc_igl_edge_topology = R"igl_Qu8mg5v7(// Initialize Edges and their topological relations (assumes an edge-manifold - // mesh) - // - // Output: - // EV : #Ex2, Stores the edge description as pair of indices to vertices - // FE : #Fx3, Stores the Triangle-Edge relation - // EF : #Ex2: Stores the Edge-Triangle relation - // - // TODO: This seems to be a inferior duplicate of edge_flaps.h: - // - unused input parameter V - // - roughly 2x slower than edge_flaps - // - outputs less information: edge_flaps reveals corner opposite edge - // - FE uses non-standard and ambiguous order: FE(f,c) is merely an edge - // incident on corner c of face f. In contrast, edge_flaps's EMAP(f,c) reveals - // the edge _opposite_ corner c of face f)igl_Qu8mg5v7"; -const char *__doc_igl_eigs = R"igl_Qu8mg5v7(See eigs for the documentation.)igl_Qu8mg5v7"; -const char *__doc_igl_embree_ambient_occlusion = R"igl_Qu8mg5v7(// Compute ambient occlusion per given point - // - // Inputs: - // ei EmbreeIntersector containing (V,F) - // P #P by 3 list of origin points - // N #P by 3 list of origin normals - // Outputs: - // S #P list of ambient occlusion values between 1 (fully occluded) and - // 0 (not occluded) - //)igl_Qu8mg5v7"; -const char *__doc_igl_embree_line_mesh_intersection = R"igl_Qu8mg5v7(// Project the point cloud V_source onto the triangle mesh - // V_target,F_target. - // A ray is casted for every vertex in the direction specified by - // N_source and its opposite. - // - // Input: - // V_source: #Vx3 Vertices of the source mesh - // N_source: #Vx3 Normals of the point cloud - // V_target: #V2x3 Vertices of the target mesh - // F_target: #F2x3 Faces of the target mesh - // - // Output: - // #Vx3 matrix of baricentric coordinate. Each row corresponds to - // a vertex of the projected mesh and it has the following format: - // id b1 b2. id is the id of a face of the source mesh. b1 and b2 are - // the barycentric coordinates wrt the first two edges of the triangle - // To convert to standard global coordinates, see barycentric_to_global.h)igl_Qu8mg5v7"; -const char *__doc_igl_embree_reorient_facets_raycast = R"igl_Qu8mg5v7(// Orient each component (identified by C) of a mesh (V,F) using ambient - // occlusion such that the front side is less occluded than back side, as - // described in "A Simple Method for Correcting Facet Orientations in - // Polygon Meshes Based on Ray Casting" [Takayama et al. 2014]. - // - // Inputs: - // V #V by 3 list of vertex positions - // F #F by 3 list of triangle indices - // rays_total Total number of rays that will be shot - // rays_minimum Minimum number of rays that each patch should receive - // facet_wise Decision made for each face independently, no use of patches - // (i.e., each face is treated as a patch) - // use_parity Use parity mode - // is_verbose Verbose output to cout - // Outputs: - // I #F list of whether face has been flipped - // C #F list of patch ID (output of bfs_orient > manifold patches))igl_Qu8mg5v7"; -const char *__doc_igl_exact_geodesic = R"igl_Qu8mg5v7( - // Exact geodesic algorithm for triangular mesh with the implementation from https://code.google.com/archive/p/geodesic/, - // and the algorithm first described by Mitchell, Mount and Papadimitriou in 1987 - // - // Inputs: - // V #V by 3 list of 3D vertex positions - // F #F by 3 list of mesh faces - // VS #VS by 1 vector specifying indices of source vertices - // FS #FS by 1 vector specifying indices of source faces - // VT #VT by 1 vector specifying indices of target vertices - // FT #FT by 1 vector specifying indices of target faces - // Output: - // D #VT+#FT by 1 vector of geodesic distances of each target w.r.t. the nearest one in the source set - // - // Note: - // Specifying a face as target/source means its center. - //)igl_Qu8mg5v7"; -const char *__doc_igl_heat_geodesics_precompute = R"igl_Qu8mg5v7( - // Precompute factorized solvers for computing a fast approximation of - // geodesic distances on a mesh (V,F). [Crane et al. 2013] - // - // Inputs: - // V #V by dim list of mesh vertex positions - // F #F by 3 list of mesh face indices into V - // Outputs: - // data precomputation data (see heat_geodesics_solve) - //)igl_Qu8mg5v7"; -const char *__doc_igl_heat_geodesics_solve = R"igl_Qu8mg5v7( - // Compute fast approximate geodesic distances using precomputed data from a - // set of selected source vertices (gamma) - // - // Inputs: - // data precomputation data (see heat_geodesics_precompute) - // gamma #gamma list of indices into V of source vertices - // Outputs: - // D #V list of distances to gamma - //)igl_Qu8mg5v7"; -const char *__doc_igl_find_cross_field_singularities = R"igl_Qu8mg5v7(// Inputs: - // V #V by 3 eigen Matrix of mesh vertex 3D positions - // F #F by 3 eigen Matrix of face (quad) indices - // Handle_MMatch #F by 3 eigen Matrix containing the integer mismatch of the cross field - // across all face edges - // Output: - // isSingularity #V by 1 boolean eigen Vector indicating the presence of a singularity on a vertex - // singularityIndex #V by 1 integer eigen Vector containing the singularity indices - //)igl_Qu8mg5v7"; -const char *__doc_igl_fit_rotations = R"igl_Qu8mg5v7(// Known issues: This seems to be implemented in Eigen/Geometry: - // Eigen::umeyama - // - // FIT_ROTATIONS Given an input mesh and new positions find rotations for - // every covariance matrix in a stack of covariance matrices - // - // Inputs: - // S nr*dim by dim stack of covariance matrices - // single_precision whether to use single precision (faster) - // Outputs: - // R dim by dim * nr list of rotations - //)igl_Qu8mg5v7"; -const char *__doc_igl_fit_rotations_planar = R"igl_Qu8mg5v7(// FIT_ROTATIONS Given an input mesh and new positions find 2D rotations for - // every vertex that best maps its one ring to the new one ring - // - // Inputs: - // S nr*dim by dim stack of covariance matrices, third column and every - // third row will be ignored - // Outputs: - // R dim by dim * nr list of rotations, third row and third column of each - // rotation will just be identity - //)igl_Qu8mg5v7"; -const char *__doc_igl_fit_rotations_SSE = R"igl_Qu8mg5v7(See fit_rotations_SSE for the documentation.)igl_Qu8mg5v7"; -const char *__doc_igl_floor = R"igl_Qu8mg5v7(// Floor a given matrix to nearest integers - // - // Inputs: - // X m by n matrix of scalars - // Outputs: - // Y m by n matrix of floored integers)igl_Qu8mg5v7"; -const char *__doc_igl_forward_kinematics = R"igl_Qu8mg5v7(// Given a skeleton and a set of relative bone rotations compute absolute - // rigid transformations for each bone. - // - // Inputs: - // C #C by dim list of joint positions - // BE #BE by 2 list of bone edge indices - // P #BE list of parent indices into BE - // dQ #BE list of relative rotations - // dT #BE list of relative translations - // Outputs: - // vQ #BE list of absolute rotations - // vT #BE list of absolute translations)igl_Qu8mg5v7"; -const char *__doc_igl_gaussian_curvature = R"igl_Qu8mg5v7(// Compute discrete local integral gaussian curvature (angle deficit, without - // averaging by local area). - // - // Inputs: - // V #V by 3 eigen Matrix of mesh vertex 3D positions - // F #F by 3 eigen Matrix of face (triangle) indices - // Output: - // K #V by 1 eigen Matrix of discrete gaussian curvature values - //)igl_Qu8mg5v7"; -const char *__doc_igl_get_seconds = R"igl_Qu8mg5v7(// Return the current time in seconds since program start - // - // Example: - // const auto & tictoc = []() - // { - // static double t_start = igl::get_seconds(); - // double diff = igl::get_seconds()-t_start; - // t_start += diff; - // return diff; - // }; - // tictoc(); - // ... // part 1 - // cout<<"part 1: "< - //IGL_INLINE void winding_number_3( - // const double * V, - // const int n, - // const DerivedF * F, - // const int m, - // const double * O, - // double * S); - // 2d)igl_Qu8mg5v7"; -const char *__doc_igl_writeMESH = R"igl_Qu8mg5v7(// save a tetrahedral volume mesh to a .mesh file - // - // Templates: - // Scalar type for positions and vectors (will be cast as double) - // Index type for indices (will be cast to int) - // Input: - // mesh_file_name path of .mesh file - // V double matrix of vertex positions #V by 3 - // T #T list of tet indices into vertex positions - // F #F list of face indices into vertex positions - // - // Known bugs: Holes and regions are not supported)igl_Qu8mg5v7"; -const char *__doc_igl_writeOBJ = R"igl_Qu8mg5v7(// Write a mesh in an ascii obj file - // Inputs: - // str path to outputfile - // V #V by 3 mesh vertex positions - // F #F by 3|4 mesh indices into V - // CN #CN by 3 normal vectors - // FN #F by 3|4 corner normal indices into CN - // TC #TC by 2|3 texture coordinates - // FTC #F by 3|4 corner texture coord indices into TC - // Returns true on success, false on error - // - // Known issues: Horrifyingly, this does not have the same order of - // parameters as readOBJ.)igl_Qu8mg5v7"; -const char *__doc_igl_writePLY = R"igl_Qu8mg5v7(// Write a mesh in an ascii ply file - // Inputs: - // str path to outputfile - // V #V by 3 mesh vertex positions - // F #F by 3 mesh indices into V - // N #V by 3 normal vectors - // UV #V by 2 texture coordinates - // Returns true on success, false on error)igl_Qu8mg5v7"; -const char *__doc_igl_readPLY= R"igl_Qu8mg5v7(// Read a mesh from an ascii ply file, filling in vertex positions, - // mesh indices, normals and texture coordinates - // Inputs: - // str path to .obj file - // Outputs: - // V double matrix of vertex positions #V by 3 - // F #F list of face indices into vertex positions - // N double matrix of corner normals #N by 3 - // UV #V by 2 texture coordinates - // Returns true on success, false on errors)igl_Qu8mg5v7"; -const char *__doc_igl_seam_edges=R"igl_Qu8mg5v7(// Finds all UV-space boundaries of a mesh. - // - // Inputs: - // V #V by dim list of positions of the input mesh. - // TC #TC by 2 list of 2D texture coordinates of the input mesh - // F #F by 3 list of triange indices into V representing a - // manifold-with-boundary triangle mesh - // FTC #F by 3 list of indices into TC for each corner - // Outputs: - // seams Edges where the forwards and backwards directions have different - // texture coordinates, as a #seams-by-4 matrix of indices. Each row is - // organized as [ forward_face_index, forward_face_vertex_index, - // backwards_face_index, backwards_face_vertex_index ] such that one side - // of the seam is the edge: - // F[ seams( i, 0 ), seams( i, 1 ) ], F[ seams( i, 0 ), (seams( i, 1 ) + 1) % 3 ] - // and the other side is the edge: - // F[ seams( i, 2 ), seams( i, 3 ) ], F[ seams( i, 2 ), (seams( i, 3 ) + 1) % 3 ] - // boundaries Edges with only one incident triangle, as a #boundaries-by-2 - // matrix of indices. Each row is organized as - // [ face_index, face_vertex_index ] - // such that the edge is: - // F[ boundaries( i, 0 ), boundaries( i, 1 ) ], F[ boundaries( i, 0 ), (boundaries( i, 1 ) + 1) % 3 ] - // foldovers Edges where the two incident triangles fold over each other - // in UV-space, as a #foldovers-by-4 matrix of indices. - // Each row is organized as [ forward_face_index, forward_face_vertex_index, - // backwards_face_index, backwards_face_vertex_index ] - // such that one side of the foldover is the edge: - // F[ foldovers( i, 0 ), foldovers( i, 1 ) ], F[ foldovers( i, 0 ), (foldovers( i, 1 ) + 1) % 3 ] - // and the other side is the edge: - // F[ foldovers( i, 2 ), foldovers( i, 3 ) ], F[ foldovers( i, 2 ), (foldovers( i, 3 ) + 1) % 3 ])igl_Qu8mg5v7"; diff --git a/python/py_doc.h b/python/py_doc.h deleted file mode 100644 index 3aab0fb28..000000000 --- a/python/py_doc.h +++ /dev/null @@ -1,132 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -extern const char *__doc_igl_active_set; -extern const char *__doc_igl_adjacency_list; -extern const char *__doc_igl_arap_precomputation; -extern const char *__doc_igl_arap_solve; -extern const char *__doc_igl_avg_edge_length; -extern const char *__doc_igl_barycenter; -extern const char *__doc_igl_barycentric_coordinates; -extern const char *__doc_igl_barycentric_to_global; -extern const char *__doc_igl_bbw; -extern const char *__doc_igl_boundary_conditions; -extern const char *__doc_igl_boundary_facets; -extern const char *__doc_igl_boundary_loop; -extern const char *__doc_igl_cat; -extern const char *__doc_igl_collapse_edge; -extern const char *__doc_igl_colon; -extern const char *__doc_igl_column_to_quats; -extern const char *__doc_igl_comb_cross_field; -extern const char *__doc_igl_comb_frame_field; -extern const char *__doc_igl_compute_frame_field_bisectors; -extern const char *__doc_igl_copyleft_cgal_mesh_boolean; -extern const char *__doc_igl_copyleft_cgal_remesh_self_intersections; -extern const char *__doc_igl_copyleft_comiso_miq; -extern const char *__doc_igl_copyleft_comiso_nrosy; -extern const char *__doc_igl_copyleft_marching_cubes; -extern const char *__doc_igl_copyleft_swept_volume; -extern const char *__doc_igl_copyleft_tetgen_tetrahedralize; -extern const char *__doc_igl_cotmatrix; -extern const char *__doc_igl_covariance_scatter_matrix; -extern const char *__doc_igl_cross_field_mismatch; -extern const char *__doc_igl_cut_mesh_from_singularities; -extern const char *__doc_igl_deform_skeleton; -extern const char *__doc_igl_directed_edge_orientations; -extern const char *__doc_igl_directed_edge_parents; -extern const char *__doc_igl_doublearea; -extern const char *__doc_igl_doublearea_single; -extern const char *__doc_igl_doublearea_quad; -extern const char *__doc_igl_dqs; -extern const char *__doc_igl_edge_lengths; -extern const char *__doc_igl_edge_topology; -extern const char *__doc_igl_eigs; -extern const char *__doc_igl_embree_ambient_occlusion; -extern const char *__doc_igl_embree_line_mesh_intersection; -extern const char *__doc_igl_embree_reorient_facets_raycast; -extern const char *__doc_igl_exact_geodesic; -extern const char *__doc_igl_heat_geodesics_precompute; -extern const char *__doc_igl_heat_geodesics_solve; -extern const char *__doc_igl_find_cross_field_singularities; -extern const char *__doc_igl_fit_rotations; -extern const char *__doc_igl_fit_rotations_planar; -extern const char *__doc_igl_fit_rotations_SSE; -extern const char *__doc_igl_floor; -extern const char *__doc_igl_forward_kinematics; -extern const char *__doc_igl_gaussian_curvature; -extern const char *__doc_igl_get_seconds; -extern const char *__doc_igl_grad; -extern const char *__doc_igl_harmonic; -extern const char *__doc_igl_hsv_to_rgb; -extern const char *__doc_igl_internal_angles; -extern const char *__doc_igl_internal_angles_using_squared_edge_lengths; -extern const char *__doc_igl_internal_angles_using_edge_lengths; -extern const char *__doc_igl_invert_diag; -extern const char *__doc_igl_is_irregular_vertex; -extern const char *__doc_igl_jet; -extern const char *__doc_igl_lbs_matrix; -extern const char *__doc_igl_lbs_matrix_column; -extern const char *__doc_igl_local_basis; -extern const char *__doc_igl_lscm; -extern const char *__doc_igl_map_vertices_to_circle; -extern const char *__doc_igl_massmatrix; -extern const char *__doc_igl_min_quad_with_fixed_precompute; -extern const char *__doc_igl_min_quad_with_fixed_solve; -extern const char *__doc_igl_min_quad_with_fixed; -extern const char *__doc_igl_normalize_row_lengths; -extern const char *__doc_igl_normalize_row_sums; -extern const char *__doc_igl_parula; -extern const char *__doc_igl_per_corner_normals; -extern const char *__doc_igl_per_edge_normals; -extern const char *__doc_igl_per_face_normals; -extern const char *__doc_igl_per_face_normals_stable; -extern const char *__doc_igl_per_vertex_normals; -extern const char *__doc_igl_planarize_quad_mesh; -extern const char *__doc_igl_png_readPNG; -extern const char *__doc_igl_png_writePNG; -extern const char *__doc_igl_point_mesh_squared_distance; -extern const char *__doc_igl_polar_svd; -extern const char *__doc_igl_principal_curvature; -extern const char *__doc_igl_quad_planarity; -extern const char *__doc_igl_randperm; -extern const char *__doc_igl_readDMAT; -extern const char *__doc_igl_readMESH; -extern const char *__doc_igl_readOBJ; -extern const char *__doc_igl_readOFF; -extern const char *__doc_igl_readTGF; -extern const char *__doc_igl_read_triangle_mesh; -extern const char *__doc_igl_remove_duplicate_vertices; -extern const char *__doc_igl_rotate_vectors; -extern const char *__doc_igl_seam_edges; -extern const char *__doc_igl_setdiff; -extern const char *__doc_igl_shape_diameter_function; -extern const char *__doc_igl_signed_distance; -extern const char *__doc_igl_signed_distance_pseudonormal; -extern const char *__doc_igl_signed_distance_winding_number; -extern const char *__doc_igl_slice; -extern const char *__doc_igl_slice_into; -extern const char *__doc_igl_slice_mask; -extern const char *__doc_igl_marching_tets; -extern const char *__doc_igl_sortrows; -extern const char *__doc_igl_streamlines_init; -extern const char *__doc_igl_streamlines_next; -extern const char *__doc_igl_triangle_triangle_adjacency; -extern const char *__doc_igl_triangle_triangle_adjacency_preprocess; -extern const char *__doc_igl_triangle_triangle_adjacency_extractTT; -extern const char *__doc_igl_triangle_triangle_adjacency_extractTTi; -extern const char *__doc_igl_triangle_triangulate; -extern const char *__doc_igl_unique; -extern const char *__doc_igl_unique_rows; -extern const char *__doc_igl_unproject_onto_mesh; -extern const char *__doc_igl_upsample; -extern const char *__doc_igl_winding_number; -extern const char *__doc_igl_winding_number_3; -extern const char *__doc_igl_winding_number_2; -extern const char *__doc_igl_writeMESH; -extern const char *__doc_igl_writeOBJ; -extern const char *__doc_igl_writePLY; -extern const char *__doc_igl_readPLY; diff --git a/python/py_igl.cpp b/python/py_igl.cpp deleted file mode 100644 index 34dad1ced..000000000 --- a/python/py_igl.cpp +++ /dev/null @@ -1,208 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -#include - -#include "python_shared.h" - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -void python_export_igl(py::module &m) -{ -#include "modules/py_typedefs.cpp" - -#include "py_igl/py_AABB.cpp" -#include "py_igl/py_ARAPEnergyType.cpp" -#include "py_igl/py_MeshBooleanType.cpp" -#include "py_igl/py_SolverStatus.cpp" -#include "py_igl/py_active_set.cpp" -#include "py_igl/py_adjacency_list.cpp" -#include "py_igl/py_adjacency_matrix.cpp" -#include "py_igl/py_arap.cpp" -#include "py_igl/py_avg_edge_length.cpp" -#include "py_igl/py_barycenter.cpp" -#include "py_igl/py_barycentric_coordinates.cpp" -#include "py_igl/py_barycentric_to_global.cpp" -#include "py_igl/py_bbw.cpp" -#include "py_igl/py_boundary_conditions.cpp" -#include "py_igl/py_boundary_facets.cpp" -#include "py_igl/py_boundary_loop.cpp" -#include "py_igl/py_cat.cpp" -#include "py_igl/py_collapse_edge.cpp" -#include "py_igl/py_colon.cpp" -#include "py_igl/py_column_to_quats.cpp" -#include "py_igl/py_comb_cross_field.cpp" -#include "py_igl/py_comb_frame_field.cpp" -#include "py_igl/py_compute_frame_field_bisectors.cpp" -#include "py_igl/py_cotmatrix.cpp" -#include "py_igl/py_covariance_scatter_matrix.cpp" -#include "py_igl/py_cross_field_mismatch.cpp" -#include "py_igl/py_cut_mesh_from_singularities.cpp" -#include "py_igl/py_deform_skeleton.cpp" -#include "py_igl/py_directed_edge_orientations.cpp" -#include "py_igl/py_directed_edge_parents.cpp" -#include "py_igl/py_doublearea.cpp" -#include "py_igl/py_dqs.cpp" -#include "py_igl/py_edge_lengths.cpp" -#include "py_igl/py_edge_topology.cpp" -#include "py_igl/py_eigs.cpp" -#include "py_igl/py_exact_geodesic.cpp" -#include "py_igl/py_heat_geodesics.cpp" -#include "py_igl/py_find_cross_field_singularities.cpp" -#include "py_igl/py_fit_rotations.cpp" -#include "py_igl/py_floor.cpp" -#include "py_igl/py_forward_kinematics.cpp" -#include "py_igl/py_gaussian_curvature.cpp" -#include "py_igl/py_get_seconds.cpp" -#include "py_igl/py_grad.cpp" -#include "py_igl/py_harmonic.cpp" -#include "py_igl/py_hsv_to_rgb.cpp" -#include "py_igl/py_internal_angles.cpp" -#include "py_igl/py_invert_diag.cpp" -#include "py_igl/py_is_irregular_vertex.cpp" -#include "py_igl/py_jet.cpp" -#include "py_igl/py_lbs_matrix.cpp" -#include "py_igl/py_local_basis.cpp" -#include "py_igl/py_lscm.cpp" -#include "py_igl/py_map_vertices_to_circle.cpp" -#include "py_igl/py_massmatrix.cpp" -#include "py_igl/py_min_quad_with_fixed.cpp" -#include "py_igl/py_normalize_row_lengths.cpp" -#include "py_igl/py_normalize_row_sums.cpp" -#include "py_igl/py_parula.cpp" -#include "py_igl/py_per_corner_normals.cpp" -#include "py_igl/py_per_edge_normals.cpp" -#include "py_igl/py_per_face_normals.cpp" -#include "py_igl/py_per_vertex_normals.cpp" -#include "py_igl/py_planarize_quad_mesh.cpp" -#include "py_igl/py_point_mesh_squared_distance.cpp" -#include "py_igl/py_polar_svd.cpp" -#include "py_igl/py_principal_curvature.cpp" -#include "py_igl/py_quad_planarity.cpp" -#include "py_igl/py_randperm.cpp" -#include "py_igl/py_readDMAT.cpp" -#include "py_igl/py_readMESH.cpp" -#include "py_igl/py_readOBJ.cpp" -#include "py_igl/py_readOFF.cpp" -#include "py_igl/py_readTGF.cpp" -#include "py_igl/py_read_triangle_mesh.cpp" -#include "py_igl/py_remove_duplicate_vertices.cpp" -#include "py_igl/py_rotate_vectors.cpp" -#include "py_igl/py_setdiff.cpp" -#include "py_igl/py_shape_diameter_function.cpp" -#include "py_igl/py_signed_distance.cpp" -#include "py_igl/py_slice.cpp" -#include "py_igl/py_slice_into.cpp" -#include "py_igl/py_slice_mask.cpp" -#include "py_igl/py_marching_tets.cpp" -#include "py_igl/py_sortrows.cpp" -#include "py_igl/py_triangle_triangle_adjacency.cpp" -#include "py_igl/py_unique.cpp" -#include "py_igl/py_unproject_onto_mesh.cpp" -#include "py_igl/py_upsample.cpp" -#include "py_igl/py_winding_number.cpp" -#include "py_igl/py_writeMESH.cpp" -#include "py_igl/py_writeOBJ.cpp" -#include "py_igl/py_writePLY.cpp" -#include "py_igl/py_readPLY.cpp" -#include "py_igl/py_seam_edges.cpp" -} diff --git a/python/py_igl/copyleft/cgal/py_RemeshSelfIntersectionsParam.cpp b/python/py_igl/copyleft/cgal/py_RemeshSelfIntersectionsParam.cpp deleted file mode 100644 index d0cb8ebde..000000000 --- a/python/py_igl/copyleft/cgal/py_RemeshSelfIntersectionsParam.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -py::class_ RemeshSelfIntersectionsParam(m, "RemeshSelfIntersectionsParam"); - -RemeshSelfIntersectionsParam -.def("__init__", [](igl::copyleft::cgal::RemeshSelfIntersectionsParam &m) -{ - new (&m) igl::copyleft::cgal::RemeshSelfIntersectionsParam(); - m.detect_only = false; - m.first_only = false; - m.stitch_all = false; -}) -.def_readwrite("detect_only", &igl::copyleft::cgal::RemeshSelfIntersectionsParam::detect_only) -.def_readwrite("first_only", &igl::copyleft::cgal::RemeshSelfIntersectionsParam::first_only) -.def_readwrite("stitch_all", &igl::copyleft::cgal::RemeshSelfIntersectionsParam::stitch_all) -; diff --git a/python/py_igl/copyleft/cgal/py_mesh_boolean.cpp b/python/py_igl/copyleft/cgal/py_mesh_boolean.cpp deleted file mode 100644 index 2728943fa..000000000 --- a/python/py_igl/copyleft/cgal/py_mesh_boolean.cpp +++ /dev/null @@ -1,114 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -// COMPLETE BINDINGS ======================== - -m.def("mesh_boolean", [] -( - const Eigen::MatrixXd& VA, - const Eigen::MatrixXi& FA, - const Eigen::MatrixXd& VB, - const Eigen::MatrixXi& FB, - igl::MeshBooleanType & type, - Eigen::MatrixXd& VC, - Eigen::MatrixXi& FC, - Eigen::MatrixXi& J -) -{ - return igl::copyleft::cgal::mesh_boolean(VA, FA, VB, FB, type, VC, FC, J); -}, __doc_igl_copyleft_cgal_mesh_boolean, -py::arg("VA"), py::arg("FA"), py::arg("VB"), py::arg("FB"), py::arg("type"), py::arg("VC"), py::arg("FC"), py::arg("J")); - - -m.def("mesh_boolean", [] -( - const Eigen::MatrixXd& VA, - const Eigen::MatrixXi& FA, - const Eigen::MatrixXd& VB, - const Eigen::MatrixXi& FB, - const std::string & type_str, - Eigen::MatrixXd& VC, - Eigen::MatrixXi& FC, - Eigen::MatrixXi& J -) -{ - return igl::copyleft::cgal::mesh_boolean(VA, FA, VB, FB, type_str, VC, FC, J); -}, __doc_igl_copyleft_cgal_mesh_boolean, -py::arg("VA"), py::arg("FA"), py::arg("VB"), py::arg("FB"), py::arg("type_str"), py::arg("VC"), py::arg("FC"), py::arg("J")); - -m.def("mesh_boolean", [] -( - const Eigen::MatrixXd& VA, - const Eigen::MatrixXi& FA, - const Eigen::MatrixXd& VB, - const Eigen::MatrixXi& FB, - const igl::MeshBooleanType & type, - Eigen::MatrixXd& VC, - Eigen::MatrixXi& FC -) -{ - return igl::copyleft::cgal::mesh_boolean(VA, FA, VB, FB, type, VC, FC); -}, __doc_igl_copyleft_cgal_mesh_boolean, -py::arg("VA"), py::arg("FA"), py::arg("VB"), py::arg("FB"), py::arg("type"), py::arg("VC"), py::arg("FC")); - - - -// INCOMPLETE BINDINGS ======================== - - - - -//m.def("mesh_boolean", [] -//( -// const Eigen::MatrixXd& VA, -// const Eigen::MatrixXd& FA, -// const Eigen::MatrixXd& VB, -// const Eigen::MatrixXd& FB, -// std::function)> & wind_num_op, -// std::function & keep, -// Eigen::MatrixXd& VC, -// Eigen::MatrixXd& FC, -// Eigen::MatrixXd& J -//) -//{ -// return igl::copyleft::cgal::mesh_boolean(VA, FA, VB, FB, wind_num_op, keep, VC, FC, J); -//}, __doc_igl_copyleft_cgal_mesh_boolean, -//py::arg("VA"), py::arg("FA"), py::arg("VB"), py::arg("FB"), py::arg("wind_num_op"), py::arg("keep"), py::arg("VC"), py::arg("FC"), py::arg("J")); - -//m.def("mesh_boolean", [] -//( -// std::vector & Vlist, -// std::vector & Flist, -// std::function)> & wind_num_op, -// std::function & keep, -// Eigen::MatrixXd& VC, -// Eigen::MatrixXd& FC, -// Eigen::MatrixXd& J -//) -//{ -// return igl::copyleft::cgal::mesh_boolean(Vlist, Flist, wind_num_op, keep, VC, FC, J); -//}, __doc_igl_copyleft_cgal_mesh_boolean, -//py::arg("Vlist"), py::arg("Flist"), py::arg("wind_num_op"), py::arg("keep"), py::arg("VC"), py::arg("FC"), py::arg("J")); - -//m.def("mesh_boolean", [] -//( -// const Eigen::MatrixXd& VV, -// const Eigen::MatrixXd& FF, -// const Eigen::MatrixXd& sizes, -// std::function)> & wind_num_op, -// std::function & keep, -// Eigen::MatrixXd& VC, -// Eigen::MatrixXd& FC, -// Eigen::MatrixXd& J -//) -//{ -// return igl::copyleft::cgal::mesh_boolean(VV, FF, sizes, wind_num_op, keep, VC, FC, J); -//}, __doc_igl_copyleft_cgal_mesh_boolean, -//py::arg("VV"), py::arg("FF"), py::arg("sizes"), py::arg("wind_num_op"), py::arg("keep"), py::arg("VC"), py::arg("FC"), py::arg("J")); - - - diff --git a/python/py_igl/copyleft/cgal/py_remesh_self_intersections.cpp b/python/py_igl/copyleft/cgal/py_remesh_self_intersections.cpp deleted file mode 100644 index f466f1bcd..000000000 --- a/python/py_igl/copyleft/cgal/py_remesh_self_intersections.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("remesh_self_intersections", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const igl::copyleft::cgal::RemeshSelfIntersectionsParam& params, - Eigen::MatrixXd& VV, - Eigen::MatrixXi& FF, - Eigen::MatrixXi& IF, - Eigen::MatrixXi& J, - Eigen::MatrixXi& IM -) -{ - assert_is_VectorX("J", J); - assert_is_VectorX("IM", IM); - Eigen::VectorXi Jt; - Eigen::VectorXi IMt; - igl::copyleft::cgal::remesh_self_intersections(V, F, params, VV, FF, IF, Jt, IMt); - J = Jt; - IM = IMt; -}, __doc_igl_copyleft_cgal_remesh_self_intersections, -py::arg("V"), py::arg("F"), py::arg("params"), py::arg("VV") -, py::arg("FF"), py::arg("IF"), py::arg("J"), py::arg("IM")); \ No newline at end of file diff --git a/python/py_igl/copyleft/comiso/py_miq.cpp b/python/py_igl/copyleft/comiso/py_miq.cpp deleted file mode 100644 index bc8d2094f..000000000 --- a/python/py_igl/copyleft/comiso/py_miq.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("miq", [] -( - const Eigen::MatrixXd &V, - const Eigen::MatrixXi &F, - const Eigen::MatrixXd &PD1, - const Eigen::MatrixXd &PD2, - Eigen::MatrixXd &UV, - Eigen::MatrixXi &FUV, - double scale, - double stiffness, - bool directRound, - int iter, - int localIter, - bool doRound, - bool singularityRound -) -{ - std::vector roundVertices; - std::vector > hardFeatures; - - igl::copyleft::comiso::miq(V, F, PD1, PD2, UV, FUV, scale, stiffness, directRound, iter, localIter, doRound, singularityRound, roundVertices, hardFeatures); -}, __doc_igl_copyleft_comiso_miq, -py::arg("V"), py::arg("F"), py::arg("PD1"), py::arg("PD2"), py::arg("UV"), py::arg("FUV"), py::arg("scale") = 30.0, py::arg("stiffness") = 5.0, py::arg("directRound") = false, py::arg("iter") = 5, py::arg("localIter") = 5, py::arg("doRound") = true, py::arg("singularityRound") = true -); - -m.def("miq", [] -( - const Eigen::MatrixXd &V, - const Eigen::MatrixXi &F, - const Eigen::MatrixXd &PD1_combed, - const Eigen::MatrixXd &PD2_combed, - const Eigen::MatrixXi &mismatch, - const Eigen::MatrixXi &singular, - const Eigen::MatrixXi &seams, - Eigen::MatrixXd &UV, - Eigen::MatrixXi &FUV, - double gradientSize, - double stiffness, - bool directRound, - int iter, - int localIter, - bool doRound, - bool singularityRound -) -{ - assert_is_VectorX("singular",singular); - - std::vector roundVertices; - std::vector > hardFeatures; - - igl::copyleft::comiso::miq(V, F, PD1_combed, PD2_combed, mismatch, singular, seams, UV, FUV, gradientSize, stiffness, directRound, iter, localIter, doRound, singularityRound, roundVertices, hardFeatures); -}, __doc_igl_copyleft_comiso_miq, -py::arg("V"), py::arg("F"), py::arg("PD1_combed"), py::arg("PD2_combed"), -py::arg("mismatch"), py::arg("singular"), py::arg("seams"), -py::arg("UV"), py::arg("FUV"), py::arg("gradientSize") = 30.0, py::arg("stiffness") = 5.0, py::arg("directRound") = false, py::arg("iter") = 5, py::arg("localIter") = 5, py::arg("doRound") = true, py::arg("singularityRound") = true -); diff --git a/python/py_igl/copyleft/comiso/py_nrosy.cpp b/python/py_igl/copyleft/comiso/py_nrosy.cpp deleted file mode 100644 index 33c8e6412..000000000 --- a/python/py_igl/copyleft/comiso/py_nrosy.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("nrosy", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::MatrixXi& b, - const Eigen::MatrixXd& bc, - const Eigen::MatrixXi& b_soft, - const Eigen::MatrixXd& w_soft, - const Eigen::MatrixXd& bc_soft, - const int N, - const double soft, - Eigen::MatrixXd& R, - Eigen::MatrixXd& S -) -{ - assert_is_VectorX("b",b); - assert_is_VectorX("b_soft",b_soft); - assert_is_VectorX("w_soft",w_soft); - - Eigen::VectorXi bt; - if (b.size() != 0) - bt = b; - - Eigen::VectorXi b_softt; - if (b_soft.size() != 0) - b_softt = b_soft; - - Eigen::VectorXd w_softt; - if (w_soft.size() != 0) - w_softt = w_soft; - - Eigen::VectorXd St; - igl::copyleft::comiso::nrosy(V,F,bt,bc,b_softt,w_softt,bc_soft,N,soft,R,St); - S = St; - -}, __doc_igl_copyleft_comiso_nrosy, -py::arg("V"), py::arg("F"), py::arg("b"), py::arg("bc"), py::arg("b_soft"), py::arg("w_soft"), py::arg("bc_soft"), py::arg("N"), py::arg("soft"), py::arg("R"), py::arg("S")); - -m.def("nrosy", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::MatrixXi& b, - const Eigen::MatrixXd& bc, - const int N, - Eigen::MatrixXd& R, - Eigen::MatrixXd& S -) -{ - assert_is_VectorX("b",b); - - Eigen::VectorXi bt; - if (b.size() != 0) - bt = b; - - Eigen::VectorXd St; - igl::copyleft::comiso::nrosy(V,F,bt,bc,N,R,St); - S = St; -}, __doc_igl_copyleft_comiso_nrosy, -py::arg("V"), py::arg("F"), py::arg("b"), py::arg("bc"), py::arg("N"), py::arg("R"), py::arg("S")); diff --git a/python/py_igl/copyleft/py_marching_cubes.cpp b/python/py_igl/copyleft/py_marching_cubes.cpp deleted file mode 100644 index 24c946302..000000000 --- a/python/py_igl/copyleft/py_marching_cubes.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - - -m.def("marching_cubes", [] -( - const Eigen::MatrixXd& values, - const Eigen::MatrixXd& points, - const unsigned int x_res, - const unsigned int y_res, - const unsigned int z_res, - Eigen::MatrixXd& vertices, - Eigen::MatrixXi& faces -) -{ - assert_is_VectorX("values", values); - Eigen::VectorXd valuesv; - if (values.size() != 0) - valuesv = values; - return igl::copyleft::marching_cubes(valuesv, points, x_res, y_res, z_res, vertices, faces); -}, __doc_igl_copyleft_marching_cubes, -py::arg("values"), py::arg("points"), py::arg("x_res"), py::arg("y_res"), py::arg("z_res"), py::arg("vertices"), py::arg("faces")); - diff --git a/python/py_igl/copyleft/py_swept_volume.cpp b/python/py_igl/copyleft/py_swept_volume.cpp deleted file mode 100644 index a59b1efff..000000000 --- a/python/py_igl/copyleft/py_swept_volume.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - -m.def("swept_volume", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const std::function & transform, - const size_t steps, - const size_t grid_res, - const size_t isolevel, - Eigen::MatrixXd& SV, - Eigen::MatrixXi& SF -) -{ - return igl::copyleft::swept_volume(V, F, transform, steps, grid_res, isolevel, SV, SF); -}, __doc_igl_copyleft_swept_volume, -py::arg("V"), py::arg("F"), py::arg("transform"), py::arg("steps"), py::arg("grid_res"), py::arg("isolevel"), py::arg("SV"), py::arg("SF")); - - - diff --git a/python/py_igl/copyleft/tetgen/py_tetrahedralize.cpp b/python/py_igl/copyleft/tetgen/py_tetrahedralize.cpp deleted file mode 100644 index fe798842d..000000000 --- a/python/py_igl/copyleft/tetgen/py_tetrahedralize.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - -m.def("tetrahedralize", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const std::string switches, - Eigen::MatrixXd& TV, - Eigen::MatrixXi& TT, - Eigen::MatrixXi& TF -) -{ - return igl::copyleft::tetgen::tetrahedralize(V, F, switches, TV, TT, TF); -}, __doc_igl_copyleft_tetgen_tetrahedralize, -py::arg("V"), py::arg("F"), py::arg("switches"), py::arg("TV"), py::arg("TT"), py::arg("TF")); - -m.def("tetrahedralize", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::MatrixXi& VM, - const Eigen::MatrixXi& FM, - const std::string switches, - Eigen::MatrixXd& TV, - Eigen::MatrixXi& TT, - Eigen::MatrixXi& TF, - Eigen::MatrixXi& TM -) -{ - return igl::copyleft::tetgen::tetrahedralize(V, F, VM, FM, switches, TV, TT, TF, TM); -}, __doc_igl_copyleft_tetgen_tetrahedralize, -py::arg("V"), py::arg("F"), py::arg("VM"), py::arg("FM"), py::arg("switches"), py::arg("TV"), py::arg("TT"), py::arg("TF"), py::arg("TM")); - diff --git a/python/py_igl/embree/py_ambient_occlusion.cpp b/python/py_igl/embree/py_ambient_occlusion.cpp deleted file mode 100644 index 399e55b16..000000000 --- a/python/py_igl/embree/py_ambient_occlusion.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - - -m.def("ambient_occlusion", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::MatrixXd& P, - const Eigen::MatrixXd& N, - const int num_samples, - Eigen::MatrixXd& S -) -{ - return igl::embree::ambient_occlusion(V, F, P, N, num_samples, S); -}, __doc_igl_embree_ambient_occlusion, -py::arg("V"), py::arg("F"), py::arg("P"), py::arg("N"), py::arg("num_samples"), py::arg("S")); - diff --git a/python/py_igl/embree/py_line_mesh_intersection.cpp b/python/py_igl/embree/py_line_mesh_intersection.cpp deleted file mode 100644 index b180d2b23..000000000 --- a/python/py_igl/embree/py_line_mesh_intersection.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - - -m.def("line_mesh_intersection", [] -( - const Eigen::MatrixXd& V_source, - const Eigen::MatrixXd& N_source, - const Eigen::MatrixXd& V_target, - const Eigen::MatrixXi& F_target -) -{ - return igl::embree::line_mesh_intersection(V_source, N_source, V_target, F_target); -}, __doc_igl_embree_line_mesh_intersection, -py::arg("V_source"), py::arg("N_source"), py::arg("V_target"), py::arg("F_target")); diff --git a/python/py_igl/embree/py_reorient_facets_raycast.cpp b/python/py_igl/embree/py_reorient_facets_raycast.cpp deleted file mode 100644 index c2308073f..000000000 --- a/python/py_igl/embree/py_reorient_facets_raycast.cpp +++ /dev/null @@ -1,44 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - - -m.def("reorient_facets_raycast", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - int rays_total, - int rays_minimum, - bool facet_wise, - bool use_parity, - bool is_verbose, - Eigen::MatrixXi& I, - Eigen::MatrixXi& C -) -{ - Eigen::VectorXi Iv; - Eigen::VectorXi Cv; - igl::embree::reorient_facets_raycast(V, F, rays_total, rays_minimum, facet_wise, use_parity, is_verbose, Iv, Cv); - I = Iv; - C = Cv; -}, __doc_igl_embree_reorient_facets_raycast, -py::arg("V"), py::arg("F"), py::arg("rays_total"), py::arg("rays_minimum"), py::arg("facet_wise"), py::arg("use_parity"), py::arg("is_verbose"), py::arg("I"), py::arg("C")); - -m.def("reorient_facets_raycast", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::MatrixXi& FF, - Eigen::MatrixXi& I -) -{ - Eigen::VectorXi Iv; - igl::embree::reorient_facets_raycast(V, F, FF, Iv); - I = Iv; -}, __doc_igl_embree_reorient_facets_raycast, -py::arg("V"), py::arg("F"), py::arg("FF"), py::arg("I")); - diff --git a/python/py_igl/png/py_readPNG.cpp b/python/py_igl/png/py_readPNG.cpp deleted file mode 100644 index 5e800bce2..000000000 --- a/python/py_igl/png/py_readPNG.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - -m.def("readPNG", [] -( - const std::string png_file, - Eigen::Matrix & R, - Eigen::Matrix & G, - Eigen::Matrix & B, - Eigen::Matrix & A -) -{ - return igl::png::readPNG(png_file, R, G, B, A); -}, __doc_igl_png_readPNG, -py::arg("png_file"), py::arg("R"), py::arg("G"), py::arg("B"), py::arg("A")); - diff --git a/python/py_igl/png/py_writePNG.cpp b/python/py_igl/png/py_writePNG.cpp deleted file mode 100644 index d8a9f8d99..000000000 --- a/python/py_igl/png/py_writePNG.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - - -m.def("writePNG", [] -( - const Eigen::Matrix & R, - const Eigen::Matrix & G, - const Eigen::Matrix & B, - const Eigen::Matrix & A, - const std::string png_file -) -{ - return igl::png::writePNG(R, G, B, A, png_file); -}, __doc_igl_png_writePNG, -py::arg("R"), py::arg("G"), py::arg("B"), py::arg("A"), py::arg("png_file")); - diff --git a/python/py_igl/py_AABB.cpp b/python/py_igl/py_AABB.cpp deleted file mode 100644 index 850724e7b..000000000 --- a/python/py_igl/py_AABB.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -py::class_ > AABB(m, "AABB"); - -AABB -.def(py::init<>()) -.def(py::init& >()) -.def("init",[](igl::AABB& tree, const Eigen::MatrixXd& V, const Eigen::MatrixXi& Ele) -{ - return tree.init(V, Ele, Eigen::Matrix(), Eigen::Matrix(), Eigen::VectorXi(), 0); -}) -.def("squared_distance", [](const igl::AABB& tree, const Eigen::MatrixXd& V, const Eigen::MatrixXi& Ele, const Eigen::MatrixXd& P, Eigen::MatrixXd& sqrD, Eigen::MatrixXi& I, Eigen::MatrixXd& C) -{ - return tree.squared_distance(V, Ele, P, sqrD, I, C); -}) -; diff --git a/python/py_igl/py_ARAPEnergyType.cpp b/python/py_igl/py_ARAPEnergyType.cpp deleted file mode 100644 index be0442b03..000000000 --- a/python/py_igl/py_ARAPEnergyType.cpp +++ /dev/null @@ -1,14 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -py::enum_(m, "ARAPEnergyType") - .value("ARAP_ENERGY_TYPE_SPOKES", igl::ARAP_ENERGY_TYPE_SPOKES) - .value("ARAP_ENERGY_TYPE_SPOKES_AND_RIMS", igl::ARAP_ENERGY_TYPE_SPOKES_AND_RIMS) - .value("ARAP_ENERGY_TYPE_ELEMENTS", igl::ARAP_ENERGY_TYPE_ELEMENTS) - .value("ARAP_ENERGY_TYPE_DEFAULT", igl::ARAP_ENERGY_TYPE_DEFAULT) - .value("NUM_ARAP_ENERGY_TYPES", igl::NUM_ARAP_ENERGY_TYPES) - .export_values(); diff --git a/python/py_igl/py_MeshBooleanType.cpp b/python/py_igl/py_MeshBooleanType.cpp deleted file mode 100644 index 219575108..000000000 --- a/python/py_igl/py_MeshBooleanType.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -py::enum_(m, "MeshBooleanType") - .value("MESH_BOOLEAN_TYPE_UNION", igl::MESH_BOOLEAN_TYPE_UNION) - .value("MESH_BOOLEAN_TYPE_INTERSECT", igl::MESH_BOOLEAN_TYPE_INTERSECT) - .value("MESH_BOOLEAN_TYPE_MINUS", igl::MESH_BOOLEAN_TYPE_MINUS) - .value("MESH_BOOLEAN_TYPE_XOR", igl::MESH_BOOLEAN_TYPE_XOR) - .value("MESH_BOOLEAN_TYPE_RESOLVE", igl::MESH_BOOLEAN_TYPE_RESOLVE) - .value("NUM_MESH_BOOLEAN_TYPES", igl::NUM_MESH_BOOLEAN_TYPES) - .export_values(); - - diff --git a/python/py_igl/py_SolverStatus.cpp b/python/py_igl/py_SolverStatus.cpp deleted file mode 100644 index ffd7d3369..000000000 --- a/python/py_igl/py_SolverStatus.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -py::enum_(m, "SolverStatus") - .value("SOLVER_STATUS_CONVERGED", igl::SOLVER_STATUS_CONVERGED) - .value("SOLVER_STATUS_MAX_ITER", igl::SOLVER_STATUS_MAX_ITER) - .value("SOLVER_STATUS_ERROR", igl::SOLVER_STATUS_ERROR) - .value("NUM_SOLVER_STATUSES", igl::NUM_SOLVER_STATUSES) - .export_values(); diff --git a/python/py_igl/py_active_set.cpp b/python/py_igl/py_active_set.cpp deleted file mode 100644 index ccfd61da8..000000000 --- a/python/py_igl/py_active_set.cpp +++ /dev/null @@ -1,55 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -// Wrap the params struct -py::class_ active_set_params(m, "active_set_params"); - -active_set_params -.def("__init__", [](igl::active_set_params &m) -{ - new (&m) igl::active_set_params(); - m.Auu_pd = false; - m.max_iter = 100; - m.inactive_threshold = igl::DOUBLE_EPS; - m.constraint_threshold = igl::DOUBLE_EPS; - m.solution_diff_threshold = igl::DOUBLE_EPS; -}) -.def_readwrite("Auu_pd", &igl::active_set_params::Auu_pd) -.def_readwrite("max_iter", &igl::active_set_params::max_iter) -.def_readwrite("inactive_threshold", &igl::active_set_params::inactive_threshold) -.def_readwrite("constraint_threshold", &igl::active_set_params::constraint_threshold) -.def_readwrite("solution_diff_threshold", &igl::active_set_params::solution_diff_threshold) -.def_readwrite("Auu_pd", &igl::active_set_params::Auu_pd) -; - -m.def("active_set", [] -( - const Eigen::SparseMatrix& A, - const Eigen::MatrixXd& B, - const Eigen::MatrixXi& known, - const Eigen::MatrixXd& Y, - const Eigen::SparseMatrix& Aeq, - const Eigen::MatrixXd& Beq, - const Eigen::SparseMatrix& Aieq, - const Eigen::MatrixXd& Bieq, - const Eigen::MatrixXd& lx, - const Eigen::MatrixXd& ux, - const igl::active_set_params& params, - Eigen::MatrixXd& Z -) -{ - assert_is_VectorX("B",B); - assert_is_VectorX("known",known); - assert_is_VectorX("Y",Y); - assert_is_VectorX("Beq",Beq); - assert_is_VectorX("Bieq",Bieq); - assert_is_VectorX("Z",Z); - - return igl::active_set(A,B,known,Y,Aeq,Eigen::VectorXd(Beq),Aieq,Bieq,lx,ux,params,Z); -}, __doc_igl_active_set, -py::arg("A"), py::arg("B"), py::arg("known"), py::arg("Y"), py::arg("Aeq"), py::arg("Beq") -, py::arg("Aieq"), py::arg("Bieq"), py::arg("lx"), py::arg("ux"), py::arg("params"), py::arg("Z")); diff --git a/python/py_igl/py_adjacency_list.cpp b/python/py_igl/py_adjacency_list.cpp deleted file mode 100644 index 8546e4276..000000000 --- a/python/py_igl/py_adjacency_list.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("adjacency_list", [](const Eigen::MatrixXi& F, std::vector>& A, bool sorted) { - igl::adjacency_list(F, A, sorted); -}, py::arg("F"), py::arg("A"), py::arg("sorted")=false); diff --git a/python/py_igl/py_adjacency_matrix.cpp b/python/py_igl/py_adjacency_matrix.cpp deleted file mode 100644 index 0dd12fbe5..000000000 --- a/python/py_igl/py_adjacency_matrix.cpp +++ /dev/null @@ -1,10 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("adjacency_matrix", [](const Eigen::MatrixXi & F, Eigen::SparseMatrix& A) { - igl::adjacency_matrix(F, A); -}, py::arg("F"), py::arg("A")); \ No newline at end of file diff --git a/python/py_igl/py_arap.cpp b/python/py_igl/py_arap.cpp deleted file mode 100644 index 439285804..000000000 --- a/python/py_igl/py_arap.cpp +++ /dev/null @@ -1,68 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -py::class_ ARAPData(m, "ARAPData"); - -ARAPData -.def(py::init<>()) -.def_readwrite("n", &igl::ARAPData::n) -.def_readwrite("energy", &igl::ARAPData::energy) -.def_property("G", -[](const igl::ARAPData& data) {return Eigen::MatrixXi(data.G);}, -[](igl::ARAPData& data, const Eigen::MatrixXi& G) -{ - assert_is_VectorX("G",G); - data.G = Eigen::VectorXi(G.cast()); -}) -.def_readwrite("with_dynamics", &igl::ARAPData::with_dynamics) -.def_readwrite("f_ext", &igl::ARAPData::f_ext) -.def_readwrite("h", &igl::ARAPData::h) -.def_readwrite("vel", &igl::ARAPData::vel) -.def_readwrite("ym", &igl::ARAPData::ym) -.def_readwrite("max_iter", &igl::ARAPData::max_iter) -.def_readwrite("K", &igl::ARAPData::K) -.def_readwrite("M", &igl::ARAPData::M) -.def_readwrite("CSM", &igl::ARAPData::CSM) -// .def_readwrite("solver_data", &igl::ARAPData::solver_data) -.def_readwrite("dim", &igl::ARAPData::dim) -.def_property("b", -[](const igl::ARAPData& data) {return Eigen::MatrixXi(data.b);}, -[](igl::ARAPData& data, const Eigen::MatrixXi& b) -{ - assert_is_VectorX("b",b); - data.b = Eigen::VectorXi(b.cast()); -}) -; - -m.def("arap_precomputation", [] -( - const Eigen::MatrixXd & V, - const Eigen::MatrixXi & F, - const int dim, - const Eigen::MatrixXi& b, - igl::ARAPData & data -) -{ - assert_is_VectorX("b",b); - Eigen::VectorXi bt; - if (b.size() != 0) - bt = b; - - return igl::arap_precomputation(V,F,dim,bt,data); -}, __doc_igl_arap_precomputation, -py::arg("V"), py::arg("F"), py::arg("dim"), py::arg("b"), py::arg("data")); - -m.def("arap_solve", [] -( - const Eigen::MatrixXd & bc, - igl::ARAPData & data, - Eigen::MatrixXd& U -) -{ - return igl::arap_solve(bc,data,U); -}, __doc_igl_arap_solve, -py::arg("bc"), py::arg("data"), py::arg("U")); diff --git a/python/py_igl/py_avg_edge_length.cpp b/python/py_igl/py_avg_edge_length.cpp deleted file mode 100644 index b4aa53b0e..000000000 --- a/python/py_igl/py_avg_edge_length.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("avg_edge_length", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F -) -{ - return igl::avg_edge_length(V,F); -}, __doc_igl_avg_edge_length, -py::arg("V"), py::arg("F")); diff --git a/python/py_igl/py_barycenter.cpp b/python/py_igl/py_barycenter.cpp deleted file mode 100644 index d0597a710..000000000 --- a/python/py_igl/py_barycenter.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("barycenter", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::MatrixXd& BC -) -{ - return igl::barycenter(V,F,BC); -}, __doc_igl_barycenter, -py::arg("V"), py::arg("F"), py::arg("BC")); diff --git a/python/py_igl/py_barycentric_coordinates.cpp b/python/py_igl/py_barycentric_coordinates.cpp deleted file mode 100644 index bc3da4282..000000000 --- a/python/py_igl/py_barycentric_coordinates.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - - -m.def("barycentric_coordinates", [] -( - const Eigen::MatrixXd& P, - const Eigen::MatrixXd& A, - const Eigen::MatrixXd& B, - const Eigen::MatrixXd& C, - const Eigen::MatrixXd& D, - Eigen::MatrixXd& L -) -{ - return igl::barycentric_coordinates(P, A, B, C, D, L); -}, __doc_igl_barycentric_coordinates, -py::arg("P"), py::arg("A"), py::arg("B"), py::arg("C"), py::arg("D"), py::arg("L")); - -m.def("barycentric_coordinates", [] -( - const Eigen::MatrixXd& P, - const Eigen::MatrixXd& A, - const Eigen::MatrixXd& B, - const Eigen::MatrixXd& C, - Eigen::MatrixXd& L -) -{ - return igl::barycentric_coordinates(P, A, B, C, L); -}, __doc_igl_barycentric_coordinates, -py::arg("P"), py::arg("A"), py::arg("B"), py::arg("C"), py::arg("L")); - diff --git a/python/py_igl/py_barycentric_to_global.cpp b/python/py_igl/py_barycentric_to_global.cpp deleted file mode 100644 index c62ffaf8a..000000000 --- a/python/py_igl/py_barycentric_to_global.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - - -m.def("barycentric_to_global", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::MatrixXd& bc -) -{ - return igl::barycentric_to_global(V, F, bc); -}, __doc_igl_barycentric_to_global, -py::arg("V"), py::arg("F"), py::arg("bc")); diff --git a/python/py_igl/py_bbw.cpp b/python/py_igl/py_bbw.cpp deleted file mode 100644 index 92fe2dda5..000000000 --- a/python/py_igl/py_bbw.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -// Wrap the BBWData class -py::class_ BBWData(m, "BBWData"); - -BBWData -.def(py::init<>()) -.def_readwrite("partition_unity", &igl::BBWData::partition_unity) -.def_readwrite("W0", &igl::BBWData::W0) -.def_readwrite("active_set_params", &igl::BBWData::active_set_params) -.def_readwrite("verbosity", &igl::BBWData::verbosity) - -.def("print", [](igl::BBWData& data) -{ - return data.print(); -}) -; - -m.def("bbw", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& Ele, - const Eigen::MatrixXi& b, - const Eigen::MatrixXd& bc, - igl::BBWData& data, - Eigen::MatrixXd& W -) -{ - assert_is_VectorX("b",b); - Eigen::VectorXi bv; - if (b.size() != 0) - bv = b; - return igl::bbw(V, Ele, bv, bc, data, W); -}, __doc_igl_bbw, -py::arg("V"), py::arg("Ele"), py::arg("b"), py::arg("bc"), py::arg("data"), py::arg("W")); diff --git a/python/py_igl/py_boundary_conditions.cpp b/python/py_igl/py_boundary_conditions.cpp deleted file mode 100644 index aecd228da..000000000 --- a/python/py_igl/py_boundary_conditions.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - - -m.def("boundary_conditions", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& Ele, - const Eigen::MatrixXd& C, - const Eigen::MatrixXi& P, - const Eigen::MatrixXi& BE, - const Eigen::MatrixXi& CE, - Eigen::MatrixXi& b, - Eigen::MatrixXd& bc -) -{ - assert_is_VectorX("P", P); - Eigen::VectorXi Pv; - if (P.size() != 0) - Pv = P; - Eigen::VectorXi bv; - igl::boundary_conditions(V, Ele, C, Pv, BE, CE, bv, bc); - b = bv; -}, __doc_igl_boundary_conditions, -py::arg("V"), py::arg("Ele"), py::arg("C"), py::arg("P"), py::arg("BE"), py::arg("CE"), py::arg("b"), py::arg("bc")); - diff --git a/python/py_igl/py_boundary_facets.cpp b/python/py_igl/py_boundary_facets.cpp deleted file mode 100644 index ef78111c8..000000000 --- a/python/py_igl/py_boundary_facets.cpp +++ /dev/null @@ -1,37 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("boundary_facets", [] -( - const Eigen::MatrixXi& T, - Eigen::MatrixXi& F -) -{ - return igl::boundary_facets(T,F); -}, __doc_igl_boundary_facets, -py::arg("T"), py::arg("F")); - -m.def("boundary_facets", [] -( - const Eigen::MatrixXi& T -) -{ - Eigen::MatrixXi F; - igl::boundary_facets(T,F); - return F; -}, __doc_igl_boundary_facets, -py::arg("T")); - -m.def("boundary_facets", [] -( - const std::vector > & T, - std::vector > & F -) -{ - return igl::boundary_facets(T,F); -}, __doc_igl_boundary_facets, -py::arg("T"), py::arg("F")); diff --git a/python/py_igl/py_boundary_loop.cpp b/python/py_igl/py_boundary_loop.cpp deleted file mode 100755 index dc5a84892..000000000 --- a/python/py_igl/py_boundary_loop.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("boundary_loop", [] -( - const Eigen::MatrixXi& F, - Eigen::MatrixXi& L -) -{ - Eigen::VectorXi T; - igl::boundary_loop(F,T); - L = T; -}, __doc_igl_boundary_loop, -py::arg("F"), py::arg("L")); - -m.def("boundary_loop", [] -( - const Eigen::MatrixXi& F, - std::vector >& L -) -{ - return igl::boundary_loop(F,L); -}, __doc_igl_boundary_loop, -py::arg("F"), py::arg("L")); - -m.def("boundary_loop", [] -( - const Eigen::MatrixXi& F, - std::vector& L -) -{ - return igl::boundary_loop(F,L); -}, __doc_igl_boundary_loop, -py::arg("F"), py::arg("L")); - - diff --git a/python/py_igl/py_cat.cpp b/python/py_igl/py_cat.cpp deleted file mode 100644 index 77344493f..000000000 --- a/python/py_igl/py_cat.cpp +++ /dev/null @@ -1,63 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("cat", [] -( - const int dim, - const Eigen::MatrixXd& A, - const Eigen::MatrixXd& B, - Eigen::MatrixXd& C -) -{ - return igl::cat(dim, A, B, C); -}, __doc_igl_cat, -py::arg("dim"), py::arg("A"), py::arg("B"), py::arg("C")); - -m.def("cat", [] -( - const int dim, - Eigen::MatrixXd& A, - Eigen::MatrixXd& B -) -{ - return igl::cat(dim, A, B); -}, __doc_igl_cat, -py::arg("dim"), py::arg("A"), py::arg("B")); - -m.def("cat", [] -( - const int dim, - Eigen::MatrixXi& A, - Eigen::MatrixXi& B -) -{ - return igl::cat(dim, A, B); -}, __doc_igl_cat, -py::arg("dim"), py::arg("A"), py::arg("B")); - -//m.def("cat", [] -//( -// const std::vector > & A, -// Eigen::MatrixXd & C -//) -//{ -// return igl::cat(A, C); -//}, __doc_igl_cat, -//py::arg("A"), py::arg("C")); - -m.def("cat", [] -( - const int dim, - const Eigen::SparseMatrix& A, - const Eigen::SparseMatrix& B, - Eigen::SparseMatrix& C -) -{ - return igl::cat(dim, A, B, C); -}, __doc_igl_cat, -py::arg("dim"), py::arg("A"), py::arg("B"), py::arg("C")); - diff --git a/python/py_igl/py_collapse_edge.cpp b/python/py_igl/py_collapse_edge.cpp deleted file mode 100644 index 19d501dea..000000000 --- a/python/py_igl/py_collapse_edge.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -// COMPLETE BINDINGS ======================== - - - - - - -// INCOMPLETE BINDINGS ======================== - - -//m.def("collapse_edge", [] -//( -// int e, -// Eigen::RowVectorXd & p, -// Eigen::MatrixXd& V, -// Eigen::MatrixXi& F, -// Eigen::MatrixXi& E, -// Eigen::MatrixXi& EMAP, -// Eigen::MatrixXi& EF, -// Eigen::MatrixXi& EI, -// int & e1, -// int & e2, -// int & f1, -// int & f2 -//) -//{ -// return igl::collapse_edge(e, p, V, F, E, EMAP, EF, EI, e1, e2, f1, f2); -//}, __doc_igl_collapse_edge, -//py::arg("e"), py::arg("p"), py::arg("V"), py::arg("F"), py::arg("E"), py::arg("EMAP"), py::arg("EF"), py::arg("EI"), py::arg("e1"), py::arg("e2"), py::arg("f1"), py::arg("f2")); - -//m.def("collapse_edge", [] -//( -// int e, -// Eigen::RowVectorXd & p, -// Eigen::MatrixXd& V, -// Eigen::MatrixXi& F, -// Eigen::MatrixXi& E, -// Eigen::MatrixXi& EMAP, -// Eigen::MatrixXi& EF, -// Eigen::MatrixXi& EI -//) -//{ -// return igl::collapse_edge(e, p, V, F, E, EMAP, EF, EI); -//}, __doc_igl_collapse_edge, -//py::arg("e"), py::arg("p"), py::arg("V"), py::arg("F"), py::arg("E"), py::arg("EMAP"), py::arg("EF"), py::arg("EI")); - -//m.def("collapse_edge", [] -//( -// std::function & cost_and_placement, -// Eigen::MatrixXd& V, -// Eigen::MatrixXi& F, -// Eigen::MatrixXi& E, -// Eigen::MatrixXi& EMAP, -// Eigen::MatrixXi& EF, -// Eigen::MatrixXi& EI, -// std::set > & Q, -// std::vector >::iterator> & Qit, -// Eigen::MatrixXd& C -//) -//{ -// return igl::collapse_edge(cost_and_placement, V, F, E, EMAP, EF, EI, Q, Qit, C); -//}, __doc_igl_collapse_edge, -//py::arg("cost_and_placement"), py::arg("V"), py::arg("F"), py::arg("E"), py::arg("EMAP"), py::arg("EF"), py::arg("EI"), py::arg("Q"), py::arg("Qit"), py::arg("C")); - -//m.def("collapse_edge", [] -//( -// std::function & cost_and_placement, -// Eigen::MatrixXd& V, -// Eigen::MatrixXi& F, -// Eigen::MatrixXi& E, -// Eigen::MatrixXi& EMAP, -// Eigen::MatrixXi& EF, -// Eigen::MatrixXi& EI, -// std::set > & Q, -// std::vector >::iterator> & Qit, -// Eigen::MatrixXd& C, -// int & e, -// int & e1, -// int & e2, -// int & f1, -// int & f2 -//) -//{ -// return igl::collapse_edge(cost_and_placement, V, F, E, EMAP, EF, EI, Q, Qit, C, e, e1, e2, f1, f2); -//}, __doc_igl_collapse_edge, -//py::arg("cost_and_placement"), py::arg("V"), py::arg("F"), py::arg("E"), py::arg("EMAP"), py::arg("EF"), py::arg("EI"), py::arg("Q"), py::arg("Qit"), py::arg("C"), py::arg("e"), py::arg("e1"), py::arg("e2"), py::arg("f1"), py::arg("f2")); - diff --git a/python/py_igl/py_colon.cpp b/python/py_igl/py_colon.cpp deleted file mode 100644 index 144801185..000000000 --- a/python/py_igl/py_colon.cpp +++ /dev/null @@ -1,81 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("colon", [] -( - const double low, - const double step, - const double high, - Eigen::MatrixXd& I -) -{ - Eigen::Matrix temp; - igl::colon(low,step,high,temp); - I = temp; -}, __doc_igl_colon, -py::arg("low"), py::arg("step"), py::arg("high"), py::arg("I")); - -m.def("colon", [] -( - const double low, - const double high, - Eigen::MatrixXd& I -) -{ - Eigen::Matrix temp; - igl::colon(low,high,temp); - I = temp; -}, __doc_igl_colon, -py::arg("low"), py::arg("high"), py::arg("I")); - -m.def("colon", [] -( - const double& low, - const double& high -) -{ - return Eigen::MatrixXd(igl::colon(low,high)); -}, __doc_igl_colon, -py::arg("low"), py::arg("high")); - - -m.def("coloni", [] -( - const int low, - const int step, - const int high, - Eigen::MatrixXi& I -) -{ - Eigen::Matrix temp; - igl::colon(low,step,high,temp); - I = temp; -}, __doc_igl_colon, -py::arg("low"), py::arg("step"), py::arg("high"), py::arg("I")); - -m.def("coloni", [] -( - const int low, - const int high, - Eigen::MatrixXi& I -) -{ - Eigen::Matrix temp; - igl::colon(low,high,temp); - I = temp; -}, __doc_igl_colon, -py::arg("low"), py::arg("high"), py::arg("I")); - -m.def("coloni", [] -( - const int& low, - const int& high -) -{ - return Eigen::MatrixXi(igl::colon(low,high)); -}, __doc_igl_colon, -py::arg("low"), py::arg("high")); diff --git a/python/py_igl/py_column_to_quats.cpp b/python/py_igl/py_column_to_quats.cpp deleted file mode 100644 index 94e9e8c25..000000000 --- a/python/py_igl/py_column_to_quats.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("column_to_quats", [] -( - const Eigen::MatrixXd& Q, - RotationList& vQ -) -{ - return igl::column_to_quats(Q, vQ); -}, __doc_igl_column_to_quats, -py::arg("Q"), py::arg("vQ")); - diff --git a/python/py_igl/py_comb_cross_field.cpp b/python/py_igl/py_comb_cross_field.cpp deleted file mode 100644 index f585a4100..000000000 --- a/python/py_igl/py_comb_cross_field.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("comb_cross_field", [] -( - const Eigen::MatrixXd &V, - const Eigen::MatrixXi &F, - const Eigen::MatrixXd &PD1in, - const Eigen::MatrixXd &PD2in, - Eigen::MatrixXd &PD1out, - Eigen::MatrixXd &PD2out -) -{ - return igl::comb_cross_field(V,F,PD1in,PD2in,PD1out,PD2out); -}, __doc_igl_comb_cross_field, -py::arg("V"), py::arg("F"), py::arg("PD1in"), py::arg("PD2in"), py::arg("PD1out"), py::arg("PD2out")); diff --git a/python/py_igl/py_comb_frame_field.cpp b/python/py_igl/py_comb_frame_field.cpp deleted file mode 100644 index 8bcc3eb9e..000000000 --- a/python/py_igl/py_comb_frame_field.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("comb_frame_field", [] -( - const Eigen::MatrixXd &V, - const Eigen::MatrixXi &F, - const Eigen::MatrixXd &PD1, - const Eigen::MatrixXd &PD2, - const Eigen::MatrixXd &BIS1_combed, - const Eigen::MatrixXd &BIS2_combed, - Eigen::MatrixXd &PD1_combed, - Eigen::MatrixXd &PD2_combed -) -{ - return igl::comb_frame_field(V,F,PD1,PD2,BIS1_combed,BIS2_combed,PD1_combed,PD2_combed); -}, __doc_igl_comb_frame_field, -py::arg("V"), py::arg("F"), py::arg("PD1"), py::arg("PD2"), py::arg("BIS1_combed"), py::arg("BIS2_combed"), py::arg("PD1_combed"), py::arg("PD2_combed")); diff --git a/python/py_igl/py_compute_frame_field_bisectors.cpp b/python/py_igl/py_compute_frame_field_bisectors.cpp deleted file mode 100644 index 8f6f2af01..000000000 --- a/python/py_igl/py_compute_frame_field_bisectors.cpp +++ /dev/null @@ -1,36 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("compute_frame_field_bisectors", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::MatrixXd& B1, - const Eigen::MatrixXd& B2, - const Eigen::MatrixXd& PD1, - const Eigen::MatrixXd& PD2, - Eigen::MatrixXd& BIS1, - Eigen::MatrixXd& BIS2 -) -{ - return igl::compute_frame_field_bisectors(V,F,B1,B2,PD1,PD2,BIS1,BIS2); -}, __doc_igl_compute_frame_field_bisectors, -py::arg("V"), py::arg("F"), py::arg("B1"), py::arg("B2"), py::arg("PD1"), py::arg("PD2"), py::arg("BIS1"), py::arg("BIS2")); - -m.def("compute_frame_field_bisectors", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::MatrixXd& PD1, - const Eigen::MatrixXd& PD2, - Eigen::MatrixXd& BIS1, - Eigen::MatrixXd& BIS2 -) -{ - return igl::compute_frame_field_bisectors(V,F,PD1,PD2,BIS1,BIS2); -}, __doc_igl_compute_frame_field_bisectors, -py::arg("V"), py::arg("F"), py::arg("PD1"), py::arg("PD2"), py::arg("BIS1"), py::arg("BIS2")); diff --git a/python/py_igl/py_cotmatrix.cpp b/python/py_igl/py_cotmatrix.cpp deleted file mode 100644 index 0cf569eb5..000000000 --- a/python/py_igl/py_cotmatrix.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("cotmatrix", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::SparseMatrix& L -) -{ - return igl::cotmatrix(V,F,L); -}, __doc_igl_cotmatrix, -py::arg("V"), py::arg("F"), py::arg("L")); diff --git a/python/py_igl/py_covariance_scatter_matrix.cpp b/python/py_igl/py_covariance_scatter_matrix.cpp deleted file mode 100644 index c7710be55..000000000 --- a/python/py_igl/py_covariance_scatter_matrix.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("covariance_scatter_matrix", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const igl::ARAPEnergyType energy, - Eigen::SparseMatrix& CSM -) -{ - return igl::covariance_scatter_matrix(V,F,energy,CSM); -}, __doc_igl_covariance_scatter_matrix, -py::arg("V"), py::arg("F"), py::arg("energy"), py::arg("CSM")); diff --git a/python/py_igl/py_cross_field_mismatch.cpp b/python/py_igl/py_cross_field_mismatch.cpp deleted file mode 100644 index 5a48ba396..000000000 --- a/python/py_igl/py_cross_field_mismatch.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("cross_field_mismatch", [] -( - const Eigen::MatrixXd &V, - const Eigen::MatrixXi &F, - const Eigen::MatrixXd &PD1, - const Eigen::MatrixXd &PD2, - const bool isCombed, - Eigen::MatrixXi &mismatch -) -{ - return igl::cross_field_mismatch(V,F,PD1,PD2,isCombed,mismatch); -}, __doc_igl_cross_field_mismatch, -py::arg("V"), py::arg("F"), py::arg("PD1"), py::arg("PD2"), py::arg("isCombed"), py::arg("mismatch")); diff --git a/python/py_igl/py_cut_mesh_from_singularities.cpp b/python/py_igl/py_cut_mesh_from_singularities.cpp deleted file mode 100644 index acc54425e..000000000 --- a/python/py_igl/py_cut_mesh_from_singularities.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("cut_mesh_from_singularities", [] -( - const Eigen::MatrixXd &V, - const Eigen::MatrixXi &F, - const Eigen::MatrixXi &MMatch, - Eigen::MatrixXi &seams -) -{ - return igl::cut_mesh_from_singularities(V,F,MMatch,seams); -}, __doc_igl_cut_mesh_from_singularities, -py::arg("V"), py::arg("F"), py::arg("mismatch"), py::arg("seams")); diff --git a/python/py_igl/py_deform_skeleton.cpp b/python/py_igl/py_deform_skeleton.cpp deleted file mode 100644 index f62f62459..000000000 --- a/python/py_igl/py_deform_skeleton.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -// COMPLETE BINDINGS ======================== - - -m.def("deform_skeleton", [] -( - const Eigen::MatrixXd& C, - const Eigen::MatrixXi& BE, - const Eigen::MatrixXd& T, - Eigen::MatrixXd& CT, - Eigen::MatrixXi& BET -) -{ - return igl::deform_skeleton(C, BE, T, CT, BET); -}, __doc_igl_deform_skeleton, -py::arg("C"), py::arg("BE"), py::arg("T"), py::arg("CT"), py::arg("BET")); - - - - - -// INCOMPLETE BINDINGS ======================== - - -//m.def("deform_skeleton", [] -//( -// const Eigen::MatrixXd& C, -// const Eigen::MatrixXi& BE, -// std::vector > & vA, -// Eigen::MatrixXd& CT, -// Eigen::MatrixXi& BET -//) -//{ -// return igl::deform_skeleton(C, BE, vA, CT, BET); -//}, __doc_igl_deform_skeleton, -//py::arg("C"), py::arg("BE"), py::arg("vA"), py::arg("CT"), py::arg("BET")); - diff --git a/python/py_igl/py_directed_edge_orientations.cpp b/python/py_igl/py_directed_edge_orientations.cpp deleted file mode 100644 index d14796e64..000000000 --- a/python/py_igl/py_directed_edge_orientations.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - -m.def("directed_edge_orientations", [] -( - const Eigen::MatrixXd& C, - const Eigen::MatrixXi& E, - RotationList& Q -) -{ - return igl::directed_edge_orientations(C, E, Q); -}, __doc_igl_directed_edge_orientations, -py::arg("C"), py::arg("E"), py::arg("Q")); - diff --git a/python/py_igl/py_directed_edge_parents.cpp b/python/py_igl/py_directed_edge_parents.cpp deleted file mode 100644 index 5a3d12e7c..000000000 --- a/python/py_igl/py_directed_edge_parents.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - - -m.def("directed_edge_parents", [] -( - const Eigen::MatrixXi& E, - Eigen::MatrixXi& P -) -{ - Eigen::VectorXi Pv; - igl::directed_edge_parents(E, Pv); - P = Pv; -}, __doc_igl_directed_edge_parents, -py::arg("E"), py::arg("P")); - diff --git a/python/py_igl/py_doublearea.cpp b/python/py_igl/py_doublearea.cpp deleted file mode 100644 index 5e77081f9..000000000 --- a/python/py_igl/py_doublearea.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("doublearea", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::MatrixXd& dblA -) -{ - return igl::doublearea(V,F,dblA); -}, __doc_igl_doublearea, -py::arg("V"), py::arg("F"), py::arg("dblA")); - -m.def("doublearea", [] -( - const Eigen::MatrixXd& A, - const Eigen::MatrixXd& B, - const Eigen::MatrixXd& C, - Eigen::MatrixXd& D -) -{ - return igl::doublearea(A,B,C,D); -}, __doc_igl_doublearea, -py::arg("A"), py::arg("B"), py::arg("C"), py::arg("D")); - -m.def("doublearea_single", [] -( - const Eigen::MatrixXd& A, - const Eigen::MatrixXd& B, - const Eigen::MatrixXd& C -) -{ - return igl::doublearea_single(A,B,C); -}, __doc_igl_doublearea_single, -py::arg("A"), py::arg("B"), py::arg("C")); - -m.def("doublearea", [] -( - const Eigen::MatrixXd& l, - Eigen::MatrixXd& dblA -) -{ - return igl::doublearea(l,dblA); -}, __doc_igl_doublearea, -py::arg("l"), py::arg("dblA")); - -m.def("doublearea_quad", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::MatrixXd& dblA -) -{ - return igl::doublearea_quad(V,F,dblA); -}, __doc_igl_doublearea_quad, -py::arg("V"), py::arg("F"), py::arg("dblA")); diff --git a/python/py_igl/py_dqs.cpp b/python/py_igl/py_dqs.cpp deleted file mode 100644 index e39dabd5a..000000000 --- a/python/py_igl/py_dqs.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - - -m.def("dqs", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXd& W, - const RotationList& vQ, - const std::vector & vT, - Eigen::MatrixXd& U -) -{ - std::vector vTv; - for (auto item : vT) { - assert_is_Vector3("item", item); - Eigen::Vector3d obj = Eigen::Vector3d(item); - vTv.push_back(obj); - } - return igl::dqs(V, W, vQ, vTv, U); -}, __doc_igl_dqs, -py::arg("V"), py::arg("W"), py::arg("vQ"), py::arg("vT"), py::arg("U")); - diff --git a/python/py_igl/py_edge_lengths.cpp b/python/py_igl/py_edge_lengths.cpp deleted file mode 100644 index 0988fb755..000000000 --- a/python/py_igl/py_edge_lengths.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("edge_lengths", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::MatrixXd& L -) -{ - return igl::edge_lengths(V, F, L); -}, __doc_igl_edge_lengths, -py::arg("V"), py::arg("F"), py::arg("L")); - diff --git a/python/py_igl/py_edge_topology.cpp b/python/py_igl/py_edge_topology.cpp deleted file mode 100644 index 4defb0dc8..000000000 --- a/python/py_igl/py_edge_topology.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("edge_topology", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::MatrixXi& EV, - Eigen::MatrixXi& FE, - Eigen::MatrixXi& EF -) -{ - return igl::edge_topology(V, F, EV, FE, EF); -}, __doc_igl_edge_lengths, -py::arg("V"), py::arg("F"), py::arg("EV"), py::arg("FE"), py::arg("EF")); - diff --git a/python/py_igl/py_eigs.cpp b/python/py_igl/py_eigs.cpp deleted file mode 100644 index b86c4b64c..000000000 --- a/python/py_igl/py_eigs.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -py::enum_(m, "EigsType") - .value("EIGS_TYPE_SM", igl::EIGS_TYPE_SM) - .value("EIGS_TYPE_LM", igl::EIGS_TYPE_LM) - .value("NUM_EIGS_TYPES", igl::NUM_EIGS_TYPES) - .export_values(); - -m.def("eigs", [] -( - const Eigen::SparseMatrix& A, - const Eigen::SparseMatrix& B, - const size_t k, - const igl::EigsType type, - Eigen::MatrixXd& sU, - Eigen::MatrixXd& sS -) -{ - Eigen::VectorXd sSt; - bool ret = igl::eigs(A,B,k,type,sU,sSt); - sS = sSt; - return ret; -}, __doc_igl_eigs, -py::arg("A"), py::arg("B"), py::arg("k"), py::arg("type"), py::arg("sU"), py::arg("sS")); diff --git a/python/py_igl/py_exact_geodesic.cpp b/python/py_igl/py_exact_geodesic.cpp deleted file mode 100644 index b05ac744b..000000000 --- a/python/py_igl/py_exact_geodesic.cpp +++ /dev/null @@ -1,24 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2018 Zhongshi Jiang -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - - -m.def("exact_geodesic", [] -( - const Eigen::MatrixXd &V, - const Eigen::MatrixXi &F, - const Eigen::MatrixXi &VS, - const Eigen::MatrixXi &FS, - const Eigen::MatrixXi &VT, - const Eigen::MatrixXi &FT, - Eigen::MatrixXd &D -) -{ - return igl::exact_geodesic(V, F, VS,FS,VT,FT, D); -}, __doc_igl_exact_geodesic, -py::arg("V"), py::arg("F"), py::arg("VS"), py::arg("FS"), py::arg("VT"), py::arg("FT"), py::arg("D")); - diff --git a/python/py_igl/py_find_cross_field_singularities.cpp b/python/py_igl/py_find_cross_field_singularities.cpp deleted file mode 100644 index dcdbac109..000000000 --- a/python/py_igl/py_find_cross_field_singularities.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("find_cross_field_singularities", [] -( - const Eigen::MatrixXd &V, - const Eigen::MatrixXi &F, - const Eigen::MatrixXi &Handle_MMatch, - Eigen::MatrixXi &isSingularity, - Eigen::MatrixXi &singularityIndex -) -{ - return igl::find_cross_field_singularities(V,F,Handle_MMatch,isSingularity,singularityIndex); -}, __doc_igl_find_cross_field_singularities, -py::arg("V"), py::arg("F"), py::arg("Handle_MMatch"), py::arg("isSingularity"), py::arg("singularityIndex")); - -m.def("find_cross_field_singularities", [] -( - const Eigen::MatrixXd &V, - const Eigen::MatrixXi &F, - const Eigen::MatrixXd &PD1, - const Eigen::MatrixXd &PD2, - Eigen::MatrixXi &isSingularity, - Eigen::MatrixXi &singularityIndex, - bool isCombed -) -{ - return igl::find_cross_field_singularities(V,F,PD1,PD2,isSingularity,singularityIndex,isCombed); -}, __doc_igl_find_cross_field_singularities, -py::arg("V"), py::arg("F"), py::arg("PD1"), py::arg("PD2"), py::arg("isSingularity"), py::arg("singularityIndex"), py::arg("isCombed") = false); diff --git a/python/py_igl/py_fit_rotations.cpp b/python/py_igl/py_fit_rotations.cpp deleted file mode 100644 index 0c4fe92f6..000000000 --- a/python/py_igl/py_fit_rotations.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("fit_rotations", [] -( - const Eigen::MatrixXd& S, - const bool single_precision, - Eigen::MatrixXd& R -) -{ - return igl::fit_rotations(S, single_precision, R); -}, __doc_igl_fit_rotations, -py::arg("S"), py::arg("single_precision"), py::arg("R")); - - -m.def("fit_rotations_planar", [] -( - const Eigen::MatrixXd& S, - Eigen::MatrixXd& R -) -{ - return igl::fit_rotations_planar(S, R); -}, __doc_igl_fit_rotations_planar, -py::arg("S"), py::arg("R")); - diff --git a/python/py_igl/py_floor.cpp b/python/py_igl/py_floor.cpp deleted file mode 100644 index e0f028767..000000000 --- a/python/py_igl/py_floor.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("floor", [] -( - const Eigen::MatrixXd& X, - Eigen::MatrixXi& Y -) -{ - return igl::floor(X,Y); -}, __doc_igl_floor, -py::arg("X"), py::arg("Y")); diff --git a/python/py_igl/py_forward_kinematics.cpp b/python/py_igl/py_forward_kinematics.cpp deleted file mode 100644 index 2d6e2e603..000000000 --- a/python/py_igl/py_forward_kinematics.cpp +++ /dev/null @@ -1,69 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - -//m.def("forward_kinematics", [] -//( -// const Eigen::MatrixXd& C, -// const Eigen::MatrixXi& BE, -// const Eigen::MatrixXi& P, -// std::vector > & dQ, -// std::vector & dT, -// std::vector > & vQ, -// std::vector & vT -//) -//{ -// return igl::forward_kinematics(C, BE, P, dQ, dT, vQ, vT); -//}, __doc_igl_forward_kinematics, -//py::arg("C"), py::arg("BE"), py::arg("P"), py::arg("dQ"), py::arg("dT"), py::arg("vQ"), py::arg("vT")); - -m.def("forward_kinematics", [] -( - const Eigen::MatrixXd& C, - const Eigen::MatrixXi& BE, - const Eigen::MatrixXi& P, - const RotationList& dQ, - RotationList& vQ, - py::list vT -) -{ - std::vector vTl; - igl::forward_kinematics(C, BE, P, dQ, vQ, vTl); - for (auto item : vTl) { - py::object obj = py::cast(Eigen::MatrixXd(item)); - vT.append(obj); - } -}, __doc_igl_forward_kinematics, -py::arg("C"), py::arg("BE"), py::arg("P"), py::arg("dQ"), py::arg("vQ"), py::arg("vT")); - -//m.def("forward_kinematics", [] -//( -// const Eigen::MatrixXd& C, -// const Eigen::MatrixXi& BE, -// const Eigen::MatrixXi& P, -// std::vector > & dQ, -// std::vector & dT, -// Eigen::MatrixXd& T -//) -//{ -// return igl::forward_kinematics(C, BE, P, dQ, dT, T); -//}, __doc_igl_forward_kinematics, -//py::arg("C"), py::arg("BE"), py::arg("P"), py::arg("dQ"), py::arg("dT"), py::arg("T")); - -//m.def("forward_kinematics", [] -//( -// const Eigen::MatrixXd& C, -// const Eigen::MatrixXi& BE, -// const Eigen::MatrixXi& P, -// std::vector > & dQ, -// Eigen::MatrixXd& T -//) -//{ -// return igl::forward_kinematics(C, BE, P, dQ, T); -//}, __doc_igl_forward_kinematics, -//py::arg("C"), py::arg("BE"), py::arg("P"), py::arg("dQ"), py::arg("T")); - diff --git a/python/py_igl/py_gaussian_curvature.cpp b/python/py_igl/py_gaussian_curvature.cpp deleted file mode 100644 index 9eefe3531..000000000 --- a/python/py_igl/py_gaussian_curvature.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("gaussian_curvature", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::MatrixXd& K -) -{ - return igl::gaussian_curvature(V,F,K); -}, __doc_igl_gaussian_curvature, -py::arg("V"), py::arg("F"), py::arg("K")); diff --git a/python/py_igl/py_get_seconds.cpp b/python/py_igl/py_get_seconds.cpp deleted file mode 100644 index fffc8d408..000000000 --- a/python/py_igl/py_get_seconds.cpp +++ /dev/null @@ -1,13 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("get_seconds", [] -() -{ - return igl::get_seconds(); -}, __doc_igl_get_seconds); - diff --git a/python/py_igl/py_grad.cpp b/python/py_igl/py_grad.cpp deleted file mode 100644 index f47ef363c..000000000 --- a/python/py_igl/py_grad.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("grad", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::SparseMatrix& G -) -{ - return igl::grad(V,F,G); -}, __doc_igl_grad, -py::arg("V"), py::arg("F"), py::arg("G")); diff --git a/python/py_igl/py_harmonic.cpp b/python/py_igl/py_harmonic.cpp deleted file mode 100644 index aab69b3e0..000000000 --- a/python/py_igl/py_harmonic.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("harmonic", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::MatrixXi& b, - const Eigen::MatrixXd& bc, - const int k, - Eigen::MatrixXd& W -) -{ - assert_is_VectorX("b",b); - return igl::harmonic(V,F,b,bc,k,W); -}, __doc_igl_harmonic, -py::arg("V"), py::arg("F"), py::arg("b"), py::arg("bc"), py::arg("k"), py::arg("W")); diff --git a/python/py_igl/py_heat_geodesics.cpp b/python/py_igl/py_heat_geodesics.cpp deleted file mode 100644 index 321ad085d..000000000 --- a/python/py_igl/py_heat_geodesics.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2018 Amrollah Seifoddini -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - -// Wrap the data class, no properties are exposed since it is not necessary -py::class_ > heat_geodesics_data(m, "heat_geodesics_data"); - -heat_geodesics_data.def(py::init<>()); - -m.def("heat_geodesics_precompute", [] -( - const Eigen::MatrixXd &V, - const Eigen::MatrixXi &F, - igl::HeatGeodesicsData &data -) -{ - return igl::heat_geodesics_precompute(V, F, data); -}, __doc_igl_heat_geodesics_precompute, -py::arg("V"), py::arg("F"), py::arg("data")); - - -m.def("heat_geodesics_solve", [] -( - const igl::HeatGeodesicsData &data, - const Eigen::MatrixXi &gamma, - Eigen::MatrixXd &D -) -{ -assert_is_VectorX("D", D); -assert_is_VectorX("gamma", gamma); -Eigen::VectorXd vD; -igl::heat_geodesics_solve(data, Eigen::VectorXi(gamma), vD); -D.resize(vD.size(), 1); -for (int i = 0; i < vD.size(); i++) -{ - D(i, 0) = vD[i]; -} -return true; -}, __doc_igl_heat_geodesics_solve, -py::arg("data"), py::arg("gamma"), py::arg("D")); - diff --git a/python/py_igl/py_hsv_to_rgb.cpp b/python/py_igl/py_hsv_to_rgb.cpp deleted file mode 100644 index d88a830b1..000000000 --- a/python/py_igl/py_hsv_to_rgb.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -// COMPLETE BINDINGS ======================== - - -m.def("hsv_to_rgb", [] -( - const Eigen::MatrixXd& H, - Eigen::MatrixXd& R -) -{ - return igl::hsv_to_rgb(H, R); -}, __doc_igl_hsv_to_rgb, -py::arg("H"), py::arg("R")); - - - - - -// INCOMPLETE BINDINGS ======================== - - -//m.def("hsv_to_rgb", [] -//( -// T * hsv, -// T * rgb -//) -//{ -// return igl::hsv_to_rgb(hsv, rgb); -//}, __doc_igl_hsv_to_rgb, -//py::arg("hsv"), py::arg("rgb")); - -//m.def("hsv_to_rgb", [] -//( -// T & h, -// T & s, -// T & v, -// T & r, -// T & g, -// T & b -//) -//{ -// return igl::hsv_to_rgb(h, s, v, r, g, b); -//}, __doc_igl_hsv_to_rgb, -//py::arg("h"), py::arg("s"), py::arg("v"), py::arg("r"), py::arg("g"), py::arg("b")); - diff --git a/python/py_igl/py_internal_angles.cpp b/python/py_igl/py_internal_angles.cpp deleted file mode 100644 index 1e17e89b9..000000000 --- a/python/py_igl/py_internal_angles.cpp +++ /dev/null @@ -1,41 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - - -m.def("internal_angles", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::MatrixXd& K -) -{ - return igl::internal_angles(V, F, K); -}, __doc_igl_internal_angles, -py::arg("V"), py::arg("F"), py::arg("K")); - -m.def("internal_angles_using_squared_edge_lengths", [] -( - const Eigen::MatrixXd& L_sq, - Eigen::MatrixXd& K -) -{ - return igl::internal_angles_using_squared_edge_lengths(L_sq, K); -}, __doc_igl_internal_angles, -py::arg("L_sq"), py::arg("K")); - -//m.def("internal_angles_using_edge_lengths", [] -//( -// const Eigen::MatrixXd& L, -// Eigen::MatrixXd& K -//) -//{ -// return igl::internal_angles_using_edge_lengths(L, K); -//}, __doc_igl_internal_angles, -//py::arg("L"), py::arg("K")); - - diff --git a/python/py_igl/py_invert_diag.cpp b/python/py_igl/py_invert_diag.cpp deleted file mode 100644 index 6f5b0b5fb..000000000 --- a/python/py_igl/py_invert_diag.cpp +++ /dev/null @@ -1,16 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("invert_diag", [] -( - const Eigen::SparseMatrix& X, - Eigen::SparseMatrix& Y -) -{ - return igl::invert_diag(X,Y); -}, __doc_igl_invert_diag, -py::arg("X"), py::arg("Y")); diff --git a/python/py_igl/py_is_irregular_vertex.cpp b/python/py_igl/py_is_irregular_vertex.cpp deleted file mode 100644 index 431868200..000000000 --- a/python/py_igl/py_is_irregular_vertex.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - - -m.def("is_irregular_vertex", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F -) -{ - return igl::is_irregular_vertex(V, F); -}, __doc_igl_is_irregular_vertex, -py::arg("V"), py::arg("F")); - diff --git a/python/py_igl/py_jet.cpp b/python/py_igl/py_jet.cpp deleted file mode 100644 index 7914d843d..000000000 --- a/python/py_igl/py_jet.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("jet", [] -( - const Eigen::MatrixXd& Z, - const bool normalize, - Eigen::MatrixXd& C -) -{ - assert_is_VectorX("Z",Z); - return igl::jet(Z,normalize,C); -}, __doc_igl_jet, -py::arg("Z"), py::arg("normalize"), py::arg("C")); - -m.def("jet", [] -( - const Eigen::MatrixXd& Z, - const double min_Z, - const double max_Z, - Eigen::MatrixXd& C -) -{ - assert_is_VectorX("Z",Z); - return igl::jet(Z,min_Z,max_Z,C); -}, __doc_igl_jet, -py::arg("Z"), py::arg("min_Z"), py::arg("max_Z"), py::arg("C")); diff --git a/python/py_igl/py_lbs_matrix.cpp b/python/py_igl/py_lbs_matrix.cpp deleted file mode 100644 index 32bfe21f7..000000000 --- a/python/py_igl/py_lbs_matrix.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -// COMPLETE BINDINGS ======================== - - -m.def("lbs_matrix", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXd& W, - Eigen::MatrixXd& M -) -{ - return igl::lbs_matrix(V, W, M); -}, __doc_igl_lbs_matrix, -py::arg("V"), py::arg("W"), py::arg("M")); - -m.def("lbs_matrix_column", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXd& W, - Eigen::MatrixXd& M -) -{ - return igl::lbs_matrix_column(V, W, M); -}, __doc_igl_lbs_matrix_column, -py::arg("V"), py::arg("W"), py::arg("M")); - -m.def("lbs_matrix_column", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXd& W, - const Eigen::MatrixXi& WI, - Eigen::MatrixXd& M -) -{ - return igl::lbs_matrix_column(V, W, WI, M); -}, __doc_igl_lbs_matrix_column, -py::arg("V"), py::arg("W"), py::arg("WI"), py::arg("M")); - - - - - -// INCOMPLETE BINDINGS ======================== - - -m.def("lbs_matrix_column", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXd& W, - Eigen::SparseMatrix& M -) -{ - return igl::lbs_matrix_column(V, W, M); -}, __doc_igl_lbs_matrix_column, -py::arg("V"), py::arg("W"), py::arg("M")); - -m.def("lbs_matrix_column", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXd& W, - const Eigen::MatrixXi& WI, - Eigen::SparseMatrix& M -) -{ - return igl::lbs_matrix_column(V, W, WI, M); -}, __doc_igl_lbs_matrix_column, -py::arg("V"), py::arg("W"), py::arg("WI"), py::arg("M")); - diff --git a/python/py_igl/py_local_basis.cpp b/python/py_igl/py_local_basis.cpp deleted file mode 100644 index 7dc34ea96..000000000 --- a/python/py_igl/py_local_basis.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("local_basis", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::MatrixXd& B1, - Eigen::MatrixXd& B2, - Eigen::MatrixXd& B3 -) -{ - return igl::local_basis(V,F,B1,B2,B3); -}, __doc_igl_local_basis, -py::arg("V"), py::arg("F"), py::arg("B1"), py::arg("B2"), py::arg("B3")); diff --git a/python/py_igl/py_lscm.cpp b/python/py_igl/py_lscm.cpp deleted file mode 100644 index 211db6add..000000000 --- a/python/py_igl/py_lscm.cpp +++ /dev/null @@ -1,20 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("lscm", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::MatrixXi& b, - const Eigen::MatrixXd& bc, - Eigen::MatrixXd& V_uv -) -{ - assert_is_VectorX("b",b); - return igl::lscm(V,F,b,bc,V_uv); -}, __doc_igl_lscm, -py::arg("V"), py::arg("F"), py::arg("b"), py::arg("bc"), py::arg("V_uv")); diff --git a/python/py_igl/py_map_vertices_to_circle.cpp b/python/py_igl/py_map_vertices_to_circle.cpp deleted file mode 100755 index e7ca6cf73..000000000 --- a/python/py_igl/py_map_vertices_to_circle.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("map_vertices_to_circle", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& bnd, - Eigen::MatrixXd& UV -) -{ - assert_is_VectorX("bnd",bnd); - return igl::map_vertices_to_circle(V,bnd,UV); -}, __doc_igl_map_vertices_to_circle, -py::arg("V"), py::arg("bnd"), py::arg("UV")); diff --git a/python/py_igl/py_marching_tets.cpp b/python/py_igl/py_marching_tets.cpp deleted file mode 100644 index ec02e1dee..000000000 --- a/python/py_igl/py_marching_tets.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("marching_tets", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& T, - const Eigen::MatrixXd& plane, - Eigen::MatrixXd& U, - Eigen::MatrixXi& G, - Eigen::MatrixXi& J, - Eigen::SparseMatrix& BC -) -{ - assert_is_VectorX("plane", plane); - Eigen::VectorXd planev; - if (plane.size() != 0) - planev = plane; - Eigen::VectorXi Jv; - igl::marching_tets(V, T, planev, U, G, Jv, BC); - J = Jv; -}, __doc_igl_marching_tets, -py::arg("V"), py::arg("T"), py::arg("plane"), py::arg("U"), py::arg("G"), py::arg("J"), py::arg("BC")); - diff --git a/python/py_igl/py_massmatrix.cpp b/python/py_igl/py_massmatrix.cpp deleted file mode 100644 index 79d73de20..000000000 --- a/python/py_igl/py_massmatrix.cpp +++ /dev/null @@ -1,26 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -py::enum_(m, "MassMatrixType") - .value("MASSMATRIX_TYPE_BARYCENTRIC", igl::MASSMATRIX_TYPE_BARYCENTRIC) - .value("MASSMATRIX_TYPE_VORONOI", igl::MASSMATRIX_TYPE_VORONOI) - .value("MASSMATRIX_TYPE_FULL", igl::MASSMATRIX_TYPE_FULL) - .value("MASSMATRIX_TYPE_DEFAULT", igl::MASSMATRIX_TYPE_DEFAULT) - .value("NUM_MASSMATRIX_TYPE", igl::NUM_MASSMATRIX_TYPE) - .export_values(); - -m.def("massmatrix", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const igl::MassMatrixType type, - Eigen::SparseMatrix& M -) -{ - return igl::massmatrix(V,F,type,M); -}, __doc_igl_massmatrix, -py::arg("V"), py::arg("F"), py::arg("type"), py::arg("M")); diff --git a/python/py_igl/py_min_quad_with_fixed.cpp b/python/py_igl/py_min_quad_with_fixed.cpp deleted file mode 100644 index 31c100a6e..000000000 --- a/python/py_igl/py_min_quad_with_fixed.cpp +++ /dev/null @@ -1,80 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - -// Wrap the data class, no properties are exposed since it is not necessary -py::class_ > min_quad_with_fixed_data(m, "min_quad_with_fixed_data"); - -min_quad_with_fixed_data -.def(py::init<>()); - -m.def("min_quad_with_fixed_precompute", [] -( - const Eigen::SparseMatrix& A, - const Eigen::MatrixXi& known, - const Eigen::SparseMatrix& Aeq, - const bool pd, - igl::min_quad_with_fixed_data & data -) -{ - assert_is_VectorX("known",known); - return igl::min_quad_with_fixed_precompute(A,known,Aeq,pd,data); -}, __doc_igl_min_quad_with_fixed, -py::arg("A"), py::arg("known"), py::arg("Aeq"), py::arg("pd"), py::arg("data")); - -m.def("min_quad_with_fixed_solve", [] -( - const igl::min_quad_with_fixed_data & data, - const Eigen::MatrixXd& B, - const Eigen::MatrixXd& Y, - const Eigen::MatrixXd & Beq, - Eigen::MatrixXd& Z, - Eigen::MatrixXd& sol -) -{ - assert_is_VectorX("B",B); - assert_is_VectorX("Y",Y); - assert_is_VectorX("Beq",Beq); - return igl::min_quad_with_fixed_solve(data,B,Y,Beq,Z,sol); -}, __doc_igl_min_quad_with_fixed, -py::arg("data"), py::arg("B"), py::arg("Y"), py::arg("Beq"), py::arg("Z"), py::arg("sol")); - -m.def("min_quad_with_fixed_solve", [] -( - const igl::min_quad_with_fixed_data & data, - const Eigen::MatrixXd& B, - const Eigen::MatrixXd& Y, - const Eigen::MatrixXd & Beq, - Eigen::MatrixXd& Z -) -{ - assert_is_VectorX("B",B); - assert_is_VectorX("Y",Y); - assert_is_VectorX("Beq",Beq); - return igl::min_quad_with_fixed_solve(data,B,Y,Beq,Z); -}, __doc_igl_min_quad_with_fixed, -py::arg("data"), py::arg("B"), py::arg("Y"), py::arg("Beq"), py::arg("Z")); - -m.def("min_quad_with_fixed", [] -( - const Eigen::SparseMatrix& A, - const Eigen::MatrixXd& B, - const Eigen::MatrixXi& known, - const Eigen::MatrixXd& Y, - const Eigen::SparseMatrix& Aeq, - const Eigen::MatrixXd& Beq, - const bool pd, - Eigen::MatrixXd& Z -) -{ - assert_is_VectorX("B",B); - assert_is_VectorX("known",known); - assert_is_VectorX("Y",Y); - assert_is_VectorX("Beq",Beq); - return igl::min_quad_with_fixed(A,B,known,Y,Aeq,Beq,pd,Z); -}, __doc_igl_min_quad_with_fixed, -py::arg("A"), py::arg("B"), py::arg("known"), py::arg("Y"), py::arg("Aeq"), py::arg("Beq"), py::arg("pd"), py::arg("Z")); diff --git a/python/py_igl/py_normalize_row_lengths.cpp b/python/py_igl/py_normalize_row_lengths.cpp deleted file mode 100644 index 546c5f66f..000000000 --- a/python/py_igl/py_normalize_row_lengths.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - - -m.def("normalize_row_lengths", [] -( - const Eigen::MatrixXd& A, - Eigen::MatrixXd& B -) -{ - return igl::normalize_row_lengths(A, B); -}, __doc_igl_normalize_row_lengths, -py::arg("A"), py::arg("B")); - diff --git a/python/py_igl/py_normalize_row_sums.cpp b/python/py_igl/py_normalize_row_sums.cpp deleted file mode 100644 index c657ae568..000000000 --- a/python/py_igl/py_normalize_row_sums.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - - -m.def("normalize_row_sums", [] -( - const Eigen::MatrixXd& A, - Eigen::MatrixXd& B -) -{ - return igl::normalize_row_sums(A, B); -}, __doc_igl_normalize_row_sums, -py::arg("A"), py::arg("B")); - diff --git a/python/py_igl/py_parula.cpp b/python/py_igl/py_parula.cpp deleted file mode 100644 index 1ab41bd6d..000000000 --- a/python/py_igl/py_parula.cpp +++ /dev/null @@ -1,65 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -//m.def("parula", [] -//( -// const double f, -// T * rgb -//) -//{ -// return igl::parula(f, rgb); -//}, __doc_igl_parula, -//py::arg("f"), py::arg("rgb")); - -m.def("parula", [] -( -const double f -) -{ - double r, g, b; - igl::parula(f, r, g, b); - return std::make_tuple(r,g,b); -}, __doc_igl_parula, -py::arg("f")); - -m.def("parula", [] -( - const double f, - double & r, - double & g, - double & b -) -{ - return igl::parula(f, r, g, b); -}, __doc_igl_parula, -py::arg("f"), py::arg("r"), py::arg("g"), py::arg("b")); - -m.def("parula", [] -( - const Eigen::MatrixXd& Z, - const bool normalize, - Eigen::MatrixXd& C -) -{ - assert_is_VectorX("Z",Z); - return igl::parula(Z, normalize, C); -}, __doc_igl_parula, -py::arg("Z"), py::arg("normalize"), py::arg("C")); - -m.def("parula", [] -( - const Eigen::MatrixXd& Z, - const double min_Z, - const double max_Z, - Eigen::MatrixXd& C -) -{ - assert_is_VectorX("Z",Z); - return igl::parula(Z, min_Z, max_Z, C); -}, __doc_igl_parula, -py::arg("Z"), py::arg("min_Z"), py::arg("max_Z"), py::arg("C")); - diff --git a/python/py_igl/py_per_corner_normals.cpp b/python/py_igl/py_per_corner_normals.cpp deleted file mode 100644 index a0b24c49b..000000000 --- a/python/py_igl/py_per_corner_normals.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("per_corner_normals", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const double corner_threshold, - Eigen::MatrixXd& CN -) -{ - return igl::per_corner_normals(V,F,corner_threshold,CN); -}, __doc_igl_per_corner_normals, -py::arg("V"), py::arg("F"), py::arg("corner_threshold"), py::arg("CN")); - -m.def("per_corner_normals", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::MatrixXd& FN, - const double corner_threshold, - Eigen::MatrixXd& CN -) -{ - return igl::per_corner_normals(V,F,FN,corner_threshold,CN); -}, __doc_igl_per_corner_normals, -py::arg("V"), py::arg("F"), py::arg("FN"), py::arg("corner_threshold"), py::arg("CN")); - -m.def("per_corner_normals", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::MatrixXd& FN, - const double corner_threshold, - const std::vector >& VF, - Eigen::MatrixXd& CN -) -{ - return igl::per_corner_normals(V,F,FN,VF,corner_threshold,CN); -}, __doc_igl_per_corner_normals, -py::arg("V"), py::arg("F"), py::arg("FN"), py::arg("corner_threshold"), py::arg("VF"), py::arg("CN")); diff --git a/python/py_igl/py_per_edge_normals.cpp b/python/py_igl/py_per_edge_normals.cpp deleted file mode 100644 index 25f929db2..000000000 --- a/python/py_igl/py_per_edge_normals.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -py::enum_(m, "PerEdgeNormalsWeightingType") - .value("PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM", igl::PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM) - .value("PER_EDGE_NORMALS_WEIGHTING_TYPE_AREA", igl::PER_EDGE_NORMALS_WEIGHTING_TYPE_AREA) - .value("PER_EDGE_NORMALS_WEIGHTING_TYPE_DEFAULT", igl::PER_EDGE_NORMALS_WEIGHTING_TYPE_DEFAULT) - .value("NUM_PER_EDGE_NORMALS_WEIGHTING_TYPE", igl::NUM_PER_EDGE_NORMALS_WEIGHTING_TYPE) - .export_values(); - - -m.def("per_edge_normals", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const igl::PerEdgeNormalsWeightingType weight, - const Eigen::MatrixXd& FN, - Eigen::MatrixXd& N, - Eigen::MatrixXi& E, - Eigen::MatrixXi& EMAP -) -{ - return igl::per_edge_normals(V, F, weight, FN, N, E, EMAP); -}, __doc_igl_per_edge_normals, -py::arg("V"), py::arg("F"), py::arg("weight"), py::arg("FN"), py::arg("N"), py::arg("E"), py::arg("EMAP")); - -m.def("per_edge_normals", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const igl::PerEdgeNormalsWeightingType weight, - Eigen::MatrixXd& N, - Eigen::MatrixXi& E, - Eigen::MatrixXi& EMAP -) -{ - return igl::per_edge_normals(V, F, weight, N, E, EMAP); -}, __doc_igl_per_edge_normals, -py::arg("V"), py::arg("F"), py::arg("weight"), py::arg("N"), py::arg("E"), py::arg("EMAP")); - -m.def("per_edge_normals", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::MatrixXd& N, - Eigen::MatrixXi& E, - Eigen::MatrixXi& EMAP -) -{ - return igl::per_edge_normals(V, F, N, E, EMAP); -}, __doc_igl_per_edge_normals, -py::arg("V"), py::arg("F"), py::arg("N"), py::arg("E"), py::arg("EMAP")); - diff --git a/python/py_igl/py_per_face_normals.cpp b/python/py_igl/py_per_face_normals.cpp deleted file mode 100644 index 2321e8903..000000000 --- a/python/py_igl/py_per_face_normals.cpp +++ /dev/null @@ -1,41 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("per_face_normals", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::MatrixXd& Z, - Eigen::MatrixXd& N -) -{ - assert_is_VectorX("Z",Z); - return igl::per_face_normals(V,F,Z,N); -}, __doc_igl_per_face_normals, -py::arg("V"), py::arg("F"), py::arg("Z"), py::arg("N")); - -m.def("per_face_normals", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::MatrixXd& N -) -{ - return igl::per_face_normals(V,F,N); -}, __doc_igl_per_face_normals, -py::arg("V"), py::arg("F"), py::arg("N")); - -m.def("per_face_normals_stable", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::MatrixXd& N -) -{ - return igl::per_face_normals_stable(V,F,N); -}, __doc_igl_per_face_normals, -py::arg("V"), py::arg("F"), py::arg("N")); diff --git a/python/py_igl/py_per_vertex_normals.cpp b/python/py_igl/py_per_vertex_normals.cpp deleted file mode 100644 index 2adb9e75a..000000000 --- a/python/py_igl/py_per_vertex_normals.cpp +++ /dev/null @@ -1,62 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -py::enum_(m, "PerVertexNormalsWeightingType") - .value("PER_VERTEX_NORMALS_WEIGHTING_TYPE_UNIFORM", igl::PER_VERTEX_NORMALS_WEIGHTING_TYPE_UNIFORM) - .value("PER_VERTEX_NORMALS_WEIGHTING_TYPE_AREA", igl::PER_VERTEX_NORMALS_WEIGHTING_TYPE_AREA) - .value("PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE", igl::PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE) - .value("PER_VERTEX_NORMALS_WEIGHTING_TYPE_DEFAULT", igl::PER_VERTEX_NORMALS_WEIGHTING_TYPE_DEFAULT) - .value("NUM_PER_VERTEX_NORMALS_WEIGHTING_TYPE", igl::NUM_PER_VERTEX_NORMALS_WEIGHTING_TYPE) - .export_values(); - -m.def("per_vertex_normals", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const igl::PerVertexNormalsWeightingType weighting, - Eigen::MatrixXd& N -) -{ - return igl::per_vertex_normals(V,F,weighting,N); -}, __doc_igl_per_vertex_normals, -py::arg("V"), py::arg("F"), py::arg("weighting"), py::arg("N")); - -m.def("per_vertex_normals", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::MatrixXd& N -) -{ - return igl::per_vertex_normals(V,F,N); -}, __doc_igl_per_vertex_normals, -py::arg("V"), py::arg("F"), py::arg("N")); - -m.def("per_vertex_normals", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const igl::PerVertexNormalsWeightingType weighting, - const Eigen::MatrixXd& FN, - Eigen::MatrixXd& N -) -{ - return igl::per_vertex_normals(V,F,weighting,FN,N); -}, __doc_igl_per_vertex_normals, -py::arg("V"), py::arg("F"), py::arg("weighting"), py::arg("FN"), py::arg("N")); - -m.def("per_vertex_normals", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::MatrixXd& FN, - Eigen::MatrixXd& N -) -{ - return igl::per_vertex_normals(V,F,FN,N); -}, __doc_igl_per_vertex_normals, -py::arg("V"), py::arg("F"), py::arg("FN"), py::arg("N")); diff --git a/python/py_igl/py_planarize_quad_mesh.cpp b/python/py_igl/py_planarize_quad_mesh.cpp deleted file mode 100644 index e577fc7f9..000000000 --- a/python/py_igl/py_planarize_quad_mesh.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - -m.def("planarize_quad_mesh", [] -( - const Eigen::MatrixXd& Vin, - const Eigen::MatrixXi& F, - const int maxIter, - const double & threshold, - Eigen::MatrixXd& Vout -) -{ - return igl::planarize_quad_mesh(Vin, F, maxIter, threshold, Vout); -}, __doc_igl_planarize_quad_mesh, -py::arg("Vin"), py::arg("F"), py::arg("maxIter"), py::arg("threshold"), py::arg("Vout")); - diff --git a/python/py_igl/py_point_mesh_squared_distance.cpp b/python/py_igl/py_point_mesh_squared_distance.cpp deleted file mode 100644 index 11c9315cf..000000000 --- a/python/py_igl/py_point_mesh_squared_distance.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("point_mesh_squared_distance", [] -( - const Eigen::MatrixXd& P, - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& Ele, - Eigen::MatrixXd& sqrD, - Eigen::MatrixXi& I, - Eigen::MatrixXd& C -) -{ -// assert_is_VectorX("I",I); - return igl::point_mesh_squared_distance(P, V, Ele, sqrD, I, C); -}, __doc_igl_point_mesh_squared_distance, -py::arg("P"), py::arg("V"), py::arg("Ele"), py::arg("sqrD"), py::arg("I"), py::arg("C")); - diff --git a/python/py_igl/py_polar_svd.cpp b/python/py_igl/py_polar_svd.cpp deleted file mode 100644 index 1a2b1d82d..000000000 --- a/python/py_igl/py_polar_svd.cpp +++ /dev/null @@ -1,33 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("polar_svd", [] -( - const Eigen::MatrixXd& A, - Eigen::MatrixXd& R, - Eigen::MatrixXd& T, - Eigen::MatrixXd& U, - Eigen::MatrixXd& S, - Eigen::MatrixXd& V -) -{ - return igl::polar_svd(A, R, T, U, S, V); -}, __doc_igl_polar_svd, -py::arg("A"), py::arg("R"), py::arg("T"), py::arg("U"), py::arg("S"), py::arg("V")); - - -m.def("polar_svd", [] -( - const Eigen::MatrixXd& A, - Eigen::MatrixXd& R, - Eigen::MatrixXd& T -) -{ - return igl::polar_svd(A, R, T); -}, __doc_igl_polar_svd, -py::arg("A"), py::arg("R"), py::arg("T")); - diff --git a/python/py_igl/py_principal_curvature.cpp b/python/py_igl/py_principal_curvature.cpp deleted file mode 100644 index d6389c2e6..000000000 --- a/python/py_igl/py_principal_curvature.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("principal_curvature", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::MatrixXd& PD1, - Eigen::MatrixXd& PD2, - Eigen::MatrixXd& PV1, - Eigen::MatrixXd& PV2, - unsigned radius, - bool useKring -) -{ - return igl::principal_curvature(V,F,PD1,PD2,PV1,PV2,radius,useKring); -}, __doc_igl_principal_curvature, -py::arg("V"), py::arg("F"), py::arg("PD1"), py::arg("PD2"), py::arg("PV1"), py::arg("PV2"), py::arg("radius") = 5, py::arg("useKring") = true); diff --git a/python/py_igl/py_quad_planarity.cpp b/python/py_igl/py_quad_planarity.cpp deleted file mode 100644 index 800d2c326..000000000 --- a/python/py_igl/py_quad_planarity.cpp +++ /dev/null @@ -1,22 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - - -m.def("quad_planarity", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::MatrixXd& P -) -{ - Eigen::VectorXd Pv; - igl::quad_planarity(V, F, Pv); - P = Pv; -}, __doc_igl_quad_planarity, -py::arg("V"), py::arg("F"), py::arg("P")); - diff --git a/python/py_igl/py_randperm.cpp b/python/py_igl/py_randperm.cpp deleted file mode 100644 index a0cea43e2..000000000 --- a/python/py_igl/py_randperm.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("randperm", [] -( - int n, - Eigen::MatrixXi& I -) -{ - return igl::randperm(n, I); -}, __doc_igl_randperm, -py::arg("n"), py::arg("I")); - diff --git a/python/py_igl/py_readDMAT.cpp b/python/py_igl/py_readDMAT.cpp deleted file mode 100644 index f80ff538d..000000000 --- a/python/py_igl/py_readDMAT.cpp +++ /dev/null @@ -1,17 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - -m.def("readDMAT", [] -( - const std::string str, - Eigen::MatrixXd& W -) -{ - return igl::readDMAT(str,W); -}, __doc_igl_readDMAT, -py::arg("str"), py::arg("W")); diff --git a/python/py_igl/py_readMESH.cpp b/python/py_igl/py_readMESH.cpp deleted file mode 100644 index 244d3392a..000000000 --- a/python/py_igl/py_readMESH.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("readMESH", [] -( - const std::string mesh_file_name, - Eigen::MatrixXd& V, - Eigen::MatrixXi& T, - Eigen::MatrixXi& F -) -{ - return igl::readMESH(mesh_file_name, V, T, F); -}, __doc_igl_readMESH, -py::arg("mesh_file_name"), py::arg("V"), py::arg("T"), py::arg("F")); - - -m.def("readMESH", [] -( - const std::string mesh_file_name, - std::vector > & V, - std::vector > & T, - std::vector > & F -) -{ - return igl::readMESH(mesh_file_name, V, T, F); -}, __doc_igl_readMESH, -py::arg("mesh_file_name"), py::arg("V"), py::arg("T"), py::arg("F")); - - - diff --git a/python/py_igl/py_readOBJ.cpp b/python/py_igl/py_readOBJ.cpp deleted file mode 100644 index a8073b3bd..000000000 --- a/python/py_igl/py_readOBJ.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("readOBJ", [] -( - const std::string str, - Eigen::MatrixXd& V, - Eigen::MatrixXd& TC, - Eigen::MatrixXd& CN, - Eigen::MatrixXi& F, - Eigen::MatrixXi& FTC, - Eigen::MatrixXi& FN -) -{ - return igl::readOBJ(str,V,TC,CN,F,FTC,FN); -}, __doc_igl_readOBJ, -py::arg("str"), py::arg("V"), py::arg("TC"), py::arg("CN"), py::arg("F"), py::arg("FTC"), py::arg("FN")); - -m.def("readOBJ", [] -( - const std::string str, - Eigen::MatrixXd& V, - Eigen::MatrixXi& F -) -{ - return igl::readOBJ(str,V,F); -}, __doc_igl_readOBJ, -py::arg("str"), py::arg("V"), py::arg("F")); diff --git a/python/py_igl/py_readOFF.cpp b/python/py_igl/py_readOFF.cpp deleted file mode 100644 index 6df9c5c57..000000000 --- a/python/py_igl/py_readOFF.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("readOFF", [] -( - const std::string str, - Eigen::MatrixXd& V, - Eigen::MatrixXi& F -) -{ - return igl::readOFF(str,V,F); -}, __doc_igl_readOFF, -py::arg("str"), py::arg("V"), py::arg("F")); - -m.def("readOFF", [] -( - const std::string str, - Eigen::MatrixXd& V, - Eigen::MatrixXi& F, - Eigen::MatrixXd& N -) -{ - return igl::readOFF(str,V,F,N); -}, __doc_igl_readOFF, -py::arg("str"), py::arg("V"), py::arg("F"), py::arg("N")); diff --git a/python/py_igl/py_readPLY.cpp b/python/py_igl/py_readPLY.cpp deleted file mode 100644 index 6f2367001..000000000 --- a/python/py_igl/py_readPLY.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("readPLY", [] -( - const std::string str, - Eigen::MatrixXd& V, - Eigen::MatrixXi& F, - Eigen::MatrixXd& N, - Eigen::MatrixXd& UV -) -{ - return igl::readPLY(str,V,F,N,UV); -}, __doc_igl_readPLY, -py::arg("str"), py::arg("V"), py::arg("F"), py::arg("N"), py::arg("UV")); diff --git a/python/py_igl/py_readTGF.cpp b/python/py_igl/py_readTGF.cpp deleted file mode 100644 index 7c9700f52..000000000 --- a/python/py_igl/py_readTGF.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -// COMPLETE BINDINGS ======================== - - -m.def("readTGF", [] -( - const std::string tgf_filename, - Eigen::MatrixXd& C, - Eigen::MatrixXi& E, - Eigen::MatrixXi& P, - Eigen::MatrixXi& BE, - Eigen::MatrixXi& CE, - Eigen::MatrixXi& PE -) -{ - Eigen::VectorXi Pv; - bool ret = igl::readTGF(tgf_filename, C, E, Pv, BE, CE, PE); - P = Pv; - return ret; -}, __doc_igl_readTGF, -py::arg("tgf_filename"), py::arg("C"), py::arg("E"), py::arg("P"), py::arg("BE"), py::arg("CE"), py::arg("PE")); - -m.def("readTGF", [] -( - const std::string tgf_filename, - Eigen::MatrixXd& C, - Eigen::MatrixXi& E -) -{ - return igl::readTGF(tgf_filename, C, E); -}, __doc_igl_readTGF, -py::arg("tgf_filename"), py::arg("C"), py::arg("E")); - - - - - -// INCOMPLETE BINDINGS ======================== - - -//m.def("readTGF", [] -//( -// const std::string tgf_filename, -// std::vector > & C, -// std::vector > & E, -// std::vector & P, -// std::vector > & BE, -// std::vector > & CE, -// std::vector > & PE -//) -//{ -// return igl::readTGF(tgf_filename, C, E, P, BE, CE, PE); -//}, __doc_igl_readTGF, -//py::arg("tgf_filename"), py::arg("C"), py::arg("E"), py::arg("P"), py::arg("BE"), py::arg("CE"), py::arg("PE")); - diff --git a/python/py_igl/py_read_triangle_mesh.cpp b/python/py_igl/py_read_triangle_mesh.cpp deleted file mode 100644 index 74cdaca7b..000000000 --- a/python/py_igl/py_read_triangle_mesh.cpp +++ /dev/null @@ -1,43 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("read_triangle_mesh", [] -( - const std::string str, - Eigen::MatrixXd& V, - Eigen::MatrixXi& F -) -{ - return igl::read_triangle_mesh(str,V,F); -}, __doc_igl_read_triangle_mesh, -py::arg("str"), py::arg("V"), py::arg("F")); - -m.def("read_triangle_mesh", [] -( - const std::string str, - Eigen::MatrixXd& V, - Eigen::MatrixXi& F, - std::string & dir, - std::string & base, - std::string & ext, - std::string & name -) -{ - return igl::read_triangle_mesh(str,V,F,dir,base,ext,name); -}, __doc_igl_read_triangle_mesh, -py::arg("str"), py::arg("V"), py::arg("F"), py::arg("dir"), py::arg("base"), py::arg("ext"), py::arg("name")); - -m.def("read_triangle_mesh", [] -( - const std::string str, - std::vector >& V, - std::vector >& F -) -{ - return igl::read_triangle_mesh(str,V,F); -}, __doc_igl_read_triangle_mesh, -py::arg("str"), py::arg("V"), py::arg("F")); diff --git a/python/py_igl/py_remove_duplicate_vertices.cpp b/python/py_igl/py_remove_duplicate_vertices.cpp deleted file mode 100644 index 8c55d4826..000000000 --- a/python/py_igl/py_remove_duplicate_vertices.cpp +++ /dev/null @@ -1,21 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("remove_duplicate_vertices", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const double epsilon, - Eigen::MatrixXd& SV, - Eigen::MatrixXi& SVI, - Eigen::MatrixXi& SVJ, - Eigen::MatrixXi& SF -) -{ - return igl::remove_duplicate_vertices(V, F, epsilon, SV, SVI, SVJ, SF); -}, __doc_igl_remove_duplicate_vertices, -py::arg("V"), py::arg("F"), py::arg("epsilon"), py::arg("SV"), py::arg("SVI"), py::arg("SVJ"), py::arg("SF")); diff --git a/python/py_igl/py_rotate_vectors.cpp b/python/py_igl/py_rotate_vectors.cpp deleted file mode 100644 index b4a9e2f04..000000000 --- a/python/py_igl/py_rotate_vectors.cpp +++ /dev/null @@ -1,19 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("rotate_vectors", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXd& A, - const Eigen::MatrixXd& B1, - const Eigen::MatrixXd& B2 -) -{ - assert_is_VectorX("A",A); - return igl::rotate_vectors(V,A,B1,B2); -}, __doc_igl_rotate_vectors, -py::arg("V"), py::arg("A"), py::arg("B1"), py::arg("B2")); diff --git a/python/py_igl/py_seam_edges.cpp b/python/py_igl/py_seam_edges.cpp deleted file mode 100755 index c3464012b..000000000 --- a/python/py_igl/py_seam_edges.cpp +++ /dev/null @@ -1,21 +0,0 @@ -m.def("seam_edges", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXd& TC, - const Eigen::MatrixXi& F, - const Eigen::MatrixXi& FTC, - Eigen::MatrixXi& seams, - Eigen::MatrixXi& boundaries, - Eigen::MatrixXi& foldovers -) -{ -return igl::seam_edges( V, TC, F, FTC, seams, boundaries, foldovers); -}, __doc_igl_seam_edges, -py::arg("V"), -py::arg("TC"), -py::arg("F"), -py::arg("FTC"), -py::arg("seams"), -py::arg("boundaries"), -py::arg("foldovers")); - diff --git a/python/py_igl/py_setdiff.cpp b/python/py_igl/py_setdiff.cpp deleted file mode 100644 index 6c7591318..000000000 --- a/python/py_igl/py_setdiff.cpp +++ /dev/null @@ -1,18 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("setdiff", [] -( - const Eigen::MatrixXi& A, - const Eigen::MatrixXi& B, - Eigen::MatrixXi& C, - Eigen::MatrixXi& IA -) -{ - return igl::setdiff(A,B,C,IA); -}, __doc_igl_setdiff, -py::arg("A"), py::arg("B"), py::arg("C"), py::arg("IA")); diff --git a/python/py_igl/py_shape_diameter_function.cpp b/python/py_igl/py_shape_diameter_function.cpp deleted file mode 100644 index 92826fc2d..000000000 --- a/python/py_igl/py_shape_diameter_function.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - -m.def("shape_diameter_function", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::MatrixXd& P, - const Eigen::MatrixXd& N, - const int num_samples, - Eigen::MatrixXd& S -) -{ - return igl::shape_diameter_function(V, F, P, N, num_samples, S); -}, __doc_igl_shape_diameter_function, -py::arg("V"), py::arg("F"), py::arg("P"), py::arg("N"), py::arg("num_samples"), py::arg("S")); - -m.def("shape_diameter_function", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const bool per_face, - const int num_samples, - Eigen::MatrixXd& S -) -{ - return igl::shape_diameter_function(V, F, per_face, num_samples, S); -}, __doc_igl_shape_diameter_function, -py::arg("V"), py::arg("F"), py::arg("per_face"), py::arg("num_samples"), py::arg("S")); - diff --git a/python/py_igl/py_signed_distance.cpp b/python/py_igl/py_signed_distance.cpp deleted file mode 100644 index 1bb7530c0..000000000 --- a/python/py_igl/py_signed_distance.cpp +++ /dev/null @@ -1,139 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - -py::enum_(m, "SignedDistanceType") - .value("SIGNED_DISTANCE_TYPE_PSEUDONORMAL", igl::SIGNED_DISTANCE_TYPE_PSEUDONORMAL) - .value("SIGNED_DISTANCE_TYPE_WINDING_NUMBER", igl::SIGNED_DISTANCE_TYPE_WINDING_NUMBER) - .value("SIGNED_DISTANCE_TYPE_DEFAULT", igl::SIGNED_DISTANCE_TYPE_DEFAULT) - .value("SIGNED_DISTANCE_TYPE_UNSIGNED", igl::SIGNED_DISTANCE_TYPE_UNSIGNED) - .value("NUM_SIGNED_DISTANCE_TYPE", igl::NUM_SIGNED_DISTANCE_TYPE) - .export_values(); - - -m.def("signed_distance", [] -( - const Eigen::MatrixXd& P, - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const igl::SignedDistanceType sign_type, - Eigen::MatrixXd& S, - Eigen::MatrixXi& I, - Eigen::MatrixXd& C, - Eigen::MatrixXd& N -) -{ - Eigen::VectorXd Sv; - Eigen::VectorXi Iv; - igl::signed_distance(P, V, F, sign_type, Sv, Iv, C, N); - S = Sv; - I = Iv; -}, __doc_igl_signed_distance, -py::arg("P"), py::arg("V"), py::arg("F"), py::arg("sign_type"), py::arg("S"), py::arg("I"), py::arg("C"), py::arg("N")); - -//m.def("signed_distance_pseudonormal", [] -//( -// const AABB & tree, -// const Eigen::MatrixXd& V, -// const Eigen::MatrixXi& F, -// const Eigen::MatrixXd& FN, -// const Eigen::MatrixXd& VN, -// const Eigen::MatrixXd& EN, -// const Eigen::MatrixXi& EMAP, -// const Eigen::MatrixXd& q -//) -//{ -// assert_is_VectorX("q", q); -// assert_is_VectorX("EMAP",EMAP); -// return igl::signed_distance_pseudonormal(tree, V, F, FN, VN, EN, EMAP, q); -//}, __doc_igl_signed_distance_pseudonormal, -//py::arg("tree"), py::arg("V"), py::arg("F"), py::arg("FN"), py::arg("VN"), py::arg("EN"), py::arg("EMAP"), py::arg("q")); - -m.def("signed_distance_pseudonormal", [] -( - const Eigen::MatrixXd& P, - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const igl::AABB & tree, - const Eigen::MatrixXd& FN, - const Eigen::MatrixXd& VN, - const Eigen::MatrixXd& EN, - const Eigen::MatrixXi& EMAP, - Eigen::MatrixXd& S, - Eigen::MatrixXi& I, - Eigen::MatrixXd& C, - Eigen::MatrixXd& N -) -{ - assert_is_VectorX("EMAP", EMAP); - Eigen::VectorXi EMAPv; - if (EMAP.size() != 0) - EMAPv = EMAP; - Eigen::VectorXd Sv; - Eigen::VectorXi Iv; - igl::signed_distance_pseudonormal(P, V, F, tree, FN, VN, EN, EMAPv, Sv, Iv, C, N); - S = Sv; - I = Iv; -}, __doc_igl_signed_distance_pseudonormal, -py::arg("P"), py::arg("V"), py::arg("F"), py::arg("tree"), py::arg("FN"), py::arg("VN"), py::arg("EN"), py::arg("EMAP"), py::arg("S"), py::arg("I"), py::arg("C"), py::arg("N")); - -//m.def("signed_distance_pseudonormal", [] -//( -// const AABB & tree, -// const Eigen::MatrixXd& V, -// const Eigen::MatrixXi& F, -// const Eigen::MatrixXd& FN, -// const Eigen::MatrixXd& VN, -// const Eigen::MatrixXd& EN, -// const Eigen::MatrixXi & EMAP, -// const Eigen::MatrixXd & q, -// double & s, -// double & sqrd, -// int & i, -// Eigen::MatrixXd & c, -// Eigen::MatrixXd & n -//) -//{ -// assert_is_VectorX("EMAP",EMAP); -// assert_is_VectorX("q",q); -// return igl::signed_distance_pseudonormal(tree, V, F, FN, VN, EN, EMAP, q, s, sqrd, i, c, n); -//}, __doc_igl_signed_distance_pseudonormal, -//py::arg("tree"), py::arg("V"), py::arg("F"), py::arg("FN"), py::arg("VN"), py::arg("EN"), py::arg("EMAP"), py::arg("q"), py::arg("s"), py::arg("sqrd"), py::arg("i"), py::arg("c"), py::arg("n")); - -//m.def("signed_distance_pseudonormal", [] -//( -// const AABB & tree, -// const Eigen::MatrixXd& V, -// const Eigen::MatrixXi& F, -// const Eigen::MatrixXd& FN, -// const Eigen::MatrixXd& VN, -// const Eigen::MatrixXd & q, -// double & s, -// double & sqrd, -// int & i, -// Eigen::MatrixXd & c, -// Eigen::MatrixXd & n -//) -//{ -// assert_is_VectorX("q",q); -// return igl::signed_distance_pseudonormal(tree, V, F, FN, VN, q, s, sqrd, i, c, n); -//}, __doc_igl_signed_distance_pseudonormal, -//py::arg("tree"), py::arg("V"), py::arg("F"), py::arg("FN"), py::arg("VN"), py::arg("q"), py::arg("s"), py::arg("sqrd"), py::arg("i"), py::arg("c"), py::arg("n")); - -//m.def("signed_distance_winding_number", [] -//( -// AABB & tree, -// const Eigen::MatrixXd& V, -// const Eigen::MatrixXi& F, -// igl::WindingNumberAABB & hier, -// Eigen::RowVector3d & q -//) -//{ -// return igl::signed_distance_winding_number(tree, V, F, hier, q); -//}, __doc_igl_signed_distance_winding_number, -//py::arg("tree"), py::arg("V"), py::arg("F"), py::arg("hier"), py::arg("q")); - diff --git a/python/py_igl/py_slice.cpp b/python/py_igl/py_slice.cpp deleted file mode 100644 index c5c5c4502..000000000 --- a/python/py_igl/py_slice.cpp +++ /dev/null @@ -1,175 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -// // Double -// -m.def("slice", [] -( - const Eigen::SparseMatrix& X, - const Eigen::MatrixXi& R, - const Eigen::MatrixXi& C, - Eigen::SparseMatrix& Y -) -{ - assert_is_VectorX("R",R); - assert_is_VectorX("C",C); - return igl::slice(X,R,C,Y); -}, __doc_igl_slice, -py::arg("X"), py::arg("R"), py::arg("C"), py::arg("Y")); - -m.def("slice", [] -( - const Eigen::SparseMatrix& X, - const Eigen::MatrixXi& R, - const int& dim, - Eigen::SparseMatrix& Y -) -{ - assert_is_VectorX("R",R); - return igl::slice(X,R,dim,Y); -}, __doc_igl_slice, -py::arg("X"), py::arg("R"), py::arg("dim"), py::arg("Y")); - -m.def("slice", [] -( - const Eigen::MatrixXd& X, - const Eigen::MatrixXi& R, - const Eigen::MatrixXi& C, - Eigen::MatrixXd& Y -) -{ - assert_is_VectorX("R",R); - assert_is_VectorX("C",C); - return igl::slice(X,R,C,Y); -}, __doc_igl_slice, -py::arg("X"), py::arg("R"), py::arg("C"), py::arg("Y")); - -m.def("slice", [] -( - const Eigen::MatrixXd& X, - const Eigen::MatrixXi& R, - const int dim, - Eigen::MatrixXd& Y -) -{ - assert_is_VectorX("R",R); - return igl::slice(X,R,dim,Y); -}, __doc_igl_slice, -py::arg("X"), py::arg("R"), py::arg("dim"), py::arg("Y")); - -m.def("slice", [] -( - const Eigen::MatrixXd& X, - const Eigen::MatrixXi& R, - Eigen::MatrixXd& Y -) -{ - assert_is_VectorX("R",R); - return igl::slice(X,R,Y); -}, __doc_igl_slice, -py::arg("X"), py::arg("R"), py::arg("Y")); - -m.def("slice", [] -( - const Eigen::MatrixXd& X, - const Eigen::MatrixXi& R -) -{ - assert_is_VectorX("R",R); - return igl::slice(X,R); -}, __doc_igl_slice, -py::arg("X"), py::arg("A")); - -m.def("slice", [] -( - const Eigen::MatrixXd& X, - const Eigen::MatrixXi& R, - const int& dim -) -{ - assert_is_VectorX("R",R); - return igl::slice(X,R,dim); -}, __doc_igl_slice, -py::arg("X"), py::arg("R"), py::arg("dim")); - -// int -m.def("slice", [] -( - const Eigen::SparseMatrix& X, - const Eigen::MatrixXi& R, - const Eigen::MatrixXi& C, - Eigen::SparseMatrix& Y -) -{ - assert_is_VectorX("R",R); - assert_is_VectorX("C",C); - return igl::slice(X,R,C,Y); -}, __doc_igl_slice, -py::arg("X"), py::arg("R"), py::arg("C"), py::arg("Y")); - -m.def("slice", [] -( - const Eigen::SparseMatrix& X, - const Eigen::MatrixXi& R, - const int& dim, - Eigen::SparseMatrix& Y -) -{ - assert_is_VectorX("R",R); - return igl::slice(X,R,dim,Y); -}, __doc_igl_slice, -py::arg("X"), py::arg("R"), py::arg("dim"), py::arg("Y")); - -m.def("slice", [] -( - const Eigen::MatrixXi& X, - const Eigen::MatrixXi& R, - const Eigen::MatrixXi& C, - Eigen::MatrixXi& Y -) -{ - assert_is_VectorX("R",R); - assert_is_VectorX("C",C); - return igl::slice(X,R,C,Y); -}, __doc_igl_slice, -py::arg("X"), py::arg("R"), py::arg("C"), py::arg("Y")); - - -m.def("slice", [] -( - const Eigen::MatrixXi& X, - const Eigen::MatrixXi& R, - Eigen::MatrixXi& Y -) -{ - assert_is_VectorX("R",R); - return igl::slice(X,R,Y); -}, __doc_igl_slice, -py::arg("X"), py::arg("R"), py::arg("Y")); - -m.def("slice", [] -( - const Eigen::MatrixXi& X, - const Eigen::MatrixXi& R -) -{ - assert_is_VectorX("R",R); - return igl::slice(X,R); -}, __doc_igl_slice, -py::arg("X"), py::arg("R")); - -m.def("slice", [] -( - const Eigen::MatrixXi& X, - const Eigen::MatrixXi& R, - const int& dim -) -{ - assert_is_VectorX("R",R); - return igl::slice(X,R,dim); -}, __doc_igl_slice, -py::arg("X"), py::arg("R"), py::arg("dim")); diff --git a/python/py_igl/py_slice_into.cpp b/python/py_igl/py_slice_into.cpp deleted file mode 100644 index 57aba982f..000000000 --- a/python/py_igl/py_slice_into.cpp +++ /dev/null @@ -1,114 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("slice_into", [] -( - const Eigen::SparseMatrix& X, - const Eigen::MatrixXi& R, - const Eigen::MatrixXi& C, - Eigen::SparseMatrix& Y -) -{ - assert_is_VectorX("R",R); - assert_is_VectorX("C",C); - return igl::slice_into(X,R,C,Y); -}, __doc_igl_slice_into, -py::arg("X"), py::arg("R"), py::arg("C"), py::arg("Y")); - -m.def("slice_into", [] -( - const Eigen::MatrixXd& X, - const Eigen::MatrixXi& R, - const Eigen::MatrixXi& C, - Eigen::MatrixXd& Y -) -{ - assert_is_VectorX("R",R); - assert_is_VectorX("C",C); - return igl::slice_into(X,R,C,Y); -}, __doc_igl_slice_into, -py::arg("X"), py::arg("R"), py::arg("C"), py::arg("Y")); - -m.def("slice_into", [] -( - const Eigen::MatrixXd& X, - const Eigen::MatrixXi& R, - const int& dim, - Eigen::MatrixXd& Y -) -{ - assert_is_VectorX("R",R); - return igl::slice_into(X,R,dim,Y); -}, __doc_igl_slice_into, -py::arg("X"), py::arg("R"), py::arg("dim"), py::arg("Y")); - -m.def("slice_into", [] -( - const Eigen::MatrixXd& X, - const Eigen::MatrixXi& R, - Eigen::MatrixXd& Y -) -{ - assert_is_VectorX("R",R); - return igl::slice_into(X,R,Y); -}, __doc_igl_slice_into, -py::arg("X"), py::arg("R"), py::arg("Y")); - -// int - -m.def("slice_into", [] -( - const Eigen::SparseMatrix& X, - const Eigen::MatrixXi& R, - const Eigen::MatrixXi& C, - Eigen::SparseMatrix& Y -) -{ - assert_is_VectorX("R",R); - assert_is_VectorX("C",C); - return igl::slice_into(X,R,C,Y); -}, __doc_igl_slice_into, -py::arg("X"), py::arg("R"), py::arg("C"), py::arg("Y")); - -m.def("slice_into", [] -( - const Eigen::MatrixXi& X, - const Eigen::MatrixXi& R, - const Eigen::MatrixXi& C, - Eigen::MatrixXi& Y -) -{ - assert_is_VectorX("R",R); - assert_is_VectorX("C",C); - return igl::slice_into(X,R,C,Y); -}, __doc_igl_slice_into, -py::arg("X"), py::arg("R"), py::arg("C"), py::arg("Y")); - -m.def("slice_into", [] -( - const Eigen::MatrixXi& X, - const Eigen::MatrixXi& R, - const int& dim, - Eigen::MatrixXi& Y -) -{ - assert_is_VectorX("R",R); - return igl::slice_into(X,R,dim,Y); -}, __doc_igl_slice_into, -py::arg("X"), py::arg("R"), py::arg("dim"), py::arg("Y")); - -m.def("slice_into", [] -( - const Eigen::MatrixXi& X, - const Eigen::MatrixXi& R, - Eigen::MatrixXi& Y -) -{ - assert_is_VectorX("R",R); - return igl::slice_into(X,R,Y); -}, __doc_igl_slice_into, -py::arg("X"), py::arg("R"), py::arg("Y")); diff --git a/python/py_igl/py_slice_mask.cpp b/python/py_igl/py_slice_mask.cpp deleted file mode 100644 index 0d2d0a2a7..000000000 --- a/python/py_igl/py_slice_mask.cpp +++ /dev/null @@ -1,83 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("slice_mask", [] -( - const Eigen::MatrixXd& X, - const Eigen::Matrix & R, - const Eigen::Matrix & C, - Eigen::MatrixXd& Y -) -{ - assert_is_VectorX("R",R); - assert_is_VectorX("C",C); - return igl::slice_mask(X, R, C, Y); -}, __doc_igl_slice_mask, -py::arg("X"), py::arg("R"), py::arg("C"), py::arg("Y")); - -m.def("slice_mask", [] -( - const Eigen::MatrixXd& X, - const Eigen::Matrix & R, - const int dim, - Eigen::MatrixXd& Y -) -{ - assert_is_VectorX("R",R); - return igl::slice_mask(X, R, dim, Y); -}, __doc_igl_slice_mask, -py::arg("X"), py::arg("R"), py::arg("dim"), py::arg("Y")); - -m.def("slice_mask", [] -( - const Eigen::MatrixXi& X, - const Eigen::Matrix & R, - const Eigen::Matrix & C, - Eigen::MatrixXi& Y -) -{ - assert_is_VectorX("R",R); - assert_is_VectorX("C",C); - return igl::slice_mask(X, R, C, Y); -}, __doc_igl_slice_mask, -py::arg("X"), py::arg("R"), py::arg("C"), py::arg("Y")); - -m.def("slice_mask", [] -( - const Eigen::MatrixXi& X, - const Eigen::Matrix & R, - const int dim, - Eigen::MatrixXi& Y -) -{ - assert_is_VectorX("R",R); - return igl::slice_mask(X, R, dim, Y); -}, __doc_igl_slice_mask, -py::arg("X"), py::arg("R"), py::arg("dim"), py::arg("Y")); - -//m.def("slice_mask", [] -//( -// const Eigen::MatrixXd& X, -// Eigen::Array & R, -// Eigen::Array & C -//) -//{ -// return igl::slice_mask(X, R, C); -//}, __doc_igl_slice_mask, -//py::arg("X"), py::arg("R"), py::arg("C")); - -//m.def("slice_mask", [] -//( -// const Eigen::MatrixXd& X, -// Eigen::Array & R, -// int dim -//) -//{ -// return igl::slice_mask(X, R, dim); -//}, __doc_igl_slice_mask, -//py::arg("X"), py::arg("R"), py::arg("dim")); - diff --git a/python/py_igl/py_sortrows.cpp b/python/py_igl/py_sortrows.cpp deleted file mode 100644 index 972be6fd4..000000000 --- a/python/py_igl/py_sortrows.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("sortrows", [] -( - const Eigen::MatrixXd& X, - const bool ascending, - Eigen::MatrixXd& Y, - Eigen::MatrixXi& I -) -{ - return igl::sortrows(X,ascending,Y,I); -}, __doc_igl_sortrows, -py::arg("X"), py::arg("ascending"), py::arg("Y"), py::arg("I")); - -m.def("sortrows", [] -( - const Eigen::MatrixXi& X, - const bool ascending, - Eigen::MatrixXi& Y, - Eigen::MatrixXi& I -) -{ - return igl::sortrows(X,ascending,Y,I); -}, __doc_igl_sortrows, -py::arg("X"), py::arg("ascending"), py::arg("Y"), py::arg("I")); diff --git a/python/py_igl/py_streamlines.cpp b/python/py_igl/py_streamlines.cpp deleted file mode 100644 index ae993e2cf..000000000 --- a/python/py_igl/py_streamlines.cpp +++ /dev/null @@ -1,60 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -py::class_ StreamlineData(m, "StreamlineData"); -StreamlineData -.def(py::init<>()) -.def_readwrite("TT", &igl::StreamlineData::TT) -.def_readwrite("E", &igl::StreamlineData::E) -.def_readwrite("F2E", &igl::StreamlineData::F2E) -.def_readwrite("E2F", &igl::StreamlineData::E2F) -.def_readwrite("field", &igl::StreamlineData::field) -.def_readwrite("match_ab", &igl::StreamlineData::match_ab) -.def_readwrite("match_ba", &igl::StreamlineData::match_ba) -.def_readwrite("nsample", &igl::StreamlineData::nsample) -.def_readwrite("degree", &igl::StreamlineData::degree) -; - -py::class_ StreamlineState(m, "StreamlineState"); -StreamlineState -.def(py::init<>()) -.def_readwrite("start_point", &igl::StreamlineState::start_point) -.def_readwrite("end_point", &igl::StreamlineState::end_point) -.def_readwrite("current_face", &igl::StreamlineState::current_face) -.def_readwrite("current_direction", &igl::StreamlineState::current_direction) -.def("copy", [](const igl::StreamlineState &m) { return igl::StreamlineState(m); }) -; - -m.def("streamlines_init", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::MatrixXd& temp_field, - const bool treat_as_symmetric, - igl::StreamlineData &data, - igl::StreamlineState &state, - double percentage -) -{ - return igl::streamlines_init(V, F, temp_field, treat_as_symmetric, data, state, percentage); - -},__doc_igl_streamlines_init, -py::arg("V"), py::arg("F"), py::arg("temp_field"), py::arg("treat_as_symmetric"), -py::arg("data"), py::arg("state"), py::arg("percentage")=0.3); - -m.def("streamlines_next", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const igl::StreamlineData &data, - igl::StreamlineState &state -) -{ - return igl::streamlines_next(V, F, data, state); - -},__doc_igl_streamlines_next, -py::arg("V"), py::arg("F"), py::arg("data"), py::arg("state")); diff --git a/python/py_igl/py_triangle_triangle_adjacency.cpp b/python/py_igl/py_triangle_triangle_adjacency.cpp deleted file mode 100644 index 4ef030479..000000000 --- a/python/py_igl/py_triangle_triangle_adjacency.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - -m.def("triangle_triangle_adjacency", [] -( - const Eigen::MatrixXi& F, - Eigen::MatrixXi& TT, - Eigen::MatrixXi& TTi -) -{ - return igl::triangle_triangle_adjacency(F, TT, TTi); -}, __doc_igl_triangle_triangle_adjacency, -py::arg("F"), py::arg("TT"), py::arg("TTi")); - -m.def("triangle_triangle_adjacency", [] -( - const Eigen::MatrixXi& F, - Eigen::MatrixXi& TT -) -{ - return igl::triangle_triangle_adjacency(F, TT); -}, __doc_igl_triangle_triangle_adjacency, -py::arg("F"), py::arg("TT")); diff --git a/python/py_igl/py_unique.cpp b/python/py_igl/py_unique.cpp deleted file mode 100644 index 6db119fcd..000000000 --- a/python/py_igl/py_unique.cpp +++ /dev/null @@ -1,98 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("unique", [] -( - const Eigen::MatrixXd& A, - Eigen::MatrixXd& C, - Eigen::MatrixXi& IA, - Eigen::MatrixXi& IC -) -{ - return igl::unique(A,C,IA,IC); -}, __doc_igl_unique, -py::arg("A"), py::arg("C"), py::arg("IA"), py::arg("IC")); - -m.def("unique", [] -( - const Eigen::MatrixXd& A, - Eigen::MatrixXd& C -) -{ - return igl::unique(A,C); -}, __doc_igl_unique, -py::arg("A"), py::arg("C")); - -//m.def("unique", [] -//( -// const std::vector & A, -// std::vector & C, -// std::vector & IA, -// std::vector & IC -//) -//{ -// return igl::unique(A,C,IA,IC); -//}, __doc_igl_unique, -//py::arg("A"), py::arg("C"), py::arg("IA"), py::arg("IC")); - -//m.def("unique", [] -//( -// const std::vector & A, -// std::vector & C -//) -//{ -// return igl::unique(A,C); -//}, __doc_igl_unique, -//py::arg("A"), py::arg("C")); - - -// int - - -m.def("unique", [] -( - const Eigen::MatrixXi& A, - Eigen::MatrixXi& C, - Eigen::MatrixXi& IA, - Eigen::MatrixXi& IC -) -{ - return igl::unique(A,C,IA,IC); -}, __doc_igl_unique, -py::arg("A"), py::arg("C"), py::arg("IA"), py::arg("IC")); - -m.def("unique", [] -( - const Eigen::MatrixXi& A, - Eigen::MatrixXi& C -) -{ - return igl::unique(A,C); -}, __doc_igl_unique, -py::arg("A"), py::arg("C")); - -//m.def("unique", [] -//( -// const std::vector & A, -// std::vector & C, -// std::vector & IA, -// std::vector & IC -//) -//{ -// return igl::unique(A,C,IA,IC); -//}, __doc_igl_unique, -//py::arg("A"), py::arg("C"), py::arg("IA"), py::arg("IC")); - -//m.def("unique", [] -//( -// const std::vector & A, -// std::vector & C -//) -//{ -// return igl::unique(A,C); -//}, __doc_igl_unique, -//py::arg("A"), py::arg("C")); diff --git a/python/py_igl/py_unique_rows.cpp b/python/py_igl/py_unique_rows.cpp deleted file mode 100644 index 9ae1c0344..000000000 --- a/python/py_igl/py_unique_rows.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("unique_rows", [] -( - const Eigen::MatrixXd& A, - Eigen::MatrixXd& C, - Eigen::MatrixXi& IA, - Eigen::MatrixXi& IC -) -{ - return igl::unique_rows(A,C,IA,IC); -}, __doc_igl_unique, -py::arg("A"), py::arg("C"), py::arg("IA"), py::arg("IC")); - -m.def("unique_rows", [] -( - const Eigen::MatrixXi& A, - Eigen::MatrixXi& C, - Eigen::MatrixXi& IA, - Eigen::MatrixXi& IC -) -{ - return igl::unique_rows(A,C,IA,IC); -}, __doc_igl_unique, -py::arg("A"), py::arg("C"), py::arg("IA"), py::arg("IC")); - diff --git a/python/py_igl/py_unproject_onto_mesh.cpp b/python/py_igl/py_unproject_onto_mesh.cpp deleted file mode 100644 index 2d995928f..000000000 --- a/python/py_igl/py_unproject_onto_mesh.cpp +++ /dev/null @@ -1,64 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -// COMPLETE BINDINGS ======================== - -m.def("unproject_onto_mesh", [] -( - const Eigen::MatrixXd & pos, - const Eigen::MatrixXd & model, - const Eigen::MatrixXd & proj, - const Eigen::MatrixXd & viewport, - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::MatrixXi& fid, // TODO: Can we replace this with integer object reference? - Eigen::MatrixXd& bc -) -{ - assert_is_Vector2("pos", pos); - Eigen::Vector2f posv; - if (pos.size() != 0) - posv = Eigen::Vector2f(pos.cast()); - assert_is_Matrix4("model", model); - Eigen::Matrix4f modelm; - if (model.size() != 0) - modelm = model.cast(); - assert_is_Matrix4("proj", proj); - Eigen::Matrix4f projm; - if (proj.size() != 0) - projm = proj.cast(); - assert_is_Vector4("viewport", viewport); - Eigen::Vector4f viewportv; - if (viewport.size() != 0) - viewportv = Eigen::Vector4f(viewport.cast()); - - Eigen::VectorXd bcv; - int fidi; - bool ret = igl::unproject_onto_mesh(posv, modelm, projm, viewportv, V, F, fidi, bcv); - fid(0, 0) = fidi; - bc = bcv; - return ret; -}, __doc_igl_unproject_onto_mesh, -py::arg("pos"), py::arg("model"), py::arg("proj"), py::arg("viewport"), py::arg("V"), py::arg("F"), py::arg("fid"), py::arg("bc")); - -// INCOMPLETE BINDINGS ======================== - -//m.def("unproject_onto_mesh", [] -//( -// Eigen::Vector2f & pos, -// Eigen::Matrix4f & model, -// Eigen::Matrix4f & proj, -// Eigen::Vector4f & viewport, -// std::function & shoot_ray, -// int & fid, -// Eigen::MatrixXd& bc -//) -//{ -// return igl::unproject_onto_mesh(pos, model, proj, viewport, shoot_ray, fid, bc); -//}, __doc_igl_unproject_onto_mesh, -//py::arg("pos"), py::arg("model"), py::arg("proj"), py::arg("viewport"), py::arg("shoot_ray"), py::arg("fid"), py::arg("bc")); - diff --git a/python/py_igl/py_upsample.cpp b/python/py_igl/py_upsample.cpp deleted file mode 100644 index 6c7a934b4..000000000 --- a/python/py_igl/py_upsample.cpp +++ /dev/null @@ -1,29 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("upsample", [] -( - Eigen::MatrixXd& V, - Eigen::MatrixXi& F -) -{ - return igl::upsample(V, F); -}, __doc_igl_upsample, -py::arg("V"), py::arg("F")); - -m.def("upsample", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - Eigen::MatrixXd& NV, - Eigen::MatrixXi& NF -) -{ - return igl::upsample(V, F, NV, NF); -}, __doc_igl_upsample, -py::arg("V"), py::arg("F"), py::arg("NV"), py::arg("NF")); - diff --git a/python/py_igl/py_winding_number.cpp b/python/py_igl/py_winding_number.cpp deleted file mode 100644 index bd1c8fe43..000000000 --- a/python/py_igl/py_winding_number.cpp +++ /dev/null @@ -1,25 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -// COMPLETE BINDINGS ======================== - - -m.def("winding_number", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::MatrixXd& O, - Eigen::MatrixXd& W -) -{ - Eigen::VectorXd Wv; - igl::winding_number(V, F, O, Wv); - W = Wv; -}, __doc_igl_winding_number, -py::arg("V"), py::arg("F"), py::arg("O"), py::arg("W")); - - diff --git a/python/py_igl/py_writeMESH.cpp b/python/py_igl/py_writeMESH.cpp deleted file mode 100644 index ae52f920b..000000000 --- a/python/py_igl/py_writeMESH.cpp +++ /dev/null @@ -1,31 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("writeMESH", [] -( - const std::string mesh_file_name, - const std::vector > & V, - const std::vector > & T, - const std::vector > & F -) -{ - return igl::writeMESH(mesh_file_name, V, T, F); -}, __doc_igl_writeMESH, -py::arg("mesh_file_name"), py::arg("V"), py::arg("T"), py::arg("F")); - -m.def("writeMESH", [] -( - const std::string str, - const Eigen::MatrixXd& V, - const Eigen::MatrixXd& T, - const Eigen::MatrixXi& F -) -{ - return igl::writeMESH(str, V, T, F); -}, __doc_igl_writeMESH, -py::arg("str"), py::arg("V"), py::arg("T"), py::arg("F")); - diff --git a/python/py_igl/py_writeOBJ.cpp b/python/py_igl/py_writeOBJ.cpp deleted file mode 100644 index 3545aa23e..000000000 --- a/python/py_igl/py_writeOBJ.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("writeOBJ", [] -( - const std::string str, - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::MatrixXd& CN, - const Eigen::MatrixXi& FN, - const Eigen::MatrixXd& TC, - const Eigen::MatrixXi& FTC -) -{ - return igl::writeOBJ(str,V,F,CN,FN,TC,FTC); -}, __doc_igl_writeOBJ, -py::arg("str"), py::arg("V"), py::arg("F"), py::arg("CN"), py::arg("FN"), py::arg("TC"), py::arg("FTC")); - -m.def("writeOBJ", [] -( - const std::string str, - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F -) -{ - return igl::writeOBJ(str,V,F); -}, __doc_igl_writeOBJ, -py::arg("str"), py::arg("V"), py::arg("F")); diff --git a/python/py_igl/py_writePLY.cpp b/python/py_igl/py_writePLY.cpp deleted file mode 100644 index c450aad56..000000000 --- a/python/py_igl/py_writePLY.cpp +++ /dev/null @@ -1,30 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -m.def("writePLY", [] -( - const std::string str, - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F, - const Eigen::MatrixXd& N, - const Eigen::MatrixXd& UV -) -{ - return igl::writePLY(str,V,F,N,UV); -}, __doc_igl_writePLY, -py::arg("str"), py::arg("V"), py::arg("F"), py::arg("N"), py::arg("UV")); - -m.def("writePLY", [] -( - const std::string str, - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& F -) -{ - return igl::writePLY(str,V,F); -}, __doc_igl_writePLY, -py::arg("str"), py::arg("V"), py::arg("F")); diff --git a/python/py_igl/triangle/py_triangulate.cpp b/python/py_igl/triangle/py_triangulate.cpp deleted file mode 100644 index b0dc621d4..000000000 --- a/python/py_igl/triangle/py_triangulate.cpp +++ /dev/null @@ -1,23 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. - - -m.def("triangulate", [] -( - const Eigen::MatrixXd& V, - const Eigen::MatrixXi& E, - const Eigen::MatrixXd& H, - const std::string flags, - Eigen::MatrixXd& V2, - Eigen::MatrixXi& F2 -) -{ - return igl::triangle::triangulate(V, E, H, flags, V2, F2); -}, __doc_igl_triangle_triangulate, -py::arg("V"), py::arg("E"), py::arg("H"), py::arg("flags"), py::arg("V2"), py::arg("F2")); - diff --git a/python/python_shared.cpp b/python/python_shared.cpp deleted file mode 100644 index 429b7b1c3..000000000 --- a/python/python_shared.cpp +++ /dev/null @@ -1,203 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -#include "python_shared.h" -#include -#include -#include - -extern void python_export_vector(py::module &); -extern void python_export_igl(py::module &); - -#ifdef PY_GLFW -extern void python_export_igl_glfw(py::module &); -#endif - -#ifdef PY_COMISO -extern void python_export_igl_comiso(py::module &); -#endif - -#ifdef PY_TETGEN -extern void python_export_igl_tetgen(py::module &); -#endif - -#ifdef PY_EMBREE -extern void python_export_igl_embree(py::module &); -#endif - -#ifdef PY_TRIANGLE -extern void python_export_igl_triangle(py::module &); -#endif - -#ifdef PY_CGAL -extern void python_export_igl_cgal(py::module &); -#endif - -#ifdef PY_COPYLEFT -extern void python_export_igl_copyleft(py::module &); -#endif - -#ifdef PY_PNG -extern void python_export_igl_png(py::module &); -#endif - -PYBIND11_PLUGIN(pyigl) { - py::module m("pyigl", R"pyigldoc( - Python wrappers for libigl - -------------------------- - - .. currentmodule:: pyigl - - .. autosummary:: - :toctree: _generate - - AABB - ARAPEnergyType - MeshBooleanType - SolverStatus - active_set - adjacency_list - arap - avg_edge_length - barycenter - barycentric_coordinates - barycentric_to_global - bbw - boundary_conditions - boundary_facets - boundary_loop - cat - collapse_edge - colon - column_to_quats - comb_cross_field - comb_frame_field - compute_frame_field_bisectors - copyleft_cgal_RemeshSelfIntersectionsParam - copyleft_cgal_mesh_boolean - copyleft_cgal_remesh_self_intersections - copyleft_comiso_miq - copyleft_comiso_nrosy - copyleft_marching_cubes - copyleft_swept_volume - copyleft_tetgen_tetrahedralize - cotmatrix - covariance_scatter_matrix - cross_field_mismatch - cut_mesh_from_singularities - deform_skeleton - directed_edge_orientations - directed_edge_parents - doublearea - dqs - edge_lengths - edge_topology - eigs - embree_ambient_occlusion - embree_line_mesh_intersection - embree_reorient_facets_raycast - find_cross_field_singularities - fit_rotations - floor - forward_kinematics - gaussian_curvature - get_seconds - grad - harmonic - hsv_to_rgb - internal_angles - invert_diag - is_irregular_vertex - jet - lbs_matrix - local_basis - lscm - map_vertices_to_circle - massmatrix - min_quad_with_fixed - normalize_row_lengths - normalize_row_sums - parula - per_corner_normals - per_edge_normals - per_face_normals - per_vertex_normals - planarize_quad_mesh - png_readPNG - png_writePNG - point_mesh_squared_distance - polar_svd - principal_curvature - quad_planarity - randperm - readDMAT - readMESH - readOBJ - readOFF - readTGF - read_triangle_mesh - remove_duplicate_vertices - rotate_vectors - setdiff - signed_distance - slice - slice_into - slice_mask - marching_tets - sortrows - streamlines - triangle_triangle_adjacency - triangle_triangulate - unique - unproject_onto_mesh - upsample - winding_number - writeMESH - writeOBJ - writePLY - readPLY - - )pyigldoc"); - - python_export_vector(m); - python_export_igl(m); - - - #ifdef PY_GLFW - python_export_igl_glfw(m); - #endif - - #ifdef PY_COMISO - python_export_igl_comiso(m); - #endif - - #ifdef PY_TETGEN - python_export_igl_tetgen(m); - #endif - - #ifdef PY_EMBREE - python_export_igl_embree(m); - #endif - - #ifdef PY_TRIANGLE - python_export_igl_triangle(m); - #endif - - #ifdef PY_CGAL - python_export_igl_cgal(m); - #endif - - #ifdef PY_COPYLEFT - python_export_igl_copyleft(m); - #endif - - #ifdef PY_PNG - python_export_igl_png(m); - #endif - - return m.ptr(); -} diff --git a/python/python_shared.h b/python/python_shared.h deleted file mode 100644 index 5017634b3..000000000 --- a/python/python_shared.h +++ /dev/null @@ -1,113 +0,0 @@ -// This file is part of libigl, a simple c++ geometry processing library. -// -// Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -// -// This Source Code Form is subject to the terms of the Mozilla Public License -// v. 2.0. If a copy of the MPL was not distributed with this file, You can -// obtain one at http://mozilla.org/MPL/2.0/. -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include "py_doc.h" -#include "modules/py_typedefs.h" - - -template -void assert_is_VectorX(const std::string name, const Eigen::PlainObjectBase& v) -{ - if (v.size() == 0) - return; - - if (v.cols() != 1) - throw std::runtime_error(name + " must be a column vector."); -} - -template -void assert_is_RowVectorX(const std::string name, const Eigen::PlainObjectBase& v) -{ - if (v.size() == 0) - return; - - if (v.rows() != 1) - throw std::runtime_error(name + " must be a row vector."); -} - -template -void assert_is_Vector2(const std::string name, const Eigen::PlainObjectBase& v) -{ - if (v.size() == 0) - return; - - if ((v.cols() != 1) || (v.rows() != 2)) - throw std::runtime_error(name + " must be a column vector with 2 entries."); -} - -template -void assert_is_RowVector2(const std::string name, const Eigen::PlainObjectBase& v) -{ - if (v.size() == 0) - return; - - if ((v.cols() != 2) || (v.rows() != 1)) - throw std::runtime_error(name + " must be a row vector with 2 entries."); -} - -template -void assert_is_Vector3(const std::string name, const Eigen::PlainObjectBase& v) -{ - if (v.size() == 0) - return; - - if ((v.cols() != 1) || (v.rows() != 3)) - throw std::runtime_error(name + " must be a column vector with 3 entries."); -} - -template -void assert_is_RowVector3(const std::string name, const Eigen::PlainObjectBase& v) -{ - if (v.size() == 0) - return; - - if ((v.cols() != 3) || (v.rows() != 1)) - throw std::runtime_error(name + " must be a row vector with 3 entries."); -} - -template -void assert_is_Vector4(const std::string name, const Eigen::PlainObjectBase& v) -{ - if (v.size() == 0) - return; - - if ((v.cols() != 1) || (v.rows() != 4)) - throw std::runtime_error(name + " must be a column vector with 4 entries."); -} - -template -void assert_is_RowVector4(const std::string name, const Eigen::PlainObjectBase& v) -{ - if (v.size() == 0) - return; - - if ((v.cols() != 4) || (v.rows() != 1)) - throw std::runtime_error(name + " must be a row vector with 4 entries."); -} - -template -void assert_is_Matrix4(const std::string name, const Eigen::PlainObjectBase& v) -{ - if (v.size() == 0) - return; - - if ((v.cols() != 4) || (v.rows() != 4)) - throw std::runtime_error(name + " must be a 4x4 matrix."); -} - - - -namespace py = pybind11; diff --git a/python/scripts/basic_function.mako b/python/scripts/basic_function.mako deleted file mode 100644 index 2267759f3..000000000 --- a/python/scripts/basic_function.mako +++ /dev/null @@ -1,46 +0,0 @@ -% for enum in enums: -py::enum_<\ -% for n in enum['namespaces']: -${n}::\ -% endfor -${enum['name']}>(m, "${enum['name']}") -% for c in enum['constants']: - .value("${c}", \ -% for n in enum['namespaces']: -${n}::\ -% endfor -${c}) -% endfor - .export_values(); -% endfor - - -% for func in functions: -m.def("${func['name']}", [] -( - % for p in func['parameters'][:-1]: - ${p['type']} ${p['name']}, - % endfor - ${func['parameters'][-1]['type']} ${func['parameters'][-1]['name']} -) -{ - return \ -% for n in func['namespaces']: -${n}::\ -% endfor -${func['name']}(\ -% for p in func['parameters'][:-1]: -${p['name']}, \ -% endfor -${func['parameters'][-1]['name']}); -}, __doc_\ -% for n in func['namespaces']: -${n}_\ -% endfor -${func['name']}, -% for p in func['parameters'][:-1]: -py::arg("${p['name']}"), \ -% endfor -py::arg("${func['parameters'][-1]['name']}")); - -% endfor diff --git a/python/scripts/generate_bindings.py b/python/scripts/generate_bindings.py deleted file mode 100755 index 69a1e5b92..000000000 --- a/python/scripts/generate_bindings.py +++ /dev/null @@ -1,311 +0,0 @@ -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -#!/usr/bin/env python3 -# -# Syntax: generate_docstrings.py -# -# Extract documentation from C++ header files to use it in libiglPython bindings -# - -import os, sys, glob -import pickle - -import shutil -from joblib import Parallel, delayed -from multiprocessing import cpu_count -from mako.template import Template -from parser import parse - - -# http://stackoverflow.com/questions/3207219/how-to-list-all-files-of-a-directory-in-python -def get_filepaths(directory): - """ - This function will generate the file names in a directory - tree by walking the tree either top-down or bottom-up. For each - directory in the tree rooted at directory top (including top itself), - it yields a 3-tuple (dirpath, dirnames, filenames). - """ - file_paths = [] # List which will store all of the full filepaths. - - # Walk the tree. - for root, directories, files in os.walk(directory): - for filename in files: - # Join the two strings in order to form the full filepath. - filepath = os.path.join(root, filename) - file_paths.append(filepath) # Add it to the list. - - return file_paths # Self-explanatory. - - -def get_name_from_path(path, basepath, prefix, postfix): - f_clean = path[len(basepath):] - f_clean = f_clean.replace(basepath, "") - f_clean = f_clean.replace(postfix, "") - f_clean = f_clean.replace(prefix, "") - f_clean = f_clean.replace("/", "_") - f_clean = f_clean.replace("\\", "_") - f_clean = f_clean.replace(" ", "_") - f_clean = f_clean.replace(".", "_") - return f_clean - - -def map_parameter_types(name, cpp_type, parsed_types, errors, enum_types): - # TODO Replace with proper regex matching and derive types from templates, comment parsing, names in cpp files - # CAUTION: This is work in progress mapping code to get a grip of the problem - # Types to map - # const int dim -> const int& dim ? - result = [] - - if cpp_type.startswith("const"): - result.append("const ") - cpp_type = cpp_type[6:] # Strip const part - - # Handle special types - skip_parsing = False - if cpp_type.startswith("MatY"): - result.append("Eigen::SparseMatrix&") - skip_parsing = True - if cpp_type.startswith("Eigen::Matrix"): - result.append("Eigen::Matrix") - skip_parsing = True - if cpp_type == "std::vector > &": - result.append("std::vector > &") - skip_parsing = True - if cpp_type == "std::vector > &": - result.append("std::vector > &") - skip_parsing = True - for constant in enum_types: - if cpp_type.endswith(constant): - result.append(cpp_type) - skip_parsing = True - - if len(parsed_types) == 0: - errors.append("Empty typechain: %s" % cpp_type) - if cpp_type == "int" or cpp_type == "bool" or cpp_type == "unsigned int": - return cpp_type, True - else: - return cpp_type, False - - # print(parsed_types, cpp_type) - if not skip_parsing: - for i, t in enumerate(parsed_types): - - if t == "Eigen": - result.append("Eigen::") - continue - if t == "std": - result.append("std::") - continue - - if t == "PlainObjectBase" or t == "MatrixBase": - if name == "F": - result.append("MatrixXi&") - elif name == "V": - result.append("MatrixXd&") - else: - result.append("MatrixXd&") - break - if t == "MatrixXi" or t == "VectorXi": - result.append("MatrixXi&") - break - if t == "MatrixXd" or t == "VectorXd": - result.append("MatrixXd&") - break - if t == "SparseMatrix" and len(parsed_types) >= i + 2 and ( - parsed_types[i + 1] == "Scalar" or parsed_types[i + 1] == "T"): - result.append("SparseMatrix&") - break - if t == "SparseVector" and len(parsed_types) >= i + 2 and (parsed_types[i + 1] == "Scalar" or parsed_types[ - i + 1] == "T"): - result.append("SparseMatrix&") - break - - if t == "bool" or t == "int" or t == "double" or t == "unsigned" or t == "string": - if cpp_type.endswith("&"): - result.append(t + " &") - else: - result.append(t) - break - - else: - errors.append("Unknown typechain: %s" % cpp_type) - return cpp_type, False - - - return "".join(result), True - - -if __name__ == '__main__': - - if len(sys.argv) != 2: - print('Syntax: %s ' % sys.argv[0]) - exit(-1) - - errors = {"missing": [], "empty": [], "others": [], "incorrect": [], "render": [], "various": []} - files = {"complete": [], "partial": [], "errors": [], "others": [], "empty": []} - - # List all files in the given folder and subfolders - cpp_base_path = sys.argv[1] - cpp_file_paths = get_filepaths(cpp_base_path) - - # Add all the .h filepaths to a dict - print("Collecting cpp files for parsing...") - mapping = {} - cppmapping = {} - for f in cpp_file_paths: - if f.endswith(".h"): - name = get_name_from_path(f, cpp_base_path, "", ".h") - mapping[name] = f - - if f.endswith(".cpp"): - name = get_name_from_path(f, cpp_base_path, "", ".cpp") - cppmapping[name] = f - - # Add all python binding files to a list - implemented_names = list(mapping.keys()) # ["point_mesh_squared_distance"] - implemented_names.sort() - single_postfix = "" - single_prefix = "" - - # Create a list of all cpp header files - files_to_parse = [] - cppfiles_to_parse = [] - for n in implemented_names: - files_to_parse.append(mapping[n]) - - if n not in cppmapping: - errors["missing"].append("No cpp source file for function %s found." % n) - else: - cppfiles_to_parse.append(cppmapping[n]) - - # Parse c++ header files - print("Parsing header files...") - load_headers = False - if load_headers: - with open("headers.dat", 'rb') as fs: - dicts = pickle.load(fs) - else: - job_count = cpu_count() - dicts = Parallel(n_jobs=job_count)(delayed(parse)(path) for path in files_to_parse) - - if not load_headers: - print("Saving parsed header files...") - with open("headers.dat", 'wb') as fs: - pickle.dump(dicts, fs) - - # Not yet needed, as explicit template parsing does not seem to be supported in clang - # Parse c++ source files - # cppdicts = Parallel(n_jobs=job_count)(delayed(parse)(path) for path in cppfiles_to_parse) - - # Change directory to become independent of execution directory - print("Generating directory tree for binding files...") - path = os.path.dirname(__file__) - if path != "": - os.chdir(path) - try: - shutil.rmtree("generated") - except: - pass # Ignore missing generated directory - os.makedirs("generated/complete") - os.mkdir("generated/partial") - - print("Generating and writing binding files...") - for idx, n in enumerate(implemented_names): - d = dicts[idx] - contained_elements = sum(map(lambda x: len(x), d.values())) - - # Skip files that don't contain functions/enums/classes - if contained_elements == 0: - errors["empty"].append("Function %s contains no parseable content in cpp header. Something might be wrong." % n) - files["empty"].append(n) - continue - - # Add functions with classes to others - if len(d["classes"]) != 0 or len(d["structs"]) != 0: - errors["others"].append("Function %s contains classes/structs in cpp header. Skipping" % n) - files["others"].append(n) - continue - - # Work on files that contain only functions/enums and namespaces - if len(d["functions"]) + len(d["namespaces"]) + len(d["enums"]) == contained_elements: - correct_functions = [] - incorrect_functions = [] - - # Collect enums to generate binding files - enums = [] - enum_types = [] - for e in d["enums"]: - enums.append({"name": e.name, "namespaces": d["namespaces"], "constants": e.constants}) - enum_types.append(e.name) - - # Collect functions to generate binding files - for f in d["functions"]: - parameters = [] - correct_function = True - f_errors = [] - for p in f.parameters: - typ, correct = map_parameter_types(p[0], p[1], p[2], f_errors, enum_types) - correct_function &= correct - parameters.append({"name": p[0], "type": typ}) - - if correct_function and len(parameters) > 0: #TODO add constants like EPS - correct_functions.append({"parameters": parameters, "namespaces": d["namespaces"], "name": f.name}) - elif len(parameters) > 0: - incorrect_functions.append({"parameters": parameters, "namespaces": d["namespaces"], "name": f.name}) - errors["incorrect"].append("Incorrect function in %s: %s, %s\n" % (n, f.name, ",".join(f_errors))) - else: - errors["various"].append("Function without pars in %s: %s, %s\n" % (n, f.name, "," - "".join(f_errors))) - - # Write binding files - try: - tpl = Template(filename='basic_function.mako') - rendered = tpl.render(functions=correct_functions, enums=enums) - tpl1 = Template(filename='basic_function.mako') - rendered1 = tpl.render(functions=incorrect_functions, enums=enums) - path = "generated/" - if len(incorrect_functions) == 0 and (len(correct_functions) != 0 or len(enums) != 0): - path += "complete/" - with open(path + single_prefix + "py_" + n + ".cpp", 'w') as fs: - fs.write(rendered) - files["complete"].append(n) - else: - path += "partial/" - with open(path + single_prefix + "py_" + n + ".cpp", 'w') as fs: - fs.write("// COMPLETE BINDINGS ========================\n") - fs.write(rendered) - fs.write("\n\n\n\n// INCOMPLETE BINDINGS ========================\n") - fs.write(rendered1) - - if len(correct_functions) != 0: - files["partial"].append(n) - else: - files["errors"].append(n) - - except Exception as e: - files["errors"].append(n) - errors["render"].append("Template rendering failed:" + n + " " + str(correct_functions) + ", incorrect " - "functions are " + str( - incorrect_functions) + str(e) + "\n") - - print("Writing error and overview files...") - with open("errors.txt" + single_postfix, 'w') as fs: - l = list(errors.keys()) - l.sort() - for k in l: - fs.write("%s: %i \n" %(k, len(errors[k]))) - fs.writelines("\n".join(errors[k])) - fs.write("\n\n\n") - - with open("files.txt" + single_postfix, 'w') as fs: - l = list(files.keys()) - l.sort() - for k in l: - fs.write("%s: %i \n" %(k, len(files[k]))) - fs.writelines("\n".join(files[k])) - fs.write("\n\n\n") diff --git a/python/scripts/generate_docstrings.py b/python/scripts/generate_docstrings.py deleted file mode 100755 index e80a80e59..000000000 --- a/python/scripts/generate_docstrings.py +++ /dev/null @@ -1,148 +0,0 @@ -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -#!/usr/bin/env python -# -# Syntax: generate_docstrings.py -# -# Extract documentation from C++ header files to use it in libiglPython bindings -# - -import os, sys, glob -from joblib import Parallel, delayed -from multiprocessing import cpu_count -from mako.template import Template -from parser import parse - - -# http://stackoverflow.com/questions/3207219/how-to-list-all-files-of-a-directory-in-python -def get_filepaths(directory): - """ - This function will generate the file names in a directory - tree by walking the tree either top-down or bottom-up. For each - directory in the tree rooted at directory top (including top itself), - it yields a 3-tuple (dirpath, dirnames, filenames). - """ - file_paths = [] # List which will store all of the full filepaths. - root_file_paths = [] - - # Walk the tree. - for root, directories, files in os.walk(directory): - for filename in files: - # Join the two strings in order to form the full filepath. - filepath = os.path.join(root, filename) - file_paths.append(filepath) # Add it to the list. - - if root.endswith(directory): # Add only the files in the root directory - root_file_paths.append(filepath) - - return file_paths, root_file_paths # file_paths contains all file paths, core_file_paths only the ones in - - -def get_name_from_path(path, basepath, prefix, postfix): - f_clean = os.path.relpath(path, basepath) - f_clean = f_clean.replace(postfix, "") - f_clean = f_clean.replace(prefix, "") - f_clean = f_clean.replace("/", "_") - f_clean = f_clean.replace("\\", "_") - f_clean = f_clean.replace(" ", "_") - f_clean = f_clean.replace(".", "_") - return f_clean - - -if __name__ == '__main__': - - if len(sys.argv) != 3: - print('Syntax: %s generate_docstrings.py ' % sys.argv[0]) - exit(-1) - - # List all files in the given folder and subfolders - cpp_base_path = sys.argv[1] - py_base_path = sys.argv[2] - cpp_file_paths, cpp_root_file_paths = get_filepaths(cpp_base_path) - py_file_paths, py_root_file_paths = get_filepaths(py_base_path) - - # Add all the .h filepaths to a dict - mapping = {} - for f in cpp_file_paths: - if f.endswith(".h"): - name = get_name_from_path(f, cpp_base_path, "", ".h") - mapping[name] = f - - # Add all python binding files to a list - implemented_names = [] - core_implemented_names = [] - for f in py_file_paths: - if f.endswith(".cpp"): - name = get_name_from_path(f, py_base_path, "py_", ".cpp") - implemented_names.append(name) - if f in py_root_file_paths: - core_implemented_names.append(name) - - implemented_names.sort() - core_implemented_names.sort() - - # Create a list of cpp header files for which a python binding file exists - files_to_parse = [] - for n in implemented_names: - if n not in mapping: - print("No cpp header file for python function %s found." % n) - continue - files_to_parse.append(mapping[n]) - # print(mapping[n]) - - # Parse c++ header files - job_count = cpu_count() - dicts = Parallel(n_jobs=job_count)(delayed(parse)(path) for path in files_to_parse) - - hpplines = [] - cpplines = [] - - for idx, n in enumerate(implemented_names): - d = dicts[idx] - contained_elements = sum(map(lambda x: len(x), d.values())) - # Check for files that don't contain functions/enums/classes - if contained_elements == 0: - print("Function %s contains no parseable content in cpp header. Something might be wrong." % n) - continue - else: - names = [] - namespaces = "_".join(d["namespaces"]) # Assumption that all entities lie in deepest namespace - for f in d["functions"]: - h_string = "extern const char *__doc_" + namespaces + "_" + f.name + ";\n" - docu_string = "See " + f.name + " for the documentation." - if f.documentation: - docu_string = f.documentation - cpp_string = "const char *__doc_" + namespaces + "_" + f.name + " = R\"igl_Qu8mg5v7(" + docu_string + ")igl_Qu8mg5v7\";\n" - - if f.name not in names: # Prevent multiple additions of declarations, TODO: Possible fix is to merge comments and add them to all functions - hpplines.append(h_string) - cpplines.append(cpp_string) - names.append(f.name) - - # Change directory to become independent of execution directory - path = os.path.dirname(__file__) - if path != "": - os.chdir(path) - - # Update the two files py_doc.h and py_doc.cpp - with open('../py_doc.h', 'w') as fh: - fh.writelines(hpplines) - with open('../py_doc.cpp', 'w') as fc: - fc.writelines(cpplines) - - # Write python_shared_cpp file - tpl = Template(filename='python_shared.mako') - rendered = tpl.render(functions=implemented_names) - with open("../python_shared.cpp", 'w') as fs: - fs.write(rendered) - - # Write py_igl_cpp file with all core library files - tpl = Template(filename='py_igl.mako') - rendered = tpl.render(functions=core_implemented_names) - with open("../py_igl.cpp", 'w') as fs: - fs.write(rendered) diff --git a/python/scripts/parser.py b/python/scripts/parser.py deleted file mode 100644 index 48648b52b..000000000 --- a/python/scripts/parser.py +++ /dev/null @@ -1,141 +0,0 @@ -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys -import os -from threading import Thread - -import clang.cindex -import ccsyspath -import itertools -from mako.template import Template - - - - - - - -def get_annotations(node): - return [c.displayname for c in node.get_children() - if c.kind == clang.cindex.CursorKind.ANNOTATE_ATTR] - - -class Function(object): - def __init__(self, cursor): - self.name = cursor.spelling - self.annotations = get_annotations(cursor) - self.access = cursor.access_specifier -# template_pars = [c.extent for c in cursor.get_children() if c.kind == clang.cindex.CursorKind.TEMPLATE_TYPE_PARAMETER] - parameter_dec = [c for c in cursor.get_children() if c.kind == clang.cindex.CursorKind.PARM_DECL] - - parameters = [] - for p in parameter_dec: - children = [] - for c in p.get_children(): -# print(c.spelling) - children.append(c.spelling) - parameters.append((p.spelling, p.type.spelling, children)) - - self.parameters = parameters - self.documentation = cursor.raw_comment - - -class Enum(object): - def __init__(self, cursor): - self.name = cursor.spelling - self.constants = [c.spelling for c in cursor.get_children() if c.kind == - clang.cindex.CursorKind.ENUM_CONSTANT_DECL] - self.documentation = cursor.raw_comment - -class Class(object): - def __init__(self, cursor): - self.name = cursor.spelling -# self.functions = [] - self.annotations = get_annotations(cursor) - -# for c in cursor.get_children(): -# if (c.kind == clang.cindex.CursorKind.CXX_METHOD and -# c.access_specifier == clang.cindex.AccessSpecifier.PUBLIC): -# f = Function(c) -# self.functions.append(f) - - - -def traverse(c, path, objects): - if c.location.file and not c.location.file.name.endswith(path): - return - - if c.spelling == "PARULA_COLOR_MAP": # Fix to prevent python stack overflow from infinite recursion - return - -# print(c.kind, c.spelling) - - - if c.kind == clang.cindex.CursorKind.TRANSLATION_UNIT or c.kind == clang.cindex.CursorKind.UNEXPOSED_DECL: - # Ignore other cursor kinds - pass - - elif c.kind == clang.cindex.CursorKind.NAMESPACE: - objects["namespaces"].append(c.spelling) - # print("Namespace", c.spelling, c.get_children()) - pass - - elif c.kind == clang.cindex.CursorKind.FUNCTION_TEMPLATE: -# print("Function Template", c.spelling, c.raw_comment) - objects["functions"].append(Function(c)) - return - - elif c.kind == clang.cindex.CursorKind.FUNCTION_DECL: - # print("FUNCTION_DECL", c.spelling, c.raw_comment) - objects["functions"].append(Function(c)) - return - - elif c.kind == clang.cindex.CursorKind.ENUM_DECL: - # print("ENUM_DECL", c.spelling, c.raw_comment) - objects["enums"].append(Enum(c)) - return - - elif c.kind == clang.cindex.CursorKind.CLASS_DECL: - objects["classes"].append(Class(c)) - return - - elif c.kind == clang.cindex.CursorKind.CLASS_TEMPLATE: - objects["classes"].append(Class(c)) - return - - elif c.kind == clang.cindex.CursorKind.STRUCT_DECL: - objects["structs"].append(Class(c)) - return - - else: - # print("Unknown", c.kind, c.spelling) - pass - - for child_node in c.get_children(): - traverse(child_node, path, objects) - - -def parse(path): - index = clang.cindex.Index.create() - # Clang can't parse files with missing definitions, add static library definition or not? - args = ['-x', 'c++', '-std=c++11', '-fparse-all-comments', '-DIGL_STATIC_LIBRARY'] - args.append('-I/usr/include/eigen3/') # TODO Properly add all needed includes - syspath = ccsyspath.system_include_paths('clang++') # Add the system libraries - incargs = [(b'-I' + inc).decode("utf-8") for inc in syspath] - args.extend(incargs) - - tu = index.parse(path, args) - objects = {"functions": [], "enums": [], "namespaces": [], "classes": [], "structs": []} - traverse(tu.cursor, path, objects) - return objects - -if __name__ == '__main__': - if len(sys.argv) != 2: - print("Usage: python3 parser.py ") - exit(-1) - parse(sys.argv[1]) diff --git a/python/scripts/py_igl.mako b/python/scripts/py_igl.mako deleted file mode 100644 index 0d5d309ec..000000000 --- a/python/scripts/py_igl.mako +++ /dev/null @@ -1,19 +0,0 @@ -#include - -#include "python_shared.h" -#include "modules/py_typedefs.h" - -% for f in functions: -#include -% endfor - - -void python_export_igl(py::module &m) -{ -#include "modules/py_typedefs.cpp" - -% for f in functions: -#include "py_igl/py_${f}.cpp" -% endfor - -} diff --git a/python/scripts/python_shared.mako b/python/scripts/python_shared.mako deleted file mode 100644 index 46cf1fd72..000000000 --- a/python/scripts/python_shared.mako +++ /dev/null @@ -1,94 +0,0 @@ -#include "python_shared.h" -#include -#include -#include - -extern void python_export_vector(py::module &); -extern void python_export_igl(py::module &); - -#ifdef PY_VIEWER -extern void python_export_igl_viewer(py::module &); -#endif - -#ifdef PY_COMISO -extern void python_export_igl_comiso(py::module &); -#endif - -#ifdef PY_TETGEN -extern void python_export_igl_tetgen(py::module &); -#endif - -#ifdef PY_EMBREE -extern void python_export_igl_embree(py::module &); -#endif - -#ifdef PY_TRIANGLE -extern void python_export_igl_triangle(py::module &); -#endif - -#ifdef PY_CGAL -extern void python_export_igl_cgal(py::module &); -#endif - -#ifdef PY_COPYLEFT -extern void python_export_igl_copyleft(py::module &); -#endif - -#ifdef PY_PNG -extern void python_export_igl_png(py::module &); -#endif - -PYBIND11_PLUGIN(pyigl) { - py::module m("pyigl", R"pyigldoc( - Python wrappers for libigl - -------------------------- - - .. currentmodule:: pyigl - - .. autosummary:: - :toctree: _generate - - % for f in functions: - ${f} - % endfor - - )pyigldoc"); - - python_export_vector(m); - python_export_igl(m); - - - #ifdef PY_VIEWER - python_export_igl_viewer(m); - #endif - - #ifdef PY_COMISO - python_export_igl_comiso(m); - #endif - - #ifdef PY_TETGEN - python_export_igl_tetgen(m); - #endif - - #ifdef PY_EMBREE - python_export_igl_embree(m); - #endif - - #ifdef PY_TRIANGLE - python_export_igl_triangle(m); - #endif - - #ifdef PY_CGAL - python_export_igl_cgal(m); - #endif - - #ifdef PY_COPYLEFT - python_export_igl_copyleft(m); - #endif - - #ifdef PY_PNG - python_export_igl_png(m); - #endif - - return m.ptr(); -} diff --git a/python/setup.py b/python/setup.py deleted file mode 100644 index 21ef19d4c..000000000 --- a/python/setup.py +++ /dev/null @@ -1,90 +0,0 @@ -import os -import re -import sys -import platform -import subprocess - -from setuptools import setup, Extension -from setuptools.command.build_ext import build_ext -from distutils.version import LooseVersion -from distutils.sysconfig import get_config_var -from distutils.sysconfig import get_python_inc - -CMAKE_ADDITIONAL_OPT = [] -if '--' in sys.argv: - i = sys.argv.index('--') - CMAKE_ADDITIONAL_OPT = sys.argv[i+1:] - sys.argv = sys.argv[:i] - -class CMakeExtension(Extension): - - def __init__(self, name, sourcedir=''): - Extension.__init__(self, name, sources=[]) - self.sourcedir = os.path.abspath(sourcedir) - - -class CMakeBuild(build_ext): - - def run(self): - try: - out = subprocess.check_output(['cmake', '--version']) - except OSError: - raise RuntimeError("CMake must be installed to build the following extensions: " + - ", ".join(e.name for e in self.extensions)) - - if platform.system() == "Windows": - cmake_version = LooseVersion( - re.search(r'version\s*([\d.]+)', out.decode()).group(1)) - if cmake_version < '3.1.0': - raise RuntimeError("CMake >= 3.1.0 is required on Windows") - - for ext in self.extensions: - self.build_extension(ext) - - def build_extension(self, ext): - extdir = os.path.abspath(os.path.dirname( - self.get_ext_fullpath(ext.name))) - - python_library = str(get_config_var('LIBDIR')) - python_include_directory = str(get_python_inc()) - - cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir, - '-DPYTHON_EXECUTABLE=' + sys.executable, - '-DPYTHON_INCLUDE_DIR=' + python_include_directory, ] - - cfg = 'Debug' if self.debug else 'Release' - build_args = ['--config', cfg] - - if platform.system() == "Windows": - cmake_args += [ - '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(cfg.upper(), extdir)] - if sys.maxsize > 2**32: - cmake_args += ['-A', 'x64'] - build_args += ['--', '/m'] - else: - cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg] - build_args += ['--', '-j2'] - cmake_args += CMAKE_ADDITIONAL_OPT - - env = os.environ.copy() - env['CXXFLAGS'] = '{} -DVERSION_INFO=\\"{}\\"'.format(env.get('CXXFLAGS', ''), - self.distribution.get_version()) - if not os.path.exists(self.build_temp): - os.makedirs(self.build_temp) - - subprocess.check_call(['cmake', ext.sourcedir] + - cmake_args, cwd=self.build_temp, env=env) - subprocess.check_call(['cmake', '--build', '.'] + - build_args, cwd=self.build_temp) - -setup( - name='pyigl', - version='0.0.1', - author='Geometric Computing Lab @ NYU', - author_email='info@geometriccomputing.org', - description='', - long_description='', - ext_modules=[CMakeExtension('pyigl')], - cmdclass=dict(build_ext=CMakeBuild), - zip_safe=False, -) diff --git a/python/tcpviewer.py b/python/tcpviewer.py deleted file mode 100644 index f7cf984f0..000000000 --- a/python/tcpviewer.py +++ /dev/null @@ -1,88 +0,0 @@ -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import socket -import threading -import pyigl as igl -import array -import time - -HOST = 'localhost' # Symbolic name meaning all available interfaces -PORT = 50008 # Arbitrary non-privileged port - -def worker(viewer,lock,s): - - print("TCP iglviewer server listening on port " + str(PORT)) - try: - while True: - conn, addr = s.accept() - lock.acquire() - slist = [] - while True: - buf = conn.recv(4096) - if not buf: - break - slist.append(buf.decode('unicode_internal','ignore')) - conn.close() - - data = ''.join(slist) - temp = list(data) - - isempty = viewer.data().V.rows() == 0 - viewer.data().deserialize(temp) - if isempty and viewer.data().V.rows() != 0: - viewer.core.align_camera_center(viewer.data().V,viewer.data().F) - - lock.release() - - except: - s.close() - return - -class TCPViewer(igl.glfw.Viewer): - def launch(self): - try: - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - s.connect((HOST, PORT)) - ser = self.data().serialize() - a = array.array('u', ser) - s.sendall(a) - s.close() - except: - print("Failed to open socket, is tcpviewer running?") - -if __name__ == "__main__": # The main script is a server - - ## Try to open the socket first - s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - try: - s.bind((HOST, PORT)) - except: - print("Failed to bind, port already used.") - exit(1) - s.listen(1) - - viewer = igl.glfw.Viewer() - - lock = threading.Lock() - t = threading.Thread(target=worker, args=(viewer,lock,s,)) - t.setDaemon(True) - t.start() - - viewer.core.is_animating = True - # viewer.data().dirty = int(0x03FF) - - viewer.launch_init(True,False) - done = False - while not done: - lock.acquire() - done = not viewer.launch_rendering(False) - lock.release() - - time.sleep(0.000001) # DO NOT REMOVE ME - - viewer.launch_shut() diff --git a/python/tutorial/001_BasicTypes.py b/python/tutorial/001_BasicTypes.py deleted file mode 100755 index 0f9673e03..000000000 --- a/python/tutorial/001_BasicTypes.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -from iglhelpers import * - -############# Dense Matrix Types ############# - -# Create a numpy dense array -# 2 types are supported by the wrappers: float64 and int64 -dense_matrix = np.array([(1, 2, 3), (4, 5, 6), (7, 8, 9)], dtype='float64') - -# libigl wrappers uses Eigen as a matrix type, you can easily convert between numpy and Eigen using -# the helper function p2e. This operation duplicates the data. -dense_matrix_eigen = p2e(dense_matrix) - -# The Eigen wrappers allows you to do operations directly on this matrix, -# without having to convert back to numpy -dense_matrix_eigen_2 = dense_matrix_eigen * dense_matrix_eigen - -# You can also inspect the data without converting it ... -print("Eigen Matrix: \n", dense_matrix_eigen_2, "\n", sep='') - -# and access single elements -print("Eigen Matrix(0,0): ", dense_matrix_eigen_2[0, 0], "\n") - -# To convert it back to a numpy array, use the helper function e2p -dense_matrix_2 = e2p(dense_matrix_eigen_2) -print("Numpy Array: \n", dense_matrix_2, "\n", sep='') - -############# Sparse Matrix Types ############# - -# Sparse matrices are handled in a very similar way -# 2 types are supported by the wrappers: float64 and int64 -sparse_matrix = sparse.rand(10, 10, 0.1) - -# To convert to the eigen forma use p2e -sparse_matrix_eigen = p2e(sparse_matrix) - -# They can directly be used plotted or used in computations -print("Sparse matrix Eigen: ", sparse_matrix_eigen, sep='') - -# And converted back with e2p -sparse_matrix_2 = e2p(sparse_matrix_eigen) -print("Sparse matrix Numpy: ", sparse_matrix_2.todense(), sep='') diff --git a/python/tutorial/101_FileIO.py b/python/tutorial/101_FileIO.py deleted file mode 100755 index a793d29bf..000000000 --- a/python/tutorial/101_FileIO.py +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH - - -# Load a mesh in OFF format -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() -igl.readOFF(TUTORIAL_SHARED_PATH + "cube.off", V, F) - -# Print the vertices and faces matrices (commented out to make this file compatible with python 2.x and 3.x) -# print("Vertices: \n", V, sep='') -# print("Faces: \n", F, sep='') - -# Save the mesh in OBJ format -igl.writeOBJ("cube.obj",V,F) diff --git a/python/tutorial/102_DrawMesh.py b/python/tutorial/102_DrawMesh.py deleted file mode 100755 index 1bc25c881..000000000 --- a/python/tutorial/102_DrawMesh.py +++ /dev/null @@ -1,29 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - -# Load a mesh in OFF format -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() -igl.readOFF(TUTORIAL_SHARED_PATH + "beetle.off", V, F) - -# Plot the mesh -viewer = igl.glfw.Viewer() -viewer.data().set_mesh(V, F) -viewer.launch() diff --git a/python/tutorial/102_DrawMesh_TCP.py b/python/tutorial/102_DrawMesh_TCP.py deleted file mode 100755 index 725bbc75d..000000000 --- a/python/tutorial/102_DrawMesh_TCP.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os -import time -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -import tcpviewer - -from shared import TUTORIAL_SHARED_PATH - - -## This is a test application for the TCPViewer -# Make sure to launch the tcpviewer.py first - -# Read a mesh -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() -igl.readOFF(TUTORIAL_SHARED_PATH + "beetle.off", V, F) - -# Send it to the viewer -viewer = tcpviewer.TCPViewer() -viewer.data().set_mesh(V, F) -viewer.launch() diff --git a/python/tutorial/103_Events.py b/python/tutorial/103_Events.py deleted file mode 100755 index e0c7ce1ca..000000000 --- a/python/tutorial/103_Events.py +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -V1 = igl.eigen.MatrixXd() -F1 = igl.eigen.MatrixXi() - -V2 = igl.eigen.MatrixXd() -F2 = igl.eigen.MatrixXi() - -def key_pressed(viewer, key, modifier): - print("Key: ", chr(key)) - - if key == ord('1'): - # # Clear should be called before drawing the mesh - viewer.data().clear() - # # Draw_mesh creates or updates the vertices and faces of the displayed mesh. - # # If a mesh is already displayed, draw_mesh returns an error if the given V and - # # F have size different than the current ones - viewer.data().set_mesh(V1, F1) - viewer.core.align_camera_center(V1,F1) - elif key == ord('2'): - viewer.data().clear() - viewer.data().set_mesh(V2, F2) - viewer.core.align_camera_center(V2,F2) - return False - - -# Load two meshes -igl.readOFF(TUTORIAL_SHARED_PATH + "bumpy.off", V1, F1) -igl.readOFF(TUTORIAL_SHARED_PATH + "fertility.off", V2, F2) - -print("1 Switch to bump mesh") -print("2 Switch to fertility mesh") - -viewer = igl.glfw.Viewer() - -# Register a keyboard callback that allows to switch between -# the two loaded meshes -viewer.callback_key_pressed = key_pressed -viewer.data().set_mesh(V1, F1) -viewer.launch() diff --git a/python/tutorial/104_Colors.py b/python/tutorial/104_Colors.py deleted file mode 100755 index 43858aa19..000000000 --- a/python/tutorial/104_Colors.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() -C = igl.eigen.MatrixXd() - -# Load a mesh in OFF format -igl.readOFF(TUTORIAL_SHARED_PATH + "screwdriver.off", V, F) - -# Plot the mesh -viewer = igl.glfw.Viewer() -viewer.data().set_mesh(V, F) - -# Use the z coordinate as a scalar field over the surface -Z = V.col(2) - -# Compute per-vertex colors -igl.jet(Z, True, C) - -# Add per-vertex colors -viewer.data().set_colors(C) - -# Launch the viewer -viewer.launch() diff --git a/python/tutorial/105_Overlays.py b/python/tutorial/105_Overlays.py deleted file mode 100755 index 852bf2e77..000000000 --- a/python/tutorial/105_Overlays.py +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() - -# Load a mesh in OFF format -igl.readOFF(TUTORIAL_SHARED_PATH + "bunny.off", V, F) - -# Find the bounding box -m = V.colwiseMinCoeff() -M = V.colwiseMaxCoeff() - -# Corners of the bounding box -V_box = igl.eigen.MatrixXd( - [ - [m[0, 0], m[0, 1], m[0, 2]], - [M[0, 0], m[0, 1], m[0, 2]], - [M[0, 0], M[0, 1], m[0, 2]], - [m[0, 0], M[0, 1], m[0, 2]], - [m[0, 0], m[0, 1], M[0, 2]], - [M[0, 0], m[0, 1], M[0, 2]], - [M[0, 0], M[0, 1], M[0, 2]], - [m[0, 0], M[0, 1], M[0, 2]] - ] -) - -E_box = igl.eigen.MatrixXd( - [ - [0, 1], - [1, 2], - [2, 3], - [3, 0], - [4, 5], - [5, 6], - [6, 7], - [7, 4], - [0, 4], - [1, 5], - [2, 6], - [7, 3] - ] -).castint() - -# Plot the mesh -viewer = igl.glfw.Viewer() -viewer.data().set_mesh(V, F) - -# Plot the corners of the bounding box as points -viewer.data().add_points(V_box, igl.eigen.MatrixXd([[1, 0, 0]])) - -# Plot the edges of the bounding box -for i in range(0, E_box.rows()): - viewer.data().add_edges( - V_box.row(E_box[i, 0]), - V_box.row(E_box[i, 1]), - igl.eigen.MatrixXd([[1, 0, 0]])) - -# Plot labels with the coordinates of bounding box vertices -l1 = 'x: ' + str(m[0, 0]) + ' y: ' + str(m[0, 1]) + ' z: ' + str(m[0, 2]) -viewer.data().add_label(m.transpose(), l1) - -l2 = 'x: ' + str(M[0, 0]) + ' y: ' + str(M[0, 1]) + ' z: ' + str(M[0, 2]) -viewer.data().add_label(M.transpose(), l2) - -# Launch the viewer -viewer.launch() diff --git a/python/tutorial/201_Normals.py b/python/tutorial/201_Normals.py deleted file mode 100755 index 43e6a60c5..000000000 --- a/python/tutorial/201_Normals.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() - -N_vertices = igl.eigen.MatrixXd() -N_faces = igl.eigen.MatrixXd() -N_corners = igl.eigen.MatrixXd() - - -# This function is called every time a keyboard button is pressed -def key_pressed(viewer, key, modifier): - if key == ord('1'): - viewer.data().set_normals(N_faces) - return True - elif key == ord('2'): - viewer.data().set_normals(N_vertices) - return True - elif key == ord('3'): - viewer.data().set_normals(N_corners) - return True - return False - - -# Load a mesh in OFF format -igl.readOFF(TUTORIAL_SHARED_PATH + "fandisk.off", V, F) - -# Compute per-face normals -N_faces = igl.eigen.MatrixXd() -igl.per_face_normals(V, F, N_faces) - -# Compute per-vertex normals -N_vertices = igl.eigen.MatrixXd() -igl.per_vertex_normals(V, F, igl.PER_VERTEX_NORMALS_WEIGHTING_TYPE_AREA, N_vertices) - -# Compute per-corner normals, |dihedral angle| > 20 degrees --> crease -N_corners = igl.eigen.MatrixXd() -igl.per_corner_normals(V, F, 20, N_corners) - -# Plot the mesh -viewer = igl.glfw.Viewer() -viewer.callback_key_pressed = key_pressed -viewer.data().show_lines = False -viewer.data().set_mesh(V, F) -viewer.data().set_normals(N_faces) -print("Press '1' for per-face normals.") -print("Press '2' for per-vertex normals.") -print("Press '3' for per-corner normals.") -viewer.launch() diff --git a/python/tutorial/202_GaussianCurvature.py b/python/tutorial/202_GaussianCurvature.py deleted file mode 100755 index 5fe243b03..000000000 --- a/python/tutorial/202_GaussianCurvature.py +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -# Load mesh -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() -igl.readOFF(TUTORIAL_SHARED_PATH + "bumpy.off", V, F) - -# Compute Gaussian curvature -K = igl.eigen.MatrixXd() -igl.gaussian_curvature(V, F, K) - -# Compute pseudocolor -C = igl.eigen.MatrixXd() -igl.jet(K, True, C) - -# Plot the mesh with pseudocolors -viewer = igl.glfw.Viewer() -viewer.data().set_mesh(V, F) -viewer.data().set_colors(C) -viewer.launch() diff --git a/python/tutorial/203_CurvatureDirections.py b/python/tutorial/203_CurvatureDirections.py deleted file mode 100755 index adf1bde22..000000000 --- a/python/tutorial/203_CurvatureDirections.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() -igl.read_triangle_mesh(TUTORIAL_SHARED_PATH + "fertility.off", V, F) - -# Alternative discrete mean curvature -HN = igl.eigen.MatrixXd() -L = igl.eigen.SparseMatrixd() -M = igl.eigen.SparseMatrixd() -Minv = igl.eigen.SparseMatrixd() - -igl.cotmatrix(V, F, L) -igl.massmatrix(V, F, igl.MASSMATRIX_TYPE_VORONOI, M) - -igl.invert_diag(M, Minv) - -# Laplace-Beltrami of position -HN = -Minv * (L * V) - -# Extract magnitude as mean curvature -H = HN.rowwiseNorm() - -# Compute curvature directions via quadric fitting -PD1 = igl.eigen.MatrixXd() -PD2 = igl.eigen.MatrixXd() - -PV1 = igl.eigen.MatrixXd() -PV2 = igl.eigen.MatrixXd() - -igl.principal_curvature(V, F, PD1, PD2, PV1, PV2) - -# Mean curvature -H = 0.5 * (PV1 + PV2) - -viewer = igl.glfw.Viewer() -viewer.data().set_mesh(V, F) - -# Compute pseudocolor -C = igl.eigen.MatrixXd() -igl.parula(H, True, C) - -viewer.data().set_colors(C) - -# Average edge length for sizing -avg = igl.avg_edge_length(V, F) - -# Draw a blue segment parallel to the minimal curvature direction -red = igl.eigen.MatrixXd([[0.8, 0.2, 0.2]]) -blue = igl.eigen.MatrixXd([[0.2, 0.2, 0.8]]) - -viewer.data().add_edges(V + PD1 * avg, V - PD1 * avg, blue) - -# Draw a red segment parallel to the maximal curvature direction -viewer.data().add_edges(V + PD2 * avg, V - PD2 * avg, red) - -# Hide wireframe -viewer.data().show_lines = False - -viewer.launch() diff --git a/python/tutorial/204_Gradient.py b/python/tutorial/204_Gradient.py deleted file mode 100755 index 49c2873df..000000000 --- a/python/tutorial/204_Gradient.py +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() - -# Load a mesh in OFF format -igl.readOFF(TUTORIAL_SHARED_PATH + "cheburashka.off", V, F) - -# Read scalar function values from a file, U: #V by 1 -U = igl.eigen.MatrixXd() -igl.readDMAT(TUTORIAL_SHARED_PATH + "cheburashka-scalar.dmat", U) -U = U.col(0) - -# Compute gradient operator: #F*3 by #V -G = igl.eigen.SparseMatrixd() -igl.grad(V, F, G) - -# Compute gradient of U -GU = (G * U).MapMatrix(F.rows(), 3) - -# Compute gradient magnitude -GU_mag = GU.rowwiseNorm() - -viewer = igl.glfw.Viewer() -viewer.data().set_mesh(V, F) - -# Compute pseudocolor for original function -C = igl.eigen.MatrixXd() - -igl.jet(U, True, C) - -# Or for gradient magnitude -# igl.jet(GU_mag,True,C) - -viewer.data().set_colors(C) - -# Average edge length divided by average gradient (for scaling) -max_size = igl.avg_edge_length(V, F) / GU_mag.mean() - -# Draw a black segment in direction of gradient at face barycenters -BC = igl.eigen.MatrixXd() -igl.barycenter(V, F, BC) - -black = igl.eigen.MatrixXd([[0.0, 0.0, 0.0]]) -viewer.data().add_edges(BC, BC + max_size * GU, black) - -# Hide wireframe -viewer.data().show_lines = False - -viewer.launch() diff --git a/python/tutorial/205_Laplacian.py b/python/tutorial/205_Laplacian.py deleted file mode 100755 index 656ae0929..000000000 --- a/python/tutorial/205_Laplacian.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os -import math - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -V = igl.eigen.MatrixXd() -U = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() - -L = igl.eigen.SparseMatrixd() -viewer = igl.glfw.Viewer() - -# Load a mesh in OFF format -igl.readOFF(TUTORIAL_SHARED_PATH + "cow.off", V, F) - -# Compute Laplace-Beltrami operator: #V by #V -igl.cotmatrix(V, F, L) - -# Alternative construction of same Laplacian -G = igl.eigen.SparseMatrixd() -K = igl.eigen.SparseMatrixd() - -# Gradient/Divergence -igl.grad(V, F, G) - -# Diagonal per-triangle "mass matrix" -dblA = igl.eigen.MatrixXd() -igl.doublearea(V, F, dblA) - -# Place areas along diagonal #dim times - -T = (dblA.replicate(3, 1) * 0.5).asDiagonal() * 1 - -# Laplacian K built as discrete divergence of gradient or equivalently -# discrete Dirichelet energy Hessian - -temp = -G.transpose() -K = -G.transpose() * T * G -print("|K-L|: ", (K - L).norm()) - - -def key_pressed(viewer, key, modifier): - global V, U, F, L - - if key == ord('r') or key == ord('R'): - U = V - print("RESET") - - elif key == ord(' '): - - # Recompute just mass matrix on each step - M = igl.eigen.SparseMatrixd() - - igl.massmatrix(U, F, igl.MASSMATRIX_TYPE_BARYCENTRIC, M) - - # Solve (M-delta*L) U = M*U - S = (M - 0.001 * L) - - solver = igl.eigen.SimplicialLLTsparse(S) - - U = solver.solve(M * U) - - # Compute centroid and subtract (also important for numerics) - dblA = igl.eigen.MatrixXd() - igl.doublearea(U, F, dblA) - - print(dblA.sum()) - - area = 0.5 * dblA.sum() - BC = igl.eigen.MatrixXd() - igl.barycenter(U, F, BC) - centroid = igl.eigen.MatrixXd([[0.0, 0.0, 0.0]]) - - for i in range(0, BC.rows()): - centroid += 0.5 * dblA[i, 0] / area * BC.row(i) - - U -= centroid.replicate(U.rows(), 1) - - # Normalize to unit surface area (important for numerics) - U = U / math.sqrt(area) - else: - return False - - # Send new positions, update normals, recenter - viewer.data().set_vertices(U) - viewer.data().compute_normals() - viewer.core.align_camera_center(U, F) - return True - - -# Use original normals as pseudo-colors -N = igl.eigen.MatrixXd() -igl.per_vertex_normals(V, F, N) -C = N.rowwiseNormalized() * 0.5 + 0.5 - -# Initialize smoothing with base mesh -U = V -viewer.data().set_mesh(U, F) -viewer.data().set_colors(C) -viewer.callback_key_pressed = key_pressed - -print("Press [space] to smooth.") -print("Press [r] to reset.") - -viewer.launch() diff --git a/python/tutorial/301_Slice.py b/python/tutorial/301_Slice.py deleted file mode 100755 index db58a361c..000000000 --- a/python/tutorial/301_Slice.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() - - -igl.readOFF(TUTORIAL_SHARED_PATH + "decimated-knight.off", V, F) - -# 100 random indices into rows of F -I = igl.eigen.MatrixXi() -igl.floor((0.5 * (igl.eigen.MatrixXd.Random(100, 1) + 1.) * F.rows()), I) - -# 50 random indices into rows of I -J = igl.eigen.MatrixXi() -igl.floor((0.5 * (igl.eigen.MatrixXd.Random(50, 1) + 1.) * I.rows()), J) - -# K = I(J); -K = igl.eigen.MatrixXi() -igl.slice(I, J, K) - -# default green for all faces -# C = p2e(np.array([[0.4,0.8,0.3]])).replicate(F.rows(),1) -C = igl.eigen.MatrixXd([[0.4, 0.8, 0.3]]).replicate(F.rows(), 1) - -# Red for each in K -R = igl.eigen.MatrixXd([[1.0, 0.3, 0.3]]).replicate(K.rows(), 1) -# C(K,:) = R -igl.slice_into(R, K, 1, C) - -# Plot the mesh with pseudocolors -viewer = igl.glfw.Viewer() -viewer.data().set_mesh(V, F) -viewer.data().set_colors(C) -viewer.launch() diff --git a/python/tutorial/302_Sort.py b/python/tutorial/302_Sort.py deleted file mode 100755 index e5bd51f76..000000000 --- a/python/tutorial/302_Sort.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() - -igl.readOFF(TUTORIAL_SHARED_PATH + "decimated-knight.off", V, F) - -# Sort barycenters lexicographically -BC = igl.eigen.MatrixXd() -sorted_BC = igl.eigen.MatrixXd() - -igl.barycenter(V, F, BC) - -I = igl.eigen.MatrixXi() -J = igl.eigen.MatrixXi() - -# sorted_BC = BC(I,:) -igl.sortrows(BC, True, sorted_BC, I) - -# Get sorted "place" from sorted indices -J.resize(I.rows(), 1) -# J(I) = 1:numel(I) - -igl.slice_into(igl.coloni(0, I.size() - 1), I, J) - -# Pseudo-color based on sorted place -C = igl.eigen.MatrixXd() -igl.jet(J.castdouble(), True, C) - -# Plot the mesh with pseudocolors -viewer = igl.glfw.Viewer() -viewer.data().set_mesh(V, F) -viewer.data().set_colors(C) -viewer.launch() diff --git a/python/tutorial/303_LaplaceEquation.py b/python/tutorial/303_LaplaceEquation.py deleted file mode 100755 index 1d590417e..000000000 --- a/python/tutorial/303_LaplaceEquation.py +++ /dev/null @@ -1,91 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() - -igl.readOFF(TUTORIAL_SHARED_PATH + "camelhead.off", V, F) - -# Find boundary edges -E = igl.eigen.MatrixXi() -igl.boundary_facets(F, E) - -# Find boundary vertices -b = igl.eigen.MatrixXi() -IA = igl.eigen.MatrixXi() -IC = igl.eigen.MatrixXi() - -igl.unique(E, b, IA, IC) - -# List of all vertex indices -vall = igl.eigen.MatrixXi() -vin = igl.eigen.MatrixXi() - -igl.coloni(0, V.rows() - 1, vall) - -# List of interior indices -igl.setdiff(vall, b, vin, IA) - -# Construct and slice up Laplacian -L = igl.eigen.SparseMatrixd() -L_in_in = igl.eigen.SparseMatrixd() -L_in_b = igl.eigen.SparseMatrixd() - -igl.cotmatrix(V, F, L) -igl.slice(L, vin, vin, L_in_in) -igl.slice(L, vin, b, L_in_b) - -# Dirichlet boundary conditions from z-coordinate -bc = igl.eigen.MatrixXd() -Z = V.col(2) -igl.slice(Z, b, bc) - -# Solve PDE -solver = igl.eigen.SimplicialLLTsparse(-L_in_in) -Z_in = solver.solve(L_in_b * bc) - -# slice into solution -igl.slice_into(Z_in, vin, Z) - -# Alternative, short hand -mqwf = igl.min_quad_with_fixed_data() - -# Linear term is 0 -B = igl.eigen.MatrixXd() -B.setZero(V.rows(), 1) - -# Empty constraints -Beq = igl.eigen.MatrixXd() -Aeq = igl.eigen.SparseMatrixd() - -# Our cotmatrix is _negative_ definite, so flip sign -igl.min_quad_with_fixed_precompute(-L, b, Aeq, True, mqwf) -igl.min_quad_with_fixed_solve(mqwf, B, bc, Beq, Z) - -# Pseudo-color based on solution -C = igl.eigen.MatrixXd() -igl.jet(Z, True, C) - -# Plot the mesh with pseudocolors -viewer = igl.glfw.Viewer() -viewer.data().set_mesh(V, F) -viewer.data().show_lines = False -viewer.data().set_colors(C) -viewer.launch() diff --git a/python/tutorial/304_LinearEqualityConstraints.py b/python/tutorial/304_LinearEqualityConstraints.py deleted file mode 100755 index 0f9294c30..000000000 --- a/python/tutorial/304_LinearEqualityConstraints.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() - -igl.readOFF(TUTORIAL_SHARED_PATH + "cheburashka.off", V, F) - -# Two fixed points -# Left hand, left foot -b = igl.eigen.MatrixXd([[4331], [5957]]).castint() -bc = igl.eigen.MatrixXd([[1], [-1]]) - -# Construct Laplacian and mass matrix -L = igl.eigen.SparseMatrixd() -M = igl.eigen.SparseMatrixd() -Minv = igl.eigen.SparseMatrixd() -Q = igl.eigen.SparseMatrixd() - -igl.cotmatrix(V, F, L) -igl.massmatrix(V, F, igl.MASSMATRIX_TYPE_VORONOI, M) -igl.invert_diag(M, Minv) - -# Bi-Laplacian -Q = L * (Minv * L) - -# Zero linear term -B = igl.eigen.MatrixXd.Zero(V.rows(), 1) - -Z = igl.eigen.MatrixXd() -Z_const = igl.eigen.MatrixXd() - -# Alternative, short hand -mqwf = igl.min_quad_with_fixed_data() - -# Empty constraints -Beq = igl.eigen.MatrixXd() -Aeq = igl.eigen.SparseMatrixd() - -igl.min_quad_with_fixed_precompute(Q, b, Aeq, True, mqwf) -igl.min_quad_with_fixed_solve(mqwf, B, bc, Beq, Z) - -# Constraint forcing difference of two points to be 0 -Aeq = igl.eigen.SparseMatrixd(1, V.rows()) - -# Right hand, right foot -Aeq.insert(0, 6074, 1) -Aeq.insert(0, 6523, -1) -Aeq.makeCompressed() - -Beq = igl.eigen.MatrixXd([[0]]) -igl.min_quad_with_fixed_precompute(Q, b, Aeq, True, mqwf) -igl.min_quad_with_fixed_solve(mqwf, B, bc, Beq, Z_const) - -# Global definitions for viewer -# Pseudo-color based on solution -C = igl.eigen.MatrixXd() -C_const = igl.eigen.MatrixXd() -toggle = True - -# Use same color axes -min_z = min(Z.minCoeff(), Z_const.minCoeff()) -max_z = max(Z.maxCoeff(), Z_const.maxCoeff()) - -igl.jet(Z, min_z, max_z, C) -igl.jet(Z_const, min_z, max_z, C_const) - -# Plot the mesh with pseudocolors -viewer = igl.glfw.Viewer() -viewer.data().set_mesh(V, F) -viewer.data().show_lines = False -viewer.data().set_colors(C) - - -def key_down(viewer, key, mode): - if key == ord(' '): - global toggle, C, C_const - - if toggle: - viewer.data().set_colors(C) - else: - viewer.data().set_colors(C_const) - - toggle = not toggle - return True - - return False - - -viewer.callback_key_down = key_down - -print("Press [space] to toggle between unconstrained and constrained.") -viewer.launch() diff --git a/python/tutorial/305_QuadraticProgramming.py b/python/tutorial/305_QuadraticProgramming.py deleted file mode 100755 index 05c639416..000000000 --- a/python/tutorial/305_QuadraticProgramming.py +++ /dev/null @@ -1,107 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -b = igl.eigen.MatrixXi() -B = igl.eigen.MatrixXd() -bc = igl.eigen.MatrixXd() -lx = igl.eigen.MatrixXd() -ux = igl.eigen.MatrixXd() -Beq = igl.eigen.MatrixXd() -Bieq = igl.eigen.MatrixXd() -Z = igl.eigen.MatrixXd() - -Q = igl.eigen.SparseMatrixd() -Aeq = igl.eigen.SparseMatrixd() -Aieq = igl.eigen.SparseMatrixd() - - -def solve(viewer): - global Q, B, b, bc, Aeq, Beq, Aieq, Bieq, lx, ux, Z - params = igl.active_set_params() - params.max_iter = 8 - - igl.active_set(Q, B, b, bc, Aeq, Beq, Aieq, Bieq, lx, ux, params, Z) - - C = igl.eigen.MatrixXd() - igl.jet(Z, 0, 1, C) - viewer.data().set_colors(C) - - -def key_down(viewer, key, mod): - global Beq, solve - if key == ord('.'): - Beq[0, 0] = Beq[0, 0] * 2.0 - solve(viewer) - return True - elif key == ord(','): - Beq[0, 0] = Beq[0, 0] / 2.0 - solve(viewer) - return True - elif key == ord(' '): - solve(viewer) - return True - return False - - -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() - -igl.readOFF(TUTORIAL_SHARED_PATH + "cheburashka.off", V, F) - -# Plot the mesh -viewer = igl.glfw.Viewer() -viewer.data().set_mesh(V, F) -viewer.data().show_lines = False -viewer.callback_key_down = key_down - -# One fixed point on belly -b = igl.eigen.MatrixXd([[2556]]).castint() -bc = igl.eigen.MatrixXd([[1]]) - -# Construct Laplacian and mass matrix -L = igl.eigen.SparseMatrixd() -M = igl.eigen.SparseMatrixd() -Minv = igl.eigen.SparseMatrixd() - -igl.cotmatrix(V, F, L) -igl.massmatrix(V, F, igl.MASSMATRIX_TYPE_VORONOI, M) -igl.invert_diag(M, Minv) - -# Bi-Laplacian -Q = L.transpose() * (Minv * L) - -# Zero linear term -B = igl.eigen.MatrixXd.Zero(V.rows(), 1) - -# Lower and upper bound -lx = igl.eigen.MatrixXd.Zero(V.rows(), 1) -ux = igl.eigen.MatrixXd.Ones(V.rows(), 1) - -# Equality constraint constrain solution to sum to 1 -Beq = igl.eigen.MatrixXd([[0.08]]) -Aeq = M.diagonal().sparseView().transpose() - -# (Empty inequality constraints) -solve(viewer) -print("Press '.' to increase scale and resolve.") -print("Press ',' to decrease scale and resolve.") - -viewer.launch() diff --git a/python/tutorial/306_EigenDecomposition.py b/python/tutorial/306_EigenDecomposition.py deleted file mode 100755 index a0e2bfd64..000000000 --- a/python/tutorial/306_EigenDecomposition.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -V = igl.eigen.MatrixXd() -U = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() - -c = 0 -bbd = 1.0 -twod = False - -if not igl.read_triangle_mesh(TUTORIAL_SHARED_PATH + "beetle.off", V, F): - print("failed to load mesh") - -twod = V.col(2).minCoeff() == V.col(2).maxCoeff() -bbd = (V.colwiseMaxCoeff() - V.colwiseMinCoeff()).norm() - -L = igl.eigen.SparseMatrixd() -M = igl.eigen.SparseMatrixd() - -igl.cotmatrix(V, F, L) -L = -L -igl.massmatrix(V, F, igl.MASSMATRIX_TYPE_DEFAULT, M) -k = 5 - -D = igl.eigen.MatrixXd() -if not igl.eigs(L, M, k + 1, igl.EIGS_TYPE_SM, U, D): - print("Eigs failed.") - -U = (U - U.minCoeff()) / (U.maxCoeff() - U.minCoeff()) - -viewer = igl.glfw.Viewer() - - -def key_down(viewer, key, mod): - global U, c - - if key == ord(' '): - U = U.rightCols(k) - - # Rescale eigen vectors for visualization - Z = bbd * 0.5 * U.col(c) - C = igl.eigen.MatrixXd() - igl.parula(U.col(c), False, C) - c = (c + 1) % U.cols() - - if twod: - V.setcol(2, Z) - - viewer.data().set_mesh(V, F) - viewer.data().compute_normals() - viewer.data().set_colors(C) - return True - return False - - -viewer.callback_key_down = key_down -viewer.callback_key_down(viewer, ord(' '), 0) -viewer.data().show_lines = False -viewer.launch() diff --git a/python/tutorial/401_BiharmonicDeformation.py b/python/tutorial/401_BiharmonicDeformation.py deleted file mode 100755 index 11685bf22..000000000 --- a/python/tutorial/401_BiharmonicDeformation.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - -bc_frac = 1.0 -bc_dir = -0.03 -deformation_field = False - -V = igl.eigen.MatrixXd() -U = igl.eigen.MatrixXd() -V_bc = igl.eigen.MatrixXd() -U_bc = igl.eigen.MatrixXd() - -# Z = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() -b = igl.eigen.MatrixXi() - - -def pre_draw(viewer): - global bc_frac, bc_dir, deformation_field, V, U, V_bc, U_bc, F, b - # Determine boundary conditions - if (viewer.core.is_animating): - bc_frac += bc_dir - bc_dir *= (-1.0 if bc_frac >= 1.0 or bc_frac <= 0.0 else 1.0) - - U_bc_anim = V_bc + bc_frac * (U_bc - V_bc) - - if (deformation_field): - D = igl.eigen.MatrixXd() - D_bc = U_bc_anim - V_bc - igl.harmonic(V, F, b, D_bc, 2, D) - U = V + D - else: - igl.harmonic(V, F, b, U_bc_anim, 2, U) - - viewer.data().set_vertices(U) - viewer.data().compute_normals() - return False - - -def key_down(viewer, key, mods): - global bc_frac, bc_dir, deformation_field, V, U, V_bc, U_bc, F, b - - if key == ord(' '): - viewer.core.is_animating = not viewer.core.is_animating - return True - if key == ord('D') or key == ord('d'): - deformation_field = not deformation_field - return True - return False - - -igl.readOBJ(TUTORIAL_SHARED_PATH + "decimated-max.obj", V, F) -U = igl.eigen.MatrixXd(V) - -# S(i) = j: j<0 (vertex i not in handle), j >= 0 (vertex i in handle j) -S = igl.eigen.MatrixXd() -igl.readDMAT(TUTORIAL_SHARED_PATH + "decimated-max-selection.dmat", S) - -S = S.castint() - -b = igl.eigen.MatrixXd([[t[0] for t in [(i, S[i]) for i in range(0, V.rows())] if t[1] >= 0]]).transpose().castint() - -# Boundary conditions directly on deformed positions -U_bc.resize(b.rows(), V.cols()) -V_bc.resize(b.rows(), V.cols()) - -for bi in range(0, b.rows()): - V_bc.setRow(bi, V.row(b[bi])) - - if S[b[bi]] == 0: - # Don't move handle 0 - U_bc.setRow(bi, V.row(b[bi])) - elif S[b[bi]] == 1: - # Move handle 1 down - U_bc.setRow(bi, V.row(b[bi]) + igl.eigen.MatrixXd([[0, -50, 0]])) - else: - # Move other handles forward - U_bc.setRow(bi, V.row(b[bi]) + igl.eigen.MatrixXd([[0, 0, -25]])) - -# Pseudo-color based on selection -C = igl.eigen.MatrixXd(F.rows(), 3) -purple = igl.eigen.MatrixXd([[80.0 / 255.0, 64.0 / 255.0, 255.0 / 255.0]]) -gold = igl.eigen.MatrixXd([[255.0 / 255.0, 228.0 / 255.0, 58.0 / 255.0]]) - -for f in range(0, F.rows()): - if (S[F[f, 0]]) >= 0 and S[F[f, 1]] >= 0 and S[F[f, 2]] >= 0: - C.setRow(f, purple) - else: - C.setRow(f, gold) - -# Plot the mesh with pseudocolors -viewer = igl.glfw.Viewer() -viewer.data().set_mesh(U, F) -viewer.data().show_lines = False -viewer.data().set_colors(C) -# viewer.core.trackball_angle = igl.eigen.Quaterniond(sqrt(2.0),0,sqrt(2.0),0) -# viewer.core.trackball_angle.normalize() - -viewer.callback_pre_draw = pre_draw -viewer.callback_key_down = key_down - -viewer.core.animation_max_fps = 30.0 -print("Press [space] to toggle deformation.") -print("Press 'd' to toggle between biharmonic surface or displacements.") -viewer.launch() diff --git a/python/tutorial/402_PolyharmonicDeformation.py b/python/tutorial/402_PolyharmonicDeformation.py deleted file mode 100755 index a231e715b..000000000 --- a/python/tutorial/402_PolyharmonicDeformation.py +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -z_max = 1.0 -z_dir = -0.03 -k = 2 -resolve = True - -V = igl.eigen.MatrixXd() -U = igl.eigen.MatrixXd() - -Z = igl.eigen.MatrixXd() - -F = igl.eigen.MatrixXi() -b = igl.eigen.MatrixXi() - -bc = igl.eigen.MatrixXd() - - -def pre_draw(viewer): - global z_max, z_dir, k, resolve, V, U, Z, F, b, bc - - if resolve: - igl.harmonic(V, F, b, bc, k, Z) - resolve = False - - U.setCol(2, z_max * Z) - viewer.data().set_vertices(U) - viewer.data().compute_normals() - - if viewer.core.is_animating: - z_max += z_dir - z_dir *= (-1.0 if z_max >= 1.0 or z_max <= 0.0 else 1.0) - - return False - - -def key_down(viewer, key, mods): - global z_max, z_dir, k, resolve, V, U, Z, F, b, bc - - if key == ord(' '): - viewer.core.is_animating = not viewer.core.is_animating - elif key == ord('.'): - k = k + 1 - k = (4 if k > 4 else k) - resolve = True - elif key == ord(','): - k = k - 1 - k = (1 if k < 1 else k) - resolve = True - return True - - -igl.readOBJ(TUTORIAL_SHARED_PATH + "bump-domain.obj", V, F) -U = igl.eigen.MatrixXd(V) - -# Find boundary vertices outside annulus - -Vrn = V.rowwiseNorm() -is_outer = [Vrn[i] - 1.00 > -1e-15 for i in range(0, V.rows())] -is_inner = [Vrn[i] - 0.15 < 1e-15 for i in range(0, V.rows())] -in_b = [is_outer[i] or is_inner[i] for i in range(0, len(is_outer))] - -b = igl.eigen.MatrixXd([[i for i in range(0, V.rows()) if (in_b[i])]]).transpose().castint() - -bc.resize(b.size(), 1) - -for bi in range(0, b.size()): - bc[bi] = (0.0 if is_outer[b[bi]] else 1.0) - -# Pseudo-color based on selection -C = igl.eigen.MatrixXd(F.rows(), 3) -purple = igl.eigen.MatrixXd([[80.0 / 255.0, 64.0 / 255.0, 255.0 / 255.0]]) -gold = igl.eigen.MatrixXd([[255.0 / 255.0, 228.0 / 255.0, 58.0 / 255.0]]) - -for f in range(0, F.rows()): - if in_b[F[f, 0]] and in_b[F[f, 1]] and in_b[F[f, 2]]: - C.setRow(f, purple) - else: - C.setRow(f, gold) - -# Plot the mesh with pseudocolors -viewer = igl.glfw.Viewer() -viewer.data().set_mesh(U, F) -viewer.data().show_lines = False -viewer.data().set_colors(C) -viewer.core.trackball_angle = igl.eigen.Quaterniond(0.81,-0.58,-0.03,-0.03) -viewer.core.trackball_angle.normalize() -viewer.callback_pre_draw = pre_draw -viewer.callback_key_down = key_down -viewer.core.is_animating = True -viewer.core.animation_max_fps = 30.0 -print("Press [space] to toggle animation.") -print("Press '.' to increase k.") -print("Press ',' to decrease k.") -viewer.launch() diff --git a/python/tutorial/403_BoundedBiharmonicWeights.py b/python/tutorial/403_BoundedBiharmonicWeights.py deleted file mode 100755 index 6cdb0bde4..000000000 --- a/python/tutorial/403_BoundedBiharmonicWeights.py +++ /dev/null @@ -1,154 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies, print_usage - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -def pre_draw(viewer): - global pose, anim_t, C, BE, P, U, M, anim_t_dir - - if viewer.core.is_animating: - # Interpolate pose and identity - anim_pose = igl.RotationList(len(pose)) - - for e in range(len(pose)): - anim_pose[e] = pose[e].slerp(anim_t, igl.eigen.Quaterniond.Identity()) - - # Propagate relative rotations via FK to retrieve absolute transformations - vQ = igl.RotationList() - vT = [] - igl.forward_kinematics(C, BE, P, anim_pose, vQ, vT) - dim = C.cols() - T = igl.eigen.MatrixXd(BE.rows() * (dim + 1), dim) - for e in range(BE.rows()): - a = igl.eigen.Affine3d.Identity() - a.translate(vT[e]) - a.rotate(vQ[e]) - T.setBlock(e * (dim + 1), 0, dim + 1, dim, a.matrix().transpose().block(0, 0, dim + 1, dim)) - - # Compute deformation via LBS as matrix multiplication - U = M * T - - # Also deform skeleton edges - CT = igl.eigen.MatrixXd() - BET = igl.eigen.MatrixXi() - igl.deform_skeleton(C, BE, T, CT, BET) - - viewer.data().set_vertices(U) - viewer.data().set_edges(CT, BET, sea_green) - viewer.data().compute_normals() - anim_t += anim_t_dir - anim_t_dir *= -1.0 if (0.0 >= anim_t or anim_t >= 1.0) else 1.0 - - return False - - -def key_down(viewer, key, mods): - global selected, W - if key == ord('.'): - selected += 1 - selected = min(max(selected, 0), W.cols()-1) - set_color(viewer) - elif key == ord(','): - selected -= 1 - selected = min(max(selected, 0), W.cols()-1) - set_color(viewer) - elif key == ord(' '): - viewer.core.is_animating = not viewer.core.is_animating - - return True - - -def set_color(viewer): - global selected, W - C = igl.eigen.MatrixXd() - igl.jet(W.col(selected), True, C) - viewer.data().set_colors(C) - - -if __name__ == "__main__": - keys = {".": "show next weight function", - ",": "show previous weight function", - "space": "toggle animation"} - - print_usage(keys) - - V = igl.eigen.MatrixXd() - W = igl.eigen.MatrixXd() - U = igl.eigen.MatrixXd() - C = igl.eigen.MatrixXd() - M = igl.eigen.MatrixXd() - Q = igl.eigen.MatrixXd() - T = igl.eigen.MatrixXi() - F = igl.eigen.MatrixXi() - BE = igl.eigen.MatrixXi() - P = igl.eigen.MatrixXi() - - sea_green = igl.eigen.MatrixXd([[70. / 255., 252. / 255., 167. / 255.]]) - - selected = 0 - pose = igl.RotationList() - anim_t = 1.0 - anim_t_dir = -0.03 - - igl.readMESH(TUTORIAL_SHARED_PATH + "hand.mesh", V, T, F) - U = igl.eigen.MatrixXd(V) - igl.readTGF(TUTORIAL_SHARED_PATH + "hand.tgf", C, BE) - - # Retrieve parents for forward kinematics - igl.directed_edge_parents(BE, P) - - # Read pose as matrix of quaternions per row - igl.readDMAT(TUTORIAL_SHARED_PATH + "hand-pose.dmat", Q) - igl.column_to_quats(Q, pose) - assert (len(pose) == BE.rows()) - - # List of boundary indices (aka fixed value indices into VV) - b = igl.eigen.MatrixXi() - # List of boundary conditions of each weight function - bc = igl.eigen.MatrixXd() - - igl.boundary_conditions(V, T, C, igl.eigen.MatrixXi(), BE, igl.eigen.MatrixXi(), b, bc) - - # compute BBW weights matrix - bbw_data = igl.BBWData() - # only a few iterations for sake of demo - bbw_data.active_set_params.max_iter = 8 - bbw_data.verbosity = 2 - if not igl.bbw(V, T, b, bc, bbw_data, W): - exit(-1) - - # Normalize weights to sum to one - igl.normalize_row_sums(W, W) - # precompute linear blend skinning matrix - igl.lbs_matrix(V, W, M) - - # Plot the mesh with pseudocolors - viewer = igl.glfw.Viewer() - viewer.data().set_mesh(U, F) - set_color(viewer) - viewer.data().set_edges(C, BE, sea_green) - viewer.data().show_lines = False - viewer.data().show_overlay_depth = False - viewer.data().line_width = 1 - viewer.core.trackball_angle.normalize() - viewer.callback_pre_draw = pre_draw - viewer.callback_key_down = key_down - viewer.core.is_animating = False - viewer.core.animation_max_fps = 30.0 - viewer.launch() diff --git a/python/tutorial/404_DualQuaternionSkinning.py b/python/tutorial/404_DualQuaternionSkinning.py deleted file mode 100755 index 812a71630..000000000 --- a/python/tutorial/404_DualQuaternionSkinning.py +++ /dev/null @@ -1,149 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os -from math import sin, cos, pi - -# Add the igl library to the modules search path -import math - -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies, print_usage - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -def pre_draw(viewer): - global recompute, anim_t, poses, C, BE, P, U, M, anim_t_dir - - if recompute: - # Find pose interval - begin = int(math.floor(anim_t)) % len(poses) - end = int(math.floor(anim_t) + 1) % len(poses) - t = anim_t - math.floor(anim_t) - - # Interpolate pose and identity - anim_pose = igl.RotationList() - for e in range(len(poses[begin])): - anim_pose.append(poses[begin][e].slerp(t, poses[end][e])) - - # Propagate relative rotations via FK to retrieve absolute transformations - vQ = igl.RotationList() - vT = [] - igl.forward_kinematics(C, BE, P, anim_pose, vQ, vT) - dim = C.cols() - T = igl.eigen.MatrixXd(BE.rows() * (dim + 1), dim) - for e in range(BE.rows()): - a = igl.eigen.Affine3d.Identity() - a.translate(vT[e]) - a.rotate(vQ[e]) - T.setBlock(e * (dim + 1), 0, dim + 1, dim, a.matrix().transpose().block(0, 0, dim + 1, dim)) - - # Compute deformation via LBS as matrix multiplication - if use_dqs: - igl.dqs(V, W, vQ, vT, U) - else: - U = M * T - - # Also deform skeleton edges - CT = igl.eigen.MatrixXd() - BET = igl.eigen.MatrixXi() - igl.deform_skeleton(C, BE, T, CT, BET) - - viewer.data().set_vertices(U) - viewer.data().set_edges(CT, BET, sea_green) - viewer.data().compute_normals() - if viewer.core.is_animating: - anim_t += anim_t_dir - else: - recompute = False - - return False - - -def key_down(viewer, key, mods): - global recompute, use_dqs, animation - recompute = True - if key == ord('D') or key == ord('d'): - use_dqs = not use_dqs - viewer.core.is_animating = False - animation = False - if use_dqs: - print("Switched to Dual Quaternion Skinning") - else: - print("Switched to Linear Blend Skinning") - elif key == ord(' '): - if animation: - viewer.core.is_animating = False - animation = False - else: - viewer.core.is_animating = True - animation = True - return False - - -if __name__ == "__main__": - keys = {"d": "toggle between LBS and DQS", - "space": "toggle animation"} - - print_usage(keys) - - V = igl.eigen.MatrixXd() - F = igl.eigen.MatrixXi() - C = igl.eigen.MatrixXd() - BE = igl.eigen.MatrixXi() - P = igl.eigen.MatrixXi() - W = igl.eigen.MatrixXd() - M = igl.eigen.MatrixXd() - - sea_green = igl.eigen.MatrixXd([[70. / 255., 252. / 255., 167. / 255.]]) - - anim_t = 0.0 - anim_t_dir = 0.015 - use_dqs = False - recompute = True - animation = False # Flag needed as there is some synchronization problem with viewer.core.is_animating - - poses = [[]] - - igl.readOBJ(TUTORIAL_SHARED_PATH + "arm.obj", V, F) - U = igl.eigen.MatrixXd(V) - igl.readTGF(TUTORIAL_SHARED_PATH + "arm.tgf", C, BE) - - # retrieve parents for forward kinematics - igl.directed_edge_parents(BE, P) - rest_pose = igl.RotationList() - igl.directed_edge_orientations(C, BE, rest_pose) - poses = [[igl.eigen.Quaterniond.Identity() for i in range(4)] for j in range(4)] - - twist = igl.eigen.Quaterniond(pi, igl.eigen.MatrixXd([1, 0, 0])) - poses[1][2] = rest_pose[2] * twist * rest_pose[2].conjugate() - bend = igl.eigen.Quaterniond(-pi * 0.7, igl.eigen.MatrixXd([0, 0, 1])) - poses[3][2] = rest_pose[2] * bend * rest_pose[2].conjugate() - - igl.readDMAT(TUTORIAL_SHARED_PATH + "arm-weights.dmat", W) - igl.lbs_matrix(V, W, M) - - # Plot the mesh with pseudocolors - viewer = igl.glfw.Viewer() - viewer.data().set_mesh(U, F) - viewer.data().set_edges(C, BE, sea_green) - viewer.data().show_lines = False - viewer.data().show_overlay_depth = False - viewer.data().line_width = 1 - viewer.core.trackball_angle.normalize() - viewer.callback_pre_draw = pre_draw - viewer.callback_key_down = key_down - viewer.core.is_animating = False - viewer.core.camera_zoom = 2.5 - viewer.core.animation_max_fps = 30.0 - viewer.launch() diff --git a/python/tutorial/405_AsRigidAsPossible.py b/python/tutorial/405_AsRigidAsPossible.py deleted file mode 100755 index 3dece5ead..000000000 --- a/python/tutorial/405_AsRigidAsPossible.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os -from math import sin, cos, pi - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -sea_green = igl.eigen.MatrixXd([[70. / 255., 252. / 255., 167. / 255.]]) - -V = igl.eigen.MatrixXd() -U = igl.eigen.MatrixXd() - -F = igl.eigen.MatrixXi() - -S = igl.eigen.MatrixXd() -b = igl.eigen.MatrixXi() - -mid = igl.eigen.MatrixXd() - -anim_t = 0.0 -anim_t_dir = 0.03 -arap_data = igl.ARAPData() - - -def pre_draw(viewer): - global anim_t - - bc = igl.eigen.MatrixXd(b.size(), V.cols()) - for i in range(0, b.size()): - bc.setRow(i, V.row(b[i])) - if S[b[i]] == 0: - r = mid[0] * 0.25 - bc[i, 0] += r * sin(0.5 * anim_t * 2. * pi) - bc[i, 1] = bc[i, 1] - r + r * cos(pi + 0.5 * anim_t * 2. * pi) - elif S[b[i]] == 1: - r = mid[1] * 0.15 - bc[i, 1] = bc[i, 1] + r + r * cos(pi + 0.15 * anim_t * 2. * pi) - bc[i, 2] -= r * sin(0.15 * anim_t * 2. * pi) - elif S[b[i]] == 2: - r = mid[1] * 0.15 - bc[i, 2] = bc[i, 2] + r + r * cos(pi + 0.35 * anim_t * 2. * pi) - bc[i, 0] += r * sin(0.35 * anim_t * 2. * pi) - - igl.arap_solve(bc, arap_data, U) - viewer.data().set_vertices(U) - viewer.data().compute_normals() - - if viewer.core.is_animating: - anim_t += anim_t_dir - - return False - - -def key_down(viewer, key, mods): - if key == ord(' '): - viewer.core.is_animating = not viewer.core.is_animating - return True - return False - - -igl.readOFF(TUTORIAL_SHARED_PATH + "decimated-knight.off", V, F) -U = igl.eigen.MatrixXd(V) -igl.readDMAT(TUTORIAL_SHARED_PATH + "decimated-knight-selection.dmat", S) - -# Vertices in selection - -b = igl.eigen.MatrixXd([[t[0] for t in [(i, S[i]) for i in range(0, V.rows())] if t[1] >= 0]]).transpose().castint() - -# Centroid -mid = 0.5 * (V.colwiseMaxCoeff() + V.colwiseMinCoeff()) - -# Precomputation -arap_data.max_iter = 100 -igl.arap_precomputation(V, F, V.cols(), b, arap_data) - -# Set color based on selection -C = igl.eigen.MatrixXd(F.rows(), 3) -purple = igl.eigen.MatrixXd([[80.0 / 255.0, 64.0 / 255.0, 255.0 / 255.0]]) -gold = igl.eigen.MatrixXd([[255.0 / 255.0, 228.0 / 255.0, 58.0 / 255.0]]) - -for f in range(0, F.rows()): - if S[F[f, 0]] >= 0 and S[F[f, 1]] >= 0 and S[F[f, 2]] >= 0: - C.setRow(f, purple) - else: - C.setRow(f, gold) - -# Plot the mesh with pseudocolors -viewer = igl.glfw.Viewer() -viewer.data().set_mesh(U, F) -viewer.data().set_colors(C) -viewer.callback_pre_draw = pre_draw -viewer.callback_key_down = key_down -viewer.core.is_animating = True -viewer.core.animation_max_fps = 30. -print("Press [space] to toggle animation") -viewer.launch() diff --git a/python/tutorial/501_HarmonicParam.py b/python/tutorial/501_HarmonicParam.py deleted file mode 100755 index e91d7d39a..000000000 --- a/python/tutorial/501_HarmonicParam.py +++ /dev/null @@ -1,70 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() -V_uv = igl.eigen.MatrixXd() - - -def key_down(viewer, key, modifier): - if key == ord('1'): - # Plot the 3D mesh - viewer.data().set_mesh(V, F) - viewer.core.align_camera_center(V, F) - elif key == ord('2'): - # Plot the mesh in 2D using the UV coordinates as vertex coordinates - viewer.data().set_mesh(V_uv, F) - viewer.core.align_camera_center(V_uv, F) - viewer.data().compute_normals() - return False - - -# Load a mesh in OFF format -igl.readOFF(TUTORIAL_SHARED_PATH + "camelhead.off", V, F) - -# Find the open boundary -bnd = igl.eigen.MatrixXi() -igl.boundary_loop(F, bnd) - -# Map the boundary to a circle, preserving edge proportions -bnd_uv = igl.eigen.MatrixXd() -igl.map_vertices_to_circle(V, bnd, bnd_uv) - -# Harmonic parametrization for the internal vertices -igl.harmonic(V, F, bnd, bnd_uv, 1, V_uv) - -# Scale UV to make the texture more clear -V_uv *= 5 - -# Plot the mesh -viewer = igl.glfw.Viewer() -viewer.data().set_mesh(V, F) -viewer.data().set_uv(V_uv) -viewer.callback_key_down = key_down - -# Disable wireframe -viewer.data().show_lines = False - -# Draw checkerboard texture -viewer.data().show_texture = True - -# Launch the viewer -viewer.launch() diff --git a/python/tutorial/502_LSCMParam.py b/python/tutorial/502_LSCMParam.py deleted file mode 100755 index 804a0a972..000000000 --- a/python/tutorial/502_LSCMParam.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() -V_uv = igl.eigen.MatrixXd() - - -def key_down(viewer, key, modifier): - if key == ord('1'): - # Plot the 3D mesh - viewer.data().set_mesh(V, F) - viewer.core.align_camera_center(V, F) - elif key == ord('2'): - # Plot the mesh in 2D using the UV coordinates as vertex coordinates - viewer.data().set_mesh(V_uv, F) - viewer.core.align_camera_center(V_uv, F) - viewer.data().compute_normals() - return False - - -# Load a mesh in OFF format -igl.readOFF(TUTORIAL_SHARED_PATH + "camelhead.off", V, F) - -# Fix two points on the boundary -bnd = igl.eigen.MatrixXi() -b = igl.eigen.MatrixXi(2, 1) - -igl.boundary_loop(F, bnd) -b[0] = bnd[0] -b[1] = bnd[int(bnd.size() / 2)] -bc = igl.eigen.MatrixXd([[0, 0], [1, 0]]) - -# LSCM parametrization -igl.lscm(V, F, b, bc, V_uv) - -# Scale the uv -V_uv *= 5 - -# Plot the mesh -viewer = igl.glfw.Viewer() -viewer.data().set_mesh(V, F) -viewer.data().set_uv(V_uv) -viewer.callback_key_down = key_down - -# Disable wireframe -viewer.data().show_lines = False - -# Draw checkerboard texture -viewer.data().show_texture = True - -# Launch the viewer -viewer.launch() diff --git a/python/tutorial/503_ARAPParam.py b/python/tutorial/503_ARAPParam.py deleted file mode 100755 index d026d967f..000000000 --- a/python/tutorial/503_ARAPParam.py +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() -V_uv = igl.eigen.MatrixXd() -initial_guess = igl.eigen.MatrixXd() - -show_uv = False - - -def key_down(viewer, key, modifier): - global show_uv, V_uv - if key == ord('1'): - show_uv = False - elif key == ord('2'): - show_uv = True - elif key == ord('q'): - V_uv = initial_guess - - if show_uv: - viewer.data().set_mesh(V_uv, F) - viewer.core.align_camera_center(V_uv, F) - else: - viewer.data().set_mesh(V, F) - viewer.core.align_camera_center(V, F) - - viewer.data().compute_normals() - return False - - -# Load a mesh in OFF format -igl.readOFF(TUTORIAL_SHARED_PATH + "camelhead.off", V, F) - -# Compute the initial solution for ARAP (harmonic parametrization) -bnd = igl.eigen.MatrixXi() -igl.boundary_loop(F, bnd) -bnd_uv = igl.eigen.MatrixXd() -igl.map_vertices_to_circle(V, bnd, bnd_uv) - -igl.harmonic(V, F, bnd, bnd_uv, 1, initial_guess) - -# Add dynamic regularization to avoid to specify boundary conditions -arap_data = igl.ARAPData() -arap_data.with_dynamics = True -b = igl.eigen.MatrixXi.Zero(0, 0) -bc = igl.eigen.MatrixXd.Zero(0, 0) - -# Initialize ARAP -arap_data.max_iter = 100 - -# 2 means that we're going to *solve* in 2d -igl.arap_precomputation(V, F, 2, b, arap_data) - -# Solve arap using the harmonic map as initial guess -V_uv = igl.eigen.MatrixXd(initial_guess) # important, make a copy of it! - -igl.arap_solve(bc, arap_data, V_uv) - -# Scale UV to make the texture more clear -V_uv *= 20 - -# Plot the mesh -viewer = igl.glfw.Viewer() -viewer.data().set_mesh(V, F) -viewer.data().set_uv(V_uv) -viewer.callback_key_down = key_down - -# Disable wireframe -viewer.data().show_lines = False - -# Draw checkerboard texture -viewer.data().show_texture = True - -# Launch the viewer -viewer.launch() diff --git a/python/tutorial/504_NRosyDesign.py b/python/tutorial/504_NRosyDesign.py deleted file mode 100755 index 7236ba3d1..000000000 --- a/python/tutorial/504_NRosyDesign.py +++ /dev/null @@ -1,131 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os -from math import atan2, pi, cos, sin - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["comiso", "glfw"] -check_dependencies(dependencies) - - -# Mesh -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() - -# Constrained faces id -b = igl.eigen.MatrixXi() - -# Constrained faces representative vector -bc = igl.eigen.MatrixXd() - -# Degree of the N-RoSy field -N = 4 - - -# Converts a representative vector per face in the full set of vectors that describe -# an N-RoSy field -def representative_to_nrosy(V, F, R, N, Y): - B1 = igl.eigen.MatrixXd() - B2 = igl.eigen.MatrixXd() - B3 = igl.eigen.MatrixXd() - - igl.local_basis(V, F, B1, B2, B3) - - Y.resize(F.rows() * N, 3) - - for i in range(0, F.rows()): - x = R.row(i) * B1.row(i).transpose() - y = R.row(i) * B2.row(i).transpose() - angle = atan2(y[0], x[0]) - - for j in range(0, N): - anglej = angle + 2 * pi * j / float(N) - xj = cos(anglej) - yj = sin(anglej) - Y.setRow(i * N + j, xj * B1.row(i) + yj * B2.row(i)) - - -# Plots the mesh with an N-RoSy field and its singularities on top -# The constrained faces (b) are colored in red. -def plot_mesh_nrosy(viewer, V, F, N, PD1, S, b): - # Clear the mesh - viewer.data().clear() - viewer.data().set_mesh(V, F) - - # Expand the representative vectors in the full vector set and plot them as lines - avg = igl.avg_edge_length(V, F) - Y = igl.eigen.MatrixXd() - representative_to_nrosy(V, F, PD1, N, Y) - - B = igl.eigen.MatrixXd() - igl.barycenter(V, F, B) - - Be = igl.eigen.MatrixXd(B.rows() * N, 3) - for i in range(0, B.rows()): - for j in range(0, N): - Be.setRow(i * N + j, B.row(i)) - - viewer.data().add_edges(Be, Be + Y * (avg / 2), igl.eigen.MatrixXd([[0, 0, 1]])) - - # Plot the singularities as colored dots (red for negative, blue for positive) - for i in range(0, S.size()): - if S[i] < -0.001: - viewer.data().add_points(V.row(i), igl.eigen.MatrixXd([[1, 0, 0]])) - elif S[i] > 0.001: - viewer.data().add_points(V.row(i), igl.eigen.MatrixXd([[0, 1, 0]])); - - # Highlight in red the constrained faces - C = igl.eigen.MatrixXd.Constant(F.rows(), 3, 1) - for i in range(0, b.size()): - C.setRow(b[i], igl.eigen.MatrixXd([[1, 0, 0]])) - viewer.data().set_colors(C) - - -# It allows to change the degree of the field when a number is pressed -def key_down(viewer, key, modifier): - global N - if ord('1') <= key <= ord('9'): - N = key - ord('0') - - R = igl.eigen.MatrixXd() - S = igl.eigen.MatrixXd() - - igl.comiso.nrosy(V, F, b, bc, igl.eigen.MatrixXi(), igl.eigen.MatrixXd(), igl.eigen.MatrixXd(), N, 0.5, R, S) - plot_mesh_nrosy(viewer, V, F, N, R, S, b) - - return False - - -# Load a mesh in OFF format -igl.readOFF(TUTORIAL_SHARED_PATH + "bumpy.off", V, F) - -# Threshold faces with high anisotropy -b = igl.eigen.MatrixXd([[0]]).castint() -bc = igl.eigen.MatrixXd([[1, 1, 1]]) - -viewer = igl.glfw.Viewer() - -# Interpolate the field and plot -key_down(viewer, ord('4'), 0) - -# Plot the mesh -viewer.data().set_mesh(V, F) -viewer.callback_key_down = key_down - -# Disable wireframe -viewer.data().show_lines = False - -# Launch the viewer -viewer.launch() diff --git a/python/tutorial/505_MIQ.py b/python/tutorial/505_MIQ.py deleted file mode 100755 index 3d62f19be..000000000 --- a/python/tutorial/505_MIQ.py +++ /dev/null @@ -1,282 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os -from math import pi - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["comiso", "glfw"] -check_dependencies(dependencies) - - -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() - -# Face barycenters -B = igl.eigen.MatrixXd() - -# Scale for visualizing the fields -global_scale = 1 -extend_arrows = False - -# Cross field -X1 = igl.eigen.MatrixXd() -X2 = igl.eigen.MatrixXd() - -# Bisector field -BIS1 = igl.eigen.MatrixXd() -BIS2 = igl.eigen.MatrixXd() - -# Combed bisector -BIS1_combed = igl.eigen.MatrixXd() -BIS2_combed = igl.eigen.MatrixXd() - -# Per-corner, integer mismatches -MMatch = igl.eigen.MatrixXi() - -# Field singularities -isSingularity = igl.eigen.MatrixXi() -singularityIndex = igl.eigen.MatrixXi() - -# Per corner seams -Seams = igl.eigen.MatrixXi() - -# Combed field -X1_combed = igl.eigen.MatrixXd() -X2_combed = igl.eigen.MatrixXd() - -# Global parametrization (with seams) -UV_seams = igl.eigen.MatrixXd() -FUV_seams = igl.eigen.MatrixXi() - -# Global parametrization -UV = igl.eigen.MatrixXd() -FUV = igl.eigen.MatrixXi() - -# Texture -texture_R = igl.eigen.MatrixXuc() -texture_G = igl.eigen.MatrixXuc() -texture_B = igl.eigen.MatrixXuc() - - -# Create a texture that hides the integer translation in the parametrization -def line_texture(): - size = 128 - size2 = int(size / 2) - lineWidth = 3 - texture_R.setConstant(size, size, 255) - - for i in range(0, size): - for j in range(size2 - lineWidth, size2 + lineWidth + 1): - texture_R[i, j] = 0 - - for i in range(size2 - lineWidth, size2 + lineWidth + 1): - for j in range(0, size): - texture_R[i, j] = 0 - - texture_G = texture_R.copy() - texture_B = texture_R.copy() - return (texture_R, texture_G, texture_B) - - -def key_down(viewer, key, modifier): - global extend_arrows, texture_R, texture_G, texture_B - - if key == ord('E'): - extend_arrows = not extend_arrows - - if key < ord('1') or key > ord('8'): - return False - - viewer.data().clear() - viewer.data().show_lines = False - viewer.data().show_texture = False - - if key == ord('1'): - # Cross field - viewer.data().set_mesh(V, F) - viewer.data().add_edges(B - global_scale * X1 if extend_arrows else B, B + global_scale * X1, - igl.eigen.MatrixXd([[1, 0, 0]])) - viewer.data().add_edges(B - global_scale * X2 if extend_arrows else B, B + global_scale * X2, - igl.eigen.MatrixXd([[0, 0, 1]])) - - if key == ord('2'): - # Bisector field - viewer.data().set_mesh(V, F) - viewer.data().add_edges(B - global_scale * BIS1 if extend_arrows else B, B + global_scale * BIS1, - igl.eigen.MatrixXd([[1, 0, 0]])) - viewer.data().add_edges(B - global_scale * BIS2 if extend_arrows else B, B + global_scale * BIS2, - igl.eigen.MatrixXd([[0, 0, 1]])) - - if key == ord('3'): - # Bisector field combed - viewer.data().set_mesh(V, F) - viewer.data().add_edges(B - global_scale * BIS1_combed if extend_arrows else B, B + global_scale * BIS1_combed, - igl.eigen.MatrixXd([[1, 0, 0]])) - viewer.data().add_edges(B - global_scale * BIS2_combed if extend_arrows else B, B + global_scale * BIS2_combed, - igl.eigen.MatrixXd([[0, 0, 1]])) - - if key == ord('4'): - # Singularities and cuts - viewer.data().set_mesh(V, F) - - # Plot cuts - l_count = Seams.sum() - P1 = igl.eigen.MatrixXd(l_count, 3) - P2 = igl.eigen.MatrixXd(l_count, 3) - - for i in range(0, Seams.rows()): - for j in range(0, Seams.cols()): - if Seams[i, j] != 0: - P1.setRow(l_count - 1, V.row(F[i, j])) - P2.setRow(l_count - 1, V.row(F[i, (j + 1) % 3])) - l_count -= 1 - - viewer.data().add_edges(P1, P2, igl.eigen.MatrixXd([[1, 0, 0]])) - - # Plot the singularities as colored dots (red for negative, blue for positive) - for i in range(0, singularityIndex.size()): - if 2 > singularityIndex[i] > 0: - viewer.data().add_points(V.row(i), igl.eigen.MatrixXd([[1, 0, 0]])) - elif singularityIndex[i] > 2: - viewer.data().add_points(V.row(i), igl.eigen.MatrixXd([[1, 0, 0]])) - - if key == ord('5'): - # Singularities and cuts, original field - # Singularities and cuts - viewer.data().set_mesh(V, F) - viewer.data().add_edges(B - global_scale * X1_combed if extend_arrows else B, B + global_scale * X1_combed, - igl.eigen.MatrixXd([[1, 0, 0]])) - viewer.data().add_edges(B - global_scale * X2_combed if extend_arrows else B, B + global_scale * X2_combed, - igl.eigen.MatrixXd([[0, 0, 1]])) - - # Plot cuts - l_count = Seams.sum() - - P1 = igl.eigen.MatrixXd(l_count, 3) - P2 = igl.eigen.MatrixXd(l_count, 3) - - for i in range(0, Seams.rows()): - for j in range(0, Seams.cols()): - if Seams[i, j] != 0: - P1.setRow(l_count - 1, V.row(F[i, j])) - P2.setRow(l_count - 1, V.row(F[i, (j + 1) % 3])) - l_count -= 1 - - viewer.data().add_edges(P1, P2, igl.eigen.MatrixXd([[1, 0, 0]])) - - # Plot the singularities as colored dots (red for negative, blue for positive) - for i in range(0, singularityIndex.size()): - if 2 > singularityIndex[i] > 0: - viewer.data().add_points(V.row(i), igl.eigen.MatrixXd([[1, 0, 0]])) - elif singularityIndex[i] > 2: - viewer.data().add_points(V.row(i), igl.eigen.MatrixXd([[0, 1, 0]])) - - if key == ord('6'): - # Global parametrization UV - viewer.data().set_mesh(UV, FUV) - viewer.data().set_uv(UV) - viewer.data().show_lines = True - - if key == ord('7'): - # Global parametrization in 3D - viewer.data().set_mesh(V, F) - viewer.data().set_uv(UV, FUV) - viewer.data().show_texture = True - - if key == ord('8'): - # Global parametrization in 3D with seams - viewer.data().set_mesh(V, F) - viewer.data().set_uv(UV_seams, FUV_seams) - viewer.data().show_texture = True - - viewer.data().set_colors(igl.eigen.MatrixXd([[1, 1, 1]])) - - viewer.data().set_texture(texture_R, texture_B, texture_G) - - viewer.core.align_camera_center(viewer.data().V, viewer.data().F) - - return False - - -# Load a mesh in OFF format -igl.readOFF(TUTORIAL_SHARED_PATH + "3holes.off", V, F) - -# Compute face barycenters -igl.barycenter(V, F, B) - -# Compute scale for visualizing fields -global_scale = .5 * igl.avg_edge_length(V, F) - -# Contrain one face -b = igl.eigen.MatrixXd([[0]]).castint() -bc = igl.eigen.MatrixXd([[1, 0, 0]]) - -# Create a smooth 4-RoSy field -S = igl.eigen.MatrixXd() - -igl.comiso.nrosy(V, F, b, bc, igl.eigen.MatrixXi(), igl.eigen.MatrixXd(), igl.eigen.MatrixXd(), 4, 0.5, X1, S) - -# Find the orthogonal vector -B1 = igl.eigen.MatrixXd() -B2 = igl.eigen.MatrixXd() -B3 = igl.eigen.MatrixXd() - -igl.local_basis(V, F, B1, B2, B3) - -X2 = igl.rotate_vectors(X1, igl.eigen.MatrixXd.Constant(1, 1, pi / 2), B1, B2) - -gradient_size = 50 -iterations = 0 -stiffness = 5.0 -direct_round = False - -# Always work on the bisectors, it is more general -igl.compute_frame_field_bisectors(V, F, X1, X2, BIS1, BIS2) - -# Comb the field, implicitly defining the seams -igl.comb_cross_field(V, F, BIS1, BIS2, BIS1_combed, BIS2_combed) - -# Find the integer mismatches -igl.cross_field_missmatch(V, F, BIS1_combed, BIS2_combed, True, MMatch) - -# Find the singularities -igl.find_cross_field_singularities(V, F, MMatch, isSingularity, singularityIndex) - -# Cut the mesh, duplicating all vertices on the seams -igl.cut_mesh_from_singularities(V, F, MMatch, Seams) - -# Comb the frame-field accordingly -igl.comb_frame_field(V, F, X1, X2, BIS1_combed, BIS2_combed, X1_combed, X2_combed) - -# Global parametrization -igl.comiso.miq(V, F, X1_combed, X2_combed, MMatch, isSingularity, Seams, UV, FUV, gradient_size, stiffness, - direct_round, iterations, 5, True, True) - -# Global parametrization (with seams, only for demonstration) -igl.comiso.miq(V, F, X1_combed, X2_combed, MMatch, isSingularity, Seams, UV_seams, FUV_seams, gradient_size, - stiffness, direct_round, iterations, 5, False) - -# Plot the mesh -viewer = igl.glfw.Viewer() - -# Replace the standard texture with an integer shift invariant texture -(texture_R, texture_G, texture_B) = line_texture() - -# Plot the original mesh with a texture parametrization -key_down(viewer, ord('7'), 0) - -# Launch the viewer -viewer.callback_key_down = key_down -viewer.launch() diff --git a/python/tutorial/507_Planarization.py b/python/tutorial/507_Planarization.py deleted file mode 100755 index dda4d2a29..000000000 --- a/python/tutorial/507_Planarization.py +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -viewer = igl.glfw.Viewer() - -# Quad mesh generated from conjugate field -VQC = igl.eigen.MatrixXd() -FQC = igl.eigen.MatrixXi() -FQCtri = igl.eigen.MatrixXi() -PQC0 = igl.eigen.MatrixXd() -PQC1 = igl.eigen.MatrixXd() -PQC2 = igl.eigen.MatrixXd() -PQC3 = igl.eigen.MatrixXd() - -# Planarized quad mesh -VQCplan = igl.eigen.MatrixXd() -FQCtriplan = igl.eigen.MatrixXi() -PQC0plan = igl.eigen.MatrixXd() -PQC1plan = igl.eigen.MatrixXd() -PQC2plan = igl.eigen.MatrixXd() -PQC3plan = igl.eigen.MatrixXd() - - -def key_down(viewer, key, modifier): - if key == ord('1'): - # Draw the triangulated quad mesh - viewer.data().set_mesh(VQC, FQCtri) - - # Assign a color to each quad that corresponds to its planarity - planarity = igl.eigen.MatrixXd() - igl.quad_planarity(VQC, FQC, planarity) - Ct = igl.eigen.MatrixXd() - igl.jet(planarity, 0, 0.01, Ct) - C = igl.eigen.MatrixXd(FQCtri.rows(), 3) - C.setTopRows(Ct.rows(), Ct) - C.setBottomRows(Ct.rows(), Ct) - viewer.data().set_colors(C) - - # Plot a line for each edge of the quad mesh - viewer.data().add_edges(PQC0, PQC1, igl.eigen.MatrixXd([[0, 0, 0]])) - viewer.data().add_edges(PQC1, PQC2, igl.eigen.MatrixXd([[0, 0, 0]])) - viewer.data().add_edges(PQC2, PQC3, igl.eigen.MatrixXd([[0, 0, 0]])) - viewer.data().add_edges(PQC3, PQC0, igl.eigen.MatrixXd([[0, 0, 0]])) - - elif key == ord('2'): - # Draw the planar quad mesh - viewer.data().set_mesh(VQCplan, FQCtri) - - # Assign a color to each quad that corresponds to its planarity - planarity = igl.eigen.MatrixXd() - igl.quad_planarity(VQCplan, FQC, planarity) - Ct = igl.eigen.MatrixXd() - igl.jet(planarity, 0, 0.01, Ct) - C = igl.eigen.MatrixXd(FQCtri.rows(), 3) - C.setTopRows(Ct.rows(), Ct) - C.setBottomRows(Ct.rows(), Ct) - viewer.data().set_colors(C) - - # Plot a line for each edge of the quad mesh - viewer.data().add_edges(PQC0plan, PQC1plan, igl.eigen.MatrixXd([[0, 0, 0]])) - viewer.data().add_edges(PQC1plan, PQC2plan, igl.eigen.MatrixXd([[0, 0, 0]])) - viewer.data().add_edges(PQC2plan, PQC3plan, igl.eigen.MatrixXd([[0, 0, 0]])) - viewer.data().add_edges(PQC3plan, PQC0plan, igl.eigen.MatrixXd([[0, 0, 0]])) - - else: - return False - - return True - - -# Load a quad mesh generated by a conjugate field -igl.readOFF(TUTORIAL_SHARED_PATH + "inspired_mesh_quads_Conjugate.off", VQC, FQC) - -# Convert it to a triangle mesh -FQCtri.resize(2 * FQC.rows(), 3) - -FQCtriUpper = igl.eigen.MatrixXi(FQC.rows(), 3) -FQCtriLower = igl.eigen.MatrixXi(FQC.rows(), 3) - -FQCtriUpper.setCol(0, FQC.col(0)) -FQCtriUpper.setCol(1, FQC.col(1)) -FQCtriUpper.setCol(2, FQC.col(2)) -FQCtriLower.setCol(0, FQC.col(2)) -FQCtriLower.setCol(1, FQC.col(3)) -FQCtriLower.setCol(2, FQC.col(0)) - -FQCtri.setTopRows(FQCtriUpper.rows(), FQCtriUpper) -FQCtri.setBottomRows(FQCtriLower.rows(), FQCtriLower) - -igl.slice(VQC, FQC.col(0), 1, PQC0) -igl.slice(VQC, FQC.col(1), 1, PQC1) -igl.slice(VQC, FQC.col(2), 1, PQC2) -igl.slice(VQC, FQC.col(3), 1, PQC3) - -# Planarize it -igl.planarize_quad_mesh(VQC, FQC, 100, 0.005, VQCplan) - -# Convert the planarized mesh to triangles -igl.slice(VQCplan, FQC.col(0), 1, PQC0plan) -igl.slice(VQCplan, FQC.col(1), 1, PQC1plan) -igl.slice(VQCplan, FQC.col(2), 1, PQC2plan) -igl.slice(VQCplan, FQC.col(3), 1, PQC3plan) - -# Launch the viewer -key_down(viewer, ord('2'), 0) -viewer.data().invert_normals = True -viewer.data().show_lines = False -viewer.callback_key_down = key_down -viewer.launch() diff --git a/python/tutorial/604_Triangle.py b/python/tutorial/604_Triangle.py deleted file mode 100755 index b872ea41a..000000000 --- a/python/tutorial/604_Triangle.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import check_dependencies - -dependencies = ["triangle", "glfw"] -check_dependencies(dependencies) - - -# Input polygon -V = igl.eigen.MatrixXd([[-1, -1], [1, -1], [1, 1], [-1, 1], [-2, -2], [2, -2], [2, 2], [-2, 2]]) -E = igl.eigen.MatrixXd([[0, 1], [1, 2], [2, 3], [3, 0], [4, 5], [5, 6], [6,7], [7,4]]).castint() -H = igl.eigen.MatrixXd([[0, 0]]) - -# Triangulated Interior -V2 = igl.eigen.MatrixXd() -F2 = igl.eigen.MatrixXi() - -igl.triangle.triangulate(V, E, H, "a0.005q", V2, F2) - -# Plot the mesh -viewer = igl.glfw.Viewer() -viewer.data().set_mesh(V2, F2) -viewer.launch() diff --git a/python/tutorial/605_Tetgen.py b/python/tutorial/605_Tetgen.py deleted file mode 100755 index b4d2084ea..000000000 --- a/python/tutorial/605_Tetgen.py +++ /dev/null @@ -1,83 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["tetgen", "glfw"] -check_dependencies(dependencies) - - -# Input polygon -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() -B = igl.eigen.MatrixXd() - -# Tetrahedralized interior -TV = igl.eigen.MatrixXd() -TT = igl.eigen.MatrixXi() -TF = igl.eigen.MatrixXi() - -viewer = igl.glfw.Viewer() - - -def key_down(viewer, key, modifier): - if key >= ord('1') and key <= ord('9'): - t = float((key - ord('1')) + 1) / 9.0 - v = igl.eigen.MatrixXd() - v = B.col(2) - B.col(2).minCoeff() - v /= v.col(0).maxCoeff() - - s = [] - for i in range(v.size()): - if v[i, 0] < t: - s.append(i) - - V_temp = igl.eigen.MatrixXd(len(s) * 4, 3) - F_temp = igl.eigen.MatrixXd(len(s) * 4, 3).castint() - - for i in range(len(s)): - V_temp.setRow(i * 4 + 0, TV.row(TT[s[i], 0])) - V_temp.setRow(i * 4 + 1, TV.row(TT[s[i], 1])) - V_temp.setRow(i * 4 + 2, TV.row(TT[s[i], 2])) - V_temp.setRow(i * 4 + 3, TV.row(TT[s[i], 3])) - - F_temp.setRow(i * 4 + 0, igl.eigen.MatrixXd([[(i*4)+0, (i*4)+1, (i*4)+3]]).castint()) - F_temp.setRow(i * 4 + 1, igl.eigen.MatrixXd([[(i*4)+0, (i*4)+2, (i*4)+1]]).castint()) - F_temp.setRow(i * 4 + 2, igl.eigen.MatrixXd([[(i*4)+3, (i*4)+2, (i*4)+0]]).castint()) - F_temp.setRow(i * 4 + 3, igl.eigen.MatrixXd([[(i*4)+1, (i*4)+2, (i*4)+3]]).castint()) - - viewer.data().clear() - viewer.data().set_mesh(V_temp, F_temp) - viewer.data().set_face_based(True) - - else: - return False - - return True - - -# Load a surface mesh -igl.readOFF(TUTORIAL_SHARED_PATH + "fertility.off", V, F) - -# Tetrahedralize the interior -igl.tetgen.tetrahedralize(V, F, "pq1.414Y", TV, TT, TF) - -# Compute barycenters -igl.barycenter(TV, TT, B) - -# Plot the generated mesh -key_down(viewer, ord('5'), 0) -viewer.callback_key_down = key_down -viewer.launch() diff --git a/python/tutorial/606_AmbientOcclusion.py b/python/tutorial/606_AmbientOcclusion.py deleted file mode 100755 index c50e45e00..000000000 --- a/python/tutorial/606_AmbientOcclusion.py +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["embree", "glfw"] -check_dependencies(dependencies) - - -# Mesh + AO values + Normals -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() -AO = igl.eigen.MatrixXd() -N = igl.eigen.MatrixXd() - - -viewer = igl.glfw.Viewer() - - -def key_down(viewer, key, modifier): - - color = igl.eigen.MatrixXd([[0.9, 0.85, 0.9]]) - - if key == ord('1'): - # Show the mesh without the ambient occlusion factor - viewer.data().set_colors(color) - elif key == ord('2'): - # Show the mesh with the ambient occlusion factor - C = color.replicate(V.rows(), 1) - for i in range(C.rows()): - C.setRow(i, C.row(i) * AO[i, 0]) - viewer.data().set_colors(C) - elif key == ord('.'): - viewer.core.lighting_factor += 0.1 - elif key == ord(','): - viewer.core.lighting_factor -= 0.1 - else: - return False - - viewer.core.lighting_factor = min(max(viewer.core.lighting_factor, 0.0), 1.0) - return True - - -print("Press 1 to turn off Ambient Occlusion\nPress 2 to turn on Ambient Occlusion\nPress . to turn up lighting\nPress , to turn down lighting") - -# Load a surface mesh -igl.readOFF(TUTORIAL_SHARED_PATH + "fertility.off", V, F) - -# Calculate vertex normals -igl.per_vertex_normals(V, F, N) - -# Compute ambient occlusion factor using embree -igl.embree.ambient_occlusion(V, F, V, N, 500, AO) -AO = 1.0 - AO - -# Plot the generated mesh -viewer.data().set_mesh(V, F) -key_down(viewer, ord('2'), 0) -viewer.callback_key_down = key_down -viewer.data().show_lines = False -viewer.core.lighting_factor = 0.0 -viewer.launch() diff --git a/python/tutorial/607_ScreenCapture.py b/python/tutorial/607_ScreenCapture.py deleted file mode 100755 index f9e8a1906..000000000 --- a/python/tutorial/607_ScreenCapture.py +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["png", "glfw"] -check_dependencies(dependencies) - -temp_png = os.path.join(os.getcwd(),"out.png") - -def key_down(viewer, key, modifier): - if key == ord('1'): - # Allocate temporary buffers - R = igl.eigen.MatrixXuc(1280, 800) - G = igl.eigen.MatrixXuc(1280, 800) - B = igl.eigen.MatrixXuc(1280, 800) - A = igl.eigen.MatrixXuc(1280, 800) - - # Draw the scene in the buffers - viewer.core.draw_buffer(viewer.data(), False, R, G, B, A) - - # Save it to a PNG - igl.png.writePNG(R, G, B, A, temp_png) - elif key == ord('2'): - # Allocate temporary buffers - R = igl.eigen.MatrixXuc() - G = igl.eigen.MatrixXuc() - B = igl.eigen.MatrixXuc() - A = igl.eigen.MatrixXuc() - - # Read the PNG - igl.png.readPNG(temp_png, R, G, B, A) - - # Replace the mesh with a triangulated square - V = igl.eigen.MatrixXd([[-0.5, -0.5, 0], - [0.5, -0.5, 0], - [0.5, 0.5, 0], - [-0.5, 0.5, 0]]) - - F = igl.eigen.MatrixXd([[0, 1, 2], [2, 3, 0]]).castint() - - UV = igl.eigen.MatrixXd([[0, 0], [1, 0], [1, 1], [0, 1]]) - - viewer.data().clear() - viewer.data().set_mesh(V, F) - viewer.data().set_uv(UV) - viewer.core.align_camera_center(V) - viewer.data().show_texture = True - - # Use the image as a texture - viewer.data().set_texture(R, G, B) - - else: - return False - - return True - - -if __name__ == "__main__": - V = igl.eigen.MatrixXd() - F = igl.eigen.MatrixXi() - - # Load meshes in OFF format - igl.readOFF(TUTORIAL_SHARED_PATH + "bunny.off", V, F) - - viewer = igl.glfw.Viewer() - - print( - "Usage: Press 1 to render the scene and save it in a png. \nPress 2 to load the saved png and use it as a texture.") - - viewer.callback_key_down = key_down - viewer.data().set_mesh(V, F) - viewer.launch() - - os.remove(temp_png) diff --git a/python/tutorial/609_Boolean.py b/python/tutorial/609_Boolean.py deleted file mode 100755 index d69b25783..000000000 --- a/python/tutorial/609_Boolean.py +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["cgal", "glfw"] -check_dependencies(dependencies) - -boolean_type_names = {igl.MESH_BOOLEAN_TYPE_UNION: "Union", igl.MESH_BOOLEAN_TYPE_INTERSECT: "Intersect", igl.MESH_BOOLEAN_TYPE_MINUS: "Minus", igl.MESH_BOOLEAN_TYPE_XOR: "XOR", igl.MESH_BOOLEAN_TYPE_RESOLVE: "Resolve"} - -boolean_types = list(boolean_type_names.keys()) - - - - -def update(viewer): - print("Calculating A %s B..." % boolean_type_names[boolean_type]) - igl.cgal.mesh_boolean(VA, FA, VB, FB, boolean_type, VC, FC, J) - C = igl.eigen.MatrixXd(FC.rows(), 3) - - for f in range(C.rows()): - if J[f] < FA.rows(): - C.setRow(f, Red) - else: - C.setRow(f, Green) - - viewer.data().clear() - viewer.data().set_mesh(VC, FC) - viewer.data().set_colors(C) - print("Done.") - - -def key_down(viewer, key, modifier): - global boolean_type - - if key == ord('.'): - boolean_type = boolean_types[(boolean_types.index(boolean_type) + 1) % (len(boolean_types))] - elif key == ord(','): - boolean_type = boolean_types[(boolean_types.index(boolean_type) + len(boolean_types) - 1) % len(boolean_types)] - elif key == ord('['): - viewer.core.camera_dnear -= 0.1 - elif key == ord(']'): - viewer.core.camera_dnear += 0.1 - else: - return False - - update(viewer) - - return False - - -if __name__ == "__main__": - - VA = igl.eigen.MatrixXd() - FA = igl.eigen.MatrixXi() - VB = igl.eigen.MatrixXd() - FB = igl.eigen.MatrixXi() - VC = igl.eigen.MatrixXd() - FC = igl.eigen.MatrixXi() - J = igl.eigen.MatrixXi() - - Red = igl.eigen.MatrixXd([[1, 0, 0]]) - Green = igl.eigen.MatrixXd([[0, 1, 0]]) - - # Load meshes in OFF format - igl.readOFF(TUTORIAL_SHARED_PATH + "cheburashka.off", VA, FA) - igl.readOFF(TUTORIAL_SHARED_PATH + "decimated-knight.off", VB, FB) - - boolean_type = igl.MESH_BOOLEAN_TYPE_UNION - - viewer = igl.glfw.Viewer() - update(viewer) - - print( - "Usage: Press '.' to switch to next boolean operation type. \nPress ',' to switch to previous boolean operation type. \nPress ']' to push near cutting plane away from camera. \nPress '[' to pull near cutting plane closer to camera. \nHint: investigate _inside_ the model to see orientation changes. \n") - - viewer.data().show_lines = True - viewer.callback_key_down = key_down - viewer.core.camera_dnear = 3.9 - viewer.launch() diff --git a/python/tutorial/701_Statistics.py b/python/tutorial/701_Statistics.py deleted file mode 100755 index ffd22b633..000000000 --- a/python/tutorial/701_Statistics.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -import math - -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = [] -check_dependencies(dependencies) - -if __name__ == "__main__": - V = igl.eigen.MatrixXd() - F = igl.eigen.MatrixXi() - - # Load meshes in OFF format - igl.readOBJ(TUTORIAL_SHARED_PATH + "horse_quad.obj", V, F) - - # Count the number of irregular vertices, the border is ignored - irregular = igl.is_irregular_vertex(V, F) - vertex_count = V.rows() - irregular_vertex_count = sum(irregular) - irregular_ratio = irregular_vertex_count / vertex_count - - print("Irregular vertices: \n%d/%d (%.2f%%)\n" % ( - irregular_vertex_count, vertex_count, irregular_ratio * 100)) - - # Compute areas, min, max and standard deviation - area = igl.eigen.MatrixXd() - igl.doublearea(V, F, area) - area /= 2.0 - - area_avg = area.mean() - area_min = area.minCoeff() / area_avg - area_max = area.maxCoeff() / area_avg - area_ns = (area - area_avg) / area_avg - area_sigma = math.sqrt(area_ns.squaredMean()) - - print("Areas (Min/Max)/Avg_Area Sigma: \n%.2f/%.2f (%.2f)\n" % ( - area_min, area_max, area_sigma)) - - # Compute per face angles, min, max and standard deviation - angles = igl.eigen.MatrixXd() - igl.internal_angles(V, F, angles) - angles = 360.0 * (angles / (2 * math.pi)) - - angle_avg = angles.mean() - angle_min = angles.minCoeff() - angle_max = angles.maxCoeff() - angle_ns = angles - angle_avg - angle_sigma = math.sqrt(angle_ns.squaredMean()) - - print("Angles in degrees (Min/Max) Sigma: \n%.2f/%.2f (%.2f)\n" % ( - angle_min, angle_max, angle_sigma)) diff --git a/python/tutorial/702_WindingNumber.py b/python/tutorial/702_WindingNumber.py deleted file mode 100755 index 76a407e8d..000000000 --- a/python/tutorial/702_WindingNumber.py +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies, print_usage - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -def append_mesh(C_vis, F_vis, V_vis, V, F, color): - F_vis.conservativeResize(F_vis.rows() + F.rows(), 3) - F_vis.setBottomRows(F.rows(), F + V_vis.rows()) - V_vis.conservativeResize(V_vis.rows() + V.rows(), 3) - V_vis.setBottomRows(V.rows(), V) - C_vis.conservativeResize(C_vis.rows() + F.rows(), 3) - colorM = igl.eigen.MatrixXd(F.rows(), C_vis.cols()) - colorM.rowwiseSet(color) - C_vis.setBottomRows(F.rows(), colorM) - - -def update(viewer): - global V, F, T, W, slice_z, overlay - plane = igl.eigen.MatrixXd([0, 0, 1, -((1 - slice_z) * V.col(2).minCoeff() + slice_z * V.col(2).maxCoeff())]) - V_vis = igl.eigen.MatrixXd() - F_vis = igl.eigen.MatrixXi() - J = igl.eigen.MatrixXi() - bary = igl.eigen.SparseMatrixd() - igl.marching_tets(V, T, plane, V_vis, F_vis, J, bary) - W_vis = igl.eigen.MatrixXd() - igl.slice(W, J, W_vis) - C_vis = igl.eigen.MatrixXd() - igl.parula(W_vis, False, C_vis) - - if overlay == 1: # OVERLAY_INPUT - append_mesh(C_vis, F_vis, V_vis, V, F, igl.eigen.MatrixXd([[1., 0.894, 0.227]])) - elif overlay == 2: # OVERLAY_OUTPUT - append_mesh(C_vis, F_vis, V_vis, V, F, igl.eigen.MatrixXd([[0.8, 0.8, 0.8]])) - - viewer.data().clear() - viewer.data().set_mesh(V_vis, F_vis) - viewer.data().set_colors(C_vis) - viewer.data().set_face_based(True) - - -def key_down(viewer, key, modifier): - global overlay, slice_z - - if key == ord(' '): - overlay = (overlay + 1) % 3 - elif key == ord('.'): - slice_z = min(slice_z + 0.01, 0.99) - elif key == ord(','): - slice_z = max(slice_z - 0.01, 0.01) - - update(viewer) - - return False - - -if __name__ == "__main__": - keys = {"space": "toggle showing input mesh, output mesh or slice through tet-mesh of convex hull", - ". / ,": "push back/pull forward slicing plane"} - - print_usage(keys) - - V = igl.eigen.MatrixXd() - BC = igl.eigen.MatrixXd() - W = igl.eigen.MatrixXd() - T = igl.eigen.MatrixXi() - F = igl.eigen.MatrixXi() - G = igl.eigen.MatrixXi() - - slice_z = 0.5 - overlay = 0 - - # Load mesh: (V,T) tet-mesh of convex hull, F contains facets of input - # surface mesh _after_ self-intersection resolution - igl.readMESH(TUTORIAL_SHARED_PATH + "big-sigcat.mesh", V, T, F) - - # Compute barycenters of all tets - igl.barycenter(V, T, BC) - - # Compute generalized winding number at all barycenters - print("Computing winding number over all %i tets..." % T.rows()) - igl.winding_number(V, F, BC, W) - - # Extract interior tets - Wt = sum(W > 0.5) - CT = igl.eigen.MatrixXi(Wt, 4) - k = 0 - for t in range(T.rows()): - if W[t] > 0.5: - CT.setRow(k, T.row(t)) - k += 1 - - # find bounary facets of interior tets - igl.boundary_facets(CT, G) - - # boundary_facets seem to be reversed... - G = G.rowwiseReverse() - - # normalize - W = (W - W.minCoeff()) / (W.maxCoeff() - W.minCoeff()) - - # Plot the generated mesh - viewer = igl.glfw.Viewer() - update(viewer) - viewer.callback_key_down = key_down - viewer.launch() diff --git a/python/tutorial/704_SignedDistance.py b/python/tutorial/704_SignedDistance.py deleted file mode 100755 index 601740bda..000000000 --- a/python/tutorial/704_SignedDistance.py +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os -import math - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() -T = igl.eigen.MatrixXi() -tree = igl.AABB() -FN = igl.eigen.MatrixXd() -VN = igl.eigen.MatrixXd() -EN = igl.eigen.MatrixXd() -E = igl.eigen.MatrixXi() -EMAP = igl.eigen.MatrixXi() - -max_distance = 1 -slice_z = 0.5 -overlay = False - -viewer = igl.glfw.Viewer() - - -def append_mesh(C_vis, F_vis, V_vis, V, F, color): - F_vis.conservativeResize(F_vis.rows() + F.rows(), 3) - F_vis.setBottomRows(F.rows(), F + V_vis.rows()) - V_vis.conservativeResize(V_vis.rows() + V.rows(), 3) - V_vis.setBottomRows(V.rows(), V) - C_vis.conservativeResize(C_vis.rows() + V.rows(), 3) - colorM = igl.eigen.MatrixXd(V.rows(), C_vis.cols()) - colorM.rowwiseSet(color) - C_vis.setBottomRows(V.rows(), colorM) - - -def update_visualization(viewer): - global V, F, T, tree, FN, VN, EN, E, EMAP, max_distance, slice_z, overlay - plane = igl.eigen.MatrixXd([0.0, 0.0, 1.0, -((1 - slice_z) * V.col(2).minCoeff() + slice_z * V.col(2).maxCoeff())]) - V_vis = igl.eigen.MatrixXd() - F_vis = igl.eigen.MatrixXi() - - # Extract triangle mesh slice through volume mesh and subdivide nasty triangles - J = igl.eigen.MatrixXi() - bary = igl.eigen.SparseMatrixd() - igl.marching_tets(V, T, plane, V_vis, F_vis, J, bary) - max_l = 0.03 - while True: - l = igl.eigen.MatrixXd() - igl.edge_lengths(V_vis, F_vis, l) - l /= (V_vis.colwiseMaxCoeff() - V_vis.colwiseMinCoeff()).norm() - - if l.maxCoeff() < max_l: - break - - bad = l.rowwiseMaxCoeff() > max_l - notbad = l.rowwiseMaxCoeff() <= max_l # TODO replace by ~ operator - F_vis_bad = igl.eigen.MatrixXi() - F_vis_good = igl.eigen.MatrixXi() - igl.slice_mask(F_vis, bad, 1, F_vis_bad) - igl.slice_mask(F_vis, notbad, 1, F_vis_good) - igl.upsample(V_vis, F_vis_bad) - F_vis = igl.cat(1, F_vis_bad, F_vis_good) - - # Compute signed distance - S_vis = igl.eigen.MatrixXd() - I = igl.eigen.MatrixXi() - N = igl.eigen.MatrixXd() - C = igl.eigen.MatrixXd() - - # Bunny is a watertight mesh so use pseudonormal for signing - igl.signed_distance_pseudonormal(V_vis, V, F, tree, FN, VN, EN, EMAP, S_vis, I, C, N) - - # push to [0,1] range - S_vis = 0.5 * (S_vis / max_distance) + 0.5 - C_vis = igl.eigen.MatrixXd() - # color without normalizing - igl.parula(S_vis, False, C_vis) - - if overlay: - append_mesh(C_vis, F_vis, V_vis, V, F, igl.eigen.MatrixXd([[0.8, 0.8, 0.8]])) - - viewer.data().clear() - viewer.data().set_mesh(V_vis, F_vis) - viewer.data().set_colors(C_vis) - viewer.core.lighting_factor = overlay - - -def key_down(viewer, key, modifier): - global slice_z, overlay - - if key == ord(' '): - overlay = not overlay - elif key == ord('.'): - slice_z = min(slice_z + 0.01, 0.99) - elif key == ord(','): - slice_z = max(slice_z - 0.01, 0.01) - else: - return False - - update_visualization(viewer) - return True - - -print("Press [space] to toggle showing surface.") -print("Press '.'/',' to push back/pull forward slicing plane.") - -# Load mesh: (V,T) tet-mesh of convex hull, F contains original surface triangles -igl.readMESH(TUTORIAL_SHARED_PATH + "bunny.mesh", V, T, F) - -# Call to point_mesh_squared_distance to determine bounds -sqrD = igl.eigen.MatrixXd() -I = igl.eigen.MatrixXi() -C = igl.eigen.MatrixXd() -igl.point_mesh_squared_distance(V, V, F, sqrD, I, C) -max_distance = math.sqrt(sqrD.maxCoeff()) - -# Precompute signed distance AABB tree -tree.init(V, F) - -# Precompute vertex, edge and face normals -igl.per_face_normals(V, F, FN) -igl.per_vertex_normals(V, F, igl.PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE, FN, VN) -igl.per_edge_normals(V, F, igl.PER_EDGE_NORMALS_WEIGHTING_TYPE_UNIFORM, FN, EN, E, EMAP) - -# Plot the generated mesh -update_visualization(viewer) -viewer.callback_key_down = key_down -viewer.data().show_lines = False -viewer.launch() diff --git a/python/tutorial/705_MarchingCubes.py b/python/tutorial/705_MarchingCubes.py deleted file mode 100755 index 85fda423d..000000000 --- a/python/tutorial/705_MarchingCubes.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies, print_usage - -dependencies = ["copyleft", "glfw"] -check_dependencies(dependencies) - - -def key_down(viewer, key, modifier): - if key == ord('1'): - viewer.data().clear() - viewer.data().set_mesh(V, F) - elif key == ord('2'): - viewer.data().clear() - viewer.data().set_mesh(SV, SF) - elif key == ord('3'): - viewer.data().clear() - viewer.data().set_mesh(BV, BF) - - return True - - -if __name__ == "__main__": - keys = {"1": "show original mesh", - "2": "show marching cubes contour of signed distance", - "3": "show marching cubes contour of indicator function"} - - print_usage(keys) - - V = igl.eigen.MatrixXd() - F = igl.eigen.MatrixXi() - - # Read in inputs as double precision floating point meshes - igl.read_triangle_mesh(TUTORIAL_SHARED_PATH + "armadillo.obj", V, F) - - # number of vertices on the largest side - s = 50 - Vmin = V.colwiseMinCoeff() - Vmax = V.colwiseMaxCoeff() - h = (Vmax - Vmin).maxCoeff() / s - res = (s * ((Vmax - Vmin) / (Vmax - Vmin).maxCoeff())).castint() - - def lerp(res, Vmin, Vmax, di, d): - return Vmin[d] + float(di) / (res[d] - 1) * (Vmax[d] - Vmin[d]) - - # create grid - print("Creating grid...") - GV = igl.eigen.MatrixXd(res[0] * res[1] * res[2], 3) - for zi in range(res[2]): - z = lerp(res, Vmin, Vmax, zi, 2) - for yi in range(res[1]): - y = lerp(res, Vmin, Vmax, yi, 1) - for xi in range(res[0]): - x = lerp(res, Vmin, Vmax, xi, 0) - GV.setRow(xi + res[0] * (yi + res[1] * zi), igl.eigen.MatrixXd([[x, y, z]])) - - # compute values - print("Computing distances...") - S = igl.eigen.MatrixXd() - B = igl.eigen.MatrixXd() - I = igl.eigen.MatrixXi() - C = igl.eigen.MatrixXd() - N = igl.eigen.MatrixXd() - - igl.signed_distance(GV, V, F, igl.SIGNED_DISTANCE_TYPE_PSEUDONORMAL, S, I, C, N) - # Convert distances to binary inside-outside data --> aliasing artifacts - B = S.copy() - for e in range(B.rows()): - if B[e] > 0: - B[e] = 1 - else: - if B[e] < 0: - B[e] = -1 - else: - B[e] = 0 - - print("Marching cubes...") - SV = igl.eigen.MatrixXd() - BV = igl.eigen.MatrixXd() - SF = igl.eigen.MatrixXi() - BF = igl.eigen.MatrixXi() - - igl.copyleft.marching_cubes(S, GV, res[0], res[1], res[2], SV, SF) - igl.copyleft.marching_cubes(B, GV, res[0], res[1], res[2], BV, BF) - - # Plot the generated mesh - viewer = igl.glfw.Viewer() - viewer.data().set_mesh(SV, SF) - viewer.callback_key_down = key_down - viewer.launch() diff --git a/python/tutorial/706_FacetOrientation.py b/python/tutorial/706_FacetOrientation.py deleted file mode 100755 index a12003c62..000000000 --- a/python/tutorial/706_FacetOrientation.py +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies, print_usage - -dependencies = ["embree", "glfw"] -check_dependencies(dependencies) - - -def key_down(viewer, key, modifier): - global facetwise, is_showing_reoriented, FF - if key == ord('F') or key == ord('f'): - facetwise = (facetwise + 1) % 2 - elif key == ord('S') or key == ord('s'): - scramble_colors() - elif key == ord(' '): - is_showing_reoriented = ~is_showing_reoriented - - viewer.data().clear() - viewer.data().set_mesh(V, FF[facetwise] if is_showing_reoriented else F) - viewer.data().set_colors(RGBcolors[facetwise]) - - return True - -def scramble_colors(): - global C, viewer, RGBcolors - for p in range(2): - R = igl.eigen.MatrixXi() - igl.randperm(C[p].maxCoeff() + 1, R) - C[p] = igl.slice(R, igl.eigen.MatrixXi(C[p])) - HSV = igl.eigen.MatrixXd(C[p].rows(), 3) - HSV.setCol(0, 360.0 * C[p].castdouble() / C[p].maxCoeff()) - HSVright = igl.eigen.MatrixXd(HSV.rows(), 2) - HSVright.setConstant(1.0) - HSV.setRightCols(2, HSVright) - igl.hsv_to_rgb(HSV, RGBcolors[p]) - viewer.data().set_colors(RGBcolors[facetwise]) - - - -if __name__ == "__main__": - keys = {"space": "toggle between original and reoriented faces", - "F,f": "toggle between patchwise and facetwise reorientation", - "S,s": "scramble colors"} - print_usage(keys) - - V = igl.eigen.MatrixXd() - F = igl.eigen.MatrixXi() - C = [igl.eigen.MatrixXi(), igl.eigen.MatrixXi()] - RGBcolors = [igl.eigen.MatrixXd(), igl.eigen.MatrixXd()] - FF = [igl.eigen.MatrixXi(), igl.eigen.MatrixXi()] - is_showing_reoriented = False - facetwise = 0 - - igl.read_triangle_mesh(TUTORIAL_SHARED_PATH + "truck.obj", V, F) - - # Compute patches - for p in range(2): - I = igl.eigen.MatrixXi() - igl.embree.reorient_facets_raycast(V, F, F.rows() * 100, 10, p == 1, False, False, I, C[p]) - # apply reorientation - FF[p].conservativeResize(F.rows(), F.cols()) - for i in range(I.rows()): - if I[i]: - FF[p].setRow(i, F.row(i).rowwiseReverse()) - else: - FF[p].setRow(i, F.row(i)) - - # Plot the generated mesh - viewer = igl.glfw.Viewer() - viewer.data().set_mesh(V, FF[facetwise] if is_showing_reoriented else F) - viewer.data().set_face_based(True) - scramble_colors() - viewer.callback_key_down = key_down - viewer.launch() diff --git a/python/tutorial/707_SweptVolume.py b/python/tutorial/707_SweptVolume.py deleted file mode 100755 index c5969f851..000000000 --- a/python/tutorial/707_SweptVolume.py +++ /dev/null @@ -1,92 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -from math import pi, cos - -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl - -from shared import TUTORIAL_SHARED_PATH, check_dependencies, print_usage - -dependencies = ["copyleft", "glfw"] -check_dependencies(dependencies) - - -def key_down(viewer, key, modifier): - global show_swept_volume, SV, SF, V, F - if key == ord(' '): - show_swept_volume = not show_swept_volume - viewer.data().clear() - - if show_swept_volume: - viewer.data().set_mesh(SV, SF) - viewer.data().uniform_colors(igl.eigen.MatrixXd([0.2, 0.2, 0.2]), igl.eigen.MatrixXd([1.0, 1.0, 1.0]), igl.eigen.MatrixXd([1.0, 1.0, 1.0])) # TODO replace with constants from cpp - else: - viewer.data().set_mesh(V, F) - - viewer.core.is_animating = not show_swept_volume - viewer.data().set_face_based(True) - - return True - - -def pre_draw(viewer): - global show_swept_volume, V - if not show_swept_volume: - T = transform(0.25 * igl.get_seconds()) - VT = V * T.matrix().block(0, 0, 3, 3).transpose() - trans = T.matrix().block(0, 3, 3, 1).transpose() - Vtrans = igl.eigen.MatrixXd(VT.rows(), VT.cols()) - Vtrans.rowwiseSet(trans) - VT += Vtrans - viewer.data().set_vertices(VT) - viewer.data().compute_normals() - return False - - -# Define a rigid motion -def transform(t): - T = igl.eigen.Affine3d() - T.setIdentity() - T.rotate(t * 2 * pi, igl.eigen.MatrixXd([0, 1, 0])) - T.translate(igl.eigen.MatrixXd([0, 0.125 * cos(2 * pi * t), 0])) - return T - - -if __name__ == "__main__": - keys = {"space": "toggle between transforming original mesh and swept volume"} - print_usage(keys) - - V = igl.eigen.MatrixXd() - SV = igl.eigen.MatrixXd() - VT = igl.eigen.MatrixXd() - F = igl.eigen.MatrixXi() - SF = igl.eigen.MatrixXi() - show_swept_volume = False - grid_size = 50 - time_steps = 200 - isolevel = 1 - - igl.read_triangle_mesh(TUTORIAL_SHARED_PATH + "bunny.off", V, F) - - print("Computing swept volume...") - igl.copyleft.swept_volume(V, F, transform, time_steps, grid_size, isolevel, SV, SF) - print("...finished.") - - # Plot the generated mesh - viewer = igl.glfw.Viewer() - viewer.data().set_mesh(V, F) - viewer.data().set_face_based(True) - viewer.core.is_animating = not show_swept_volume - viewer.callback_pre_draw = pre_draw - viewer.callback_key_down = key_down - viewer.launch() diff --git a/python/tutorial/708_Picking.py b/python/tutorial/708_Picking.py deleted file mode 100755 index 16809b3f7..000000000 --- a/python/tutorial/708_Picking.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl -import numpy as np - -from shared import TUTORIAL_SHARED_PATH, check_dependencies, print_usage - -dependencies = ["glfw"] -check_dependencies(dependencies) - - -def mouse_down(viewer, a, b): - bc = igl.eigen.MatrixXd() - - # Cast a ray in the view direction starting from the mouse position - fid = igl.eigen.MatrixXi(np.array([-1])) - coord = igl.eigen.MatrixXd([viewer.current_mouse_x, viewer.core.viewport[3] - viewer.current_mouse_y]) - hit = igl.unproject_onto_mesh(coord, viewer.core.view, - viewer.core.proj, viewer.core.viewport, V, F, fid, bc) - if hit: - # paint hit red - C.setRow(fid[0, 0], igl.eigen.MatrixXd([[1, 0, 0]])) - viewer.data().set_colors(C) - return True - - return False - - -if __name__ == "__main__": - keys = {"click": "Pick face on shape"} - print_usage(keys) - - # Mesh with per-face color - V = igl.eigen.MatrixXd() - F = igl.eigen.MatrixXi() - C = igl.eigen.MatrixXd() - - # Load a mesh in OFF format - igl.readOFF(TUTORIAL_SHARED_PATH + "fertility.off", V, F) - - # Initialize white - C.setConstant(F.rows(), 3, 1.0) - - # Show mesh - viewer = igl.glfw.Viewer() - viewer.data().set_mesh(V, F) - viewer.data().set_colors(C) - viewer.data().show_lines = False - viewer.callback_mouse_down = mouse_down - viewer.launch() diff --git a/python/tutorial/709_VectorFieldVisualizer.py b/python/tutorial/709_VectorFieldVisualizer.py deleted file mode 100755 index 9ab64a8e0..000000000 --- a/python/tutorial/709_VectorFieldVisualizer.py +++ /dev/null @@ -1,135 +0,0 @@ -#!/usr/bin/env python -# -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import sys, os -import numpy as np - -# Add the igl library to the modules search path -sys.path.insert(0, os.getcwd() + "/../") -import pyigl as igl -from shared import TUTORIAL_SHARED_PATH, check_dependencies - -dependencies = ["glfw"] -check_dependencies(dependencies) - -# Input mesh -V = igl.eigen.MatrixXd() -F = igl.eigen.MatrixXi() - -data = igl.StreamlineData() -state = igl.StreamlineState() - -treat_as_symmetric = True - -# animation params -anim_t = 0 -anim_t_dir = 1 - - -def representative_to_nrosy(V, F, R, N, Y): - B1 = igl.eigen.MatrixXd() - B2 = igl.eigen.MatrixXd() - B3 = igl.eigen.MatrixXd() - - igl.local_basis(V, F, B1, B2, B3) - - Y.resize(F.rows(), 3 * N) - for i in range(0, F.rows()): - x = R.row(i) * B1.row(i).transpose() - y = R.row(i) * B2.row(i).transpose() - angle = np.arctan2(y, x) - - for j in range(0, N): - anglej = angle + np.pi * float(j) / float(N) - xj = float(np.cos(anglej)) - yj = float(np.sin(anglej)) - Y.setBlock(i, j * 3, 1, 3, xj * B1.row(i) + yj * B2.row(i)) - - -def pre_draw(viewer): - if not viewer.core.is_animating: - return False - - global anim_t - global start_point - global end_point - - igl.streamlines_next(V, F, data, state) - - value = (anim_t % 100) / 100.0 - - if value > 0.5: - value = 1 - value - value /= 0.5 - r, g, b = igl.parula(value) - viewer.data().add_edges(state.start_point, state.end_point, igl.eigen.MatrixXd([[r, g, b]])) - - anim_t += anim_t_dir - - return False - - -def key_down(viewer, key, modifier): - if key == ord(' '): - viewer.core.is_animating = not viewer.core.is_animating - return True - - return False - - -def main(): - # Load a mesh in OFF format - igl.readOFF(TUTORIAL_SHARED_PATH + "bumpy.off", V, F) - - # Create a Vector Field - temp_field = igl.eigen.MatrixXd() - b = igl.eigen.MatrixXi([[0]]) - bc = igl.eigen.MatrixXd([[1, 1, 1]]) - S = igl.eigen.MatrixXd() # unused - - degree = 3 - igl.comiso.nrosy(V, F, b, bc, igl.eigen.MatrixXi(), igl.eigen.MatrixXd(), igl.eigen.MatrixXd(), 1, 0.5, temp_field, S) - temp_field2 = igl.eigen.MatrixXd() - representative_to_nrosy(V, F, temp_field, degree, temp_field2) - - # Initialize tracer - igl.streamlines_init(V, F, temp_field2, treat_as_symmetric, data, state) - - # Setup viewer - viewer = igl.glfw.Viewer() - viewer.data().set_mesh(V, F) - viewer.callback_pre_draw = pre_draw - viewer.callback_key_down = key_down - - viewer.core.show_lines = False - - viewer.core.is_animating = False - viewer.core.animation_max_fps = 30.0 - - # Paint mesh grayish - C = igl.eigen.MatrixXd() - C.setConstant(viewer.data().V.rows(), 3, .9) - viewer.data().set_colors(C) - - # Draw vector field on sample points - state0 = state.copy() - - igl.streamlines_next(V, F, data, state0) - v = state0.end_point - state0.start_point - v = v.rowwiseNormalized() - - viewer.data().add_edges(state0.start_point, - state0.start_point + 0.059 * v, - igl.eigen.MatrixXd([[1.0, 1.0, 1.0]])) - - print("Press [space] to toggle animation") - viewer.launch() - -if __name__ == "__main__": - main() diff --git a/python/tutorial/shared.py b/python/tutorial/shared.py deleted file mode 100644 index 85e2fd4d7..000000000 --- a/python/tutorial/shared.py +++ /dev/null @@ -1,29 +0,0 @@ -# This file is part of libigl, a simple c++ geometry processing library. -# -# Copyright (C) 2017 Sebastian Koch and Daniele Panozzo -# -# This Source Code Form is subject to the terms of the Mozilla Public License -# v. 2.0. If a copy of the MPL was not distributed with this file, You can -# obtain one at http://mozilla.org/MPL/2.0/. -import pyigl as igl -import sys -import os - -TUTORIAL_SHARED_PATH = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../../tutorial/data/") - -def check_dependencies(deps): - available = [hasattr(igl, m) for m in deps] - all_available = True - for i, d in enumerate(available): - if not d: - all_available = False - print("The libigl python bindings were compiled without %s support. Please recompile with the CMAKE flag LIBIGL_WITH_%s." %(deps[i], deps[i].upper())) - - if not all_available: - sys.exit(-1) - - -def print_usage(key_dict): - print("Usage:") - for k in key_dict.keys(): - print("%s : %s" %(k, key_dict[k])) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 8a0af135f..273324d7a 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -27,11 +27,22 @@ add_subdirectory(${LIBIGL_EXTERNAL}/catch2 catch2) add_executable(libigl_tests main.cpp test_common.h) target_link_libraries(libigl_tests PUBLIC igl::core Catch2::Catch2) target_include_directories(libigl_tests PUBLIC ${CMAKE_CURRENT_LIST_DIR}) +target_compile_definitions(libigl_tests PUBLIC CATCH_CONFIG_ENABLE_BENCHMARKING) # Set DATA_DIR definition set(DATA_DIR "${CMAKE_CURRENT_SOURCE_DIR}/data/") target_compile_definitions(libigl_tests PUBLIC -DLIBIGL_DATA_DIR="${IGL_TEST_DATA}") +# Silencing some compile warnings +if(MSVC) + target_compile_options(libigl_tests PRIVATE + # Type conversion warnings. These can be fixed with some effort and possibly more verbose code. + /wd4267 # conversion from 'size_t' to 'type', possible loss of data + /wd4244 # conversion from 'type1' to 'type2', possible loss of data + /wd4018 # signed/unsigned mismatch + /wd4305 # truncation from 'double' to 'float' + ) +endif(MSVC) # Process code in each subdirectories: add in decreasing order of complexity # (last added will run first and those should be the fastest tests) diff --git a/tests/include/igl/avg_edge_length.cpp b/tests/include/igl/avg_edge_length.cpp index 87c336e6f..cc15756c4 100644 --- a/tests/include/igl/avg_edge_length.cpp +++ b/tests/include/igl/avg_edge_length.cpp @@ -10,7 +10,7 @@ TEST_CASE("avg_edge_length: cube", "[igl]") Eigen::MatrixXd V; Eigen::MatrixXi F; //This is a cube of dimensions 1.0x1.0x1.0 - test_common::load_mesh("cube.obj", V, F); + igl::read_triangle_mesh(test_common::data_path("cube.obj"), V, F); //Create scaled versions of the cube double scale = 1.0; double huge_scale = 1.0e8; diff --git a/tests/include/igl/bbw.cpp b/tests/include/igl/bbw.cpp index 90f09aa2e..05b01edcf 100644 --- a/tests/include/igl/bbw.cpp +++ b/tests/include/igl/bbw.cpp @@ -5,7 +5,7 @@ #include #include -TEST_CASE("bbw: decimated_knight", "[igl]") +TEST_CASE("bbw: decimated_knight", "[igl]" "[slow]") { Eigen::MatrixXd V,C; Eigen::MatrixXi T,F,E; diff --git a/tests/include/igl/boundary_loop.cpp b/tests/include/igl/boundary_loop.cpp index 4e9c0a3aa..fc1f52d24 100644 --- a/tests/include/igl/boundary_loop.cpp +++ b/tests/include/igl/boundary_loop.cpp @@ -9,7 +9,7 @@ TEST_CASE("boundary_loop: cube", "[igl]") Eigen::MatrixXd V; Eigen::MatrixXi F; //This is a cube of dimensions 1.0x1.0x1.0 - test_common::load_mesh("cube.off", V, F); + igl::read_triangle_mesh(test_common::data_path("cube.off"), V, F); //Compute Boundary Loop Eigen::VectorXi boundary; @@ -19,12 +19,12 @@ TEST_CASE("boundary_loop: cube", "[igl]") REQUIRE (boundary.size() == 0); } -TEST_CASE("boundary_loop: bunny", "[igl]") +TEST_CASE("boundary_loop: bunny", "[igl]" "[slow]") { Eigen::MatrixXd V; Eigen::MatrixXi F; //Load the Stanford bunny - test_common::load_mesh("bunny.off", V, F); + igl::read_triangle_mesh(test_common::data_path("bunny.off"), V, F); //Compute list of ordered boundary loops for a manifold mesh std::vector >boundaries; diff --git a/tests/include/igl/copyleft/boolean/mesh_boolean.cpp b/tests/include/igl/copyleft/boolean/mesh_boolean.cpp index 8e9ed1bd6..d130771eb 100644 --- a/tests/include/igl/copyleft/boolean/mesh_boolean.cpp +++ b/tests/include/igl/copyleft/boolean/mesh_boolean.cpp @@ -55,7 +55,7 @@ namespace { TEST_CASE("MeshBoolean: TwoCubes", "[igl/copyleft/boolean]") { Eigen::MatrixXd V1; Eigen::MatrixXi F1; - test_common::load_mesh("two-boxes-bad-self-union.ply", V1, F1); + igl::read_triangle_mesh(test_common::data_path("two-boxes-bad-self-union.ply"), V1, F1); Eigen::MatrixXd V2(0, 3); Eigen::MatrixXi F2(0, 3); @@ -76,8 +76,8 @@ TEST_CASE("MeshBoolean: MinusTest", "[igl/copyleft/boolean]") { // Many thanks to Eric Yao for submitting this test case. Eigen::MatrixXd V1, V2, Vo; Eigen::MatrixXi F1, F2, Fo; - test_common::load_mesh("boolean_minus_test_cube.obj", V1, F1); - test_common::load_mesh("boolean_minus_test_green.obj", V2, F2); + igl::read_triangle_mesh(test_common::data_path("boolean_minus_test_cube.obj"), V1, F1); + igl::read_triangle_mesh(test_common::data_path("boolean_minus_test_green.obj"), V2, F2); igl::copyleft::cgal::mesh_boolean(V1, F1, V2, F2, igl::MESH_BOOLEAN_TYPE_MINUS, @@ -91,7 +91,7 @@ TEST_CASE("MeshBoolean: MinusTest", "[igl/copyleft/boolean]") { TEST_CASE("MeshBoolean: IntersectWithSelf", "[igl/copyleft/boolean]") { Eigen::MatrixXd V1, Vo; Eigen::MatrixXi F1, Fo; - test_common::load_mesh("cube.obj", V1, F1); + igl::read_triangle_mesh(test_common::data_path("cube.obj"), V1, F1); igl::copyleft::cgal::mesh_boolean(V1, F1, V1, F1, igl::MESH_BOOLEAN_TYPE_INTERSECT, diff --git a/tests/include/igl/copyleft/cgal/CSGTree.cpp b/tests/include/igl/copyleft/cgal/CSGTree.cpp index 01d87abc9..51807622c 100644 --- a/tests/include/igl/copyleft/cgal/CSGTree.cpp +++ b/tests/include/igl/copyleft/cgal/CSGTree.cpp @@ -5,7 +5,7 @@ TEST_CASE("CSGTree: extrusion", "[igl/copyleft/cgal]") { Eigen::MatrixXd V; Eigen::MatrixXi F; - test_common::load_mesh("extrusion.obj", V, F); + igl::read_triangle_mesh(test_common::data_path("extrusion.obj"), V, F); igl::copyleft::cgal::CSGTree tree(V, F); igl::copyleft::cgal::CSGTree inter(tree, tree, "i"); // returns error diff --git a/tests/include/igl/copyleft/cgal/hausdorff.cpp b/tests/include/igl/copyleft/cgal/hausdorff.cpp index d4a94954e..7e900120d 100644 --- a/tests/include/igl/copyleft/cgal/hausdorff.cpp +++ b/tests/include/igl/copyleft/cgal/hausdorff.cpp @@ -9,8 +9,8 @@ TEST_CASE("hausdorff: knightVScheburashka", "[igl/copyleft/cgal]") { Eigen::MatrixXd VA,VB; Eigen::MatrixXi FA,FB; - test_common::load_mesh("decimated-knight.obj", VA, FA); - test_common::load_mesh("cheburashka.off", VB, FB); + igl::read_triangle_mesh(test_common::data_path("decimated-knight.obj"), VA, FA); + igl::read_triangle_mesh(test_common::data_path("cheburashka.off"), VB, FB); //typedef CGAL::Epeck Kernel; typedef CGAL::Simple_cartesian Kernel; CGAL::AABB_tree< diff --git a/tests/include/igl/copyleft/cgal/mesh_to_polyhedron.cpp b/tests/include/igl/copyleft/cgal/mesh_to_polyhedron.cpp index 1c085f2dc..4dcb97dfc 100644 --- a/tests/include/igl/copyleft/cgal/mesh_to_polyhedron.cpp +++ b/tests/include/igl/copyleft/cgal/mesh_to_polyhedron.cpp @@ -12,7 +12,7 @@ TEST_CASE( { Eigen::MatrixXd V; Eigen::MatrixXi F; - test_common::load_mesh(param, V, F); + igl::read_triangle_mesh(test_common::data_path(param), V, F); CGAL::Polyhedron_3< CGAL::Simple_cartesian, CGAL::Polyhedron_items_with_id_3, @@ -31,7 +31,7 @@ TEST_CASE( { Eigen::MatrixXd V; Eigen::MatrixXi F; - test_common::load_mesh("truck.obj", V, F); + igl::read_triangle_mesh(test_common::data_path("truck.obj"), V, F); CGAL::Polyhedron_3< CGAL::Simple_cartesian, CGAL::Polyhedron_items_with_id_3, diff --git a/tests/include/igl/copyleft/cgal/order_facets_around_edges.cpp b/tests/include/igl/copyleft/cgal/order_facets_around_edges.cpp index b9d373b88..08309e9b8 100644 --- a/tests/include/igl/copyleft/cgal/order_facets_around_edges.cpp +++ b/tests/include/igl/copyleft/cgal/order_facets_around_edges.cpp @@ -54,7 +54,7 @@ void assert_order( Eigen::MatrixXd N; //igl::per_face_normals_stable(V, F, N); //igl::per_face_normals(V, F, N); - test_common::load_matrix(normal, N); + igl::readDMAT(test_common::data_path(normal), N); igl::copyleft::cgal::order_facets_around_edges( V, F, N, uE, uE2E, uE2oE, uE2C); } else { @@ -192,9 +192,9 @@ TEST_CASE("copyleft_cgal_order_facets_around_edges: NormalSensitivity", "[igl/co // results in very different ordering of facets. Eigen::MatrixXd V; - test_common::load_matrix("duplicated_faces_V.dmat", V); + igl::readDMAT(test_common::data_path("duplicated_faces_V.dmat"), V); Eigen::MatrixXi F; - test_common::load_matrix("duplicated_faces_F.dmat", F); + igl::readDMAT(test_common::data_path("duplicated_faces_F.dmat"), F); assert_order(V, F, 223, 224, {2, 0, 3, 1}, "duplicated_faces_N1.dmat"); assert_order(V, F, 223, 224, {0, 3, 2, 1}, "duplicated_faces_N2.dmat"); diff --git a/tests/include/igl/copyleft/cgal/outer_facet.cpp b/tests/include/igl/copyleft/cgal/outer_facet.cpp index f79047120..d3290dc92 100644 --- a/tests/include/igl/copyleft/cgal/outer_facet.cpp +++ b/tests/include/igl/copyleft/cgal/outer_facet.cpp @@ -22,7 +22,7 @@ TEST_CASE("OuterFacet: Simple", "[igl/copyleft/cgal]") { Eigen::MatrixXd V; Eigen::MatrixXi F; - test_common::load_mesh("cube.obj", V, F); + igl::read_triangle_mesh(test_common::data_path("cube.obj"), V, F); const size_t num_faces = F.rows(); @@ -41,7 +41,7 @@ TEST_CASE("OuterFacet: DuplicatedOppositeFaces", "[igl/copyleft/cgal]") { Eigen::MatrixXd V; Eigen::MatrixXi F1; - test_common::load_mesh("cube.obj", V, F1); + igl::read_triangle_mesh(test_common::data_path("cube.obj"), V, F1); Eigen::MatrixXi F2 = F1; F2.col(0).swap(F2.col(1)); @@ -64,7 +64,7 @@ TEST_CASE("OuterFacet: FullyDegnerated", "[igl/copyleft/cgal]") { Eigen::MatrixXd V; Eigen::MatrixXi F; - test_common::load_mesh("degenerated.obj", V, F); + igl::read_triangle_mesh(test_common::data_path("degenerated.obj"), V, F); Eigen::VectorXi I(F.rows()); I.setLinSpaced(F.rows(), 0, F.rows()-1); @@ -81,7 +81,7 @@ TEST_CASE("OuterFacet: InvertedNormal", "[igl/copyleft/cgal]") { Eigen::MatrixXd V; Eigen::MatrixXi F; - test_common::load_mesh("cube.obj", V, F); + igl::read_triangle_mesh(test_common::data_path("cube.obj"), V, F); F.col(0).swap(F.col(1)); Eigen::VectorXi I(F.rows()); @@ -99,7 +99,7 @@ TEST_CASE("OuterFacet: SliverTet", "[igl/copyleft/cgal]") { Eigen::MatrixXd V; Eigen::MatrixXi F; - test_common::load_mesh("sliver_tet.ply", V, F); + igl::read_triangle_mesh(test_common::data_path("sliver_tet.ply"), V, F); Eigen::VectorXi I(F.rows()); I.setLinSpaced(F.rows(), 0, F.rows()-1); diff --git a/tests/include/igl/copyleft/cgal/outer_hull.cpp b/tests/include/igl/copyleft/cgal/outer_hull.cpp index d20f911df..3f0d0126b 100644 --- a/tests/include/igl/copyleft/cgal/outer_hull.cpp +++ b/tests/include/igl/copyleft/cgal/outer_hull.cpp @@ -7,7 +7,7 @@ TEST_CASE("OuterHull: CubeWithFold", "[igl/copyleft/cgal]") { Eigen::MatrixXd V; Eigen::MatrixXi F; - test_common::load_mesh("cube_with_fold.ply", V, F); + igl::read_triangle_mesh(test_common::data_path("cube_with_fold.ply"), V, F); Eigen::MatrixXi G,J,flip; // Is this just checking that it doesn't crash? diff --git a/tests/include/igl/copyleft/cgal/peel_outer_hull_layers.cpp b/tests/include/igl/copyleft/cgal/peel_outer_hull_layers.cpp index 19f0ef604..086de5328 100644 --- a/tests/include/igl/copyleft/cgal/peel_outer_hull_layers.cpp +++ b/tests/include/igl/copyleft/cgal/peel_outer_hull_layers.cpp @@ -15,7 +15,7 @@ TEST_CASE("copyleft_cgal_peel_outer_hull_layers: TwoCubes", "[igl/copyleft/cgal] { Eigen::MatrixXd V; Eigen::MatrixXi F; - test_common::load_mesh("two-boxes-bad-self-union.ply", V, F); + igl::read_triangle_mesh(test_common::data_path("two-boxes-bad-self-union.ply"), V, F); REQUIRE (V.rows() == 486); REQUIRE (F.rows() == 708); @@ -55,7 +55,7 @@ TEST_CASE("PeelOuterHullLayers: CubeWithFold", "[igl/copyleft/cgal]") { Eigen::Matrix V; Eigen::MatrixXi F; - test_common::load_mesh("cube_with_fold.ply", V, F); + igl::read_triangle_mesh(test_common::data_path("cube_with_fold.ply"), V, F); typedef CGAL::Exact_predicates_exact_constructions_kernel K; typedef K::FT Scalar; diff --git a/tests/include/igl/copyleft/cgal/points_inside_component.cpp b/tests/include/igl/copyleft/cgal/points_inside_component.cpp index 8b04b551e..e6eb314ca 100644 --- a/tests/include/igl/copyleft/cgal/points_inside_component.cpp +++ b/tests/include/igl/copyleft/cgal/points_inside_component.cpp @@ -7,7 +7,7 @@ TEST_CASE("PointInsideComponent: simple", "[igl/copyleft/cgal]") { Eigen::MatrixXd V1; Eigen::MatrixXi F1; - test_common::load_mesh("cube.obj", V1, F1); + igl::read_triangle_mesh(test_common::data_path("cube.obj"), V1, F1); Eigen::MatrixXd P(4, 3); P << 0.0, 0.0, 0.0, @@ -27,7 +27,7 @@ TEST_CASE("PointInsideComponent: near_boundary", "[igl/copyleft/cgal]") { Eigen::MatrixXd V1; Eigen::MatrixXi F1; - test_common::load_mesh("cube.obj", V1, F1); + igl::read_triangle_mesh(test_common::data_path("cube.obj"), V1, F1); const double EPS = std::numeric_limits::epsilon(); Eigen::MatrixXd P(6, 3); @@ -52,7 +52,7 @@ TEST_CASE("PointInsideComponent: near_corner", "[igl/copyleft/cgal]") { Eigen::MatrixXd V1; Eigen::MatrixXi F1; - test_common::load_mesh("cube.obj", V1, F1); + igl::read_triangle_mesh(test_common::data_path("cube.obj"), V1, F1); const double EPS = std::numeric_limits::epsilon(); Eigen::MatrixXd P_out(8, 3); diff --git a/tests/include/igl/copyleft/cgal/remesh_self_intersections.cpp b/tests/include/igl/copyleft/cgal/remesh_self_intersections.cpp index bfa441b3f..172a93d77 100644 --- a/tests/include/igl/copyleft/cgal/remesh_self_intersections.cpp +++ b/tests/include/igl/copyleft/cgal/remesh_self_intersections.cpp @@ -10,7 +10,7 @@ TEST_CASE("RemeshSelfIntersections: CubeWithFold", "[igl/copyleft/cgal]") { Eigen::MatrixXd V; Eigen::MatrixXi F; - test_common::load_mesh("cube_with_fold.ply", V, F); + igl::read_triangle_mesh(test_common::data_path("cube_with_fold.ply"), V, F); typedef CGAL::Exact_predicates_exact_constructions_kernel K; typedef Eigen::Matrix MatrixXe; diff --git a/tests/include/igl/cotmatrix.cpp b/tests/include/igl/cotmatrix.cpp index 5f6c8e42f..3acddb502 100644 --- a/tests/include/igl/cotmatrix.cpp +++ b/tests/include/igl/cotmatrix.cpp @@ -2,7 +2,7 @@ #include #include -TEST_CASE("cotmatrix: constant_in_null_space", "[igl]") +TEST_CASE("cotmatrix: constant_in_null_space", "[igl]" "[slow]") { const auto test_case = [](const std::string ¶m) { @@ -10,7 +10,7 @@ TEST_CASE("cotmatrix: constant_in_null_space", "[igl]") Eigen::MatrixXi F; Eigen::SparseMatrix L; // Load example mesh: GetParam() will be name of mesh file - test_common::load_mesh(param, V, F); + igl::read_triangle_mesh(test_common::data_path(param), V, F); igl::cotmatrix(V,F,L); REQUIRE (L.rows() == V.rows()); REQUIRE (L.cols() == L.rows()); @@ -33,7 +33,7 @@ TEST_CASE("cotmatrix: cube", "[igl]") Eigen::MatrixXd V; Eigen::MatrixXi F; //This is a cube of dimensions 1.0x1.0x1.0 - test_common::load_mesh("cube.obj", V, F); + igl::read_triangle_mesh(test_common::data_path("cube.obj"), V, F); //Scale the cube to have huge sides Eigen::MatrixXd V_huge = V * 1.0e8; @@ -109,7 +109,7 @@ TEST_CASE("cotmatrix: tetrahedron", "[igl]") Eigen::MatrixXd V; Eigen::MatrixXi F; //This is a cube of dimensions 1.0x1.0x1.0 - test_common::load_mesh("cube.obj", V, F); + igl::read_triangle_mesh(test_common::data_path("cube.obj"), V, F); //Prepare another mesh with triangles along side diagonals of the cube //These triangles are form a regular tetrahedron of side sqrt(2) diff --git a/tests/include/igl/cotmatrix_entries.cpp b/tests/include/igl/cotmatrix_entries.cpp index 405fb2f37..6be242850 100644 --- a/tests/include/igl/cotmatrix_entries.cpp +++ b/tests/include/igl/cotmatrix_entries.cpp @@ -12,7 +12,7 @@ TEST_CASE("cotmatrix_entries: simple", "[igl]") Eigen::MatrixXd V; Eigen::MatrixXi F; //This is a cube of dimensions 1.0x1.0x1.0 - test_common::load_mesh("cube.obj", V, F); + igl::read_triangle_mesh(test_common::data_path("cube.obj"), V, F); //Prepare another mesh with triangles along side diagonals of the cube //These triangles are form a regular tetrahedron of side sqrt(2) @@ -142,7 +142,7 @@ TEST_CASE("cotmatrix_entries: intrinsic", "[igl]") Eigen::MatrixXd V; Eigen::MatrixXi F; //This is a cube of dimensions 1.0x1.0x1.0 - test_common::load_mesh("cube.obj", V, F); + igl::read_triangle_mesh(test_common::data_path("cube.obj"), V, F); Eigen::MatrixXd Cext,Cint; // compute C extrinsically igl::cotmatrix_entries(V,F,Cext); diff --git a/tests/include/igl/cotmatrix_intrinsic.cpp b/tests/include/igl/cotmatrix_intrinsic.cpp index 1d3a3e710..82ad6c45c 100644 --- a/tests/include/igl/cotmatrix_intrinsic.cpp +++ b/tests/include/igl/cotmatrix_intrinsic.cpp @@ -61,13 +61,13 @@ TEST_CASE("cotmatrix_intrinsic: periodic", "[igl]") test_common::assert_near(L_d,L_gt,igl::EPS()); } -TEST_CASE("cotmatrix_intrinsic: manifold_meshes", "[igl]") +TEST_CASE("cotmatrix_intrinsic: manifold_meshes", "[igl]" "[slow]") { auto test_case = [](const std::string ¶m) { Eigen::MatrixXd V; Eigen::MatrixXi F; - test_common::load_mesh(param, V, F); + igl::read_triangle_mesh(test_common::data_path(param), V, F); Eigen::MatrixXd l; igl::edge_lengths(V,F,l); Eigen::SparseMatrix L,Li; diff --git a/tests/include/igl/cut_mesh.cpp b/tests/include/igl/cut_mesh.cpp new file mode 100644 index 000000000..b91affd61 --- /dev/null +++ b/tests/include/igl/cut_mesh.cpp @@ -0,0 +1,86 @@ +#include +#include +#include +#include + +TEST_CASE("seperate mesh", "[igl]") { + + Eigen::MatrixXd V(9,3); + V << 0,0,0, + 0,1,0, + 0,2,0, + 1,2,0, + 2,2,0, + 2,1,0, + 2,0,0, + 1,0,0, + 1,1,0; + Eigen::MatrixXi F(8,3); + F << 0,1,8, + 1,2,8, + 2,3,8, + 3,4,8, + 4,5,8, + 5,6,8, + 6,7,8, + 7,0,8; + + Eigen::MatrixXi C(8,3); + C << 0,1,1, + 0,1,1, + 0,0,1, + 0,0,0, + 0,0,0, + 0,0,0, + 0,0,0, + 0,1,0; + Eigen::VectorXi I; + igl::cut_mesh(V,F,C,I); + Eigen::VectorXi count; + igl::vertex_components(F, count); + REQUIRE(count.maxCoeff() == 2); + +} + +TEST_CASE("single edge", "[igl]") { + + Eigen::MatrixXd V(9,3); + V << 0,0,0, + 0,1,0, + 0,2,0, + 1,2,0, + 2,2,0, + 2,1,0, + 2,0,0, + 1,0,0, + 1,1,0; + Eigen::MatrixXi F(8,3); + F << 0,1,8, + 1,2,8, + 2,3,8, + 3,4,8, + 4,5,8, + 5,6,8, + 6,7,8, + 7,0,8; + + Eigen::MatrixXi C(8,3); + C << 0,1,0, + 0,0,1, + 0,0,0, + 0,0,0, + 0,0,0, + 0,0,0, + 0,0,0, + 0,0,0; + Eigen::VectorXi I; + igl::cut_mesh(V,F,C,I); + Eigen::VectorXi count; + igl::vertex_components(F, count); + REQUIRE(0 == count.maxCoeff()); + Eigen::MatrixXi E; + igl::edges(F, E); + const auto euler = V.rows() - E.rows() + F.rows(); + REQUIRE ( 1 == euler ); + +} \ No newline at end of file diff --git a/tests/include/igl/cut_to_disk.cpp b/tests/include/igl/cut_to_disk.cpp index c68d62294..4abb625ec 100644 --- a/tests/include/igl/cut_to_disk.cpp +++ b/tests/include/igl/cut_to_disk.cpp @@ -108,7 +108,7 @@ TEST_CASE("cut_to_disk: torus", "[igl]") using namespace igl; Eigen::MatrixXd V; Eigen::MatrixXi F; - test_common::load_mesh("TinyTorus.obj", V, F); + igl::read_triangle_mesh(test_common::data_path("TinyTorus.obj"), V, F); std::vector> cuts; cut_to_disk(F, cuts); @@ -122,7 +122,7 @@ TEST_CASE("cut_to_disk: cube", "[igl]") using namespace igl; Eigen::MatrixXd V; Eigen::MatrixXi F; - test_common::load_mesh("cube.obj", V, F); + igl::read_triangle_mesh(test_common::data_path("cube.obj"), V, F); std::vector> cuts; cut_to_disk(F, cuts); @@ -136,7 +136,7 @@ TEST_CASE("cut_to_disk: annulus", "[igl]") { using namespace igl; Eigen::MatrixXd V; Eigen::MatrixXi F; - test_common::load_mesh("annulus.obj", V, F); + igl::read_triangle_mesh(test_common::data_path("annulus.obj"), V, F); std::vector> cuts; cut_to_disk(F, cuts); diff --git a/tests/include/igl/decimate.cpp b/tests/include/igl/decimate.cpp index abc699577..8a5aba2b0 100644 --- a/tests/include/igl/decimate.cpp +++ b/tests/include/igl/decimate.cpp @@ -22,7 +22,7 @@ TEST_CASE("decimate: hemisphere", "[igl]") Eigen::MatrixXi F,G; Eigen::VectorXi J,I; // Load example mesh: GetParam() will be name of mesh file - test_common::load_mesh("hemisphere.obj", V, F); + igl::read_triangle_mesh(test_common::data_path("hemisphere.obj"), V, F); // Perfect normals from positions Eigen::MatrixXd NV = V.rowwise().normalized(); // Remove half of the faces @@ -48,7 +48,7 @@ TEST_CASE("decimate: closed", "[igl]") Eigen::MatrixXi F,G; Eigen::VectorXi J; // Load example mesh: GetParam() will be name of mesh file - test_common::load_mesh(param, V, F); + igl::read_triangle_mesh(test_common::data_path(param), V, F); igl::decimate(V,F,0,U,G,J); REQUIRE (4 == U.rows()); REQUIRE (4 == G.rows()); diff --git a/tests/include/igl/delaunay_triangulation.cpp b/tests/include/igl/delaunay_triangulation.cpp new file mode 100644 index 000000000..970ef3039 --- /dev/null +++ b/tests/include/igl/delaunay_triangulation.cpp @@ -0,0 +1,103 @@ +#ifdef IGL_STATIC_LIBRARY +#undef IGL_STATIC_LIBRARY +#endif + +#include +#include + +namespace git_issue { + +constexpr static double EPSILON_LENGTH = 0.0005; // Sketchup support 1/1000 precision +constexpr static double EPSILON_ANGLE = 0.0000000000005; +constexpr static double INV_EPSILON_LENGTH = 2000.0; + +template +inline int orient2d(const T &pa, const T &pb, const T &pc) { + double acx, bcx, acy, bcy; + acx = pa[0] - pc[0]; + bcx = pb[0] - pc[0]; + acy = pa[1] - pc[1]; + bcy = pb[1] - pc[1]; + + double val = acx * bcy - acy * bcx; + if (val < -EPSILON_LENGTH) { + return -1; + } else if (val > EPSILON_LENGTH) { + return 1; + } else { + return 0; + } + return 0; +} + +template +inline int incircle(const T &pa, const T &pb, const T &pc, const T &pd) { + double adx, ady, bdx, bdy, cdx, cdy; + double abdet, bcdet, cadet; + double alift, blift, clift; + + adx = pa[0] - pd[0]; + ady = pa[1] - pd[1]; + bdx = pb[0] - pd[0]; + bdy = pb[1] - pd[1]; + cdx = pc[0] - pd[0]; + cdy = pc[1] - pd[1]; + + abdet = adx * bdy - bdx * ady; + bcdet = bdx * cdy - cdx * bdy; + cadet = cdx * ady - adx * cdy; + alift = adx * adx + ady * ady; + blift = bdx * bdx + bdy * bdy; + clift = cdx * cdx + cdy * cdy; + + double val = alift * bcdet + blift * cadet + clift * abdet; + if (val < -EPSILON_LENGTH) { + return -1; + } else if (val > EPSILON_LENGTH) { + return 1; + } else { + return 0; + } + return 0; +} +} + + +TEST_CASE("delaunay_triangulation_issue_521", "[igl]") { + using namespace Eigen; + using namespace git_issue; + MatrixXd V(16, 2); + MatrixXi F; + + V << 4.55E-13, 2.33E-12, + 248.718, 249.939, + 463.602, 36.1059, + 764.953, 338.937, + -1002.42, 2097.68, + -1303.78, 1794.85, + -1120.79, 1612.75, + -1369.5, 1362.81, + -1552.49, 1544.91, + -1843.04, 1252.94, + -75.6625, -505.806, + 214.883, -213.834, + -191.721, 190.784, + -1166.14, 1160.44, + -917.424, 1410.38, + 56.9975, 440.723; + + const auto &orient2d_predicates = [](const double * pa, const double * pb, const double * pc) { + return orient2d(pa, pb, pc); + }; + const auto &incircle_predicates = [](const double * pa, const double * pb, const double * pc, const double * pd) { + return incircle(pa, pb, pc, pd); + }; + + igl::delaunay_triangulation(V, orient2d_predicates, incircle_predicates, F); + + REQUIRE(F.rows() > 0); + REQUIRE(F.cols() == 3); + REQUIRE(F.maxCoeff() < 16); + REQUIRE(F.minCoeff() == 0); +} + diff --git a/tests/include/igl/dijkstra.cpp b/tests/include/igl/dijkstra.cpp new file mode 100644 index 000000000..5bd812294 --- /dev/null +++ b/tests/include/igl/dijkstra.cpp @@ -0,0 +1,22 @@ +#include +#include +#include +#include + +TEST_CASE("dijkstra: cube", "[igl]") +{ + Eigen::MatrixXd V; + Eigen::MatrixXi F; + //This is a cube of dimensions 1.0x1.0x1.0 + igl::read_triangle_mesh(test_common::data_path("cube.off"), V, F); + + std::vector> VV; + igl::adjacency_list(F, VV); + + Eigen::VectorXd min_distance; + Eigen::VectorXi previous; + igl::dijkstra(V, VV, 0, {7}, min_distance, previous); + + REQUIRE(min_distance(0) == 0); + REQUIRE(min_distance(7) == Approx(sqrt(2)).margin(1e-10)); +} diff --git a/tests/include/igl/doublearea.cpp b/tests/include/igl/doublearea.cpp index 00342f513..21547548a 100644 --- a/tests/include/igl/doublearea.cpp +++ b/tests/include/igl/doublearea.cpp @@ -1,14 +1,13 @@ #include #include - -TEST_CASE("doublearea: VF_vs_ABC", "[igl]") +TEST_CASE("doublearea: VF_vs_ABC", "[igl]" "[slow]") { auto test_case = [](const std::string ¶m) { Eigen::MatrixXd V; Eigen::MatrixXi F; - test_common::load_mesh(param, V, F); + igl::read_triangle_mesh(test_common::data_path(param), V, F); // Check that computing double area with (V,F) is the same as computing // double area with (V1,V2,V2) diff --git a/tests/include/igl/edge_flaps.cpp b/tests/include/igl/edge_flaps.cpp index 5b1ce3e95..f05f83803 100644 --- a/tests/include/igl/edge_flaps.cpp +++ b/tests/include/igl/edge_flaps.cpp @@ -1,42 +1,41 @@ #include #include - -TEST_CASE("edge_flaps: verify", "[igl]") +TEST_CASE("edge_flaps: verify", "[igl]" "[slow]") { - const auto test_case = [](const std::string ¶m) - { - Eigen::MatrixXd V; - Eigen::MatrixXi F; - test_common::load_mesh(param, V, F); + const auto test_case = [](const std::string ¶m) + { + Eigen::MatrixXd V; + Eigen::MatrixXi F; + igl::read_triangle_mesh(test_common::data_path(param), V, F); - Eigen::MatrixXi efE,efEF,efEI; - Eigen::VectorXi efEMAP; - igl::edge_flaps(F,efE,efEMAP,efEF,efEI); - REQUIRE (efEF.rows() == efE.rows()); - REQUIRE (2 == efE.cols()); - REQUIRE (efEF.cols() == efE.cols()); - // for each edge, make sure edge appears in face - for(int e = 0;e= 0) - { - // Either efE(e,[1 2]) = [i,j] appears after vertex c of face f - // Or efE(e,[2 1]) = [j,i] appears after vertex c of face f - CHECK(( - ((efE(e,0) == F(f,(c+1)%3)) && (efE(e,1) == F(f,(c+2)%3))) || - ((efE(e,1) == F(f,(c+1)%3)) && (efE(e,0) == F(f,(c+2)%3))))); - } - } - } - }; + Eigen::MatrixXi efE,efEF,efEI; + Eigen::VectorXi efEMAP; + igl::edge_flaps(F,efE,efEMAP,efEF,efEI); + REQUIRE (efEF.rows() == efE.rows()); + REQUIRE (2 == efE.cols()); + REQUIRE (efEF.cols() == efE.cols()); + // for each edge, make sure edge appears in face + for(int e = 0;e= 0) + { + // Either efE(e,[1 2]) = [i,j] appears after vertex c of face f + // Or efE(e,[2 1]) = [j,i] appears after vertex c of face f + CHECK(( + ((efE(e,0) == F(f,(c+1)%3)) && (efE(e,1) == F(f,(c+2)%3))) || + ((efE(e,1) == F(f,(c+1)%3)) && (efE(e,0) == F(f,(c+2)%3))))); + } + } + } + }; - test_common::run_test_cases(test_common::all_meshes(), test_case); + test_common::run_test_cases(test_common::all_meshes(), test_case); } diff --git a/tests/include/igl/edge_lengths.cpp b/tests/include/igl/edge_lengths.cpp index 4f60a5d43..c7d5723a9 100644 --- a/tests/include/igl/edge_lengths.cpp +++ b/tests/include/igl/edge_lengths.cpp @@ -9,7 +9,7 @@ TEST_CASE("edge_lengths: cube", "[igl]") Eigen::MatrixXd V; Eigen::MatrixXi F; //This is a cube of dimensions 1.0x1.0x1.0 - test_common::load_mesh("cube.obj", V, F); + igl::read_triangle_mesh(test_common::data_path("cube.obj"), V, F); //Create scaled versions of the cube double scale = 1.0; double huge_scale = 1.0e8; diff --git a/tests/include/igl/embree/EmbreeIntersector.cpp b/tests/include/igl/embree/EmbreeIntersector.cpp index fe646e988..8535b9408 100644 --- a/tests/include/igl/embree/EmbreeIntersector.cpp +++ b/tests/include/igl/embree/EmbreeIntersector.cpp @@ -9,7 +9,7 @@ TEST_CASE("EmbreeIntersector: cube", "[igl/embree]") Eigen::MatrixXd V; Eigen::MatrixXi F; // This is a cube of dimensions 1.0x1.0x1.0 - test_common::load_mesh("cube.obj", V, F); + igl::read_triangle_mesh(test_common::data_path("cube.obj"), V, F); // Initialize embree igl::embree::EmbreeIntersector embree; diff --git a/tests/include/igl/fast_winding_number.cpp b/tests/include/igl/fast_winding_number.cpp new file mode 100644 index 000000000..68cacd4d7 --- /dev/null +++ b/tests/include/igl/fast_winding_number.cpp @@ -0,0 +1,107 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2019 Alec Jacobson +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// obtain one at http://mozilla.org/MPL/2.0/. +#include +#include +#include +#include +#include +#include +#include +#include + +TEST_CASE("fast_winding_number: one_point_cloud", "[igl]") +{ + Eigen::MatrixXd P(1,3); + P<<0.1,0.2,0.3; + // Unit normal + Eigen::MatrixXd N(1,3); + N<<4,5,6; + N /= N.row(0).norm(); + Eigen::VectorXd A(1,1); + A(0) = 0.7; + + std::vector > O_PI; + Eigen::MatrixXi O_CH; + Eigen::MatrixXd O_CN; + Eigen::VectorXd O_W; + igl::octree(P,O_PI,O_CH,O_CN,O_W); + + Eigen::MatrixXd O_CM; + Eigen::VectorXd O_R; + Eigen::MatrixXd O_EC; + igl::fast_winding_number(P,N,A,O_PI,O_CH,2,O_CM,O_R,O_EC); + Eigen::MatrixXd Q(4,3); + Q<< + 0, 0, 0, + 4,-3, 2, + -1, 1, 3, + 0, 5,-2; + Eigen::VectorXd WiP; + igl::fast_winding_number(P,N,A,O_PI,O_CH,O_CM,O_R,O_EC,Q,2,WiP); + Eigen::VectorXd WiP_cached(4); + WiP_cached<< + 0.38779369004261133, + -0.00041235296362485, + -0.00362978253577090, + -0.00041235296362485; + test_common::assert_near(WiP,WiP_cached,1e-15); +} + +TEST_CASE("fast_winding_number: meshes", "[igl]" "[slow]") +{ + const auto test_case = [](const std::string ¶m) + { + INFO(param); + Eigen::MatrixXd V; + Eigen::MatrixXi F; + igl::read_triangle_mesh(test_common::data_path(param),V,F); + // vertex centroid will be our query + Eigen::MatrixXd Q = V.array().colwise().mean(); + + Eigen::VectorXd Wexact(1,1); + Wexact(0,0) = igl::winding_number(V,F,Eigen::RowVector3d(Q)); + + // SOUP + { + INFO("soup"); + igl::FastWindingNumberBVH fwn_bvh; + igl::fast_winding_number(V,F,2,fwn_bvh); + Eigen::VectorXd Wfwn_soup; + igl::fast_winding_number(fwn_bvh,2,Q,Wfwn_soup); + test_common::assert_near(Wfwn_soup,Wexact,1e-2); + } + + // CLOUD + // triangle barycenters, normals and areas will be our point cloud + { + INFO("cloud"); + Eigen::MatrixXd BC,N; + Eigen::VectorXd A; + igl::barycenter(V,F,BC); + igl::per_face_normals(V,F,N); + igl::doublearea(V,F,A); + A *= 0.5; + Eigen::VectorXd Wfwn_cloud; + std::vector > O_PI; + Eigen::MatrixXi O_CH; + Eigen::MatrixXd O_CN; + Eigen::VectorXd O_W; + igl::octree(BC,O_PI,O_CH,O_CN,O_W); + Eigen::MatrixXd O_CM; + Eigen::VectorXd O_R; + Eigen::MatrixXd O_EC; + igl::fast_winding_number(BC,N,A,O_PI,O_CH,2,O_CM,O_R,O_EC); + igl::fast_winding_number(BC,N,A,O_PI,O_CH,O_CM,O_R,O_EC,Q,2,Wfwn_cloud); + test_common::assert_near(Wfwn_cloud,Wexact,1e-2); + } + }; + // FWN clouds using barycenters won't work well for very coarse models like the cube + test_common::run_test_cases( + {"bunny.off", "elephant.off", "hemisphere.obj"}, + test_case); +} diff --git a/tests/include/igl/intrinsic_delaunay_cotmatrix.cpp b/tests/include/igl/intrinsic_delaunay_cotmatrix.cpp index 4b84be39e..23675c73c 100644 --- a/tests/include/igl/intrinsic_delaunay_cotmatrix.cpp +++ b/tests/include/igl/intrinsic_delaunay_cotmatrix.cpp @@ -37,13 +37,13 @@ TEST_CASE("intrinsic_delaunay_cotmatrix: skewed_grid", "[igl]") } } -TEST_CASE("intrinsic_delaunay_cotmatrix: manifold_meshes", "[igl]") +TEST_CASE("intrinsic_delaunay_cotmatrix: manifold_meshes", "[igl]" "[slow]") { auto test_case = [](const std::string ¶m) { Eigen::MatrixXd V; Eigen::MatrixXi F; - test_common::load_mesh(param, V, F); + igl::read_triangle_mesh(test_common::data_path(param), V, F); Eigen::SparseMatrix L; Eigen::MatrixXi F_intrinsic; Eigen::MatrixXd l_intrinsic; @@ -56,7 +56,7 @@ TEST_CASE("intrinsic_delaunay_cotmatrix: manifold_meshes", "[igl]") // Off diagonals should be all non-positive for(int k = 0;k() < LV(k)); diff --git a/tests/include/igl/is_edge_manifold.cpp b/tests/include/igl/is_edge_manifold.cpp index 5a5ede0ce..0c88a68e0 100644 --- a/tests/include/igl/is_edge_manifold.cpp +++ b/tests/include/igl/is_edge_manifold.cpp @@ -1,14 +1,13 @@ #include #include - -TEST_CASE("is_edge_manifold: positive", "[igl]") +TEST_CASE("is_edge_manifold: positive", "[igl]" "[slow]") { const auto test_case = [](const std::string ¶m) { Eigen::MatrixXd V; Eigen::MatrixXi F; - test_common::load_mesh(param, V, F); + igl::read_triangle_mesh(test_common::data_path(param), V, F); REQUIRE ( igl::is_edge_manifold(F) ); }; @@ -20,6 +19,6 @@ TEST_CASE("is_edge_manifold: negative", "[igl]") Eigen::MatrixXd V; Eigen::MatrixXi F; // Known non-manifold mesh - test_common::load_mesh("truck.obj", V, F); + igl::read_triangle_mesh(test_common::data_path("truck.obj"), V, F); REQUIRE (! igl::is_edge_manifold(F) ); } diff --git a/tests/include/igl/is_irregular_vertex.cpp b/tests/include/igl/is_irregular_vertex.cpp new file mode 100644 index 000000000..843f81d14 --- /dev/null +++ b/tests/include/igl/is_irregular_vertex.cpp @@ -0,0 +1,15 @@ +#include +#include + + +TEST_CASE("is_irregular_vertex: simple", "[igl]") +{ + Eigen::MatrixXd V; + Eigen::MatrixXi F; + // Known "bad" mesh (many boundaries + irregular vertices, non-manifold) + igl::read_triangle_mesh(test_common::data_path("truck.obj"), V, F); + std::vector vec = igl::is_irregular_vertex(V,F); + // some vertices are irregular thus the sum over all vertices should evaluate to true + REQUIRE(std::any_of(vec.begin(),vec.end(), [](bool v) { return v; })); + +} \ No newline at end of file diff --git a/tests/include/igl/iterative_closest_point.cpp b/tests/include/igl/iterative_closest_point.cpp new file mode 100644 index 000000000..b12806274 --- /dev/null +++ b/tests/include/igl/iterative_closest_point.cpp @@ -0,0 +1,32 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2019 Alec Jacobson +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// obtain one at http://mozilla.org/MPL/2.0/. +#include +#include + + +TEST_CASE("iterative_closest_point: identity","[igl]" "[slow]") +{ + const auto test_case = [](const std::string ¶m) + { + Eigen::MatrixXd VX,VY; + Eigen::MatrixXi FX,FY; + // Load example mesh: GetParam() will be name of mesh file + igl::read_triangle_mesh(test_common::data_path(param), VY, FY); + VX = VY; + FX = FY; + // Single iteration should find a identity + srand(0); + Eigen::Matrix3d R; + Eigen::RowVector3d t; + igl::iterative_closest_point(VX,FX,VY,FY,1000,1,R,t); + test_common::assert_near(R,Eigen::Matrix3d::Identity(),1e-12); + test_common::assert_near(t,Eigen::RowVector3d::Zero(),1e-12); + }; + + test_common::run_test_cases(test_common::all_meshes(), test_case); +} diff --git a/tests/include/igl/path_to_edges.cpp b/tests/include/igl/path_to_edges.cpp new file mode 100644 index 000000000..d02f2efde --- /dev/null +++ b/tests/include/igl/path_to_edges.cpp @@ -0,0 +1,53 @@ +#include +#include + +#include + +TEST_CASE("igl_path_to_edges: basic_test", "[igl]") +{ + const Eigen::VectorXi I = (Eigen::VectorXi(6)<<0,1,2,3,4,5).finished(); + const Eigen::MatrixXi Eexpected = (Eigen::MatrixXi(5,2)<<0,1, 1,2, 2,3, 3,4, 4,5).finished(); + + Eigen::MatrixXi Eactual; + igl::path_to_edges(I, Eactual); + + test_common::assert_eq(Eactual, Eexpected); +} + +#include + +TEST_CASE("igl_path_to_edges: loop_test", "[igl]") +{ + const Eigen::VectorXi I = (Eigen::VectorXi(6)<<0,1,2,3,4,5).finished(); + const Eigen::MatrixXi Eexpected = (Eigen::MatrixXi(6,2)<<0,1, 1,2, 2,3, 3,4, 4,5, 5,0).finished(); + + Eigen::MatrixXi Eactual; + const bool make_loop = true; + igl::path_to_edges(I, Eactual, make_loop); + std::cout << Eactual << std::endl; + test_common::assert_eq(Eactual, Eexpected); +} + +TEST_CASE("igl_path_to_edges: vector_basic_test", "[igl]") +{ + const std::vector I{0,1,2,3,4,5}; + const Eigen::MatrixXi Eexpected = (Eigen::MatrixXi(5,2)<<0,1, 1,2, 2,3, 3,4, 4,5).finished(); + + Eigen::MatrixXi Eactual; + igl::path_to_edges(I, Eactual); + + test_common::assert_eq(Eactual, Eexpected); +} + + +TEST_CASE("igl_path_to_edges: vector_loop_test", "[igl]") +{ + const std::vector I{0,1,2,3,4,5}; + const Eigen::MatrixXi Eexpected = (Eigen::MatrixXi(6,2)<<0,1, 1,2, 2,3, 3,4, 4,5, 5,0).finished(); + + Eigen::MatrixXi Eactual; + const bool make_loop = true; + igl::path_to_edges(I, Eactual, make_loop); + + test_common::assert_eq(Eactual, Eexpected); +} \ No newline at end of file diff --git a/tests/include/igl/path_to_executable.cpp b/tests/include/igl/path_to_executable.cpp new file mode 100644 index 000000000..f5c3ffdb3 --- /dev/null +++ b/tests/include/igl/path_to_executable.cpp @@ -0,0 +1,15 @@ +#include +#include + +#include + + +TEST_CASE("path_to_executable: example", "[igl]") +{ + std::string path_to_executable = igl::path_to_executable(); + REQUIRE(0 < path_to_executable.size()); + // check if path_to_executable ends with correct file name, on windows .exe suffix is added. + std::string executable = "libigl_tests"; + int pos = path_to_executable.length()-(executable.length() + 4/*".exe"*/); + REQUIRE( std::string::npos != path_to_executable.find(executable, pos)); +} diff --git a/tests/include/igl/per_face_normals.cpp b/tests/include/igl/per_face_normals.cpp index 8406c3905..a2546b764 100644 --- a/tests/include/igl/per_face_normals.cpp +++ b/tests/include/igl/per_face_normals.cpp @@ -3,14 +3,14 @@ #include #include -TEST_CASE("per_face_normals: dot", "[igl]") +TEST_CASE("per_face_normals: dot", "[igl]" "[slow]") { const auto test_case = [](const std::string ¶m) { Eigen::MatrixXd V,N; Eigen::MatrixXi F; // Load example mesh: GetParam() will be name of mesh file - test_common::load_mesh(param, V, F); + igl::read_triangle_mesh(test_common::data_path(param), V, F); igl::per_face_normals(V,F,N); REQUIRE (N.rows() == F.rows()); for(int f = 0;f +#include + +TEST_CASE("ear_clipping: boolean", "[igl/predicates]") +{ + // Example1: simple polygon + Eigen::MatrixXd polygon(10,2); + polygon<<2,-3,4,1,5.5,-2,6,2.5,5,1,4,5,3,0,1,1,1,5,0,0; + Eigen::VectorXi RT,nR,M; + Eigen::MatrixXi eF; + Eigen::MatrixXd nP; + RT.setZero(polygon.rows()); + igl::predicates::ear_clipping(polygon,RT,M,eF,nP); + REQUIRE(nP.rows() == 0); + +} diff --git a/tests/include/igl/predicates/segment_segment_intersect.cpp b/tests/include/igl/predicates/segment_segment_intersect.cpp new file mode 100644 index 000000000..14f1bb833 --- /dev/null +++ b/tests/include/igl/predicates/segment_segment_intersect.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +TEST_CASE("segment_segment_intersect: robust", "[igl/predicates]") +{ + // example 1: vanila intersecting case + auto A1 = Eigen::RowVector2d(0, 128.5); + auto B1 = Eigen::RowVector2d(-77.44,1.2); + auto C1 = Eigen::RowVector2d(-83.2,2.8); + auto D1 = Eigen::RowVector2d(-1.0,-1.0); + + bool check1 = igl::predicates::segment_segment_intersect(A1,B1,C1,D1); + REQUIRE(check1 == true); + + // example 2: colinear overlapping + auto A2 = Eigen::RowVector2d(1.0,5.0); + auto B2 = Eigen::RowVector2d(1.0,9.0); + auto C2 = Eigen::RowVector2d(1.0,8.0); + auto D2 = Eigen::RowVector2d(1.0,12.0); + + bool check2 = igl::predicates::segment_segment_intersect(A2,B2,C2,D2); + REQUIRE(check2 == true); + + // example 3: colinear touching endpoint + auto A3 = Eigen::RowVector2d(0.0,0.0); + auto B3 = Eigen::RowVector2d(1.5,1.5); + auto C3 = Eigen::RowVector2d(1.5,1.5); + auto D3 = Eigen::RowVector2d(2.0,2.0); + + bool check3 = igl::predicates::segment_segment_intersect(A3,B3,C3,D3); + REQUIRE(check3 == true); + + // example 6: colinear not touching endpoint + double eps = 1e-14; + auto A4 = Eigen::RowVector2d(0.0,0.0); + auto B4 = Eigen::RowVector2d(1.5,1.5); + auto C4 = Eigen::RowVector2d(1.5+eps,1.5+eps); + auto D4 = Eigen::RowVector2d(2.0,2.0); + bool check4 = igl::predicates::segment_segment_intersect(A4,B4,C4,D4); + REQUIRE(check4 == false); + +} \ No newline at end of file diff --git a/tests/include/igl/qslim.cpp b/tests/include/igl/qslim.cpp index 91804f82c..31d1e7c65 100644 --- a/tests/include/igl/qslim.cpp +++ b/tests/include/igl/qslim.cpp @@ -6,7 +6,7 @@ //#include #include -TEST_CASE("qslim: cylinder", "[igl]") +TEST_CASE("qslim: cylinder", "[igl]" "[slow]") { using namespace igl; const int axis_devisions = 5; @@ -19,7 +19,7 @@ TEST_CASE("qslim: cylinder", "[igl]") Eigen::VectorXi I,J; qslim(V,F,2*axis_devisions,U,G,I,J); REQUIRE (U.rows() == axis_devisions*2); - double l,u; + //double l,u; igl::writePLY("qslim-cylinder-vf.ply",V,F); igl::writePLY("qslim-cylinder-ug.ply",U,G); const auto & hausdorff_lower_bound = []( diff --git a/tests/include/igl/readDMAT.cpp b/tests/include/igl/readDMAT.cpp index 7660e907f..f442d9ec0 100644 --- a/tests/include/igl/readDMAT.cpp +++ b/tests/include/igl/readDMAT.cpp @@ -3,8 +3,8 @@ TEST_CASE("readDMAT: Comp", "[igl]") { Eigen::MatrixXd N1, N2; - test_common::load_matrix("duplicated_faces_N1.dmat", N1); - test_common::load_matrix("duplicated_faces_N2.dmat", N2); + igl::readDMAT(test_common::data_path("duplicated_faces_N1.dmat"), N1); + igl::readDMAT(test_common::data_path("duplicated_faces_N2.dmat"), N2); REQUIRE (N2.rows() == N1.rows()); REQUIRE (N2.cols() == N1.cols()); diff --git a/tests/include/igl/readOBJ.cpp b/tests/include/igl/readOBJ.cpp index 9589273fa..055549be4 100644 --- a/tests/include/igl/readOBJ.cpp +++ b/tests/include/igl/readOBJ.cpp @@ -1,4 +1,8 @@ +#include #include +#include +#include +#include TEST_CASE("readOBJ: simple", "[igl]") { @@ -6,7 +10,32 @@ TEST_CASE("readOBJ: simple", "[igl]") Eigen::MatrixXi F; // wait... so this is actually testing test_common::load_mesh not readOBJ // directly... - test_common::load_mesh("cube.obj", V, F); + igl::read_triangle_mesh(test_common::data_path("cube.obj"), V, F); REQUIRE (V.rows() == 8); REQUIRE (F.rows() == 12); } + +TEST_CASE("readOBJ: Obj with material", "[igl]") +{ + std::vector > V; + std::vector > TC; + std::vector > N; + std::vector > F; + std::vector > FTC; + std::vector > FN; + std::vector> FM; + igl::readOBJ(test_common::data_path("cubewithmaterial.obj"), V, TC, N, F, FTC, FN, FM); + + REQUIRE (V.size() == 8); + REQUIRE (F.size() == 6); + for ( const auto& i : FM ) { + std::cout << "material "; + std::cout << std::get<0>(i) << ' '; + std::cout << "fstart "; + std::cout << std::get<1>(i) << ' '; + std::cout << "fend "; + std::cout << std::get<2>(i) << ' '; + std::cout << std::endl; + } + REQUIRE (FM.size() == 2); +} diff --git a/tests/include/igl/readOFF.cpp b/tests/include/igl/readOFF.cpp index 607ca15c2..bc8905390 100644 --- a/tests/include/igl/readOFF.cpp +++ b/tests/include/igl/readOFF.cpp @@ -6,7 +6,7 @@ TEST_CASE("readOFF: simple", "[igl]") Eigen::MatrixXi F; // wait... so this is actually testing test_common::load_mesh not readOFF // directly... - test_common::load_mesh("cube.off", V, F); + igl::read_triangle_mesh(test_common::data_path("cube.off"), V, F); REQUIRE (V.rows() == 8); REQUIRE (V.cols() == 3); REQUIRE (F.rows() == 12); diff --git a/tests/include/igl/rigid_alignment.cpp b/tests/include/igl/rigid_alignment.cpp new file mode 100644 index 000000000..4a71871ec --- /dev/null +++ b/tests/include/igl/rigid_alignment.cpp @@ -0,0 +1,34 @@ +// This file is part of libigl, a simple c++ geometry processing library. +// +// Copyright (C) 2019 Alec Jacobson +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// obtain one at http://mozilla.org/MPL/2.0/. +#include +#include +#include +#include + + +TEST_CASE("rigid_alignment: identity", "[igl]") +{ + const Eigen::MatrixXd X = (Eigen::MatrixXd(10,3)<< + 0.814724,0.157613,0.655741, + 0.905792,0.970593,0.035712, + 0.126987,0.957167,0.849129, + 0.913376,0.485376,0.933993, + 0.632359,0.800280,0.678735, + 0.097540,0.141886,0.757740, + 0.278498,0.421761,0.743132, + 0.546882,0.915736,0.392227, + 0.957507,0.792207,0.655478, + 0.964889,0.959492,0.171187).finished(); + const Eigen::MatrixXd Y = X; + const Eigen::MatrixXd N = (Y.array()-0.5).matrix().rowwise().normalized(); + Eigen::Matrix3d R; + Eigen::RowVector3d t; + igl::rigid_alignment(X,Y,N,R,t); + test_common::assert_near(R,Eigen::Matrix3d::Identity(),1e-12); + test_common::assert_near(t,Eigen::RowVector3d::Zero(),1e-12); +} diff --git a/tests/include/igl/slice_sorted.cpp b/tests/include/igl/slice_sorted.cpp new file mode 100644 index 000000000..026c070ed --- /dev/null +++ b/tests/include/igl/slice_sorted.cpp @@ -0,0 +1,79 @@ +#include +#include +#include +#include + +namespace +{ + Eigen::SparseMatrix generate_random_sparse_matrix(int rows, int cols) + { + std::mt19937 gen; + std::uniform_real_distribution dist(0.0, 1.0); + + using T = Eigen::Triplet; + std::vector tripletList; + for (int i = 0; i < rows; ++i) + { + for (int j = 0; j < cols; ++j) + { + auto v_ij = dist(gen); // generate random number + if (v_ij < 0.1) + { + tripletList.push_back(T(i, j, v_ij)); // if larger than treshold, insert it + } + } + } + Eigen::SparseMatrix mat(rows, cols); + mat.setFromTriplets(tripletList.begin(), tripletList.end()); // create the matrix + return mat; + } + +} // namespace + +TEST_CASE("slice_sorted: correctness", "[igl]") +{ + constexpr int rows = 1e3; + constexpr int cols = 1e3; + + Eigen::SparseMatrix M = generate_random_sparse_matrix(rows, cols); + + Eigen::Matrix R(rows / 2); + Eigen::Matrix C(cols / 2); + for (int i = 0; i < rows; i += 2) R[i / 2] = i; + for (int i = 0; i < cols; i += 2) C[i / 2] = i; + + SECTION("correctness") + { + // Check for correctness + Eigen::SparseMatrix A, B; + igl::slice(M, R, C, A); + igl::slice_sorted(M, R, C, B); + REQUIRE((A - B).norm() == 0); + } +} + +TEST_CASE("slice_sorted: benchmark", "[igl]" IGL_DEBUG_OFF) +{ + constexpr int rows = 1e3; + constexpr int cols = 1e3; + + Eigen::SparseMatrix M = generate_random_sparse_matrix(rows, cols); + + Eigen::Matrix R(rows / 2); + Eigen::Matrix C(cols / 2); + for (int i = 0; i < rows; i += 2) R[i / 2] = i; + for (int i = 0; i < cols; i += 2) C[i / 2] = i; + + BENCHMARK("igl::slice") { + Eigen::SparseMatrix A; + igl::slice(M, R, C, A); + return A.norm(); + }; + + BENCHMARK("igl::slice_sorted") { + Eigen::SparseMatrix A; + igl::slice_sorted(M, R, C, A); + return A.norm(); + }; +} + diff --git a/tests/include/igl/squared_edge_lengths.cpp b/tests/include/igl/squared_edge_lengths.cpp index a0f0060eb..29bc76065 100644 --- a/tests/include/igl/squared_edge_lengths.cpp +++ b/tests/include/igl/squared_edge_lengths.cpp @@ -10,7 +10,7 @@ TEST_CASE("squared_edge_lengths: cube", "[igl]") Eigen::MatrixXd V; Eigen::MatrixXi F; //This is a cube of dimensions 1.0x1.0x1.0 - test_common::load_mesh("cube.obj", V, F); + igl::read_triangle_mesh(test_common::data_path("cube.obj"), V, F); //Create scaled versions of the cube double scale = 1.0; double huge_scale = 1.0e8; diff --git a/tests/include/igl/triangle_triangle_adjacency.cpp b/tests/include/igl/triangle_triangle_adjacency.cpp index 5ba832270..1cb11a147 100644 --- a/tests/include/igl/triangle_triangle_adjacency.cpp +++ b/tests/include/igl/triangle_triangle_adjacency.cpp @@ -3,15 +3,14 @@ #include #include - -TEST_CASE("triangle_triangle_adjacency: dot", "[igl]") +TEST_CASE("triangle_triangle_adjacency: dot", "[igl]" "[slow]") { const auto test_case = [](const std::string ¶m) { Eigen::MatrixXd V; Eigen::MatrixXi F,TT,TTi; // Load example mesh: GetParam() will be name of mesh file - test_common::load_mesh(param, V, F); + igl::read_triangle_mesh(test_common::data_path(param), V, F); igl::triangle_triangle_adjacency(F,TT,TTi); REQUIRE (TT.rows() == F.rows()); REQUIRE (TTi.rows() == F.rows()); diff --git a/tests/include/igl/upsample.cpp b/tests/include/igl/upsample.cpp index 5bd57e9a0..6864c6883 100644 --- a/tests/include/igl/upsample.cpp +++ b/tests/include/igl/upsample.cpp @@ -27,14 +27,14 @@ TEST_CASE("upsample: single_triangle", "[igl]") test_common::assert_eq(NV_groundtruth,NV); } -TEST_CASE("upsample: V_comes_first_F_ordering", "[igl]") +TEST_CASE("upsample: V_comes_first_F_ordering", "[igl]" "[slow]") { const auto test_case = [](const std::string ¶m) { Eigen::MatrixXd V,NV; Eigen::MatrixXi F,NF; // Load example mesh: GetParam() will be name of mesh file - test_common::load_mesh(param, V, F); + igl::read_triangle_mesh(test_common::data_path(param), V, F); igl::upsample(V,F,NV,NF); REQUIRE (V.rows() <= NV.rows()); REQUIRE (4*F.rows() == NF.rows()); diff --git a/tests/test_common.h b/tests/test_common.h index 8e5044be0..d7bd8c9ff 100644 --- a/tests/test_common.h +++ b/tests/test_common.h @@ -1,10 +1,12 @@ #pragma once - +// These are not directly used but would otherwise be included in most files. +// Leaving them included here. #include -#include #include +#include + #include #include @@ -14,13 +16,33 @@ #include #include +// Disable lengthy tests in debug mode +#ifdef NDEBUG +#define IGL_DEBUG_OFF "" +#else +#define IGL_DEBUG_OFF "[!hide]" +#endif + namespace test_common { template void run_test_cases(const std::vector ¶ms, Fun test_case) { for(const auto &p : params) + { + // Can't use INFO( p ) because we're not sure how to print p test_case(p); + } + } + + template + void run_test_cases(const std::vector ¶ms, Fun test_case) + { + for(const auto &p : params) + { + INFO( p ); + test_case(p); + } } inline std::vector closed_genus_0_meshes() @@ -74,29 +96,6 @@ namespace test_common return std::string(LIBIGL_DATA_DIR) + "/" + s; }; - // TODO: this seems like a pointless indirection. Should just find and - // replace test_common::load_mesh(X,...) with - // igl::read_triangle_mesh(test_common::data_path(X),...) - template - void load_mesh( - const std::string& filename, - Eigen::PlainObjectBase& V, - Eigen::PlainObjectBase& F) - { - igl::read_triangle_mesh(data_path(filename), V, F); - } - - // TODO: this seems like a pointless indirection. Should just find and - // replace test_common::load_matrix(X,...) with - // igl::readDMAT(test_common::data_path(X),...) - template - void load_matrix( - const std::string& filename, - Eigen::PlainObjectBase& M) - { - igl::readDMAT(data_path(filename), M); - } - template void assert_eq( const Eigen::MatrixBase & A, diff --git a/tutorial/104_Colors/main.cpp b/tutorial/104_Colors/main.cpp index c79d1e460..66ee7ff8b 100755 --- a/tutorial/104_Colors/main.cpp +++ b/tutorial/104_Colors/main.cpp @@ -1,6 +1,5 @@ #include #include -#include #include "tutorial_shared_path.h" Eigen::MatrixXd V; @@ -16,11 +15,10 @@ int main(int argc, char *argv[]) igl::opengl::glfw::Viewer viewer; viewer.data().set_mesh(V, F); - // Use the z coordinate as a scalar field over the surface - Eigen::VectorXd Z = V.col(2); - - // Compute per-vertex colors - igl::jet(Z,true,C); + // Use the (normalized) vertex positions as colors + C = + (V.rowwise() - V.colwise().minCoeff()).array().rowwise()/ + (V.colwise().maxCoeff() - V.colwise().minCoeff()).array(); // Add per-vertex colors viewer.data().set_colors(C); diff --git a/tutorial/105_Overlays/main.cpp b/tutorial/105_Overlays/main.cpp index 20fc83312..2570c8e63 100755 --- a/tutorial/105_Overlays/main.cpp +++ b/tutorial/105_Overlays/main.cpp @@ -67,6 +67,8 @@ int main(int argc, char *argv[]) std::stringstream l2; l2 << M(0) << ", " << M(1) << ", " << M(2); viewer.data().add_label(M,l2.str()); + // activate label rendering + viewer.data().show_labels = true; // Rendering of text labels is handled by ImGui, so we need to enable the ImGui // plugin to show text labels. diff --git a/tutorial/202_GaussianCurvature/main.cpp b/tutorial/202_GaussianCurvature/main.cpp index 734888d7f..bbf882aa3 100644 --- a/tutorial/202_GaussianCurvature/main.cpp +++ b/tutorial/202_GaussianCurvature/main.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include "tutorial_shared_path.h" int main(int argc, char *argv[]) @@ -24,13 +23,9 @@ int main(int argc, char *argv[]) // Divide by area to get integral average K = (Minv*K).eval(); - // Compute pseudocolor - MatrixXd C; - igl::jet(K,true,C); - // Plot the mesh with pseudocolors igl::opengl::glfw::Viewer viewer; viewer.data().set_mesh(V, F); - viewer.data().set_colors(C); + viewer.data().set_data(K); viewer.launch(); } diff --git a/tutorial/203_CurvatureDirections/main.cpp b/tutorial/203_CurvatureDirections/main.cpp index 5dc859ffa..73914aa86 100755 --- a/tutorial/203_CurvatureDirections/main.cpp +++ b/tutorial/203_CurvatureDirections/main.cpp @@ -46,11 +46,7 @@ int main(int argc, char *argv[]) igl::opengl::glfw::Viewer viewer; viewer.data().set_mesh(V, F); - - // Compute pseudocolor - MatrixXd C; - igl::parula(H,true,C); - viewer.data().set_colors(C); + viewer.data().set_data(H); // Average edge length for sizing const double avg = igl::avg_edge_length(V,F); diff --git a/tutorial/204_Gradient/main.cpp b/tutorial/204_Gradient/main.cpp index 45c9cf443..888d93a75 100755 --- a/tutorial/204_Gradient/main.cpp +++ b/tutorial/204_Gradient/main.cpp @@ -35,12 +35,7 @@ int main(int argc, char *argv[]) igl::opengl::glfw::Viewer viewer; viewer.data().set_mesh(V, F); - // Compute pseudocolor for original function - MatrixXd C; - igl::jet(U,true,C); - // // Or for gradient magnitude - //igl::jet(GU_mag,true,C); - viewer.data().set_colors(C); + viewer.data().set_data(U); // Average edge length divided by average gradient (for scaling) const double max_size = igl::avg_edge_length(V,F) / GU_mag.mean(); diff --git a/tutorial/206_GeodesicDistance/main.cpp b/tutorial/206_GeodesicDistance/main.cpp index c88cb663b..8041583de 100755 --- a/tutorial/206_GeodesicDistance/main.cpp +++ b/tutorial/206_GeodesicDistance/main.cpp @@ -1,8 +1,9 @@ #include #include #include -#include #include +#include +#include #include #include #include "tutorial_shared_path.h" @@ -29,15 +30,12 @@ int main(int argc, char *argv[]) Eigen::VectorXd d; std::cout<<"Computing geodesic distance to vertex "<bool + viewer.callback_key_down = + [&Z,&Z_const,&min_z,&max_z](igl::opengl::glfw::Viewer& viewer,unsigned char key,int mod)->bool { if(key == ' ') { - Data & data = *static_cast(viewer.callback_key_down_data); static bool toggle = true; - viewer.data().set_colors(toggle?data.C_const:data.C); + viewer.data().set_data(toggle?Z_const:Z,min_z,max_z); toggle = !toggle; return true; }else @@ -92,7 +84,6 @@ int main(int argc, char *argv[]) return false; } }; - viewer.callback_key_down_data = &data; cout<< "Press [space] to toggle between unconstrained and constrained."< list of singleton lists std::vector > S; + // S will hav size of low.V.rows() and each list inside will have 1 element igl::matrix_to_list(b,S); cout<<"Computing weights for "< M; igl::massmatrix(low.V,low.T,igl::MASSMATRIX_TYPE_DEFAULT,M); const size_t n = low.V.rows(); + // f = ma arap_data.f_ext = M * RowVector3d(0,-9.8,0).replicate(n,1); // Random initial velocities to wiggle things arap_data.vel = MatrixXd::Random(n,3); @@ -104,6 +126,7 @@ int main(int argc, char * argv[]) igl::opengl::glfw::Viewer viewer; // Create one huge mesh containing both meshes igl::cat(1,low.U,high.U,scene.U); + // need to remap the indices since we cat the V matrices igl::cat(1,low.F,MatrixXi(high.F.array()+low.V.rows()),scene.F); // Color each mesh viewer.data().set_mesh(scene.U,scene.F); diff --git a/tutorial/504_NRosyDesign/main.cpp b/tutorial/504_NRosyDesign/main.cpp index 871e361bf..dbb26ce90 100755 --- a/tutorial/504_NRosyDesign/main.cpp +++ b/tutorial/504_NRosyDesign/main.cpp @@ -85,13 +85,13 @@ void plot_mesh_nrosy( viewer.data().add_edges(Be,Be+Y*(avg/2),RowVector3d(0,0,1)); - // Plot the singularities as colored dots (red for negative, blue for positive) + // Plot the singularities as colored dots (red for positive, blue for negative) for (unsigned i=0; i 0.001) - viewer.data().add_points(V.row(i),RowVector3d(0,1,0)); + viewer.data().add_points(V.row(i),RowVector3d(1,0,0)); } // Highlight in red the constrained faces diff --git a/tutorial/602_Matlab/main.cpp b/tutorial/602_Matlab/main.cpp index 644e256b5..10cedb9cb 100755 --- a/tutorial/602_Matlab/main.cpp +++ b/tutorial/602_Matlab/main.cpp @@ -1,11 +1,14 @@ -#include +#include "tutorial_shared_path.h" + #include #include #include #include #include -#include "tutorial_shared_path.h" +// On mac you may need to issue something like: +// +// PATH=$PATH:/Applications/MATLAB_R2019a.app/bin/ ./tutorial/602_Matlab_bin // Base mesh Eigen::MatrixXd V; @@ -17,29 +20,13 @@ Engine* engine; // Eigenvectors of the laplacian Eigen::MatrixXd EV; -void plotEV(igl::opengl::glfw::Viewer& viewer, int id) -{ - Eigen::VectorXd v = EV.col(id); - v = v.array() - v.minCoeff(); - v = v.array() / v.maxCoeff(); - - // Map to colors using jet colorramp - Eigen::MatrixXd C(V.rows(),3); - for (unsigned i=0; i= '1' && key <= '9') - plotEV(viewer,(key - '1') + 1); + { + viewer.data().set_data(EV.col((key - '1') + 1)); + } return false; } @@ -77,7 +64,7 @@ int main(int argc, char *argv[]) viewer.data().set_mesh(V, F); // Plot the first non-trivial eigenvector - plotEV(viewer,1); + viewer.data().set_data(EV.col(1)); // Launch the viewer viewer.launch(); diff --git a/tutorial/604_Triangle/main.cpp b/tutorial/604_Triangle/main.cpp index 3167f4e8d..41034f208 100755 --- a/tutorial/604_Triangle/main.cpp +++ b/tutorial/604_Triangle/main.cpp @@ -19,15 +19,26 @@ int main(int argc, char *argv[]) E.resize(8,2); H.resize(1,2); + // create two squares, one with edge length of 4, + // one with edge length of 2 + // both centered at origin V << -1,-1, 1,-1, 1,1, -1, 1, -2,-2, 2,-2, 2,2, -2, 2; + // add the edges of the squares E << 0,1, 1,2, 2,3, 3,0, 4,5, 5,6, 6,7, 7,4; + // specify a point that is inside a closed shape + // where we do not want triangulation to happen H << 0,0; // Triangulate the interior + // a0.005 means that the area of each triangle should + // not be greater than 0.005 + // q means that no angles will be smaller than 20 degrees + // for a detailed set of commands please refer to: + // https://www.cs.cmu.edu/~quake/triangle.switch.html igl::triangle::triangulate(V,E,H,"a0.005q",V2,F2); // Plot the generated mesh diff --git a/tutorial/704_SignedDistance/main.cpp b/tutorial/704_SignedDistance/main.cpp index e05cd9536..3624c69e5 100755 --- a/tutorial/704_SignedDistance/main.cpp +++ b/tutorial/704_SignedDistance/main.cpp @@ -78,14 +78,8 @@ void update_visualization(igl::opengl::glfw::Viewer & viewer) // Bunny is a watertight mesh so use pseudonormal for signing signed_distance_pseudonormal(V_vis,V,F,tree,FN,VN,EN,EMAP,S_vis,I,C,N); } - // push to [0,1] range - S_vis.array() = 0.5*(S_vis.array()/max_distance)+0.5; - MatrixXd C_vis; - // color without normalizing - igl::parula(S_vis,false,C_vis); - - const auto & append_mesh = [&C_vis,&F_vis,&V_vis]( + const auto & append_mesh = [&F_vis,&V_vis]( const Eigen::MatrixXd & V, const Eigen::MatrixXi & F, const RowVector3d & color) @@ -94,8 +88,6 @@ void update_visualization(igl::opengl::glfw::Viewer & viewer) F_vis.bottomRows(F.rows()) = F.array()+V_vis.rows(); V_vis.conservativeResize(V_vis.rows()+V.rows(),3); V_vis.bottomRows(V.rows()) = V; - C_vis.conservativeResize(C_vis.rows()+V.rows(),3); - C_vis.bottomRows(V.rows()).rowwise() = color; }; if(overlay) { @@ -103,7 +95,7 @@ void update_visualization(igl::opengl::glfw::Viewer & viewer) } viewer.data().clear(); viewer.data().set_mesh(V_vis,F_vis); - viewer.data().set_colors(C_vis); + viewer.data().set_data(S_vis); viewer.core().lighting_factor = overlay; } diff --git a/tutorial/710_SCAF/main.cpp b/tutorial/710_SCAF/main.cpp index 107df79ce..28c523757 100755 --- a/tutorial/710_SCAF/main.cpp +++ b/tutorial/710_SCAF/main.cpp @@ -21,7 +21,7 @@ igl::Timer timer; igl::SCAFData scaf_data; bool show_uv = false; -float uv_scale = 0.2; +float uv_scale = 0.2f; bool key_down(igl::opengl::glfw::Viewer& viewer, unsigned char key, int modifier) { @@ -99,7 +99,7 @@ int main(int argc, char *argv[]) Eigen::MatrixXi F_filled; igl::topological_hole_fill(F, bnd, all_bnds, F_filled); igl::harmonic(F_filled, bnd, bnd_uv ,1, uv_init); - uv_init = uv_init.topRows(V.rows()); + uv_init.conservativeResize(V.rows(), 2); } Eigen::VectorXi b; Eigen::MatrixXd bc; diff --git a/tutorial/712_DataSmoothing/main.cpp b/tutorial/712_DataSmoothing/main.cpp index 2f863de59..fe9ed0e24 100755 --- a/tutorial/712_DataSmoothing/main.cpp +++ b/tutorial/712_DataSmoothing/main.cpp @@ -2,8 +2,8 @@ #include #include #include -#include -#include +#include +#include #include #include #include @@ -18,7 +18,6 @@ #include "tutorial_shared_path.h" -#include int main(int argc, char * argv[]) @@ -27,12 +26,11 @@ int main(int argc, char * argv[]) //Read our mesh Eigen::MatrixXd V; - Eigen::MatrixXi F, E; + Eigen::MatrixXi F; if(!igl::read_triangle_mesh( argc>1?argv[1]: TUTORIAL_SHARED_PATH "/beetle.off",V,F)) { std::cout << "Failed to load mesh." << std::endl; } - igl::edges(F,E); //Constructing an exact function to smooth Eigen::VectorXd zexact = V.block(0,2,V.rows(),1).array() @@ -88,14 +86,7 @@ int main(int argc, char * argv[]) default: return false; } - Eigen::MatrixXd isoV; - Eigen::MatrixXi isoE; - if(key!='2') - igl::isolines(V, F, *z, 30, isoV, isoE); - viewer.data().set_edges(isoV,isoE,Eigen::RowVector3d(0,0,0)); - Eigen::MatrixXd colors; - igl::jet(*z, true, colors); - viewer.data().set_colors(colors); + viewer.data().set_data(*z); return true; }; std::cout << R"(Usage: @@ -105,6 +96,11 @@ int main(int argc, char * argv[]) 4 Biharmonic smoothing (natural Hessian boundary) )"; + Eigen::MatrixXd CM; + igl::parula(Eigen::VectorXd::LinSpaced(21,0,1).eval(),false,CM); + igl::isolines_map(Eigen::MatrixXd(CM),CM); + viewer.data().set_colormap(CM); + viewer.data().set_data(znoisy); viewer.launch(); return 0; diff --git a/tutorial/716_HeatGeodesics/main.cpp b/tutorial/716_HeatGeodesics/main.cpp index c27bfc9c4..c2947d5fd 100755 --- a/tutorial/716_HeatGeodesics/main.cpp +++ b/tutorial/716_HeatGeodesics/main.cpp @@ -4,11 +4,28 @@ #include #include #include +#include #include #include #include #include +void set_colormap(igl::opengl::glfw::Viewer & viewer) +{ + const int num_intervals = 30; + Eigen::MatrixXd CM(num_intervals,3); + // Colormap texture + for(int i = 0;ibool @@ -43,20 +58,33 @@ int main(int argc, char *argv[]) if(igl::unproject_onto_mesh(Eigen::Vector2f(x,y), viewer.core().view, viewer.core().proj, viewer.core().viewport, V, F, fid, bc)) { - // 3d position of hit - const Eigen::RowVector3d m3 = - V.row(F(fid,0))*bc(0) + V.row(F(fid,1))*bc(1) + V.row(F(fid,2))*bc(2); - int cid = 0; - Eigen::Vector3d( - (V.row(F(fid,0))-m3).squaredNorm(), - (V.row(F(fid,1))-m3).squaredNorm(), - (V.row(F(fid,2))-m3).squaredNorm()).minCoeff(&cid); - const int vid = F(fid,cid); - C.row(vid)<<1,0,0; - Eigen::VectorXd D = Eigen::VectorXd::Zero(data.Grad.cols()); - D(vid) = 1; - igl::heat_geodesics_solve(data,(Eigen::VectorXi(1,1)<100000) + { + // 3d position of hit + const Eigen::RowVector3d m3 = + V.row(F(fid,0))*bc(0) + V.row(F(fid,1))*bc(1) + V.row(F(fid,2))*bc(2); + int cid = 0; + Eigen::Vector3d( + (V.row(F(fid,0))-m3).squaredNorm(), + (V.row(F(fid,1))-m3).squaredNorm(), + (V.row(F(fid,2))-m3).squaredNorm()).minCoeff(&cid); + const int vid = F(fid,cid); + igl::heat_geodesics_solve(data,(Eigen::VectorXi(1,1)< +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char *argv[]) +{ + const auto time = [](std::function func)->double + { + const double t_before = igl::get_seconds(); + func(); + const double t_after = igl::get_seconds(); + return t_after-t_before; + }; + + Eigen::MatrixXd V; + Eigen::MatrixXi F; + igl::read_triangle_mesh(argc>1?argv[1]:TUTORIAL_SHARED_PATH "/bunny.off",V,F); + // Sample mesh for point cloud + Eigen::MatrixXd P,N; + { + Eigen::VectorXi I; + Eigen::SparseMatrix B; + igl::random_points_on_mesh(10000,V,F,B,I); + P = B*V; + Eigen::MatrixXd FN; + igl::per_face_normals(V,F,FN); + N.resize(P.rows(),3); + for(int p = 0;p > O_PI; + Eigen::MatrixXi O_CH; + Eigen::MatrixXd O_CN; + Eigen::VectorXd O_W; + igl::octree(P,O_PI,O_CH,O_CN,O_W); + Eigen::VectorXd A; + { + Eigen::MatrixXi I; + igl::knn(P,20,O_PI,O_CH,O_CN,O_W,I); + // CGAL is only used to help get point areas + igl::copyleft::cgal::point_areas(P,I,N,A); + } + + if(argc<=1) + { + // corrupt mesh + Eigen::MatrixXd BC; + igl::barycenter(V,F,BC); + Eigen::MatrixXd OV = V; + V.resize(F.rows()*3,3); + for(int f = 0;f (rand()) / static_cast (RAND_MAX), + Eigen::Vector3d::Random(3,1)); + V.row(v) = (OV.row(F(f,c))-BC.row(f))*R.matrix()+BC.row(f); + F(f,c) = v; + } + } + } + + // Generate a list of random query points in the bounding box + Eigen::MatrixXd Q = Eigen::MatrixXd::Random(1000000,3); + const Eigen::RowVector3d Vmin = V.colwise().minCoeff(); + const Eigen::RowVector3d Vmax = V.colwise().maxCoeff(); + const Eigen::RowVector3d Vdiag = Vmax-Vmin; + for(int q = 0;q0.5).eval(),1,QiP); + } + + // Positions of points inside of triangle soup (V,F) + Eigen::MatrixXd QiV; + { + igl::FastWindingNumberBVH fwn_bvh; + printf("triangle soup precomputation (% 8ld triangles): %g secs\n", + F.rows(), + time([&](){igl::fast_winding_number(V.cast().eval(),F,2,fwn_bvh);})); + Eigen::VectorXf WiV; + printf(" triangle soup evaluation (% 8ld queries): %g secs\n", + Q.rows(), + time([&](){igl::fast_winding_number(fwn_bvh,2,Q.cast().eval(),WiV);})); + igl::slice_mask(Q,WiV.array()>0.5,1,QiV); + } + + + // Visualization + igl::opengl::glfw::Viewer viewer; + // For dislpaying normals as little line segments + Eigen::MatrixXd PN(2*P.rows(),3); + Eigen::MatrixXi E(P.rows(),2); + const double bbd = igl::bounding_box_diagonal(V); + for(int p = 0;p +// +// This Source Code Form is subject to the terms of the Mozilla Public License +// v. 2.0. If a copy of the MPL was not distributed with this file, You can +// obtain one at http://mozilla.org/MPL/2.0/. +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int main(int argc, char * argv[]) +{ + Eigen::MatrixXd OVX,VX,VY; + Eigen::MatrixXi FX,FY; + igl::read_triangle_mesh( argc>1?argv[1]: TUTORIAL_SHARED_PATH "/decimated-max.obj",VY,FY); + const double bbd = (VY.colwise().maxCoeff()-VY.colwise().minCoeff()).norm(); + FX = FY; + { + // sprinkle a noise so that we can see z-fighting when the match is perfect. + const double h = igl::avg_edge_length(VY,FY); + OVX = VY + 1e-2*h*Eigen::MatrixXd::Random(VY.rows(),VY.cols()); + } + + VX = OVX; + + igl::AABB Ytree; + Ytree.init(VY,FY); + Eigen::MatrixXd NY; + igl::per_face_normals(VY,FY,NY); + + igl::opengl::glfw::Viewer v; + std::cout<bool + { + if(v.core().is_animating) + { + single_iteration(); + } + return false; + }; + v.callback_key_pressed = + [&](igl::opengl::glfw::Viewer &,unsigned char key,int)->bool + { + switch(key) + { + case ' ': + { + v.core().is_animating = false; + single_iteration(); + return true; + } + case 'R': + case 'r': + // Random rigid transformation + apply_random_rotation(); + v.data().set_mesh(VX,FX); + v.data().compute_normals(); + return true; + break; + } + return false; + }; + + v.data().set_mesh(VY,FY); + v.data().set_colors(Eigen::RowVector3d(1,1,1)); + v.data().show_lines = false; + v.append_mesh(); + v.data().set_mesh(VX,FX); + v.data().show_lines = false; + v.launch(); +} diff --git a/tutorial/CMakeLists.txt b/tutorial/CMakeLists.txt index 1307e1df6..32fd95d26 100644 --- a/tutorial/CMakeLists.txt +++ b/tutorial/CMakeLists.txt @@ -155,4 +155,8 @@ if(TUTORIALS_CHAPTER7) endif() add_subdirectory("715_MeshImplicitFunction") add_subdirectory("716_HeatGeodesics") + if(LIBIGL_WITH_CGAL) + add_subdirectory("717_FastWindingNumber") + endif() + add_subdirectory("718_IterativeClosestPoint") endif()