diff --git a/README.md b/README.md index 147687a..62976b1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,14 @@ # ImplicitSurfaceNetwork -extract explicit mesh with topology information from implicit surfaces with boolean operations. \ No newline at end of file +extract explicit mesh with topology information from implicit surfaces with boolean operations. + + +## Key Concepts + +- **primitive**: A basic geometric object, such as a sphere, cube, or cylinder, which serves as the building block for complex shapes. Primitives are the input elements for boolean operations. + +- **subface**: A geometric fragment or patch of a primitive. For example, a cube has six subfaces (its faces), a cylinder has three (side, top, bottom), and a sphere has one (its surface). Subfaces are used to precisely track and propagate geometric and topological information during boolean and labeling operations. + +- **shell**: A watertight surface formed by connecting one or more subfaces (or their patches). Shells act as the boundaries that separate different spatial regions (cells) after the arrangement of primitives and their subfaces. + +- **cell**: A spatial region enclosed by a set of shells. After all primitives and their subfaces are arranged and combined, the space is partitioned into multiple non-overlapping cells, each bounded by shells. Cells are the fundamental units for labeling, boolean evaluation, and mesh extraction. diff --git a/application/main.cpp b/application/main.cpp index 6437509..5010d36 100644 --- a/application/main.cpp +++ b/application/main.cpp @@ -1,15 +1,42 @@ #include #include +#include +#include +#include #include +// filepath: c:\Users\mckay\programs\ImplicitSurfaceNetwork\application\main.cpp +void write_obj(const polymesh_t& mesh, std::string filename = "output.obj") { + std::ofstream obj(filename); + if (!obj) return; + + // 写入顶点 + for (uint32_t i = 0; i < mesh.num_vertices; ++i) { + const auto& v = mesh.vertices[i]; + obj << "v " << v.x << " " << v.y << " " << v.z << "\n"; + } + + // 写入面 + uint32_t idx = 0; + for (uint32_t i = 0; i < mesh.num_faces; ++i) { + obj << "f"; + for (uint32_t j = 0; j < mesh.vertex_counts[i]; ++j) { + // OBJ 索引从1开始 + obj << " " << (mesh.faces[idx++] + 1); + } + obj << "\n"; + } + std::cout << "OBJ file written to: " << std::filesystem::absolute(filename) << std::endl; +} + int main() { auto primitive_data_center = create_primitive_data_center(); auto sphere1 = create_primitive(primitive_data_center, PRIMITIVE_TYPE_SPHERE); // auto sphere2 = create_primitive(primitive_data_center, PRIMITIVE_TYPE_SPHERE); auto cylinder = create_primitive(primitive_data_center, PRIMITIVE_TYPE_CYLINDER); - primitive_apply_translation(sphere1, {1.0, 0.0, 0.0}); + primitive_apply_translation(sphere1, {0.5, 0.0, 0.0}); std::cout << "primitive created..." << std::endl; auto runtime_blobtree = create_blobtree(); @@ -28,6 +55,7 @@ int main() auto solver = create_solver(baked_blobtree, settings); auto result = generate_polymesh(solver); + write_obj(result.mesh, "output.obj"); print_statistics(solver); destroy_solver(solver); diff --git a/network_process/src/post_topo/patch_propagation.cpp b/network_process/src/post_topo/patch_propagation.cpp index 81c71a5..68ce1fb 100644 --- a/network_process/src/post_topo/patch_propagation.cpp +++ b/network_process/src/post_topo/patch_propagation.cpp @@ -112,7 +112,21 @@ void propagate_subface_labels(const baked_blobtree_t& tree void transform_subface_to_primitive_labels(const baked_blobtree_t& tree, const stl_vector_mp>& cell_subface_signs, stl_vector_mp>& cell_primitive_signs) -{ +{ + std::cout << "transform_subface_to_primitive_labels debug info: " << std::endl; + for (size_t i = 0; i < cell_subface_signs.size(); ++i) { + std::cout << "Subface " << i << " subface signs: " << std::endl; + for (size_t j = 0; j < cell_subface_signs[i].size(); ++j) { + std::cout << " subface sign for cell " << j << ": " << cell_subface_signs[i][j] << std::endl; + } + } + for (size_t j = 0; j < cell_subface_signs[0].size(); ++j) { + std::cout << "Cell " << j << " subface signs: " ; + for (size_t i = 0; i < cell_subface_signs.size(); ++i) { + std::cout << " " << cell_subface_signs[i][j]; + } + std::cout << std::endl; + } stl_vector_mp> temp_subface_signs{}; for (size_t i = 0; i < tree.primitives.size(); ++i) { auto& cell_primitive_sign = cell_primitive_signs[i]; @@ -121,9 +135,11 @@ void transform_subface_to_primitive_labels(const baked_blobtree_t& temp_subface_signs.clear(); temp_subface_signs.reserve(subface_indices.size()); - for (const auto& subface_index : subface_indices) temp_subface_signs.emplace_back(cell_subface_signs[subface_index]); + for (const auto& subface_index : subface_indices) + temp_subface_signs.emplace_back(cell_subface_signs[subface_index]); cell_primitive_sign = primitive.judge_sign_by_subface_sign(temp_subface_signs); + std::cout << "primitive " << i << " sign: " << cell_primitive_sign << std::endl; } } diff --git a/network_process/src/process.cpp b/network_process/src/process.cpp index 36fea8c..c5ff3a7 100644 --- a/network_process/src/process.cpp +++ b/network_process/src/process.cpp @@ -106,10 +106,7 @@ ISNP_API void build_implicit_network_by_blobtree(const s_settings& { arrangement_cells.reserve(shells.size()); for (uint32_t i = 0; i < shells.size(); ++i) { arrangement_cells.emplace_back(stl_vector_mp{i}); } - shell_to_cell.resize(shells.size()); - for (uint32_t i = 0; i < arrangement_cells.size(); i++) { - for (auto shell : arrangement_cells[i]) shell_to_cell[shell] = i; - } + } else { { stl_vector_mp> shell_links{}; @@ -129,6 +126,10 @@ ISNP_API void build_implicit_network_by_blobtree(const s_settings& compute_arrangement_cells(static_cast(shells.size()), shell_links, arrangement_cells); } } + shell_to_cell.resize(shells.size()); + for (uint32_t i = 0; i < arrangement_cells.size(); i++) { + for (auto shell : arrangement_cells[i]) shell_to_cell[shell] = i; + } // post process { dynamic_bitset_mp<> active_cell_label{};