Compare commits

...
Author SHA1 Message Date
Peizhuo LiandAlec Jacobson 40e7900ccb Fix dqs not checking if quaternions are on the same hemisphere (#2390)
Co-authored-by: Alec Jacobson <alecjacobson@gmail.com>
2025-05-14 23:21:03 -04:00
NevsorandAlec Jacobson b443ac0261 Fix "Assertion failed" when calling igl::heat_geodesics_precompute using a V with fixed column count (#2419) [skip ci]
* Fix bug where `igl::heat_geodesics_precompute` will fail for `V` with a fixed number of columns.

See https://github.com/libigl/libigl/issues/2418

* Add missing call to .transpose()

---------

Co-authored-by: Alec Jacobson <alecjacobson@gmail.com>
2025-05-14 23:05:22 -04:00
Siqi WangandAlec Jacobson b286e13ac6 Update extract_non_manifold_edge_curves.cpp (#2423) [skip ci]
Co-authored-by: Alec Jacobson <alecjacobson@gmail.com>
2025-05-14 22:59:25 -04:00
Flo e91ffcb549 dijkstra: Fix inconsistent typing (#2469) [skip ci] 2025-05-14 22:37:48 -04:00
nicolas hsu d9524ade53 laplace equation tutorial - fixed bug with slice/lazy eval (#2447) [ci-skip] 2025-05-14 21:29:56 -04:00
Jérémie Dumas 89267b4a80 Use box-drawing characters in comments. (#2466) 2025-04-25 13:20:51 -07:00
Jérémie Dumas 7c3c05d637 Update ubuntu image (#2467) 2025-04-25 11:24:24 -07:00
Alec Jacobson 7888711039 bump deps (#2462) 2025-04-15 09:35:58 -04:00
Alec JacobsonandAlec Jacobson 08be0704c2 bump embree 4 and missing template (#2460)
* add missing template

* bump embree

---------

Co-authored-by: Alec Jacobson <ajx@mac.lan>
2025-04-07 17:23:22 -04:00
Alec Jacobson 0e360d5250 Revert templating on collapse_edge, separate overloads (#2455)
* Fix 2452

* fix cachev2 issue?

* and the windows ❄️

* removed __1::

* fix tutorial to use new func

* cmake bullshit
2025-03-31 17:00:36 -04:00
Alec Jacobson 5e561c28c8 Update isolines.h doc [ci skip] 2025-03-28 11:15:45 -04:00
Alec Jacobson 25d63024bb [ci skip] improve doc 2025-03-18 19:40:46 -04:00
Alec Jacobson f85a3c76db [ci skip] improve doc 2025-03-18 19:40:05 -04:00
Alec Jacobson 0c9c8cd643 Merge branch 'main' of github.com:libigl/libigl 2025-03-18 19:39:44 -04:00
Alec Jacobson a72b9386c8 [ci skip] improve doc 2025-03-18 19:39:38 -04:00
DJAntivenom ba69acc509 Fix division type error for highdpi calculation (#2386)
The way the highdpi value was calculated could lead to it being set to 0 or inf for certain types of window managers.
(Tiling window managers). This was caused by it trying to resize the window to a width and height of 0x0, or by having
the logical width/height of the window be smaller than the pyhsical one. This would cause the `highdpi` variable to be
set to 0, which would later cause a glfw call to be made with `inf` as an argument.
2025-02-18 08:36:41 -05:00
evouga a221faf1e4 Update voxel_grid.h (#2441)
Clarify the documentation
2025-01-07 18:50:48 -05:00
Alec Jacobson 69e2b7ee67 Fix Derived in heat_geodesics; boost url (#2440)
* PlainObject -> MatrixBase

* template igl::Hit

* vector input intersect rays with multiple hits

* initialize

* initialize

* only write if hit

* fix templates

* template me baby

* templates

* my god. so many PlainObject -> Matrix; Derived -> PlainMatrix<Derived>

* Options doesn't exist for Maps/Refs

* templates; windows size_t shinanigans

* Derived->PlainMatrix

* windows template

* derived -> plainvector

* options

* fix templating

* std types

* fix windingnumbertree tempalting

* further fix windingnumbertree tempalting

* Xi->XI

* templating

* clean up and template some of the decimation code; eventually gave up on templating outer functions

* rm needless cast

* attempt to fix index templating in boolean code

* remove debugging casts

* more templatin hell

* debug kruft

* vector resize

* assert

* int -> template

* int -> template

* int -> template

* templating away more Xi

* templating away more 3i

* formatting

* vector

* plainmatrix

* plainmatrix

* bug

* templating MSH io

* remove use of Map

* zero default tags

* bug fix

* file debug flags

* __1::

* better typing

* knn tempalte

* note

* templating

* reorder scaf inputs

* fix build

* doc

* templates

* messier than I thought

* doc

* Xi -> XI

* use templated type

* 1x1 is always symmetric

* use index type

* split intrinsic

* templating

* template internal

* restore boost link

* actually add the change to hg
2025-01-07 18:50:16 -05:00
Alec Jacobson 667101084a Add support for maintaining segments during refinement (#2424)
* segment control

* typos
2024-12-20 11:12:35 -05:00
Alec Jacobson 7472691fe6 PlainObject -> MatrixBase (#2425)
* PlainObject -> MatrixBase

* template igl::Hit

* vector input intersect rays with multiple hits

* initialize

* initialize

* only write if hit

* fix templates

* template me baby

* templates

* my god. so many PlainObject -> Matrix; Derived -> PlainMatrix<Derived>

* Options doesn't exist for Maps/Refs

* templates; windows size_t shinanigans

* Derived->PlainMatrix

* windows template

* derived -> plainvector

* options

* fix templating

* std types

* fix windingnumbertree tempalting

* further fix windingnumbertree tempalting

* Xi->XI

* templating

* clean up and template some of the decimation code; eventually gave up on templating outer functions

* rm needless cast

* attempt to fix index templating in boolean code

* remove debugging casts

* more templatin hell

* debug kruft

* vector resize

* assert

* int -> template

* int -> template

* int -> template

* templating away more Xi

* templating away more 3i

* formatting

* vector

* plainmatrix

* plainmatrix

* bug

* templating MSH io

* remove use of Map

* zero default tags

* bug fix

* file debug flags

* __1::

* better typing

* knn tempalte

* note

* templating

* reorder scaf inputs

* fix build

* doc

* templates

* messier than I thought

* doc

* Xi -> XI

* use templated type

* 1x1 is always symmetric

* use index type

* split intrinsic

* templating

* template internal
2024-12-20 11:12:11 -05:00
Alf-André Walla 20c3ee0740 Add missing include <cassert> in AABB.h (#2432) 2024-12-06 14:52:26 -05:00
Alec Jacobson 5067c8b7eb bump cgal, boost; rm gmp, mpfr (#2431)
* bump cgal; boost; mpf4; (mpfr+gmp may no longer be needed)

* actually use boost from cmake

* rm gmp mpfr 🎉

* try to tell cgal to use boost

* explicitly disable gmp

* rm gmp templates

* actually remove them
2024-11-26 22:30:10 -05:00
Alec Jacobson c2f96e8e18 improved docs 2024-11-07 08:28:37 -05:00
Alec Jacobson f962e4a6b6 Support Batched Marching Cubes (#2422)
* Working example; need to change name rather than overwrite 705

* separate tutorial for batch

* comment
2024-10-28 11:25:43 -04:00
Alec Jacobson 5d93f800ba fix warnings for Eigen's 'convenience' type all (#2421) 2024-10-28 11:25:29 -04:00
Martin Heistermann 8aca5bd0c4 Eigen build fix, Eigen::all has been renamed: (#2399)
Replace deprecated/removed Eigen::all with Eigen::placeholders:all.
2024-10-28 09:19:00 -04:00
Jérémie Dumas fac5d4a01d Change arg to const & to avoid MSan issue. (#2415) 2024-09-27 07:52:34 -04:00
Alec Jacobson 0e02103df7 add refine functionality for triangle wrapper (#2402) 2024-07-18 12:38:47 -04:00
Alec Jacobson dd9654a476 allow shared edge to be conflictingly oriented (#2395) 2024-06-13 09:08:10 -04:00
Alec Jacobson 01f2dc0a60 Add and fix test for fast_find_self_intersections (#2382)
* add test case

* add coplanarity test

* another failing test

* use orient3d

* no printing

* reverting... That introduced lots of other failure cases

* subdivided knight case

* wip predicates

* promising predicates version

* tri_tri_overlap compiles, header guards, predicate find_*

* tests for predicates::find_in...

* parallel for

* note

* mv to predicates

* remove old functions

* tutorials; extracting segments is broken 904

* fix extraction bug

* missing header

* capture consts
2024-05-03 12:01:17 -04:00
Alec Jacobson 8afe66e8fd fix static bug (#2380) 2024-05-02 22:34:41 -04:00
Alec Jacobson 6e32964a82 Fix CI Build: avoid test on windows, remove Comiso module, specific xcode on github (#2384)
* just avoid failing test on windows 😔

* mayfil instead

* mac os x xcode bug fix

* rm bonus endif

* rm comiso
2024-04-29 14:42:12 -04:00
Alec JacobsonandAlec Jacobson dafd52343b fix merge of non shared edges (#2374)
Co-authored-by: Alec Jacobson <alecjacobson@adobe.com>
2024-04-15 13:28:17 -04:00
David Coeurjolly 36930e5d19 Fixing shadowed variable declaration (that may lead to a compiler error if -Werror=shadow) (#2366) 2024-03-28 08:34:42 -04:00
Alec JacobsonandAlec Jacobson b4d8556a6b hybrid mass matrix for tets (#2364)
Co-authored-by: Alec Jacobson <alecjacobson@adobe.com>
2024-03-18 23:53:46 -04:00
Alec JacobsonandAlec Jacobson 81180a6e6a Boundary facets orientation (#2362)
* fix boundary_facets orientation + test

* rm print in tests

---------

Co-authored-by: Alec Jacobson <alecjacobson@adobe.com>
2024-03-17 11:10:07 -04:00
Alec JacobsonandAlec Jacobson a8819dcf9b fix bug (#2361)
Co-authored-by: Alec Jacobson <alecjacobson@adobe.com>
2024-03-14 17:45:34 -04:00
Alec JacobsonandAlec Jacobson 1886d18147 fix debug bug (#2360)
Co-authored-by: Alec Jacobson <alecjacobson@adobe.com>
2024-03-07 20:16:48 -05:00
Alec Jacobson 7e6bf3b81c missing break (#2354) 2024-02-20 11:23:23 -05:00
Alec Jacobson c7a84522c3 CGAL tests don't seem to run on Windows CI builds (#2351)
* show all tests

* fix cmake target
2024-02-19 23:18:34 -05:00
Alec Jacobson fe65ecb907 remove or hide cerr<< behind ifdef (#2349) [ci skip] 2024-02-09 11:13:07 -05:00
William8915 33a931d019 Fix compile error on gcc-12.3 (#2336)
This is a follow up fix of #2254. After #2254 gcc-12.3 reports the error "template-id not allowed for destructor".
2024-02-07 09:26:22 -05:00
Alec JacobsonandAlec Jacobson 94c6afde11 fix bug where cost of collapsed edge was attempted (#2347)
Co-authored-by: Alec Jacobson <alecjacobson@adobe.com>
2024-02-07 09:25:54 -05:00
Alec Jacobson 8185a213d0 centroid only worked for fixed size input (#2340)
* template for variable size and failing test

* fix

* static asserts
2024-01-23 20:14:49 -05:00
Alec JacobsonandAlec Jacobson 7d1614af1e Fix split_nonmanifold (#2344)
* failing test

* simply cut along all non-manifold edges

* fix compile

* before rewrite

* after rewrite

---------

Co-authored-by: Alec Jacobson <alecjacobson@adobe.com>
2024-01-23 09:25:44 -05:00
Bryn LloydandBryn Lloyd 293e79ff86 enable mixed polygons using convention that negative indices are ignored (#2338)
* enable mixed polygons using convention that negative indices are ignored

* add unit tests

---------

Co-authored-by: Bryn Lloyd <lloyd@itis.swiss>
2024-01-17 10:36:24 -05:00
Alec Jacobson 37f3b1d821 fix bug in cut_mesh; improve documentation; add test (#2315) 2024-01-10 09:40:11 -05:00
Taylor Holliday a8b3833942 fix compile error (#2328)
* Update eigs.cpp

Reduce terminal spew

* Revert "Update eigs.cpp"

This reverts commit fdbdb42934.

* Fix compile error and propagate errors
2024-01-10 09:39:41 -05:00
Alec JacobsonandAlec Jacobson 7f7f0fe007 use our boost-cmake which uses slow, non-jfrog url (#2330)
Co-authored-by: Alec Jacobson <alecjacobson@adobe.com>
2024-01-08 18:06:08 -05:00
Alec Jacobson 0b9030b1ed wrong header 2023-10-23 08:25:36 -04:00
Alec JacobsonandAlec Jacobson 112c1b8e48 Dynamic updates to AABB tree; intersection-blocking mesh decimation (#2301)
* working insertion and rotation b-b-b-but pointers aren't stuck to m_primitive

* insert now maintains primitive's pointers;+rotate is now getting heights in right ballpark

* sibling rotations working (and helping); dry run test working (and helping)

* working insertion, deletion (detach), and refit with padding.

* working; inexact

* working; inexact

* working; inexact

* note about poor assumptions

* working well after bug fixes. before refactor into functions

* simple self-intersection test function

* moved all functions to files

* docs

* blocking directly in qslim. better docs. aabb templates/tests;

* dont use size_t and fix namespace

* brute-force too fast on linux

* rm overloads in qslim/decimate; cgal template

* fix coplanar bug; factor out raytri.c

* fix and cgal debug

* refactor fast_find; fix bugs in fast_find; fix bugs in shared_vertex

* tutorials running again

* cleaned up aabb tutorials; templates

* format docs

* docs. arg names

* template name

* improve docs

* debugging test

* debugging test

* debugging test

* debugging test

* debugging test

* debugging test

* debugging test

* debugging test

* ebuggin test

* ebuggin test

* add epsilon to ray_triangle ifs

* erroneous includes

* rm leftover includes

* fix cmake bug

* uh actually fix cmake bug

* missing delete

* simple insert test

* don't pad all leaves F.rows() times

* fix pad bug

---------

Co-authored-by: Alec Jacobson <alecjacobson@adobe.com>
2023-10-14 07:32:50 -04:00
Alec Jacobson 7c9387c92b prefer std::u?int[0-9]+_t and include <cstdint> else include <stdint.h> (#2302) 2023-10-13 20:15:17 -04:00
Alec Jacobson 1c8c6d38ba Stay up to date with stable (#2300)
* bump version in cmake

* fix aassertions, add templates to compile in debug (#2299)
2023-10-06 19:47:53 -04:00
Alec JacobsonandAlec Jacobson 7991ee81d8 tata -> data (#2295) [ci skip]
Co-authored-by: Alec Jacobson <alecjacobson@adobe.com>
2023-09-28 13:12:57 -04:00
Alec Jacobson fdaac01bcc Fix AABB::find to not try to run 2D code on 3D input and vice versa (#2294) [ci skip]
* pull out DIM from find

* AABB find test

* templates
2023-09-26 21:39:36 -04:00
Alec Jacobson b4152c576c better docs (#2293) [ci skip] 2023-09-26 12:07:22 -04:00
Alec Jacobson 1b07ebcf9e rm vector overloads and simplify api (#2290) [ci skip] 2023-09-25 16:27:01 -04:00
Alec Jacobson 64c2740230 bump cgal to 5.6 (#2289) [ci skip] 2023-09-25 09:59:14 -04:00
Evan Barentin 2b05343e0d Normalize all the line endings (#2288) 2023-09-22 12:39:53 -04:00
Alec Jacobson 7547801f58 use unit vector atan formula; split intrinsic version (#2285) [ci skip]
* use unit vector atan formula; split intrinsic version

* fix on linux
2023-09-19 23:28:58 -04:00
Emmanuel OliviandAlec Jacobson d154f0587c Add test for issue/2270 and a fix (#2271)
* Add test for issue/2270 and a (dirty) fix

* restore func; simplify test (failing)

* more robust fix

* Implement solution from T.Ize in "Robust BVH Ray Traversal" 4.2

* Implement solution from T.Ize in "Robust BVH Ray Traversal" 4.1

* Move nextafter in its own file

* Add std:: to other nextafter calls

* Add test for nextafter

* Use unaryExpr for nextafter on Eigen elements

* Fix and rename into increment_ulp

* missing templates

* correct overload name; missing templates

---------

Co-authored-by: Alec Jacobson <alecjacobson@gmail.com>
2023-09-18 20:18:08 -04:00
Alec Jacobson dddfd92c7a Merge branch 'main' of github.com:libigl/libigl 2023-09-18 17:51:31 -04:00
Alec Jacobson 6ddf3b0dd7 better documentation [ci skip] 2023-09-18 17:51:26 -04:00
Alec Jacobson e139702373 writeOFF for quads etc. (#2283) [ci skip] 2023-09-18 17:01:12 -04:00
Alec Jacobson fe8e17c095 add gitattributes file (#2282) [ci skip] 2023-09-18 17:00:35 -04:00
Alec Jacobson 0c78def493 Custom Shader tutorial (#2281) [ci skip] 2023-09-18 17:00:16 -04:00
Alec Jacobson 3c0f31f132 better templates for marching tets (#2279) [ci skip]
* better templates

* fabs -> abs

* missing cast
2023-09-18 15:07:26 -04:00
Alec Jacobson 2b62322cd5 improve color doc [ci skip] 2023-09-18 14:33:46 -04:00
Alec Jacobson cb111f6838 Bump to OpenGL version 4.1 (#2277)
* bump glad

* fix name changes

* remove compilation guards

* bump runtime to 4.1 too

* fix map_texture; template bind

* doc

* attempt to skip tests

* that didnt work, disable with cmake

* missing template

* rm __1::
2023-09-14 22:29:44 -04:00
Alec Jacobson 68684132e5 adj list fix unref; manifold doc; icosa; tests (#2276) [ci skip] 2023-09-13 18:27:47 -04:00
Alec Jacobson 0c1865a8d6 Fix bug in half_space_box (#2269) [ci skip]
* test

* fix 1384 and add test
2023-09-09 00:12:46 -04:00
Alec Jacobson 5dcce37c9d rm empty ifdef [ci skip] 2023-09-08 20:51:35 -04:00
Alec Jacobson d6448a86fb 3 new trimming methods and tutorial (#2268) [ci skip]
* 3 new trimming methods and tutorial

* missing template

* rm warning

* add tests

* Windows templates
2023-09-08 12:58:07 -04:00
HomayoonT 6a31dbf126 Update MeshGL.h (#2267) [ci skip]
Added #include <cstdint> for fixing build failure mingw-w64 "w64devkit"
2023-09-07 12:12:07 -04:00
Alec Jacobson 321d0d8ed0 Fix most floating point exceptions (#2266)
* better documentation, test against eigen slicing

* remove a bunch of slices

* clean up templates; static asserts on vector types

* final purges of slice

* fix templates in debug and ears test

* fix slice mask bug

* fix slice bug

* fix most fpe exceptions

* fix limit case

* more robust push, pop
2023-09-06 23:25:28 -04:00
Alec Jacobson 9bfacf8fb6 fix slim doublearea -> volume for tets (#2262) [ci skip] 2023-09-04 10:00:16 -04:00
Alec Jacobson f48c5a93f1 Fix 1462 2023-09-03 21:59:57 -04:00
Alec Jacobson d326251896 fix moments to work with more input types 2023-09-03 14:59:57 -04:00
Alec Jacobson 74160c4c1c sitemap xml; link to functions list 2023-09-02 10:44:09 -04:00
Alec Jacobson b774e1b31c Phase out slice for dense matrices (#2259)
* better documentation, test against eigen slicing

* remove a bunch of slices

* clean up templates; static asserts on vector types

* final purges of slice

* fix templates in debug and ears test

* fix slice mask bug

* fix slice bug

* boo. try to get around windows poor template deduction

* annoying left over bad windows ❄️ template
2023-09-01 11:11:46 -04:00
Alec Jacobson f5702f63e7 Fully avoid conflicting template parameters in AABB/signed_distance (#2257) [ci skip]
* readPLY: dont touch unread; point_mesh... dim pattern

* static asserts in pseudonormal test

* better handling of dimensions in signed_distance

* test fixed column case
2023-08-30 10:50:12 -04:00
Alec Jacobson 0262ef5866 Merge branch 'main' of github.com:libigl/libigl 2023-08-29 23:43:49 -04:00
Alec Jacobson 9350803420 fix namespace / include issues 2023-08-29 23:43:42 -04:00
Alec Jacobson 0e39b473b1 readPLY: dont touch unread; point_mesh... dim pattern (#2256) [ci skip] 2023-08-29 21:17:20 -04:00
Alec Jacobson 7a84503c8e Expose cutoff parameter for CGAL intersections; better default (#2255) [ci skip]
* cutoff in cgal intersections

* missing cast
2023-08-28 22:12:19 -04:00
Alec Jacobson deae7a2767 unfix dimensions 2023-08-26 23:16:00 -04:00
Alec Jacobson a0bb5bb813 fix dimensions 2023-08-26 23:13:36 -04:00
Alec Jacobson 5779714a5b fix hardcoded vectorxi 2023-08-26 23:01:47 -04:00
Alec Jacobson 687530283c Fix a bunch of warnings (#2254)
* fix a couple warnings

* fix a bunch of warnings (mostly unused variable)

* fix a bunch of warnings and simplify params

* Special assert so that variables aren't seen as unused

* fix tutorial

* undo erroneous line removal

* ASSERT -> IGL_ASSERT

* VSC ❄️ doesn't realize MAX_DEPTH is conts
2023-08-26 22:42:47 -04:00
Alec Jacobson 5c17f85621 fix debug compile bug 2023-08-25 10:56:39 -04:00
Alec Jacobson e5e0539e7d Remove extra calls to set_face_based (#2253) 2023-08-25 10:40:33 -04:00
Alec Jacobson eee808949e info about header/static [ci skip] 2023-08-24 17:57:59 -04:00
Alec Jacobson 75209c5d6c Robust isolines (#2251)
* robust isolines, test

* documentation
2023-08-24 17:24:17 -04:00
Alec Jacobson ab6229c77a Euler Characteristic tests (#2250)
* test for euler characteristic

* doc
2023-08-23 16:19:42 -04:00
Alec Jacobson b1fe6ba49c read blank lines as comments (#2247) [ci skip] 2023-08-22 20:20:53 -04:00
Alec Jacobson 8d940367bf support rowmajor (#2246) [ci skip] 2023-08-22 20:20:34 -04:00
661 changed files with 20811 additions and 16749 deletions
+20
View File
@@ -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
+17 -5
View File
@@ -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
+3
View File
@@ -48,3 +48,6 @@ LibiglOptions.cmake
# macos debris
.DS_Store
*~
dox/
latex/
scripts/
+9 -1
View File
@@ -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")
-95
View File
@@ -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()
-95
View File
@@ -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()
+5
View File
@@ -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
+4
View File
@@ -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)
-27
View File
@@ -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})
+6
View File
@@ -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()
-1
View File
@@ -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
+22 -26
View File
@@ -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()
+6 -14
View File
@@ -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()
-31
View File
@@ -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)
+1 -1
View File
@@ -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
)
+1 -1
View File
@@ -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)
-96
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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}\"")
-91
View File
@@ -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
View File
@@ -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)
+1 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+517 -116
View File
@@ -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
View File
@@ -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());
+19
View File
@@ -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
+67 -67
View File
@@ -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> &copy)
: 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)
+1 -1
View File
@@ -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)
{
+4 -4
View File
@@ -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, ...
+4 -4
View File
@@ -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
View File
@@ -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
+9
View File
@@ -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
-4
View File
@@ -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++) {
+95
View File
@@ -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
+36
View File
@@ -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
View File
@@ -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;
+84 -85
View File
@@ -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
View File
@@ -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
View File
@@ -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
+7 -7
View File
@@ -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
);
+1
View File
@@ -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;
+1 -1
View File
@@ -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}
+30 -24
View File
@@ -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
+2 -2
View File
@@ -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,
+1 -4
View File
@@ -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
View File
@@ -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);
+3 -3
View File
@@ -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
+6
View File
@@ -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
View File
@@ -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
View File
@@ -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);
}
+2 -1
View File
@@ -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++)
+1 -1
View File
@@ -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)
{
-1
View File
@@ -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();
+6 -7
View File
@@ -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;
+26 -12
View File
@@ -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
+19 -9
View File
@@ -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
+8 -98
View File
@@ -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
+3 -10
View File
@@ -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
-1
View File
@@ -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"
+94
View File
@@ -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
+46
View File
@@ -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
+35
View File
@@ -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
+30
View File
@@ -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
+4
View File
@@ -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&);
+2 -2
View File
@@ -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
View File
@@ -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);
}
+13 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
+58
View File
@@ -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
+20
View File
@@ -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
View File
@@ -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
View File
@@ -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
+148
View File
@@ -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;
}
+82
View File
@@ -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
+16 -3
View File
@@ -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
+7 -3
View File
@@ -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
+5 -5
View File
@@ -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
+1 -1
View File
@@ -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);
+4 -3
View File
@@ -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:
+11 -9
View File
@@ -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);
+4 -3
View File
@@ -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");
}
};
+1 -1
View File
@@ -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?");
}
}
+50 -7
View File
@@ -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 -42
View File
@@ -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