From bcdb7a83c7e3fef2e333e6a09af99c0fd35f6976 Mon Sep 17 00:00:00 2001 From: zhouyuan chen <867442167@qq.com> Date: Sun, 25 Feb 2024 16:06:37 -0500 Subject: [PATCH 01/10] mesh_decimation first version --- components/CMakeLists.txt | 1 + components/tests/CMakeLists.txt | 1 - .../tests/test_component_mesh_decimation.cpp | 188 ++++++++++++++++++ .../components/mesh_decimation/CMakeLists.txt | 13 ++ .../internal/MeshDecimation.cpp | 172 ++++++++++++++++ .../internal/MeshDecimation.hpp | 29 +++ .../internal/MeshDecimationOptions.cpp | 28 +++ .../internal/MeshDecimationOptions.hpp | 26 +++ .../mesh_decimation/mesh_decimation.cpp | 6 + .../mesh_decimation/mesh_decimation.hpp | 15 ++ .../mesh_decimation/mesh_decimation_spec.json | 80 ++++++++ src/wmtk/invariants/CMakeLists.txt | 2 + .../invariants/SmallerFunctionInvariant.cpp | 39 ++++ .../invariants/SmallerFunctionInvariant.hpp | 32 +++ 14 files changed, 631 insertions(+), 1 deletion(-) create mode 100644 components/tests/test_component_mesh_decimation.cpp create mode 100644 components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/CMakeLists.txt create mode 100644 components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp create mode 100644 components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.hpp create mode 100644 components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp create mode 100644 components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp create mode 100644 components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp create mode 100644 components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.hpp create mode 100644 components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_spec.json create mode 100644 src/wmtk/invariants/SmallerFunctionInvariant.cpp create mode 100644 src/wmtk/invariants/SmallerFunctionInvariant.hpp diff --git a/components/CMakeLists.txt b/components/CMakeLists.txt index d75c1d9dda..be871a89a1 100644 --- a/components/CMakeLists.txt +++ b/components/CMakeLists.txt @@ -57,6 +57,7 @@ add_component(${WMTK_COMPONENT_PREFIX} "procedural") add_component(${WMTK_COMPONENT_PREFIX} "fusion") add_component(${WMTK_COMPONENT_PREFIX} "triangle_insertion") add_component(${WMTK_COMPONENT_PREFIX} "to_points") +add_component(${WMTK_COMPONENT_PREFIX} "mesh_decimation") string(LENGTH ${json_components} json_components_length) math(EXPR json_components_length "${json_components_length}-2") diff --git a/components/tests/CMakeLists.txt b/components/tests/CMakeLists.txt index 1de2a064a4..924f0607fc 100644 --- a/components/tests/CMakeLists.txt +++ b/components/tests/CMakeLists.txt @@ -17,7 +17,6 @@ wmtk::components) target_include_directories(${WMTK_COMPONENT_TEST_TARGET} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/..) target_compile_definitions(${WMTK_COMPONENT_TEST_TARGET} PRIVATE WMTK_TEST_DIR=\"${CMAKE_CURRENT_SOURCE_DIR}\") - FetchContent_GetProperties(catch2) list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras) include(Catch) diff --git a/components/tests/test_component_mesh_decimation.cpp b/components/tests/test_component_mesh_decimation.cpp new file mode 100644 index 0000000000..bdb953b695 --- /dev/null +++ b/components/tests/test_component_mesh_decimation.cpp @@ -0,0 +1,188 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include "wmtk/Scheduler.hpp" +#include "wmtk/function/simplex/AMIPS.hpp" +#include "wmtk/invariants/SimplexInversionInvariant.hpp" +#include "wmtk/invariants/SmallerFunctionInvariant.hpp" +#include "wmtk/invariants/TodoInvariant.hpp" +#include "wmtk/operations/EdgeCollapse.hpp" +#include "wmtk/operations/attribute_new/CollapseNewAttributeStrategy.hpp" +#include "wmtk/operations/attribute_update/AttributeTransferStrategy.hpp" + +using json = nlohmann::json; +using namespace wmtk; + +const std::filesystem::path data_dir = WMTK_DATA_DIR; + +TEST_CASE("preprocess", "[.]") +{ + using namespace wmtk::components; + + auto mesh_in = wmtk::read_mesh(data_dir / "3d_images/sphere_regularized.hdf5"); + Mesh& mesh = static_cast(*mesh_in); + + std::vector pass_though; + wmtk::attribute::MeshAttributeHandle vertex = + mesh.get_attribute_handle("vertex_tag", PrimitiveType::Vertex); + wmtk::attribute::MeshAttributeHandle edge = + mesh.get_attribute_handle("edge_tag", PrimitiveType::Edge); + wmtk::attribute::MeshAttributeHandle face = + mesh.get_attribute_handle("face_tag", PrimitiveType::Triangle); + pass_though.push_back(vertex); + pass_though.push_back(edge); + pass_though.push_back(face); + internal::MeshDecimation MD(mesh, "tag", 1, 5, pass_though); + MD.process(); + + wmtk::io::ParaviewWriter + writer(data_dir / "3d_images/out.hdf", "vertices", mesh, false, true, true, false); + mesh.serialize(writer); + + // wmtk::io::Cache cache("wmtk_cache", "."); + // cache.write_mesh(mesh, data_dir / "3d_images/kinderout"); +} + +TEST_CASE("preprocessss", "[.]") +{ + using namespace wmtk::attribute; + using namespace wmtk::invariants; + double target_len = 0.00026; + auto mesh_in = wmtk::read_mesh(data_dir / "3d_images/sphere_regularized.hdf5"); + TetMesh& mesh = static_cast(*mesh_in); + + wmtk::attribute::MeshAttributeHandle tet_handle = + mesh.get_attribute_handle("tag", PrimitiveType::Tetrahedron); + + wmtk::attribute::MeshAttributeHandle position = + mesh.get_attribute_handle("vertices", PrimitiveType::Vertex); + + wmtk::attribute::MeshAttributeHandle edge_handle = + mesh.register_attribute("todo_edge_", PrimitiveType::Edge, 1); + + wmtk::attribute::MeshAttributeHandle vertex_handle = + mesh.register_attribute("todo_vertex_", PrimitiveType::Vertex, 1); + + wmtk::attribute::MeshAttributeHandle edge_len_handle = + mesh.register_attribute("len_edge_", PrimitiveType::Edge, 1); + + Accessor acc_tet = mesh.create_accessor(tet_handle); + Accessor acc_edge = mesh.create_accessor(edge_handle); + Accessor acc_vertex = mesh.create_accessor(vertex_handle); + Accessor acc_pos = mesh.create_accessor(position); + Accessor acc_len = mesh.create_accessor(edge_len_handle); + + for (const Tuple& face : mesh.get_all(PrimitiveType::Triangle)) { + if (mesh.is_boundary_face(face)) { + acc_vertex.scalar_attribute(face) = 1; + acc_vertex.scalar_attribute(mesh.switch_vertex(face)) = 1; + acc_vertex.scalar_attribute(mesh.switch_vertex(mesh.switch_edge(face))) = 1; + + acc_edge.scalar_attribute(face) = 1; + acc_edge.scalar_attribute(mesh.switch_edge(face)) = 1; + acc_edge.scalar_attribute(mesh.switch_edge(mesh.switch_vertex(face))) = 1; + } else if ( + acc_tet.scalar_attribute(face) != + acc_tet.scalar_attribute(mesh.switch_tetrahedron(face))) { + acc_vertex.scalar_attribute(face) = 1; + acc_vertex.scalar_attribute(mesh.switch_vertex(face)) = 1; + acc_vertex.scalar_attribute(mesh.switch_vertex(mesh.switch_edge(face))) = 1; + + acc_edge.scalar_attribute(face) = 1; + acc_edge.scalar_attribute(mesh.switch_edge(face)) = 1; + acc_edge.scalar_attribute(mesh.switch_edge(mesh.switch_vertex(face))) = 1; + } + } + + for (const Tuple& edge : mesh.get_all(PrimitiveType::Edge)) { + if (acc_vertex.scalar_attribute(edge) == 1 || + acc_vertex.scalar_attribute(mesh.switch_vertex(edge)) == 1) { + acc_edge.scalar_attribute(edge) = 1; + } + acc_len.scalar_attribute(edge) = + (acc_pos.vector_attribute(edge) - acc_pos.vector_attribute(mesh.switch_vertex(edge))) + .norm(); + } + + auto op_scaffold = std::make_shared(mesh); + + op_scaffold->add_invariant(std::make_shared(mesh, edge_handle.as(), 0)); + op_scaffold->add_invariant(std::make_shared( + mesh, + edge_len_handle.as(), + 4.0 / 5.0 * target_len)); + + auto m_amips = std::make_shared(mesh, position); + auto m_link_conditions = std::make_shared(mesh); + auto m_function_invariant = std::make_shared( + mesh.top_simplex_type(), + m_amips, + 30); + auto m_inversion_invariant = + std::make_shared(mesh, position.as()); + + // Edge length update + auto compute_edge_length = [](const Eigen::MatrixXd& P) -> Eigen::VectorXd { + assert(P.cols() == 2); + assert(P.rows() == 2 || P.rows() == 3); + return Eigen::VectorXd::Constant(1, (P.col(0) - P.col(1)).norm()); + }; + auto m_edge_length_update = + std::make_shared>( + edge_len_handle, + position, + compute_edge_length); + auto m_prio_short_edges_first = [&](const simplex::Simplex& s) { + assert(s.primitive_type() == PrimitiveType::Edge); + auto acc = mesh.create_accessor(edge_len_handle); + return std::vector({acc.scalar_attribute(s.tuple())}); + }; + + + op_scaffold->add_invariant(m_link_conditions); + op_scaffold->add_invariant(m_function_invariant); + op_scaffold->add_invariant(m_inversion_invariant); + + op_scaffold->add_transfer_strategy(m_edge_length_update); + + op_scaffold->set_priority(m_prio_short_edges_first); + + op_scaffold->set_new_attribute_strategy( + position, + wmtk::operations::CollapseBasicStrategy::Mean); + op_scaffold->set_new_attribute_strategy(vertex_handle); + + op_scaffold->set_new_attribute_strategy(edge_handle); + op_scaffold->set_new_attribute_strategy(edge_len_handle); + op_scaffold->set_new_attribute_strategy(tet_handle); + + while (true) { + Scheduler scheduler; + SchedulerStats pass_stats = scheduler.run_operation_on_all(*op_scaffold); + if (pass_stats.number_of_successful_operations() == 0) break; + } + + wmtk::io::ParaviewWriter + writer(data_dir / "3d_images/kinderout.hdf", "vertices", mesh, false, true, true, false); + mesh.serialize(writer); + + wmtk::io::Cache cache("wmtk_cache", "."); + cache.write_mesh(mesh, data_dir / "3d_images/kinderout"); +} \ No newline at end of file diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/CMakeLists.txt b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/CMakeLists.txt new file mode 100644 index 0000000000..36dd007eee --- /dev/null +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/CMakeLists.txt @@ -0,0 +1,13 @@ + +set(SRC_FILES + internal/MeshDecimationOptions.hpp + internal/MeshDecimationOptions.cpp + internal/MeshDecimation.hpp + internal/MeshDecimation.cpp + mesh_decimation.hpp + mesh_decimation.cpp + ) + + +#CURRENT_COMPONENT_LIB_NAME is set from the main cmake +target_sources(${CURRENT_COMPONENT_LIB_NAME} PRIVATE ${SRC_FILES}) diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp new file mode 100644 index 0000000000..a644f05100 --- /dev/null +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp @@ -0,0 +1,172 @@ +#include "MeshDecimation.hpp" +#include "wmtk/Scheduler.hpp" +#include "wmtk/function/simplex/AMIPS.hpp" +#include "wmtk/invariants/MultiMeshLinkConditionInvariant.hpp" +#include "wmtk/invariants/SimplexInversionInvariant.hpp" +#include "wmtk/invariants/SmallerFunctionInvariant.hpp" +#include "wmtk/invariants/TodoInvariant.hpp" +#include "wmtk/operations/EdgeCollapse.hpp" +#include "wmtk/operations/attribute_new/CollapseNewAttributeStrategy.hpp" +#include "wmtk/operations/attribute_update/AttributeTransferStrategy.hpp" + +namespace wmtk::components::internal { + +MeshDecimation::MeshDecimation( + Mesh& mesh, + std::string constriant_name, + int64_t constrait_value, + double target_len, + const std::vector& pass_through_attributes) + : m_mesh(mesh) + , m_constriant_name(constriant_name) + , m_constrait_value(constrait_value) + , m_target_len(target_len) + , m_pass_through_attributes(pass_through_attributes) +{} + +void MeshDecimation::process() +{ + using namespace wmtk::attribute; + using namespace wmtk::invariants; + PrimitiveType PV = PrimitiveType::Vertex; + PrimitiveType PE = PrimitiveType::Edge; + PrimitiveType PF = PrimitiveType::Triangle; + PrimitiveType PT = PrimitiveType::Tetrahedron; + + volatile PrimitiveType x = m_mesh.top_simplex_type(); + + MeshAttributeHandle cell_tag_handle = + m_mesh.get_attribute_handle(m_constriant_name, m_mesh.top_simplex_type()); + MeshAttributeHandle position = m_mesh.get_attribute_handle("vertices", PV); + MeshAttributeHandle edge_handle = m_mesh.register_attribute("todo_edge_", PE, 1); + MeshAttributeHandle vertex_handle = m_mesh.register_attribute("todo_vertex_", PV, 1); + MeshAttributeHandle edge_len_handle = m_mesh.register_attribute("len_edge_", PE, 1); + + Accessor acc_cell = m_mesh.create_accessor(cell_tag_handle); + Accessor acc_pos = m_mesh.create_accessor(position); + Accessor acc_edge = m_mesh.create_accessor(edge_handle); + Accessor acc_vertex = m_mesh.create_accessor(vertex_handle); + Accessor acc_len = m_mesh.create_accessor(edge_len_handle); + + switch (m_mesh.top_cell_dimension()) { + case 2: + for (const Tuple& edge : m_mesh.get_all(PE)) { + if (m_mesh.is_boundary(PE, edge)) { + acc_vertex.scalar_attribute(edge) = 1; + acc_vertex.scalar_attribute(m_mesh.switch_tuple(edge, PV)) = 1; + + acc_edge.scalar_attribute(edge) = 1; + } else if ( + acc_cell.scalar_attribute(edge) != + acc_cell.scalar_attribute(m_mesh.switch_tuple(edge, PF))) { + acc_vertex.scalar_attribute(edge) = 1; + acc_vertex.scalar_attribute(m_mesh.switch_tuple(edge, PV)) = 1; + + acc_edge.scalar_attribute(edge) = 1; + } + } + break; + case 3: { + for (const Tuple& face : m_mesh.get_all(PF)) { + if (m_mesh.is_boundary(PF, face)) { + acc_vertex.scalar_attribute(face) = 1; + acc_vertex.scalar_attribute(m_mesh.switch_tuple(face, PV)) = 1; + acc_vertex.scalar_attribute(m_mesh.switch_tuples(face, {PE, PV})) = 1; + + acc_edge.scalar_attribute(face) = 1; + acc_edge.scalar_attribute(m_mesh.switch_tuple(face, PE)) = 1; + acc_edge.scalar_attribute(m_mesh.switch_tuples(face, {PV, PE})) = 1; + } else if ( + acc_cell.scalar_attribute(face) != + acc_cell.scalar_attribute(m_mesh.switch_tuple(face, PT))) { + acc_vertex.scalar_attribute(face) = 1; + acc_vertex.scalar_attribute(m_mesh.switch_tuple(face, PV)) = 1; + acc_vertex.scalar_attribute(m_mesh.switch_tuples(face, {PE, PV})) = 1; + + acc_edge.scalar_attribute(face) = 1; + acc_edge.scalar_attribute(m_mesh.switch_tuple(face, PE)) = 1; + acc_edge.scalar_attribute(m_mesh.switch_tuples(face, {PV, PE})) = 1; + } + } + break; + } + default: + std::runtime_error("MeshDecimation.cpp: mesh_decimation component only supports tetmesh " + "and trimesh for now!"); + } + + for (const Tuple& edge : m_mesh.get_all(PE)) { + if (acc_vertex.scalar_attribute(edge) == 1 || + acc_vertex.scalar_attribute(m_mesh.switch_tuple(edge, PV)) == 1) { + acc_edge.scalar_attribute(edge) = 1; + } + acc_len.scalar_attribute(edge) = (acc_pos.vector_attribute(edge) - + acc_pos.vector_attribute(m_mesh.switch_tuple(edge, PV))) + .norm(); + } + + auto op_scaffold = std::make_shared(m_mesh); + + op_scaffold->add_invariant( + std::make_shared(m_mesh, edge_handle.as(), 0)); + op_scaffold->add_invariant(std::make_shared( + m_mesh, + edge_len_handle.as(), + 4.0 / 5.0 * m_target_len)); + + auto m_amips = std::make_shared(m_mesh, position); + auto m_link_conditions = std::make_shared(m_mesh); + m_link_conditions->add(std::make_shared(m_mesh)); + auto m_function_invariant = + std::make_shared(m_mesh.top_simplex_type(), m_amips, 30); + auto m_inversion_invariant = + std::make_shared(m_mesh, position.as()); + + // Edge length update + auto compute_edge_length = [](const Eigen::MatrixXd& P) -> Eigen::VectorXd { + assert(P.cols() == 2); + assert(P.rows() == 2 || P.rows() == 3); + return Eigen::VectorXd::Constant(1, (P.col(0) - P.col(1)).norm()); + }; + auto m_edge_length_update = + std::make_shared>( + edge_len_handle, + position, + compute_edge_length); + auto m_prio_short_edges_first = [&](const simplex::Simplex& s) { + assert(s.primitive_type() == PrimitiveType::Edge); + auto acc = m_mesh.create_accessor(edge_len_handle); + return std::vector({acc.scalar_attribute(s.tuple())}); + }; + + + op_scaffold->add_invariant(m_link_conditions); + op_scaffold->add_invariant(m_function_invariant); + op_scaffold->add_invariant(m_inversion_invariant); + + op_scaffold->add_transfer_strategy(m_edge_length_update); + + op_scaffold->set_priority(m_prio_short_edges_first); + + op_scaffold->set_new_attribute_strategy( + position, + wmtk::operations::CollapseBasicStrategy::Mean); + op_scaffold->set_new_attribute_strategy(vertex_handle); + + op_scaffold->set_new_attribute_strategy(edge_handle); + op_scaffold->set_new_attribute_strategy(edge_len_handle); + op_scaffold->set_new_attribute_strategy(cell_tag_handle); + + // pass_through + for (const auto& attr : m_pass_through_attributes) { + op_scaffold->set_new_attribute_strategy(attr); + } + + while (true) { + Scheduler scheduler; + SchedulerStats pass_stats = scheduler.run_operation_on_all(*op_scaffold); + if (pass_stats.number_of_successful_operations() == 0) break; + } +} + +} // namespace wmtk::components::internal diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.hpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.hpp new file mode 100644 index 0000000000..becbb808e1 --- /dev/null +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.hpp @@ -0,0 +1,29 @@ +#pragma once + +#include + +namespace wmtk::components::internal { + +class MeshDecimation +{ +public: + MeshDecimation( + Mesh& mesh, + std::string constriant_name, + int64_t constrait_value, + double target_len, + const std::vector& pass_through_attributes); + + void process(); + +private: + Mesh& m_mesh; + + int64_t m_constrait_value; + std::string m_constriant_name; + double m_target_len; + + std::vector m_pass_through_attributes; +}; + +} // namespace wmtk::components::internal diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp new file mode 100644 index 0000000000..22a8756c1d --- /dev/null +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp @@ -0,0 +1,28 @@ +#include "MeshDecimationOptions.hpp" + +#include + +namespace wmtk::components::internal { + +void to_json(nlohmann::json& j, MeshDecimationOptions& o) +{ + j = { + {"input", o.input}, + {"output", o.output}, + {"constrait_value", o.constrait_value}, + {"decimation_factor", o.decimation_factor}, + {"tet_constrait_tag_name", o.tet_constrait_tag_name}, + {"pass_through", o.pass_through}}; +} + +void from_json(const nlohmann::json& j, MeshDecimationOptions& o) +{ + o.input = j.at("input"); + o.output = j.at("output"); + o.constrait_value = j.at("constrait_value"); + o.decimation_factor = j.at("decimation_factor"); + o.tet_constrait_tag_name = j.at("tet_constrait_tag_name"); + j.at("pass_through").get_to(o.pass_through); +} + +} // namespace wmtk::components::internal \ No newline at end of file diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp new file mode 100644 index 0000000000..7269299708 --- /dev/null +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include + +namespace wmtk { +namespace components { +namespace internal { + +struct MeshDecimationOptions +{ + std::string input; + std::string output; + int64_t constrait_value; + double decimation_factor; + std::string tet_constrait_tag_name; + std::vector pass_through; +}; + + +void to_json(nlohmann::json& j, MeshDecimationOptions& o); + +void from_json(const nlohmann::json& j, MeshDecimationOptions& o); + +} // namespace internal +} // namespace components +} // namespace wmtk \ No newline at end of file diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp new file mode 100644 index 0000000000..bb2e9e5775 --- /dev/null +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp @@ -0,0 +1,6 @@ +#include "mesh_decimation.hpp" + + +namespace wmtk::components { +void mesh_decimation(const base::Paths& paths, const nlohmann::json& j, io::Cache& cache) {} +} // namespace wmtk::components \ No newline at end of file diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.hpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.hpp new file mode 100644 index 0000000000..ae89b3e9dc --- /dev/null +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.hpp @@ -0,0 +1,15 @@ +#pragma once +#include +#include + +#include + + +namespace wmtk::components { + +/** + * @brief Perform decimation tetrahedra/triangles. + */ +void mesh_decimation(const base::Paths& paths, const nlohmann::json& j, io::Cache& cache); + +} // namespace wmtk::components diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_spec.json b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_spec.json new file mode 100644 index 0000000000..a438da6dd6 --- /dev/null +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_spec.json @@ -0,0 +1,80 @@ +[ + { + "pointer": "/", + "type": "object", + "required": [ + "input", + "output", + "attributes", + "input_values", + "output_value" + ], + "optional": ["pass_through", "filter_values"] + }, + { + "pointer": "/input", + "type": "string", + "doc": "input mesh" + }, + { + "pointer": "/output", + "type": "string", + "doc": "output mesh" + }, + { + "pointer": "/attributes", + "type": "object", + "required": "input_label", + "optional": "filter_labels", + "doc": "all attributes required for this component" + }, + { + "pointer": "/attributes/vertex_label", + "type": "string", + "doc": "The vertex int64_t attribute which is used for deciding if an edge should be split." + }, + { + "pointer": "/attributes/filter_labels", + "type": "list", + "default": [], + "doc": "List of edge int64_t attributes that are used as filter. Only if all given edge labels are present, an edge is considered for a split. If no edge labels are given, every edge is considered for splitting." + }, + { + "pointer": "/attributes/filter_labels/*", + "type": "string", + "doc": "Name of the edge int64_t attribute that is used as filter." + }, + + { + "pointer": "/input_values", + "type": "list", + "doc": "List of vertex labels that are considered in the split", + "min": 1, + "max": 2 + }, + { + "pointer": "/output_value", + "type": "int", + "doc": "The label that is assigned to new vertices emerging from a split, i.e. vertices that are on the isosurface." + }, + { + "pointer": "/filter_values", + "type": "list", + "doc": "Values for the edge filters. Each value corresponds to one edge filter" + }, + { + "pointer": "/filter_values/*", + "type": "int", + "doc": "Edge filter value." + }, + { + "pointer": "/pass_through", + "type": "list", + "default": [], + "doc": "all attributes that are not deleted by the component but also not required" + }, + { + "pointer": "/pass_through/*", + "type": "string" + } +] diff --git a/src/wmtk/invariants/CMakeLists.txt b/src/wmtk/invariants/CMakeLists.txt index c9d2c37365..65ca04d727 100644 --- a/src/wmtk/invariants/CMakeLists.txt +++ b/src/wmtk/invariants/CMakeLists.txt @@ -52,6 +52,8 @@ set(SRC_FILES FusionEdgeInvariant.hpp FusionEdgeInvariant.cpp + SmallerFunctionInvariant.hpp + SmallerFunctionInvariant.cpp internal/ConstantInvariant.hpp internal/ConstantInvariant.cpp diff --git a/src/wmtk/invariants/SmallerFunctionInvariant.cpp b/src/wmtk/invariants/SmallerFunctionInvariant.cpp new file mode 100644 index 0000000000..c7634953c6 --- /dev/null +++ b/src/wmtk/invariants/SmallerFunctionInvariant.cpp @@ -0,0 +1,39 @@ +#include "SmallerFunctionInvariant.hpp" + +#include +#include + +namespace wmtk::invariants { + +SmallerFunctionInvariant::SmallerFunctionInvariant( + const PrimitiveType type, + const std::shared_ptr& func, + const double max_value) + : Invariant(func->mesh()) + , m_func(func) + , m_max_value(max_value) + , m_type(type) +{} + +bool SmallerFunctionInvariant::after( + const std::vector& top_dimension_tuples_before, + const std::vector& top_dimension_tuples_after) const +{ + auto max = [&](const std::vector& tuples) { + double value = std::numeric_limits::lowest(); + for (const auto& t : tuples) + value = std::max(value, m_func->get_value(simplex::Simplex(m_type, t))); + + return value; + }; + const double after = max(top_dimension_tuples_after); + + if (after < m_max_value) { + return true; + } + + const double before = mesh().parent_scope(max, top_dimension_tuples_before); + + return after < before; +} +} // namespace wmtk::invariants \ No newline at end of file diff --git a/src/wmtk/invariants/SmallerFunctionInvariant.hpp b/src/wmtk/invariants/SmallerFunctionInvariant.hpp new file mode 100644 index 0000000000..9204ab4691 --- /dev/null +++ b/src/wmtk/invariants/SmallerFunctionInvariant.hpp @@ -0,0 +1,32 @@ +#pragma once + +#include +#include "Invariant.hpp" + +namespace wmtk { + +namespace function { +class PerSimplexFunction; +} + +namespace invariants { + +class SmallerFunctionInvariant : public Invariant +{ +public: + SmallerFunctionInvariant( + const PrimitiveType type, + const std::shared_ptr& func, + const double max_value); + + bool after( + const std::vector& top_dimension_tuples_before, + const std::vector& top_dimension_tuples_after) const override; + +private: + std::shared_ptr m_func; + const double m_max_value; + const PrimitiveType m_type; +}; +} // namespace invariants +} // namespace wmtk \ No newline at end of file From 67fe7013d759102189cef7b617cbccdde7648d2b Mon Sep 17 00:00:00 2001 From: zhouyuan chen <867442167@qq.com> Date: Sun, 25 Feb 2024 16:35:42 -0500 Subject: [PATCH 02/10] add a safe average length function --- .../internal/MeshDecimationOptions.cpp | 4 +- .../internal/MeshDecimationOptions.hpp | 2 +- .../mesh_decimation/mesh_decimation.cpp | 86 ++++++++++++++++++- 3 files changed, 88 insertions(+), 4 deletions(-) diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp index 22a8756c1d..2e636fa9a0 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp @@ -11,7 +11,7 @@ void to_json(nlohmann::json& j, MeshDecimationOptions& o) {"output", o.output}, {"constrait_value", o.constrait_value}, {"decimation_factor", o.decimation_factor}, - {"tet_constrait_tag_name", o.tet_constrait_tag_name}, + {"cell_constrait_tag_name", o.cell_constrait_tag_name}, {"pass_through", o.pass_through}}; } @@ -21,7 +21,7 @@ void from_json(const nlohmann::json& j, MeshDecimationOptions& o) o.output = j.at("output"); o.constrait_value = j.at("constrait_value"); o.decimation_factor = j.at("decimation_factor"); - o.tet_constrait_tag_name = j.at("tet_constrait_tag_name"); + o.cell_constrait_tag_name = j.at("cell_constrait_tag_name"); j.at("pass_through").get_to(o.pass_through); } diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp index 7269299708..4372fb8b57 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp @@ -12,7 +12,7 @@ struct MeshDecimationOptions std::string output; int64_t constrait_value; double decimation_factor; - std::string tet_constrait_tag_name; + std::string cell_constrait_tag_name; std::vector pass_through; }; diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp index bb2e9e5775..ecf3d77ead 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp @@ -1,6 +1,90 @@ #include "mesh_decimation.hpp" +#include "internal/MeshDecimation.hpp" +#include "internal/MeshDecimationOptions.hpp" namespace wmtk::components { -void mesh_decimation(const base::Paths& paths, const nlohmann::json& j, io::Cache& cache) {} + +// compute the length relative to the bounding box diagonal +double compute_target_len( + const attribute::MeshAttributeHandle& pos_handle, + const double decimation_relative_len_factor) +{ + auto pos = pos_handle.mesh().create_const_accessor(pos_handle); + const auto vertices = pos_handle.mesh().get_all(PrimitiveType::Vertex); + double avg = 0; + double cnt = 0; + for (const Tuple edge : pos_handle.mesh().get_all(PrimitiveType::Edge)) { + double len = + (pos.vector_attribute(edge) - + pos.vector_attribute(pos_handle.mesh().switch_tuple(edge, PrimitiveType::Vertex))) + .norm(); + avg = avg * cnt / (cnt + 1) + len / (cnt + 1); + cnt++; + } + + return avg * decimation_relative_len_factor; +} + +void mesh_decimation(const base::Paths& paths, const nlohmann::json& j, io::Cache& cache) +{ + using namespace internal; + + MeshDecimationOptions options = j.get(); + + // input + std::shared_ptr mesh_in = cache.read_mesh(options.input); + options.pass_through; + // vector<> + Mesh& mesh = static_cast(*mesh_in); + std::vector pass_though_attributes; + for (int i = 0; i < options.pass_through.size(); ++i) { + // base get attribute... + } + + MeshDecimation md( + mesh, + options.cell_constrait_tag_name, + options.constrait_value, + 1, + pass_though_attributes); + + // // clear attributes + // { + // std::vector keeps = pass_through_attributes; + // keeps.emplace_back(vertex_tag_handle); + // keeps.insert(keeps.end(), filter_labels.begin(), filter_labels.end()); + // mesh.clear_attributes(keeps); + // } + + // std::tie(vertex_tag_handle, filter_labels, pass_through_attributes) = + // gather_attributes(cache, mesh, options); + + // switch (mesh.top_cell_dimension()) { + // case 2: + // case 3: { + // // Marching mc(mesh, vertex_tags, options.output_vertex_tag, edge_filter_tags); + // Marching mc( + // mesh, + // vertex_tag_handle, + // options.input_values, + // options.output_value, + // filter_labels, + // options.filter_values, + // pass_through_attributes); + // mc.process(); + // } break; + // default: throw std::runtime_error("dimension setting error!"); break; + // } + + // // clear attributes + // { + // std::vector keeps = pass_through_attributes; + // keeps.emplace_back(vertex_tag_handle); + // keeps.insert(keeps.end(), filter_labels.begin(), filter_labels.end()); + // mesh.clear_attributes(keeps); + // } + + cache.write_mesh(*mesh_in, options.output); +} } // namespace wmtk::components \ No newline at end of file From 1042a16bd58ef642c061fae7f48e2a6aa348631d Mon Sep 17 00:00:00 2001 From: zhouyuan chen <867442167@qq.com> Date: Sun, 25 Feb 2024 22:37:36 -0500 Subject: [PATCH 03/10] finished mesh_decimation component --- cmake/recipes/tests/wmtk_data.cmake | 2 +- components/tests/integration_test.cpp | 76 ++++----- .../tests/test_component_mesh_decimation.cpp | 156 ++---------------- .../internal/MeshDecimation.cpp | 2 +- .../internal/MeshDecimationOptions.cpp | 4 +- .../internal/MeshDecimationOptions.hpp | 3 +- .../mesh_decimation/mesh_decimation.cpp | 77 ++------- .../mesh_decimation_example.json | 17 ++ .../mesh_decimation/mesh_decimation_spec.json | 57 ++----- 9 files changed, 106 insertions(+), 288 deletions(-) create mode 100644 components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_example.json diff --git a/cmake/recipes/tests/wmtk_data.cmake b/cmake/recipes/tests/wmtk_data.cmake index a84a29dff3..fae4141437 100644 --- a/cmake/recipes/tests/wmtk_data.cmake +++ b/cmake/recipes/tests/wmtk_data.cmake @@ -16,7 +16,7 @@ ExternalProject_Add( SOURCE_DIR ${WMTK_DATA_ROOT} GIT_REPOSITORY https://github.com/wildmeshing/data.git - GIT_TAG dfd3dc188aeb7e1c313e472db2ec56c5d14ba4b8 + GIT_TAG 964b4918ceafd14dd2b0dfa18358b6b985fedfc5 CONFIGURE_COMMAND "" BUILD_COMMAND "" diff --git a/components/tests/integration_test.cpp b/components/tests/integration_test.cpp index 97a95da4d9..80b40bb33e 100644 --- a/components/tests/integration_test.cpp +++ b/components/tests/integration_test.cpp @@ -58,16 +58,17 @@ int authenticate_json(const std::string& json_file, const bool compute_validatio in_args["root_path"] = json_file; - if (compute_validation && !contains_results(in_args)) { - spdlog::error("JSON file missing vertices edges faces or tetrahedra or meshes key. Add a * " - "to the beginning of filename to allow appends."); - return 2; - } - - //in_args["settings"] = R"({ - // "log_level": 5, - // "opt_log_level": 5 - // })"_json; + // if (compute_validation && !contains_results(in_args)) { + // spdlog::error("JSON file missing vertices edges faces or tetrahedra or meshes key. Add a + // * " + // "to the beginning of filename to allow appends."); + // return 2; + // } + + // in_args["settings"] = R"({ + // "log_level": 5, + // "opt_log_level": 5 + // })"_json; utils::set_random_seed(0); auto cache = wmtk::components::run_components(in_args, true); @@ -88,9 +89,10 @@ int authenticate_json(const std::string& json_file, const bool compute_validatio auto tetrahedra = in_args["tests"]["tetrahedra"]; if (meshes.size() != vertices.size() || meshes.size() != edges.size() || meshes.size() != faces.size() || meshes.size() != tetrahedra.size()) { - spdlog::error("JSON size missmatch between meshes and vertices edges faces or " - "tetrahedra or meshes key. Add a * " - "to the beginning of filename to allow appends."); + spdlog::error( + "JSON size missmatch between meshes and vertices edges faces or " + "tetrahedra or meshes key. Set true for the parameter \"compute_validation\"" + "to allow appends."); return 2; } @@ -174,29 +176,29 @@ std::string tagsrun = "[.][integration]"; #endif } // namespace -#define WMTK_INTEGRATION(NAME, DO_VALIDATION)\ -TEST_CASE(std::string("integration_") + NAME, tagsrun) \ -{ \ - std::string path = std::string("unit_test/") + NAME + ".json"; \ - bool compute_validation = DO_VALIDATION; \ - spdlog::info("Processing {}", NAME); \ - auto flag = authenticate_json(WMTK_DATA_DIR "/" + path, compute_validation); \ - REQUIRE(flag == 0); \ -} - +#define WMTK_INTEGRATION(NAME, DO_VALIDATION) \ + TEST_CASE(std::string("integration_") + NAME, tagsrun) \ + { \ + std::string path = std::string("unit_test/") + NAME + ".json"; \ + bool compute_validation = DO_VALIDATION; \ + spdlog::info("Processing {}", NAME); \ + auto flag = authenticate_json(WMTK_DATA_DIR "/" + path, compute_validation); \ + REQUIRE(flag == 0); \ + } -WMTK_INTEGRATION("input",false); -WMTK_INTEGRATION("to_points",false); -WMTK_INTEGRATION("delaunay",false); -WMTK_INTEGRATION("insertion",false); -WMTK_INTEGRATION("insertion_open",false); -WMTK_INTEGRATION("multimesh",false); -WMTK_INTEGRATION("multimesh_boundary_2d",false); -WMTK_INTEGRATION("multimesh_boundary_3d",false); -WMTK_INTEGRATION("isotropic_remeshing",false); -WMTK_INTEGRATION("isotropic_remeshing_mm",false); -WMTK_INTEGRATION("disk_fan_mm",false); -//WMTK_INTEGRATION("grid",false); -WMTK_INTEGRATION("wildmeshing_2d",false); -WMTK_INTEGRATION("wildmeshing_3d",false); +WMTK_INTEGRATION("input", false); +WMTK_INTEGRATION("to_points", false); +WMTK_INTEGRATION("delaunay", false); +WMTK_INTEGRATION("insertion", false); +WMTK_INTEGRATION("insertion_open", false); +WMTK_INTEGRATION("multimesh", false); +WMTK_INTEGRATION("multimesh_boundary_2d", false); +WMTK_INTEGRATION("multimesh_boundary_3d", false); +WMTK_INTEGRATION("isotropic_remeshing", false); +WMTK_INTEGRATION("isotropic_remeshing_mm", false); +WMTK_INTEGRATION("disk_fan_mm", false); +// WMTK_INTEGRATION("grid",false); +WMTK_INTEGRATION("wildmeshing_2d", false); +WMTK_INTEGRATION("wildmeshing_3d", false); +WMTK_INTEGRATION("mesh_decimation", false); \ No newline at end of file diff --git a/components/tests/test_component_mesh_decimation.cpp b/components/tests/test_component_mesh_decimation.cpp index bdb953b695..88d544e88a 100644 --- a/components/tests/test_component_mesh_decimation.cpp +++ b/components/tests/test_component_mesh_decimation.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -17,21 +18,26 @@ #include #include - -#include "wmtk/Scheduler.hpp" -#include "wmtk/function/simplex/AMIPS.hpp" -#include "wmtk/invariants/SimplexInversionInvariant.hpp" -#include "wmtk/invariants/SmallerFunctionInvariant.hpp" -#include "wmtk/invariants/TodoInvariant.hpp" -#include "wmtk/operations/EdgeCollapse.hpp" -#include "wmtk/operations/attribute_new/CollapseNewAttributeStrategy.hpp" -#include "wmtk/operations/attribute_update/AttributeTransferStrategy.hpp" - using json = nlohmann::json; using namespace wmtk; const std::filesystem::path data_dir = WMTK_DATA_DIR; +TEST_CASE("component_mesh_decimation_options", "[components][mesh_decimation]") +{ + using namespace components::internal; + + json o = { + {"input", "input_mesh"}, + {"output", "output_mesh"}, + {"constrait_value", 1}, + {"target_len", 1.0}, + {"cell_constrait_tag_name", "tag"}, + {"pass_through", {"vertices"}}}; + + CHECK_NOTHROW(o.get()); +} + TEST_CASE("preprocess", "[.]") { using namespace wmtk::components; @@ -55,134 +61,4 @@ TEST_CASE("preprocess", "[.]") wmtk::io::ParaviewWriter writer(data_dir / "3d_images/out.hdf", "vertices", mesh, false, true, true, false); mesh.serialize(writer); - - // wmtk::io::Cache cache("wmtk_cache", "."); - // cache.write_mesh(mesh, data_dir / "3d_images/kinderout"); -} - -TEST_CASE("preprocessss", "[.]") -{ - using namespace wmtk::attribute; - using namespace wmtk::invariants; - double target_len = 0.00026; - auto mesh_in = wmtk::read_mesh(data_dir / "3d_images/sphere_regularized.hdf5"); - TetMesh& mesh = static_cast(*mesh_in); - - wmtk::attribute::MeshAttributeHandle tet_handle = - mesh.get_attribute_handle("tag", PrimitiveType::Tetrahedron); - - wmtk::attribute::MeshAttributeHandle position = - mesh.get_attribute_handle("vertices", PrimitiveType::Vertex); - - wmtk::attribute::MeshAttributeHandle edge_handle = - mesh.register_attribute("todo_edge_", PrimitiveType::Edge, 1); - - wmtk::attribute::MeshAttributeHandle vertex_handle = - mesh.register_attribute("todo_vertex_", PrimitiveType::Vertex, 1); - - wmtk::attribute::MeshAttributeHandle edge_len_handle = - mesh.register_attribute("len_edge_", PrimitiveType::Edge, 1); - - Accessor acc_tet = mesh.create_accessor(tet_handle); - Accessor acc_edge = mesh.create_accessor(edge_handle); - Accessor acc_vertex = mesh.create_accessor(vertex_handle); - Accessor acc_pos = mesh.create_accessor(position); - Accessor acc_len = mesh.create_accessor(edge_len_handle); - - for (const Tuple& face : mesh.get_all(PrimitiveType::Triangle)) { - if (mesh.is_boundary_face(face)) { - acc_vertex.scalar_attribute(face) = 1; - acc_vertex.scalar_attribute(mesh.switch_vertex(face)) = 1; - acc_vertex.scalar_attribute(mesh.switch_vertex(mesh.switch_edge(face))) = 1; - - acc_edge.scalar_attribute(face) = 1; - acc_edge.scalar_attribute(mesh.switch_edge(face)) = 1; - acc_edge.scalar_attribute(mesh.switch_edge(mesh.switch_vertex(face))) = 1; - } else if ( - acc_tet.scalar_attribute(face) != - acc_tet.scalar_attribute(mesh.switch_tetrahedron(face))) { - acc_vertex.scalar_attribute(face) = 1; - acc_vertex.scalar_attribute(mesh.switch_vertex(face)) = 1; - acc_vertex.scalar_attribute(mesh.switch_vertex(mesh.switch_edge(face))) = 1; - - acc_edge.scalar_attribute(face) = 1; - acc_edge.scalar_attribute(mesh.switch_edge(face)) = 1; - acc_edge.scalar_attribute(mesh.switch_edge(mesh.switch_vertex(face))) = 1; - } - } - - for (const Tuple& edge : mesh.get_all(PrimitiveType::Edge)) { - if (acc_vertex.scalar_attribute(edge) == 1 || - acc_vertex.scalar_attribute(mesh.switch_vertex(edge)) == 1) { - acc_edge.scalar_attribute(edge) = 1; - } - acc_len.scalar_attribute(edge) = - (acc_pos.vector_attribute(edge) - acc_pos.vector_attribute(mesh.switch_vertex(edge))) - .norm(); - } - - auto op_scaffold = std::make_shared(mesh); - - op_scaffold->add_invariant(std::make_shared(mesh, edge_handle.as(), 0)); - op_scaffold->add_invariant(std::make_shared( - mesh, - edge_len_handle.as(), - 4.0 / 5.0 * target_len)); - - auto m_amips = std::make_shared(mesh, position); - auto m_link_conditions = std::make_shared(mesh); - auto m_function_invariant = std::make_shared( - mesh.top_simplex_type(), - m_amips, - 30); - auto m_inversion_invariant = - std::make_shared(mesh, position.as()); - - // Edge length update - auto compute_edge_length = [](const Eigen::MatrixXd& P) -> Eigen::VectorXd { - assert(P.cols() == 2); - assert(P.rows() == 2 || P.rows() == 3); - return Eigen::VectorXd::Constant(1, (P.col(0) - P.col(1)).norm()); - }; - auto m_edge_length_update = - std::make_shared>( - edge_len_handle, - position, - compute_edge_length); - auto m_prio_short_edges_first = [&](const simplex::Simplex& s) { - assert(s.primitive_type() == PrimitiveType::Edge); - auto acc = mesh.create_accessor(edge_len_handle); - return std::vector({acc.scalar_attribute(s.tuple())}); - }; - - - op_scaffold->add_invariant(m_link_conditions); - op_scaffold->add_invariant(m_function_invariant); - op_scaffold->add_invariant(m_inversion_invariant); - - op_scaffold->add_transfer_strategy(m_edge_length_update); - - op_scaffold->set_priority(m_prio_short_edges_first); - - op_scaffold->set_new_attribute_strategy( - position, - wmtk::operations::CollapseBasicStrategy::Mean); - op_scaffold->set_new_attribute_strategy(vertex_handle); - - op_scaffold->set_new_attribute_strategy(edge_handle); - op_scaffold->set_new_attribute_strategy(edge_len_handle); - op_scaffold->set_new_attribute_strategy(tet_handle); - - while (true) { - Scheduler scheduler; - SchedulerStats pass_stats = scheduler.run_operation_on_all(*op_scaffold); - if (pass_stats.number_of_successful_operations() == 0) break; - } - - wmtk::io::ParaviewWriter - writer(data_dir / "3d_images/kinderout.hdf", "vertices", mesh, false, true, true, false); - mesh.serialize(writer); - - wmtk::io::Cache cache("wmtk_cache", "."); - cache.write_mesh(mesh, data_dir / "3d_images/kinderout"); } \ No newline at end of file diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp index a644f05100..4436eafd5d 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp @@ -18,8 +18,8 @@ MeshDecimation::MeshDecimation( double target_len, const std::vector& pass_through_attributes) : m_mesh(mesh) - , m_constriant_name(constriant_name) , m_constrait_value(constrait_value) + , m_constriant_name(constriant_name) , m_target_len(target_len) , m_pass_through_attributes(pass_through_attributes) {} diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp index 2e636fa9a0..356b218557 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp @@ -10,7 +10,7 @@ void to_json(nlohmann::json& j, MeshDecimationOptions& o) {"input", o.input}, {"output", o.output}, {"constrait_value", o.constrait_value}, - {"decimation_factor", o.decimation_factor}, + {"target_len", o.target_len}, {"cell_constrait_tag_name", o.cell_constrait_tag_name}, {"pass_through", o.pass_through}}; } @@ -20,7 +20,7 @@ void from_json(const nlohmann::json& j, MeshDecimationOptions& o) o.input = j.at("input"); o.output = j.at("output"); o.constrait_value = j.at("constrait_value"); - o.decimation_factor = j.at("decimation_factor"); + o.target_len = j.at("target_len"); o.cell_constrait_tag_name = j.at("cell_constrait_tag_name"); j.at("pass_through").get_to(o.pass_through); } diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp index 4372fb8b57..fff2c16857 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp @@ -11,12 +11,11 @@ struct MeshDecimationOptions std::string input; std::string output; int64_t constrait_value; - double decimation_factor; + double target_len; std::string cell_constrait_tag_name; std::vector pass_through; }; - void to_json(nlohmann::json& j, MeshDecimationOptions& o); void from_json(const nlohmann::json& j, MeshDecimationOptions& o); diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp index ecf3d77ead..3dcefcaa88 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp @@ -1,31 +1,11 @@ #include "mesh_decimation.hpp" #include "internal/MeshDecimation.hpp" #include "internal/MeshDecimationOptions.hpp" +#include "wmtk/components/base/get_attributes.hpp" namespace wmtk::components { -// compute the length relative to the bounding box diagonal -double compute_target_len( - const attribute::MeshAttributeHandle& pos_handle, - const double decimation_relative_len_factor) -{ - auto pos = pos_handle.mesh().create_const_accessor(pos_handle); - const auto vertices = pos_handle.mesh().get_all(PrimitiveType::Vertex); - double avg = 0; - double cnt = 0; - for (const Tuple edge : pos_handle.mesh().get_all(PrimitiveType::Edge)) { - double len = - (pos.vector_attribute(edge) - - pos.vector_attribute(pos_handle.mesh().switch_tuple(edge, PrimitiveType::Vertex))) - .norm(); - avg = avg * cnt / (cnt + 1) + len / (cnt + 1); - cnt++; - } - - return avg * decimation_relative_len_factor; -} - void mesh_decimation(const base::Paths& paths, const nlohmann::json& j, io::Cache& cache) { using namespace internal; @@ -34,56 +14,29 @@ void mesh_decimation(const base::Paths& paths, const nlohmann::json& j, io::Cach // input std::shared_ptr mesh_in = cache.read_mesh(options.input); - options.pass_through; - // vector<> Mesh& mesh = static_cast(*mesh_in); - std::vector pass_though_attributes; - for (int i = 0; i < options.pass_through.size(); ++i) { - // base get attribute... + auto pass_through_attributes = base::get_attributes(cache, mesh, options.pass_through); + + // clear attributes + { + std::vector keeps = pass_through_attributes; + mesh.clear_attributes(keeps); } MeshDecimation md( mesh, options.cell_constrait_tag_name, options.constrait_value, - 1, - pass_though_attributes); - - // // clear attributes - // { - // std::vector keeps = pass_through_attributes; - // keeps.emplace_back(vertex_tag_handle); - // keeps.insert(keeps.end(), filter_labels.begin(), filter_labels.end()); - // mesh.clear_attributes(keeps); - // } + options.target_len, + pass_through_attributes); - // std::tie(vertex_tag_handle, filter_labels, pass_through_attributes) = - // gather_attributes(cache, mesh, options); + md.process(); - // switch (mesh.top_cell_dimension()) { - // case 2: - // case 3: { - // // Marching mc(mesh, vertex_tags, options.output_vertex_tag, edge_filter_tags); - // Marching mc( - // mesh, - // vertex_tag_handle, - // options.input_values, - // options.output_value, - // filter_labels, - // options.filter_values, - // pass_through_attributes); - // mc.process(); - // } break; - // default: throw std::runtime_error("dimension setting error!"); break; - // } - - // // clear attributes - // { - // std::vector keeps = pass_through_attributes; - // keeps.emplace_back(vertex_tag_handle); - // keeps.insert(keeps.end(), filter_labels.begin(), filter_labels.end()); - // mesh.clear_attributes(keeps); - // } + // clear attributes + { + std::vector keeps = pass_through_attributes; + mesh.clear_attributes(keeps); + } cache.write_mesh(*mesh_in, options.output); } diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_example.json b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_example.json new file mode 100644 index 0000000000..fd2f15fba9 --- /dev/null +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_example.json @@ -0,0 +1,17 @@ +{ + "components": [ + { + "mesh_decimation": { + "input": "input_mesh", + "output": "output_mesh", + "constrait_value": 1, + "target_len": 2.0, + "cell_constrait_tag_name": "tag", + "pass_through": [ + "vertices", + "tag" + ] + } + } + ] +} \ No newline at end of file diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_spec.json b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_spec.json index a438da6dd6..a0e0726391 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_spec.json +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_spec.json @@ -5,11 +5,13 @@ "required": [ "input", "output", - "attributes", - "input_values", - "output_value" + "constrait_value", + "target_len", + "cell_constrait_tag_name" ], - "optional": ["pass_through", "filter_values"] + "optional": [ + "pass_through" + ] }, { "pointer": "/input", @@ -22,50 +24,19 @@ "doc": "output mesh" }, { - "pointer": "/attributes", - "type": "object", - "required": "input_label", - "optional": "filter_labels", - "doc": "all attributes required for this component" - }, - { - "pointer": "/attributes/vertex_label", + "pointer": "/cell_constrait_tag_name", "type": "string", - "doc": "The vertex int64_t attribute which is used for deciding if an edge should be split." + "doc": "constrait_tag_handle's name" }, { - "pointer": "/attributes/filter_labels", - "type": "list", - "default": [], - "doc": "List of edge int64_t attributes that are used as filter. Only if all given edge labels are present, an edge is considered for a split. If no edge labels are given, every edge is considered for splitting." - }, - { - "pointer": "/attributes/filter_labels/*", - "type": "string", - "doc": "Name of the edge int64_t attribute that is used as filter." - }, - - { - "pointer": "/input_values", - "type": "list", - "doc": "List of vertex labels that are considered in the split", - "min": 1, - "max": 2 - }, - { - "pointer": "/output_value", + "pointer": "/constrait_value", "type": "int", - "doc": "The label that is assigned to new vertices emerging from a split, i.e. vertices that are on the isosurface." + "doc": "used for specific tagged simplices that we don't want to touch" }, { - "pointer": "/filter_values", - "type": "list", - "doc": "Values for the edge filters. Each value corresponds to one edge filter" - }, - { - "pointer": "/filter_values/*", - "type": "int", - "doc": "Edge filter value." + "pointer": "/target_len", + "type": "float", + "doc": "the decimation will make sure all edge will end with a length larger than target_len" }, { "pointer": "/pass_through", @@ -77,4 +48,4 @@ "pointer": "/pass_through/*", "type": "string" } -] +] \ No newline at end of file From 5eca7c3e75905a0765ae4309a2b3a718354f39f9 Mon Sep 17 00:00:00 2001 From: zhouyuan chen <867442167@qq.com> Date: Mon, 26 Feb 2024 18:18:03 -0500 Subject: [PATCH 04/10] cleanup the code and added 2d test --- cmake/recipes/tests/wmtk_data.cmake | 2 +- components/tests/integration_test.cpp | 12 ++-- .../tests/test_component_mesh_decimation.cpp | 70 +++++++++++++------ .../internal/MeshDecimation.cpp | 20 +++--- .../internal/MeshDecimation.hpp | 6 +- .../internal/MeshDecimationOptions.cpp | 4 +- .../internal/MeshDecimationOptions.hpp | 2 +- .../mesh_decimation/mesh_decimation.cpp | 15 ++-- .../mesh_decimation/mesh_decimation.hpp | 4 ++ .../mesh_decimation_example.json | 10 +-- .../mesh_decimation/mesh_decimation_spec.json | 18 +++-- 11 files changed, 99 insertions(+), 64 deletions(-) diff --git a/cmake/recipes/tests/wmtk_data.cmake b/cmake/recipes/tests/wmtk_data.cmake index fae4141437..f2a6af8623 100644 --- a/cmake/recipes/tests/wmtk_data.cmake +++ b/cmake/recipes/tests/wmtk_data.cmake @@ -16,7 +16,7 @@ ExternalProject_Add( SOURCE_DIR ${WMTK_DATA_ROOT} GIT_REPOSITORY https://github.com/wildmeshing/data.git - GIT_TAG 964b4918ceafd14dd2b0dfa18358b6b985fedfc5 + GIT_TAG 49eef87ea8e889bcdbe71dd31080833fa423392d CONFIGURE_COMMAND "" BUILD_COMMAND "" diff --git a/components/tests/integration_test.cpp b/components/tests/integration_test.cpp index 80b40bb33e..0ecce6cbc5 100644 --- a/components/tests/integration_test.cpp +++ b/components/tests/integration_test.cpp @@ -58,12 +58,12 @@ int authenticate_json(const std::string& json_file, const bool compute_validatio in_args["root_path"] = json_file; - // if (compute_validation && !contains_results(in_args)) { - // spdlog::error("JSON file missing vertices edges faces or tetrahedra or meshes key. Add a - // * " - // "to the beginning of filename to allow appends."); - // return 2; - // } + if (compute_validation && !contains_results(in_args)) { + spdlog::error("JSON file missing vertices edges faces or tetrahedra or meshes key. Add a * " + "to the beginning of filename to allow appends."); + return 2; + } + // in_args["settings"] = R"({ // "log_level": 5, diff --git a/components/tests/test_component_mesh_decimation.cpp b/components/tests/test_component_mesh_decimation.cpp index 88d544e88a..ff7bbf6c77 100644 --- a/components/tests/test_component_mesh_decimation.cpp +++ b/components/tests/test_component_mesh_decimation.cpp @@ -30,35 +30,65 @@ TEST_CASE("component_mesh_decimation_options", "[components][mesh_decimation]") json o = { {"input", "input_mesh"}, {"output", "output_mesh"}, - {"constrait_value", 1}, {"target_len", 1.0}, {"cell_constrait_tag_name", "tag"}, - {"pass_through", {"vertices"}}}; + {"attributes", {"vertices", "tag"}}, + {"pass_through", {"dummy"}}}; CHECK_NOTHROW(o.get()); } -TEST_CASE("preprocess", "[.]") +TEST_CASE("decimation_test", "[components][2D][3D]") { using namespace wmtk::components; - auto mesh_in = wmtk::read_mesh(data_dir / "3d_images/sphere_regularized.hdf5"); - Mesh& mesh = static_cast(*mesh_in); + SECTION("3D") + { + auto mesh_in = wmtk::read_mesh(data_dir / "unit_test/meshes/sphere_regularized.hdf5"); + Mesh& mesh = *mesh_in; - std::vector pass_though; - wmtk::attribute::MeshAttributeHandle vertex = - mesh.get_attribute_handle("vertex_tag", PrimitiveType::Vertex); - wmtk::attribute::MeshAttributeHandle edge = - mesh.get_attribute_handle("edge_tag", PrimitiveType::Edge); - wmtk::attribute::MeshAttributeHandle face = - mesh.get_attribute_handle("face_tag", PrimitiveType::Triangle); - pass_though.push_back(vertex); - pass_though.push_back(edge); - pass_though.push_back(face); - internal::MeshDecimation MD(mesh, "tag", 1, 5, pass_though); - MD.process(); + std::vector keep; + wmtk::attribute::MeshAttributeHandle constrait_cell_tag_handle = + mesh.get_attribute_handle("tag", mesh.top_simplex_type()); + wmtk::attribute::MeshAttributeHandle pos_handle = + mesh.get_attribute_handle("vertices", PrimitiveType::Vertex); + keep.emplace_back(constrait_cell_tag_handle); + keep.emplace_back(pos_handle); + mesh.clear_attributes(keep); - wmtk::io::ParaviewWriter - writer(data_dir / "3d_images/out.hdf", "vertices", mesh, false, true, true, false); - mesh.serialize(writer); + std::vector pass_though; + internal::MeshDecimation MD(mesh, constrait_cell_tag_handle, 5, pass_though); + MD.process(); + + if (false) { + wmtk::io::ParaviewWriter + writer(data_dir / "out3d.hdf", "vertices", mesh, false, true, true, true); + mesh.serialize(writer); + } + } + + SECTION("2D") + { + auto mesh_in = wmtk::read_mesh(data_dir / "2d/ellipse_layer/ellipse_01_substructure.hdf5"); + Mesh& mesh = *mesh_in; + + std::vector keep; + wmtk::attribute::MeshAttributeHandle constrait_cell_tag_handle = + mesh.get_attribute_handle("tag", mesh.top_simplex_type()); + wmtk::attribute::MeshAttributeHandle pos_handle = + mesh.get_attribute_handle("vertices", PrimitiveType::Vertex); + keep.emplace_back(constrait_cell_tag_handle); + keep.emplace_back(pos_handle); + mesh.clear_attributes(keep); + + std::vector pass_though; + internal::MeshDecimation MD(mesh, constrait_cell_tag_handle, 5, pass_though); + MD.process(); + + if (false) { + wmtk::io::ParaviewWriter + writer(data_dir / "out2d.hdf", "vertices", mesh, false, true, true, false); + mesh.serialize(writer); + } + } } \ No newline at end of file diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp index 4436eafd5d..324fc33b45 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp @@ -13,13 +13,11 @@ namespace wmtk::components::internal { MeshDecimation::MeshDecimation( Mesh& mesh, - std::string constriant_name, - int64_t constrait_value, + attribute::MeshAttributeHandle constraited_cell_tag_handle, double target_len, const std::vector& pass_through_attributes) : m_mesh(mesh) - , m_constrait_value(constrait_value) - , m_constriant_name(constriant_name) + , m_constraited_cell_tag_handle(constraited_cell_tag_handle) , m_target_len(target_len) , m_pass_through_attributes(pass_through_attributes) {} @@ -35,8 +33,7 @@ void MeshDecimation::process() volatile PrimitiveType x = m_mesh.top_simplex_type(); - MeshAttributeHandle cell_tag_handle = - m_mesh.get_attribute_handle(m_constriant_name, m_mesh.top_simplex_type()); + MeshAttributeHandle& cell_tag_handle = m_constraited_cell_tag_handle; MeshAttributeHandle position = m_mesh.get_attribute_handle("vertices", PV); MeshAttributeHandle edge_handle = m_mesh.register_attribute("todo_edge_", PE, 1); MeshAttributeHandle vertex_handle = m_mesh.register_attribute("todo_vertex_", PV, 1); @@ -109,10 +106,8 @@ void MeshDecimation::process() op_scaffold->add_invariant( std::make_shared(m_mesh, edge_handle.as(), 0)); - op_scaffold->add_invariant(std::make_shared( - m_mesh, - edge_len_handle.as(), - 4.0 / 5.0 * m_target_len)); + op_scaffold->add_invariant( + std::make_shared(m_mesh, edge_len_handle.as(), m_target_len)); auto m_amips = std::make_shared(m_mesh, position); auto m_link_conditions = std::make_shared(m_mesh); @@ -165,7 +160,10 @@ void MeshDecimation::process() while (true) { Scheduler scheduler; SchedulerStats pass_stats = scheduler.run_operation_on_all(*op_scaffold); - if (pass_stats.number_of_successful_operations() == 0) break; + if (pass_stats.number_of_successful_operations() == 0) { + break; + } + m_mesh.consolidate(); } } diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.hpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.hpp index becbb808e1..197e2780dc 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.hpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.hpp @@ -9,8 +9,7 @@ class MeshDecimation public: MeshDecimation( Mesh& mesh, - std::string constriant_name, - int64_t constrait_value, + attribute::MeshAttributeHandle constraited_cell_tag_handle, double target_len, const std::vector& pass_through_attributes); @@ -19,8 +18,7 @@ class MeshDecimation private: Mesh& m_mesh; - int64_t m_constrait_value; - std::string m_constriant_name; + attribute::MeshAttributeHandle m_constraited_cell_tag_handle; double m_target_len; std::vector m_pass_through_attributes; diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp index 356b218557..3fbb8fb197 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp @@ -9,9 +9,9 @@ void to_json(nlohmann::json& j, MeshDecimationOptions& o) j = { {"input", o.input}, {"output", o.output}, - {"constrait_value", o.constrait_value}, {"target_len", o.target_len}, {"cell_constrait_tag_name", o.cell_constrait_tag_name}, + {"attributes", o.attributes}, {"pass_through", o.pass_through}}; } @@ -19,9 +19,9 @@ void from_json(const nlohmann::json& j, MeshDecimationOptions& o) { o.input = j.at("input"); o.output = j.at("output"); - o.constrait_value = j.at("constrait_value"); o.target_len = j.at("target_len"); o.cell_constrait_tag_name = j.at("cell_constrait_tag_name"); + j.at("attributes").get_to(o.attributes); j.at("pass_through").get_to(o.pass_through); } diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp index fff2c16857..3962ba46b9 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp @@ -10,9 +10,9 @@ struct MeshDecimationOptions { std::string input; std::string output; - int64_t constrait_value; double target_len; std::string cell_constrait_tag_name; + std::vector attributes; std::vector pass_through; }; diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp index 3dcefcaa88..0614f93763 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp @@ -14,27 +14,28 @@ void mesh_decimation(const base::Paths& paths, const nlohmann::json& j, io::Cach // input std::shared_ptr mesh_in = cache.read_mesh(options.input); - Mesh& mesh = static_cast(*mesh_in); + Mesh& mesh = *mesh_in; auto pass_through_attributes = base::get_attributes(cache, mesh, options.pass_through); + auto original_attributes = base::get_attributes(cache, mesh, options.attributes); + auto cell_constrait_tag_handle = mesh.get_attribute_handle( + options.cell_constrait_tag_name, + mesh.top_simplex_type()); // clear attributes { std::vector keeps = pass_through_attributes; + keeps.insert(keeps.end(), original_attributes.begin(), original_attributes.end()); mesh.clear_attributes(keeps); } - MeshDecimation md( - mesh, - options.cell_constrait_tag_name, - options.constrait_value, - options.target_len, - pass_through_attributes); + MeshDecimation md(mesh, cell_constrait_tag_handle, options.target_len, pass_through_attributes); md.process(); // clear attributes { std::vector keeps = pass_through_attributes; + keeps.insert(keeps.end(), original_attributes.begin(), original_attributes.end()); mesh.clear_attributes(keeps); } diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.hpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.hpp index ae89b3e9dc..e9efa045bc 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.hpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.hpp @@ -9,6 +9,10 @@ namespace wmtk::components { /** * @brief Perform decimation tetrahedra/triangles. + * If you given a mesh and the tag of the top simplex. then this component will + * preserve the tagged mesh's boundary edge and the edges incident to different + * tagged simplices. And decimate the mesh until the all edge need to collapse + * are large or equal the target length. */ void mesh_decimation(const base::Paths& paths, const nlohmann::json& j, io::Cache& cache); diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_example.json b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_example.json index fd2f15fba9..a9a017ddc0 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_example.json +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_example.json @@ -4,13 +4,13 @@ "mesh_decimation": { "input": "input_mesh", "output": "output_mesh", - "constrait_value": 1, "target_len": 2.0, "cell_constrait_tag_name": "tag", - "pass_through": [ - "vertices", - "tag" - ] + "attributes": [ + "tag", + "vertices" + ], + "pass_through": [] } } ] diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_spec.json b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_spec.json index a0e0726391..8ab52ec8da 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_spec.json +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_spec.json @@ -5,9 +5,9 @@ "required": [ "input", "output", - "constrait_value", "target_len", - "cell_constrait_tag_name" + "cell_constrait_tag_name", + "attributes" ], "optional": [ "pass_through" @@ -28,16 +28,20 @@ "type": "string", "doc": "constrait_tag_handle's name" }, - { - "pointer": "/constrait_value", - "type": "int", - "doc": "used for specific tagged simplices that we don't want to touch" - }, { "pointer": "/target_len", "type": "float", "doc": "the decimation will make sure all edge will end with a length larger than target_len" }, + { + "pointer": "/attributes", + "type": "list", + "doc": "the original attributes" + }, + { + "pointer": "/attributes/*", + "type": "string" + }, { "pointer": "/pass_through", "type": "list", From cbeebb46b8e5d8a2087311f14d8ebec45b3f23ec Mon Sep 17 00:00:00 2001 From: zhouyuan chen <867442167@qq.com> Date: Tue, 27 Feb 2024 09:14:24 -0500 Subject: [PATCH 05/10] re-arrange the order of the invariants --- .../wmtk/components/mesh_decimation/internal/MeshDecimation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp index 324fc33b45..4df11e17d6 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp @@ -136,8 +136,8 @@ void MeshDecimation::process() op_scaffold->add_invariant(m_link_conditions); - op_scaffold->add_invariant(m_function_invariant); op_scaffold->add_invariant(m_inversion_invariant); + op_scaffold->add_invariant(m_function_invariant); op_scaffold->add_transfer_strategy(m_edge_length_update); From 23ca6bb6ef7c5b29e8dc5b73daf099ec34361074 Mon Sep 17 00:00:00 2001 From: zhouyuan chen <867442167@qq.com> Date: Tue, 27 Feb 2024 15:46:00 -0500 Subject: [PATCH 06/10] keep incident tet --- cmake/recipes/tests/wmtk_data.cmake | 2 +- .../mesh_decimation/internal/MeshDecimation.cpp | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/cmake/recipes/tests/wmtk_data.cmake b/cmake/recipes/tests/wmtk_data.cmake index f2a6af8623..b1cde1f05c 100644 --- a/cmake/recipes/tests/wmtk_data.cmake +++ b/cmake/recipes/tests/wmtk_data.cmake @@ -16,7 +16,7 @@ ExternalProject_Add( SOURCE_DIR ${WMTK_DATA_ROOT} GIT_REPOSITORY https://github.com/wildmeshing/data.git - GIT_TAG 49eef87ea8e889bcdbe71dd31080833fa423392d + GIT_TAG 27adb7b676193faf260ae42265f4db151d8a84a0 CONFIGURE_COMMAND "" BUILD_COMMAND "" diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp index 4df11e17d6..4ceb51e8f9 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp @@ -102,6 +102,20 @@ void MeshDecimation::process() .norm(); } + for (const Tuple& edge : m_mesh.get_all(PE)) { + if (acc_edge.scalar_attribute(edge) == 1) { + acc_vertex.scalar_attribute(edge) = 1; + acc_vertex.scalar_attribute(m_mesh.switch_tuple(edge, PV)) = 1; + } + } + + for (const Tuple& edge : m_mesh.get_all(PE)) { + if (acc_vertex.scalar_attribute(edge) == 1 || + acc_vertex.scalar_attribute(m_mesh.switch_tuple(edge, PV)) == 1) { + acc_edge.scalar_attribute(edge) = 1; + } + } + auto op_scaffold = std::make_shared(m_mesh); op_scaffold->add_invariant( From 38b2574e15c9907a9d371fd471bc2c0b419509af Mon Sep 17 00:00:00 2001 From: zhouyuan chen <867442167@qq.com> Date: Tue, 27 Feb 2024 15:51:21 -0500 Subject: [PATCH 07/10] change the collapse operation name --- .../internal/MeshDecimation.cpp | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp index 4ceb51e8f9..4b97f872a2 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp @@ -116,11 +116,11 @@ void MeshDecimation::process() } } - auto op_scaffold = std::make_shared(m_mesh); + auto op_collapse = std::make_shared(m_mesh); - op_scaffold->add_invariant( + op_collapse->add_invariant( std::make_shared(m_mesh, edge_handle.as(), 0)); - op_scaffold->add_invariant( + op_collapse->add_invariant( std::make_shared(m_mesh, edge_len_handle.as(), m_target_len)); auto m_amips = std::make_shared(m_mesh, position); @@ -149,31 +149,31 @@ void MeshDecimation::process() }; - op_scaffold->add_invariant(m_link_conditions); - op_scaffold->add_invariant(m_inversion_invariant); - op_scaffold->add_invariant(m_function_invariant); + op_collapse->add_invariant(m_link_conditions); + op_collapse->add_invariant(m_inversion_invariant); + op_collapse->add_invariant(m_function_invariant); - op_scaffold->add_transfer_strategy(m_edge_length_update); + op_collapse->add_transfer_strategy(m_edge_length_update); - op_scaffold->set_priority(m_prio_short_edges_first); + op_collapse->set_priority(m_prio_short_edges_first); - op_scaffold->set_new_attribute_strategy( + op_collapse->set_new_attribute_strategy( position, wmtk::operations::CollapseBasicStrategy::Mean); - op_scaffold->set_new_attribute_strategy(vertex_handle); + op_collapse->set_new_attribute_strategy(vertex_handle); - op_scaffold->set_new_attribute_strategy(edge_handle); - op_scaffold->set_new_attribute_strategy(edge_len_handle); - op_scaffold->set_new_attribute_strategy(cell_tag_handle); + op_collapse->set_new_attribute_strategy(edge_handle); + op_collapse->set_new_attribute_strategy(edge_len_handle); + op_collapse->set_new_attribute_strategy(cell_tag_handle); // pass_through for (const auto& attr : m_pass_through_attributes) { - op_scaffold->set_new_attribute_strategy(attr); + op_collapse->set_new_attribute_strategy(attr); } while (true) { Scheduler scheduler; - SchedulerStats pass_stats = scheduler.run_operation_on_all(*op_scaffold); + SchedulerStats pass_stats = scheduler.run_operation_on_all(*op_collapse); if (pass_stats.number_of_successful_operations() == 0) { break; } From b50ccb516831c39c25229b2e8a6d751cfe90af04 Mon Sep 17 00:00:00 2001 From: zhouyuan chen <867442167@qq.com> Date: Tue, 27 Feb 2024 23:44:09 -0500 Subject: [PATCH 08/10] refine the compnent --- cmake/recipes/tests/wmtk_data.cmake | 2 +- .../tests/test_component_mesh_decimation.cpp | 23 ++--- .../internal/MeshDecimation.cpp | 92 ++++++++++--------- .../internal/MeshDecimation.hpp | 4 +- .../internal/MeshDecimationOptions.cpp | 4 +- .../internal/MeshDecimationOptions.hpp | 2 +- .../mesh_decimation/mesh_decimation.cpp | 2 +- .../mesh_decimation_example.json | 2 +- .../mesh_decimation/mesh_decimation_spec.json | 6 +- 9 files changed, 67 insertions(+), 70 deletions(-) diff --git a/cmake/recipes/tests/wmtk_data.cmake b/cmake/recipes/tests/wmtk_data.cmake index b1cde1f05c..cb9a45fb57 100644 --- a/cmake/recipes/tests/wmtk_data.cmake +++ b/cmake/recipes/tests/wmtk_data.cmake @@ -16,7 +16,7 @@ ExternalProject_Add( SOURCE_DIR ${WMTK_DATA_ROOT} GIT_REPOSITORY https://github.com/wildmeshing/data.git - GIT_TAG 27adb7b676193faf260ae42265f4db151d8a84a0 + GIT_TAG 3dae1070163ebccc61abdd36e59dc4ca2c6f0beb CONFIGURE_COMMAND "" BUILD_COMMAND "" diff --git a/components/tests/test_component_mesh_decimation.cpp b/components/tests/test_component_mesh_decimation.cpp index ff7bbf6c77..e5157f1ede 100644 --- a/components/tests/test_component_mesh_decimation.cpp +++ b/components/tests/test_component_mesh_decimation.cpp @@ -31,7 +31,7 @@ TEST_CASE("component_mesh_decimation_options", "[components][mesh_decimation]") {"input", "input_mesh"}, {"output", "output_mesh"}, {"target_len", 1.0}, - {"cell_constrait_tag_name", "tag"}, + {"cell_constraint_tag_name", "tag"}, {"attributes", {"vertices", "tag"}}, {"pass_through", {"dummy"}}}; @@ -41,6 +41,7 @@ TEST_CASE("component_mesh_decimation_options", "[components][mesh_decimation]") TEST_CASE("decimation_test", "[components][2D][3D]") { using namespace wmtk::components; + wmtk::io::Cache cache("wmtk_cache", "."); SECTION("3D") { @@ -57,14 +58,10 @@ TEST_CASE("decimation_test", "[components][2D][3D]") mesh.clear_attributes(keep); std::vector pass_though; - internal::MeshDecimation MD(mesh, constrait_cell_tag_handle, 5, pass_though); - MD.process(); + internal::MeshDecimation md(mesh, constrait_cell_tag_handle, 5, pass_though); + md.process(); - if (false) { - wmtk::io::ParaviewWriter - writer(data_dir / "out3d.hdf", "vertices", mesh, false, true, true, true); - mesh.serialize(writer); - } + cache.write_mesh(mesh, "out3d"); } SECTION("2D") @@ -82,13 +79,9 @@ TEST_CASE("decimation_test", "[components][2D][3D]") mesh.clear_attributes(keep); std::vector pass_though; - internal::MeshDecimation MD(mesh, constrait_cell_tag_handle, 5, pass_though); - MD.process(); + internal::MeshDecimation md(mesh, constrait_cell_tag_handle, 5, pass_though); + md.process(); - if (false) { - wmtk::io::ParaviewWriter - writer(data_dir / "out2d.hdf", "vertices", mesh, false, true, true, false); - mesh.serialize(writer); - } + cache.write_mesh(mesh, "out2d"); } } \ No newline at end of file diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp index 4b97f872a2..164cb0177b 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp @@ -8,16 +8,17 @@ #include "wmtk/operations/EdgeCollapse.hpp" #include "wmtk/operations/attribute_new/CollapseNewAttributeStrategy.hpp" #include "wmtk/operations/attribute_update/AttributeTransferStrategy.hpp" +#include "wmtk/utils/Logger.hpp" namespace wmtk::components::internal { MeshDecimation::MeshDecimation( Mesh& mesh, - attribute::MeshAttributeHandle constraited_cell_tag_handle, + attribute::MeshAttributeHandle constrainted_cell_tag_handle, double target_len, const std::vector& pass_through_attributes) : m_mesh(mesh) - , m_constraited_cell_tag_handle(constraited_cell_tag_handle) + , m_constrainted_cell_tag_handle(constrainted_cell_tag_handle) , m_target_len(target_len) , m_pass_through_attributes(pass_through_attributes) {} @@ -26,27 +27,29 @@ void MeshDecimation::process() { using namespace wmtk::attribute; using namespace wmtk::invariants; - PrimitiveType PV = PrimitiveType::Vertex; - PrimitiveType PE = PrimitiveType::Edge; - PrimitiveType PF = PrimitiveType::Triangle; - PrimitiveType PT = PrimitiveType::Tetrahedron; + constexpr PrimitiveType PV = PrimitiveType::Vertex; + constexpr PrimitiveType PE = PrimitiveType::Edge; + constexpr PrimitiveType PF = PrimitiveType::Triangle; + constexpr PrimitiveType PT = PrimitiveType::Tetrahedron; - volatile PrimitiveType x = m_mesh.top_simplex_type(); - - MeshAttributeHandle& cell_tag_handle = m_constraited_cell_tag_handle; + MeshAttributeHandle& cell_tag_handle = m_constrainted_cell_tag_handle; MeshAttributeHandle position = m_mesh.get_attribute_handle("vertices", PV); - MeshAttributeHandle edge_handle = m_mesh.register_attribute("todo_edge_", PE, 1); - MeshAttributeHandle vertex_handle = m_mesh.register_attribute("todo_vertex_", PV, 1); - MeshAttributeHandle edge_len_handle = m_mesh.register_attribute("len_edge_", PE, 1); + MeshAttributeHandle todo_edge_handle = + m_mesh.register_attribute("mesh_decimation_todo_edge", PE, 1); + MeshAttributeHandle todo_vertex_handle = + m_mesh.register_attribute("mesh_decimation_todo_vertex", PV, 1); + MeshAttributeHandle edge_len_handle = + m_mesh.register_attribute("mesh_decimation_edge_len", PE, 1); Accessor acc_cell = m_mesh.create_accessor(cell_tag_handle); Accessor acc_pos = m_mesh.create_accessor(position); - Accessor acc_edge = m_mesh.create_accessor(edge_handle); - Accessor acc_vertex = m_mesh.create_accessor(vertex_handle); + Accessor acc_edge = m_mesh.create_accessor(todo_edge_handle); + Accessor acc_vertex = m_mesh.create_accessor(todo_vertex_handle); Accessor acc_len = m_mesh.create_accessor(edge_len_handle); - switch (m_mesh.top_cell_dimension()) { - case 2: + // build edge tag to protect to topology of the tagged input + switch (m_mesh.top_simplex_type()) { + case PF: for (const Tuple& edge : m_mesh.get_all(PE)) { if (m_mesh.is_boundary(PE, edge)) { acc_vertex.scalar_attribute(edge) = 1; @@ -63,7 +66,7 @@ void MeshDecimation::process() } } break; - case 3: { + case PT: { for (const Tuple& face : m_mesh.get_all(PF)) { if (m_mesh.is_boundary(PF, face)) { acc_vertex.scalar_attribute(face) = 1; @@ -87,28 +90,28 @@ void MeshDecimation::process() } break; } + case PE: + case PV: default: - std::runtime_error("MeshDecimation.cpp: mesh_decimation component only supports tetmesh " - "and trimesh for now!"); + log_and_throw_error("MeshDecimation.cpp: mesh_decimation component only supports tetmesh " + "and trimesh for now!"); } + // stage 1: tag edges incident to the surface for (const Tuple& edge : m_mesh.get_all(PE)) { if (acc_vertex.scalar_attribute(edge) == 1 || acc_vertex.scalar_attribute(m_mesh.switch_tuple(edge, PV)) == 1) { acc_edge.scalar_attribute(edge) = 1; } - acc_len.scalar_attribute(edge) = (acc_pos.vector_attribute(edge) - - acc_pos.vector_attribute(m_mesh.switch_tuple(edge, PV))) - .norm(); } - + // stage 2: tag vertices incident to the tagged edge for (const Tuple& edge : m_mesh.get_all(PE)) { if (acc_edge.scalar_attribute(edge) == 1) { acc_vertex.scalar_attribute(edge) = 1; acc_vertex.scalar_attribute(m_mesh.switch_tuple(edge, PV)) = 1; } } - + // stage 3: tag edges incident to the tagged vertices for (const Tuple& edge : m_mesh.get_all(PE)) { if (acc_vertex.scalar_attribute(edge) == 1 || acc_vertex.scalar_attribute(m_mesh.switch_tuple(edge, PV)) == 1) { @@ -116,53 +119,54 @@ void MeshDecimation::process() } } - auto op_collapse = std::make_shared(m_mesh); - - op_collapse->add_invariant( - std::make_shared(m_mesh, edge_handle.as(), 0)); - op_collapse->add_invariant( - std::make_shared(m_mesh, edge_len_handle.as(), m_target_len)); - - auto m_amips = std::make_shared(m_mesh, position); - auto m_link_conditions = std::make_shared(m_mesh); - m_link_conditions->add(std::make_shared(m_mesh)); - auto m_function_invariant = - std::make_shared(m_mesh.top_simplex_type(), m_amips, 30); - auto m_inversion_invariant = - std::make_shared(m_mesh, position.as()); - - // Edge length update + // Storing edge lengths and Edge length update auto compute_edge_length = [](const Eigen::MatrixXd& P) -> Eigen::VectorXd { assert(P.cols() == 2); assert(P.rows() == 2 || P.rows() == 3); return Eigen::VectorXd::Constant(1, (P.col(0) - P.col(1)).norm()); }; - auto m_edge_length_update = + auto edge_length_update = std::make_shared>( edge_len_handle, position, compute_edge_length); + edge_length_update->run_on_all(); + auto m_prio_short_edges_first = [&](const simplex::Simplex& s) { assert(s.primitive_type() == PrimitiveType::Edge); auto acc = m_mesh.create_accessor(edge_len_handle); return std::vector({acc.scalar_attribute(s.tuple())}); }; + auto op_collapse = std::make_shared(m_mesh); + + op_collapse->add_invariant( + std::make_shared(m_mesh, todo_edge_handle.as(), 0)); + op_collapse->add_invariant( + std::make_shared(m_mesh, edge_len_handle.as(), m_target_len)); + + auto m_amips = std::make_shared(m_mesh, position); + auto m_link_conditions = std::make_shared(m_mesh); + m_link_conditions->add(std::make_shared(m_mesh)); + auto m_function_invariant = + std::make_shared(m_mesh.top_simplex_type(), m_amips, 30); + auto m_inversion_invariant = + std::make_shared(m_mesh, position.as()); op_collapse->add_invariant(m_link_conditions); op_collapse->add_invariant(m_inversion_invariant); op_collapse->add_invariant(m_function_invariant); - op_collapse->add_transfer_strategy(m_edge_length_update); + op_collapse->add_transfer_strategy(edge_length_update); op_collapse->set_priority(m_prio_short_edges_first); op_collapse->set_new_attribute_strategy( position, wmtk::operations::CollapseBasicStrategy::Mean); - op_collapse->set_new_attribute_strategy(vertex_handle); + op_collapse->set_new_attribute_strategy(todo_vertex_handle); - op_collapse->set_new_attribute_strategy(edge_handle); + op_collapse->set_new_attribute_strategy(todo_edge_handle); op_collapse->set_new_attribute_strategy(edge_len_handle); op_collapse->set_new_attribute_strategy(cell_tag_handle); diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.hpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.hpp index 197e2780dc..f569a456da 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.hpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.hpp @@ -9,7 +9,7 @@ class MeshDecimation public: MeshDecimation( Mesh& mesh, - attribute::MeshAttributeHandle constraited_cell_tag_handle, + attribute::MeshAttributeHandle constrainted_cell_tag_handle, double target_len, const std::vector& pass_through_attributes); @@ -18,7 +18,7 @@ class MeshDecimation private: Mesh& m_mesh; - attribute::MeshAttributeHandle m_constraited_cell_tag_handle; + attribute::MeshAttributeHandle m_constrainted_cell_tag_handle; double m_target_len; std::vector m_pass_through_attributes; diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp index 3fbb8fb197..8d4c596a32 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.cpp @@ -10,7 +10,7 @@ void to_json(nlohmann::json& j, MeshDecimationOptions& o) {"input", o.input}, {"output", o.output}, {"target_len", o.target_len}, - {"cell_constrait_tag_name", o.cell_constrait_tag_name}, + {"cell_constraint_tag_name", o.cell_constraint_tag_name}, {"attributes", o.attributes}, {"pass_through", o.pass_through}}; } @@ -20,7 +20,7 @@ void from_json(const nlohmann::json& j, MeshDecimationOptions& o) o.input = j.at("input"); o.output = j.at("output"); o.target_len = j.at("target_len"); - o.cell_constrait_tag_name = j.at("cell_constrait_tag_name"); + o.cell_constraint_tag_name = j.at("cell_constraint_tag_name"); j.at("attributes").get_to(o.attributes); j.at("pass_through").get_to(o.pass_through); } diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp index 3962ba46b9..e89f2fda9d 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimationOptions.hpp @@ -11,7 +11,7 @@ struct MeshDecimationOptions std::string input; std::string output; double target_len; - std::string cell_constrait_tag_name; + std::string cell_constraint_tag_name; std::vector attributes; std::vector pass_through; }; diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp index 0614f93763..4fc72bbd83 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation.cpp @@ -18,7 +18,7 @@ void mesh_decimation(const base::Paths& paths, const nlohmann::json& j, io::Cach auto pass_through_attributes = base::get_attributes(cache, mesh, options.pass_through); auto original_attributes = base::get_attributes(cache, mesh, options.attributes); auto cell_constrait_tag_handle = mesh.get_attribute_handle( - options.cell_constrait_tag_name, + options.cell_constraint_tag_name, mesh.top_simplex_type()); // clear attributes diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_example.json b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_example.json index a9a017ddc0..b1cc246eef 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_example.json +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_example.json @@ -5,7 +5,7 @@ "input": "input_mesh", "output": "output_mesh", "target_len": 2.0, - "cell_constrait_tag_name": "tag", + "cell_constraint_tag_name": "tag", "attributes": [ "tag", "vertices" diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_spec.json b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_spec.json index 8ab52ec8da..1804914310 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_spec.json +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/mesh_decimation_spec.json @@ -6,7 +6,7 @@ "input", "output", "target_len", - "cell_constrait_tag_name", + "cell_constraint_tag_name", "attributes" ], "optional": [ @@ -24,9 +24,9 @@ "doc": "output mesh" }, { - "pointer": "/cell_constrait_tag_name", + "pointer": "/cell_constraint_tag_name", "type": "string", - "doc": "constrait_tag_handle's name" + "doc": "constraint_tag_handle's name" }, { "pointer": "/target_len", From d6818770d2baf04f42d064e1ec5fdfef6e905862 Mon Sep 17 00:00:00 2001 From: Zhouyuan Chen <867442167@qq.com> Date: Fri, 15 Mar 2024 14:36:35 -0400 Subject: [PATCH 09/10] consolidate before checking convergence --- .../wmtk/components/mesh_decimation/internal/MeshDecimation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp index 164cb0177b..64aa3d3d5f 100644 --- a/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp +++ b/components/wmtk_components/mesh_decimation/wmtk/components/mesh_decimation/internal/MeshDecimation.cpp @@ -178,10 +178,10 @@ void MeshDecimation::process() while (true) { Scheduler scheduler; SchedulerStats pass_stats = scheduler.run_operation_on_all(*op_collapse); + m_mesh.consolidate(); if (pass_stats.number_of_successful_operations() == 0) { break; } - m_mesh.consolidate(); } } From fb6a53a28eec9eff71e6f9d4f69933bcee28d068 Mon Sep 17 00:00:00 2001 From: zhouyuan chen <867442167@qq.com> Date: Sat, 23 Mar 2024 23:06:16 -0400 Subject: [PATCH 10/10] rename the test --- components/tests/test_component_mesh_decimation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/tests/test_component_mesh_decimation.cpp b/components/tests/test_component_mesh_decimation.cpp index e5157f1ede..f315c5bfbe 100644 --- a/components/tests/test_component_mesh_decimation.cpp +++ b/components/tests/test_component_mesh_decimation.cpp @@ -38,7 +38,7 @@ TEST_CASE("component_mesh_decimation_options", "[components][mesh_decimation]") CHECK_NOTHROW(o.get()); } -TEST_CASE("decimation_test", "[components][2D][3D]") +TEST_CASE("component_mesh_decimation", "[components][2D][3D]") { using namespace wmtk::components; wmtk::io::Cache cache("wmtk_cache", ".");