Compare commits
96
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
40e7900ccb | ||
|
|
b443ac0261 | ||
|
|
b286e13ac6 | ||
|
|
e91ffcb549 | ||
|
|
d9524ade53 | ||
|
|
89267b4a80 | ||
|
|
7c3c05d637 | ||
|
|
7888711039 | ||
|
|
08be0704c2 | ||
|
|
0e360d5250 | ||
|
|
5e561c28c8 | ||
|
|
25d63024bb | ||
|
|
f85a3c76db | ||
|
|
0c9c8cd643 | ||
|
|
a72b9386c8 | ||
|
|
ba69acc509 | ||
|
|
a221faf1e4 | ||
|
|
69e2b7ee67 | ||
|
|
667101084a | ||
|
|
7472691fe6 | ||
|
|
20c3ee0740 | ||
|
|
5067c8b7eb | ||
|
|
c2f96e8e18 | ||
|
|
f962e4a6b6 | ||
|
|
5d93f800ba | ||
|
|
8aca5bd0c4 | ||
|
|
fac5d4a01d | ||
|
|
0e02103df7 | ||
|
|
dd9654a476 | ||
|
|
01f2dc0a60 | ||
|
|
8afe66e8fd | ||
|
|
6e32964a82 | ||
|
|
dafd52343b | ||
|
|
36930e5d19 | ||
|
|
b4d8556a6b | ||
|
|
81180a6e6a | ||
|
|
a8819dcf9b | ||
|
|
1886d18147 | ||
|
|
7e6bf3b81c | ||
|
|
c7a84522c3 | ||
|
|
fe65ecb907 | ||
|
|
33a931d019 | ||
|
|
94c6afde11 | ||
|
|
8185a213d0 | ||
|
|
7d1614af1e | ||
|
|
293e79ff86 | ||
|
|
37f3b1d821 | ||
|
|
a8b3833942 | ||
|
|
7f7f0fe007 | ||
|
|
0b9030b1ed | ||
|
|
112c1b8e48 | ||
|
|
7c9387c92b | ||
|
|
1c8c6d38ba | ||
|
|
7991ee81d8 | ||
|
|
fdaac01bcc | ||
|
|
b4152c576c | ||
|
|
1b07ebcf9e | ||
|
|
64c2740230 | ||
|
|
2b05343e0d | ||
|
|
7547801f58 | ||
|
|
d154f0587c | ||
|
|
dddfd92c7a | ||
|
|
6ddf3b0dd7 | ||
|
|
e139702373 | ||
|
|
fe8e17c095 | ||
|
|
0c78def493 | ||
|
|
3c0f31f132 | ||
|
|
2b62322cd5 | ||
|
|
cb111f6838 | ||
|
|
68684132e5 | ||
|
|
0c1865a8d6 | ||
|
|
5dcce37c9d | ||
|
|
d6448a86fb | ||
|
|
6a31dbf126 | ||
|
|
321d0d8ed0 | ||
|
|
9bfacf8fb6 | ||
|
|
f48c5a93f1 | ||
|
|
d326251896 | ||
|
|
74160c4c1c | ||
|
|
b774e1b31c | ||
|
|
f5702f63e7 | ||
|
|
0262ef5866 | ||
|
|
9350803420 | ||
|
|
0e39b473b1 | ||
|
|
7a84503c8e | ||
|
|
deae7a2767 | ||
|
|
a0bb5bb813 | ||
|
|
5779714a5b | ||
|
|
687530283c | ||
|
|
5c17f85621 | ||
|
|
e5e0539e7d | ||
|
|
eee808949e | ||
|
|
75209c5d6c | ||
|
|
ab6229c77a | ||
|
|
b1fe6ba49c | ||
|
|
8d940367bf |
@@ -0,0 +1,20 @@
|
||||
# Set the default behavior, in case people don't have core.autocrlf set.
|
||||
* text=auto
|
||||
|
||||
# Explicitly declare text files you want to always be normalized and converted
|
||||
# to native line endings on checkout.
|
||||
*.tex text
|
||||
*.bib text
|
||||
*.svg text
|
||||
*.py text
|
||||
*.vbs text
|
||||
*.cpp text
|
||||
*.hpp text
|
||||
Makefile text
|
||||
|
||||
# Declare files that will always have CRLF line endings on checkout.
|
||||
*.sln text eol=crlf
|
||||
|
||||
# Denote all files that are truly binary and should not be modified.
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
@@ -25,7 +25,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu-20.04, macos-latest]
|
||||
os: [ubuntu-24.04, macos-latest]
|
||||
config: [Release]
|
||||
build-params: [ {static: ON, tutorials: ON, tests: ON }, {static: OFF, tutorials: OFF, tests: ON }, {static: OFF, tutorials: ON, tests: OFF }]
|
||||
env:
|
||||
@@ -52,9 +52,15 @@ jobs:
|
||||
run: |
|
||||
HOMEBREW_NO_AUTO_UPDATE=1 brew install ccache
|
||||
|
||||
- name: Setup Xcode version
|
||||
if: runner.os == 'macOS'
|
||||
uses: maxim-lobanov/setup-xcode@v1
|
||||
with:
|
||||
xcode-version: '15.2'
|
||||
|
||||
- name: Cache Build
|
||||
id: cache-build
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.ccache
|
||||
key: ${{ runner.os }}-${{ matrix.config }}-${{ matrix.build-params.static }}-cache
|
||||
@@ -68,11 +74,14 @@ jobs:
|
||||
run: |
|
||||
mkdir -p build
|
||||
cd build
|
||||
# https://github.com/eclipse-ecal/ecal/issues/2041
|
||||
cmake .. \
|
||||
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 \
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.config }} \
|
||||
-DLIBIGL_USE_STATIC_LIBRARY=${{ matrix.build-params.static }} \
|
||||
-DLIBIGL_BUILD_TUTORIALS=${{ matrix.build-params.tutorials }} \
|
||||
-DLIBIGL_GLFW_TESTS=OFF \
|
||||
-DLIBIGL_BUILD_TESTS=${{ matrix.build-params.tests }} \
|
||||
-DLIBIGL_COPYLEFT_CGAL=ON
|
||||
|
||||
@@ -80,7 +89,7 @@ jobs:
|
||||
run: cd build; make -j2; ccache --show-stats
|
||||
|
||||
- name: Tests
|
||||
run: cd build; ctest --verbose
|
||||
run: cd build; ctest --show-only; ctest --verbose
|
||||
|
||||
####################
|
||||
# Windows
|
||||
@@ -121,7 +130,7 @@ jobs:
|
||||
|
||||
- name: Cache build
|
||||
id: cache-build
|
||||
uses: actions/cache@v2
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ env.appdata }}\Mozilla\sccache
|
||||
key: ${{ runner.os }}-${{ matrix.config }}-${{ matrix.build-params.static }}-cache
|
||||
@@ -138,13 +147,16 @@ jobs:
|
||||
shell: cmd
|
||||
run: |
|
||||
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=x64
|
||||
# https://github.com/eclipse-ecal/ecal/issues/2041
|
||||
cmake -G Ninja ^
|
||||
-DCMAKE_POLICY_VERSION_MINIMUM=3.5 ^
|
||||
-DCMAKE_CXX_COMPILER_LAUNCHER=sccache ^
|
||||
-DCMAKE_BUILD_TYPE=${{ matrix.config }} ^
|
||||
-DLIBIGL_USE_STATIC_LIBRARY=${{ matrix.build-params.static }} ^
|
||||
-DLIBIGL_COPYLEFT_CGAL=ON ^
|
||||
-DLIBIGL_BUILD_TUTORIALS=${{ matrix.build-params.tutorials }} ^
|
||||
-DLIBIGL_BUILD_TESTS=${{ matrix.build-params.tests }} ^
|
||||
-DLIBIGL_GLFW_TESTS=OFF ^
|
||||
-DLIBIGL_TUTORIALS_CHAPTER1=${{ (matrix.build-params.selected_tutorial == 'NONE' || matrix.build-params.selected_tutorial == '1') && 'ON' || 'OFF' }} ^
|
||||
-DLIBIGL_TUTORIALS_CHAPTER2=${{ (matrix.build-params.selected_tutorial == 'NONE' || matrix.build-params.selected_tutorial == '2') && 'ON' || 'OFF' }} ^
|
||||
-DLIBIGL_TUTORIALS_CHAPTER3=${{ (matrix.build-params.selected_tutorial == 'NONE' || matrix.build-params.selected_tutorial == '3') && 'ON' || 'OFF' }} ^
|
||||
@@ -159,5 +171,5 @@ jobs:
|
||||
cmake --build build -j2
|
||||
|
||||
- name: Tests
|
||||
run: cd build; ctest --verbose -j2
|
||||
run: cd build; ctest --show-only; ctest --verbose -j2
|
||||
|
||||
|
||||
@@ -48,3 +48,6 @@ LibiglOptions.cmake
|
||||
# macos debris
|
||||
.DS_Store
|
||||
*~
|
||||
dox/
|
||||
latex/
|
||||
scripts/
|
||||
|
||||
+9
-1
@@ -6,6 +6,8 @@ else()
|
||||
set(LIBIGL_TOPLEVEL_PROJECT OFF)
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
# Check required CMake version
|
||||
set(REQUIRED_CMAKE_VERSION "3.16.0")
|
||||
if(LIBIGL_TOPLEVEL_PROJECT)
|
||||
@@ -35,7 +37,7 @@ if(HUNTER_ENABLED)
|
||||
endif()
|
||||
|
||||
################################################################################
|
||||
project(libigl VERSION 2.4.0)
|
||||
project(libigl VERSION 2.5.0)
|
||||
|
||||
# CMake module path
|
||||
list(PREPEND CMAKE_MODULE_PATH
|
||||
@@ -119,6 +121,12 @@ option(LIBIGL_RESTRICTED_MATLAB "Build target igl_restricted::matlab" ${LIBI
|
||||
option(LIBIGL_RESTRICTED_MOSEK "Build target igl_restricted::mosek" ${LIBIGL_DEFAULT_MOSEK})
|
||||
option(LIBIGL_RESTRICTED_TRIANGLE "Build target igl_restricted::triangle" ${LIBIGL_TOPLEVEL_PROJECT})
|
||||
|
||||
# GLFW doesn't run on headless CI machines so don't run (or build them).
|
||||
# Unfortunately on headless mac machines glfw seems to hang rather than crash
|
||||
# making it hard to catch at runtime.
|
||||
option(LIBIGL_GLFW_TESTS "Build igl::glfw tests" ${LIBIGL_TOPLEVEL_PROJECT})
|
||||
|
||||
option(LIBIGL_WARNINGS_AS_ERRORS "Turn on many warnings and treat as errors" OFF)
|
||||
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin")
|
||||
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
# Try to find the GNU Multiple Precision Arithmetic Library (GMP)
|
||||
# See http://gmplib.org/
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.18.0")
|
||||
set(REQUIRED_FLAG "")
|
||||
else()
|
||||
set(REQUIRED_FLAG REQUIRED)
|
||||
endif()
|
||||
|
||||
# On Windows, we must use the pre-compiled versions downloaded with libigl
|
||||
if(WIN32)
|
||||
set(NO_DEFAULT_FLAG NO_DEFAULT_PATH)
|
||||
else()
|
||||
set(NO_DEFAULT_FLAG "")
|
||||
endif()
|
||||
|
||||
find_path(GMP_INCLUDES
|
||||
NAMES
|
||||
gmp.h
|
||||
PATHS
|
||||
ENV GMP_DIR
|
||||
${INCLUDE_INSTALL_DIR}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
${REQUIRED_FLAG}
|
||||
${NO_DEFAULT_FLAG}
|
||||
)
|
||||
|
||||
find_library(GMP_LIBRARIES
|
||||
NAMES
|
||||
gmp
|
||||
libgmp-10
|
||||
PATHS
|
||||
ENV GMP_DIR
|
||||
${LIB_INSTALL_DIR}
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
${REQUIRED_FLAG}
|
||||
${NO_DEFAULT_FLAG}
|
||||
)
|
||||
|
||||
set(GMP_EXTRA_VARS "")
|
||||
if(WIN32)
|
||||
# Find dll file and set IMPORTED_LOCATION to the .dll file
|
||||
find_file(GMP_RUNTIME_LIB
|
||||
NAMES
|
||||
gmp.dll
|
||||
libgmp-10.dll
|
||||
PATHS
|
||||
ENV GMP_DIR
|
||||
${LIB_INSTALL_DIR}
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
${REQUIRED_FLAG}
|
||||
${NO_DEFAULT_FLAG}
|
||||
)
|
||||
list(APPEND GMP_EXTRA_VARS GMP_RUNTIME_LIB)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(GMP
|
||||
REQUIRED_VARS
|
||||
GMP_INCLUDES
|
||||
GMP_LIBRARIES
|
||||
${GMP_EXTRA_VARS}
|
||||
REASON_FAILURE_MESSAGE
|
||||
"GMP is not installed on your system. Either install GMP using your preferred package manager, or disable libigl modules that depend on GMP, such as CGAL. See LibiglOptions.cmake.sample for configuration options. Do not forget to delete your <build>/CMakeCache.txt for the changes to take effect."
|
||||
)
|
||||
mark_as_advanced(GMP_INCLUDES GMP_LIBRARIES)
|
||||
|
||||
if(GMP_INCLUDES AND GMP_LIBRARIES AND NOT TARGET gmp::gmp)
|
||||
if(GMP_RUNTIME_LIB)
|
||||
add_library(gmp::gmp SHARED IMPORTED)
|
||||
else()
|
||||
add_library(gmp::gmp UNKNOWN IMPORTED)
|
||||
endif()
|
||||
|
||||
# Set public header location and link language
|
||||
set_target_properties(gmp::gmp PROPERTIES
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${GMP_INCLUDES}"
|
||||
)
|
||||
|
||||
# Set lib location. On Windows we specify both the .lib and the .dll paths
|
||||
if(GMP_RUNTIME_LIB)
|
||||
set_target_properties(gmp::gmp PROPERTIES
|
||||
IMPORTED_IMPLIB "${GMP_LIBRARIES}"
|
||||
IMPORTED_LOCATION "${GMP_RUNTIME_LIB}"
|
||||
)
|
||||
else()
|
||||
set_target_properties(gmp::gmp PROPERTIES
|
||||
IMPORTED_LOCATION "${GMP_LIBRARIES}"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
@@ -1,95 +0,0 @@
|
||||
# Try to find the MPFR library
|
||||
# See http://www.mpfr.org/
|
||||
|
||||
if(${CMAKE_VERSION} VERSION_LESS "3.18.0")
|
||||
set(REQUIRED_FLAG "")
|
||||
else()
|
||||
set(REQUIRED_FLAG REQUIRED)
|
||||
endif()
|
||||
|
||||
# On Windows, we must use the pre-compiled versions downloaded with libigl
|
||||
if(WIN32)
|
||||
set(NO_DEFAULT_FLAG NO_DEFAULT_PATH)
|
||||
else()
|
||||
set(NO_DEFAULT_FLAG "")
|
||||
endif()
|
||||
|
||||
find_path(MPFR_INCLUDES
|
||||
NAMES
|
||||
mpfr.h
|
||||
PATHS
|
||||
ENV MPFR_DIR
|
||||
${INCLUDE_INSTALL_DIR}
|
||||
PATH_SUFFIXES
|
||||
include
|
||||
${REQUIRED_FLAG}
|
||||
${NO_DEFAULT_FLAG}
|
||||
)
|
||||
|
||||
find_library(MPFR_LIBRARIES
|
||||
NAMES
|
||||
mpfr
|
||||
libmpfr-4
|
||||
PATHS
|
||||
ENV MPFR_DIR
|
||||
${LIB_INSTALL_DIR}
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
${REQUIRED_FLAG}
|
||||
${NO_DEFAULT_FLAG}
|
||||
)
|
||||
|
||||
set(MPFR_EXTRA_VARS "")
|
||||
if(WIN32)
|
||||
# Find dll file and set IMPORTED_LOCATION to the .dll file
|
||||
find_file(MPFR_RUNTIME_LIB
|
||||
NAMES
|
||||
mpfr.dll
|
||||
libmpfr-4.dll
|
||||
PATHS
|
||||
ENV MPFR_DIR
|
||||
${LIB_INSTALL_DIR}
|
||||
PATH_SUFFIXES
|
||||
lib
|
||||
${REQUIRED_FLAG}
|
||||
${NO_DEFAULT_FLAG}
|
||||
)
|
||||
list(APPEND MPFR_EXTRA_VARS MPFR_RUNTIME_LIB)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(MPFR
|
||||
REQUIRED_VARS
|
||||
MPFR_INCLUDES
|
||||
MPFR_LIBRARIES
|
||||
${MPFR_EXTRA_VARS}
|
||||
REASON_FAILURE_MESSAGE
|
||||
"MPFR is not installed on your system. Either install MPFR using your preferred package manager, or disable libigl modules that depend on MPFR, such as CGAL. See LibiglOptions.cmake.sample for configuration options. Do not forget to delete your <build>/CMakeCache.txt for the changes to take effect."
|
||||
)
|
||||
mark_as_advanced(MPFR_INCLUDES MPFR_LIBRARIES)
|
||||
|
||||
if(MPFR_INCLUDES AND MPFR_LIBRARIES AND NOT TARGET mpfr::mpfr)
|
||||
if(MPFR_RUNTIME_LIB)
|
||||
add_library(mpfr::mpfr SHARED IMPORTED)
|
||||
else()
|
||||
add_library(mpfr::mpfr UNKNOWN IMPORTED)
|
||||
endif()
|
||||
|
||||
# Set public header location and link language
|
||||
set_target_properties(mpfr::mpfr PROPERTIES
|
||||
IMPORTED_LINK_INTERFACE_LANGUAGES "C"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${MPFR_INCLUDES}"
|
||||
)
|
||||
|
||||
# Set lib location. On Windows we specify both the .lib and the .dll paths
|
||||
if(MPFR_RUNTIME_LIB)
|
||||
set_target_properties(mpfr::mpfr PROPERTIES
|
||||
IMPORTED_IMPLIB "${MPFR_LIBRARIES}"
|
||||
IMPORTED_LOCATION "${MPFR_RUNTIME_LIB}"
|
||||
)
|
||||
else()
|
||||
set_target_properties(mpfr::mpfr PROPERTIES
|
||||
IMPORTED_LOCATION "${MPFR_LIBRARIES}"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
@@ -36,12 +36,17 @@ function(igl_add_library module_name)
|
||||
# C++11 features
|
||||
target_compile_features(${module_name} ${IGL_SCOPE} cxx_std_11)
|
||||
|
||||
if(LIBIGL_WARNINGS_AS_ERRORS)
|
||||
target_compile_options(${module_name} PRIVATE -Wall -Wextra -Wpedantic -Wno-sign-compare -Werror -Wno-gnu -Wno-unknown-pragmas)
|
||||
endif()
|
||||
|
||||
# Other compilation flags
|
||||
if(MSVC)
|
||||
# Enable parallel compilation for Visual Studio
|
||||
target_compile_options(${module_name} ${IGL_SCOPE} $<$<COMPILE_LANGUAGE:CXX>:/MP> $<$<COMPILE_LANGUAGE:CXX>:/bigobj>)
|
||||
target_compile_definitions(${module_name} ${IGL_SCOPE} -DNOMINMAX)
|
||||
|
||||
|
||||
# Silencing some compilation warnings
|
||||
if(LIBIGL_USE_STATIC_LIBRARY)
|
||||
target_compile_options(${module_name} PRIVATE
|
||||
|
||||
@@ -50,6 +50,10 @@ function(igl_copy_dll target)
|
||||
if(NOT WIN32)
|
||||
return()
|
||||
endif()
|
||||
if(NOT TARGET ${target})
|
||||
message(STATUS "igl_copy_dll() was called with a non-target: ${target}")
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Sanity checks
|
||||
get_target_property(TYPE ${target} TYPE)
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
# 1. Define module
|
||||
igl_add_library(igl_copyleft_comiso)
|
||||
|
||||
# 2. Include headers
|
||||
include(GNUInstallDirs)
|
||||
target_include_directories(igl_copyleft_comiso ${IGL_SCOPE}
|
||||
$<BUILD_INTERFACE:${libigl_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
|
||||
)
|
||||
|
||||
# 3. Target sources
|
||||
file(GLOB INC_FILES "${libigl_SOURCE_DIR}/include/igl/copyleft/comiso/*.h")
|
||||
file(GLOB SRC_FILES "${libigl_SOURCE_DIR}/include/igl/copyleft/comiso/*.cpp")
|
||||
igl_target_sources(igl_copyleft_comiso ${INC_FILES} ${SRC_FILES})
|
||||
|
||||
# 4. Dependencies
|
||||
include(comiso)
|
||||
igl_include(copyleft core)
|
||||
target_link_libraries(igl_copyleft_comiso ${IGL_SCOPE}
|
||||
igl::core
|
||||
igl_copyleft::core
|
||||
CoMISo::CoMISo
|
||||
)
|
||||
|
||||
# 5. Unit tests
|
||||
file(GLOB SRC_FILES "${libigl_SOURCE_DIR}/tests/include/igl/copyleft/comiso/*.cpp")
|
||||
igl_add_test(igl_copyleft_comiso ${SRC_FILES})
|
||||
@@ -21,3 +21,9 @@ target_link_libraries(igl_glfw ${IGL_SCOPE}
|
||||
igl::opengl
|
||||
glfw::glfw
|
||||
)
|
||||
|
||||
# 5. Unit tests
|
||||
if(LIBIGL_GLFW_TESTS)
|
||||
file(GLOB SRC_FILES "${libigl_SOURCE_DIR}/tests/include/igl/opengl/glfw/*.cpp")
|
||||
igl_add_test(igl_glfw ${SRC_FILES})
|
||||
endif()
|
||||
|
||||
@@ -25,7 +25,6 @@ igl_include_optional(xml)
|
||||
# Libigl copyleft modules
|
||||
igl_include_optional(copyleft core)
|
||||
igl_include_optional(copyleft cgal)
|
||||
igl_include_optional(copyleft comiso)
|
||||
igl_include_optional(copyleft tetgen)
|
||||
|
||||
# Libigl restricted modules
|
||||
|
||||
Vendored
+22
-26
@@ -4,32 +4,27 @@ endif()
|
||||
|
||||
message(STATUS "Third-party: creating targets 'Boost::boost'...")
|
||||
|
||||
cmake_minimum_required(VERSION 3.24) # Ensure modern FetchContent features
|
||||
project(BoostFetchExample)
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
# Define the Boost library to fetch
|
||||
FetchContent_Declare(
|
||||
boost-cmake
|
||||
GIT_REPOSITORY https://github.com/Orphis/boost-cmake.git
|
||||
GIT_TAG 7f97a08b64bd5d2e53e932ddf80c40544cf45edf
|
||||
Boost
|
||||
URL https://archives.boost.io/release/1.86.0/source/boost_1_86_0.tar.gz
|
||||
URL_HASH MD5=ac857d73bb754b718a039830b07b9624
|
||||
)
|
||||
# Fetch Boost
|
||||
FetchContent_MakeAvailable(Boost)
|
||||
|
||||
set(PREVIOUS_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
|
||||
set(OLD_CMAKE_POSITION_INDEPENDENT_CODE ${CMAKE_POSITION_INDEPENDENT_CODE})
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
# This guy will download boost using FetchContent
|
||||
FetchContent_GetProperties(boost-cmake)
|
||||
if(NOT boost-cmake_POPULATED)
|
||||
FetchContent_Populate(boost-cmake)
|
||||
# File lcid.cpp from Boost_locale.cpp doesn't compile on MSVC, so we exclude them from the default
|
||||
# targets being built by the project (only targets explicitly used by other targets will be built).
|
||||
add_subdirectory(${boost-cmake_SOURCE_DIR} ${boost-cmake_BINARY_DIR} EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
# Ensure Boost paths are set before CGAL
|
||||
set(Boost_INCLUDE_DIR ${boost_SOURCE_DIR})
|
||||
set(Boost_LIBRARY_DIR ${boost_BINARY_DIR})
|
||||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ${OLD_CMAKE_POSITION_INDEPENDENT_CODE})
|
||||
set(CMAKE_CXX_FLAGS "${PREVIOUS_CMAKE_CXX_FLAGS}")
|
||||
|
||||
# Set VS target folders
|
||||
set(boost_modules
|
||||
# Add Boost libraries needed for your project
|
||||
set(BOOST_LIBRARIES
|
||||
container
|
||||
regex
|
||||
atomic
|
||||
@@ -48,6 +43,7 @@ set(boost_modules
|
||||
log_setup
|
||||
unit_test_framework
|
||||
math
|
||||
multiprecision
|
||||
program_options
|
||||
timer
|
||||
random
|
||||
@@ -55,10 +51,10 @@ set(boost_modules
|
||||
system
|
||||
thread
|
||||
type_erasure
|
||||
)
|
||||
foreach(module IN ITEMS ${boost_modules})
|
||||
if(TARGET Boost_${module})
|
||||
set_target_properties(Boost_${module} PROPERTIES FOLDER ThirdParty/Boost)
|
||||
endif()
|
||||
endforeach()
|
||||
)
|
||||
|
||||
foreach(lib IN LISTS BOOST_LIBRARIES)
|
||||
add_library(boost_${lib} INTERFACE)
|
||||
target_include_directories(boost_${lib} INTERFACE ${Boost_SOURCE_DIR})
|
||||
target_link_libraries(boost_${lib} INTERFACE Boost::${lib})
|
||||
endforeach()
|
||||
|
||||
Vendored
+6
-14
@@ -7,8 +7,8 @@ message(STATUS "Third-party: creating target 'CGAL::CGAL'")
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
cgal
|
||||
URL https://github.com/CGAL/cgal/releases/download/v5.4/CGAL-5.4-library.tar.xz
|
||||
URL_MD5 996f7ee9ba1553edac60debb115699cd
|
||||
URL https://github.com/CGAL/cgal/releases/download/v6.0.1/CGAL-6.0.1-library.tar.xz
|
||||
URL_MD5 ea827f6778063e00554ae41f4c845492
|
||||
)
|
||||
FetchContent_GetProperties(cgal)
|
||||
if(cgal_POPULATED)
|
||||
@@ -29,29 +29,21 @@ function(cgal_import_target)
|
||||
set(${NAME}_ROOT ${CMAKE_CURRENT_BINARY_DIR}/${NAME} CACHE PATH "")
|
||||
endmacro()
|
||||
|
||||
include(gmp)
|
||||
include(mpfr)
|
||||
include(boost)
|
||||
|
||||
ignore_package(GMP 5.0.1)
|
||||
set(GMP_INCLUDE_DIR ${gmp_INCLUDE_DIR})
|
||||
set(GMP_LIBRARIES gmp::gmp)
|
||||
set(GMPXX_INCLUDE_DIR ${GMP_INCLUDE_DIR})
|
||||
set(GMPXX_LIBRARIES ${GMP_LIBRARIES})
|
||||
|
||||
ignore_package(MPFR 3.0.0)
|
||||
set(MPFR_INCLUDE_DIR "")
|
||||
set(MPFR_LIBRARIES mpfr::mpfr)
|
||||
|
||||
ignore_package(Boost 1.71.0)
|
||||
set(Boost_INCLUDE_DIRS "")
|
||||
set(Boost_LIBRARIES Boost::thread Boost::system)
|
||||
set(Boost_LIBRARIES Boost::thread Boost::system Boost::multiprecision)
|
||||
|
||||
# Prefer Config mode before Module mode to prevent CGAL from loading its own FindXXX.cmake
|
||||
set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE)
|
||||
|
||||
# https://stackoverflow.com/a/71714947/148668
|
||||
set(CGAL_DATA_DIR "unspecified")
|
||||
|
||||
set(CGAL_CMAKE_EXACT_NT_BACKEND "BOOST_BACKEND" CACHE STRING "CGAL exact NT backend")
|
||||
set(CGAL_DISABLE_GMP ON CACHE BOOL "Disable GMP")
|
||||
find_package(CGAL CONFIG COMPONENTS Core PATHS ${cgal_SOURCE_DIR} NO_DEFAULT_PATH)
|
||||
endfunction()
|
||||
|
||||
|
||||
Vendored
-31
@@ -1,31 +0,0 @@
|
||||
if(TARGET CoMISo::CoMISo)
|
||||
return()
|
||||
endif()
|
||||
|
||||
message(STATUS "Third-party: creating target 'CoMISo::CoMISo'")
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
comiso
|
||||
GIT_REPOSITORY https://github.com/libigl/CoMISo.git
|
||||
GIT_TAG 536440e714f412e7ef6c0b96b90ba37b1531bb39
|
||||
)
|
||||
|
||||
include(eigen)
|
||||
|
||||
FetchContent_MakeAvailable(comiso)
|
||||
|
||||
add_library(CoMISo::CoMISo ALIAS CoMISo)
|
||||
|
||||
# Copy .hh headers into a subfolder `CoMISo/`
|
||||
file(GLOB_RECURSE INC_FILES "${comiso_SOURCE_DIR}/*.hh" "${comiso_SOURCE_DIR}/*.cc")
|
||||
set(output_folder "${CMAKE_CURRENT_BINARY_DIR}/CoMISo/include/CoMISo")
|
||||
message(VERBOSE "Copying CoMISo headers to '${output_folder}'")
|
||||
foreach(filepath IN ITEMS ${INC_FILES})
|
||||
file(RELATIVE_PATH filename "${comiso_SOURCE_DIR}" ${filepath})
|
||||
configure_file(${filepath} "${output_folder}/${filename}" COPYONLY)
|
||||
endforeach()
|
||||
|
||||
target_include_directories(CoMISo PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/CoMISo/include)
|
||||
|
||||
set_target_properties(CoMISo PROPERTIES FOLDER ThirdParty)
|
||||
Vendored
+1
-1
@@ -8,7 +8,7 @@ include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
embree
|
||||
GIT_REPOSITORY https://github.com/embree/embree.git
|
||||
GIT_TAG v3.13.3
|
||||
GIT_TAG v4.4.0
|
||||
GIT_SHALLOW TRUE
|
||||
)
|
||||
|
||||
|
||||
Vendored
+1
-1
@@ -8,7 +8,7 @@ include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
glad
|
||||
GIT_REPOSITORY https://github.com/libigl/libigl-glad.git
|
||||
GIT_TAG ceef55fcd08bdd16e985370a99cfb60e69623221
|
||||
GIT_TAG 651a425101365aa6e8504988ef9bb363d066c5ee
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(glad)
|
||||
|
||||
Vendored
-96
@@ -1,96 +0,0 @@
|
||||
if(TARGET gmp::gmp)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Download precompiled .dll on Windows
|
||||
if(WIN32)
|
||||
include(gmp_mpfr)
|
||||
# Find_package will look for our downloaded lib on Windows, and system-wide on Linux/macOS
|
||||
find_package(GMP REQUIRED)
|
||||
else()
|
||||
message(STATUS "Third-party: creating target 'gmp::gmp'")
|
||||
|
||||
# SERIOUSLY !?! CMAKE and configure use transposed definitions of "build" and
|
||||
# "host"?
|
||||
#
|
||||
# https://cmake.org/cmake/help/latest/variable/CMAKE_SYSTEM_NAME.html#variable:CMAKE_SYSTEM_NAME
|
||||
# https://gcc.gnu.org/onlinedocs/gccint/Configure-Terms.html
|
||||
#
|
||||
# Seems these aren't to be trusted much
|
||||
# https://gitlab.kitware.com/cmake/cmake/-/issues/20989
|
||||
if(APPLE)
|
||||
# https://gmplib.org/list-archives/gmp-discuss/2020-November/006607.html
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
|
||||
set(gmp_BUILD "x86_64-apple-darwin")
|
||||
set(gmp_HOST "arm64-apple-darwin")
|
||||
set(gmp_CFLAGS "--target=arm64-apple-darwin")
|
||||
set(gmp_LDFLAGS "-arch arm64")
|
||||
message(STATUS "GMP Recipe notices building on ${gmp_BUILD} for ${gmp_HOST}")
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64" AND CMAKE_OSX_ARCHITECTURES STREQUAL "x86_64")
|
||||
set(gmp_HOST "x86_64-apple-darwin")
|
||||
set(gmp_BUILD "arm64-apple-darwin")
|
||||
set(gmp_CFLAGS "--target=x86_64-apple-darwin13.0.0")
|
||||
set(gmp_LDFLAGS "")
|
||||
message(STATUS "GMP Recipe notices building on ${gmp_HOST} for ${gmp_BUILD}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(FetchContent)
|
||||
include(ProcessorCount)
|
||||
ProcessorCount(Ncpu)
|
||||
include(ExternalProject)
|
||||
set(prefix ${FETCHCONTENT_BASE_DIR}/gmp)
|
||||
set(gmp_INSTALL ${prefix}/install)
|
||||
set(gmp_LIB_DIR ${gmp_INSTALL}/lib)
|
||||
set(gmp_LIBRARY
|
||||
${gmp_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gmp${CMAKE_STATIC_LIBRARY_SUFFIX}
|
||||
${gmp_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}gmpxx${CMAKE_STATIC_LIBRARY_SUFFIX}
|
||||
)
|
||||
set(gmp_INCLUDE_DIR ${gmp_INSTALL}/include)
|
||||
|
||||
# Try to use CONFIGURE_HANDLED_BY_BUILD ON to avoid constantly reconfiguring
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.20)
|
||||
# CMake < 3.20, do not use any extra option
|
||||
set(gmp_ExternalProject_Add_extra_options)
|
||||
else()
|
||||
# CMake >= 3.20
|
||||
set(gmp_ExternalProject_Add_extra_options "CONFIGURE_HANDLED_BY_BUILD;ON")
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(gmp
|
||||
PREFIX ${prefix}
|
||||
URL https://github.com/alisw/GMP/archive/refs/tags/v6.2.1.tar.gz
|
||||
URL_MD5 f060ad4e762ae550d16f1bb477aadba5
|
||||
UPDATE_DISCONNECTED true # need this to avoid constant rebuild
|
||||
PATCH_COMMAND
|
||||
curl "https://gist.githubusercontent.com/alecjacobson/d34d9307c17d1b853571699b9786e9d1/raw/8d14fc21cb7654f51c2e8df4deb0f82f9d0e8355/gmp-patch" "|" git apply -v
|
||||
${gmp_ExternalProject_Add_extra_options}
|
||||
CONFIGURE_COMMAND
|
||||
${CMAKE_COMMAND} -E env
|
||||
CFLAGS=${gmp_CFLAGS}
|
||||
LDFLAGS=${gmp_LDFLAGS}
|
||||
${prefix}/src/gmp/configure
|
||||
--disable-debug --disable-dependency-tracking --enable-cxx --with-pic
|
||||
--prefix=${gmp_INSTALL}
|
||||
--build=${gmp_BUILD}
|
||||
--host=${gmp_HOST}
|
||||
--disable-shared
|
||||
BUILD_COMMAND make -j${Ncpu}
|
||||
INSTALL_COMMAND make -j${Ncpu} install
|
||||
INSTALL_DIR ${gmp_INSTALL}
|
||||
TEST_COMMAND ""
|
||||
BUILD_BYPRODUCTS ${gmp_LIBRARY}
|
||||
)
|
||||
ExternalProject_Get_Property(gmp SOURCE_DIR)
|
||||
set(gmp_LIBRARIES ${gmp_LIBRARY})
|
||||
add_library(gmp::gmp INTERFACE IMPORTED GLOBAL)
|
||||
file(MAKE_DIRECTORY ${gmp_INCLUDE_DIR}) # avoid race condition
|
||||
target_include_directories(gmp::gmp INTERFACE ${gmp_INCLUDE_DIR})
|
||||
target_link_libraries(gmp::gmp INTERFACE "${gmp_LIBRARIES}") # need the quotes to expand list
|
||||
add_dependencies(gmp::gmp gmp)
|
||||
|
||||
endif()
|
||||
|
||||
if(NOT TARGET gmp::gmp)
|
||||
message(FATAL_ERROR "Creation of target 'gmp::gmp' failed")
|
||||
endif()
|
||||
-34
@@ -1,34 +0,0 @@
|
||||
if(WIN32)
|
||||
message(STATUS "Third-party: downloading gmp + mpfr")
|
||||
|
||||
include(FetchContent)
|
||||
|
||||
# CGAL 5+ ships with a single .zip combining GMP + MPFR's precompiled dlls.
|
||||
# For now we still download them separately.
|
||||
|
||||
FetchContent_Declare(
|
||||
gmp
|
||||
URL https://cgal.geometryfactory.com/CGAL/precompiled_libs/auxiliary/x64/GMP/5.0.1/gmp-all-CGAL-3.9.zip
|
||||
URL_MD5 508c1292319c832609329116a8234c9f
|
||||
)
|
||||
FetchContent_MakeAvailable(gmp)
|
||||
|
||||
FetchContent_Declare(
|
||||
mpfr
|
||||
URL https://cgal.geometryfactory.com/CGAL/precompiled_libs/auxiliary/x64/MPFR/3.0.0/mpfr-all-CGAL-3.9.zip
|
||||
URL_MD5 48840454eef0ff18730050c05028734b
|
||||
)
|
||||
FetchContent_MakeAvailable(mpfr)
|
||||
|
||||
# FetchContent_Declare(
|
||||
# gmp_mpfr
|
||||
# URL https://github.com/CGAL/cgal/releases/download/v5.2.1/CGAL-5.2.1-win64-auxiliary-libraries-gmp-mpfr.zip
|
||||
# URL_MD5 247f4dca741c6b9a9be76286414070fa
|
||||
# )
|
||||
|
||||
# For CGAL
|
||||
set(ENV{GMP_DIR} "${gmp_SOURCE_DIR}")
|
||||
set(ENV{MPFR_DIR} "${mpfr_SOURCE_DIR}")
|
||||
else()
|
||||
# On Linux/macOS, gmp+mpfr will be fetched and compiled
|
||||
endif()
|
||||
+3
-3
@@ -6,13 +6,13 @@ message(STATUS "Third-party: creating target 'igl::tests_data'")
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
libigl_tests_tata
|
||||
libigl_tests_data
|
||||
GIT_REPOSITORY https://github.com/libigl/libigl-tests-data
|
||||
GIT_TAG 19cedf96d70702d8b3a83eb27934780c542356fe
|
||||
)
|
||||
FetchContent_MakeAvailable(libigl_tests_tata)
|
||||
FetchContent_MakeAvailable(libigl_tests_data)
|
||||
|
||||
add_library(igl_tests_data INTERFACE)
|
||||
add_library(igl::tests_data ALIAS igl_tests_data)
|
||||
|
||||
target_compile_definitions(igl_tests_data INTERFACE LIBIGL_DATA_DIR=\"${libigl_tests_tata_SOURCE_DIR}\")
|
||||
target_compile_definitions(igl_tests_data INTERFACE LIBIGL_DATA_DIR=\"${libigl_tests_data_SOURCE_DIR}\")
|
||||
|
||||
+3
-3
@@ -6,13 +6,13 @@ message(STATUS "Third-party: creating target 'igl::tutorial_data'")
|
||||
|
||||
include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
libigl_tutorial_tata
|
||||
libigl_tutorial_data
|
||||
GIT_REPOSITORY https://github.com/libigl/libigl-tutorial-data
|
||||
GIT_TAG c1f9ede366d02e3531ecbaec5e3769312f31cccd
|
||||
)
|
||||
FetchContent_MakeAvailable(libigl_tutorial_tata)
|
||||
FetchContent_MakeAvailable(libigl_tutorial_data)
|
||||
|
||||
add_library(igl_tutorial_data INTERFACE)
|
||||
add_library(igl::tutorial_data ALIAS igl_tutorial_data)
|
||||
|
||||
target_compile_definitions(igl_tutorial_data INTERFACE "-DTUTORIAL_SHARED_PATH=\"${libigl_tutorial_tata_SOURCE_DIR}\"")
|
||||
target_compile_definitions(igl_tutorial_data INTERFACE "-DTUTORIAL_SHARED_PATH=\"${libigl_tutorial_data_SOURCE_DIR}\"")
|
||||
|
||||
Vendored
-91
@@ -1,91 +0,0 @@
|
||||
# Expects
|
||||
# gmp_INCLUDE_DIR
|
||||
# gmp_LIB_DIR
|
||||
# gmp_LIBRARIES
|
||||
if(TARGET mpfr::mpfr)
|
||||
return()
|
||||
endif()
|
||||
|
||||
# Download precompiled .dll on Windows
|
||||
if(WIN32)
|
||||
include(gmp_mpfr)
|
||||
# Find_package will look for our downloaded lib on Windows, and system-wide on Linux/macOS
|
||||
find_package(MPFR REQUIRED)
|
||||
else()
|
||||
message(STATUS "Third-party: creating target 'mpfr::mpfr'")
|
||||
|
||||
# Praying this will work the same as gmp
|
||||
if(APPLE)
|
||||
# https://gmplib.org/list-archives/gmp-discuss/2020-November/006607.html
|
||||
if(CMAKE_SYSTEM_PROCESSOR STREQUAL "x86_64" AND CMAKE_OSX_ARCHITECTURES STREQUAL "arm64")
|
||||
set(mpfr_BUILD "x86_64-apple-darwin")
|
||||
set(mpfr_HOST "arm64-apple-darwin")
|
||||
set(mpfr_CFLAGS "--target=arm64-apple-darwin")
|
||||
set(mpfr_LDFLAGS "-arch arm64")
|
||||
elseif(CMAKE_SYSTEM_PROCESSOR STREQUAL "arm64" AND CMAKE_OSX_ARCHITECTURES STREQUAL "x86_64")
|
||||
set(mpfr_HOST "x86_64-apple-darwin")
|
||||
set(mpfr_BUILD "arm64-apple-darwin")
|
||||
set(mpfr_CFLAGS "--target=x86_64-apple-darwin13.0.0")
|
||||
set(mpfr_LDFLAGS "")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(FetchContent)
|
||||
include(ProcessorCount)
|
||||
ProcessorCount(Ncpu)
|
||||
include(ExternalProject)
|
||||
set(prefix ${FETCHCONTENT_BASE_DIR}/mpfr)
|
||||
set(mpfr_INSTALL ${prefix}/install)
|
||||
set(mpfr_LIBRARY ${mpfr_INSTALL}/lib/${CMAKE_STATIC_LIBRARY_PREFIX}mpfr${CMAKE_STATIC_LIBRARY_SUFFIX})
|
||||
set(mpfr_INCLUDE_DIR ${mpfr_INSTALL}/include)
|
||||
|
||||
# Try to use CONFIGURE_HANDLED_BY_BUILD ON to avoid constantly reconfiguring
|
||||
if(${CMAKE_VERSION} VERSION_LESS 3.20)
|
||||
# CMake < 3.20, do not use any extra option
|
||||
set(mpfr_ExternalProject_Add_extra_options)
|
||||
else()
|
||||
# CMake >= 3.20
|
||||
set(mpfr_ExternalProject_Add_extra_options "CONFIGURE_HANDLED_BY_BUILD;ON")
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(mpfr
|
||||
PREFIX ${prefix}
|
||||
DEPENDS gmp
|
||||
URL https://ftp.gnu.org/gnu/mpfr/mpfr-4.2.0.tar.xz
|
||||
URL_MD5 a25091f337f25830c16d2054d74b5af7
|
||||
UPDATE_DISCONNECTED true # need this to avoid constant rebuild
|
||||
${mpfr_ExternalProject_Add_extra_options} # avoid constant reconfigure
|
||||
CONFIGURE_COMMAND
|
||||
${CMAKE_COMMAND} -E env
|
||||
CFLAGS=${gmp_CFLAGS}
|
||||
LDFLAGS=${gmp_LDFLAGS}
|
||||
${prefix}/src/mpfr/configure
|
||||
--disable-debug --disable-dependency-tracking --disable-silent-rules --enable-cxx --with-pic
|
||||
--with-gmp-include=${gmp_INCLUDE_DIR} --with-gmp-lib=${gmp_LIB_DIR}
|
||||
--disable-shared
|
||||
--prefix=${mpfr_INSTALL}
|
||||
--build=${gmp_BUILD}
|
||||
--host=${gmp_HOST}
|
||||
--disable-shared
|
||||
BUILD_COMMAND make -j${Ncpu}
|
||||
INSTALL_COMMAND make -j${Ncpu} install
|
||||
INSTALL_DIR ${mpfr_INSTALL}
|
||||
TEST_COMMAND ""
|
||||
BUILD_BYPRODUCTS ${mpfr_LIBRARY}
|
||||
)
|
||||
#PATCH_COMMAND curl "https://raw.githubusercontent.com/Homebrew/formula-patches/03cf8088210822aa2c1ab544ed58ea04c897d9c4/libtool/configure-big_sur.diff" "|" sed -e "s/configure.orig/configure/g" "|" git apply -v
|
||||
ExternalProject_Get_Property(mpfr SOURCE_DIR)
|
||||
set(mpfr_LIBRARIES ${mpfr_LIBRARY})
|
||||
add_library(mpfr::mpfr INTERFACE IMPORTED GLOBAL)
|
||||
file(MAKE_DIRECTORY ${mpfr_INCLUDE_DIR}) # avoid race condition
|
||||
target_include_directories(mpfr::mpfr INTERFACE ${mpfr_INCLUDE_DIR})
|
||||
target_link_libraries(mpfr::mpfr INTERFACE "${mpfr_LIBRARIES}") # need the quotes to expand list
|
||||
# This is necessary to ensure that mpfr appears before gmp in link order.
|
||||
# Otherwise undefined reference errors occur at link time on Linux with gcc
|
||||
target_link_libraries(mpfr::mpfr INTERFACE "${gmp_LIBRARIES}")
|
||||
add_dependencies(mpfr::mpfr mpfr)
|
||||
endif()
|
||||
|
||||
if(NOT TARGET mpfr::mpfr)
|
||||
message(FATAL_ERROR "Creation of target 'mpfr::mpfr' failed")
|
||||
endif()
|
||||
+1
-1
@@ -8,7 +8,7 @@ include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
predicates
|
||||
GIT_REPOSITORY https://github.com/libigl/libigl-predicates.git
|
||||
GIT_TAG 488242fa2b1f98a9c5bd1441297fb4a99a6a9ae4
|
||||
GIT_TAG decb7bc1260e689cbe008109e3cc5d3a5a433aea
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(predicates)
|
||||
|
||||
Vendored
+1
-1
@@ -8,7 +8,7 @@ include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
tetgen
|
||||
GIT_REPOSITORY https://github.com/libigl/tetgen.git
|
||||
GIT_TAG 4f3bfba3997f20aa1f96cfaff604313a8c2c85b6
|
||||
GIT_TAG e05aca7df74e3f531bc35733ed87d36d437266c5
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(tetgen)
|
||||
|
||||
+1
-1
@@ -8,7 +8,7 @@ include(FetchContent)
|
||||
FetchContent_Declare(
|
||||
triangle
|
||||
GIT_REPOSITORY https://github.com/libigl/triangle.git
|
||||
GIT_TAG 3ee6cac2230f0fe1413879574f741c7b6da11221
|
||||
GIT_TAG 62f02db9ab4ff4b62d5ff82a77c8ea458c84c23a
|
||||
)
|
||||
|
||||
FetchContent_MakeAvailable(triangle)
|
||||
|
||||
+2
-1
@@ -1311,6 +1311,7 @@ HTML_STYLESHEET =
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_EXTRA_STYLESHEET = docs/doxygen-awesome.css
|
||||
#HTML_EXTRA_STYLESHEET =
|
||||
|
||||
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
|
||||
# other source files which should be copied to the HTML output directory. Note
|
||||
@@ -1522,7 +1523,7 @@ TOC_EXPAND = NO
|
||||
# protocol see https://www.sitemaps.org
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
SITEMAP_URL =
|
||||
SITEMAP_URL = https://libigl.github.io/dox/
|
||||
|
||||
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
|
||||
# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
|
||||
|
||||
+34
-1
@@ -3,7 +3,7 @@
|
||||
This detailed documentation browser is automatically generated from the comments
|
||||
in libigl header (.h) files.
|
||||
|
||||
In general, each function (e.g., `igl::func`) will be defined in a
|
||||
In general, each [libigl function](./namespaceigl.html#func-members) (e.g., `igl::func`) will be defined in a
|
||||
correspondingly named header file (e.g., `#include <igl/func.h>`).
|
||||
|
||||
The _core_ library only depends on the standard template library (`std::`) and
|
||||
@@ -16,6 +16,39 @@ resides in the [`igl::spectra::` namespace](./namespaceigl_1_1spectra.html).
|
||||
Functions which depend on external code under a copyleft license reside in the
|
||||
[`igl::copyleft::` namepsace](file:///Users/alecjacobson/Repos/libigl/dox/namespaceigl_1_1copyleft.html).
|
||||
|
||||
|
||||
Most libigl functions are templated over the Eigen matrix inputs and outputs.
|
||||
Callers can choose their own scalar types (e.g., `double`/`float`) and storage
|
||||
orders (`Eigen::ColMajor`/`Eigen::RowMajor`). Libigl can be used as a:
|
||||
|
||||
- **header only library** (via CMake, make sure
|
||||
`LIBIGL_USE_STATIC_LIBRARY=OFF`) and insure that `IGL_STATIC_LIBRARY` is
|
||||
_not_ defined_ when compiling --- easiest if you're new to libigl, or
|
||||
- **static library** (`LIBIGL_USE_STATIC_LIBRARY=ON` → `IGL_STATIC_LIBRARY` is
|
||||
defined) --- speeds up repeated compilation.
|
||||
|
||||
The libigl static library is filled with _explicit template instantiations_ for
|
||||
common Eigen inputs and outputs. If the library doesn't contain your types, you
|
||||
may get some form of linker error (e.g., `Undefined symbols for architecture`,
|
||||
`undefined reference to` or `unresolved external symbol`).
|
||||
|
||||
You can fix this by:
|
||||
|
||||
1. Switching to header only mode for your project,
|
||||
2. Making a file in your project to compile the missing templates. E.g., `my_templates.cpp`
|
||||
```cpp
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
#undef IGL_STATIC_LIBRARY
|
||||
#endif
|
||||
#include <igl/per_vertex_normals.h>
|
||||
template void igl::per_vertex_normals<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&);
|
||||
```
|
||||
3. [Submit a PR](https://github.com/libigl/libigl/pulls) containing your missing template to the development branch of libigl
|
||||
4. Change your input/output types to match existing templates (e.g., `Eigen::MatrixXd`).
|
||||
|
||||
|
||||
|
||||
|
||||
https://libigl.github.io/
|
||||
|
||||
https://github.com/libigl/libigl/
|
||||
|
||||
+1020
-299
File diff suppressed because it is too large
Load Diff
+517
-116
@@ -1,15 +1,16 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2015 Alec Jacobson <alecjacobson@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
|
||||
//
|
||||
// This Source Code Form is subject to 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_AABB_H
|
||||
#define IGL_AABB_H
|
||||
|
||||
#include "Hit.h"
|
||||
#include "igl_inline.h"
|
||||
#include <cassert>
|
||||
#include <Eigen/Core>
|
||||
#include <Eigen/Geometry>
|
||||
#include <vector>
|
||||
@@ -26,9 +27,12 @@ namespace igl
|
||||
/// @tparam DerivedV Matrix type of vertex positions (e.g., `Eigen::MatrixXd`)
|
||||
/// @tparam DIM Dimension of mesh vertex positions (2 or 3)
|
||||
template <typename DerivedV, int DIM>
|
||||
class AABB
|
||||
class AABB
|
||||
{
|
||||
public:
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Member variables
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Scalar type of vertex positions (e.g., `double`)
|
||||
typedef typename DerivedV::Scalar Scalar;
|
||||
/// Fixed-size (`DIM`) RowVector type using `Scalar`
|
||||
@@ -39,27 +43,35 @@ public:
|
||||
typedef Eigen::Matrix<Scalar,Eigen::Dynamic,DIM> MatrixXDIMS;
|
||||
/// Pointer to "left" child node (`nullptr` if leaf)
|
||||
// Shared pointers are slower...
|
||||
AABB * m_left;
|
||||
AABB * m_left;
|
||||
/// Pointer to "right" child node (`nullptr` if leaf)
|
||||
AABB * m_right;
|
||||
/// Pointer to "parent" node (`nullptr` if root)
|
||||
AABB * m_parent;
|
||||
/// Axis-Aligned Bounding Box containing this node
|
||||
Eigen::AlignedBox<Scalar,DIM> m_box;
|
||||
/// Index of single primitive in this node if full leaf, otherwise -1 for non-leaf
|
||||
int m_primitive;
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Non-templated member functions
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
//Scalar m_low_sqr_d;
|
||||
//int m_depth;
|
||||
/// @private
|
||||
AABB():
|
||||
m_left(NULL), m_right(NULL),
|
||||
m_left(nullptr), m_right(nullptr),m_parent(nullptr),
|
||||
m_box(), m_primitive(-1)
|
||||
//m_low_sqr_d(std::numeric_limits<double>::infinity()),
|
||||
//m_depth(0)
|
||||
{}
|
||||
{
|
||||
static_assert(DerivedV::ColsAtCompileTime == DIM || DerivedV::ColsAtCompileTime == Eigen::Dynamic,"DerivedV::ColsAtCompileTime == DIM || DerivedV::ColsAtCompileTime == Eigen::Dynamic");
|
||||
}
|
||||
/// @private
|
||||
// http://stackoverflow.com/a/3279550/148668
|
||||
AABB(const AABB& other):
|
||||
m_left(other.m_left ? new AABB(*other.m_left) : NULL),
|
||||
m_right(other.m_right ? new AABB(*other.m_right) : NULL),
|
||||
m_left (other.m_left ? new AABB(*other.m_left) : nullptr),
|
||||
m_right(other.m_right ? new AABB(*other.m_right) : nullptr),
|
||||
m_parent(other.m_parent),
|
||||
m_box(other.m_box),
|
||||
m_primitive(other.m_primitive)
|
||||
//m_low_sqr_d(other.m_low_sqr_d),
|
||||
@@ -67,6 +79,8 @@ public:
|
||||
// m_left ? m_left->m_depth + 1 : 0,
|
||||
// m_right ? m_right->m_depth + 1 : 0))
|
||||
{
|
||||
if(m_left) { m_left->m_parent = this; }
|
||||
if(m_right) { m_right->m_parent = this; }
|
||||
}
|
||||
/// @private
|
||||
// copy-swap idiom
|
||||
@@ -76,6 +90,7 @@ public:
|
||||
using std::swap;
|
||||
swap(first.m_left,second.m_left);
|
||||
swap(first.m_right,second.m_right);
|
||||
swap(first.m_parent,second.m_parent);
|
||||
swap(first.m_box,second.m_box);
|
||||
swap(first.m_primitive,second.m_primitive);
|
||||
//swap(first.m_low_sqr_d,second.m_low_sqr_d);
|
||||
@@ -91,44 +106,381 @@ public:
|
||||
/// @private
|
||||
AABB(AABB&& other):
|
||||
// initialize via default constructor
|
||||
AABB()
|
||||
AABB()
|
||||
{
|
||||
swap(*this,other);
|
||||
}
|
||||
/// @private
|
||||
// Seems like there should have been an elegant solution to this using
|
||||
// the copy-swap idiom above:
|
||||
IGL_INLINE void deinit()
|
||||
IGL_INLINE void clear()
|
||||
{
|
||||
m_primitive = -1;
|
||||
m_box = Eigen::AlignedBox<Scalar,DIM>();
|
||||
delete m_left;
|
||||
m_left = NULL;
|
||||
m_left = nullptr;
|
||||
delete m_right;
|
||||
m_right = NULL;
|
||||
m_right = nullptr;
|
||||
// Tell my parent I'm dead
|
||||
if(m_parent)
|
||||
{
|
||||
if(m_parent->m_left == this)
|
||||
{
|
||||
m_parent->m_left = nullptr;
|
||||
}else if(m_parent->m_right == this)
|
||||
{
|
||||
m_parent->m_right = nullptr;
|
||||
}else
|
||||
{
|
||||
assert(false && "I'm not my parent's child");
|
||||
}
|
||||
auto * grandparent = m_parent->m_parent;
|
||||
if(grandparent)
|
||||
{
|
||||
// Before
|
||||
// grandparent
|
||||
// ╱ ╲
|
||||
// parent pibling
|
||||
// ╱ ╲
|
||||
// sibling this
|
||||
//
|
||||
// After
|
||||
// grandparent
|
||||
// ╱ ╲
|
||||
// sibling® pibling
|
||||
}else
|
||||
{
|
||||
// Before
|
||||
// parent=root
|
||||
// ╱ ╲
|
||||
// sibling this
|
||||
//
|
||||
// After
|
||||
// grandparent
|
||||
// ╱ ╲
|
||||
// sibling® pibling
|
||||
}
|
||||
}
|
||||
// Now my parent is dead to me.
|
||||
m_parent = nullptr;
|
||||
}
|
||||
/// @private
|
||||
~AABB()
|
||||
{
|
||||
deinit();
|
||||
clear();
|
||||
}
|
||||
/// Return whether at leaf node
|
||||
IGL_INLINE bool is_leaf() const;
|
||||
/// Return whether at root node
|
||||
IGL_INLINE bool is_root() const;
|
||||
/// Return the root node of this node's tree by following its parent
|
||||
IGL_INLINE AABB<DerivedV,DIM>* root() const;
|
||||
IGL_INLINE AABB<DerivedV,DIM>* detach();
|
||||
IGL_INLINE void refit_lineage();
|
||||
/// Get a vector of leaves indexed by their m_primitive id (these better
|
||||
/// be non-negative and tightly packed.
|
||||
/// @param[in] m number of leaves/elements (Ele.rows())
|
||||
/// @returns leaves m list of pointers to leaves
|
||||
IGL_INLINE std::vector<AABB<DerivedV,DIM>*> gather_leaves(const int m);
|
||||
/// \overload where m is the max m_primitive id in the tree.
|
||||
IGL_INLINE std::vector<AABB<DerivedV,DIM>*> gather_leaves();
|
||||
/// Pad leaves by `pad` in each dimension
|
||||
/// @param[in] pad padding amount
|
||||
/// @param[in] polish_rotate_passes number of passes to polish rotations
|
||||
/// @returns pointer to (potentially new) root
|
||||
IGL_INLINE AABB<DerivedV,DIM>* pad(
|
||||
const std::vector<AABB<DerivedV,DIM>*> & leaves,
|
||||
const Scalar pad,
|
||||
const int polish_rotate_passes=0);
|
||||
/// @returns `this` if no update was needed, otherwise returns pointer to
|
||||
/// (potentially new) root
|
||||
///
|
||||
/// Example:
|
||||
/// ```cpp
|
||||
/// auto * up = leaf->update(new_box);
|
||||
/// if(up != leaf)
|
||||
/// {
|
||||
/// tree = up->root();
|
||||
/// }else
|
||||
/// {
|
||||
/// printf("no update occurred\n");
|
||||
/// }
|
||||
///
|
||||
/// // or simply
|
||||
/// tree = leaf->update(new_box)->root();
|
||||
/// ```
|
||||
IGL_INLINE AABB<DerivedV,DIM>* update(
|
||||
const Eigen::AlignedBox<Scalar,DIM> & new_box,
|
||||
const Scalar pad=0);
|
||||
/// Insert a (probably a leaf) AABB `other` into this AABB tree. If
|
||||
/// `other`'s box is contained in this AABB's box then insert it as a child recursively.
|
||||
///
|
||||
/// If `other`'s box is not contained in this AABB's box then insert it as a
|
||||
/// sibling.
|
||||
///
|
||||
/// It's a very good idea to call either `rotate` (faster, less good) or `rotate_lineage` (slower, better)
|
||||
/// after insertion. Rotating continues to improve the tree's quality so
|
||||
/// after doing a bunch of insertions you might even consider calling
|
||||
/// `rotate` on all nodes.
|
||||
///
|
||||
/// `insert` attempts to minimize total internal surface area. Where as
|
||||
/// `init` is top-down and splits boxes based on the median along the
|
||||
/// longest dimension. When initializing a tree, `init` seems to result in
|
||||
/// great trees (small height and small total internal surface area).
|
||||
///
|
||||
/// @param[in] other pointer to another AABB node
|
||||
/// @returns pointer to the parent of `other` or `other` itself. This
|
||||
/// could be == to a `new`ly created internal node or to `other` if
|
||||
/// `this==other`. Calling ->root() on this returned node will give you
|
||||
/// the root of the tree.
|
||||
///
|
||||
/// ##### Example
|
||||
///
|
||||
/// ```cpp
|
||||
/// // Create a tree (use pointer to track changes to root)
|
||||
/// auto * tree = new igl::AABB<DerivedV,3>::AABB();
|
||||
/// // Fill the tree (e.g., using ->init())
|
||||
/// …
|
||||
/// // Create a new leafe node
|
||||
/// auto * leaf = new igl::AABB<DerivedV,3>::AABB();
|
||||
/// // Fill the leaf node with a primitive and box
|
||||
/// …
|
||||
/// // Insert into the tree and find the possibly new root
|
||||
/// tree = tree->insert(leaf)->root();
|
||||
/// ```
|
||||
IGL_INLINE AABB<DerivedV,DIM>* insert(AABB * other);
|
||||
/// Insert `other` as a sibling to `this` by creating a new internal node
|
||||
/// to be their shared parent.
|
||||
///
|
||||
/// Before
|
||||
/// parent
|
||||
/// ╱ ╲
|
||||
/// this(C) sibling
|
||||
/// ╱ ╲
|
||||
/// left right
|
||||
///
|
||||
/// After
|
||||
/// parent
|
||||
/// ╱ ╲
|
||||
/// newbie sibling
|
||||
/// ╱ ╲
|
||||
/// this other
|
||||
/// ╱ ╲
|
||||
/// left right
|
||||
///
|
||||
///
|
||||
/// @param[in] other pointer to another AABB node
|
||||
/// @returns pointer to the new shared parent.
|
||||
IGL_INLINE AABB<DerivedV,DIM>* insert_as_sibling(AABB * other);
|
||||
/// Try to swap this node with its close relatives if it will decrease
|
||||
/// total internal surface area.
|
||||
///
|
||||
///
|
||||
/// grandparent
|
||||
/// ╱ ╲
|
||||
/// parent pibling°
|
||||
/// ╱ ╲ ╱ ╲
|
||||
/// sibling this cuz1° cuz2°
|
||||
/// ╱ ╲
|
||||
/// nib1° nib2°
|
||||
///
|
||||
/// °Swap Candidates
|
||||
///
|
||||
/// @param[in] dry_run if true then don't actually swap
|
||||
/// @return[in] the change in total internal surface area, 0 if no
|
||||
/// improvement and rotate won't be carried out.
|
||||
IGL_INLINE Scalar rotate(const bool dry_run = false);
|
||||
/// Try to swap this node with its cousins if it will decrease
|
||||
/// total internal surface area.
|
||||
///
|
||||
/// @param[in] dry_run if true then don't actually swap
|
||||
/// @return[in] the change in total internal surface area, 0 if no
|
||||
/// improvement and rotate won't be carried out.
|
||||
///
|
||||
/// Before
|
||||
/// grandparent
|
||||
/// ╱ ╲
|
||||
/// parent pibling
|
||||
/// ╱ ╲ ╱ ╲
|
||||
/// sibling this cuz1 cuz2
|
||||
///
|
||||
///
|
||||
/// Candidates
|
||||
/// grandparent
|
||||
/// ╱ ╲
|
||||
/// parent pibling
|
||||
/// ╱ ╲ ╱ ╲
|
||||
/// sibling cuz1 this cuz2
|
||||
///
|
||||
/// Or
|
||||
/// grandparent
|
||||
/// ╱ ╲
|
||||
/// parent pibling
|
||||
/// ╱ ╲ ╱ ╲
|
||||
/// sibling cuz2 cuz1 this
|
||||
IGL_INLINE Scalar rotate_across(const bool dry_run = false);
|
||||
/// Try to swap this node with its pibling if it will decrease
|
||||
/// total internal surface area.
|
||||
///
|
||||
/// @param[in] dry_run if true then don't actually swap
|
||||
/// @return[in] the change in total internal surface area, 0 if no
|
||||
/// improvement and rotate won't be carried out.
|
||||
///
|
||||
/// Before
|
||||
/// grandparent
|
||||
/// ╱ ╲
|
||||
/// other parent
|
||||
/// ╱ ╲
|
||||
/// this sibling
|
||||
///
|
||||
///
|
||||
/// Candidate
|
||||
/// grandparent
|
||||
/// ╱ ╲
|
||||
/// this parent
|
||||
/// ╱ ╲
|
||||
/// other sibling
|
||||
IGL_INLINE Scalar rotate_up(const bool dry_run = false);
|
||||
/// Try to swap this node with one of its niblings if it will decrease
|
||||
/// total internal surface area.
|
||||
///
|
||||
/// @param[in] dry_run if true then don't actually swap
|
||||
/// @return[in] the change in total internal surface area, 0 if no
|
||||
/// improvement and rotate won't be carried out.
|
||||
///
|
||||
/// Before
|
||||
/// parent
|
||||
/// ╱ ╲
|
||||
/// this sibling
|
||||
/// ╱ ╲
|
||||
/// left right
|
||||
///
|
||||
///
|
||||
/// Candidates
|
||||
/// parent
|
||||
/// ╱ ╲
|
||||
/// left sibling
|
||||
/// ╱ ╲
|
||||
/// this right
|
||||
///
|
||||
/// Or
|
||||
///
|
||||
/// parent
|
||||
/// ╱ ╲
|
||||
/// right sibling
|
||||
/// ╱ ╲
|
||||
/// left this
|
||||
IGL_INLINE Scalar rotate_down(const bool dry_run = false);
|
||||
/// "Rotate" (swap) `reining` with `challenger`.
|
||||
///
|
||||
/// Before
|
||||
/// grandparent
|
||||
/// ╱ ╲
|
||||
/// reining parent
|
||||
/// ╱ ╲
|
||||
/// challenger sibling
|
||||
///
|
||||
///
|
||||
/// Candidate
|
||||
/// grandparent
|
||||
/// ╱ ╲
|
||||
/// challenger parent
|
||||
/// ╱ ╲
|
||||
/// reining sibling
|
||||
/// @param[in] reining pointer to AABB node to be rotated
|
||||
/// @param[in] grandparent pointer to challenger's grandparent
|
||||
/// @param[in] parent pointer to challenger's parent
|
||||
/// @param[in] challenger pointer to AABB node to be rotated
|
||||
/// @param[in] sibling pointer to challenger's sibling
|
||||
/// @returns true only if rotation was possible and successfully carried
|
||||
/// out.
|
||||
static IGL_INLINE Scalar rotate_up(
|
||||
const bool dry_run,
|
||||
AABB<DerivedV,DIM>* reining,
|
||||
AABB<DerivedV,DIM>* grandparent,
|
||||
AABB<DerivedV,DIM>* parent,
|
||||
AABB<DerivedV,DIM>* challenger,
|
||||
AABB<DerivedV,DIM>* sibling);
|
||||
// Should this be a static function with an argument?
|
||||
IGL_INLINE void rotate_lineage();
|
||||
/// Number of nodes contained in subtree (is it?)
|
||||
///
|
||||
/// \note At best, this function has a dubious name. This is really an
|
||||
/// internal helper function for the serialization.
|
||||
///
|
||||
/// \see size()
|
||||
///
|
||||
/// @return Number of elements m then total tree size should be 2*h where h is
|
||||
/// the deepest depth 2^ceil(log(#Ele*2-1))
|
||||
IGL_INLINE int subtree_size() const;
|
||||
/// @param[in] box query box
|
||||
/// @param[in,out] leaves list of leaves to append to
|
||||
IGL_INLINE bool append_intersecting_leaves(
|
||||
const Eigen::AlignedBox<Scalar,DIM> & box,
|
||||
std::vector<const AABB<DerivedV,DIM>*> & leaves) const;
|
||||
/// Compute sum of surface area of all internal (non-root, non-leaf) boxes
|
||||
IGL_INLINE typename DerivedV::Scalar internal_surface_area() const;
|
||||
/// Validate the subtree under this node by running a bunch of assertions.
|
||||
/// Does nothing when not in debug mode
|
||||
IGL_INLINE void validate() const;
|
||||
/// print the memory addresses of the tree in a somewhat legible way
|
||||
IGL_INLINE void print(const int depth = 0) const;
|
||||
/// @returns Actual size of tree. Total number of nodes in tree. A singleton root
|
||||
/// has size 1.
|
||||
///
|
||||
/// \see subtree_size
|
||||
IGL_INLINE int size() const;
|
||||
/// @returns Height of the tree. A singleton root has height 1.
|
||||
IGL_INLINE int height() const;
|
||||
private:
|
||||
/// If new distance (sqr_d_candidate) is less than current distance
|
||||
/// (sqr_d), then update this distance and its associated values
|
||||
/// _in-place_:
|
||||
///
|
||||
/// @param[in] p dim-long query point (only used in DEBUG mode)
|
||||
/// @param[in] sqr_d candidate minimum distance for this query, see
|
||||
/// output
|
||||
/// @param[in] i candidate index into Ele of closest point, see output
|
||||
/// @param[in] c dim-long candidate closest point, see output
|
||||
/// @param[in] sqr_d current minimum distance for this query, see output
|
||||
/// @param[in] i current index into Ele of closest point, see output
|
||||
/// @param[in] c dim-long current closest point, see output
|
||||
/// @param[out] sqr_d minimum of initial value and squared distance to
|
||||
/// this primitive
|
||||
/// @param[out] i possibly updated index into Ele of closest point
|
||||
/// @param[out] c dim-long possibly updated closest point
|
||||
IGL_INLINE void set_min(
|
||||
const RowVectorDIMS & p,
|
||||
const Scalar sqr_d_candidate,
|
||||
const int & i_candidate,
|
||||
const RowVectorDIMS & c_candidate,
|
||||
Scalar & sqr_d,
|
||||
int & i,
|
||||
Eigen::PlainObjectBase<RowVectorDIMS> & c) const;
|
||||
public:
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Templated member functions
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
/// Build an Axis-Aligned Bounding Box tree for a given mesh and given
|
||||
/// serialization of a previous AABB tree.
|
||||
///
|
||||
/// @param[in] V #V by dim list of mesh vertex positions.
|
||||
/// @param[in] Ele #Ele by dim+1 list of mesh indices into #V.
|
||||
/// @param[in] bb_mins max_tree by dim list of bounding box min corner positions
|
||||
/// @param[in] bb_maxs max_tree by dim list of bounding box max corner positions
|
||||
/// @param[in] elements max_tree list of element or (not leaf id) indices into Ele
|
||||
/// @param[in] V #V by dim list of mesh vertex positions.
|
||||
/// @param[in] Ele #Ele by dim+1 list of mesh indices into #V.
|
||||
/// @param[in] bb_mins max_tree by dim list of bounding box min corner
|
||||
/// positions
|
||||
/// @param[in] bb_maxs max_tree by dim list of bounding box max corner
|
||||
/// positions
|
||||
/// @param[in] elements max_tree list of element or (not leaf id) indices
|
||||
/// into Ele
|
||||
/// @param[in] i recursive call index {0}
|
||||
template <
|
||||
typename DerivedEle,
|
||||
typename Derivedbb_mins,
|
||||
typename DerivedEle,
|
||||
typename Derivedbb_mins,
|
||||
typename Derivedbb_maxs,
|
||||
typename Derivedelements>
|
||||
IGL_INLINE void init(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<Derivedbb_mins> & bb_mins,
|
||||
const Eigen::MatrixBase<Derivedbb_maxs> & bb_maxs,
|
||||
const Eigen::MatrixBase<Derivedelements> & elements,
|
||||
@@ -136,62 +488,65 @@ public:
|
||||
/// Build an Axis-Aligned Bounding Box tree for a given mesh and given
|
||||
/// serialization of a previous AABB tree.
|
||||
///
|
||||
/// @param[in] V #V by dim list of mesh vertex positions.
|
||||
/// @param[in] Ele #Ele by dim+1 list of mesh indices into #V.
|
||||
/// @param[in] V #V by dim list of mesh vertex positions.
|
||||
/// @param[in] Ele #Ele by dim+1 list of mesh indices into #V.
|
||||
template <typename DerivedEle>
|
||||
IGL_INLINE void init(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele);
|
||||
/// Build an Axis-Aligned Bounding Box tree for a given mesh.
|
||||
///
|
||||
/// @param[in] V #V by dim list of mesh vertex positions.
|
||||
/// @param[in] Ele #Ele by dim+1 list of mesh indices into #V.
|
||||
/// @param[in] SI #Ele by dim list revealing for each coordinate where Ele's
|
||||
/// barycenters would be sorted: SI(e,d) = i --> the dth coordinate of
|
||||
/// the barycenter of the eth element would be placed at position i in a
|
||||
/// sorted list.
|
||||
/// @param[in] I #I list of indices into Ele of elements to include (for recursive
|
||||
/// calls)
|
||||
///
|
||||
/// @param[in] V #V by dim list of mesh vertex positions.
|
||||
/// @param[in] Ele #Ele by dim+1 list of mesh indices into #V.
|
||||
/// @param[in] SI #Ele by dim list revealing for each coordinate where
|
||||
/// Ele's barycenters would be sorted: SI(e,d) = i --> the dth
|
||||
/// coordinate of the barycenter of the eth element would be placed at
|
||||
/// position i in a sorted list.
|
||||
/// @param[in] I #I list of indices into Ele of elements to include (for
|
||||
/// recursive calls)
|
||||
///
|
||||
template <typename DerivedEle, typename DerivedSI, typename DerivedI>
|
||||
IGL_INLINE void init(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedSI> & SI,
|
||||
const Eigen::MatrixBase<DerivedI>& I);
|
||||
/// Return whether at leaf node
|
||||
IGL_INLINE bool is_leaf() const;
|
||||
/// @returns `this` if no update was needed, otherwise returns pointer to
|
||||
/// (potentially new) root
|
||||
template <typename DerivedEle>
|
||||
IGL_INLINE AABB<DerivedV,DIM>* update_primitive(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Scalar pad=0);
|
||||
|
||||
/// Find the indices of elements containing given point: this makes sense
|
||||
/// when Ele is a co-dimension 0 simplex (tets in 3D, triangles in 2D).
|
||||
///
|
||||
/// @param[in] V #V by dim list of mesh vertex positions. **Should be same as used to
|
||||
/// construct mesh.**
|
||||
/// @param[in] Ele #Ele by dim+1 list of mesh indices into #V. **Should be same as used to
|
||||
/// construct mesh.**
|
||||
/// @param[in] V #V by dim list of mesh vertex positions. **Should be
|
||||
/// same as used to construct mesh.**
|
||||
/// @param[in] Ele #Ele by dim+1 list of mesh indices into #V. **Should
|
||||
/// be same as used to construct mesh.**
|
||||
/// @param[in] q dim row-vector query position
|
||||
/// @param[in] first whether to only return first element containing q
|
||||
/// @return list of indices of elements containing q
|
||||
template <typename DerivedEle, typename Derivedq>
|
||||
IGL_INLINE std::vector<int> find(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<Derivedq> & q,
|
||||
const bool first=false) const;
|
||||
|
||||
/// Number of nodes contained in subtree
|
||||
///
|
||||
/// @return Number of elements m then total tree size should be 2*h where h is
|
||||
/// the deepest depth 2^ceil(log(#Ele*2-1))
|
||||
IGL_INLINE int subtree_size() const;
|
||||
|
||||
/// Serialize this class into 3 arrays (so we can pass it pack to matlab)
|
||||
///
|
||||
/// @param[out] bb_mins max_tree by dim list of bounding box min corner positions
|
||||
/// @param[out] bb_maxs max_tree by dim list of bounding box max corner positions
|
||||
/// @param[out] elements max_tree list of element or (not leaf id) indices into Ele
|
||||
/// @param[out] bb_mins max_tree by dim list of bounding box min corner
|
||||
/// positions
|
||||
/// @param[out] bb_maxs max_tree by dim list of bounding box max corner
|
||||
/// positions
|
||||
/// @param[out] elements max_tree list of element or (not leaf id)
|
||||
/// indices into Ele
|
||||
/// @param[in] i recursive call index into these arrays {0}
|
||||
template <
|
||||
typename Derivedbb_mins,
|
||||
typename Derivedbb_mins,
|
||||
typename Derivedbb_maxs,
|
||||
typename Derivedelements>
|
||||
IGL_INLINE void serialize(
|
||||
@@ -203,7 +558,7 @@ public:
|
||||
///
|
||||
/// @param[in] V #V by dim list of vertex positions
|
||||
/// @param[in] Ele #Ele by dim list of simplex indices
|
||||
/// @param[in] p dim-long query point
|
||||
/// @param[in] p dim-long query point
|
||||
/// @param[out] i facet index corresponding to smallest distances
|
||||
/// @param[out] c closest point
|
||||
/// @return squared distance
|
||||
@@ -213,7 +568,7 @@ public:
|
||||
template <typename DerivedEle>
|
||||
IGL_INLINE Scalar squared_distance(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const RowVectorDIMS & p,
|
||||
int & i,
|
||||
Eigen::PlainObjectBase<RowVectorDIMS> & c) const;
|
||||
@@ -222,12 +577,12 @@ public:
|
||||
///
|
||||
/// @param[in] V #V by dim list of vertex positions
|
||||
/// @param[in] Ele #Ele by dim list of simplex indices
|
||||
/// @param[in] p dim-long query point
|
||||
/// @param[in] low_sqr_d lower bound on squared distance, specified maximum squared
|
||||
/// distance
|
||||
/// @param[in] up_sqr_d current upper bounded on squared distance, current minimum
|
||||
/// squared distance (only consider distances less than this), see
|
||||
/// output.
|
||||
/// @param[in] p dim-long query point
|
||||
/// @param[in] low_sqr_d lower bound on squared distance, specified
|
||||
/// maximum squared distance
|
||||
/// @param[in] up_sqr_d current upper bounded on squared distance,
|
||||
/// current minimum squared distance (only consider distances less than
|
||||
/// this), see output.
|
||||
/// @param[out] i facet index corresponding to smallest distances
|
||||
/// @param[out] c closest point
|
||||
/// @return squared distance
|
||||
@@ -237,7 +592,7 @@ public:
|
||||
template <typename DerivedEle>
|
||||
IGL_INLINE Scalar squared_distance(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const RowVectorDIMS & p,
|
||||
const Scalar low_sqr_d,
|
||||
const Scalar up_sqr_d,
|
||||
@@ -247,10 +602,10 @@ public:
|
||||
///
|
||||
/// @param[in] V #V by dim list of vertex positions
|
||||
/// @param[in] Ele #Ele by dim list of simplex indices
|
||||
/// @param[in] p dim-long query point
|
||||
/// @param[in] up_sqr_d current upper bounded on squared distance, current minimum
|
||||
/// squared distance (only consider distances less than this), see
|
||||
/// output.
|
||||
/// @param[in] p dim-long query point
|
||||
/// @param[in] up_sqr_d current upper bounded on squared distance,
|
||||
/// current minimum squared distance (only consider distances less than
|
||||
/// this), see output.
|
||||
/// @param[out] i facet index corresponding to smallest distances
|
||||
/// @param[out] c closest point
|
||||
/// @return squared distance
|
||||
@@ -258,7 +613,7 @@ public:
|
||||
template <typename DerivedEle>
|
||||
IGL_INLINE Scalar squared_distance(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const RowVectorDIMS & p,
|
||||
const Scalar up_sqr_d,
|
||||
int & i,
|
||||
@@ -274,10 +629,10 @@ public:
|
||||
template <typename DerivedEle>
|
||||
IGL_INLINE bool intersect_ray(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const RowVectorDIMS & origin,
|
||||
const RowVectorDIMS & dir,
|
||||
std::vector<igl::Hit> & hits) const;
|
||||
std::vector<igl::Hit<typename DerivedV::Scalar>> & hits) const;
|
||||
/// Intersect a ray with the mesh return first hit
|
||||
///
|
||||
/// @param[in] V #V by dim list of vertex positions
|
||||
@@ -289,10 +644,11 @@ public:
|
||||
template <typename DerivedEle>
|
||||
IGL_INLINE bool intersect_ray(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const RowVectorDIMS & origin,
|
||||
const RowVectorDIMS & dir,
|
||||
igl::Hit & hit) const;
|
||||
igl::Hit<typename DerivedV::Scalar> & hit) const;
|
||||
|
||||
/// Intersect a ray with the mesh return first hit farther than `min_t`
|
||||
///
|
||||
/// @param[in] V #V by dim list of vertex positions
|
||||
@@ -305,13 +661,48 @@ public:
|
||||
template <typename DerivedEle>
|
||||
IGL_INLINE bool intersect_ray(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const RowVectorDIMS & origin,
|
||||
const RowVectorDIMS & dir,
|
||||
const Scalar min_t,
|
||||
igl::Hit & hit) const;
|
||||
|
||||
public:
|
||||
igl::Hit<typename DerivedV::Scalar> & hit) const;
|
||||
/// Intersect a rays with the mesh return first hit for each
|
||||
///
|
||||
/// @param[in] V #V by dim list of vertex positions
|
||||
/// @param[in] Ele #Ele by dim list of simplex indices
|
||||
/// @param[in] origin #ray by dim+1 list of ray origins
|
||||
/// @param[in] dir #ray by dim list of ray directions
|
||||
/// @param[in] min_t minimum t value to consider
|
||||
/// @param[out] I #ray list of indices into Ele of closest primitives
|
||||
/// (-1 indicates no hit)
|
||||
/// @param[out] T #ray list of t values (nan indicates no hit)
|
||||
/// @param[out] UV #ray by dim list of barycentric coordinates
|
||||
template <
|
||||
typename DerivedEle,
|
||||
typename DerivedOrigin,
|
||||
typename DerivedDir,
|
||||
typename DerivedI,
|
||||
typename DerivedT,
|
||||
typename DerivedUV>
|
||||
IGL_INLINE void intersect_ray(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedOrigin> & origin,
|
||||
const Eigen::MatrixBase<DerivedDir> & dir,
|
||||
const Scalar min_t,
|
||||
Eigen::PlainObjectBase<DerivedI> & I,
|
||||
Eigen::PlainObjectBase<DerivedT> & T,
|
||||
Eigen::PlainObjectBase<DerivedUV> & UV);
|
||||
template <
|
||||
typename DerivedEle,
|
||||
typename DerivedOrigin,
|
||||
typename DerivedDir>
|
||||
IGL_INLINE void intersect_ray(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedOrigin> & origin,
|
||||
const Eigen::MatrixBase<DerivedDir> & dir,
|
||||
std::vector<std::vector<igl::Hit<typename DerivedV::Scalar>>> & hits);
|
||||
/// Compute the squared distance from all query points in P to the
|
||||
/// _closest_ points on the primitives stored in the AABB hierarchy for
|
||||
/// the mesh (V,Ele).
|
||||
@@ -324,18 +715,17 @@ public:
|
||||
/// @param[out] C #P by dim list of closest points
|
||||
template <
|
||||
typename DerivedEle,
|
||||
typename DerivedP,
|
||||
typename DerivedsqrD,
|
||||
typename DerivedI,
|
||||
typename DerivedP,
|
||||
typename DerivedsqrD,
|
||||
typename DerivedI,
|
||||
typename DerivedC>
|
||||
IGL_INLINE void squared_distance(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedP> & P,
|
||||
Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
|
||||
Eigen::PlainObjectBase<DerivedI> & I,
|
||||
Eigen::PlainObjectBase<DerivedC> & C) const;
|
||||
|
||||
/// Compute the squared distance from all query points in P already stored
|
||||
/// in its own AABB hierarchy to the _closest_ points on the primitives
|
||||
/// stored in the AABB hierarchy for the mesh (V,Ele).
|
||||
@@ -349,36 +739,36 @@ public:
|
||||
/// @param[out] sqrD #P list of squared distances
|
||||
/// @param[out] I #P list of indices into Ele of closest primitives
|
||||
/// @param[out] C #P by dim list of closest points
|
||||
template <
|
||||
template <
|
||||
typename DerivedEle,
|
||||
typename Derivedother_V,
|
||||
typename Derivedother_Ele,
|
||||
typename DerivedsqrD,
|
||||
typename DerivedI,
|
||||
typename DerivedsqrD,
|
||||
typename DerivedI,
|
||||
typename DerivedC>
|
||||
IGL_INLINE void squared_distance(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const AABB<Derivedother_V,DIM> & other,
|
||||
const Eigen::MatrixBase<Derivedother_V> & other_V,
|
||||
const Eigen::MatrixBase<Derivedother_Ele> & other_Ele,
|
||||
const Eigen::MatrixBase<Derivedother_Ele> & other_Ele,
|
||||
Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
|
||||
Eigen::PlainObjectBase<DerivedI> & I,
|
||||
Eigen::PlainObjectBase<DerivedC> & C) const;
|
||||
private:
|
||||
template <
|
||||
template <
|
||||
typename DerivedEle,
|
||||
typename Derivedother_V,
|
||||
typename Derivedother_Ele,
|
||||
typename DerivedsqrD,
|
||||
typename DerivedI,
|
||||
typename DerivedsqrD,
|
||||
typename DerivedI,
|
||||
typename DerivedC>
|
||||
IGL_INLINE Scalar squared_distance_helper(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const AABB<Derivedother_V,DIM> * other,
|
||||
const Eigen::MatrixBase<Derivedother_V> & other_V,
|
||||
const Eigen::MatrixBase<Derivedother_Ele>& other_Ele,
|
||||
const Eigen::MatrixBase<Derivedother_Ele>& other_Ele,
|
||||
const Scalar up_sqr_d,
|
||||
Eigen::PlainObjectBase<DerivedsqrD> & sqrD,
|
||||
Eigen::PlainObjectBase<DerivedI> & I,
|
||||
@@ -401,7 +791,7 @@ private:
|
||||
template <typename DerivedEle>
|
||||
IGL_INLINE void leaf_squared_distance(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const RowVectorDIMS & p,
|
||||
const Scalar low_sqr_d,
|
||||
Scalar & sqr_d,
|
||||
@@ -411,36 +801,47 @@ private:
|
||||
template <typename DerivedEle>
|
||||
IGL_INLINE void leaf_squared_distance(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const RowVectorDIMS & p,
|
||||
Scalar & sqr_d,
|
||||
int & i,
|
||||
Eigen::PlainObjectBase<RowVectorDIMS> & c) const;
|
||||
// If new distance (sqr_d_candidate) is less than current distance
|
||||
// (sqr_d), then update this distance and its associated values
|
||||
// _in-place_:
|
||||
//
|
||||
// Inputs:
|
||||
// p dim-long query point (only used in DEBUG mode)
|
||||
// sqr_d candidate minimum distance for this query, see output
|
||||
// i candidate index into Ele of closest point, see output
|
||||
// c dim-long candidate closest point, see output
|
||||
// sqr_d current minimum distance for this query, see output
|
||||
// i current index into Ele of closest point, see output
|
||||
// c dim-long current closest point, see output
|
||||
// Outputs:
|
||||
// sqr_d minimum of initial value and squared distance to this
|
||||
// primitive
|
||||
// i possibly updated index into Ele of closest point
|
||||
// c dim-long possibly updated closest point
|
||||
IGL_INLINE void set_min(
|
||||
const RowVectorDIMS & p,
|
||||
const Scalar sqr_d_candidate,
|
||||
const int i_candidate,
|
||||
const RowVectorDIMS & c_candidate,
|
||||
Scalar & sqr_d,
|
||||
int & i,
|
||||
Eigen::PlainObjectBase<RowVectorDIMS> & c) const;
|
||||
/// Intersect a ray with the mesh return all hits
|
||||
///
|
||||
/// @param[in] V #V by dim list of vertex positions
|
||||
/// @param[in] Ele #Ele by dim list of simplex indices
|
||||
/// @param[in] origin dim-long ray origin
|
||||
/// @param[in] dir dim-long ray direction
|
||||
/// @param[out] hits list of hits
|
||||
/// @return true if any hits
|
||||
template <typename DerivedEle>
|
||||
IGL_INLINE bool intersect_ray_opt(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const RowVectorDIMS & origin,
|
||||
const RowVectorDIMS & dir,
|
||||
const RowVectorDIMS & inv_dir,
|
||||
const RowVectorDIMS & inv_dir_pad,
|
||||
std::vector<igl::Hit<typename DerivedV::Scalar>> & hits) const;
|
||||
/// Intersect a ray with the mesh return first hit farther than `min_t`
|
||||
///
|
||||
/// @param[in] V #V by dim list of vertex positions
|
||||
/// @param[in] Ele #Ele by dim list of simplex indices
|
||||
/// @param[in] origin dim-long ray origin
|
||||
/// @param[in] dir dim-long ray direction
|
||||
/// @param[in] min_t minimum t value to consider
|
||||
/// @param[out] hit first hit
|
||||
/// @return true if any hit
|
||||
template <typename DerivedEle>
|
||||
IGL_INLINE bool intersect_ray_opt(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const RowVectorDIMS & origin,
|
||||
const RowVectorDIMS & dir,
|
||||
const RowVectorDIMS & inv_dir,
|
||||
const RowVectorDIMS & inv_dir_pad,
|
||||
const Scalar min_t,
|
||||
igl::Hit<typename DerivedV::Scalar> & hit) const;
|
||||
public:
|
||||
EIGEN_MAKE_ALIGNED_OPERATOR_NEW
|
||||
};
|
||||
|
||||
+13
-12
@@ -6,6 +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 "AtA_cached.h"
|
||||
#include "IGL_ASSERT.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
@@ -34,12 +35,12 @@ IGL_INLINE void igl::AtA_cached_precompute(
|
||||
int col = k;
|
||||
int row = *(A.innerIndexPtr()+l);
|
||||
int value_index = l;
|
||||
assert(col < A.cols());
|
||||
assert(col >= 0);
|
||||
assert(row < A.rows());
|
||||
assert(row >= 0);
|
||||
assert(value_index >= 0);
|
||||
assert(value_index < A.nonZeros());
|
||||
IGL_ASSERT(col < A.cols());
|
||||
IGL_ASSERT(col >= 0);
|
||||
IGL_ASSERT(row < A.rows());
|
||||
IGL_ASSERT(row >= 0);
|
||||
IGL_ASSERT(value_index >= 0);
|
||||
IGL_ASSERT(value_index < A.nonZeros());
|
||||
|
||||
Col_RowPtr[col].push_back(row);
|
||||
Col_IndexPtr[col].push_back(value_index);
|
||||
@@ -74,12 +75,12 @@ IGL_INLINE void igl::AtA_cached_precompute(
|
||||
int col = k;
|
||||
int row = *(AtA.innerIndexPtr()+l);
|
||||
int value_index = l;
|
||||
assert(col < AtA.cols());
|
||||
assert(col >= 0);
|
||||
assert(row < AtA.rows());
|
||||
assert(row >= 0);
|
||||
assert(value_index >= 0);
|
||||
assert(value_index < AtA.nonZeros());
|
||||
IGL_ASSERT(col < AtA.cols());
|
||||
IGL_ASSERT(col >= 0);
|
||||
IGL_ASSERT(row < AtA.rows());
|
||||
IGL_ASSERT(row >= 0);
|
||||
IGL_ASSERT(value_index >= 0);
|
||||
IGL_ASSERT(value_index < AtA.nonZeros());
|
||||
|
||||
data.I_outer.push_back(data.I_row.size());
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2025 Alec Jacobson <alecjacobson@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_COLLAPSE_EDGE_NULL_H
|
||||
#define IGL_COLLAPSE_EDGE_NULL_H
|
||||
namespace igl
|
||||
{
|
||||
#ifndef IGL_COLLAPSE_EDGE_NULL
|
||||
/// Special value for indicating a null vertex index as the result of a
|
||||
/// collapsed edge.
|
||||
#define IGL_COLLAPSE_EDGE_NULL 0
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
@@ -200,10 +200,10 @@ typedef union SYS_FPRealUnionT<fpreal64> 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)
|
||||
#define UT_IGL_ASSERT_P(ZZ) ((void)0)
|
||||
#define UT_IGL_ASSERT(ZZ) ((void)0)
|
||||
#define UT_IGL_ASSERT_MSG_P(ZZ, MM) ((void)0)
|
||||
#define UT_IGL_ASSERT_MSG(ZZ, MM) ((void)0)
|
||||
/// @}
|
||||
}}
|
||||
|
||||
@@ -1961,7 +1961,7 @@ public:
|
||||
/// asserts are enabled.
|
||||
T & operator()(exint i)
|
||||
{
|
||||
UT_ASSERT_P(i >= 0 && i < mySize);
|
||||
UT_IGL_ASSERT_P(i >= 0 && i < mySize);
|
||||
return myData[i];
|
||||
}
|
||||
/// Const subscript operator
|
||||
@@ -1969,7 +1969,7 @@ public:
|
||||
/// asserts are enabled.
|
||||
const T & operator()(exint i) const
|
||||
{
|
||||
UT_ASSERT_P(i >= 0 && i < mySize);
|
||||
UT_IGL_ASSERT_P(i >= 0 && i < mySize);
|
||||
return myData[i];
|
||||
}
|
||||
|
||||
@@ -1978,7 +1978,7 @@ public:
|
||||
/// asserts are enabled.
|
||||
T & operator[](exint i)
|
||||
{
|
||||
UT_ASSERT_P(i >= 0 && i < mySize);
|
||||
UT_IGL_ASSERT_P(i >= 0 && i < mySize);
|
||||
return myData[i];
|
||||
}
|
||||
/// Const subscript operator
|
||||
@@ -1986,7 +1986,7 @@ public:
|
||||
/// asserts are enabled.
|
||||
const T & operator[](exint i) const
|
||||
{
|
||||
UT_ASSERT_P(i >= 0 && i < mySize);
|
||||
UT_IGL_ASSERT_P(i >= 0 && i < mySize);
|
||||
return myData[i];
|
||||
}
|
||||
|
||||
@@ -1995,7 +1995,7 @@ public:
|
||||
/// class types.
|
||||
T & forcedRef(exint i)
|
||||
{
|
||||
UT_ASSERT_P(i >= 0);
|
||||
UT_IGL_ASSERT_P(i >= 0);
|
||||
if (i >= mySize)
|
||||
bumpSize(i+1);
|
||||
return myData[i];
|
||||
@@ -2010,12 +2010,12 @@ public:
|
||||
|
||||
T & last()
|
||||
{
|
||||
UT_ASSERT_P(mySize);
|
||||
UT_IGL_ASSERT_P(mySize);
|
||||
return myData[mySize-1];
|
||||
}
|
||||
const T & last() const
|
||||
{
|
||||
UT_ASSERT_P(mySize);
|
||||
UT_IGL_ASSERT_P(mySize);
|
||||
return myData[mySize-1];
|
||||
}
|
||||
|
||||
@@ -2541,7 +2541,7 @@ UT_Array<T>::insert(exint index)
|
||||
}
|
||||
bumpCapacity(mySize + 1);
|
||||
|
||||
UT_ASSERT_P(index >= 0);
|
||||
UT_IGL_ASSERT_P(index >= 0);
|
||||
::memmove((void *)&myData[index+1], (void *)&myData[index],
|
||||
((mySize-index)*sizeof(T)));
|
||||
|
||||
@@ -2599,7 +2599,7 @@ template <typename T>
|
||||
inline void
|
||||
UT_Array<T>::appendMultiple(const T &t, exint count)
|
||||
{
|
||||
UT_ASSERT_P(count >= 0);
|
||||
UT_IGL_ASSERT_P(count >= 0);
|
||||
if (count <= 0)
|
||||
return;
|
||||
if (mySize + count >= myCapacity)
|
||||
@@ -2723,8 +2723,8 @@ template <typename T>
|
||||
inline void
|
||||
UT_Array<T>::removeRange(exint begin_i, exint end_i)
|
||||
{
|
||||
UT_ASSERT(begin_i <= end_i);
|
||||
UT_ASSERT(end_i <= size());
|
||||
UT_IGL_ASSERT(begin_i <= end_i);
|
||||
UT_IGL_ASSERT(end_i <= size());
|
||||
if (end_i < size())
|
||||
{
|
||||
trivialDestructRange(myData + begin_i, end_i - begin_i);
|
||||
@@ -2738,10 +2738,10 @@ template <typename T>
|
||||
inline void
|
||||
UT_Array<T>::extractRange(exint begin_i, exint end_i, UT_Array<T>& dest)
|
||||
{
|
||||
UT_ASSERT_P(begin_i >= 0);
|
||||
UT_ASSERT_P(begin_i <= end_i);
|
||||
UT_ASSERT_P(end_i <= size());
|
||||
UT_ASSERT(this != &dest);
|
||||
UT_IGL_ASSERT_P(begin_i >= 0);
|
||||
UT_IGL_ASSERT_P(begin_i <= end_i);
|
||||
UT_IGL_ASSERT_P(end_i <= size());
|
||||
UT_IGL_ASSERT(this != &dest);
|
||||
|
||||
exint nelements = end_i - begin_i;
|
||||
|
||||
@@ -2832,7 +2832,7 @@ UT_Array<T>::removeIf(IsEqual is_equal)
|
||||
{
|
||||
if (!is_equal(myData[idx]))
|
||||
{
|
||||
UT_ASSERT(idx != dst);
|
||||
UT_IGL_ASSERT(idx != dst);
|
||||
myData[dst] = myData[idx];
|
||||
dst++;
|
||||
}
|
||||
@@ -2907,7 +2907,7 @@ UT_Array<T>::setCapacity(exint capacity)
|
||||
T *prev = myData;
|
||||
myData = (T *)malloc(sizeof(T) * capacity);
|
||||
// myData is safe because we're already a stack buffer
|
||||
UT_ASSERT_P(isHeapBuffer());
|
||||
UT_IGL_ASSERT_P(isHeapBuffer());
|
||||
if (mySize > 0)
|
||||
memcpy((void *)myData, (void *)prev, sizeof(T) * mySize);
|
||||
myCapacity = capacity;
|
||||
@@ -2915,7 +2915,7 @@ UT_Array<T>::setCapacity(exint capacity)
|
||||
else
|
||||
{
|
||||
// Keep myCapacity unchanged in this case
|
||||
UT_ASSERT_P(capacity >= mySize && capacity <= myCapacity);
|
||||
UT_IGL_ASSERT_P(capacity >= mySize && capacity <= myCapacity);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -2955,7 +2955,7 @@ UT_Array<T>::setCapacity(exint capacity)
|
||||
}
|
||||
|
||||
myCapacity = capacity;
|
||||
UT_ASSERT(myData);
|
||||
UT_IGL_ASSERT(myData);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -3119,14 +3119,14 @@ public:
|
||||
// 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() \
|
||||
#define UT_SMALL_ARRAY_SIZE_IGL_ASSERT() \
|
||||
using ThisT = UT_SmallArray<T,MAX_BYTES>; \
|
||||
static_assert(offsetof(ThisT, myBuffer) == sizeof(UT_Array<T>), \
|
||||
"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<T>::isHeapBuffer());
|
||||
#define UT_SMALL_ARRAY_SIZE_IGL_ASSERT() \
|
||||
UT_IGL_ASSERT_P(!UT_Array<T>::isHeapBuffer());
|
||||
#endif
|
||||
|
||||
/// Default construction
|
||||
@@ -3134,7 +3134,7 @@ public:
|
||||
: UT_Array<T>(/*capacity*/0)
|
||||
{
|
||||
UT_Array<T>::unsafeShareData((T*)myBuffer, 0, MAX_ELEMS);
|
||||
UT_SMALL_ARRAY_SIZE_ASSERT();
|
||||
UT_SMALL_ARRAY_SIZE_IGL_ASSERT();
|
||||
}
|
||||
|
||||
/// Copy constructor
|
||||
@@ -3143,14 +3143,14 @@ public:
|
||||
: UT_Array<T>(/*capacity*/0)
|
||||
{
|
||||
UT_Array<T>::unsafeShareData((T*)myBuffer, 0, MAX_ELEMS);
|
||||
UT_SMALL_ARRAY_SIZE_ASSERT();
|
||||
UT_SMALL_ARRAY_SIZE_IGL_ASSERT();
|
||||
UT_Array<T>::operator=(copy);
|
||||
}
|
||||
explicit UT_SmallArray(const UT_SmallArray<T,MAX_BYTES> ©)
|
||||
: UT_Array<T>(/*capacity*/0)
|
||||
{
|
||||
UT_Array<T>::unsafeShareData((T*)myBuffer, 0, MAX_ELEMS);
|
||||
UT_SMALL_ARRAY_SIZE_ASSERT();
|
||||
UT_SMALL_ARRAY_SIZE_IGL_ASSERT();
|
||||
UT_Array<T>::operator=(copy);
|
||||
}
|
||||
/// @}
|
||||
@@ -3160,13 +3160,13 @@ public:
|
||||
UT_SmallArray(UT_Array<T> &&movable) noexcept
|
||||
{
|
||||
UT_Array<T>::unsafeShareData((T*)myBuffer, 0, MAX_ELEMS);
|
||||
UT_SMALL_ARRAY_SIZE_ASSERT();
|
||||
UT_SMALL_ARRAY_SIZE_IGL_ASSERT();
|
||||
UT_Array<T>::operator=(std::move(movable));
|
||||
}
|
||||
UT_SmallArray(UT_SmallArray<T,MAX_BYTES> &&movable) noexcept
|
||||
{
|
||||
UT_Array<T>::unsafeShareData((T*)myBuffer, 0, MAX_ELEMS);
|
||||
UT_SMALL_ARRAY_SIZE_ASSERT();
|
||||
UT_SMALL_ARRAY_SIZE_IGL_ASSERT();
|
||||
UT_Array<T>::operator=(std::move(movable));
|
||||
}
|
||||
/// @}
|
||||
@@ -3175,11 +3175,11 @@ public:
|
||||
explicit UT_SmallArray(std::initializer_list<T> init)
|
||||
{
|
||||
UT_Array<T>::unsafeShareData((T*)myBuffer, 0, MAX_ELEMS);
|
||||
UT_SMALL_ARRAY_SIZE_ASSERT();
|
||||
UT_SMALL_ARRAY_SIZE_IGL_ASSERT();
|
||||
UT_Array<T>::operator=(init);
|
||||
}
|
||||
|
||||
#undef UT_SMALL_ARRAY_SIZE_ASSERT
|
||||
#undef UT_SMALL_ARRAY_SIZE_IGL_ASSERT
|
||||
|
||||
/// Assignment operator
|
||||
/// @{
|
||||
@@ -3303,12 +3303,12 @@ public:
|
||||
|
||||
SYS_FORCE_INLINE const T &operator[](exint i) const noexcept
|
||||
{
|
||||
UT_ASSERT_P(i >= 0 && i < SIZE);
|
||||
UT_IGL_ASSERT_P(i >= 0 && i < SIZE);
|
||||
return vec[i];
|
||||
}
|
||||
SYS_FORCE_INLINE T &operator[](exint i) noexcept
|
||||
{
|
||||
UT_ASSERT_P(i >= 0 && i < SIZE);
|
||||
UT_IGL_ASSERT_P(i >= 0 && i < SIZE);
|
||||
return vec[i];
|
||||
}
|
||||
|
||||
@@ -3816,9 +3816,9 @@ namespace UT_Thread { inline int getNumProcessors() {
|
||||
//{
|
||||
// const size_t num_processors( UT_Thread::getNumProcessors() );
|
||||
//
|
||||
// UT_ASSERT( num_processors >= 1 );
|
||||
// UT_ASSERT( min_grain_size >= 1 );
|
||||
// UT_ASSERT( subscribe_ratio >= 0 );
|
||||
// UT_IGL_ASSERT( num_processors >= 1 );
|
||||
// UT_IGL_ASSERT( min_grain_size >= 1 );
|
||||
// UT_IGL_ASSERT( subscribe_ratio >= 0 );
|
||||
//
|
||||
// const size_t est_range_size( UTestimatedNumItems(range) );
|
||||
//
|
||||
@@ -3948,11 +3948,11 @@ struct Box {
|
||||
}
|
||||
|
||||
SYS_FORCE_INLINE const T* operator[](const size_t axis) const noexcept {
|
||||
UT_ASSERT_P(axis < NAXES);
|
||||
UT_IGL_ASSERT_P(axis < NAXES);
|
||||
return vals[axis];
|
||||
}
|
||||
SYS_FORCE_INLINE T* operator[](const size_t axis) noexcept {
|
||||
UT_ASSERT_P(axis < NAXES);
|
||||
UT_IGL_ASSERT_P(axis < NAXES);
|
||||
return vals[axis];
|
||||
}
|
||||
|
||||
@@ -4402,7 +4402,7 @@ private:
|
||||
T diameter2 = box.diameter2();
|
||||
return diameter2*SYSsqrt(diameter2);
|
||||
}
|
||||
UT_ASSERT_MSG(0, "BVH_Heuristic::MEDIAN_MAX_AXIS should be handled separately by caller!");
|
||||
UT_IGL_ASSERT_MSG(0, "BVH_Heuristic::MEDIAN_MAX_AXIS should be handled separately by caller!");
|
||||
return T(1);
|
||||
}
|
||||
|
||||
@@ -4535,8 +4535,8 @@ struct ut_BoxCentre<UT_FixedVector<T,NAXES,INSTANTIATED>> {
|
||||
template<typename BOX_TYPE,typename SRC_INT_TYPE,typename INT_TYPE>
|
||||
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;
|
||||
//constexpr INT_TYPE PARALLEL_THRESHOLD = 65536;
|
||||
//INT_TYPE ntasks = 1;
|
||||
//if (nboxes >= PARALLEL_THRESHOLD)
|
||||
//{
|
||||
// INT_TYPE nprocessors = UT_Thread::getNumProcessors();
|
||||
@@ -4774,7 +4774,7 @@ inline void BVH<N>::traverseParallelHelper(
|
||||
}
|
||||
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.");
|
||||
UT_IGL_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 {
|
||||
@@ -4851,7 +4851,7 @@ inline void BVH<N>::traverseVectorHelper(
|
||||
template<uint N>
|
||||
template<typename SRC_INT_TYPE>
|
||||
inline void BVH<N>::createTrivialIndices(SRC_INT_TYPE* indices, const INT_TYPE n) noexcept {
|
||||
igl::parallel_for(n, [indices,n](INT_TYPE i) { indices[i] = i; }, 65536);
|
||||
igl::parallel_for(n, [indices](INT_TYPE i) { indices[i] = i; }, 65536);
|
||||
}
|
||||
|
||||
template<uint N>
|
||||
@@ -4980,7 +4980,7 @@ inline void BVH<N>::initNode(UT_Array<Node>& nodes, Node &node, const Box<T,NAXE
|
||||
++counted_parallel;
|
||||
}
|
||||
}
|
||||
UT_ASSERT_P(counted_parallel == taski);
|
||||
UT_IGL_ASSERT_P(counted_parallel == taski);
|
||||
|
||||
UT_Array<Node>& local_nodes = parallel_nodes[taski];
|
||||
// Preallocate an overestimate of the number of nodes needed.
|
||||
@@ -5174,7 +5174,7 @@ inline void BVH<N>::initNodeReorder(UT_Array<Node>& nodes, Node &node, const Box
|
||||
// ++counted_parallel;
|
||||
// }
|
||||
// }
|
||||
// UT_ASSERT_P(counted_parallel == taski);
|
||||
// UT_IGL_ASSERT_P(counted_parallel == taski);
|
||||
|
||||
// UT_Array<Node>& local_nodes = parallel_nodes[taski];
|
||||
// // Preallocate an overestimate of the number of nodes needed.
|
||||
@@ -5297,7 +5297,7 @@ inline void BVH<N>::multiSplit(const Box<T,NAXES>& axes_minmax, const BOX_TYPE*
|
||||
box = sub_boxes_unsorted[j];
|
||||
}
|
||||
}
|
||||
UT_ASSERT_P(min_pointer);
|
||||
UT_IGL_ASSERT_P(min_pointer);
|
||||
sub_indices[i] = min_pointer;
|
||||
sub_boxes[i] = box;
|
||||
}
|
||||
@@ -5321,7 +5321,7 @@ inline void BVH<N>::multiSplit(const Box<T,NAXES>& axes_minmax, const BOX_TYPE*
|
||||
}
|
||||
}
|
||||
}
|
||||
UT_ASSERT_MSG_P(split_choice != INT_TYPE(-1), "There should always be at least one that can be split!");
|
||||
UT_IGL_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];
|
||||
@@ -5354,10 +5354,10 @@ inline void BVH<N>::split(const Box<T,NAXES>& axes_minmax, const BOX_TYPE* boxes
|
||||
split_indices = indices+1;
|
||||
return;
|
||||
}
|
||||
UT_ASSERT_MSG_P(nboxes > 2, "Cases with less than 3 boxes should have already been handled!");
|
||||
UT_IGL_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!!!");
|
||||
UT_IGL_ASSERT_MSG(0, "FIXME: Implement this!!!");
|
||||
}
|
||||
|
||||
constexpr INT_TYPE SMALL_LIMIT = 6;
|
||||
@@ -5683,9 +5683,9 @@ inline void BVH<N>::split(const Box<T,NAXES>& axes_minmax, const BOX_TYPE* boxes
|
||||
|
||||
// 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");
|
||||
UT_IGL_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.");
|
||||
UT_IGL_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<T>::infinity();
|
||||
INT_TYPE split_index = -1;
|
||||
for (INT_TYPE spliti = 0; spliti < NSPLITS; ++spliti) {
|
||||
@@ -5820,7 +5820,7 @@ inline void BVH<N>::adjustParallelChildNodes(INT_TYPE nparallel, UT_Array<Node>&
|
||||
++counted_parallel;
|
||||
}
|
||||
}
|
||||
UT_ASSERT_P(counted_parallel == taski);
|
||||
UT_IGL_ASSERT_P(counted_parallel == taski);
|
||||
|
||||
const UT_Array<Node>& local_nodes = parallel_nodes[counted_parallel];
|
||||
INT_TYPE n = local_nodes.size();
|
||||
@@ -6661,11 +6661,11 @@ inline void UT_SolidAngle<T,S>::init(
|
||||
, myPositions(positions)
|
||||
, myOrder(order)
|
||||
{}
|
||||
constexpr SYS_FORCE_INLINE bool pre(const int nodei, LocalData *data_for_parent) const
|
||||
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
|
||||
void item(const int itemi, const int /*parent_nodei*/, LocalData &data_for_parent) const
|
||||
{
|
||||
const UT_Vector3T<S> *const positions = myPositions;
|
||||
const int *const cur_triangle_points = myTrianglePoints + 3*itemi;
|
||||
@@ -6776,9 +6776,9 @@ inline void UT_SolidAngle<T,S>::init(
|
||||
const UT_Vector3T<T> oab = b - a;
|
||||
const UT_Vector3T<T> oac = c - a;
|
||||
const UT_Vector3T<T> ocb = b - c;
|
||||
UT_ASSERT_MSG_P(oac[i] > 0, "This should have been checked by the caller.");
|
||||
UT_IGL_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.");
|
||||
UT_IGL_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);
|
||||
@@ -6889,7 +6889,7 @@ inline void UT_SolidAngle<T,S>::init(
|
||||
#endif
|
||||
}
|
||||
|
||||
void post(const int nodei, const int parent_nodei, LocalData *data_for_parent, const int nchildren, const LocalData *child_data_array) const
|
||||
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.
|
||||
@@ -7169,9 +7169,9 @@ inline T UT_SolidAngle<T, S>::computeSolidAngle(const UT_Vector3T<T> &query_poin
|
||||
: myBoxData(box_data)
|
||||
, myQueryPoint(query_point)
|
||||
, myAccuracyScale2(accuracy_scale2)
|
||||
, myOrder(order)
|
||||
, myPositions(positions)
|
||||
, myTrianglePoints(triangle_points)
|
||||
, myOrder(order)
|
||||
{}
|
||||
uint pre(const int nodei, T *data_for_parent) const
|
||||
{
|
||||
@@ -7257,7 +7257,7 @@ inline T UT_SolidAngle<T, S>::computeSolidAngle(const UT_Vector3T<T> &query_poin
|
||||
|
||||
return descend_bitmask;
|
||||
}
|
||||
void item(const int itemi, const int parent_nodei, T &data_for_parent) const
|
||||
void item(const int itemi, const int /*parent_nodei*/, T &data_for_parent) const
|
||||
{
|
||||
const UT_Vector3T<S> *const positions = myPositions;
|
||||
const int *const cur_triangle_points = myTrianglePoints + 3*itemi;
|
||||
@@ -7267,7 +7267,7 @@ inline T UT_SolidAngle<T, S>::computeSolidAngle(const UT_Vector3T<T> &query_poin
|
||||
|
||||
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
|
||||
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)
|
||||
@@ -7446,11 +7446,11 @@ inline void UT_SubtendedAngle<T,S>::init(
|
||||
, myPositions(positions)
|
||||
, myOrder(order)
|
||||
{}
|
||||
constexpr SYS_FORCE_INLINE bool pre(const int nodei, LocalData *data_for_parent) const
|
||||
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
|
||||
void item(const int itemi, const int /*parent_nodei*/, LocalData &data_for_parent) const
|
||||
{
|
||||
const UT_Vector2T<S> *const positions = myPositions;
|
||||
const int *const cur_segment_points = mySegmentPoints + 2*itemi;
|
||||
@@ -7516,7 +7516,7 @@ inline void UT_SubtendedAngle<T,S>::init(
|
||||
#endif
|
||||
}
|
||||
|
||||
void post(const int nodei, const int parent_nodei, LocalData *data_for_parent, const int nchildren, const LocalData *child_data_array) const
|
||||
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.
|
||||
@@ -7798,7 +7798,7 @@ inline T UT_SubtendedAngle<T, S>::computeAngle(const UT_Vector2T<T> &query_point
|
||||
|
||||
return descend_bitmask;
|
||||
}
|
||||
void item(const int itemi, const int parent_nodei, T &data_for_parent) const
|
||||
void item(const int itemi, const int /*parent_nodei*/, T &data_for_parent) const
|
||||
{
|
||||
const UT_Vector2T<S> *const positions = myPositions;
|
||||
const int *const cur_segment_points = mySegmentPoints + 2*itemi;
|
||||
@@ -7807,7 +7807,7 @@ inline T UT_SubtendedAngle<T, S>::computeAngle(const UT_Vector2T<T> &query_point
|
||||
|
||||
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
|
||||
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)
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace igl {
|
||||
pos_type seekoff(
|
||||
off_type off,
|
||||
std::ios_base::seekdir dir,
|
||||
std::ios_base::openmode which) override
|
||||
std::ios_base::openmode /*which*/) override
|
||||
{
|
||||
if (dir == std::ios_base::cur)
|
||||
{
|
||||
|
||||
@@ -63,10 +63,10 @@ IGL_INLINE bool igl::HalfEdgeIterator<DerivedF,DerivedFF,DerivedFFi>::isBorder()
|
||||
/*!
|
||||
* Returns the next edge skipping the border
|
||||
* _________
|
||||
* /\ c | b /\
|
||||
* / \ | / \
|
||||
* / d \ | / a \
|
||||
* /______\|/______\
|
||||
* ╱╲ c | b ╱╲
|
||||
* ╱ ╲ | ╱ ╲
|
||||
* ╱ d ╲ | ╱ a ╲
|
||||
* ╱______╲|╱______╲
|
||||
* v
|
||||
* In this example, if a and d are of-border and the pos is iterating counterclockwise, this method iterate through the faces incident on vertex v,
|
||||
* producing the sequence a, b, c, d, a, b, c, ...
|
||||
|
||||
@@ -69,10 +69,10 @@ namespace igl
|
||||
|
||||
/// Change to next edge skipping the border
|
||||
/// _________
|
||||
/// /\ c | b /\
|
||||
/// / \ | / \
|
||||
/// / d \ | / a \
|
||||
/// /______\|/______\
|
||||
/// ╱╲ c | b ╱╲
|
||||
/// ╱ ╲ | ╱ ╲
|
||||
/// ╱ d ╲ | ╱ a ╲
|
||||
/// ╱______╲|╱______╲
|
||||
/// v
|
||||
/// In this example, if a and d are of-border and the pos is iterating
|
||||
/// counterclockwise, this method iterate through the faces incident on vertex
|
||||
|
||||
+3
-3
@@ -13,7 +13,7 @@ namespace igl
|
||||
{
|
||||
/// Reimplementation of the embree::Hit struct from embree1.0
|
||||
///
|
||||
// TODO: template on floating point type
|
||||
template <typename Scalar>
|
||||
struct Hit
|
||||
{
|
||||
/// primitive id
|
||||
@@ -22,10 +22,10 @@ namespace igl
|
||||
int gid;
|
||||
/// barycentric coordinates so that
|
||||
/// pos = V.row(F(id,0))*(1-u-v)+V.row(F(id,1))*u+V.row(F(id,2))*v;
|
||||
float u,v;
|
||||
Scalar u,v;
|
||||
/// parametric distance so that
|
||||
/// pos = origin + t * dir
|
||||
float t;
|
||||
Scalar t;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
// https://stackoverflow.com/a/985807/148668
|
||||
#include <cassert>
|
||||
#ifndef IGL_ASSERT
|
||||
#ifdef NDEBUG
|
||||
#define IGL_ASSERT(x) do { (void)sizeof(x);} while (0)
|
||||
#else
|
||||
#define IGL_ASSERT(x) assert(x)
|
||||
#endif
|
||||
#endif
|
||||
@@ -105,7 +105,6 @@ IGL_INLINE void igl::MshSaver::save_elements(const IndexVector& elements,
|
||||
|
||||
if (m_num_elements > 0) {
|
||||
//int elem_type = el_type;
|
||||
int num_elems = m_num_elements;
|
||||
//int tags = 0;
|
||||
if (!m_binary) {
|
||||
size_t el_ptr=0;
|
||||
@@ -213,7 +212,6 @@ IGL_INLINE void igl::MshSaver::save_vector_field(const std::string& fieldname, c
|
||||
fout << "3" << std::endl; // 3-component vector field.
|
||||
fout << m_num_nodes << std::endl; // number of nodes
|
||||
|
||||
const Float zero = 0.0;
|
||||
if (m_binary) {
|
||||
for (size_t i=0; i<m_num_nodes; i++) {
|
||||
int node_idx = i+1;
|
||||
@@ -275,7 +273,6 @@ IGL_INLINE void igl::MshSaver::save_elem_vector_field(const std::string& fieldna
|
||||
fout << "3" << std::endl; // 3-component vector field.
|
||||
fout << m_num_elements << std::endl; // number of elements
|
||||
|
||||
const Float zero = 0.0;
|
||||
if (m_binary) {
|
||||
for (size_t i=0; i<m_num_elements; ++i) {
|
||||
int elem_idx = i+1;
|
||||
@@ -310,7 +307,6 @@ IGL_INLINE void igl::MshSaver::save_elem_tensor_field(const std::string& fieldna
|
||||
fout << "9" << std::endl; // 9-component tensor field.
|
||||
fout << m_num_elements << std::endl; // number of elements
|
||||
|
||||
const Float zero = 0.0;
|
||||
|
||||
if (m_binary) {
|
||||
for (size_t i=0; i<m_num_elements; i++) {
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2024 Alec Jacobson <alecjacobson@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_PLAINMATRIX_H
|
||||
#define IGL_PLAINMATRIX_H
|
||||
#include <Eigen/Core>
|
||||
|
||||
#include <type_traits>
|
||||
#include <Eigen/Dense>
|
||||
|
||||
// Define void_t for compatibility if it's not in the standard library (C++11 and later)
|
||||
#if __cplusplus < 201703L
|
||||
namespace std {
|
||||
template <typename... Ts>
|
||||
using void_t = void;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef IGL_DEFAULT_MAJORING
|
||||
#define IGL_DEFAULT_MAJORING Eigen::ColMajor
|
||||
#endif
|
||||
|
||||
namespace igl
|
||||
{
|
||||
template <typename Derived, int Rows, int Cols, int Options>
|
||||
struct PlainMatrixHelper {
|
||||
using Type = Eigen::Matrix<typename Derived::Scalar,Rows,Cols,((Rows == 1 && Cols != 1) ? Eigen::RowMajor : ((Cols == 1 && Rows != 1) ? Eigen::ColMajor : Options))>;
|
||||
};
|
||||
template <typename Derived, typename = void>
|
||||
struct get_options {
|
||||
static constexpr int value = IGL_DEFAULT_MAJORING;
|
||||
};
|
||||
|
||||
template <typename Derived>
|
||||
struct get_options<Derived, std::void_t<decltype(Derived::Options)>> {
|
||||
static constexpr int value = Derived::Options;
|
||||
};
|
||||
/// Some libigl implementations would (still do?) use a pattern like:
|
||||
///
|
||||
/// template <typename DerivedA>
|
||||
/// void foo(const Eigen::MatrixBase<DerivedA>& A)
|
||||
/// {
|
||||
/// DerivedA B;
|
||||
/// igl::unique_rows(A,true,B);
|
||||
/// }
|
||||
///
|
||||
/// If `DerivedA` is `Eigen::Matrix`, then this may compile, but `DerivedA` might be
|
||||
/// from a Eigen::Map or Eigen::Ref and fail to compile due to missing
|
||||
/// construtor.
|
||||
///
|
||||
/// Even worse, the code above will work if `DerivedA` has dynamic rows, but will
|
||||
/// throw a runtime error if `DerivedA` has fixed number of rows.
|
||||
///
|
||||
/// Instead it's better to declare `B` as a `Eigen::Matrix`
|
||||
///
|
||||
/// Eigen::Matrix<typename DerivedA::Scalar,Eigen::Dynamic,DerivedA::ColsAtCompileTime,DerivedA::Options> B;
|
||||
///
|
||||
/// Using `Eigen::Dynamic` for dimensions that may not be known at compile
|
||||
/// time (or may be different from A).
|
||||
///
|
||||
/// `igl::PlainMatrix` is just a helper to make this easier. So in this case
|
||||
/// we could write:
|
||||
///
|
||||
/// igl::PlainMatrix<DerivedA,Eigen::Dynamic> B;
|
||||
///
|
||||
/// IIUC, if the code in question looks like:
|
||||
///
|
||||
/// template <typename DerivedC>
|
||||
/// void foo(Eigen::PlainObjectBase<DerivedC>& C)
|
||||
/// {
|
||||
/// DerivedC B;
|
||||
/// …
|
||||
/// C.resize(not_known_at_compile_time,also_not_known_at_compile_time);
|
||||
/// }
|
||||
///
|
||||
/// Then it's probably fine. If C can be resized to different sizes, then
|
||||
/// `DerivedC` should be `Eigen::Matrix`-like .
|
||||
// Helper to check if `Options` exists in Derived
|
||||
|
||||
// Modify PlainMatrix to use get_options
|
||||
template <typename Derived,
|
||||
int Rows = Derived::RowsAtCompileTime,
|
||||
int Cols = Derived::ColsAtCompileTime,
|
||||
int Options = get_options<Derived>::value>
|
||||
using PlainMatrix = typename PlainMatrixHelper<Derived, Rows, Cols, Options>::Type;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2024 Alec Jacobson <alecjacobson@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_PLAINVECTOR_H
|
||||
#define IGL_PLAINVECTOR_H
|
||||
#include <Eigen/Core>
|
||||
#include "PlainMatrix.h"
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// PlainVectorHelper to determine correct matrix type based on Derived and Size
|
||||
template <typename Derived, int Size, int Options>
|
||||
struct PlainVectorHelper {
|
||||
// Conditional Type: Column vector if is_column_vector is true, otherwise row vector
|
||||
using Type = Eigen::Matrix<
|
||||
typename Derived::Scalar,
|
||||
(Derived::ColsAtCompileTime == 1 && Derived::RowsAtCompileTime != 1) ? Size : 1,
|
||||
(Derived::ColsAtCompileTime == 1 && Derived::RowsAtCompileTime != 1) ? 1 : Size,
|
||||
Options>;
|
||||
};
|
||||
|
||||
/// \see PlainMatrix
|
||||
template <
|
||||
typename Derived,
|
||||
int Size = (Derived::ColsAtCompileTime == 1 && Derived::RowsAtCompileTime != 1) ? Derived::RowsAtCompileTime : Derived::ColsAtCompileTime,
|
||||
int Options = get_options<Derived>::value>
|
||||
using PlainVector = typename PlainVectorHelper<Derived, Size, Options>::Type;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
#pragma warning( disable : 592 )
|
||||
#endif
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wuninitialized"
|
||||
|
||||
// #define USE_ACCURATE_RSQRT_IN_JACOBI_CONJUGATION
|
||||
// #define PERFORM_STRICT_QUATERNION_RENORMALIZATION
|
||||
|
||||
@@ -1272,6 +1275,8 @@
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
#ifdef __INTEL_COMPILER
|
||||
#pragma warning( default : 592 )
|
||||
#endif
|
||||
|
||||
+5
-4
@@ -22,6 +22,7 @@
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace igl
|
||||
{
|
||||
@@ -69,9 +70,9 @@ namespace igl
|
||||
/// @param[in] endTime end time
|
||||
/// @param[in] startTime start time
|
||||
/// @return time
|
||||
double subtractTimes( uint64_t endTime, uint64_t startTime )
|
||||
double subtractTimes( std::uint64_t endTime, std::uint64_t startTime )
|
||||
{
|
||||
uint64_t difference = endTime - startTime;
|
||||
std::uint64_t difference = endTime - startTime;
|
||||
static double conversion = 0.0;
|
||||
|
||||
if( conversion == 0.0 )
|
||||
@@ -175,8 +176,8 @@ namespace igl
|
||||
LARGE_INTEGER startCount;
|
||||
LARGE_INTEGER endCount;
|
||||
#elif __APPLE__
|
||||
uint64_t startCount;
|
||||
uint64_t endCount;
|
||||
std::uint64_t startCount;
|
||||
std::uint64_t endCount;
|
||||
#else
|
||||
timeval startCount;
|
||||
timeval endCount;
|
||||
|
||||
@@ -13,21 +13,24 @@
|
||||
#ifndef IGL_WINDINGNUMBERAABB_H
|
||||
#define IGL_WINDINGNUMBERAABB_H
|
||||
#include "WindingNumberTree.h"
|
||||
#include "PlainMatrix.h"
|
||||
|
||||
namespace igl
|
||||
{
|
||||
/// Class for building an AABB tree to implement the divide and conquer
|
||||
/// algorithm described in [Jacobson et al. 2013].
|
||||
template <
|
||||
typename Point,
|
||||
typename DerivedV,
|
||||
typename DerivedF >
|
||||
class WindingNumberAABB : public WindingNumberTree<Point,DerivedV,DerivedF>
|
||||
typename Scalar,
|
||||
typename Index>
|
||||
class WindingNumberAABB : public WindingNumberTree<Scalar,Index>
|
||||
{
|
||||
protected:
|
||||
// WindingNumberTree defines Point
|
||||
using Point = typename WindingNumberTree<Scalar,Index>::Point;
|
||||
using MatrixXF = typename WindingNumberTree<Scalar,Index>::MatrixXF;
|
||||
Point min_corner;
|
||||
Point max_corner;
|
||||
typename DerivedV::Scalar total_positive_area;
|
||||
Scalar total_positive_area;
|
||||
public:
|
||||
enum SplitMethod
|
||||
{
|
||||
@@ -37,23 +40,25 @@ namespace igl
|
||||
} split_method;
|
||||
public:
|
||||
inline WindingNumberAABB():
|
||||
total_positive_area(std::numeric_limits<typename DerivedV::Scalar>::infinity()),
|
||||
total_positive_area(std::numeric_limits<Scalar>::infinity()),
|
||||
split_method(MEDIAN_ON_LONGEST_AXIS)
|
||||
{}
|
||||
/// Constructor
|
||||
///
|
||||
/// @param[in] V #V by 3 list of vertex positions
|
||||
/// @param[in] F #F by 3 list of triangle indices into V
|
||||
template <typename DerivedV, typename DerivedF>
|
||||
inline WindingNumberAABB(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F);
|
||||
inline WindingNumberAABB(
|
||||
const WindingNumberTree<Point,DerivedV,DerivedF> & parent,
|
||||
const Eigen::MatrixBase<DerivedF> & F);
|
||||
const WindingNumberTree<Scalar,Index> & parent,
|
||||
const typename WindingNumberTree<Scalar,Index>::MatrixXF & F);
|
||||
/// Initialize the hierarchy to a given mesh
|
||||
///
|
||||
/// @param[in] V #V by 3 list of vertex positions
|
||||
/// @param[in] F #F by 3 list of triangle indices into V
|
||||
template <typename DerivedV, typename DerivedF>
|
||||
inline void set_mesh(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F);
|
||||
@@ -62,8 +67,8 @@ namespace igl
|
||||
inline virtual void grow();
|
||||
// Compute min and max corners
|
||||
inline void compute_min_max_corners();
|
||||
inline typename DerivedV::Scalar max_abs_winding_number(const Point & p) const;
|
||||
inline typename DerivedV::Scalar max_simple_abs_winding_number(const Point & p) const;
|
||||
inline Scalar max_abs_winding_number(const Point & p) const;
|
||||
inline Scalar max_simple_abs_winding_number(const Point & p) const;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -86,70 +91,76 @@ namespace igl
|
||||
# define WindingNumberAABB_MIN_F 100
|
||||
#endif
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline void igl::WindingNumberAABB<Point,DerivedV,DerivedF>::set_mesh(
|
||||
template <typename Scalar, typename Index>
|
||||
template <typename DerivedV, typename DerivedF>
|
||||
inline void igl::WindingNumberAABB<Scalar,Index>::set_mesh(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F)
|
||||
{
|
||||
igl::WindingNumberTree<Point,DerivedV,DerivedF>::set_mesh(V,F);
|
||||
// static assert that DerivedF::ColsAtCompileTime == 3 or Eigen::Dynamic
|
||||
static_assert(
|
||||
DerivedF::ColsAtCompileTime == 3 || DerivedF::ColsAtCompileTime == Eigen::Dynamic,
|
||||
"F should have 3 or Dynamic columns");
|
||||
igl::WindingNumberTree<Scalar,Index>::set_mesh(V,F);
|
||||
init();
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline void igl::WindingNumberAABB<Point,DerivedV,DerivedF>::init()
|
||||
template <typename Scalar, typename Index>
|
||||
inline void igl::WindingNumberAABB<Scalar,Index>::init()
|
||||
{
|
||||
using namespace Eigen;
|
||||
assert(max_corner.size() == 3);
|
||||
assert(min_corner.size() == 3);
|
||||
compute_min_max_corners();
|
||||
Eigen::Matrix<typename DerivedV::Scalar,Eigen::Dynamic,1> dblA;
|
||||
doublearea(this->getV(),this->getF(),dblA);
|
||||
Eigen::Matrix<Scalar,Eigen::Dynamic,1> dblA;
|
||||
doublearea((*this->Vptr),(this->F),dblA);
|
||||
total_positive_area = dblA.sum()/2.0;
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline igl::WindingNumberAABB<Point,DerivedV,DerivedF>::WindingNumberAABB(
|
||||
template <typename Scalar, typename Index>
|
||||
template <typename DerivedV, typename DerivedF>
|
||||
inline igl::WindingNumberAABB<Scalar,Index>::WindingNumberAABB(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F):
|
||||
WindingNumberTree<Point,DerivedV,DerivedF>(V,F),
|
||||
WindingNumberTree<Scalar,Index>(V,F),
|
||||
min_corner(),
|
||||
max_corner(),
|
||||
total_positive_area(
|
||||
std::numeric_limits<typename DerivedV::Scalar>::infinity()),
|
||||
std::numeric_limits<Scalar>::infinity()),
|
||||
split_method(MEDIAN_ON_LONGEST_AXIS)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline igl::WindingNumberAABB<Point,DerivedV,DerivedF>::WindingNumberAABB(
|
||||
const WindingNumberTree<Point,DerivedV,DerivedF> & parent,
|
||||
const Eigen::MatrixBase<DerivedF> & F):
|
||||
WindingNumberTree<Point,DerivedV,DerivedF>(parent,F),
|
||||
template <typename Scalar, typename Index>
|
||||
inline igl::WindingNumberAABB<Scalar,Index>::WindingNumberAABB(
|
||||
const WindingNumberTree<Scalar,Index> & parent,
|
||||
const typename WindingNumberTree<Scalar,Index>::MatrixXF & F):
|
||||
WindingNumberTree<Scalar,Index>(parent,F),
|
||||
min_corner(),
|
||||
max_corner(),
|
||||
total_positive_area(
|
||||
std::numeric_limits<typename DerivedV::Scalar>::infinity()),
|
||||
std::numeric_limits<Scalar>::infinity()),
|
||||
split_method(MEDIAN_ON_LONGEST_AXIS)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline void igl::WindingNumberAABB<Point,DerivedV,DerivedF>::grow()
|
||||
template <typename Scalar, typename Index>
|
||||
inline void igl::WindingNumberAABB<Scalar,Index>::grow()
|
||||
{
|
||||
using namespace std;
|
||||
using namespace Eigen;
|
||||
// Clear anything that already exists
|
||||
this->delete_children();
|
||||
|
||||
//cout<<"cap.rows(): "<<this->getcap().rows()<<endl;
|
||||
//cout<<"F.rows(): "<<this->getF().rows()<<endl;
|
||||
//cout<<"cap.rows(): "<<(this->cap).rows()<<endl;
|
||||
//cout<<"F.rows(): "<<(this->F).rows()<<endl;
|
||||
|
||||
// Base cases
|
||||
if(
|
||||
this->getF().rows() <= (WindingNumberAABB_MIN_F>0?WindingNumberAABB_MIN_F:0) ||
|
||||
(this->getcap().rows() - 2) >= this->getF().rows())
|
||||
(this->F).rows() <= (WindingNumberAABB_MIN_F>0?WindingNumberAABB_MIN_F:0) ||
|
||||
((this->cap).rows() - 2) >= (this->F).rows())
|
||||
{
|
||||
// Don't grow
|
||||
return;
|
||||
@@ -157,8 +168,8 @@ inline void igl::WindingNumberAABB<Point,DerivedV,DerivedF>::grow()
|
||||
|
||||
// Compute longest direction
|
||||
int max_d = -1;
|
||||
typename DerivedV::Scalar max_len =
|
||||
-numeric_limits<typename DerivedV::Scalar>::infinity();
|
||||
Scalar max_len =
|
||||
-numeric_limits<Scalar>::infinity();
|
||||
for(int d = 0;d<min_corner.size();d++)
|
||||
{
|
||||
if( (max_corner[d] - min_corner[d]) > max_len )
|
||||
@@ -168,13 +179,13 @@ inline void igl::WindingNumberAABB<Point,DerivedV,DerivedF>::grow()
|
||||
}
|
||||
}
|
||||
// Compute facet barycenters
|
||||
Eigen::Matrix<typename DerivedV::Scalar,Eigen::Dynamic,Eigen::Dynamic> BC;
|
||||
barycenter(this->getV(),this->getF(),BC);
|
||||
Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic> BC;
|
||||
barycenter((*this->Vptr),(this->F),BC);
|
||||
|
||||
|
||||
// Blerg, why is selecting rows so difficult
|
||||
|
||||
typename DerivedV::Scalar split_value;
|
||||
Scalar split_value;
|
||||
// Split in longest direction
|
||||
switch(split_method)
|
||||
{
|
||||
@@ -191,8 +202,8 @@ inline void igl::WindingNumberAABB<Point,DerivedV,DerivedF>::grow()
|
||||
//cout<<"c: "<<0.5*(max_corner[max_d] + min_corner[max_d])<<" "<<
|
||||
// "m: "<<split_value<<endl;;
|
||||
|
||||
vector<int> id( this->getF().rows());
|
||||
for(int i = 0;i<this->getF().rows();i++)
|
||||
vector<int> id( (this->F).rows());
|
||||
for(int i = 0;i<(this->F).rows();i++)
|
||||
{
|
||||
if(BC(i,max_d) <= split_value)
|
||||
{
|
||||
@@ -210,19 +221,19 @@ inline void igl::WindingNumberAABB<Point,DerivedV,DerivedF>::grow()
|
||||
// badly balanced base case (could try to recut)
|
||||
return;
|
||||
}
|
||||
assert(lefts+rights == this->getF().rows());
|
||||
DerivedF leftF(lefts, this->getF().cols());
|
||||
DerivedF rightF(rights,this->getF().cols());
|
||||
assert(lefts+rights == (this->F).rows());
|
||||
MatrixXF leftF(lefts, (this->F).cols());
|
||||
MatrixXF rightF(rights,(this->F).cols());
|
||||
int left_i = 0;
|
||||
int right_i = 0;
|
||||
for(int i = 0;i<this->getF().rows();i++)
|
||||
for(int i = 0;i<(this->F).rows();i++)
|
||||
{
|
||||
if(id[i] == 0)
|
||||
{
|
||||
leftF.row(left_i++) = this->getF().row(i);
|
||||
leftF.row(left_i++) = (this->F).row(i);
|
||||
}else if(id[i] == 1)
|
||||
{
|
||||
rightF.row(right_i++) = this->getF().row(i);
|
||||
rightF.row(right_i++) = (this->F).row(i);
|
||||
}else
|
||||
{
|
||||
assert(false);
|
||||
@@ -231,18 +242,18 @@ inline void igl::WindingNumberAABB<Point,DerivedV,DerivedF>::grow()
|
||||
assert(right_i == rightF.rows());
|
||||
assert(left_i == leftF.rows());
|
||||
// Finally actually grow children and Recursively grow
|
||||
WindingNumberAABB<Point,DerivedV,DerivedF> * leftWindingNumberAABB =
|
||||
new WindingNumberAABB<Point,DerivedV,DerivedF>(*this,leftF);
|
||||
WindingNumberAABB<Scalar,Index> * leftWindingNumberAABB =
|
||||
new WindingNumberAABB<Scalar,Index>(*this,leftF);
|
||||
leftWindingNumberAABB->grow();
|
||||
this->children.push_back(leftWindingNumberAABB);
|
||||
WindingNumberAABB<Point,DerivedV,DerivedF> * rightWindingNumberAABB =
|
||||
new WindingNumberAABB<Point,DerivedV,DerivedF>(*this,rightF);
|
||||
WindingNumberAABB<Scalar,Index> * rightWindingNumberAABB =
|
||||
new WindingNumberAABB<Scalar,Index>(*this,rightF);
|
||||
rightWindingNumberAABB->grow();
|
||||
this->children.push_back(rightWindingNumberAABB);
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline bool igl::WindingNumberAABB<Point,DerivedV,DerivedF>::inside(const Point & p) const
|
||||
template <typename Scalar, typename Index>
|
||||
inline bool igl::WindingNumberAABB<Scalar,Index>::inside(const Point & p) const
|
||||
{
|
||||
assert(p.size() == max_corner.size());
|
||||
assert(p.size() == min_corner.size());
|
||||
@@ -259,8 +270,8 @@ inline bool igl::WindingNumberAABB<Point,DerivedV,DerivedF>::inside(const Point
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline void igl::WindingNumberAABB<Point,DerivedV,DerivedF>::compute_min_max_corners()
|
||||
template <typename Scalar, typename Index>
|
||||
inline void igl::WindingNumberAABB<Scalar,Index>::compute_min_max_corners()
|
||||
{
|
||||
using namespace std;
|
||||
// initialize corners
|
||||
@@ -272,26 +283,26 @@ inline void igl::WindingNumberAABB<Point,DerivedV,DerivedF>::compute_min_max_cor
|
||||
|
||||
this->center = Point(0,0,0);
|
||||
// Loop over facets
|
||||
for(int i = 0;i<this->getF().rows();i++)
|
||||
for(int i = 0;i<(this->F).rows();i++)
|
||||
{
|
||||
for(int j = 0;j<this->getF().cols();j++)
|
||||
for(int j = 0;j<(this->F).cols();j++)
|
||||
{
|
||||
for(int d = 0;d<min_corner.size();d++)
|
||||
{
|
||||
min_corner[d] =
|
||||
this->getV()(this->getF()(i,j),d) < min_corner[d] ?
|
||||
this->getV()(this->getF()(i,j),d) : min_corner[d];
|
||||
(*this->Vptr)((this->F)(i,j),d) < min_corner[d] ?
|
||||
(*this->Vptr)((this->F)(i,j),d) : min_corner[d];
|
||||
max_corner[d] =
|
||||
this->getV()(this->getF()(i,j),d) > max_corner[d] ?
|
||||
this->getV()(this->getF()(i,j),d) : max_corner[d];
|
||||
(*this->Vptr)((this->F)(i,j),d) > max_corner[d] ?
|
||||
(*this->Vptr)((this->F)(i,j),d) : max_corner[d];
|
||||
}
|
||||
// This is biased toward vertices incident on more than one face, but
|
||||
// perhaps that's good
|
||||
this->center += this->getV().row(this->getF()(i,j));
|
||||
this->center += (*this->Vptr).row((this->F)(i,j));
|
||||
}
|
||||
}
|
||||
// Average
|
||||
this->center.array() /= this->getF().size();
|
||||
this->center.array() /= (this->F).size();
|
||||
|
||||
//cout<<"min_corner: "<<this->min_corner.transpose()<<endl;
|
||||
//cout<<"Center: "<<this->center.transpose()<<endl;
|
||||
@@ -302,24 +313,24 @@ inline void igl::WindingNumberAABB<Point,DerivedV,DerivedF>::compute_min_max_cor
|
||||
this->radius = (max_corner-min_corner).norm()/2.0;
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline typename DerivedV::Scalar
|
||||
igl::WindingNumberAABB<Point,DerivedV,DerivedF>::max_abs_winding_number(const Point & p) const
|
||||
template <typename Scalar, typename Index>
|
||||
inline Scalar
|
||||
igl::WindingNumberAABB<Scalar,Index>::max_abs_winding_number(const Point & p) const
|
||||
{
|
||||
using namespace std;
|
||||
// Only valid if not inside
|
||||
if(inside(p))
|
||||
{
|
||||
return numeric_limits<typename DerivedV::Scalar>::infinity();
|
||||
return numeric_limits<Scalar>::infinity();
|
||||
}
|
||||
// Q: we know the total positive area so what's the most this could project
|
||||
// to? Remember it could be layered in the same direction.
|
||||
return numeric_limits<typename DerivedV::Scalar>::infinity();
|
||||
return numeric_limits<Scalar>::infinity();
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline typename DerivedV::Scalar
|
||||
igl::WindingNumberAABB<Point,DerivedV,DerivedF>::max_simple_abs_winding_number(
|
||||
template <typename Scalar, typename Index>
|
||||
inline Scalar
|
||||
igl::WindingNumberAABB<Scalar,Index>::max_simple_abs_winding_number(
|
||||
const Point & p) const
|
||||
{
|
||||
using namespace std;
|
||||
@@ -327,7 +338,7 @@ inline typename DerivedV::Scalar
|
||||
// Only valid if not inside
|
||||
if(inside(p))
|
||||
{
|
||||
return numeric_limits<typename DerivedV::Scalar>::infinity();
|
||||
return numeric_limits<Scalar>::infinity();
|
||||
}
|
||||
// Max simple is the same as sum of positive winding number contributions of
|
||||
// bounding box
|
||||
@@ -335,10 +346,10 @@ inline typename DerivedV::Scalar
|
||||
// begin precomputation
|
||||
//MatrixXd BV((int)pow(2,3),3);
|
||||
typedef
|
||||
Eigen::Matrix<typename DerivedV::Scalar,Eigen::Dynamic,Eigen::Dynamic>
|
||||
Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>
|
||||
MatrixXS;
|
||||
typedef
|
||||
Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,Eigen::Dynamic>
|
||||
Eigen::Matrix<Index,Eigen::Dynamic,Eigen::Dynamic>
|
||||
MatrixXF;
|
||||
MatrixXS BV((int)(1<<3),3);
|
||||
BV <<
|
||||
@@ -383,16 +394,4 @@ inline typename DerivedV::Scalar
|
||||
return igl::winding_number(BV,PBF,p);
|
||||
}
|
||||
|
||||
// This is a bullshit template because AABB annoyingly needs templates for bad
|
||||
// combinations of 3D V with DIM=2 AABB
|
||||
//
|
||||
// _Define_ as a no-op rather than monkeying around with the proper code above
|
||||
namespace igl
|
||||
{
|
||||
template <> inline igl::WindingNumberAABB<Eigen::Matrix<double, 1, 3, 1, 1, 3>,Eigen::Matrix<double, -1, 2, 0, -1, 2>,Eigen::Matrix<int, -1, 2, 0, -1, 2>>::WindingNumberAABB(const Eigen::MatrixBase<Eigen::Matrix<double, -1, 2, 0, -1, 2>> & V, const Eigen::MatrixBase<Eigen::Matrix<int, -1, 2, 0, -1, 2>> & F){};
|
||||
template <> inline void igl::WindingNumberAABB<Eigen::Matrix<double, 1, 3, 1, 1, 3>,Eigen::Matrix<double, -1, 2, 0, -1, 2>,Eigen::Matrix<int, -1, 2, 0, -1, 2>>::grow(){};
|
||||
template <> inline void igl::WindingNumberAABB<Eigen::Matrix<double, 1, 3, 1, 1, 3>,Eigen::Matrix<double, -1, 2, 0, -1, 2>,Eigen::Matrix<int, -1, 2, 0, -1, 2>>::init(){};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
+101
-128
@@ -11,73 +11,67 @@
|
||||
#include <map>
|
||||
#include <Eigen/Dense>
|
||||
#include "WindingNumberMethod.h"
|
||||
#include <memory>
|
||||
|
||||
namespace igl
|
||||
{
|
||||
/// Space partitioning tree for computing winding number hierarchically.
|
||||
///
|
||||
/// @tparam Point type for points in space, e.g. Eigen::Vector3d
|
||||
template <
|
||||
typename Point,
|
||||
typename DerivedV,
|
||||
typename DerivedF >
|
||||
typename Scalar,
|
||||
typename Index>
|
||||
class WindingNumberTree
|
||||
{
|
||||
public:
|
||||
using Point = Eigen::Matrix<Scalar,1,3>;
|
||||
// Method to use (see enum above)
|
||||
//static double min_max_w;
|
||||
static std::map<
|
||||
std::pair<const WindingNumberTree*,const WindingNumberTree*>,
|
||||
typename DerivedV::Scalar>
|
||||
Scalar>
|
||||
cached;
|
||||
// This is only need to fill in references, it should never actually be touched
|
||||
// and shouldn't cause race conditions. (This is a hack, but I think it's "safe")
|
||||
static DerivedV dummyV;
|
||||
protected:
|
||||
WindingNumberMethod method;
|
||||
const WindingNumberTree * parent;
|
||||
std::list<WindingNumberTree * > children;
|
||||
typedef
|
||||
Eigen::Matrix<typename DerivedV::Scalar,Eigen::Dynamic,Eigen::Dynamic>
|
||||
Eigen::Matrix<Scalar,Eigen::Dynamic,Eigen::Dynamic>
|
||||
MatrixXS;
|
||||
typedef
|
||||
Eigen::Matrix<typename DerivedF::Scalar,Eigen::Dynamic,Eigen::Dynamic>
|
||||
Eigen::Matrix<Index,Eigen::Dynamic,Eigen::Dynamic>
|
||||
MatrixXF;
|
||||
//// List of boundary edges (recall edges are vertices in 2d)
|
||||
//const Eigen::MatrixXi boundary;
|
||||
// Base mesh vertices
|
||||
DerivedV & V;
|
||||
// Base mesh vertices with duplicates removed
|
||||
// Base mesh vertices with duplicates removed (root will fill this in and
|
||||
// then everyone's Vptr will point to it.
|
||||
MatrixXS SV;
|
||||
// Shared pointer to base mesh vertices
|
||||
std::shared_ptr<MatrixXS> Vptr;
|
||||
// Facets in this bounding volume
|
||||
MatrixXF F;
|
||||
// Tessellated boundary curve
|
||||
MatrixXF cap;
|
||||
// Upper Bound on radius of enclosing ball
|
||||
typename DerivedV::Scalar radius;
|
||||
Scalar radius;
|
||||
// (Approximate) center (of mass)
|
||||
Point center;
|
||||
public:
|
||||
inline WindingNumberTree();
|
||||
// For root
|
||||
template <typename DerivedV, typename DerivedF>
|
||||
inline WindingNumberTree(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F);
|
||||
// For chilluns
|
||||
inline WindingNumberTree(
|
||||
const WindingNumberTree<Point,DerivedV,DerivedF> & parent,
|
||||
const Eigen::MatrixBase<DerivedF> & F);
|
||||
const WindingNumberTree<Scalar,Index> & parent,
|
||||
const typename igl::WindingNumberTree<Scalar,Index>::MatrixXF & F);
|
||||
inline virtual ~WindingNumberTree();
|
||||
inline void delete_children();
|
||||
inline virtual void set_mesh(
|
||||
template <typename DerivedV, typename DerivedF>
|
||||
inline void set_mesh(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F);
|
||||
// Set method
|
||||
inline void set_method( const WindingNumberMethod & m);
|
||||
public:
|
||||
inline const DerivedV & getV() const;
|
||||
inline const MatrixXF & getF() const;
|
||||
inline const MatrixXF & getcap() const;
|
||||
// Grow the Tree recursively
|
||||
inline virtual void grow();
|
||||
// Determine whether a given point is inside the bounding
|
||||
@@ -92,12 +86,12 @@ namespace igl
|
||||
// Inputs:
|
||||
// p query point
|
||||
// Returns winding number
|
||||
inline typename DerivedV::Scalar winding_number(const Point & p) const;
|
||||
inline Scalar winding_number(const Point & p) const;
|
||||
// Same as above, but always computes winding number using exact method
|
||||
// (sum over every facet)
|
||||
inline typename DerivedV::Scalar winding_number_all(const Point & p) const;
|
||||
inline Scalar winding_number_all(const Point & p) const;
|
||||
// Same as above, but always computes using sum over tessllated boundary
|
||||
inline typename DerivedV::Scalar winding_number_boundary(const Point & p) const;
|
||||
inline Scalar winding_number_boundary(const Point & p) const;
|
||||
//// Same as winding_number above, but if max_simple_abs_winding_number is
|
||||
//// less than some threshold min_max_w just return 0 (colloquially the "fast
|
||||
//// multipole method)
|
||||
@@ -120,10 +114,10 @@ namespace igl
|
||||
// Inputs:
|
||||
// p query point
|
||||
// Returns max winding number of
|
||||
inline virtual typename DerivedV::Scalar max_abs_winding_number(const Point & p) const;
|
||||
inline virtual Scalar max_abs_winding_number(const Point & p) const;
|
||||
// Same as above, but stronger assumptions on (V,F). Assumes (V,F) is a
|
||||
// simple polyhedron
|
||||
inline virtual typename DerivedV::Scalar max_simple_abs_winding_number(const Point & p) const;
|
||||
inline virtual Scalar max_simple_abs_winding_number(const Point & p) const;
|
||||
// Compute or read cached winding number for point p with respect to mesh
|
||||
// in bounding box, recursing according to approximation criteria
|
||||
//
|
||||
@@ -131,7 +125,7 @@ namespace igl
|
||||
// p query point
|
||||
// that WindingNumberTree containing mesh w.r.t. which we're computing w.n.
|
||||
// Returns cached winding number
|
||||
inline virtual typename DerivedV::Scalar cached_winding_number(const WindingNumberTree & that, const Point & p) const;
|
||||
inline virtual Scalar cached_winding_number(const WindingNumberTree & that, const Point & p) const;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -148,45 +142,45 @@ namespace igl
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
//template <typename Point, typename DerivedV, typename DerivedF>
|
||||
//WindingNumberMethod WindingNumberTree<Point,DerivedV,DerivedF>::method = EXACT_WINDING_NUMBER_METHOD;
|
||||
//template <typename Point, typename DerivedV, typename DerivedF>
|
||||
//double WindingNumberTree<Point,DerivedV,DerivedF>::min_max_w = 0;
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
std::map< std::pair<const igl::WindingNumberTree<Point,DerivedV,DerivedF>*,const igl::WindingNumberTree<Point,DerivedV,DerivedF>*>, typename DerivedV::Scalar>
|
||||
igl::WindingNumberTree<Point,DerivedV,DerivedF>::cached;
|
||||
//template <typename Scalar, typename Index>
|
||||
//WindingNumberMethod WindingNumberTree<Scalar,Index>::method = EXACT_WINDING_NUMBER_METHOD;
|
||||
//template <typename Scalar, typename Index>
|
||||
//double WindingNumberTree<Scalar,Index>::min_max_w = 0;
|
||||
template <typename Scalar, typename Index>
|
||||
std::map< std::pair<const igl::WindingNumberTree<Scalar,Index>*,const igl::WindingNumberTree<Scalar,Index>*>, Scalar>
|
||||
igl::WindingNumberTree<Scalar,Index>::cached;
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline igl::WindingNumberTree<Point,DerivedV,DerivedF>::WindingNumberTree():
|
||||
template <typename Scalar, typename Index>
|
||||
inline igl::WindingNumberTree<Scalar,Index>::WindingNumberTree():
|
||||
method(EXACT_WINDING_NUMBER_METHOD),
|
||||
parent(NULL),
|
||||
V(dummyV),
|
||||
SV(),
|
||||
F(),
|
||||
cap(),
|
||||
radius(std::numeric_limits<typename DerivedV::Scalar>::infinity()),
|
||||
radius(std::numeric_limits<Scalar>::infinity()),
|
||||
center(0,0,0)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline igl::WindingNumberTree<Point,DerivedV,DerivedF>::WindingNumberTree(
|
||||
template <typename Scalar, typename Index>
|
||||
template <typename DerivedV, typename DerivedF>
|
||||
inline igl::WindingNumberTree<Scalar,Index>::WindingNumberTree(
|
||||
const Eigen::MatrixBase<DerivedV> & _V,
|
||||
const Eigen::MatrixBase<DerivedF> & _F):
|
||||
method(EXACT_WINDING_NUMBER_METHOD),
|
||||
parent(NULL),
|
||||
V(dummyV),
|
||||
SV(),
|
||||
F(),
|
||||
cap(),
|
||||
radius(std::numeric_limits<typename DerivedV::Scalar>::infinity()),
|
||||
radius(std::numeric_limits<Scalar>::infinity()),
|
||||
center(0,0,0)
|
||||
{
|
||||
set_mesh(_V,_F);
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline void igl::WindingNumberTree<Point,DerivedV,DerivedF>::set_mesh(
|
||||
template <typename Scalar, typename Index>
|
||||
template <typename DerivedV, typename DerivedF>
|
||||
inline void igl::WindingNumberTree<Scalar,Index>::set_mesh(
|
||||
const Eigen::MatrixBase<DerivedV> & _V,
|
||||
const Eigen::MatrixBase<DerivedF> & _F)
|
||||
{
|
||||
@@ -194,37 +188,45 @@ inline void igl::WindingNumberTree<Point,DerivedV,DerivedF>::set_mesh(
|
||||
// Remove any exactly duplicate vertices
|
||||
// Q: Can this ever increase the complexity of the boundary?
|
||||
// Q: Would we gain even more by remove almost exactly duplicate vertices?
|
||||
MatrixXF SF,SVI,SVJ;
|
||||
Eigen::Matrix<typename MatrixXF::Scalar,Eigen::Dynamic,1> SVI,SVJ;
|
||||
igl::remove_duplicate_vertices(_V,_F,0.0,SV,SVI,SVJ,F);
|
||||
triangle_fan(igl::exterior_edges(F),cap);
|
||||
V = SV;
|
||||
{
|
||||
Eigen::Matrix<typename MatrixXF::Scalar,Eigen::Dynamic,2> EE;
|
||||
igl::exterior_edges(F,EE);
|
||||
triangle_fan(EE,cap);
|
||||
}
|
||||
// point Vptr to SV
|
||||
Vptr = std::make_shared<MatrixXS>(SV);
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline igl::WindingNumberTree<Point,DerivedV,DerivedF>::WindingNumberTree(
|
||||
const igl::WindingNumberTree<Point,DerivedV,DerivedF> & parent,
|
||||
const Eigen::MatrixBase<DerivedF> & _F):
|
||||
template <typename Scalar, typename Index>
|
||||
inline igl::WindingNumberTree<Scalar,Index>::WindingNumberTree(
|
||||
const igl::WindingNumberTree<Scalar,Index> & parent,
|
||||
const typename igl::WindingNumberTree<Scalar,Index>::MatrixXF & _F):
|
||||
method(parent.method),
|
||||
parent(&parent),
|
||||
V(parent.V),
|
||||
Vptr(parent.Vptr),
|
||||
SV(),
|
||||
F(_F),
|
||||
cap(triangle_fan(igl::exterior_edges(_F)))
|
||||
cap()
|
||||
{
|
||||
Eigen::Matrix<typename MatrixXF::Scalar,Eigen::Dynamic,2> EE;
|
||||
igl::exterior_edges(F,EE);
|
||||
triangle_fan(EE,cap);
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline igl::WindingNumberTree<Point,DerivedV,DerivedF>::~WindingNumberTree()
|
||||
template <typename Scalar, typename Index>
|
||||
inline igl::WindingNumberTree<Scalar,Index>::~WindingNumberTree()
|
||||
{
|
||||
delete_children();
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline void igl::WindingNumberTree<Point,DerivedV,DerivedF>::delete_children()
|
||||
template <typename Scalar, typename Index>
|
||||
inline void igl::WindingNumberTree<Scalar,Index>::delete_children()
|
||||
{
|
||||
using namespace std;
|
||||
// Delete children
|
||||
typename list<WindingNumberTree<Point,DerivedV,DerivedF>* >::iterator cit = children.begin();
|
||||
typename list<WindingNumberTree<Scalar,Index>* >::iterator cit = children.begin();
|
||||
while(cit != children.end())
|
||||
{
|
||||
// clear the memory of this item
|
||||
@@ -234,8 +236,8 @@ inline void igl::WindingNumberTree<Point,DerivedV,DerivedF>::delete_children()
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline void igl::WindingNumberTree<Point,DerivedV,DerivedF>::set_method(const WindingNumberMethod & m)
|
||||
template <typename Scalar, typename Index>
|
||||
inline void igl::WindingNumberTree<Scalar,Index>::set_method(const WindingNumberMethod & m)
|
||||
{
|
||||
this->method = m;
|
||||
for(auto child : children)
|
||||
@@ -244,42 +246,22 @@ inline void igl::WindingNumberTree<Point,DerivedV,DerivedF>::set_method(const Wi
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline const DerivedV & igl::WindingNumberTree<Point,DerivedV,DerivedF>::getV() const
|
||||
{
|
||||
return V;
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline const typename igl::WindingNumberTree<Point,DerivedV,DerivedF>::MatrixXF&
|
||||
igl::WindingNumberTree<Point,DerivedV,DerivedF>::getF() const
|
||||
{
|
||||
return F;
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline const typename igl::WindingNumberTree<Point,DerivedV,DerivedF>::MatrixXF&
|
||||
igl::WindingNumberTree<Point,DerivedV,DerivedF>::getcap() const
|
||||
{
|
||||
return cap;
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline void igl::WindingNumberTree<Point,DerivedV,DerivedF>::grow()
|
||||
template <typename Scalar, typename Index>
|
||||
inline void igl::WindingNumberTree<Scalar,Index>::grow()
|
||||
{
|
||||
// Don't grow
|
||||
return;
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline bool igl::WindingNumberTree<Point,DerivedV,DerivedF>::inside(const Point & /*p*/) const
|
||||
template <typename Scalar, typename Index>
|
||||
inline bool igl::WindingNumberTree<Scalar,Index>::inside(const Point & /*p*/) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline typename DerivedV::Scalar
|
||||
igl::WindingNumberTree<Point,DerivedV,DerivedF>::winding_number(const Point & p) const
|
||||
template <typename Scalar, typename Index>
|
||||
inline Scalar
|
||||
igl::WindingNumberTree<Scalar,Index>::winding_number(const Point & p) const
|
||||
{
|
||||
using namespace std;
|
||||
//cout<<"+"<<boundary.rows();
|
||||
@@ -290,9 +272,9 @@ igl::WindingNumberTree<Point,DerivedV,DerivedF>::winding_number(const Point & p)
|
||||
if(children.size()>0)
|
||||
{
|
||||
// Recurse on each child and accumulate
|
||||
typename DerivedV::Scalar sum = 0;
|
||||
Scalar sum = 0;
|
||||
for(
|
||||
typename list<WindingNumberTree<Point,DerivedV,DerivedF>* >::const_iterator cit = children.begin();
|
||||
typename list<WindingNumberTree<Scalar,Index>* >::const_iterator cit = children.begin();
|
||||
cit != children.end();
|
||||
cit++)
|
||||
{
|
||||
@@ -330,7 +312,7 @@ igl::WindingNumberTree<Point,DerivedV,DerivedF>::winding_number(const Point & p)
|
||||
return winding_number_boundary(p);
|
||||
case APPROX_SIMPLE_WINDING_NUMBER_METHOD:
|
||||
{
|
||||
typename DerivedV::Scalar dist = (p-center).norm();
|
||||
Scalar dist = (p-center).norm();
|
||||
// Radius is already an overestimate of inside
|
||||
if(dist>1.0*radius)
|
||||
{
|
||||
@@ -355,24 +337,22 @@ igl::WindingNumberTree<Point,DerivedV,DerivedF>::winding_number(const Point & p)
|
||||
return 0;
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline typename DerivedV::Scalar
|
||||
igl::WindingNumberTree<Point,DerivedV,DerivedF>::winding_number_all(const Point & p) const
|
||||
template <typename Scalar, typename Index>
|
||||
inline Scalar
|
||||
igl::WindingNumberTree<Scalar,Index>::winding_number_all(const Point & p) const
|
||||
{
|
||||
return igl::winding_number(V,F,p);
|
||||
return igl::winding_number(*Vptr,F,p);
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline typename DerivedV::Scalar
|
||||
igl::WindingNumberTree<Point,DerivedV,DerivedF>::winding_number_boundary(const Point & p) const
|
||||
template <typename Scalar, typename Index>
|
||||
inline Scalar
|
||||
igl::WindingNumberTree<Scalar,Index>::winding_number_boundary(const Point & p) const
|
||||
{
|
||||
using namespace Eigen;
|
||||
using namespace std;
|
||||
return igl::winding_number(V,cap,p);
|
||||
return igl::winding_number(*Vptr,cap,p);
|
||||
}
|
||||
|
||||
//template <typename Point, typename DerivedV, typename DerivedF>
|
||||
//inline double igl::WindingNumberTree<Point,DerivedV,DerivedF>::winding_number_approx_simple(
|
||||
//template <typename Scalar, typename Index>
|
||||
//inline double igl::WindingNumberTree<Scalar,Index>::winding_number_approx_simple(
|
||||
// const Point & p,
|
||||
// const double min_max_w)
|
||||
//{
|
||||
@@ -387,15 +367,15 @@ igl::WindingNumberTree<Point,DerivedV,DerivedF>::winding_number_boundary(const P
|
||||
// }
|
||||
//}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline void igl::WindingNumberTree<Point,DerivedV,DerivedF>::print(const char * tab)
|
||||
template <typename Scalar, typename Index>
|
||||
inline void igl::WindingNumberTree<Scalar,Index>::print(const char * tab)
|
||||
{
|
||||
using namespace std;
|
||||
// Print all facets
|
||||
cout<<tab<<"["<<endl<<F<<endl<<"]";
|
||||
// Print children
|
||||
for(
|
||||
typename list<WindingNumberTree<Point,DerivedV,DerivedF>* >::iterator cit = children.begin();
|
||||
typename list<WindingNumberTree<Scalar,Index>* >::iterator cit = children.begin();
|
||||
cit != children.end();
|
||||
cit++)
|
||||
{
|
||||
@@ -404,26 +384,26 @@ inline void igl::WindingNumberTree<Point,DerivedV,DerivedF>::print(const char *
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline typename DerivedV::Scalar
|
||||
igl::WindingNumberTree<Point,DerivedV,DerivedF>::max_abs_winding_number(const Point & /*p*/) const
|
||||
template <typename Scalar, typename Index>
|
||||
inline Scalar
|
||||
igl::WindingNumberTree<Scalar,Index>::max_abs_winding_number(const Point & /*p*/) const
|
||||
{
|
||||
return std::numeric_limits<typename DerivedV::Scalar>::infinity();
|
||||
return std::numeric_limits<Scalar>::infinity();
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline typename DerivedV::Scalar
|
||||
igl::WindingNumberTree<Point,DerivedV,DerivedF>::max_simple_abs_winding_number(
|
||||
template <typename Scalar, typename Index>
|
||||
inline Scalar
|
||||
igl::WindingNumberTree<Scalar,Index>::max_simple_abs_winding_number(
|
||||
const Point & /*p*/) const
|
||||
{
|
||||
using namespace std;
|
||||
return numeric_limits<typename DerivedV::Scalar>::infinity();
|
||||
return numeric_limits<Scalar>::infinity();
|
||||
}
|
||||
|
||||
template <typename Point, typename DerivedV, typename DerivedF>
|
||||
inline typename DerivedV::Scalar
|
||||
igl::WindingNumberTree<Point,DerivedV,DerivedF>::cached_winding_number(
|
||||
const igl::WindingNumberTree<Point,DerivedV,DerivedF> & that,
|
||||
template <typename Scalar, typename Index>
|
||||
inline Scalar
|
||||
igl::WindingNumberTree<Scalar,Index>::cached_winding_number(
|
||||
const igl::WindingNumberTree<Scalar,Index> & that,
|
||||
const Point & p) const
|
||||
{
|
||||
using namespace std;
|
||||
@@ -447,7 +427,7 @@ igl::WindingNumberTree<Point,DerivedV,DerivedF>::cached_winding_number(
|
||||
bool is_far = this->radius<that.radius;
|
||||
if(is_far)
|
||||
{
|
||||
typename DerivedV::Scalar a = atan2(
|
||||
Scalar a = atan2(
|
||||
that.radius - this->radius,
|
||||
(that.center - this->center).norm());
|
||||
assert(a>0);
|
||||
@@ -472,7 +452,7 @@ igl::WindingNumberTree<Point,DerivedV,DerivedF>::cached_winding_number(
|
||||
}else
|
||||
{
|
||||
for(
|
||||
typename list<WindingNumberTree<Point,DerivedV,DerivedF>* >::const_iterator cit = children.begin();
|
||||
typename list<WindingNumberTree<Scalar,Index>* >::const_iterator cit = children.begin();
|
||||
cit != children.end();
|
||||
cit++)
|
||||
{
|
||||
@@ -490,11 +470,4 @@ igl::WindingNumberTree<Point,DerivedV,DerivedF>::cached_winding_number(
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Explicit instantiation of static variable
|
||||
template <
|
||||
typename Point,
|
||||
typename DerivedV,
|
||||
typename DerivedF >
|
||||
DerivedV igl::WindingNumberTree<Point,DerivedV,DerivedF>::dummyV;
|
||||
|
||||
#endif
|
||||
|
||||
+45
-27
@@ -11,6 +11,8 @@
|
||||
#include "slice_into.h"
|
||||
#include "cat.h"
|
||||
//#include "matlab_format.h"
|
||||
#include "placeholders.h"
|
||||
#include "PlainMatrix.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
@@ -31,19 +33,20 @@ template <
|
||||
>
|
||||
IGL_INLINE igl::SolverStatus igl::active_set(
|
||||
const Eigen::SparseMatrix<AT>& A,
|
||||
const Eigen::PlainObjectBase<DerivedB> & B,
|
||||
const Eigen::PlainObjectBase<Derivedknown> & known,
|
||||
const Eigen::PlainObjectBase<DerivedY> & Y,
|
||||
const Eigen::MatrixBase<DerivedB> & B,
|
||||
const Eigen::MatrixBase<Derivedknown> & known,
|
||||
const Eigen::MatrixBase<DerivedY> & Y,
|
||||
const Eigen::SparseMatrix<AeqT>& Aeq,
|
||||
const Eigen::PlainObjectBase<DerivedBeq> & Beq,
|
||||
const Eigen::MatrixBase<DerivedBeq> & Beq,
|
||||
const Eigen::SparseMatrix<AieqT>& Aieq,
|
||||
const Eigen::PlainObjectBase<DerivedBieq> & Bieq,
|
||||
const Eigen::PlainObjectBase<Derivedlx> & p_lx,
|
||||
const Eigen::PlainObjectBase<Derivedux> & p_ux,
|
||||
const Eigen::MatrixBase<DerivedBieq> & Bieq,
|
||||
const Eigen::MatrixBase<Derivedlx> & p_lx,
|
||||
const Eigen::MatrixBase<Derivedux> & p_ux,
|
||||
const igl::active_set_params & params,
|
||||
Eigen::PlainObjectBase<DerivedZ> & Z
|
||||
)
|
||||
{
|
||||
|
||||
//#define ACTIVE_SET_CPP_DEBUG
|
||||
#if defined(ACTIVE_SET_CPP_DEBUG) && !defined(_MSC_VER)
|
||||
# warning "ACTIVE_SET_CPP_DEBUG"
|
||||
@@ -109,9 +112,7 @@ IGL_INLINE igl::SolverStatus igl::active_set(
|
||||
Matrix<BOOL,Dynamic,1> as_ieq = Matrix<BOOL,Dynamic,1>::Constant(Aieq.rows(),1,FALSE);
|
||||
|
||||
// Keep track of previous Z for comparison
|
||||
DerivedZ old_Z;
|
||||
old_Z = DerivedZ::Constant(
|
||||
n,1,numeric_limits<typename DerivedZ::Scalar>::max());
|
||||
PlainMatrix<DerivedZ> old_Z;
|
||||
|
||||
int iter = 0;
|
||||
while(true)
|
||||
@@ -121,35 +122,43 @@ IGL_INLINE igl::SolverStatus igl::active_set(
|
||||
cout<<" pre"<<endl;
|
||||
#endif
|
||||
// FIND BREACHES OF CONSTRAINTS
|
||||
#ifdef ACTIVE_SET_CPP_DEBUG
|
||||
int new_as_lx = 0;
|
||||
int new_as_ux = 0;
|
||||
int new_as_ieq = 0;
|
||||
#endif
|
||||
if(Z.size() > 0)
|
||||
{
|
||||
for(int z = 0;z < n;z++)
|
||||
{
|
||||
if(Z(z) < lx(z))
|
||||
{
|
||||
#ifdef ACTIVE_SET_CPP_DEBUG
|
||||
new_as_lx += (as_lx(z)?0:1);
|
||||
#endif
|
||||
//new_as_lx++;
|
||||
as_lx(z) = TRUE;
|
||||
}
|
||||
if(Z(z) > ux(z))
|
||||
{
|
||||
#ifdef ACTIVE_SET_CPP_DEBUG
|
||||
new_as_ux += (as_ux(z)?0:1);
|
||||
#endif
|
||||
//new_as_ux++;
|
||||
as_ux(z) = TRUE;
|
||||
}
|
||||
}
|
||||
if(Aieq.rows() > 0)
|
||||
{
|
||||
DerivedZ AieqZ;
|
||||
PlainMatrix<DerivedZ,Eigen::Dynamic> AieqZ;
|
||||
AieqZ = Aieq*Z;
|
||||
for(int a = 0;a<Aieq.rows();a++)
|
||||
{
|
||||
if(AieqZ(a) > Bieq(a))
|
||||
{
|
||||
#ifdef ACTIVE_SET_CPP_DEBUG
|
||||
new_as_ieq += (as_ieq(a)?0:1);
|
||||
#endif
|
||||
as_ieq(a) = TRUE;
|
||||
}
|
||||
}
|
||||
@@ -158,14 +167,17 @@ IGL_INLINE igl::SolverStatus igl::active_set(
|
||||
cout<<" new_as_lx: "<<new_as_lx<<endl;
|
||||
cout<<" new_as_ux: "<<new_as_ux<<endl;
|
||||
#endif
|
||||
const double diff = (Z-old_Z).squaredNorm();
|
||||
#ifdef ACTIVE_SET_CPP_DEBUG
|
||||
cout<<"diff: "<<diff<<endl;
|
||||
#endif
|
||||
if(diff < params.solution_diff_threshold)
|
||||
if(iter > 0)
|
||||
{
|
||||
ret = SOLVER_STATUS_CONVERGED;
|
||||
break;
|
||||
const double diff = (Z-old_Z).squaredNorm();
|
||||
#ifdef ACTIVE_SET_CPP_DEBUG
|
||||
cout<<"diff: "<<diff<<endl;
|
||||
#endif
|
||||
if(diff < params.solution_diff_threshold)
|
||||
{
|
||||
ret = SOLVER_STATUS_CONVERGED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
old_Z = Z;
|
||||
}
|
||||
@@ -190,9 +202,9 @@ IGL_INLINE igl::SolverStatus igl::active_set(
|
||||
#endif
|
||||
|
||||
// PREPARE FIXED VALUES
|
||||
Derivedknown known_i;
|
||||
Eigen::Matrix<typename Derivedknown::Scalar,Eigen::Dynamic,1> known_i;
|
||||
known_i.resize(nk + as_lx_count + as_ux_count,1);
|
||||
DerivedY Y_i;
|
||||
PlainMatrix<DerivedY,Eigen::Dynamic,1> Y_i;
|
||||
Y_i.resize(nk + as_lx_count + as_ux_count,1);
|
||||
{
|
||||
known_i.block(0,0,known.rows(),known.cols()) = known;
|
||||
@@ -225,7 +237,7 @@ IGL_INLINE igl::SolverStatus igl::active_set(
|
||||
// PREPARE EQUALITY CONSTRAINTS
|
||||
Eigen::Matrix<typename DerivedY::Scalar, Eigen::Dynamic, 1> as_ieq_list(as_ieq_count,1);
|
||||
// Gather active constraints and resp. rhss
|
||||
DerivedBeq Beq_i;
|
||||
PlainMatrix<DerivedBeq,Eigen::Dynamic,1> Beq_i;
|
||||
Beq_i.resize(Beq.rows()+as_ieq_count,1);
|
||||
Beq_i.head(Beq.rows()) = Beq;
|
||||
{
|
||||
@@ -262,7 +274,7 @@ IGL_INLINE igl::SolverStatus igl::active_set(
|
||||
}
|
||||
#endif
|
||||
|
||||
DerivedZ sol;
|
||||
PlainMatrix<DerivedZ,Eigen::Dynamic,Eigen::Dynamic> sol;
|
||||
if(known_i.size() == A.rows())
|
||||
{
|
||||
// Everything's fixed?
|
||||
@@ -270,7 +282,7 @@ IGL_INLINE igl::SolverStatus igl::active_set(
|
||||
cout<<" everything's fixed."<<endl;
|
||||
#endif
|
||||
Z.resize(A.rows(),Y_i.cols());
|
||||
slice_into(Y_i,known_i,1,Z);
|
||||
Z(known_i,igl::placeholders::all) = Y_i;
|
||||
sol.resize(0,Y_i.cols());
|
||||
assert(Aeq_i.rows() == 0 && "All fixed but linearly constrained");
|
||||
}else
|
||||
@@ -280,11 +292,15 @@ IGL_INLINE igl::SolverStatus igl::active_set(
|
||||
#endif
|
||||
if(!min_quad_with_fixed_precompute(A,known_i,Aeq_i,params.Auu_pd,data))
|
||||
{
|
||||
#ifdef ACTIVE_SET_CPP_DEBUG
|
||||
cerr<<"Error: min_quad_with_fixed precomputation failed."<<endl;
|
||||
#endif
|
||||
if(iter > 0 && Aeq_i.rows() > Aeq.rows())
|
||||
{
|
||||
#ifdef ACTIVE_SET_CPP_DEBUG
|
||||
cerr<<" *Are you sure rows of [Aeq;Aieq] are linearly independent?*"<<
|
||||
endl;
|
||||
#endif
|
||||
}
|
||||
ret = SOLVER_STATUS_ERROR;
|
||||
break;
|
||||
@@ -294,7 +310,9 @@ IGL_INLINE igl::SolverStatus igl::active_set(
|
||||
#endif
|
||||
if(!min_quad_with_fixed_solve(data,B,Y_i,Beq_i,Z,sol))
|
||||
{
|
||||
#ifdef ACTIVE_SET_CPP_DEBUG
|
||||
cerr<<"Error: min_quad_with_fixed solve failed."<<endl;
|
||||
#endif
|
||||
ret = SOLVER_STATUS_ERROR;
|
||||
break;
|
||||
}
|
||||
@@ -311,8 +329,8 @@ IGL_INLINE igl::SolverStatus igl::active_set(
|
||||
SparseMatrix<AT> Ak;
|
||||
// Slow
|
||||
slice(A,known_i,1,Ak);
|
||||
DerivedB Bk;
|
||||
slice(B,known_i,Bk);
|
||||
//slice(B,known_i,Bk);
|
||||
PlainMatrix<DerivedB,Eigen::Dynamic> Bk = B(known_i,igl::placeholders::all);
|
||||
MatrixXd Lambda_known_i = -(0.5*Ak*Z + 0.5*Bk);
|
||||
// reverse the lambda values for lx
|
||||
Lambda_known_i.block(nk,0,as_lx_count,1) =
|
||||
@@ -365,6 +383,6 @@ IGL_INLINE igl::SolverStatus igl::active_set(
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
template igl::SolverStatus igl::active_set<double, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, double, Eigen::Matrix<double, -1, 1, 0, -1, 1>, double, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::SparseMatrix<double, 0, int> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::SparseMatrix<double, 0, int> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, igl::active_set_params const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
|
||||
template igl::SolverStatus igl::active_set<double, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, -1, 1, 0, -1, 1>, double, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::SparseMatrix<double, 0, int> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, igl::active_set_params const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
template igl::SolverStatus igl::active_set<double, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, double, Eigen::Matrix<double, -1, 1, 0, -1, 1>, double, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::SparseMatrix<double, 0, int> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::SparseMatrix<double, 0, int> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, igl::active_set_params const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
|
||||
template igl::SolverStatus igl::active_set<double, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, double, Eigen::Matrix<double, -1, 1, 0, -1, 1>, double, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::SparseMatrix<double, 0, int> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::SparseMatrix<double, 0, int> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> > const&, Eigen::SparseMatrix<double, 0, int> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, igl::active_set_params const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
#endif
|
||||
|
||||
@@ -70,15 +70,15 @@ namespace igl
|
||||
>
|
||||
IGL_INLINE igl::SolverStatus active_set(
|
||||
const Eigen::SparseMatrix<AT>& A,
|
||||
const Eigen::PlainObjectBase<DerivedB> & B,
|
||||
const Eigen::PlainObjectBase<Derivedknown> & known,
|
||||
const Eigen::PlainObjectBase<DerivedY> & Y,
|
||||
const Eigen::MatrixBase<DerivedB> & B,
|
||||
const Eigen::MatrixBase<Derivedknown> & known,
|
||||
const Eigen::MatrixBase<DerivedY> & Y,
|
||||
const Eigen::SparseMatrix<AeqT>& Aeq,
|
||||
const Eigen::PlainObjectBase<DerivedBeq> & Beq,
|
||||
const Eigen::MatrixBase<DerivedBeq> & Beq,
|
||||
const Eigen::SparseMatrix<AieqT>& Aieq,
|
||||
const Eigen::PlainObjectBase<DerivedBieq> & Bieq,
|
||||
const Eigen::PlainObjectBase<Derivedlx> & lx,
|
||||
const Eigen::PlainObjectBase<Derivedux> & ux,
|
||||
const Eigen::MatrixBase<DerivedBieq> & Bieq,
|
||||
const Eigen::MatrixBase<Derivedlx> & lx,
|
||||
const Eigen::MatrixBase<Derivedux> & ux,
|
||||
const igl::active_set_params & params,
|
||||
Eigen::PlainObjectBase<DerivedZ> & Z
|
||||
);
|
||||
|
||||
@@ -70,6 +70,7 @@ IGL_INLINE void igl::adjacency_list(
|
||||
for(int v=0; v<(int)SR.size();++v)
|
||||
{
|
||||
std::vector<IndexVector>& vv = A.at(v);
|
||||
if(vv.size() == 0){ continue; }
|
||||
std::vector<std::vector<int> >& sr = SR[v];
|
||||
|
||||
std::vector<std::vector<int> > pn = sr;
|
||||
|
||||
@@ -19,7 +19,7 @@ namespace igl
|
||||
/// @tparam T should be a eigen sparse matrix primitive type like int or double
|
||||
/// @param[in] F #F by dim list of mesh faces (must be triangles)
|
||||
/// @param[out] A vector<vector<T> > containing at row i the adjacent vertices of vertex i
|
||||
/// @param[in] sorted flag that indicates if the list should be sorted counter-clockwise
|
||||
/// @param[in] sorted flag that indicates if the list should be sorted counter-clockwise. Input assumed to be manifold.
|
||||
///
|
||||
/// Example:
|
||||
/// \code{.cpp}
|
||||
|
||||
@@ -22,8 +22,8 @@ template <
|
||||
IGL_INLINE void igl::ambient_occlusion(
|
||||
const std::function<
|
||||
bool(
|
||||
const Eigen::Vector3f&,
|
||||
const Eigen::Vector3f&)
|
||||
const Eigen::Matrix<typename DerivedP::Scalar,3,1> &,
|
||||
const Eigen::Matrix<typename DerivedP::Scalar,3,1> &)
|
||||
> & shoot_ray,
|
||||
const Eigen::MatrixBase<DerivedP> & P,
|
||||
const Eigen::MatrixBase<DerivedN> & N,
|
||||
@@ -35,16 +35,19 @@ IGL_INLINE void igl::ambient_occlusion(
|
||||
// Resize output
|
||||
S.resize(n,1);
|
||||
// Embree seems to be parallel when constructing but not when tracing rays
|
||||
const MatrixXf D = random_dir_stratified(num_samples).cast<float>();
|
||||
typedef typename DerivedP::Scalar Scalar;
|
||||
typedef Eigen::Matrix<Scalar,3,1> Vector3N;
|
||||
|
||||
const Matrix<Scalar,Eigen::Dynamic,3> D = random_dir_stratified(num_samples).cast<Scalar>();
|
||||
|
||||
const auto & inner = [&P,&N,&num_samples,&D,&S,&shoot_ray](const int p)
|
||||
{
|
||||
const Vector3f origin = P.row(p).template cast<float>();
|
||||
const Vector3f normal = N.row(p).template cast<float>();
|
||||
const Vector3N origin = P.row(p);
|
||||
const Vector3N normal = N.row(p);
|
||||
int num_hits = 0;
|
||||
for(int s = 0;s<num_samples;s++)
|
||||
{
|
||||
Vector3f d = D.row(s);
|
||||
Vector3N d = D.row(s);
|
||||
if(d.dot(normal) < 0)
|
||||
{
|
||||
// reverse ray
|
||||
@@ -76,17 +79,19 @@ IGL_INLINE void igl::ambient_occlusion(
|
||||
const int num_samples,
|
||||
Eigen::PlainObjectBase<DerivedS> & S)
|
||||
{
|
||||
typedef typename DerivedV::Scalar Scalar;
|
||||
using Vector3S = Eigen::Matrix<Scalar,3,1>;
|
||||
const auto & shoot_ray = [&aabb,&V,&F](
|
||||
const Eigen::Vector3f& _s,
|
||||
const Eigen::Vector3f& dir)->bool
|
||||
const Eigen::Matrix<Scalar,3,1> & _s,
|
||||
const Eigen::Matrix<Scalar,3,1> & dir)->bool
|
||||
{
|
||||
Eigen::Vector3f s = _s+1e-4*dir;
|
||||
igl::Hit hit;
|
||||
Vector3S s = _s+1e-4*dir;
|
||||
igl::Hit<Scalar> hit;
|
||||
return aabb.intersect_ray(
|
||||
V,
|
||||
F,
|
||||
s .cast<typename DerivedV::Scalar>().eval(),
|
||||
dir.cast<typename DerivedV::Scalar>().eval(),
|
||||
s,
|
||||
dir,
|
||||
hit);
|
||||
};
|
||||
return ambient_occlusion(shoot_ray,P,N,num_samples,S);
|
||||
@@ -107,15 +112,17 @@ IGL_INLINE void igl::ambient_occlusion(
|
||||
const int num_samples,
|
||||
Eigen::PlainObjectBase<DerivedS> & S)
|
||||
{
|
||||
typedef typename DerivedV::Scalar Scalar;
|
||||
using Vector3S = Eigen::Matrix<Scalar,3,1>;
|
||||
if(F.rows() < 100)
|
||||
{
|
||||
// Super naive
|
||||
const auto & shoot_ray = [&V,&F](
|
||||
const Eigen::Vector3f& _s,
|
||||
const Eigen::Vector3f& dir)->bool
|
||||
const Eigen::Matrix<Scalar,3,1> & _s,
|
||||
const Eigen::Matrix<Scalar,3,1> & dir)->bool
|
||||
{
|
||||
Eigen::Vector3f s = _s+1e-4*dir;
|
||||
igl::Hit hit;
|
||||
Vector3S s = _s+1e-4*dir;
|
||||
igl::Hit<Scalar> hit;
|
||||
return ray_mesh_intersect(s,dir,V,F,hit);
|
||||
};
|
||||
return ambient_occlusion(shoot_ray,P,N,num_samples,S);
|
||||
@@ -127,13 +134,12 @@ IGL_INLINE void igl::ambient_occlusion(
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::ambient_occlusion<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::ambient_occlusion<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::function<bool (Eigen::Matrix<float, 3, 1, 0, 3, 1> const&, Eigen::Matrix<float, 3, 1, 0, 3, 1> const&)> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::ambient_occlusion<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::function<bool (Eigen::Matrix<float, 3, 1, 0, 3, 1> const&, Eigen::Matrix<float, 3, 1, 0, 3, 1> const&)> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::ambient_occlusion<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::function<bool (Eigen::Matrix<float, 3, 1, 0, 3, 1> const&, Eigen::Matrix<float, 3, 1, 0, 3, 1> const&)> const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
|
||||
template void igl::ambient_occlusion<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(std::function<bool (Eigen::Matrix<float, 3, 1, 0, 3, 1> const&, Eigen::Matrix<float, 3, 1, 0, 3, 1> const&)> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
template void igl::ambient_occlusion<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::function<bool (Eigen::Matrix<double, 3, 1, 0, 3, 1> const&, Eigen::Matrix<double, 3, 1, 0, 3, 1> const&)> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
|
||||
template void igl::ambient_occlusion<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::function<bool (Eigen::Matrix<double, 3, 1, 0, 3, 1> const&, Eigen::Matrix<double, 3, 1, 0, 3, 1> const&)> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
|
||||
template void igl::ambient_occlusion<Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(std::function<bool (Eigen::Matrix<double, 3, 1, 0, 3, 1> const&, Eigen::Matrix<double, 3, 1, 0, 3, 1> const&)> const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
|
||||
template void igl::ambient_occlusion<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(std::function<bool (Eigen::Matrix<double, 3, 1, 0, 3, 1> const&, Eigen::Matrix<double, 3, 1, 0, 3, 1> const&)> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
template void igl::ambient_occlusion<Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Matrix<float, 1, 3, 1, 1, 3>, Eigen::Matrix<float, -1, 1, 0, -1, 1>>(std::function<bool (Eigen::Matrix<Eigen::Matrix<float, 1, 3, 1, 1, 3>::Scalar, 3, 1, 0, 3, 1> const&, Eigen::Matrix<Eigen::Matrix<float, 1, 3, 1, 1, 3>::Scalar, 3, 1, 0, 3, 1> const&)> const&, Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3>> const&, Eigen::MatrixBase<Eigen::Matrix<float, 1, 3, 1, 1, 3>> const&, int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 1, 0, -1, 1>>&);
|
||||
template void igl::ambient_occlusion<Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<float, -1, 3, 0, -1, 3>, Eigen::Matrix<float, -1, 1, 0, -1, 1>>(std::function<bool (Eigen::Matrix<Eigen::Matrix<float, -1, 3, 0, -1, 3>::Scalar, 3, 1, 0, 3, 1> const&, Eigen::Matrix<Eigen::Matrix<float, -1, 3, 0, -1, 3>::Scalar, 3, 1, 0, 3, 1> const&)> const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3>> const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 0, -1, 3>> const&, int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 1, 0, -1, 1>>&);
|
||||
template void igl::ambient_occlusion<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, 1, 0, -1, 1>>(std::function<bool (Eigen::Matrix<Eigen::Matrix<float, -1, -1, 0, -1, -1>::Scalar, 3, 1, 0, 3, 1> const&, Eigen::Matrix<Eigen::Matrix<float, -1, -1, 0, -1, -1>::Scalar, 3, 1, 0, 3, 1> const&)> const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1>> const&, int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 1, 0, -1, 1>>&);
|
||||
#endif
|
||||
|
||||
@@ -31,8 +31,8 @@ namespace igl
|
||||
IGL_INLINE void ambient_occlusion(
|
||||
const std::function<
|
||||
bool(
|
||||
const Eigen::Vector3f&,
|
||||
const Eigen::Vector3f&)
|
||||
const Eigen::Matrix<typename DerivedP::Scalar,3,1>&,
|
||||
const Eigen::Matrix<typename DerivedP::Scalar,3,1>&)
|
||||
> & shoot_ray,
|
||||
const Eigen::MatrixBase<DerivedP> & P,
|
||||
const Eigen::MatrixBase<DerivedN> & N,
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
#include "speye.h"
|
||||
#include "mode.h"
|
||||
#include "project_isometrically_to_plane.h"
|
||||
#include "slice.h"
|
||||
#include "arap_rhs.h"
|
||||
#include "repdiag.h"
|
||||
#include "columnize.h"
|
||||
@@ -126,9 +125,7 @@ IGL_INLINE bool igl::arap_precomputation(
|
||||
MatrixXi GF(F.rows(),F.cols());
|
||||
for(int j = 0;j<F.cols();j++)
|
||||
{
|
||||
Matrix<int,Eigen::Dynamic,1> GFj;
|
||||
slice(data.G,F.col(j),GFj);
|
||||
GF.col(j) = GFj;
|
||||
GF.col(j) = data.G(F.col(j));
|
||||
}
|
||||
mode<int>(GF,2,GG);
|
||||
data.G=GG;
|
||||
|
||||
+43
-10
@@ -6,6 +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 "arap_dof.h"
|
||||
#include "IGL_ASSERT.h"
|
||||
|
||||
#include "cotmatrix.h"
|
||||
#include "massmatrix.h"
|
||||
@@ -29,10 +30,32 @@
|
||||
#include "kkt_inverse.h"
|
||||
#include "get_seconds.h"
|
||||
#include "columnize.h"
|
||||
#include <type_traits>
|
||||
|
||||
// defined if no early exit is supported, i.e., always take a fixed number of iterations
|
||||
#define IGL_ARAP_DOF_FIXED_ITERATIONS_COUNT
|
||||
|
||||
// To avoid putting _any_ dense slices in the static library use a work around
|
||||
// so that we can slice LbsMatrixType as sparse or dense below.
|
||||
#if __cplusplus < 201703L
|
||||
template <typename Mat, bool IsSparse> struct arap_dof_slice_helper;
|
||||
template <typename Mat> struct arap_dof_slice_helper<Mat,true>
|
||||
{
|
||||
static void slice(const Mat & A, const Eigen::VectorXi & I, const Eigen::VectorXi & J, Mat & B)
|
||||
{
|
||||
static_assert(std::is_base_of<Eigen::SparseMatrixBase<Mat>, Mat>::value, "Mat must be sparse");
|
||||
igl::slice(A,I,J,B);
|
||||
}
|
||||
};
|
||||
template <typename Mat> struct arap_dof_slice_helper<Mat,false>
|
||||
{
|
||||
static void slice(const Mat & A, const Eigen::VectorXi & I, const Eigen::VectorXi & J, Mat & B)
|
||||
{
|
||||
B = A(I,J);
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
// A careful derivation of this implementation is given in the corresponding
|
||||
// matlab function arap_dof.m
|
||||
template <typename LbsMatrixType, typename SSCALAR>
|
||||
@@ -98,9 +121,7 @@ IGL_INLINE bool igl::arap_dof_precomputation(
|
||||
MatrixXi GF(F.rows(),F.cols());
|
||||
for(int j = 0;j<F.cols();j++)
|
||||
{
|
||||
Matrix<int,Eigen::Dynamic,1> GFj;
|
||||
slice(G,F.col(j),GFj);
|
||||
GF.col(j) = GFj;
|
||||
GF.col(j) = G(F.col(j));
|
||||
}
|
||||
mode<int>(GF,2,GG);
|
||||
}else
|
||||
@@ -182,7 +203,20 @@ IGL_INLINE bool igl::arap_dof_precomputation(
|
||||
//printf("CSM_M(): Mi\n");
|
||||
LbsMatrixType M_i;
|
||||
//printf("CSM_M(): slice\n");
|
||||
slice(M,(span_n.array()+i*n).matrix().eval(),span_mlbs_cols,M_i);
|
||||
#if __cplusplus >= 201703L
|
||||
// Check if LbsMatrixType is a sparse matrix
|
||||
if constexpr (std::is_base_of<SparseMatrixBase<LbsMatrixType>, LbsMatrixType>::value)
|
||||
{
|
||||
slice(M,(span_n.array()+i*n).matrix().eval(),span_mlbs_cols,M_i);
|
||||
}
|
||||
else
|
||||
{
|
||||
M_i = M((span_n.array()+i*n).eval(),span_mlbs_cols);
|
||||
}
|
||||
#else
|
||||
constexpr bool LbsMatrixTypeIsSparse = std::is_base_of<SparseMatrixBase<LbsMatrixType>, LbsMatrixType>::value;
|
||||
arap_dof_slice_helper<LbsMatrixType,LbsMatrixTypeIsSparse>::slice(M,(span_n.array()+i*n).matrix().eval(),span_mlbs_cols,M_i);
|
||||
#endif
|
||||
LbsMatrixType M_i_dim;
|
||||
data.CSM_M[i].resize(k*data.dim,data.m*data.dim*(data.dim+1));
|
||||
assert(data.CSM_M[i].cols() == M.cols());
|
||||
@@ -619,10 +653,10 @@ IGL_INLINE bool igl::arap_dof_update(
|
||||
#endif
|
||||
|
||||
// number of dimensions
|
||||
assert((int)data.CSM_M.size() == data.dim);
|
||||
assert((int)L0.size() == (data.m)*data.dim*(data.dim+1));
|
||||
assert(max_iters >= 0);
|
||||
assert(tol >= 0);
|
||||
IGL_ASSERT((int)data.CSM_M.size() == data.dim);
|
||||
IGL_ASSERT((int)L0.size() == (data.m)*data.dim*(data.dim+1));
|
||||
IGL_ASSERT(max_iters >= 0);
|
||||
IGL_ASSERT(tol >= 0);
|
||||
|
||||
// timing variables
|
||||
double
|
||||
@@ -667,9 +701,8 @@ IGL_INLINE bool igl::arap_dof_update(
|
||||
MatrixXS R(data.dim,data.dim*k);
|
||||
Eigen::Matrix<SSCALAR,Eigen::Dynamic,1> Rcol(data.dim * data.dim * k);
|
||||
Matrix<SSCALAR,Dynamic,1> B_eq_SSCALAR = B_eq.cast<SSCALAR>();
|
||||
Matrix<SSCALAR,Dynamic,1> B_eq_fix_SSCALAR;
|
||||
Matrix<SSCALAR,Dynamic,1> L0SSCALAR = L0.cast<SSCALAR>();
|
||||
slice(L0SSCALAR, data.fixed_dim, B_eq_fix_SSCALAR);
|
||||
Matrix<SSCALAR,Dynamic,1> B_eq_fix_SSCALAR = L0SSCALAR(data.fixed_dim);
|
||||
//MatrixXS rhsFull(Rcol.rows() + B_eq.rows() + B_eq_fix_SSCALAR.rows(), 1);
|
||||
|
||||
MatrixXS Lsep(data.m*(data.dim + 1), 3);
|
||||
|
||||
@@ -49,7 +49,7 @@ IGL_INLINE void igl::arap_rhs(
|
||||
return;
|
||||
}
|
||||
|
||||
DerivedK KX,KY,KZ;
|
||||
Eigen::SparseMatrix<typename DerivedK::Scalar> KX,KY,KZ;
|
||||
arap_linear_block(V,F,0,energy,KX);
|
||||
arap_linear_block(V,F,1,energy,KY);
|
||||
if(Vdim == 2)
|
||||
@@ -63,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)
|
||||
{
|
||||
DerivedK ZZ(KX.rows()*2,KX.cols());
|
||||
Eigen::SparseMatrix<typename DerivedK::Scalar> ZZ(KX.rows()*2,KX.cols());
|
||||
K = cat(2,cat(2,
|
||||
cat(2,repdiag(KX,dim),ZZ),
|
||||
cat(2,repdiag(KY,dim),ZZ)),
|
||||
@@ -92,4 +92,4 @@ IGL_INLINE void igl::arap_rhs(
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
template void igl::arap_rhs(const Eigen::MatrixBase<Eigen::MatrixXd> & V, const Eigen::MatrixBase<Eigen::MatrixXi> & F,const int dim, const igl::ARAPEnergyType energy,Eigen::SparseCompressedBase<Eigen::SparseMatrix<double>>& K);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -15,9 +15,9 @@ namespace igl
|
||||
/// Move a scalar field defined on edges to vertices by averaging
|
||||
///
|
||||
/// @param[in] F #F by 3 triangle mesh connectivity
|
||||
/// @param[in] E #E by 3 mapping from each halfedge to each edge
|
||||
/// @param[in] oE #E by 3 orientation as generated by orient_halfedges
|
||||
/// @param[in] uE #E by 1 list of scalars
|
||||
/// @param[in] E #F by 3 mapping from each halfedge to each edge
|
||||
/// @param[in] oE #F by 3 orientation as generated by orient_halfedges
|
||||
/// @param[in] uE #uE by 1 list of scalars
|
||||
/// @param[out] uV #V by 1 list of scalar defined on vertices
|
||||
///
|
||||
/// \see orient_halfedges
|
||||
|
||||
@@ -34,6 +34,11 @@ IGL_INLINE void igl::barycenter(
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
// generated by autoexplicit.sh
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::barycenter<Eigen::Matrix<double, -1, 2, 0, -1, 2>, Eigen::Matrix<int, -1, 2, 0, -1, 2>, Eigen::Matrix<double, -1, 2, 0, -1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 2, 0, -1, 2> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::barycenter<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::barycenter<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 3, 0, -1, 3> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::barycenter<Eigen::Matrix<double, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
|
||||
@@ -55,4 +60,5 @@ template void igl::barycenter<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::M
|
||||
template void igl::barycenter<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, 2, 3, 0, 2, 3>, Eigen::Matrix<double, 2, 3, 0, 2, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, 2, 3, 0, 2, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 2, 3, 0, 2, 3> >&);
|
||||
template void igl::barycenter<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 2, 0, -1, 2> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 2, 0, -1, 2> >&);
|
||||
template void igl::barycenter<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
|
||||
template void igl::barycenter<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1>>(Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1>>&);
|
||||
#endif
|
||||
|
||||
+9
-5
@@ -39,10 +39,10 @@ template <
|
||||
typename Derivedbc,
|
||||
typename DerivedW>
|
||||
IGL_INLINE bool igl::bbw(
|
||||
const Eigen::PlainObjectBase<DerivedV> & V,
|
||||
const Eigen::PlainObjectBase<DerivedEle> & Ele,
|
||||
const Eigen::PlainObjectBase<Derivedb> & b,
|
||||
const Eigen::PlainObjectBase<Derivedbc> & bc,
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<Derivedb> & b,
|
||||
const Eigen::MatrixBase<Derivedbc> & bc,
|
||||
igl::BBWData & data,
|
||||
Eigen::PlainObjectBase<DerivedW> & W
|
||||
)
|
||||
@@ -109,11 +109,15 @@ IGL_INLINE bool igl::bbw(
|
||||
case SOLVER_STATUS_CONVERGED:
|
||||
break;
|
||||
case SOLVER_STATUS_MAX_ITER:
|
||||
#ifdef IGL_BBW_DEBUG
|
||||
cerr<<"active_set: max iter without convergence."<<endl;
|
||||
#endif
|
||||
break;
|
||||
case SOLVER_STATUS_ERROR:
|
||||
default:
|
||||
#ifdef IGL_BBW_DEBUG
|
||||
cerr<<"active_set error."<<endl;
|
||||
#endif
|
||||
error = true;
|
||||
}
|
||||
W.col(i) = Wi;
|
||||
@@ -139,6 +143,6 @@ IGL_INLINE bool igl::bbw(
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
template bool igl::bbw<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, igl::BBWData&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
template bool igl::bbw<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const&, igl::BBWData&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>&);
|
||||
#endif
|
||||
|
||||
|
||||
+4
-4
@@ -60,10 +60,10 @@ namespace igl
|
||||
typename Derivedbc,
|
||||
typename DerivedW>
|
||||
IGL_INLINE bool bbw(
|
||||
const Eigen::PlainObjectBase<DerivedV> & V,
|
||||
const Eigen::PlainObjectBase<DerivedEle> & Ele,
|
||||
const Eigen::PlainObjectBase<Derivedb> & b,
|
||||
const Eigen::PlainObjectBase<Derivedbc> & bc,
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<Derivedb> & b,
|
||||
const Eigen::MatrixBase<Derivedbc> & bc,
|
||||
BBWData & data,
|
||||
Eigen::PlainObjectBase<DerivedW> & W);
|
||||
}
|
||||
|
||||
@@ -6,6 +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 "bezier.h"
|
||||
#include "PlainMatrix.h"
|
||||
#include <cassert>
|
||||
|
||||
// Adapted from main.c accompanying
|
||||
@@ -19,7 +20,7 @@ IGL_INLINE void igl::bezier(
|
||||
Eigen::PlainObjectBase<DerivedP> & P)
|
||||
{
|
||||
// working local copy
|
||||
DerivedV Vtemp = V;
|
||||
PlainMatrix<DerivedV> Vtemp = V;
|
||||
int degree = Vtemp.rows()-1;
|
||||
/* Triangle computation */
|
||||
for (int i = 1; i <= degree; i++)
|
||||
|
||||
@@ -149,7 +149,7 @@ IGL_INLINE bool igl::biharmonic_coordinates(
|
||||
}
|
||||
// Vertices in point handles
|
||||
const size_t mp =
|
||||
count_if(S.begin(),S.end(),[](const vector<int> & h){return h.size()==1;});
|
||||
count_if(S.begin(),S.end(),[](const vector<SType> & h){return h.size()==1;});
|
||||
// number of region handles
|
||||
const size_t r = S.size()-mp;
|
||||
// Vertices in region handles
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "bijective_composite_harmonic_mapping.h"
|
||||
|
||||
#include "slice.h"
|
||||
#include "doublearea.h"
|
||||
#include "harmonic.h"
|
||||
#include "placeholders.h"
|
||||
//#include "matlab/MatlabWorkspace.h"
|
||||
#include <iostream>
|
||||
|
||||
@@ -49,10 +49,9 @@ IGL_INLINE bool igl::bijective_composite_harmonic_mapping(
|
||||
typedef typename Derivedbc::Scalar Scalar;
|
||||
assert(V.cols() == 2 && bc.cols() == 2 && "Input should be 2D");
|
||||
assert(F.cols() == 3 && "F should contain triangles");
|
||||
int tries = 0;
|
||||
int nsteps = min_steps;
|
||||
Eigen::Matrix<typename Derivedbc::Scalar, Eigen::Dynamic, Eigen::Dynamic> bc0;
|
||||
slice(V,b.col(0),1,bc0);
|
||||
Eigen::Matrix<typename Derivedbc::Scalar, Eigen::Dynamic, Eigen::Dynamic> bc0 =
|
||||
V(b.col(0),igl::placeholders::all);
|
||||
|
||||
// It's difficult to check for flips "robustly" in the sense that the input
|
||||
// mesh might not have positive/consistent sign to begin with.
|
||||
@@ -83,7 +82,7 @@ IGL_INLINE bool igl::bijective_composite_harmonic_mapping(
|
||||
//mw.save(bct,"bct");
|
||||
//mw.write("numerical.mat");
|
||||
harmonic(Eigen::Matrix<typename DerivedU::Scalar, Eigen::Dynamic, Eigen::Dynamic>(U), F, b, bct, 1, U);
|
||||
igl::slice(U,b.col(0),1,bct);
|
||||
bct = U(b.col(0),igl::placeholders::all);
|
||||
nans = (U.array() != U.array()).count();
|
||||
if(test_for_flips)
|
||||
{
|
||||
|
||||
@@ -14,7 +14,6 @@ IGL_INLINE void igl::blkdiag(
|
||||
{
|
||||
int nr = 0;
|
||||
int nc = 0;
|
||||
int nnz = 0;
|
||||
for(const auto & A : L)
|
||||
{
|
||||
nr += A.rows();
|
||||
|
||||
@@ -8,20 +8,21 @@
|
||||
#include "blue_noise.h"
|
||||
#include "doublearea.h"
|
||||
#include "random_points_on_mesh.h"
|
||||
#include "slice.h"
|
||||
#include "sortrows.h"
|
||||
#include "placeholders.h"
|
||||
#include "PI.h"
|
||||
#include "get_seconds.h"
|
||||
#include <unordered_map>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <random>
|
||||
#include <cstdint>
|
||||
|
||||
namespace igl
|
||||
{
|
||||
// It is very important that we use 64bit keys to avoid out of bounds (easy to
|
||||
// get to happen with dense samplings (e.g., r = 0.0005*bbd)
|
||||
typedef int64_t BlueNoiseKeyType;
|
||||
typedef std::int64_t BlueNoiseKeyType;
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
@@ -71,7 +72,6 @@ namespace igl
|
||||
const int xi = Xs(i,0);
|
||||
const int yi = Xs(i,1);
|
||||
const int zi = Xs(i,2);
|
||||
BlueNoiseKeyType k = blue_noise_key(w,xi,yi,zi);
|
||||
int g = 2; // ceil(r/s)
|
||||
for(int x = std::max(xi-g,0);x<=std::min(xi+g,w-1);x++)
|
||||
for(int y = std::max(yi-g,0);y<=std::min(yi+g,w-1);y++)
|
||||
@@ -257,7 +257,6 @@ IGL_INLINE void igl::blue_noise(
|
||||
URBG && urbg)
|
||||
{
|
||||
typedef typename DerivedV::Scalar Scalar;
|
||||
typedef Eigen::Matrix<Scalar,Eigen::Dynamic,1> VectorXS;
|
||||
// float+RowMajor is faster...
|
||||
typedef Eigen::Matrix<Scalar,Eigen::Dynamic,3,Eigen::RowMajor> MatrixX3S;
|
||||
assert(V.cols() == 3 && "Only 3D embeddings allowed");
|
||||
@@ -292,10 +291,10 @@ IGL_INLINE void igl::blue_noise(
|
||||
{
|
||||
Eigen::VectorXi I;
|
||||
igl::sortrows(decltype(Xs)(Xs),true,Xs,I);
|
||||
igl::slice(decltype(X)(X),I,1,X);
|
||||
X = X(I,igl::placeholders::all).eval();
|
||||
// These two could be spun off in their own thread.
|
||||
igl::slice(decltype(XB)(XB),I,1,XB);
|
||||
igl::slice(decltype(XFI)(XFI),I,1,XFI);
|
||||
XB = XB(I,igl::placeholders::all).eval();
|
||||
XFI = XFI(I,igl::placeholders::all).eval();
|
||||
}
|
||||
// Initialization
|
||||
std::unordered_map<BlueNoiseKeyType,std::vector<int> > M;
|
||||
|
||||
@@ -15,16 +15,26 @@
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedEle,
|
||||
typename DerivedC,
|
||||
typename DerivedP,
|
||||
typename DerivedBE,
|
||||
typename DerivedCE,
|
||||
typename DerivedCF,
|
||||
typename Derivedb,
|
||||
typename Derivedbc>
|
||||
IGL_INLINE bool igl::boundary_conditions(
|
||||
const Eigen::MatrixXd & V ,
|
||||
const Eigen::MatrixXi & /*Ele*/,
|
||||
const Eigen::MatrixXd & C ,
|
||||
const Eigen::VectorXi & P ,
|
||||
const Eigen::MatrixXi & BE ,
|
||||
const Eigen::MatrixXi & CE ,
|
||||
const Eigen::MatrixXi & CF ,
|
||||
Eigen::VectorXi & b ,
|
||||
Eigen::MatrixXd & bc )
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedC> & C,
|
||||
const Eigen::MatrixBase<DerivedP> & P,
|
||||
const Eigen::MatrixBase<DerivedBE> & BE,
|
||||
const Eigen::MatrixBase<DerivedCE> & CE,
|
||||
const Eigen::MatrixBase<DerivedCF> & CF,
|
||||
Eigen::PlainObjectBase<Derivedb> & b,
|
||||
Eigen::PlainObjectBase<Derivedbc> & bc)
|
||||
{
|
||||
using namespace Eigen;
|
||||
using namespace std;
|
||||
@@ -122,7 +132,7 @@ IGL_INLINE bool igl::boundary_conditions(
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<uint8_t> vertices_marked(V.rows(), 0);
|
||||
std::vector<bool> vertices_marked(V.rows(), false);
|
||||
// loop over cage faces
|
||||
for(int f = 0;f<CF.rows();f++)
|
||||
{
|
||||
@@ -142,7 +152,6 @@ IGL_INLINE bool igl::boundary_conditions(
|
||||
Vector3d point = V.row(i);
|
||||
Vector3d v = point - v_0;
|
||||
double dist = abs(v.dot(n));
|
||||
Vector3d projected_point = point - dist * n;
|
||||
if (dist <= 1.e-1f)
|
||||
{
|
||||
//barycentric coordinates
|
||||
@@ -159,7 +168,7 @@ IGL_INLINE bool igl::boundary_conditions(
|
||||
|
||||
if (u>=0. && u<=1.0 && v>=0. && v<=1.0 && w >=0. && w<=1.0)
|
||||
{
|
||||
vertices_marked[i] = 1;
|
||||
vertices_marked[i] = true;
|
||||
bci.push_back(i);
|
||||
bcj.push_back(CF(f, 0));
|
||||
bcv.push_back(u);
|
||||
@@ -243,3 +252,8 @@ IGL_INLINE bool igl::boundary_conditions(
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
template bool igl::boundary_conditions<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>>&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>&);
|
||||
#endif
|
||||
|
||||
@@ -36,16 +36,26 @@ namespace igl
|
||||
/// 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)
|
||||
///
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedEle,
|
||||
typename DerivedC,
|
||||
typename DerivedP,
|
||||
typename DerivedBE,
|
||||
typename DerivedCE,
|
||||
typename DerivedCF,
|
||||
typename Derivedb,
|
||||
typename Derivedbc>
|
||||
IGL_INLINE bool boundary_conditions(
|
||||
const Eigen::MatrixXd & V,
|
||||
const Eigen::MatrixXi & Ele,
|
||||
const Eigen::MatrixXd & C,
|
||||
const Eigen::VectorXi & P,
|
||||
const Eigen::MatrixXi & BE,
|
||||
const Eigen::MatrixXi & CE,
|
||||
const Eigen::MatrixXi & CF,
|
||||
Eigen::VectorXi & b,
|
||||
Eigen::MatrixXd & bc);
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedEle> & Ele,
|
||||
const Eigen::MatrixBase<DerivedC> & C,
|
||||
const Eigen::MatrixBase<DerivedP> & P,
|
||||
const Eigen::MatrixBase<DerivedBE> & BE,
|
||||
const Eigen::MatrixBase<DerivedCE> & CE,
|
||||
const Eigen::MatrixBase<DerivedCF> & CF,
|
||||
Eigen::PlainObjectBase<Derivedb> & b,
|
||||
Eigen::PlainObjectBase<Derivedbc> & bc);
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "sort.h"
|
||||
#include "unique_rows.h"
|
||||
#include "accumarray.h"
|
||||
#include "slice_mask.h"
|
||||
|
||||
#include <Eigen/Core>
|
||||
|
||||
@@ -48,21 +47,21 @@ IGL_INLINE void igl::boundary_facets(
|
||||
for(int i = 0; i< (int)T.rows();i++)
|
||||
{
|
||||
// get face in correct order
|
||||
allF(i*simplex_size+0,0) = T(i,1);
|
||||
allF(i*simplex_size+0,2) = T(i,1);
|
||||
allF(i*simplex_size+0,1) = T(i,3);
|
||||
allF(i*simplex_size+0,2) = T(i,2);
|
||||
allF(i*simplex_size+0,0) = T(i,2);
|
||||
// get face in correct order
|
||||
allF(i*simplex_size+1,0) = T(i,0);
|
||||
allF(i*simplex_size+1,2) = T(i,0);
|
||||
allF(i*simplex_size+1,1) = T(i,2);
|
||||
allF(i*simplex_size+1,2) = T(i,3);
|
||||
allF(i*simplex_size+1,0) = T(i,3);
|
||||
// get face in correct order
|
||||
allF(i*simplex_size+2,0) = T(i,0);
|
||||
allF(i*simplex_size+2,2) = T(i,0);
|
||||
allF(i*simplex_size+2,1) = T(i,3);
|
||||
allF(i*simplex_size+2,2) = T(i,1);
|
||||
allF(i*simplex_size+2,0) = T(i,1);
|
||||
// get face in correct order
|
||||
allF(i*simplex_size+3,0) = T(i,0);
|
||||
allF(i*simplex_size+3,2) = T(i,0);
|
||||
allF(i*simplex_size+3,1) = T(i,1);
|
||||
allF(i*simplex_size+3,2) = T(i,2);
|
||||
allF(i*simplex_size+3,0) = T(i,2);
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
@@ -125,101 +124,12 @@ Ret igl::boundary_facets(
|
||||
return F;
|
||||
}
|
||||
|
||||
template <typename IntegerT, typename IntegerF>
|
||||
IGL_INLINE void igl::boundary_facets(
|
||||
const std::vector<std::vector<IntegerT> > & T,
|
||||
std::vector<std::vector<IntegerF> > & F)
|
||||
{
|
||||
// Kept for legacy reasons. Could probably just delete.
|
||||
using namespace std;
|
||||
|
||||
if(T.size() == 0)
|
||||
{
|
||||
F.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
int simplex_size = T[0].size();
|
||||
// Get a list of all faces
|
||||
vector<vector<IntegerF> > allF(
|
||||
T.size()*simplex_size,
|
||||
vector<IntegerF>(simplex_size-1));
|
||||
|
||||
// Gather faces, loop over tets
|
||||
for(int i = 0; i< (int)T.size();i++)
|
||||
{
|
||||
assert((int)T[i].size() == simplex_size);
|
||||
switch(simplex_size)
|
||||
{
|
||||
case 4:
|
||||
// get face in correct order
|
||||
allF[i*simplex_size+0][0] = T[i][1];
|
||||
allF[i*simplex_size+0][1] = T[i][3];
|
||||
allF[i*simplex_size+0][2] = T[i][2];
|
||||
// get face in correct order
|
||||
allF[i*simplex_size+1][0] = T[i][0];
|
||||
allF[i*simplex_size+1][1] = T[i][2];
|
||||
allF[i*simplex_size+1][2] = T[i][3];
|
||||
// get face in correct order
|
||||
allF[i*simplex_size+2][0] = T[i][0];
|
||||
allF[i*simplex_size+2][1] = T[i][3];
|
||||
allF[i*simplex_size+2][2] = T[i][1];
|
||||
// get face in correct order
|
||||
allF[i*simplex_size+3][0] = T[i][0];
|
||||
allF[i*simplex_size+3][1] = T[i][1];
|
||||
allF[i*simplex_size+3][2] = T[i][2];
|
||||
break;
|
||||
case 3:
|
||||
allF[i*simplex_size+0][0] = T[i][1];
|
||||
allF[i*simplex_size+0][1] = T[i][2];
|
||||
allF[i*simplex_size+1][0] = T[i][2];
|
||||
allF[i*simplex_size+1][1] = T[i][0];
|
||||
allF[i*simplex_size+2][0] = T[i][0];
|
||||
allF[i*simplex_size+2][1] = T[i][1];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Counts
|
||||
vector<int> C;
|
||||
face_occurrences(allF,C);
|
||||
|
||||
// Q: Why not just count the number of ones?
|
||||
// A: because we are including non-manifold edges as boundary edges
|
||||
int twos = (int) count(C.begin(),C.end(),2);
|
||||
//int ones = (int) count(C.begin(),C.end(),1);
|
||||
// Resize output to fit number of ones
|
||||
F.resize(allF.size() - twos);
|
||||
//F.resize(ones);
|
||||
int k = 0;
|
||||
for(int i = 0;i< (int)allF.size();i++)
|
||||
{
|
||||
if(C[i] != 2)
|
||||
{
|
||||
assert(k<(int)F.size());
|
||||
F[k] = allF[i];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
assert(k==(int)F.size());
|
||||
//if(k != F.size())
|
||||
//{
|
||||
// printf("%d =? %d\n",k,F.size());
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> >&);
|
||||
template void igl::boundary_facets<int, int>(std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > > const&, std::vector<std::vector<int, std::allocator<int> >, std::allocator<std::vector<int, std::allocator<int> > > >&);
|
||||
//template Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > igl::boundary_facets(Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
|
||||
template Eigen::Matrix<int, -1, -1, 0, -1, -1> igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&);
|
||||
template void igl::boundary_facets<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 1, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> >&);
|
||||
#endif
|
||||
|
||||
@@ -19,7 +19,9 @@ namespace igl
|
||||
/// (analogous to qptoolbox's `outline` and `boundary_faces`).
|
||||
///
|
||||
/// @param[in] T tetrahedron (triangle) index list, m by 4 (3), where m is the number of tetrahedra
|
||||
/// @param[out] F list of boundary faces, n by 3 (2), where n is the number of boundary faces
|
||||
/// @param[out] F list of boundary faces, n by 3 (2), where n is the number
|
||||
/// of boundary faces. Faces are oriented so that igl::centroid(V,F,…)
|
||||
/// computes the same sign volume as igl::volume(V,T)
|
||||
/// @param[out] J list of indices into T, n by 1
|
||||
/// @param[out] K list of indices revealing across from which vertex is this facet
|
||||
///
|
||||
@@ -48,15 +50,6 @@ namespace igl
|
||||
template <typename DerivedT, typename Ret>
|
||||
Ret boundary_facets(
|
||||
const Eigen::MatrixBase<DerivedT>& T);
|
||||
/// Determine boundary faces (edges) of tetrahedra (triangles) stored in T;
|
||||
/// inputs and outputs lists.
|
||||
///
|
||||
/// @param[in] T tetrahedron (triangle) index list, m by 4 (3), where m is the number of tetrahedra
|
||||
/// @param[out] F list of boundary faces, n by 3 (2), where n is the number of boundary faces
|
||||
template <typename IntegerT, typename IntegerF>
|
||||
IGL_INLINE void boundary_facets(
|
||||
const std::vector<std::vector<IntegerT> > & T,
|
||||
std::vector<std::vector<IntegerF> > & F);
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
|
||||
@@ -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 "boundary_loop.h"
|
||||
#include "slice.h"
|
||||
#include "triangle_triangle_adjacency.h"
|
||||
#include "vertex_triangle_adjacency.h"
|
||||
#include "is_border_vertex.h"
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
#include "box_faces.h"
|
||||
#include "AABB.h"
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
template <typename DerivedV, typename DerivedQ>
|
||||
IGL_INLINE void igl::box_faces(
|
||||
const Eigen::AlignedBox<typename DerivedV::Scalar,3> & box,
|
||||
const typename DerivedV::Scalar shrink,
|
||||
Eigen::PlainObjectBase<DerivedV> & P,
|
||||
Eigen::PlainObjectBase<DerivedQ> & Q)
|
||||
{
|
||||
auto min_corner = box.min();
|
||||
auto max_corner = box.max();
|
||||
// shrink by 3%
|
||||
min_corner = min_corner + shrink*(max_corner-min_corner);
|
||||
max_corner = max_corner - shrink*(max_corner-min_corner);
|
||||
P.resize(8,3);
|
||||
Q.resize(6,4);
|
||||
int p = 0;
|
||||
int q = 0;
|
||||
Q.row(q++) << p+0,p+1,p+2,p+3;
|
||||
Q.row(q++) << p+0,p+1,p+5,p+4;
|
||||
Q.row(q++) << p+1,p+2,p+6,p+5;
|
||||
Q.row(q++) << p+2,p+3,p+7,p+6;
|
||||
Q.row(q++) << p+3,p+0,p+4,p+7;
|
||||
Q.row(q++) << p+4,p+5,p+6,p+7;
|
||||
P.row(p++) = min_corner;
|
||||
P.row(p++) = Eigen::RowVector3d(max_corner[0],min_corner[1],min_corner[2]);
|
||||
P.row(p++) = Eigen::RowVector3d(max_corner[0],max_corner[1],min_corner[2]);
|
||||
P.row(p++) = Eigen::RowVector3d(min_corner[0],max_corner[1],min_corner[2]);
|
||||
P.row(p++) = Eigen::RowVector3d(min_corner[0],min_corner[1],max_corner[2]);
|
||||
P.row(p++) = Eigen::RowVector3d(max_corner[0],min_corner[1],max_corner[2]);
|
||||
P.row(p++) = max_corner;
|
||||
P.row(p++) = Eigen::RowVector3d(min_corner[0],max_corner[1],max_corner[2]);
|
||||
}
|
||||
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedP,
|
||||
typename DerivedQ,
|
||||
typename DerivedD >
|
||||
IGL_INLINE void igl::box_faces(
|
||||
const igl::AABB<DerivedV,3> & tree,
|
||||
Eigen::PlainObjectBase<DerivedP> & P,
|
||||
Eigen::PlainObjectBase<DerivedQ> & Q,
|
||||
Eigen::PlainObjectBase<DerivedD> & D)
|
||||
{
|
||||
const int num_nodes = tree.size();
|
||||
P.resize(8*num_nodes,3);
|
||||
Q.resize(6*num_nodes,4);
|
||||
D.resize(6*num_nodes);
|
||||
int d = 0;
|
||||
int p = 0;
|
||||
int q = 0;
|
||||
std::vector<std::pair<const igl::AABB<DerivedV,3> *,int> > stack;
|
||||
stack.push_back({&tree,0});
|
||||
while(!stack.empty())
|
||||
{
|
||||
const auto pair = stack.back();
|
||||
const auto * node = pair.first;
|
||||
const int depth = pair.second;
|
||||
D(d++) = depth;
|
||||
D(d++) = depth;
|
||||
D(d++) = depth;
|
||||
D(d++) = depth;
|
||||
D(d++) = depth;
|
||||
D(d++) = depth;
|
||||
stack.pop_back();
|
||||
const auto & box = node->m_box;
|
||||
|
||||
DerivedP Pi;
|
||||
DerivedQ Qi;
|
||||
box_faces(box,0.03,Pi,Qi);
|
||||
P.block(p,0,8,3) = Pi;
|
||||
Q.block(q,0,6,4) = Qi.array()+p;
|
||||
p += 8;
|
||||
q += 6;
|
||||
if(node->m_left)
|
||||
{
|
||||
stack.push_back({node->m_left,depth+1});
|
||||
}
|
||||
if(node->m_right)
|
||||
{
|
||||
stack.push_back({node->m_right,depth+1});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::box_faces<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
|
||||
#endif
|
||||
@@ -0,0 +1,46 @@
|
||||
#ifndef IGL_BOX_FACES_H
|
||||
#define IGL_BOX_FACES_H
|
||||
#include "igl_inline.h"
|
||||
#include <Eigen/Core>
|
||||
#include <Eigen/Geometry>
|
||||
|
||||
namespace igl
|
||||
{
|
||||
/// Compute the quad faces of an axis-aligned bounding box) shrunk by a given
|
||||
/// factor.
|
||||
///
|
||||
/// @param[in] box Axis-aligned bounding box
|
||||
/// @param[in] shrink Factor by which to shrink the box
|
||||
/// @param[out] P #P by 3 list of vertex positions
|
||||
/// @param[out] Q #Q by 4 list of triangle indices into rows of P
|
||||
template <typename DerivedV, typename DerivedQ>
|
||||
IGL_INLINE void box_faces(
|
||||
const Eigen::AlignedBox<typename DerivedV::Scalar,3> & box,
|
||||
const typename DerivedV::Scalar shrink,
|
||||
Eigen::PlainObjectBase<DerivedV> & P,
|
||||
Eigen::PlainObjectBase<DerivedQ> & Q);
|
||||
// Forward declaration
|
||||
template <typename DerivedV, int DIM> class AABB;
|
||||
/// Compute the quad faces of a tree of axis-aligned bounding boxes.
|
||||
///
|
||||
/// @param[in] tree Tree of axis-aligned bounding boxes
|
||||
/// @param[out] P #P by 3 list of vertex positions
|
||||
/// @param[out] Q #Q by 4 list of triangle indices into rows of P
|
||||
/// @param[out] D #Q list of tree depths (0==root)
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedP,
|
||||
typename DerivedQ,
|
||||
typename DerivedD >
|
||||
IGL_INLINE void box_faces(
|
||||
const igl::AABB<DerivedV,3> & tree,
|
||||
Eigen::PlainObjectBase<DerivedP> & P,
|
||||
Eigen::PlainObjectBase<DerivedQ> & Q,
|
||||
Eigen::PlainObjectBase<DerivedD> & D);
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "box_faces.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "box_surface_area.h"
|
||||
|
||||
|
||||
template <typename DerivedCorner>
|
||||
IGL_INLINE typename DerivedCorner::Scalar igl::box_surface_area(
|
||||
const Eigen::MatrixBase<DerivedCorner> & min_corner,
|
||||
const Eigen::MatrixBase<DerivedCorner> & max_corner)
|
||||
{
|
||||
using Scalar = typename DerivedCorner::Scalar;
|
||||
const auto dimensions = (max_corner - min_corner).eval();
|
||||
const auto num_dimensions = dimensions.size();
|
||||
|
||||
Scalar surface_area = 0;
|
||||
for (int i = 0; i < num_dimensions; ++i) {
|
||||
for (int j = i + 1; j < num_dimensions; ++j) {
|
||||
surface_area += 2 * dimensions[i] * dimensions[j];
|
||||
}
|
||||
}
|
||||
|
||||
return surface_area;
|
||||
}
|
||||
|
||||
template <typename Scalar, int AmbientDim>
|
||||
IGL_INLINE Scalar igl::box_surface_area(
|
||||
const Eigen::AlignedBox<Scalar,AmbientDim> & box)
|
||||
{
|
||||
return igl::box_surface_area(box.min(),box.max());
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
// generated by autoexplicit.sh
|
||||
template double igl::box_surface_area<double, 2>(Eigen::AlignedBox<double, 2> const&);
|
||||
template double igl::box_surface_area<double, 3>(Eigen::AlignedBox<double, 3> const&);
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
#ifndef IGL_BOX_SURFACE_AREA_H
|
||||
#define IGL_BOX_SURFACE_AREA_H
|
||||
#include "igl_inline.h"
|
||||
#include <Eigen/Core>
|
||||
#include <Eigen/Geometry>
|
||||
|
||||
namespace igl
|
||||
{
|
||||
/// Compute the surface area of a box given its min and max corners
|
||||
///
|
||||
/// @param[in] min_corner #d vector of min corner position
|
||||
/// @param[in] max_corner #d vector of max corner position
|
||||
/// @return surface area of box
|
||||
template <typename DerivedCorner>
|
||||
IGL_INLINE typename DerivedCorner::Scalar box_surface_area(
|
||||
const Eigen::MatrixBase<DerivedCorner> & min_corner,
|
||||
const Eigen::MatrixBase<DerivedCorner> & max_corner);
|
||||
/// \overload
|
||||
/// @param[in] box axis-aligned bounding box
|
||||
template <typename Scalar, int AmbientDim>
|
||||
IGL_INLINE Scalar box_surface_area(
|
||||
const Eigen::AlignedBox<Scalar,AmbientDim> & box);
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "box_surface_area.cpp"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -236,6 +236,10 @@ IGL_INLINE void igl::cat(const int dim, const std::vector<T> & A, Eigen::PlainOb
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::cat<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, 1, 0, -1, 1> >(int, std::vector<Eigen::Matrix<int, -1, 1, 0, -1, 1>, std::allocator<Eigen::Matrix<int, -1, 1, 0, -1, 1> > > const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::cat<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(int, std::vector<Eigen::Matrix<double, -1, -1, 0, -1, -1>, std::allocator<Eigen::Matrix<double, -1, -1, 0, -1, -1> > > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::cat<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1> >(int, std::vector<Eigen::Matrix<float, -1, -1, 0, -1, -1>, std::allocator<Eigen::Matrix<float, -1, -1, 0, -1, -1> > > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template Eigen::Matrix<double, -1, -1, 0, -1, -1> igl::cat<Eigen::Matrix<double, -1, -1, 0, -1, -1> >(int, Eigen::Matrix<double, -1, -1, 0, -1, -1> const&, Eigen::Matrix<double, -1, -1, 0, -1, -1> const&);
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
template < typename DerivedX, typename DerivedY>
|
||||
IGL_INLINE void igl::ceil(
|
||||
const Eigen::PlainObjectBase<DerivedX>& X,
|
||||
const Eigen::MatrixBase<DerivedX>& X,
|
||||
Eigen::PlainObjectBase<DerivedY>& Y)
|
||||
{
|
||||
using namespace std;
|
||||
@@ -20,5 +20,5 @@ IGL_INLINE void igl::ceil(
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
template void igl::ceil<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
template void igl::ceil<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
#endif
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ namespace igl
|
||||
/// @param[out] Y m by n matrix of ceiled integers
|
||||
template < typename DerivedX, typename DerivedY>
|
||||
IGL_INLINE void ceil(
|
||||
const Eigen::PlainObjectBase<DerivedX>& X,
|
||||
const Eigen::MatrixBase<DerivedX>& X,
|
||||
Eigen::PlainObjectBase<DerivedY>& Y);
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,16 @@ IGL_INLINE void igl::centroid(
|
||||
assert(F.cols() == 3 && "F should contain triangles.");
|
||||
assert(V.cols() == 3 && "V should contain 3d points.");
|
||||
const int m = F.rows();
|
||||
cen.setZero();
|
||||
// static assert that cen is either a 3d rowvector a 3d vector or a variable
|
||||
// size vector
|
||||
static_assert(Derivedc::IsVectorAtCompileTime,"cen should be a vector");
|
||||
static_assert(
|
||||
Derivedc::RowsAtCompileTime == 3 ||
|
||||
Derivedc::RowsAtCompileTime == -1 ||
|
||||
Derivedc::ColsAtCompileTime == 3 ||
|
||||
Derivedc::ColsAtCompileTime == -1,
|
||||
"cen should be sizeable to 3 vector");
|
||||
cen.setZero(3);
|
||||
vol = 0;
|
||||
// loop over faces
|
||||
for(int f = 0;f<m;f++)
|
||||
@@ -61,6 +70,8 @@ IGL_INLINE void igl::centroid(
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::centroid<Eigen::Matrix<double, 8, 3, 0, 8, 3>, Eigen::Matrix<int, 12, 3, 0, 12, 3>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, double>(Eigen::MatrixBase<Eigen::Matrix<double, 8, 3, 0, 8, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, 12, 3, 0, 12, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, double&);
|
||||
template void igl::centroid<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 1, 3, 1, 1, 3>, double>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&, double&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::centroid<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3>, Eigen::Matrix<float, 3, 1, 0, 3, 1>, float>(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<unsigned int, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, 3, 1, 0, 3, 1> >&, float&);
|
||||
@@ -70,4 +81,5 @@ template void igl::centroid<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix
|
||||
template void igl::centroid<Eigen::Matrix<float, -1, 3, 1, -1, 3>, Eigen::Matrix<int, -1, 3, 1, -1, 3>, Eigen::Matrix<float, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, 3, 1, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 1, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<float, 1, 3, 1, 1, 3> >&);
|
||||
template void igl::centroid<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 3, 1, 0, 3, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 3, 1, 0, 3, 1> >&);
|
||||
template void igl::centroid<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 1, 3, 1, 1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, 3, 1, 1, 3> >&);
|
||||
template void igl::centroid<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, 1, -1, 1, 1, -1>>(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::PlainObjectBase<Eigen::Matrix<double, 1, -1, 1, 1, -1>>&);
|
||||
#endif
|
||||
|
||||
+36
-26
@@ -1,20 +1,21 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
//
|
||||
// Copyright (C) 2015 Alec Jacobson <alecjacobson@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
|
||||
//
|
||||
// This Source Code Form is subject to 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 "circulation.h"
|
||||
#include "list_to_matrix.h"
|
||||
#include <cassert>
|
||||
|
||||
template <typename DerivedEMAP, typename DerivedEF, typename DerivedEI>
|
||||
IGL_INLINE std::vector<int> igl::circulation(
|
||||
const int e,
|
||||
const bool ccw,
|
||||
const Eigen::VectorXi & EMAP,
|
||||
const Eigen::MatrixXi & EF,
|
||||
const Eigen::MatrixXi & EI)
|
||||
const Eigen::MatrixBase<DerivedEMAP> & EMAP,
|
||||
const Eigen::MatrixBase<DerivedEF> & EF,
|
||||
const Eigen::MatrixBase<DerivedEI> & EI)
|
||||
{
|
||||
// prepare output
|
||||
std::vector<int> N;
|
||||
@@ -22,9 +23,9 @@ IGL_INLINE std::vector<int> igl::circulation(
|
||||
const int m = EMAP.size()/3;
|
||||
assert(m*3 == EMAP.size());
|
||||
const auto & step = [&](
|
||||
const int e,
|
||||
const int e,
|
||||
const int ff,
|
||||
int & ne,
|
||||
int & ne,
|
||||
int & nf)
|
||||
{
|
||||
assert((EF(e,1) == ff || EF(e,0) == ff) && "e should touch ff");
|
||||
@@ -33,7 +34,7 @@ IGL_INLINE std::vector<int> igl::circulation(
|
||||
const int nv = EI(e,nside);
|
||||
// get next face
|
||||
nf = EF(e,nside);
|
||||
// get next edge
|
||||
// get next edge
|
||||
const int dir = ccw?-1:1;
|
||||
ne = EMAP(nf+m*((nv+dir+3)%3));
|
||||
};
|
||||
@@ -56,36 +57,38 @@ IGL_INLINE std::vector<int> igl::circulation(
|
||||
return N;
|
||||
}
|
||||
|
||||
template <typename DerivedEMAP, typename DerivedEF, typename DerivedEI, typename DerivedvN>
|
||||
IGL_INLINE void igl::circulation(
|
||||
const int e,
|
||||
const bool ccw,
|
||||
const Eigen::VectorXi & EMAP,
|
||||
const Eigen::MatrixXi & EF,
|
||||
const Eigen::MatrixXi & EI,
|
||||
Eigen::VectorXi & vN)
|
||||
const Eigen::MatrixBase<DerivedEMAP> & EMAP,
|
||||
const Eigen::MatrixBase<DerivedEF> & EF,
|
||||
const Eigen::MatrixBase<DerivedEI> & EI,
|
||||
Eigen::PlainObjectBase<DerivedvN> & vN)
|
||||
{
|
||||
std::vector<int> N = circulation(e,ccw,EMAP,EF,EI);
|
||||
igl::list_to_matrix(N,vN);
|
||||
}
|
||||
|
||||
template <typename DerivedF, typename DerivedEMAP, typename DerivedEF, typename DerivedEI, typename Nv_type>
|
||||
IGL_INLINE void igl::circulation(
|
||||
const int e,
|
||||
const bool ccw,
|
||||
const Eigen::MatrixXi & F,
|
||||
const Eigen::VectorXi & EMAP,
|
||||
const Eigen::MatrixXi & EF,
|
||||
const Eigen::MatrixXi & EI,
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
const Eigen::MatrixBase<DerivedEMAP> & EMAP,
|
||||
const Eigen::MatrixBase<DerivedEF> & EF,
|
||||
const Eigen::MatrixBase<DerivedEI> & EI,
|
||||
/*std::vector<int> & Ne,*/
|
||||
std::vector<int> & Nv,
|
||||
std::vector<int> & Nf)
|
||||
std::vector<Nv_type> & Nv,
|
||||
std::vector<Nv_type> & Nf)
|
||||
{
|
||||
//
|
||||
// for e --> (bf) and ccw=true
|
||||
//
|
||||
// c---d
|
||||
// / \ / \
|
||||
// ╱ ╲ ╱ ╲
|
||||
// a---b-e-f
|
||||
// \ / \ /
|
||||
// ╲ ╱ ╲ ╱
|
||||
// g---h
|
||||
//
|
||||
// // (might start with {bhf} depending on edge)
|
||||
@@ -101,9 +104,9 @@ IGL_INLINE void igl::circulation(
|
||||
const int m = EMAP.size()/3;
|
||||
assert(m*3 == EMAP.size());
|
||||
const auto & step = [&](
|
||||
const int e,
|
||||
const int e,
|
||||
const int ff,
|
||||
int & ne,
|
||||
int & ne,
|
||||
//int & re,
|
||||
int & rv,
|
||||
int & nf)
|
||||
@@ -114,7 +117,7 @@ IGL_INLINE void igl::circulation(
|
||||
const int nv = EI(e,nside);
|
||||
// get next face
|
||||
nf = EF(e,nside);
|
||||
// get next edge
|
||||
// get next edge
|
||||
const int dir = ccw?-1:1;
|
||||
rv = F(nf,nv);
|
||||
ne = EMAP(nf+m*((nv+dir+3)%3));
|
||||
@@ -127,7 +130,7 @@ IGL_INLINE void igl::circulation(
|
||||
int ei = e;
|
||||
while(true)
|
||||
{
|
||||
int re,rv;
|
||||
int rv;
|
||||
step(ei,fi,ei/*,re*/,rv,fi);
|
||||
Nf.push_back(fi);
|
||||
//Ne.push_back(re);
|
||||
@@ -141,3 +144,10 @@ IGL_INLINE void igl::circulation(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template specialization
|
||||
template std::vector<int, std::allocator<int>> igl::circulation<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>>(int, bool, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&);
|
||||
template void igl::circulation<Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>>(int, bool, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::PlainObjectBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>>&);
|
||||
template void igl::circulation<Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, int>(int, bool, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, std::vector<int, std::allocator<int>>&, std::vector<int, std::allocator<int>>&);
|
||||
#endif
|
||||
|
||||
+16
-13
@@ -28,12 +28,13 @@ namespace igl
|
||||
/// @return list of faces touched by circulation (in cyclically order).
|
||||
///
|
||||
/// \see edge_flaps
|
||||
template <typename DerivedEMAP, typename DerivedEF, typename DerivedEI>
|
||||
IGL_INLINE std::vector<int> circulation(
|
||||
const int e,
|
||||
const bool ccw,
|
||||
const Eigen::VectorXi & EMAP,
|
||||
const Eigen::MatrixXi & EF,
|
||||
const Eigen::MatrixXi & EI);
|
||||
const Eigen::MatrixBase<DerivedEMAP> & EMAP,
|
||||
const Eigen::MatrixBase<DerivedEF> & EF,
|
||||
const Eigen::MatrixBase<DerivedEI> & EI);
|
||||
/// Return list of faces around the end point of an edge. Assumes
|
||||
/// data-structures are built from an edge-manifold **closed** mesh.
|
||||
///
|
||||
@@ -49,13 +50,14 @@ namespace igl
|
||||
/// @param[out] #vN list of of faces touched by circulation (in cyclically order).
|
||||
///
|
||||
/// \see edge_flaps
|
||||
template <typename DerivedEMAP, typename DerivedEF, typename DerivedEI, typename DerivedvN>
|
||||
IGL_INLINE void circulation(
|
||||
const int e,
|
||||
const bool ccw,
|
||||
const Eigen::VectorXi & EMAP,
|
||||
const Eigen::MatrixXi & EF,
|
||||
const Eigen::MatrixXi & EI,
|
||||
Eigen::VectorXi & vN);
|
||||
const Eigen::MatrixBase<DerivedEMAP> & EMAP,
|
||||
const Eigen::MatrixBase<DerivedEF> & EF,
|
||||
const Eigen::MatrixBase<DerivedEI> & EI,
|
||||
Eigen::PlainObjectBase<DerivedvN> & vN);
|
||||
/// Return list of faces around the end point of an edge. Assumes
|
||||
/// data-structures are built from an edge-manifold **closed** mesh.
|
||||
///
|
||||
@@ -72,16 +74,17 @@ namespace igl
|
||||
/// @param[out] Nf #Nf list of face indices
|
||||
///
|
||||
/// \see edge_flaps
|
||||
template <typename DerivedF, typename DerivedEMAP, typename DerivedEF, typename DerivedEI, typename Nv_type>
|
||||
IGL_INLINE void circulation(
|
||||
const int e,
|
||||
const bool ccw,
|
||||
const Eigen::MatrixXi & F,
|
||||
const Eigen::VectorXi & EMAP,
|
||||
const Eigen::MatrixXi & EF,
|
||||
const Eigen::MatrixXi & EI,
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
const Eigen::MatrixBase<DerivedEMAP> & EMAP,
|
||||
const Eigen::MatrixBase<DerivedEF> & EF,
|
||||
const Eigen::MatrixBase<DerivedEI> & EI,
|
||||
/*std::vector<int> & Ne,*/
|
||||
std::vector<int> & Nv,
|
||||
std::vector<int> & Nf);
|
||||
std::vector<Nv_type> & Nv,
|
||||
std::vector<Nv_type> & Nf);
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
#include "circumradius.h"
|
||||
#include "edge_lengths.h"
|
||||
#include "doublearea.h"
|
||||
#include "placeholders.h"
|
||||
#include <Eigen/QR>
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
@@ -17,6 +19,9 @@ IGL_INLINE void igl::circumradius(
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
Eigen::PlainObjectBase<DerivedR> & R)
|
||||
{
|
||||
// cols at compiletime should be Dynamic or 3
|
||||
static_assert(DerivedF::ColsAtCompileTime == Eigen::Dynamic || DerivedF::ColsAtCompileTime == 3,"F should contain triangles");
|
||||
assert(F.cols() == 3 && "F should contain triangles");
|
||||
Eigen::Matrix<typename DerivedV::Scalar,Eigen::Dynamic,3> l;
|
||||
igl::edge_lengths(V,F,l);
|
||||
DerivedR A;
|
||||
@@ -25,6 +30,59 @@ IGL_INLINE void igl::circumradius(
|
||||
R = l.col(0).array() * l.col(1).array() * l.col(2).array() / (2.0*A.array());
|
||||
}
|
||||
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedT,
|
||||
typename DerivedR,
|
||||
typename DerivedC,
|
||||
typename DerivedB>
|
||||
IGL_INLINE void igl::circumradius(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedT> & T,
|
||||
Eigen::PlainObjectBase<DerivedR> & R,
|
||||
Eigen::PlainObjectBase<DerivedC> & C,
|
||||
Eigen::PlainObjectBase<DerivedB> & B)
|
||||
{
|
||||
using Scalar = typename DerivedV::Scalar;
|
||||
const int TCOLS = DerivedT::ColsAtCompileTime;
|
||||
const int VCOLS = DerivedV::ColsAtCompileTime;
|
||||
const int ACOLS = TCOLS==Eigen::Dynamic?Eigen::Dynamic:TCOLS+1;
|
||||
const int ss = T.cols();
|
||||
R.resize(T.rows(),1);
|
||||
C.resize(T.rows(),V.cols());
|
||||
B.resize(T.rows(),T.cols());
|
||||
for(int i = 0;i<T.rows();i++)
|
||||
{
|
||||
Eigen::Matrix<Scalar,ACOLS,ACOLS> A(T.cols()+1,T.cols()+1);
|
||||
// Not sure if this .eval() is a good idea
|
||||
const auto Vi = V(T.row(i),igl::placeholders::all).eval();
|
||||
A.topLeftCorner(T.cols(),T.cols()) = 2*(Vi*Vi.transpose());
|
||||
A.block(0,T.cols(),T.cols(),1).setConstant(1);
|
||||
A.block(T.cols(),0,1,T.cols()).setConstant(1);
|
||||
A(T.cols(),T.cols()) = 0;
|
||||
Eigen::Matrix<Scalar,ACOLS,1> b(T.cols()+1,1);
|
||||
b.head(T.cols()) = (Vi.array().square().rowwise().sum()).eval();
|
||||
b(T.cols()) = 1;
|
||||
// [B;λ] = A\b
|
||||
const auto x = (A.colPivHouseholderQr().solve(b)).eval();
|
||||
B.row(i) = x.head(T.cols());
|
||||
C.row(i) = B.row(i) * Vi;
|
||||
const Scalar lambda = x(T.cols());
|
||||
R(i) = std::sqrt(lambda + C.row(i).squaredNorm());
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::circumradius<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
template void igl::circumradius<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
|
||||
template void igl::circumradius<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 4, 0, -1, 4> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 4, 0, -1, 4> >&);
|
||||
template void igl::circumradius<Eigen::Matrix<double, -1, -1, 1, -1, -1>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 1, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
|
||||
template void igl::circumradius<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 4, 0, -1, 4> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 4, 0, -1, 4> >&);
|
||||
template void igl::circumradius<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
|
||||
template void igl::circumradius<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 4, 0, -1, 4> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 4, 0, -1, 4> >&);
|
||||
template void igl::circumradius<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 4, 0, -1, 4>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 4, 0, -1, 4> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 4, 0, -1, 4> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 4, 0, -1, 4> >&);
|
||||
template void igl::circumradius<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<int, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 1, 0, -1, 1>, Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
|
||||
template void igl::circumradius<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
#endif
|
||||
|
||||
@@ -25,6 +25,26 @@ namespace igl
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
Eigen::PlainObjectBase<DerivedR> & R);
|
||||
/// Generic version
|
||||
///
|
||||
/// @param[in] V #V by dim list of mesh vertex positions
|
||||
/// @param[in] T #T by simplex-size list of simplex indices into V
|
||||
/// @param[out] R #T list of circumradius
|
||||
/// @param[out] C #T by dim list of circumcenter
|
||||
/// @param[out] B #T by simplex-size list of barycentric coordinates of circumcenter
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedT,
|
||||
typename DerivedR,
|
||||
typename DerivedC,
|
||||
typename DerivedB>
|
||||
IGL_INLINE void circumradius(
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedT> & T,
|
||||
Eigen::PlainObjectBase<DerivedR> & R,
|
||||
Eigen::PlainObjectBase<DerivedC> & C,
|
||||
Eigen::PlainObjectBase<DerivedB> & B);
|
||||
|
||||
}
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "circumradius.cpp"
|
||||
|
||||
+36
-207
@@ -8,18 +8,25 @@
|
||||
#include "collapse_edge.h"
|
||||
#include "circulation.h"
|
||||
#include "edge_collapse_is_valid.h"
|
||||
#include "decimate_trivial_callbacks.h"
|
||||
#include <vector>
|
||||
|
||||
template <
|
||||
typename Derivedp,
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
typename DerivedE,
|
||||
typename DerivedEMAP,
|
||||
typename DerivedEF,
|
||||
typename DerivedEI>
|
||||
IGL_INLINE bool igl::collapse_edge(
|
||||
const int e,
|
||||
const Eigen::RowVectorXd & p,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
const Eigen::MatrixBase<Derivedp> & p,
|
||||
Eigen::MatrixBase<DerivedV> & V,
|
||||
Eigen::MatrixBase<DerivedF> & F,
|
||||
Eigen::MatrixBase<DerivedE> & E,
|
||||
Eigen::MatrixBase<DerivedEMAP> & EMAP,
|
||||
Eigen::MatrixBase<DerivedEF> & EF,
|
||||
Eigen::MatrixBase<DerivedEI> & EI,
|
||||
int & e1,
|
||||
int & e2,
|
||||
int & f1,
|
||||
@@ -33,19 +40,28 @@ IGL_INLINE bool igl::collapse_edge(
|
||||
e,p,Nsv,Nsf,Ndv,Ndf,V,F,E,EMAP,EF,EI,e1,e2,f1,f2);
|
||||
}
|
||||
|
||||
template
|
||||
<
|
||||
typename Derivedp,
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
typename DerivedE,
|
||||
typename DerivedEMAP,
|
||||
typename DerivedEF,
|
||||
typename DerivedEI>
|
||||
IGL_INLINE bool igl::collapse_edge(
|
||||
const int e,
|
||||
const Eigen::RowVectorXd & p,
|
||||
const Eigen::MatrixBase<Derivedp> & p,
|
||||
/*const*/ std::vector<int> & Nsv,
|
||||
const std::vector<int> & Nsf,
|
||||
/*const*/ std::vector<int> & Ndv,
|
||||
const std::vector<int> & Ndf,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
Eigen::MatrixBase<DerivedV> & V,
|
||||
Eigen::MatrixBase<DerivedF> & F,
|
||||
Eigen::MatrixBase<DerivedE> & E,
|
||||
Eigen::MatrixBase<DerivedEMAP> & EMAP,
|
||||
Eigen::MatrixBase<DerivedEF> & EF,
|
||||
Eigen::MatrixBase<DerivedEI> & EI,
|
||||
int & a_e1,
|
||||
int & a_e2,
|
||||
int & a_f1,
|
||||
@@ -178,196 +194,9 @@ IGL_INLINE bool igl::collapse_edge(
|
||||
return true;
|
||||
}
|
||||
|
||||
IGL_INLINE bool igl::collapse_edge(
|
||||
const int e,
|
||||
const Eigen::RowVectorXd & p,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI)
|
||||
{
|
||||
int e1,e2,f1,f2;
|
||||
return collapse_edge(e,p,V,F,E,EMAP,EF,EI,e1,e2,f1,f2);
|
||||
}
|
||||
|
||||
IGL_INLINE bool igl::collapse_edge(
|
||||
const decimate_cost_and_placement_callback & cost_and_placement,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
igl::min_heap< std::tuple<double,int,int> > & Q,
|
||||
Eigen::VectorXi & EQ,
|
||||
Eigen::MatrixXd & C)
|
||||
{
|
||||
int e,e1,e2,f1,f2;
|
||||
decimate_pre_collapse_callback always_try;
|
||||
decimate_post_collapse_callback never_care;
|
||||
decimate_trivial_callbacks(always_try,never_care);
|
||||
return
|
||||
collapse_edge(
|
||||
cost_and_placement,always_try,never_care,
|
||||
V,F,E,EMAP,EF,EI,Q,EQ,C,e,e1,e2,f1,f2);
|
||||
}
|
||||
|
||||
IGL_INLINE bool igl::collapse_edge(
|
||||
const decimate_cost_and_placement_callback & cost_and_placement,
|
||||
const decimate_pre_collapse_callback & pre_collapse,
|
||||
const decimate_post_collapse_callback & post_collapse,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
igl::min_heap< std::tuple<double,int,int> > & Q,
|
||||
Eigen::VectorXi & EQ,
|
||||
Eigen::MatrixXd & C)
|
||||
{
|
||||
int e,e1,e2,f1,f2;
|
||||
return
|
||||
collapse_edge(
|
||||
cost_and_placement,pre_collapse,post_collapse,
|
||||
V,F,E,EMAP,EF,EI,Q,EQ,C,e,e1,e2,f1,f2);
|
||||
}
|
||||
|
||||
|
||||
IGL_INLINE bool igl::collapse_edge(
|
||||
const decimate_cost_and_placement_callback & cost_and_placement,
|
||||
const decimate_pre_collapse_callback & pre_collapse,
|
||||
const decimate_post_collapse_callback & post_collapse,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
igl::min_heap< std::tuple<double,int,int> > & Q,
|
||||
Eigen::VectorXi & EQ,
|
||||
Eigen::MatrixXd & C,
|
||||
int & e,
|
||||
int & e1,
|
||||
int & e2,
|
||||
int & f1,
|
||||
int & f2)
|
||||
{
|
||||
using namespace Eigen;
|
||||
using namespace igl;
|
||||
std::tuple<double,int,int> p;
|
||||
while(true)
|
||||
{
|
||||
// Check if Q is empty
|
||||
if(Q.empty())
|
||||
{
|
||||
// no edges to collapse
|
||||
e = -1;
|
||||
return false;
|
||||
}
|
||||
// pop from Q
|
||||
p = Q.top();
|
||||
if(std::get<0>(p) == std::numeric_limits<double>::infinity())
|
||||
{
|
||||
e = -1;
|
||||
// min cost edge is infinite cost
|
||||
return false;
|
||||
}
|
||||
Q.pop();
|
||||
e = std::get<1>(p);
|
||||
// Check if matches timestamp
|
||||
if(std::get<2>(p) == EQ(e))
|
||||
{
|
||||
break;
|
||||
}
|
||||
// must be stale or dead.
|
||||
assert(std::get<2>(p) < EQ(e) || EQ(e) == -1);
|
||||
// try again.
|
||||
}
|
||||
|
||||
// Why is this computed up here?
|
||||
// If we just need original face neighbors of edge, could we gather that more
|
||||
// directly than gathering face neighbors of each vertex?
|
||||
std::vector<int> /*Nse,*/Nsf,Nsv;
|
||||
circulation(e, true,F,EMAP,EF,EI,/*Nse,*/Nsv,Nsf);
|
||||
std::vector<int> /*Nde,*/Ndf,Ndv;
|
||||
circulation(e, false,F,EMAP,EF,EI,/*Nde,*/Ndv,Ndf);
|
||||
|
||||
|
||||
bool collapsed = true;
|
||||
if(pre_collapse(V,F,E,EMAP,EF,EI,Q,EQ,C,e))
|
||||
{
|
||||
collapsed = collapse_edge(
|
||||
e,C.row(e),
|
||||
Nsv,Nsf,Ndv,Ndf,
|
||||
V,F,E,EMAP,EF,EI,e1,e2,f1,f2);
|
||||
}else
|
||||
{
|
||||
// Aborted by pre collapse callback
|
||||
collapsed = false;
|
||||
}
|
||||
post_collapse(V,F,E,EMAP,EF,EI,Q,EQ,C,e,e1,e2,f1,f2,collapsed);
|
||||
if(collapsed)
|
||||
{
|
||||
// Erase the two, other collapsed edges by marking their timestamps as -1
|
||||
EQ(e1) = -1;
|
||||
EQ(e2) = -1;
|
||||
// TODO: visits edges multiple times, ~150% more updates than should
|
||||
//
|
||||
// update local neighbors
|
||||
// loop over original face neighbors
|
||||
//
|
||||
// Can't use previous computed Nse and Nde because those refer to EMAP
|
||||
// before it was changed...
|
||||
std::vector<int> Nf;
|
||||
Nf.reserve( Nsf.size() + Ndf.size() ); // preallocate memory
|
||||
Nf.insert( Nf.end(), Nsf.begin(), Nsf.end() );
|
||||
Nf.insert( Nf.end(), Ndf.begin(), Ndf.end() );
|
||||
// https://stackoverflow.com/a/1041939/148668
|
||||
std::sort( Nf.begin(), Nf.end() );
|
||||
Nf.erase( std::unique( Nf.begin(), Nf.end() ), Nf.end() );
|
||||
// Collect all edges that must be updated
|
||||
std::vector<int> Ne;
|
||||
Ne.reserve(3*Nf.size());
|
||||
for(auto & n : Nf)
|
||||
{
|
||||
if(F(n,0) != IGL_COLLAPSE_EDGE_NULL ||
|
||||
F(n,1) != IGL_COLLAPSE_EDGE_NULL ||
|
||||
F(n,2) != IGL_COLLAPSE_EDGE_NULL)
|
||||
{
|
||||
for(int v = 0;v<3;v++)
|
||||
{
|
||||
// get edge id
|
||||
const int ei = EMAP(v*F.rows()+n);
|
||||
Ne.push_back(ei);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Only process edge once
|
||||
std::sort( Ne.begin(), Ne.end() );
|
||||
Ne.erase( std::unique( Ne.begin(), Ne.end() ), Ne.end() );
|
||||
for(auto & ei : Ne)
|
||||
{
|
||||
// compute cost and potential placement
|
||||
double cost;
|
||||
RowVectorXd place;
|
||||
cost_and_placement(ei,V,F,E,EMAP,EF,EI,cost,place);
|
||||
// Increment timestamp
|
||||
EQ(ei)++;
|
||||
// Replace in queue
|
||||
Q.emplace(cost,ei,EQ(ei));
|
||||
C.row(ei) = place;
|
||||
}
|
||||
}else
|
||||
{
|
||||
// reinsert with infinite weight (the provided cost function must **not**
|
||||
// have given this un-collapsable edge inf cost already)
|
||||
// Increment timestamp
|
||||
EQ(e)++;
|
||||
// Replace in queue
|
||||
Q.emplace(std::numeric_limits<double>::infinity(),e,EQ(e));
|
||||
}
|
||||
return collapsed;
|
||||
}
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
template bool igl::collapse_edge<Eigen::Matrix<double, 1, -1, 1, 1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>>(int, Eigen::MatrixBase<Eigen::Matrix<double, 1, -1, 1, 1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, int&, int&, int&, int&);
|
||||
template bool igl::collapse_edge<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>>(int, Eigen::MatrixBase<Eigen::Block<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 1, -1, false>> const&, std::vector<int, std::allocator<int>>&, std::vector<int, std::allocator<int>> const&, std::vector<int, std::allocator<int>>&, std::vector<int, std::allocator<int>> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>>&, int&, int&, int&, int&);
|
||||
#endif
|
||||
|
||||
+96
-116
@@ -8,18 +8,11 @@
|
||||
#ifndef IGL_COLLAPSE_EDGE_H
|
||||
#define IGL_COLLAPSE_EDGE_H
|
||||
#include "igl_inline.h"
|
||||
#include "min_heap.h"
|
||||
#include "decimate_callback_types.h"
|
||||
#include "COLLAPSE_EDGE_NULL.h"
|
||||
#include <Eigen/Core>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
namespace igl
|
||||
{
|
||||
#ifndef IGL_COLLAPSE_EDGE_NULL
|
||||
/// Special value for indicating a null vertex index as the result of a
|
||||
/// collapsed edge.
|
||||
#define IGL_COLLAPSE_EDGE_NULL 0
|
||||
#endif
|
||||
/// Attempt to collapse a given edge of a mesh. Assumes (V,F) is a closed
|
||||
/// manifold mesh (except for previously collapsed faces which should be set
|
||||
/// to: [IGL_COLLAPSE_EDGE_NULL IGL_COLLAPSE_EDGE_NULL
|
||||
@@ -48,15 +41,83 @@ namespace igl
|
||||
/// @param[out] f1 index into F of face collpased on left
|
||||
/// @param[out] f2 index into F of face collpased on right
|
||||
/// @return true if edge was collapsed
|
||||
///
|
||||
///
|
||||
/// Define [s,d] = sort(E(e,:)) so that s<d, then d is "detached" from
|
||||
/// connectivity meaning all faces/edges incident on d will now be incident on
|
||||
/// s. (This reduces fragmentation by preferring to collapse toward the start
|
||||
/// of V)¹. If E(e,1)==s then we say the edge is "flipped" (`eflip` true in
|
||||
/// the implementation).
|
||||
///
|
||||
/// f1 is set to EF(e,0) and f2 is set to EF(e,1). Let v1 be EI(e,0) the
|
||||
/// corner of F(f1,:) opposite e. _If_ (s<d) then e1 will be the edge after e
|
||||
/// within f1:
|
||||
///
|
||||
/// s<d
|
||||
/// ✅s----e-----d☠️
|
||||
/// \ ← /
|
||||
/// \ ↘f₁↗ /
|
||||
/// e₁ /
|
||||
/// \ /
|
||||
/// \/
|
||||
///
|
||||
/// _If_ (s>d) then e1 will be the edge after e within f1:
|
||||
///
|
||||
/// s>d
|
||||
/// ✅s----e-----d☠️
|
||||
/// \ ← /
|
||||
/// \ ↘f₁↗ /
|
||||
/// \ e₁
|
||||
/// \ /
|
||||
/// \/
|
||||
///
|
||||
///
|
||||
/// ¹Or at least it would if we templated these functions to allow using
|
||||
/// RowMajor V.
|
||||
///
|
||||
/// It really seems that this callback should provide a meaningful edge on the
|
||||
/// _new_ mesh. Meanwhile – Oof – You can use this gross mechanism to find the faces incident on the
|
||||
/// collapsed vertex:
|
||||
///
|
||||
/// ```cpp
|
||||
/// const auto survivors =
|
||||
/// [&F,&e,&EMAP](const int f1, const int e1, int & d1)
|
||||
/// {
|
||||
/// for(int c=0;c<3;c++)
|
||||
/// {
|
||||
/// d1 = EMAP(f1+c*F.rows());
|
||||
/// if((d1 != e) && (d1 != e1)) { break; }
|
||||
/// }
|
||||
/// };
|
||||
/// int d1,d2;
|
||||
/// survivors(f1,e1,d1);
|
||||
/// survivors(f2,e2,d2);
|
||||
/// // Will circulating by continuing in the CCW direction of E(d1,:)
|
||||
/// // encircle the common edge? That is, is E(d1,1) the common vertex?
|
||||
/// const bool ccw = E(d1,1) == E(d2,0) || E(d1,1) == E(d2,1);
|
||||
/// std::vector<int> Nf;
|
||||
/// {
|
||||
/// std::vector<int> Nv;
|
||||
/// igl::circulation(d1,ccw,F,EMAP,EF,EI,Nv,Nf);
|
||||
/// }
|
||||
/// ```
|
||||
template <
|
||||
typename Derivedp,
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
typename DerivedE,
|
||||
typename DerivedEMAP,
|
||||
typename DerivedEF,
|
||||
typename DerivedEI>
|
||||
IGL_INLINE bool collapse_edge(
|
||||
const int e,
|
||||
const Eigen::RowVectorXd & p,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
const Eigen::MatrixBase<Derivedp> & p,
|
||||
Eigen::MatrixBase<DerivedV> & V,
|
||||
Eigen::MatrixBase<DerivedF> & F,
|
||||
Eigen::MatrixBase<DerivedE> & E,
|
||||
Eigen::MatrixBase<DerivedEMAP> & EMAP,
|
||||
Eigen::MatrixBase<DerivedEF> & EF,
|
||||
Eigen::MatrixBase<DerivedEI> & EI,
|
||||
int & e1,
|
||||
int & e2,
|
||||
int & f1,
|
||||
@@ -67,113 +128,32 @@ namespace igl
|
||||
/// @param[in] Nsf #Nsf face circulation around s
|
||||
/// @param[in] Ndv #Ndv vertex circulation around d
|
||||
/// @param[in] Ndf #Ndf face circulation around d
|
||||
template
|
||||
<
|
||||
typename Derivedp,
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
typename DerivedE,
|
||||
typename DerivedEMAP,
|
||||
typename DerivedEF,
|
||||
typename DerivedEI>
|
||||
IGL_INLINE bool collapse_edge(
|
||||
const int e,
|
||||
const Eigen::RowVectorXd & p,
|
||||
const Eigen::MatrixBase<Derivedp> & p,
|
||||
/*const*/ std::vector<int> & Nsv,
|
||||
const std::vector<int> & Nsf,
|
||||
/*const*/ std::vector<int> & Ndv,
|
||||
const std::vector<int> & Ndf,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
int & e1,
|
||||
int & e2,
|
||||
int & f1,
|
||||
int & f2);
|
||||
/// \overload
|
||||
IGL_INLINE bool collapse_edge(
|
||||
const int e,
|
||||
const Eigen::RowVectorXd & p,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI);
|
||||
/// Collapse least-cost edge from a priority queue and update queue
|
||||
///
|
||||
/// See decimate.h for more details.
|
||||
///
|
||||
/// @param[in] cost_and_placement function computing cost of collapsing an edge and 3d
|
||||
/// position where it should be placed:
|
||||
/// cost_and_placement(V,F,E,EMAP,EF,EI,cost,placement);
|
||||
/// **If the edges is collapsed** then this function will be called on all
|
||||
/// edges of all faces previously incident on the endpoints of the
|
||||
/// collapsed edge.
|
||||
/// @param[in] pre_collapse callback called with index of edge whose collapse is about
|
||||
/// to be attempted. This function should return whether to **proceed**
|
||||
/// with the collapse: returning true means "yes, try to collapse",
|
||||
/// returning false means "No, consider this edge 'uncollapsable', behave
|
||||
/// as if collapse_edge(e) returned false.
|
||||
/// @param[in] post_collapse callback called with index of edge whose collapse was
|
||||
/// just attempted and a flag revealing whether this was successful.
|
||||
/// @param[in,out] V #V by dim list of vertex positions, lesser index of E(e,:) will be set
|
||||
/// to midpoint of edge.
|
||||
/// @param[in,out] F #F by 3 list of face indices into V.
|
||||
/// @param[in,out] E #E by 2 list of edge indices into V.
|
||||
/// @param[in,out] EMAP #F*3 list of indices into E, mapping each directed edge to unique
|
||||
/// unique edge in E
|
||||
/// @param[in,out] EF #E by 2 list of edge flaps, EF(e,0)=f means e=(i-->j) is the edge of
|
||||
/// F(f,:) opposite the vth corner, where EI(e,0)=v. Similarly EF(e,1)
|
||||
/// e=(j->i)
|
||||
/// @param[in,out] EI #E by 2 list of edge flap corners (see above).
|
||||
/// @param[in] Q queue containing pairs of costs and edge indices and insertion "time"
|
||||
/// @param[in] EQ #E list of "time" of last time pushed into Q
|
||||
/// @param[in] C #E by dim list of stored placements
|
||||
/// @param[out] e index into E of attempted collapsed edge. Set to -1 if Q is empty or
|
||||
/// contains only infinite cost edges.
|
||||
/// @param[out] e1 index into E of edge collpased on left.
|
||||
/// @param[out] e2 index into E of edge collpased on right.
|
||||
/// @param[out] f1 index into F of face collpased on left.
|
||||
/// @param[out] f2 index into F of face collpased on right.
|
||||
IGL_INLINE bool collapse_edge(
|
||||
const decimate_cost_and_placement_callback & cost_and_placement,
|
||||
const decimate_pre_collapse_callback & pre_collapse,
|
||||
const decimate_post_collapse_callback & post_collapse,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
igl::min_heap< std::tuple<double,int,int> > & Q,
|
||||
Eigen::VectorXi & EQ,
|
||||
Eigen::MatrixXd & C,
|
||||
int & e,
|
||||
int & e1,
|
||||
int & e2,
|
||||
int & f1,
|
||||
int & f2);
|
||||
/// \overload
|
||||
IGL_INLINE bool collapse_edge(
|
||||
const decimate_cost_and_placement_callback & cost_and_placement,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
igl::min_heap< std::tuple<double,int,int> > & Q,
|
||||
Eigen::VectorXi & EQ,
|
||||
Eigen::MatrixXd & C);
|
||||
/// \overload
|
||||
IGL_INLINE bool collapse_edge(
|
||||
const decimate_cost_and_placement_callback & cost_and_placement,
|
||||
const decimate_pre_collapse_callback & pre_collapse,
|
||||
const decimate_post_collapse_callback & post_collapse,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
igl::min_heap< std::tuple<double,int,int> > & Q,
|
||||
Eigen::VectorXi & EQ,
|
||||
Eigen::MatrixXd & C);
|
||||
Eigen::MatrixBase<DerivedV> & V,
|
||||
Eigen::MatrixBase<DerivedF> & F,
|
||||
Eigen::MatrixBase<DerivedE> & E,
|
||||
Eigen::MatrixBase<DerivedEMAP> & EMAP,
|
||||
Eigen::MatrixBase<DerivedEF> & EF,
|
||||
Eigen::MatrixBase<DerivedEI> & EI,
|
||||
int & a_e1,
|
||||
int & a_e2,
|
||||
int & a_f1,
|
||||
int & a_f2);
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
#include "collapse_edge_would_create_intersections.h"
|
||||
#include "AABB.h"
|
||||
#include "circulation.h"
|
||||
#include "writePLY.h"
|
||||
#include "triangle_triangle_intersect.h"
|
||||
#include <Eigen/Geometry>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
|
||||
template <
|
||||
typename Derivedp,
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
typename DerivedE,
|
||||
typename DerivedEMAP,
|
||||
typename DerivedEF,
|
||||
typename DerivedEI>
|
||||
IGL_INLINE bool igl::collapse_edge_would_create_intersections(
|
||||
const int e,
|
||||
const Eigen::MatrixBase<Derivedp> & p,
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
const Eigen::MatrixBase<DerivedE> & E,
|
||||
const Eigen::MatrixBase<DerivedEMAP> & EMAP,
|
||||
const Eigen::MatrixBase<DerivedEF> & EF,
|
||||
const Eigen::MatrixBase<DerivedEI> & EI,
|
||||
const igl::AABB<DerivedV,3> & tree,
|
||||
const int inf_face_id)
|
||||
{
|
||||
// Merge two lists of integers
|
||||
const auto merge = [&](
|
||||
const std::vector<int> & A, const std::vector<int> & B)->
|
||||
std::vector<int>
|
||||
{
|
||||
std::vector<int> C;
|
||||
C.reserve( A.size() + B.size() ); // preallocate memory
|
||||
C.insert( C.end(), A.begin(), A.end() );
|
||||
C.insert( C.end(), B.begin(), B.end() );
|
||||
// https://stackoverflow.com/a/1041939/148668
|
||||
std::sort( C.begin(), C.end() );
|
||||
C.erase( std::unique( C.begin(), C.end() ), C.end() );
|
||||
return C;
|
||||
};
|
||||
|
||||
std::vector<int> old_one_ring;
|
||||
{
|
||||
std::vector<int> Nsv,Nsf,Ndv,Ndf;
|
||||
igl::circulation(e, true,F,EMAP,EF,EI,Nsv,Nsf);
|
||||
igl::circulation(e,false,F,EMAP,EF,EI,Ndv,Ndf);
|
||||
old_one_ring = merge(Nsf,Ndf);
|
||||
}
|
||||
int f1 = EF(e,0);
|
||||
int f2 = EF(e,1);
|
||||
std::vector<int> new_one_ring = old_one_ring;
|
||||
// erase if ==f1 or ==f2
|
||||
new_one_ring.erase(
|
||||
std::remove(new_one_ring.begin(), new_one_ring.end(), f1),
|
||||
new_one_ring.end());
|
||||
new_one_ring.erase(
|
||||
std::remove(new_one_ring.begin(), new_one_ring.end(), f2),
|
||||
new_one_ring.end());
|
||||
|
||||
|
||||
// big box containing new_one_ring
|
||||
Eigen::AlignedBox<double,3> big_box;
|
||||
// Extend box by placement point
|
||||
big_box.extend(p.transpose());
|
||||
// Extend box by all other corners (skipping old edge vertices)
|
||||
for(const auto f : new_one_ring)
|
||||
{
|
||||
Eigen::RowVector3d corners[3];
|
||||
for(int c = 0;c<3;c++)
|
||||
{
|
||||
if(F(f,c) == E(e,0) || F(f,c) == E(e,1))
|
||||
{
|
||||
corners[c] = p;
|
||||
}else
|
||||
{
|
||||
corners[c] = V.row(F(f,c));
|
||||
big_box.extend(V.row(F(f,c)).transpose());
|
||||
}
|
||||
}
|
||||
// Degenerate triangles are considered intersections
|
||||
if((corners[0]-corners[1]).cross(corners[0]-corners[2]).squaredNorm() < 1e-16)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<const igl::AABB<Eigen::MatrixXd,3>*> candidates;
|
||||
tree.append_intersecting_leaves(big_box,candidates);
|
||||
|
||||
|
||||
// Exclude any candidates that are in old_one_ring.
|
||||
// consider using unordered_set above so that this is O(n+m) rather than O(nm)
|
||||
candidates.erase(
|
||||
std::remove_if(candidates.begin(), candidates.end(),
|
||||
[&](const igl::AABB<Eigen::MatrixXd,3>* candidate) {
|
||||
return std::find(old_one_ring.begin(), old_one_ring.end(), candidate->m_primitive) != old_one_ring.end();
|
||||
}),
|
||||
candidates.end());
|
||||
// print candidates
|
||||
//const bool stinker = e==2581;
|
||||
constexpr bool stinker = false;
|
||||
if(stinker)
|
||||
{
|
||||
igl::writePLY("before.ply",V,F);
|
||||
std::cout<<"Ee = ["<<E(e,0)<<" "<<E(e,1)<<"]+1;"<<std::endl;
|
||||
std::cout<<"p = ["<<p<<"];"<<std::endl;
|
||||
// print new_one_ring as matlab vector of indices
|
||||
std::cout<<"new_one_ring = [";
|
||||
for(const auto f : new_one_ring)
|
||||
{
|
||||
std::cout<<f<<" ";
|
||||
}
|
||||
std::cout<<"]+1;"<<std::endl;
|
||||
// print candidates as matlab vector of indices
|
||||
std::cout<<"candidates = [";
|
||||
for(const auto * candidate : candidates)
|
||||
{
|
||||
std::cout<<candidate->m_primitive<<" ";
|
||||
}
|
||||
std::cout<<"]+1;"<<std::endl;
|
||||
}
|
||||
|
||||
// For each pair of candidate and new_one_ring, check if they intersect
|
||||
bool found_intersection = false;
|
||||
for(const int & f : new_one_ring)
|
||||
{
|
||||
if(inf_face_id >= 0 && f >= inf_face_id) { continue; }
|
||||
|
||||
Eigen::AlignedBox<double,3> small_box;
|
||||
small_box.extend(p.transpose());
|
||||
for(int c = 0;c<3;c++)
|
||||
{
|
||||
if(F(f,c) != E(e,0) && F(f,c) != E(e,1))
|
||||
{
|
||||
small_box.extend(V.row(F(f,c)).transpose());
|
||||
}
|
||||
}
|
||||
for(const auto * candidate : candidates)
|
||||
{
|
||||
const int g = candidate->m_primitive;
|
||||
//constexpr bool inner_stinker = false;
|
||||
const bool inner_stinker = stinker && (f==1492 && g==1554);
|
||||
if(inner_stinker){ printf(" f: %d g: %d\n",f,g); }
|
||||
if(!small_box.intersects(candidate->m_box))
|
||||
{
|
||||
if(inner_stinker){ printf(" ✅ boxes don't overlap\n"); }
|
||||
continue;
|
||||
}
|
||||
// Corner replaced by p
|
||||
int c;
|
||||
for(c = 0;c<3;c++)
|
||||
{
|
||||
if(F(f,c) == E(e,0) || F(f,c) == E(e,1))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(c<3);
|
||||
found_intersection = triangle_triangle_intersect(V,F,E,EMAP,EF,f,c,p,g);
|
||||
if(found_intersection) { break; }
|
||||
}
|
||||
if(found_intersection) { break; }
|
||||
}
|
||||
return found_intersection;
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
template bool igl::collapse_edge_would_create_intersections<Eigen::Matrix<double, 1, -1, 1, 1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, 1, 0, -1, 1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>, Eigen::Matrix<int, -1, -1, 0, -1, -1>>(int, Eigen::MatrixBase<Eigen::Matrix<double, 1, -1, 1, 1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, 1, 0, -1, 1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, Eigen::MatrixBase<Eigen::Matrix<int, -1, -1, 0, -1, -1>> const&, igl::AABB<Eigen::Matrix<double, -1, -1, 0, -1, -1>, 3> const&, int);
|
||||
#endif
|
||||
@@ -0,0 +1,53 @@
|
||||
#ifndef IGL_COLLAPSE_EDGE_WOULD_CREATE_INTERSECTIONS_H
|
||||
#define IGL_COLLAPSE_EDGE_WOULD_CREATE_INTERSECTIONS_H
|
||||
#include "igl_inline.h"
|
||||
#include <Eigen/Core>
|
||||
namespace igl
|
||||
{
|
||||
/// Determine if collapse the edge `e` would create new intersections.
|
||||
///
|
||||
/// @param[in] e index into E of edge to try to collapse. E(e,:) = [s d] or [d s] so
|
||||
/// that s<d, then d is collapsed to s.
|
||||
/// @param[in] p dim list of vertex position where to place merged vertex
|
||||
/// [mesh inputs]
|
||||
/// @param[in,out] V #V by dim list of vertex positions, lesser index of E(e,:) will be set
|
||||
/// to midpoint of edge.
|
||||
/// @param[in,out] F #F by 3 list of face indices into V.
|
||||
/// @param[in,out] E #E by 2 list of edge indices into V.
|
||||
/// @param[in,out] EMAP #F*3 list of indices into E, mapping each directed edge to unique
|
||||
/// unique edge in E
|
||||
/// @param[in,out] EF #E by 2 list of edge flaps, EF(e,0)=f means e=(i-->j) is the edge of
|
||||
/// F(f,:) opposite the vth corner, where EI(e,0)=v. Similarly EF(e,1) "
|
||||
/// e=(j->i)
|
||||
/// @param[in,out] EI #E by 2 list of edge flap corners (see above).
|
||||
/// [mesh inputs]
|
||||
/// @param[in] tree AABB tree whose leaves correspond to the current
|
||||
/// (non-null) faces in (V,F)
|
||||
///
|
||||
/// \see collapse_edge
|
||||
template <typename DerivedV, int DIM> class AABB;
|
||||
|
||||
template <
|
||||
typename Derivedp,
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
typename DerivedE,
|
||||
typename DerivedEMAP,
|
||||
typename DerivedEF,
|
||||
typename DerivedEI>
|
||||
IGL_INLINE bool collapse_edge_would_create_intersections(
|
||||
const int e,
|
||||
const Eigen::MatrixBase<Derivedp> & p,
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
const Eigen::MatrixBase<DerivedE> & E,
|
||||
const Eigen::MatrixBase<DerivedEMAP> & EMAP,
|
||||
const Eigen::MatrixBase<DerivedEF> & EF,
|
||||
const Eigen::MatrixBase<DerivedEI> & EI,
|
||||
const igl::AABB<DerivedV,3> & tree,
|
||||
const int inf_face_id = -1);
|
||||
}
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "collapse_edge_would_create_intersections.cpp"
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,148 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2025 Alec Jacobson <alecjacobson@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/.
|
||||
#include "collapse_least_cost_edge.h"
|
||||
#include "collapse_edge.h"
|
||||
#include "circulation.h"
|
||||
|
||||
IGL_INLINE bool igl::collapse_least_cost_edge(
|
||||
const decimate_cost_and_placement_callback & cost_and_placement,
|
||||
const decimate_pre_collapse_callback & pre_collapse,
|
||||
const decimate_post_collapse_callback & post_collapse,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
igl::min_heap< std::tuple<double,int,int> > & Q,
|
||||
Eigen::VectorXi & EQ,
|
||||
Eigen::MatrixXd & C,
|
||||
int & e,
|
||||
int & e1,
|
||||
int & e2,
|
||||
int & f1,
|
||||
int & f2)
|
||||
{
|
||||
using namespace Eigen;
|
||||
using namespace igl;
|
||||
std::tuple<double,int,int> p;
|
||||
while(true)
|
||||
{
|
||||
// Check if Q is empty
|
||||
if(Q.empty())
|
||||
{
|
||||
// no edges to collapse
|
||||
e = -1;
|
||||
return false;
|
||||
}
|
||||
// pop from Q
|
||||
p = Q.top();
|
||||
if(std::get<0>(p) == std::numeric_limits<double>::infinity())
|
||||
{
|
||||
e = -1;
|
||||
// min cost edge is infinite cost
|
||||
return false;
|
||||
}
|
||||
Q.pop();
|
||||
e = std::get<1>(p);
|
||||
// Check if matches timestamp
|
||||
if(std::get<2>(p) == EQ(e))
|
||||
{
|
||||
break;
|
||||
}
|
||||
// must be stale or dead.
|
||||
assert(std::get<2>(p) < EQ(e) || EQ(e) == -1);
|
||||
// try again.
|
||||
}
|
||||
|
||||
// Why is this computed up here?
|
||||
// If we just need original face neighbors of edge, could we gather that more
|
||||
// directly than gathering face neighbors of each vertex?
|
||||
std::vector<int> /*Nse,*/Nsf,Nsv;
|
||||
circulation(e, true,F,EMAP,EF,EI,/*Nse,*/Nsv,Nsf);
|
||||
std::vector<int> /*Nde,*/Ndf,Ndv;
|
||||
circulation(e, false,F,EMAP,EF,EI,/*Nde,*/Ndv,Ndf);
|
||||
|
||||
|
||||
bool collapsed = true;
|
||||
if(pre_collapse(V,F,E,EMAP,EF,EI,Q,EQ,C,e))
|
||||
{
|
||||
collapsed = collapse_edge(
|
||||
e,C.row(e),
|
||||
Nsv,Nsf,Ndv,Ndf,
|
||||
V,F,E,EMAP,EF,EI,e1,e2,f1,f2);
|
||||
}else
|
||||
{
|
||||
// Aborted by pre collapse callback
|
||||
collapsed = false;
|
||||
}
|
||||
post_collapse(V,F,E,EMAP,EF,EI,Q,EQ,C,e,e1,e2,f1,f2,collapsed);
|
||||
if(collapsed)
|
||||
{
|
||||
// Erase the center edge, marking its timestamp as -1
|
||||
EQ(e) = -1;
|
||||
// Erase the two, other collapsed edges by marking their timestamps as -1
|
||||
EQ(e1) = -1;
|
||||
EQ(e2) = -1;
|
||||
// TODO: visits edges multiple times, ~150% more updates than should
|
||||
//
|
||||
// update local neighbors
|
||||
// loop over original face neighbors
|
||||
//
|
||||
// Can't use previous computed Nse and Nde because those refer to EMAP
|
||||
// before it was changed...
|
||||
std::vector<int> Nf;
|
||||
Nf.reserve( Nsf.size() + Ndf.size() ); // preallocate memory
|
||||
Nf.insert( Nf.end(), Nsf.begin(), Nsf.end() );
|
||||
Nf.insert( Nf.end(), Ndf.begin(), Ndf.end() );
|
||||
// https://stackoverflow.com/a/1041939/148668
|
||||
std::sort( Nf.begin(), Nf.end() );
|
||||
Nf.erase( std::unique( Nf.begin(), Nf.end() ), Nf.end() );
|
||||
// Collect all edges that must be updated
|
||||
std::vector<int> Ne;
|
||||
Ne.reserve(3*Nf.size());
|
||||
for(auto & n : Nf)
|
||||
{
|
||||
if(F(n,0) != IGL_COLLAPSE_EDGE_NULL ||
|
||||
F(n,1) != IGL_COLLAPSE_EDGE_NULL ||
|
||||
F(n,2) != IGL_COLLAPSE_EDGE_NULL)
|
||||
{
|
||||
for(int v = 0;v<3;v++)
|
||||
{
|
||||
// get edge id
|
||||
const int ei = EMAP(v*F.rows()+n);
|
||||
Ne.push_back(ei);
|
||||
}
|
||||
}
|
||||
}
|
||||
// Only process edge once
|
||||
std::sort( Ne.begin(), Ne.end() );
|
||||
Ne.erase( std::unique( Ne.begin(), Ne.end() ), Ne.end() );
|
||||
for(auto & ei : Ne)
|
||||
{
|
||||
// compute cost and potential placement
|
||||
double cost;
|
||||
RowVectorXd place;
|
||||
cost_and_placement(ei,V,F,E,EMAP,EF,EI,cost,place);
|
||||
// Increment timestamp
|
||||
EQ(ei)++;
|
||||
// Replace in queue
|
||||
Q.emplace(cost,ei,EQ(ei));
|
||||
C.row(ei) = place;
|
||||
}
|
||||
}else
|
||||
{
|
||||
// reinsert with infinite weight (the provided cost function must **not**
|
||||
// have given this un-collapsable edge inf cost already)
|
||||
// Increment timestamp
|
||||
EQ(e)++;
|
||||
// Replace in queue
|
||||
Q.emplace(std::numeric_limits<double>::infinity(),e,EQ(e));
|
||||
}
|
||||
return collapsed;
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
// This file is part of libigl, a simple c++ geometry processing library.
|
||||
//
|
||||
// Copyright (C) 2015 Alec Jacobson <alecjacobson@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_COLLAPSE_LEAST_COST_EDGE_H
|
||||
#define IGL_COLLAPSE_LEAST_COST_EDGE_H
|
||||
#include "igl_inline.h"
|
||||
#include "min_heap.h"
|
||||
#include "decimate_callback_types.h"
|
||||
#include "COLLAPSE_EDGE_NULL.h"
|
||||
#include <Eigen/Core>
|
||||
#include <vector>
|
||||
namespace igl
|
||||
{
|
||||
/// Collapse least-cost edge from a priority queue and update queue
|
||||
///
|
||||
/// See decimate.h for more details.
|
||||
///
|
||||
/// @param[in] cost_and_placement function computing cost of collapsing an edge and 3d
|
||||
/// position where it should be placed:
|
||||
/// cost_and_placement(V,F,E,EMAP,EF,EI,cost,placement);
|
||||
/// **If the edges is collapsed** then this function will be called on all
|
||||
/// edges of all faces previously incident on the endpoints of the
|
||||
/// collapsed edge.
|
||||
/// @param[in] pre_collapse callback called with index of edge whose collapse is about
|
||||
/// to be attempted. This function should return whether to **proceed**
|
||||
/// with the collapse: returning true means "yes, try to collapse",
|
||||
/// returning false means "No, consider this edge 'uncollapsable', behave
|
||||
/// as if collapse_edge(e) returned false.
|
||||
/// @param[in] post_collapse callback called with index of edge whose collapse was
|
||||
/// just attempted and a flag revealing whether this was successful.
|
||||
/// @param[in,out] V #V by dim list of vertex positions, lesser index of E(e,:) will be set
|
||||
/// to midpoint of edge.
|
||||
/// @param[in,out] F #F by 3 list of face indices into V.
|
||||
/// @param[in,out] E #E by 2 list of edge indices into V.
|
||||
/// @param[in,out] EMAP #F*3 list of indices into E, mapping each directed edge to unique
|
||||
/// unique edge in E
|
||||
/// @param[in,out] EF #E by 2 list of edge flaps, EF(e,0)=f means e=(i-->j) is the edge of
|
||||
/// F(f,:) opposite the vth corner, where EI(e,0)=v. Similarly EF(e,1)
|
||||
/// e=(j->i)
|
||||
/// @param[in,out] EI #E by 2 list of edge flap corners (see above).
|
||||
/// @param[in] Q queue containing pairs of costs and edge indices and insertion "time"
|
||||
/// @param[in] EQ #E list of "time" of last time pushed into Q
|
||||
/// @param[in] C #E by dim list of stored placements
|
||||
/// @param[out] e index into E of attempted collapsed edge. Set to -1 if Q is empty or
|
||||
/// contains only infinite cost edges.
|
||||
/// @param[out] e1 index into E of edge collpased on left.
|
||||
/// @param[out] e2 index into E of edge collpased on right.
|
||||
/// @param[out] f1 index into F of face collpased on left.
|
||||
/// @param[out] f2 index into F of face collpased on right.
|
||||
///
|
||||
/// \bug This function is not templated nicely and refactoring it and its
|
||||
/// dependencies to do so is non-trivial, see
|
||||
/// https://github.com/libigl/libigl/issues/2452
|
||||
IGL_INLINE bool collapse_least_cost_edge(
|
||||
const decimate_cost_and_placement_callback & cost_and_placement,
|
||||
const decimate_pre_collapse_callback & pre_collapse,
|
||||
const decimate_post_collapse_callback & post_collapse,
|
||||
Eigen::MatrixXd & V,
|
||||
Eigen::MatrixXi & F,
|
||||
Eigen::MatrixXi & E,
|
||||
Eigen::VectorXi & EMAP,
|
||||
Eigen::MatrixXi & EF,
|
||||
Eigen::MatrixXi & EI,
|
||||
igl::min_heap< std::tuple<double,int,int> > & Q,
|
||||
Eigen::VectorXi & EQ,
|
||||
Eigen::MatrixXd & C,
|
||||
int & e,
|
||||
int & e1,
|
||||
int & e2,
|
||||
int & f1,
|
||||
int & f2);
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
# include "collapse_least_cost_edge.cpp"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -17,11 +17,15 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
typename DerivedFF>
|
||||
void igl::collapse_small_triangles(
|
||||
const Eigen::MatrixXd & V,
|
||||
const Eigen::MatrixXi & F,
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
const double eps,
|
||||
Eigen::MatrixXi & FF)
|
||||
Eigen::PlainObjectBase<DerivedFF> & FF)
|
||||
{
|
||||
using namespace Eigen;
|
||||
using namespace std;
|
||||
@@ -92,7 +96,9 @@ void igl::collapse_small_triangles(
|
||||
}
|
||||
|
||||
FF.resizeLike(rF);
|
||||
#ifndef NDEBUG
|
||||
int num_face_collapses=0;
|
||||
#endif
|
||||
// Only keep uncollapsed faces
|
||||
{
|
||||
int ff = 0;
|
||||
@@ -108,7 +114,9 @@ void igl::collapse_small_triangles(
|
||||
if(rF(f,i)==rF(f,j))
|
||||
{
|
||||
collapsed = true;
|
||||
#ifndef NDEBUG
|
||||
num_face_collapses++;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -137,3 +145,8 @@ void igl::collapse_small_triangles(
|
||||
MatrixXi recFF = FF;
|
||||
return collapse_small_triangles(V,recFF,eps,FF);
|
||||
}
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
template void igl::collapse_small_triangles<Eigen::MatrixXd, Eigen::MatrixXi, Eigen::MatrixXi> ( const Eigen::MatrixBase<Eigen::MatrixXd> &, const Eigen::MatrixBase<Eigen::MatrixXi> &, const double , Eigen::PlainObjectBase<Eigen::MatrixXi> & );
|
||||
#endif
|
||||
|
||||
@@ -24,11 +24,15 @@ namespace igl
|
||||
/// @param[out] FF #FF by 3 list of triangle indices into V
|
||||
///
|
||||
///
|
||||
template <
|
||||
typename DerivedV,
|
||||
typename DerivedF,
|
||||
typename DerivedFF>
|
||||
void collapse_small_triangles(
|
||||
const Eigen::MatrixXd & V,
|
||||
const Eigen::MatrixXi & F,
|
||||
const Eigen::MatrixBase<DerivedV> & V,
|
||||
const Eigen::MatrixBase<DerivedF> & F,
|
||||
const double eps,
|
||||
Eigen::MatrixXi & FF);
|
||||
Eigen::PlainObjectBase<DerivedFF> & FF);
|
||||
}
|
||||
|
||||
#ifndef IGL_STATIC_LIBRARY
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
template <typename DerivedA, typename DerivedB>
|
||||
IGL_INLINE void igl::columnize(
|
||||
const Eigen::PlainObjectBase<DerivedA> & A,
|
||||
const Eigen::MatrixBase<DerivedA> & A,
|
||||
const int k,
|
||||
const int dim,
|
||||
Eigen::PlainObjectBase<DerivedB> & B)
|
||||
@@ -56,8 +56,8 @@ IGL_INLINE void igl::columnize(
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
template void igl::columnize<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
|
||||
template void igl::columnize<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
template void igl::columnize<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, int, int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&);
|
||||
template void igl::columnize<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, 1, 0, -1, 1> >(Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, int, int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 1, 0, -1, 1> >&);
|
||||
template void igl::columnize<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 1, 0, -1, 1> >&);
|
||||
template void igl::columnize<Eigen::Matrix<double, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> > const&, int, int, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
template void igl::columnize<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, int, int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> >&);
|
||||
template void igl::columnize<Eigen::Matrix<float, -1, -1, 0, -1, -1>, Eigen::Matrix<float, -1, 1, 0, -1, 1> >(Eigen::MatrixBase<Eigen::Matrix<float, -1, -1, 0, -1, -1> > const&, int, int, Eigen::PlainObjectBase<Eigen::Matrix<float, -1, 1, 0, -1, 1> >&);
|
||||
#endif
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace igl
|
||||
/// \see transpose_blocks
|
||||
template <typename DerivedA, typename DerivedB>
|
||||
IGL_INLINE void columnize(
|
||||
const Eigen::PlainObjectBase<DerivedA> & A,
|
||||
const Eigen::MatrixBase<DerivedA> & A,
|
||||
const int k,
|
||||
const int dim,
|
||||
Eigen::PlainObjectBase<DerivedB> & B);
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
#include "per_face_normals.h"
|
||||
#include "is_border_vertex.h"
|
||||
#include "rotation_matrix_from_directions.h"
|
||||
#include "PlainMatrix.h"
|
||||
|
||||
#include "triangle_triangle_adjacency.h"
|
||||
|
||||
@@ -27,12 +28,12 @@ namespace igl {
|
||||
const Eigen::MatrixBase<DerivedF> &F;
|
||||
const Eigen::MatrixBase<DerivedV> &PD1;
|
||||
const Eigen::MatrixBase<DerivedV> &PD2;
|
||||
DerivedV N;
|
||||
PlainMatrix<DerivedV> N;
|
||||
|
||||
private:
|
||||
// internal
|
||||
DerivedF TT;
|
||||
DerivedF TTi;
|
||||
PlainMatrix<DerivedF> TT;
|
||||
PlainMatrix<DerivedF> TTi;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -14,18 +14,20 @@
|
||||
#include "comb_frame_field.h"
|
||||
#include "local_basis.h"
|
||||
#include "PI.h"
|
||||
#include "PlainMatrix.h"
|
||||
|
||||
template <typename DerivedV, typename DerivedF, typename DerivedP>
|
||||
IGL_INLINE void igl::comb_frame_field(const Eigen::MatrixBase<DerivedV> &V,
|
||||
const Eigen::MatrixBase<DerivedF> &F,
|
||||
const Eigen::MatrixBase<DerivedP> &PD1,
|
||||
const Eigen::MatrixBase<DerivedP> &PD2,
|
||||
const Eigen::MatrixBase<DerivedP> &BIS1_combed,
|
||||
const Eigen::MatrixBase<DerivedP> &BIS2_combed,
|
||||
Eigen::PlainObjectBase<DerivedP> &PD1_combed,
|
||||
Eigen::PlainObjectBase<DerivedP> &PD2_combed)
|
||||
IGL_INLINE void igl::comb_frame_field(
|
||||
const Eigen::MatrixBase<DerivedV> &V,
|
||||
const Eigen::MatrixBase<DerivedF> &F,
|
||||
const Eigen::MatrixBase<DerivedP> &PD1,
|
||||
const Eigen::MatrixBase<DerivedP> &PD2,
|
||||
const Eigen::MatrixBase<DerivedP> &BIS1_combed,
|
||||
const Eigen::MatrixBase<DerivedP> &BIS2_combed,
|
||||
Eigen::PlainObjectBase<DerivedP> &PD1_combed,
|
||||
Eigen::PlainObjectBase<DerivedP> &PD2_combed)
|
||||
{
|
||||
DerivedV B1, B2, B3;
|
||||
PlainMatrix<DerivedV,Eigen::Dynamic> B1, B2, B3;
|
||||
igl::local_basis(V,F,B1,B2,B3);
|
||||
|
||||
PD1_combed.resize(BIS1_combed.rows(),3);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "rotation_matrix_from_directions.h"
|
||||
|
||||
#include "triangle_triangle_adjacency.h"
|
||||
#include "PlainMatrix.h"
|
||||
|
||||
namespace igl {
|
||||
template <typename DerivedV, typename DerivedF>
|
||||
@@ -25,12 +26,12 @@ public:
|
||||
const Eigen::MatrixBase<DerivedV> &V;
|
||||
const Eigen::MatrixBase<DerivedF> &F;
|
||||
const Eigen::MatrixBase<DerivedV> &PD1;
|
||||
DerivedV N;
|
||||
PlainMatrix<DerivedV> N;
|
||||
|
||||
private:
|
||||
// internal
|
||||
DerivedF TT;
|
||||
DerivedF TTi;
|
||||
PlainMatrix<DerivedF> TT;
|
||||
PlainMatrix<DerivedF> TTi;
|
||||
|
||||
|
||||
private:
|
||||
|
||||
@@ -14,11 +14,12 @@
|
||||
#include "compute_frame_field_bisectors.h"
|
||||
#include "igl/local_basis.h"
|
||||
#include "PI.h"
|
||||
#include "PlainMatrix.h"
|
||||
|
||||
template <typename DerivedV, typename DerivedF>
|
||||
IGL_INLINE void igl::compute_frame_field_bisectors(
|
||||
const Eigen::MatrixBase<DerivedV>& V,
|
||||
const Eigen::MatrixBase<DerivedF>& F,
|
||||
const Eigen::MatrixBase<DerivedV>& /*V*/,
|
||||
const Eigen::MatrixBase<DerivedF>& /*F*/,
|
||||
const Eigen::MatrixBase<DerivedV>& B1,
|
||||
const Eigen::MatrixBase<DerivedV>& B2,
|
||||
const Eigen::MatrixBase<DerivedV>& PD1,
|
||||
@@ -71,7 +72,7 @@ IGL_INLINE void igl::compute_frame_field_bisectors(
|
||||
Eigen::PlainObjectBase<DerivedV>& BIS1,
|
||||
Eigen::PlainObjectBase<DerivedV>& BIS2)
|
||||
{
|
||||
DerivedV B1, B2, B3;
|
||||
PlainMatrix<DerivedV,Eigen::Dynamic> B1, B2, B3;
|
||||
igl::local_basis(V,F,B1,B2,B3);
|
||||
|
||||
compute_frame_field_bisectors( V, F, B1, B2, PD1, PD2, BIS1, BIS2);
|
||||
|
||||
@@ -23,6 +23,8 @@ namespace igl
|
||||
/// @param[out] BIS1 #F by 3 eigen Matrix of the first per face frame field bisector
|
||||
/// @param[out] BIS2 #F by 3 eigen Matrix of the second per face frame field bisector
|
||||
///
|
||||
/// \bug `V` and `F` are not used. If this function is actually being used we
|
||||
/// should remove `V` and `F` here.
|
||||
template <typename DerivedV, typename DerivedF>
|
||||
IGL_INLINE void compute_frame_field_bisectors(
|
||||
const Eigen::MatrixBase<DerivedV>& V,
|
||||
|
||||
@@ -25,7 +25,6 @@ IGL_INLINE void igl::connect_boundary_to_infinity(
|
||||
Eigen::Matrix<typename DerivedFO::Scalar,Eigen::Dynamic,Eigen::Dynamic> O;
|
||||
boundary_facets(F,O);
|
||||
FO.resize(F.rows()+O.rows(),F.cols());
|
||||
typedef Eigen::Matrix<typename DerivedFO::Scalar,Eigen::Dynamic,1> VectorXI;
|
||||
FO.topLeftCorner(F.rows(),F.cols()) = F;
|
||||
FO.bottomLeftCorner(O.rows(),O.cols()) = O.rowwise().reverse();
|
||||
FO.bottomRightCorner(O.rows(),1).setConstant(inf_index);
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace igl
|
||||
public:
|
||||
template<typename DerivedW>
|
||||
typename DerivedW::Scalar operator()(
|
||||
const Eigen::PlainObjectBase<DerivedW>& /*win_nums*/) const {
|
||||
const Eigen::MatrixBase<DerivedW>& /*win_nums*/) const {
|
||||
throw (std::runtime_error("not implemented!"));
|
||||
}
|
||||
};
|
||||
@@ -43,7 +43,7 @@ namespace igl
|
||||
public:
|
||||
template<typename DerivedW>
|
||||
typename DerivedW::Scalar operator()(
|
||||
const Eigen::PlainObjectBase<DerivedW>& win_nums) const
|
||||
const Eigen::MatrixBase<DerivedW>& win_nums) const
|
||||
{
|
||||
for(int i = 0;i<win_nums.size();i++)
|
||||
{
|
||||
@@ -59,7 +59,7 @@ namespace igl
|
||||
public:
|
||||
template<typename DerivedW>
|
||||
typename DerivedW::Scalar operator()(
|
||||
const Eigen::PlainObjectBase<DerivedW>& win_nums) const
|
||||
const Eigen::MatrixBase<DerivedW>& win_nums) const
|
||||
{
|
||||
for(int i = 0;i<win_nums.size();i++)
|
||||
{
|
||||
@@ -75,7 +75,7 @@ namespace igl
|
||||
public:
|
||||
template<typename DerivedW>
|
||||
typename DerivedW::Scalar operator()(
|
||||
const Eigen::PlainObjectBase<DerivedW>& win_nums) const
|
||||
const Eigen::MatrixBase<DerivedW>& win_nums) const
|
||||
{
|
||||
assert(win_nums.size()>1);
|
||||
// Union of objects 1 through n-1
|
||||
@@ -96,7 +96,7 @@ namespace igl
|
||||
public:
|
||||
template<typename DerivedW>
|
||||
typename DerivedW::Scalar operator()(
|
||||
const Eigen::PlainObjectBase<DerivedW>& win_nums) const
|
||||
const Eigen::MatrixBase<DerivedW>& win_nums) const
|
||||
{
|
||||
// If inside an odd number of objects
|
||||
int count = 0;
|
||||
@@ -114,7 +114,7 @@ namespace igl
|
||||
public:
|
||||
template<typename DerivedW>
|
||||
typename DerivedW::Scalar operator()(
|
||||
const Eigen::PlainObjectBase<DerivedW>& /*win_nums*/) const {
|
||||
const Eigen::MatrixBase<DerivedW>& /*win_nums*/) const {
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -139,7 +139,7 @@ namespace igl
|
||||
public:
|
||||
template<typename DerivedW>
|
||||
short operator()(
|
||||
const Eigen::PlainObjectBase<DerivedW>& /*win_nums*/) const {
|
||||
const Eigen::MatrixBase<DerivedW>& /*win_nums*/) const {
|
||||
throw std::runtime_error("Not implemented");
|
||||
}
|
||||
};
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace igl
|
||||
/// converted to exact)
|
||||
/// @param[in] F #F by 3 list of mesh face indices into V
|
||||
template <typename DerivedV>
|
||||
CSGTree(const Eigen::PlainObjectBase<DerivedV> & V, const POBF & F)//:
|
||||
CSGTree(const Eigen::MatrixBase<DerivedV> & V, const POBF & F)//:
|
||||
// Possible Eigen bug:
|
||||
// https://forum.kde.org/viewtopic.php?f=74&t=128414
|
||||
//m_V(V.template cast<ExactScalar>()),m_F(F)
|
||||
|
||||
@@ -29,16 +29,22 @@ namespace igl
|
||||
bool stitch_all;
|
||||
/// whether to use slow and more precise rounding (see assign_scalar)
|
||||
bool slow_and_more_precise_rounding;
|
||||
/// cutoff parameter for box_self_intersection_d (based on some casual
|
||||
/// testing 1000 works better than 1,10,100,10000 etc. and better than
|
||||
/// the recommended √n)
|
||||
int cutoff;
|
||||
inline RemeshSelfIntersectionsParam(
|
||||
bool _detect_only=false,
|
||||
bool _first_only=false,
|
||||
bool _stitch_all=false,
|
||||
bool _slow_and_more_precise_rounding=false
|
||||
bool _slow_and_more_precise_rounding=false,
|
||||
int _cutoff=1000
|
||||
):
|
||||
detect_only(_detect_only),
|
||||
first_only(_first_only),
|
||||
stitch_all(_stitch_all),
|
||||
slow_and_more_precise_rounding(_slow_and_more_precise_rounding)
|
||||
slow_and_more_precise_rounding(_slow_and_more_precise_rounding),
|
||||
cutoff(_cutoff)
|
||||
{};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -244,7 +244,6 @@ namespace igl
|
||||
#include "mesh_to_cgal_triangle_list.h"
|
||||
#include "remesh_intersections.h"
|
||||
|
||||
#include "../../REDRUM.h"
|
||||
#include "../../get_seconds.h"
|
||||
#include "../../C_STR.h"
|
||||
|
||||
@@ -253,7 +252,6 @@ namespace igl
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
|
||||
// References:
|
||||
// http://minregret.googlecode.com/svn/trunk/skyline/src/extern/CGAL-3.3.1/examples/Polyhedron/polyhedron_self_intersection.cpp
|
||||
@@ -345,7 +343,7 @@ inline igl::copyleft::cgal::SelfIntersectMesh<
|
||||
return diff;
|
||||
};
|
||||
const auto log_time = [&](const std::string& label) -> void{
|
||||
printf("%50s: %0.5lf\n",
|
||||
std::printf("%50s: %0.5lf\n",
|
||||
C_STR("SelfIntersectMesh." << label),tictoc());
|
||||
};
|
||||
tictoc();
|
||||
@@ -380,8 +378,8 @@ inline igl::copyleft::cgal::SelfIntersectMesh<
|
||||
#ifdef IGL_SELFINTERSECTMESH_TIMING
|
||||
log_time("box_and_bind");
|
||||
#endif
|
||||
// Run the self intersection algorithm with all defaults
|
||||
CGAL::box_self_intersection_d(boxes.begin(), boxes.end(),cb);
|
||||
// Run the self intersection algorithm with given cutoff size
|
||||
CGAL::box_self_intersection_d(boxes.begin(), boxes.end(),cb,std::ptrdiff_t(params.cutoff));
|
||||
#ifdef IGL_SELFINTERSECTMESH_TIMING
|
||||
log_time("box_intersection_d");
|
||||
#endif
|
||||
@@ -631,8 +629,8 @@ inline bool igl::copyleft::cgal::SelfIntersectMesh<
|
||||
return true;
|
||||
}else
|
||||
{
|
||||
cerr<<REDRUM("Segment ∩ triangle neither point nor segment?")<<endl;
|
||||
assert(false);
|
||||
// Should never happen.
|
||||
assert(false && "Segment ∩ triangle neither point nor segment?");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,40 @@
|
||||
#include "assign.h"
|
||||
#include "../../parallel_for.h"
|
||||
#include "assign_scalar.h"
|
||||
#include <type_traits>
|
||||
|
||||
namespace igl { namespace copyleft { namespace cgal {
|
||||
// Would be simpler with C++17 `if constexpr`
|
||||
template <bool Simple> struct assign_Helper { };
|
||||
template <> struct assign_Helper<false>
|
||||
{
|
||||
template <typename DerivedC, typename DerivedD>
|
||||
static void run(
|
||||
const Eigen::MatrixBase<DerivedC> & C,
|
||||
const bool slow_and_more_precise,
|
||||
Eigen::PlainObjectBase<DerivedD> & D)
|
||||
{
|
||||
D.resizeLike(C);
|
||||
igl::parallel_for(C.size(),[&](Eigen::Index k)
|
||||
{
|
||||
const Eigen::Index i = k%C.rows();
|
||||
const Eigen::Index j = k/C.rows();
|
||||
assign_scalar(C(i,j),slow_and_more_precise,D(i,j));
|
||||
},1000);
|
||||
}
|
||||
};
|
||||
template <> struct assign_Helper<true>
|
||||
{
|
||||
template <typename DerivedC, typename DerivedD>
|
||||
static void run(
|
||||
const Eigen::MatrixBase<DerivedC> & C,
|
||||
const bool /*slow_and_more_precise*/,
|
||||
Eigen::PlainObjectBase<DerivedD> & D)
|
||||
{
|
||||
D = C.template cast<typename DerivedD::Scalar>();
|
||||
}
|
||||
};
|
||||
} } }
|
||||
|
||||
template <typename DerivedC, typename DerivedD>
|
||||
IGL_INLINE void igl::copyleft::cgal::assign(
|
||||
@@ -15,13 +49,10 @@ IGL_INLINE void igl::copyleft::cgal::assign(
|
||||
const bool slow_and_more_precise,
|
||||
Eigen::PlainObjectBase<DerivedD> & D)
|
||||
{
|
||||
D.resizeLike(C);
|
||||
igl::parallel_for(C.size(),[&](Eigen::Index k)
|
||||
{
|
||||
const Eigen::Index i = k%C.rows();
|
||||
const Eigen::Index j = k/C.rows();
|
||||
assign_scalar(C(i,j),slow_and_more_precise,D(i,j));
|
||||
},1000);
|
||||
using CScalar = typename DerivedC::Scalar;
|
||||
using DScalar = typename DerivedD::Scalar;
|
||||
constexpr bool simple = std::is_assignable<DScalar,CScalar>::value;
|
||||
assign_Helper<simple>::run(C,slow_and_more_precise,D);
|
||||
}
|
||||
template <typename DerivedC, typename DerivedD>
|
||||
IGL_INLINE void igl::copyleft::cgal::assign(
|
||||
@@ -57,6 +88,18 @@ igl::copyleft::cgal::assign(
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::copyleft::cgal::assign<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::copyleft::cgal::assign<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 1, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 1, -1, -1> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::copyleft::cgal::assign<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::copyleft::cgal::assign<Eigen::Matrix<double, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::copyleft::cgal::assign<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 1, -1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 1, -1, 3> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
// generated by autoexplicit.sh
|
||||
template void igl::copyleft::cgal::assign<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> > const&, bool, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
template void igl::copyleft::cgal::assign<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1>, Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<CGAL::Epeck::FT, -1, 3, 0, -1, 3> >&);
|
||||
template void igl::copyleft::cgal::assign<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, -1, 0, -1, -1> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, -1, 0, -1, -1> >&);
|
||||
template void igl::copyleft::cgal::assign<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1>, Eigen::Matrix<double, -1, 3, 0, -1, 3> >(Eigen::MatrixBase<Eigen::Matrix<CGAL::Epeck::FT, -1, -1, 0, -1, -1> > const&, Eigen::PlainObjectBase<Eigen::Matrix<double, -1, 3, 0, -1, 3> >&);
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
// obtain one at http://mozilla.org/MPL/2.0/.
|
||||
#include "assign_scalar.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
template <>
|
||||
IGL_INLINE void igl::copyleft::cgal::assign_scalar(
|
||||
const CGAL::Epeck::FT & rhs,
|
||||
@@ -53,7 +55,7 @@ IGL_INLINE void igl::copyleft::cgal::assign_scalar(
|
||||
template <typename RHS, typename LHS>
|
||||
IGL_INLINE void igl::copyleft::cgal::assign_scalar(
|
||||
const RHS & rhs,
|
||||
const bool & slow_and_more_precise,
|
||||
const bool & /*slow_and_more_precise*/,
|
||||
LHS & lhs)
|
||||
{
|
||||
return assign_scalar(rhs,lhs);
|
||||
@@ -75,7 +77,7 @@ IGL_INLINE void igl::copyleft::cgal::assign_scalar(
|
||||
const auto interval = CGAL::to_interval(cgal);
|
||||
d = interval.first;
|
||||
do {
|
||||
const double next = nextafter(d, interval.second);
|
||||
const double next = std::nextafter(d, interval.second);
|
||||
if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
|
||||
d = next;
|
||||
} while (d < interval.second);
|
||||
@@ -90,7 +92,7 @@ IGL_INLINE void igl::copyleft::cgal::assign_scalar(
|
||||
const auto interval = CGAL::to_interval(cgal);
|
||||
d = interval.first;
|
||||
do {
|
||||
const float next = nextafter(d, float(interval.second));
|
||||
const float next = std::nextafter(d, float(interval.second));
|
||||
if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
|
||||
d = next;
|
||||
} while (d < float(interval.second));
|
||||
@@ -131,7 +133,7 @@ IGL_INLINE void igl::copyleft::cgal::assign_scalar(
|
||||
const auto interval = CGAL::to_interval(cgal);
|
||||
d = interval.first;
|
||||
do {
|
||||
const double next = nextafter(d, interval.second);
|
||||
const double next = std::nextafter(d, interval.second);
|
||||
if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
|
||||
d = next;
|
||||
} while (d < interval.second);
|
||||
@@ -144,49 +146,12 @@ IGL_INLINE void igl::copyleft::cgal::assign_scalar(
|
||||
const auto interval = CGAL::to_interval(cgal);
|
||||
d = interval.first;
|
||||
do {
|
||||
const float next = nextafter(d, float(interval.second));
|
||||
const float next = std::nextafter(d, float(interval.second));
|
||||
if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
|
||||
d = next;
|
||||
} while (d < float(interval.second));
|
||||
}
|
||||
|
||||
#ifndef WIN32
|
||||
|
||||
IGL_INLINE void igl::copyleft::cgal::assign_scalar(
|
||||
const CGAL::Simple_cartesian<mpq_class>::FT & cgal,
|
||||
CGAL::Simple_cartesian<mpq_class>::FT & d)
|
||||
{
|
||||
d = cgal;
|
||||
}
|
||||
|
||||
IGL_INLINE void igl::copyleft::cgal::assign_scalar(
|
||||
const CGAL::Simple_cartesian<mpq_class>::FT & cgal,
|
||||
double & d)
|
||||
{
|
||||
const auto interval = CGAL::to_interval(cgal);
|
||||
d = interval.first;
|
||||
do {
|
||||
const double next = nextafter(d, interval.second);
|
||||
if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
|
||||
d = next;
|
||||
} while (d < interval.second);
|
||||
}
|
||||
|
||||
IGL_INLINE void igl::copyleft::cgal::assign_scalar(
|
||||
const CGAL::Simple_cartesian<mpq_class>::FT & cgal,
|
||||
float& d)
|
||||
{
|
||||
const auto interval = CGAL::to_interval(cgal);
|
||||
d = interval.first;
|
||||
do {
|
||||
const float next = nextafter(d, float(interval.second));
|
||||
if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break;
|
||||
d = next;
|
||||
} while (d < float(interval.second));
|
||||
}
|
||||
|
||||
#endif // WIN32
|
||||
|
||||
#ifdef IGL_STATIC_LIBRARY
|
||||
// Explicit template instantiation
|
||||
// generated by autoexplicit.sh
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user