From 61b77935102b2e16e8ba11e25f2f041f1ab4f51d Mon Sep 17 00:00:00 2001 From: Nuno Miguel Nobre Date: Fri, 12 May 2023 11:53:38 +0100 Subject: [PATCH 01/11] Fix a minor typo Co-authored-by: Andrew Davis --- src/MeshImprovement.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/MeshImprovement.cpp b/src/MeshImprovement.cpp index 764844ff..ddb9d2ea 100644 --- a/src/MeshImprovement.cpp +++ b/src/MeshImprovement.cpp @@ -615,7 +615,7 @@ void floatTetWild::operation(const std::vector &input_vertices, const s bool floatTetWild::update_scaling_field(Mesh &mesh, Scalar max_energy) { // return false; - cout << "updating sclaing field ..." << endl; + cout << "updating scaling field ..." << endl; bool is_hit_min_edge_length = false; Scalar radius0 = mesh.params.ideal_edge_length * 1.8;//increasing the radius would increase the #v in output From 3a38369d5857f4c8e0b8a2ba5911f21ee584dffd Mon Sep 17 00:00:00 2001 From: Nuno Miguel Nobre Date: Thu, 18 May 2023 08:16:09 +0100 Subject: [PATCH 02/11] Fix a few minor typos in the readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b5dcafcd..ecfef4b4 100644 --- a/README.md +++ b/README.md @@ -85,9 +85,9 @@ sudo apt-get install gmp conda install -c conda-forge mpir ``` -**Note Windows** The executable needs that the file `mpir.dll` is in the same directiory of `FloatTetwild_bin.exe`. Once you compliled the code, copy `mpir.dll` (e.g., `\Library\bin`) to the directoy containing `FloatTetwild_bin.exe`. +**Note Windows** The executable needs that the file `mpir.dll` is in the same directory as `FloatTetwild_bin.exe`. Once you compiled the code, copy `mpir.dll` (e.g., `\Library\bin`) to the directory containing `FloatTetwild_bin.exe`. -**Note** if cmake cannot find gmp you need to export the envirnement variable `GMP_INC` and `GMP_LIB` to the folder where you installed (e.g., `\Library\include` for `GMP_INC` and `\Library\lib` for `GMP_LIB`). +**Note** if cmake cannot find gmp you need to export the environment variable `GMP_INC` and `GMP_LIB` to the folder where you installed (e.g., `\Library\include` for `GMP_INC` and `\Library\lib` for `GMP_LIB`). - Check the installation: @@ -134,7 +134,7 @@ Users can provide a background tetmesh in .msh format with vertex scalar field v - Smoothing open regions -Our method can fill gaps and holes but the tetmesh faces on those parts could be bumpy. We provide users an option to do Lapacian smoothing on those faces to get a smoother surface. +Our method can fill gaps and holes but the tetmesh faces on those parts could be bumpy. We provide users an option to do Laplacian smoothing on those faces to get a smoother surface. ### Command Line Switches Our software supports usage via command line or via a C++ function wrapper. Here is an overview of all command line switches: From 5eb12cc150741a7cc061150d772dd3577bc7f354 Mon Sep 17 00:00:00 2001 From: Nuno Miguel Nobre Date: Fri, 12 May 2023 12:01:02 +0100 Subject: [PATCH 03/11] Add missing time units to output msgs --- src/Simplification.cpp | 4 ++-- src/TriangleInsertion.cpp | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/Simplification.cpp b/src/Simplification.cpp index a85753c3..fed1b031 100644 --- a/src/Simplification.cpp +++ b/src/Simplification.cpp @@ -42,11 +42,11 @@ void floatTetWild::simplify(std::vector& input_vertices, std::vector &input_verti covered_fs_infos[f_id].push_back(std::make_pair(i, j)); } } - logger().info("time1 = {}", timer.getElapsedTime()); + logger().info("time1 = {}s", timer.getElapsedTime()); bool is_all_inserted = true; int cnt = 0; @@ -2060,11 +2060,11 @@ bool floatTetWild::insert_boundary_edges(const std::vector &input_verti } logger().info("uninsert boundary #e = {}/{}", b_edge_infos.size() - cnt, b_edge_infos.size()); - logger().info("time2 = {}", time2); - logger().info("time3 = {}", time3); - logger().info("time4 = {}", time4); - logger().info("time5 = {}", time5); - logger().info("time6 = {}", time6); + logger().info("time2 = {}s", time2); + logger().info("time3 = {}s", time3); + logger().info("time4 = {}s", time4); + logger().info("time5 = {}s", time5); + logger().info("time6 = {}s", time6); // logger().info("time_e1 = {}", time_e1); // logger().info("time_e2 = {}", time_e2); From 9ad6458e4af524f1acd31771dc9603e8f59c29e4 Mon Sep 17 00:00:00 2001 From: Nuno Miguel Nobre Date: Thu, 18 May 2023 10:10:37 +0100 Subject: [PATCH 04/11] Fix GitHub workflows --- .github/workflows/continuous.yml | 40 ++++++++++++++------------------ 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/.github/workflows/continuous.yml b/.github/workflows/continuous.yml index efe02cc3..aefedeae 100644 --- a/.github/workflows/continuous.yml +++ b/.github/workflows/continuous.yml @@ -18,27 +18,22 @@ jobs: #################### Unix: - name: ${{ matrix.name }}-${{ matrix.envelope }} (${{ matrix.config }}) - runs-on: ${{ matrix.os }} + name: ${{ matrix.os }}-${{ matrix.envelope }} (${{ matrix.config }}) + runs-on: ${{ matrix.os }}-latest strategy: fail-fast: false matrix: - os: [ubuntu-18.04, macos-latest] + os: [ubuntu, macos] config: [Debug, Release] envelope: [ON, OFF] - include: - - os: macos-latest - name: macOS - - os: ubuntu-18.04 - name: Linux steps: - name: Checkout repository - uses: actions/checkout@v1 + uses: actions/checkout@v3 with: fetch-depth: 10 - name: Dependencies (Linux) - if: runner.os == 'Linux' + if: matrix.os == 'ubuntu' run: | sudo apt-get update sudo apt-get install \ @@ -52,15 +47,15 @@ jobs: ccache - name: Dependencies (macOS) - if: runner.os == 'macOS' + if: matrix.os == 'macos' run: brew install suite-sparse ccache gmp - name: Cache Build id: cache-build - uses: actions/cache@v1 + uses: actions/cache@v3 with: path: ~/.ccache - key: ${{ runner.os }}-${{ matrix.config }}-${{ matrix.envelope }}-cache + key: ${{ matrix.os }}-${{ matrix.config }}-${{ matrix.envelope }}-cache - name: Prepare ccache run: | @@ -90,8 +85,8 @@ jobs: #################### Windows: - name: Windows-${{ matrix.envelope }} (${{ matrix.config }}) - runs-on: windows-2019 + name: windows-${{ matrix.envelope }} (${{ matrix.config }}) + runs-on: windows-latest env: CC: cl.exe CXX: cl.exe @@ -114,7 +109,7 @@ jobs: conda install -c conda-forge mpir -y - name: Checkout repository - uses: actions/checkout@v1 + uses: actions/checkout@v3 with: fetch-depth: 10 - uses: seanmiddleditch/gha-setup-ninja@master @@ -127,14 +122,15 @@ jobs: - name: Cache build id: cache-build - uses: actions/cache@v1 + uses: actions/cache@v3 with: path: ${{ env.appdata }}\Mozilla\sccache - key: ${{ runner.os }}-${{ matrix.config }}-${{ matrix.envelope }}-cache + key: ${{ matrix.os }}-${{ matrix.config }}-${{ matrix.envelope }}-cache - name: Prepare sccache run: | - Invoke-Expression (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh') + irm get.scoop.sh -outfile 'install.ps1' + .\install.ps1 -RunAsAdmin scoop install sccache --global # Scoop modifies the PATH so we make it available for the next steps of the job echo "${env:PATH}" >> ${env:GITHUB_PATH} @@ -142,7 +138,7 @@ jobs: - name: Configure and build shell: cmd run: | - call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=x64 + call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\Common7\Tools\VsDevCmd.bat" -arch=x64 cmake --version cmake -G Ninja ^ -DCMAKE_CXX_COMPILER_LAUNCHER=sccache ^ @@ -162,6 +158,6 @@ jobs: shell: powershell run: | cd build - cp C:\Miniconda\Library\bin\mpir.dll .\ - cp C:\Miniconda\Library\bin\gmp.dll .\ + cp C:\Miniconda\envs\__setup_conda\Library\bin\mpir.dll .\ + cp C:\Miniconda\envs\__setup_conda\Library\bin\gmp.dll .\ .\FloatTetwild_bin.exe --input ..\tests\bunny.off --level 0 --stop-energy 200 From 24f35766df7ef5feea330d074a41d40ff78c3464 Mon Sep 17 00:00:00 2001 From: Nuno Miguel Nobre Date: Fri, 19 May 2023 15:44:34 +0100 Subject: [PATCH 05/11] Use NO_SURFACE_TAG macro --- src/Mesh.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Mesh.hpp b/src/Mesh.hpp index c121794f..31b44931 100644 --- a/src/Mesh.hpp +++ b/src/Mesh.hpp @@ -111,7 +111,7 @@ class Random is_surface_fs = {{NOT_SURFACE, NOT_SURFACE, NOT_SURFACE, NOT_SURFACE}}; is_bbox_fs = {{NOT_BBOX, NOT_BBOX, NOT_BBOX, NOT_BBOX}}; opp_t_ids = {{OPP_T_ID_UNKNOWN, OPP_T_ID_UNKNOWN, OPP_T_ID_UNKNOWN, OPP_T_ID_UNKNOWN}}; - surface_tags = {{0, 0, 0, 0}}; + surface_tags = {{NO_SURFACE_TAG, NO_SURFACE_TAG, NO_SURFACE_TAG, NO_SURFACE_TAG}}; quality = 0; scalar = 0; @@ -152,7 +152,7 @@ class Random std::array is_surface_fs = {{NOT_SURFACE, NOT_SURFACE, NOT_SURFACE, NOT_SURFACE}}; std::array is_bbox_fs = {{NOT_BBOX, NOT_BBOX, NOT_BBOX, NOT_BBOX}}; std::array opp_t_ids = {{OPP_T_ID_UNKNOWN, OPP_T_ID_UNKNOWN, OPP_T_ID_UNKNOWN, OPP_T_ID_UNKNOWN}}; - std::array surface_tags = {{0, 0, 0, 0}}; + std::array surface_tags = {{NO_SURFACE_TAG, NO_SURFACE_TAG, NO_SURFACE_TAG, NO_SURFACE_TAG}}; Scalar quality = 0; Scalar scalar = 0; From f4d14af68f890542dd817e7762cbc1ca1a4f474a Mon Sep 17 00:00:00 2001 From: Nuno Miguel Nobre Date: Fri, 30 Jun 2023 19:49:42 +0100 Subject: [PATCH 06/11] Fix description of the output scalar field --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index ecfef4b4..454c8194 100644 --- a/README.md +++ b/README.md @@ -102,7 +102,7 @@ This command should show a list of fTetWild parameters. The inputs of our software are triangle surface meshes in `.off/.obj/.stl/.ply` format. -We support `.mesh/.msh` format output. The default output format is `.msh` with minimum dihedral angle recorded as element scalar field, which can be visualized by software [Gmsh](http://gmsh.info/). You can use `PyMesh::MshLoader` and `PyMesh::MshSaver` in `pymesh/` for read and write `.msh` meshes. +We support `.mesh/.msh` format output. The default output format is `.msh` with the elements' energy as the scalar field, which can be visualized by software [Gmsh](http://gmsh.info/). You can use `PyMesh::MshLoader` and `PyMesh::MshSaver` in `pymesh/` for read and write `.msh` meshes. ### Features From 3bbb9b19dce1dbfcae3a1251f6fffe5e478a0312 Mon Sep 17 00:00:00 2001 From: Nuno Miguel Nobre Date: Mon, 3 Jul 2023 12:20:03 +0100 Subject: [PATCH 07/11] Specify default filtering energy in usage msg --- README.md | 2 +- src/main.cpp | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 454c8194..f46d1f68 100644 --- a/README.md +++ b/README.md @@ -150,7 +150,7 @@ Options: --op INT Boolean operation: 0: union, 1: intersection, 2: difference. -l,--lr FLOAT ideal_edge_length = diag_of_bbox * L. (double, optional, default: 0.05) -e,--epsr FLOAT epsilon = diag_of_bbox * EPS. (double, optional, default: 1e-3) - --stop-energy FLOAT Stop optimization when max energy is lower than this. + --stop-energy FLOAT Stop optimization when max energy is lower than this. (double, optional, default: 10.0) --log TEXT Log info to given file. --level INT Log level (0 = most verbose, 6 = off). -q,--is-quiet Mute console output. (optional) diff --git a/src/main.cpp b/src/main.cpp index f277e892..06b4d2ce 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -202,7 +202,9 @@ int main(int argc, char** argv) command_line.add_option("--max-its", params.max_its, "(for debugging usage only)"); command_line.add_option( - "--stop-energy", params.stop_energy, "Stop optimization when max energy is lower than this."); + "--stop-energy", + params.stop_energy, + "Stop optimization when max energy is lower than this. (double, optional, default: 10.0)"); command_line.add_option("--stage", params.stage, "(for debugging usage only)"); command_line.add_option("--stop-p", params.stop_p, "(for debugging usage only)"); From 870d9b3206f555a836c380109c872b8bdc817ded Mon Sep 17 00:00:00 2001 From: Nuno Miguel Nobre Date: Wed, 5 Jul 2023 10:56:20 +0100 Subject: [PATCH 08/11] Improve log msgs during the simplification/preprocessing stage Previously, the new no. of faces printed after remove duplicates didn't take into account the removal of repeated faces w/ opposite orientation and of degenerate faces, i.e. those w/ repeated vertices or too small an area. In addition, the edge collapsing and swapping log msgs used to speak of faces, which while technically correct, could be confusing since we're talking 2d faces, i.e. edges. --- src/Simplification.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Simplification.cpp b/src/Simplification.cpp index fed1b031..ed40bebe 100644 --- a/src/Simplification.cpp +++ b/src/Simplification.cpp @@ -204,6 +204,11 @@ bool floatTetWild::remove_duplicates(std::vector& input_vertices, std:: input_tags.push_back(old_input_tags[i]); } + logger().info("remove degenerate triangles and duplicated opposite-oriented triangles:"); + logger().info("(removing degenerate triangles might leave lone vertices that will be removed later)"); + logger().info("#v: {} -> {}", V_in.rows(), input_vertices.size()); + logger().info("#f: {} -> {}", F_in.rows(), input_faces.size()); + return true; } @@ -491,7 +496,7 @@ void floatTetWild::collapsing(std::vector& input_vertices, std::vector< // cout<& input_vertices, std::vector& input_faces, @@ -615,7 +620,7 @@ void floatTetWild::swapping(std::vector& input_vertices, std::vector Date: Wed, 5 Jul 2023 17:00:07 +0100 Subject: [PATCH 09/11] Tune TBB conditionals in the preprocessing edge collapsing algorithm --- src/Simplification.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Simplification.cpp b/src/Simplification.cpp index ed40bebe..661fa2fa 100644 --- a/src/Simplification.cpp +++ b/src/Simplification.cpp @@ -362,6 +362,7 @@ void floatTetWild::collapsing(std::vector& input_vertices, std::vector< } //real update +#ifndef FLOAT_TETWILD_USE_TBB // std::unordered_set n_v_ids;//get this info before real update for later usage std::vector n_v_ids;//get this info before real update for later usage for (int f_id:new_f_ids) { @@ -371,6 +372,7 @@ void floatTetWild::collapsing(std::vector& input_vertices, std::vector< } } vector_unique(n_v_ids); +#endif v_is_removed[v1_id] = true; input_vertices[v2_id] = p; From bcb029d6b31deb9074834c3d5eb03eda132c7cb3 Mon Sep 17 00:00:00 2001 From: Nuno Miguel Nobre Date: Wed, 5 Jul 2023 12:50:19 +0100 Subject: [PATCH 10/11] Fix face flipping detection in the preprocessing edge swapping algorithm --- src/Simplification.cpp | 63 +++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 37 deletions(-) diff --git a/src/Simplification.cpp b/src/Simplification.cpp index 661fa2fa..18a8f2f8 100644 --- a/src/Simplification.cpp +++ b/src/Simplification.cpp @@ -523,7 +523,6 @@ void floatTetWild::swapping(std::vector& input_vertices, std::vector({{e[1], e[0]}}), weight)); } int cnt = 0; @@ -558,26 +557,11 @@ void floatTetWild::swapping(std::vector& input_vertices, std::vector -0.999) {//maybe it's for avoiding numerical issue - if (old_nvs[0].dot(old_nvs[1]) < 1 - 1e-6)//not coplanar + if (cos_a0 > -0.999 and cos_a1 > -0.999) {//if any old face too degenerate, ignore coplanarity + if (old_nvs[0].dot(old_nvs[1]) < 1 - SCALAR_ZERO)//not coplanar continue; } - //check inversion - auto &old_nv = cos_a1 < cos_a0 ? old_nvs[0] : old_nvs[1]; - bool is_filp = false; - for (int f_id:n12_f_ids) { - auto &a = input_vertices[input_faces[f_id][0]]; - auto &b = input_vertices[input_faces[f_id][1]]; - auto &c = input_vertices[input_faces[f_id][2]]; - if (old_nv.dot(((b - c).cross(a - c)).normalized()) < 0) { - is_filp = true; - break; - } - } - if (is_filp) - continue; - //check quality Scalar cos_a0_new = get_angle_cos(input_vertices[v1_id], input_vertices[n_v_ids[0]], input_vertices[n_v_ids[1]]); @@ -586,31 +570,36 @@ void floatTetWild::swapping(std::vector& input_vertices, std::vector Date: Thu, 6 Jul 2023 16:52:12 +0100 Subject: [PATCH 11/11] Fix data race in the preprocessing edge collapsing algorithm See the Container data races section [container.requirements.dataraces] of the C++ standard. You can find draft documents hosted at https://www.open-std.org/jtc1/sc22/wg21/docs/standards#14882. --- src/Mesh.cpp | 2 +- src/Mesh.hpp | 4 ++-- src/Simplification.cpp | 10 +++++----- src/Simplification.h | 6 +++--- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Mesh.cpp b/src/Mesh.cpp index 85b171a8..4036ecf7 100644 --- a/src/Mesh.cpp +++ b/src/Mesh.cpp @@ -101,7 +101,7 @@ namespace floatTetWild { } - void Mesh::one_ring_edge_set(const std::vector> &edges, const std::vector& v_is_removed, const std::vector& f_is_removed, + void Mesh::one_ring_edge_set(const std::vector> &edges, const std::vector& v_is_removed, const std::vector& f_is_removed, const std::vector>& conn_fs, const std::vector& input_vertices, std::vector &safe_set) { // std::vector indices(edges.size()); diff --git a/src/Mesh.hpp b/src/Mesh.hpp index 31b44931..744bb422 100644 --- a/src/Mesh.hpp +++ b/src/Mesh.hpp @@ -189,8 +189,8 @@ class Random void partition(const int n_parts, std::vector> &tets_id) const; - static void one_ring_edge_set(const std::vector> &edges, const std::vector &v_is_removed, - const std::vector &f_is_removed, const std::vector> &conn_fs, + static void one_ring_edge_set(const std::vector> &edges, const std::vector &v_is_removed, + const std::vector &f_is_removed, const std::vector> &conn_fs, const std::vector &input_vertices, std::vector &safe_set); inline int t_empty_size() const { diff --git a/src/Simplification.cpp b/src/Simplification.cpp index 18a8f2f8..7dab1d3e 100644 --- a/src/Simplification.cpp +++ b/src/Simplification.cpp @@ -31,8 +31,8 @@ void floatTetWild::simplify(std::vector& input_vertices, std::vector v_is_removed(input_vertices.size(), false); - std::vector f_is_removed(input_faces.size(), false); + std::vector v_is_removed(input_vertices.size(), false); + std::vector f_is_removed(input_faces.size(), false); std::vector> conn_fs(input_vertices.size()); for (int i = 0; i < input_faces.size(); i++) { for (int j = 0; j < 3; j++) @@ -214,7 +214,7 @@ bool floatTetWild::remove_duplicates(std::vector& input_vertices, std:: void floatTetWild::collapsing(std::vector& input_vertices, std::vector& input_faces, const AABBWrapper& tree, const Parameters& params, - std::vector& v_is_removed, std::vector& f_is_removed, std::vector>& conn_fs){ + std::vector& v_is_removed, std::vector& f_is_removed, std::vector>& conn_fs){ #ifdef FLOAT_TETWILD_USE_TBB std::vector> edges; @@ -503,7 +503,7 @@ void floatTetWild::collapsing(std::vector& input_vertices, std::vector< void floatTetWild::swapping(std::vector& input_vertices, std::vector& input_faces, const AABBWrapper& tree, const Parameters& params, - std::vector& v_is_removed, std::vector& f_is_removed, std::vector>& conn_fs) { + std::vector& v_is_removed, std::vector& f_is_removed, std::vector>& conn_fs) { std::vector> edges; edges.reserve(input_faces.size() * 6); for (int i = 0; i < input_faces.size(); i++) { @@ -919,7 +919,7 @@ bool floatTetWild::is_out_envelope(const std::array& vs, const AABBW // return false; } -void floatTetWild::check_surface(std::vector& input_vertices, std::vector& input_faces, const std::vector& f_is_removed, +void floatTetWild::check_surface(std::vector& input_vertices, std::vector& input_faces, const std::vector& f_is_removed, const AABBWrapper& tree, const Parameters& params) { cout<<"checking surface"<& input_vertices, std::vector& input_faces, std::vector& input_tags, const Parameters& params); void collapsing(std::vector& input_vertices, std::vector& input_faces, const AABBWrapper& sf_tree, const Parameters& params, - std::vector& is_v_removed, std::vector& is_f_removed, std::vector>& conn_fs); + std::vector& v_is_removed, std::vector& f_is_removed, std::vector>& conn_fs); void swapping(std::vector& input_vertices, std::vector& input_faces, const AABBWrapper& sf_tree, const Parameters& params, - std::vector& is_v_removed, std::vector& is_f_removed, std::vector>& conn_fs); + std::vector& v_is_removed, std::vector& f_is_removed, std::vector>& conn_fs); void flattening(std::vector& input_vertices, std::vector& input_faces, const AABBWrapper& sf_tree, const Parameters& params); bool is_out_envelope(const std::array& vs, const AABBWrapper& tree, const Parameters& params); Scalar get_angle_cos(const Vector3& p, const Vector3& p1, const Vector3& p2); - void check_surface(std::vector& input_vertices, std::vector& input_faces, const std::vector& is_f_removed, + void check_surface(std::vector& input_vertices, std::vector& input_faces, const std::vector& f_is_removed, const AABBWrapper& tree, const Parameters& params); void output_component(const std::vector& input_vertices, const std::vector& input_faces, const std::vector& input_tags);