Browse Source

fixed a few of bugs with solver;

now it can work on a variety of cases.
Known bug: due to current design of primitive, some primitives with sharp rounding may not be detected, so that their integrand may not be correct, as well as their output mesh.
gjj
Zhicheng Wang 2 months ago
parent
commit
105f7e6012
  1. 7
      frontend/src/implicit_surface_network_processor.cpp
  2. 1
      frontend/src/patch_propagator.cpp
  3. 5
      implicit_arrangements/src/ia_cut_1_face.cpp
  4. 28
      network_process/interface/extract_patch.hpp
  5. 22
      network_process/interface/pair_faces.hpp
  6. 22
      network_process/interface/topology_ray_shooting.hpp
  7. 26
      network_process/src/extract_patch.cpp
  8. 30
      network_process/src/pair_faces.cpp
  9. 34
      network_process/src/topology_ray_shooting.cpp

7
frontend/src/implicit_surface_network_processor.cpp

@ -2,6 +2,7 @@
#include <extract_patch.hpp>
#include <implicit_arrangement.hpp>
#include <optional>
#include <patch_connectivity.hpp>
#include <pair_faces.hpp>
#include <topology_ray_shooting.hpp>
@ -129,7 +130,7 @@ solve_result_t ImplicitSurfaceNetworkProcessor::run(const virtual_node_t& tree_n
// compute arrangement in each tet
// HINT: we skip robust test for this part for now
stl_vector_mp<std::shared_ptr<arrangement_t>> cut_results{};
stl_vector_mp<std::optional<arrangement_t>> cut_results{};
uint32_t num_1_func = 0;
uint32_t num_2_func = 0;
uint32_t num_more_func = 0;
@ -143,7 +144,7 @@ solve_result_t ImplicitSurfaceNetworkProcessor::run(const virtual_node_t& tree_n
const auto start_index = start_index_of_tet[i];
const auto active_funcs_in_curr_tet = start_index_of_tet[i + 1] - start_index;
if (active_funcs_in_curr_tet == 0) {
cut_results.emplace_back(nullptr);
cut_results.emplace_back(std::nullopt);
continue;
}
g_timers_manager.push_timer(active_funcs_in_curr_tet == 1
@ -160,7 +161,7 @@ solve_result_t ImplicitSurfaceNetworkProcessor::run(const virtual_node_t& tree_n
-vertex_scalar_values[tet[2]][fid],
-vertex_scalar_values[tet[3]][fid]});
}
cut_results.emplace_back(std::make_shared<arrangement_t>(std::move(compute_arrangement(planes))));
cut_results.emplace_back(std::move(compute_arrangement(planes)));
switch (active_funcs_in_curr_tet) {
case 1:
g_timers_manager.pop_timer("implicit arrangements calculation (1 func)");

1
frontend/src/patch_propagator.cpp

@ -215,6 +215,7 @@ dynamic_bitset_mp<> PatchPropagator::filter_cells_by_boolean(const virtual_node_
const stl_vector_mp<uint32_t>& leaf_index_of_primitive,
const stl_vector_mp<dynamic_bitset_mp<>>& function_cell_labels)
{
// system("pause");
const auto num_funcs = get_primitive_count();
const auto num_cells = function_cell_labels[0].size();
const auto max_parent_node_index = tree_root.inner_index;

5
implicit_arrangements/src/ia_cut_1_face.cpp

@ -33,8 +33,9 @@ std::array<uint32_t, 3> ia_cut_1_face(ia_complex_t& ia_complex,
return static_cast<uint32_t>(vertices.size() - 1);
};
// do nothing if edge is coplanar with plane (o0 == 0 && o1 == 0)
if (o0 >= 0 && o1 >= 0) {
if (o0 == 0 && o1 == 0) {
// do nothing if edge is coplanar with plane (o0 == 0 && o1 == 0)
} else if (o0 >= 0 && o1 >= 0) {
positive_subedge_id = eid;
} else if (o0 <= 0 && o1 <= 0) {
negative_subedge_id = eid;

28
network_process/interface/extract_patch.hpp

@ -3,17 +3,17 @@
#include <utils/fwd_types.hpp>
// extract iso-mesh (topology only)
ISNP_API void extract_iso_mesh(uint32_t num_1_func,
uint32_t num_2_func,
uint32_t num_more_func,
const stl_vector_mp<std::shared_ptr<arrangement_t>>& cut_results,
const stl_vector_mp<uint32_t>& func_in_tet,
const stl_vector_mp<uint32_t>& start_index_of_tet,
const tetrahedron_mesh_t& background_mesh,
const stl_vector_mp<stl_vector_mp<double>>& func_vals,
stl_vector_mp<raw_point_t>& iso_pts,
stl_vector_mp<iso_vertex_t>& iso_verts,
stl_vector_mp<polygon_face_t>& iso_faces);
ISNP_API void extract_iso_mesh(uint32_t num_1_func,
uint32_t num_2_func,
uint32_t num_more_func,
const stl_vector_mp<std::optional<arrangement_t>>& cut_results,
const stl_vector_mp<uint32_t>& func_in_tet,
const stl_vector_mp<uint32_t>& start_index_of_tet,
const tetrahedron_mesh_t& background_mesh,
const stl_vector_mp<stl_vector_mp<double>>& func_vals,
stl_vector_mp<raw_point_t>& iso_pts,
stl_vector_mp<iso_vertex_t>& iso_verts,
stl_vector_mp<polygon_face_t>& iso_faces);
// given the list of vertex indices of a face, return the unique key of the face: (the smallest vert Id,
// second-smallest vert Id, the largest vert Id) assume: face_verts is a list of non-duplicate natural
@ -24,8 +24,8 @@ ISNP_API void compute_iso_face_key(const stl_vector_mp<uint32_t>& face_verts, po
// Point in tet cell
template <typename Scalar>
inline std::array<Scalar, 4> compute_barycentric_coords(const std::array<Scalar, 4>& plane1,
const std::array<Scalar, 4>& plane2,
const std::array<Scalar, 4>& plane3)
const std::array<Scalar, 4>& plane2,
const std::array<Scalar, 4>& plane3)
{
Scalar n1 = plane1[3] * (plane2[2] * plane3[1] - plane2[1] * plane3[2])
+ plane1[2] * (plane2[1] * plane3[3] - plane2[3] * plane3[1])
@ -47,7 +47,7 @@ inline std::array<Scalar, 4> compute_barycentric_coords(const std::array<Scalar,
// Point on tet face
template <typename Scalar>
inline std::array<Scalar, 3> compute_barycentric_coords(const std::array<Scalar, 3>& plane1,
const std::array<Scalar, 3>& plane2)
const std::array<Scalar, 3>& plane2)
{
Scalar n1 = plane1[2] * plane2[1] - plane1[1] * plane2[2];
Scalar n2 = plane1[0] * plane2[2] - plane1[2] * plane2[0];

22
network_process/interface/pair_faces.hpp

@ -12,7 +12,7 @@ ISNP_API void compute_patch_order(const iso_edge_t
const stl_vector_mp<tetrahedron_vertex_indices_t> &tets,
const stl_vector_mp<iso_vertex_t> &iso_verts,
const stl_vector_mp<polygon_face_t> &iso_faces,
const stl_vector_mp<std::shared_ptr<arrangement_t>> &cut_results,
const stl_vector_mp<std::optional<arrangement_t>> &cut_results,
const stl_vector_mp<uint32_t> &func_in_tet,
const stl_vector_mp<uint32_t> &start_index_of_tet,
const flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>> &incident_tets,
@ -29,13 +29,13 @@ ISNP_API void pair_patches_in_one_tet(const arrangement_t &te
// compute neighboring pair of half-patches around an iso-edge in multiple tetrahedrons
// half-patch adjacency list : (patch i, 1) <--> 2i, (patch i, -1) <--> 2i+1
ISNP_API void pair_patches_in_tets(const iso_edge_t &iso_edge,
const stl_vector_mp<uint32_t> &containing_simplex,
const stl_vector_mp<uint32_t> &containing_tetIds,
const stl_vector_mp<tetrahedron_vertex_indices_t> &tets,
const stl_vector_mp<polygon_face_t> &iso_faces,
const stl_vector_mp<std::shared_ptr<arrangement_t>> &cut_results,
const stl_vector_mp<uint32_t> &func_in_tet,
const stl_vector_mp<uint32_t> &start_index_of_tet,
const stl_vector_mp<uint32_t> &patch_of_face_mapping,
stl_vector_mp<stl_vector_mp<uint32_t>> &half_patch_adj_list);
ISNP_API void pair_patches_in_tets(const iso_edge_t &iso_edge,
const stl_vector_mp<uint32_t> &containing_simplex,
const stl_vector_mp<uint32_t> &containing_tetIds,
const stl_vector_mp<tetrahedron_vertex_indices_t> &tets,
const stl_vector_mp<polygon_face_t> &iso_faces,
const stl_vector_mp<std::optional<arrangement_t>> &cut_results,
const stl_vector_mp<uint32_t> &func_in_tet,
const stl_vector_mp<uint32_t> &start_index_of_tet,
const stl_vector_mp<uint32_t> &patch_of_face_mapping,
stl_vector_mp<stl_vector_mp<uint32_t>> &half_patch_adj_list);

22
network_process/interface/topology_ray_shooting.hpp

@ -74,17 +74,17 @@ struct equal_to<face_with_orient_t> {
} // namespace std
// topological ray shooting for implicit arrangement
ISNP_API void topo_ray_shooting(const tetrahedron_mesh_t &tet_mesh,
const stl_vector_mp<std::shared_ptr<arrangement_t>> &cut_results,
const stl_vector_mp<iso_vertex_t> &iso_verts,
const stl_vector_mp<polygon_face_t> &iso_faces,
const stl_vector_mp<stl_vector_mp<uint32_t>> &patches,
const stl_vector_mp<uint32_t> &patch_of_face,
const stl_vector_mp<stl_vector_mp<uint32_t>> &shells,
const stl_vector_mp<uint32_t> &shell_of_half_patch,
const stl_vector_mp<stl_vector_mp<uint32_t>> &components,
const stl_vector_mp<uint32_t> &component_of_patch,
stl_vector_mp<std::pair<uint32_t, uint32_t>> &shell_links);
ISNP_API void topo_ray_shooting(const tetrahedron_mesh_t &tet_mesh,
const stl_vector_mp<std::optional<arrangement_t>> &cut_results,
const stl_vector_mp<iso_vertex_t> &iso_verts,
const stl_vector_mp<polygon_face_t> &iso_faces,
const stl_vector_mp<stl_vector_mp<uint32_t>> &patches,
const stl_vector_mp<uint32_t> &patch_of_face,
const stl_vector_mp<stl_vector_mp<uint32_t>> &shells,
const stl_vector_mp<uint32_t> &shell_of_half_patch,
const stl_vector_mp<stl_vector_mp<uint32_t>> &components,
const stl_vector_mp<uint32_t> &component_of_patch,
stl_vector_mp<std::pair<uint32_t, uint32_t>> &shell_links);
// Given tet mesh,
// build the map: v-->v_next, where v_next has lower order than v

26
network_process/src/extract_patch.cpp

@ -4,17 +4,17 @@
/// EDIT: swap the 1st and the 2nd indices of func_vals
/// TODO: compress implicit function indices into uint16_t instead of uint32_t
ISNP_API void extract_iso_mesh(uint32_t num_1_func,
uint32_t num_2_func,
uint32_t num_more_func,
const stl_vector_mp<std::shared_ptr<arrangement_t>>& cut_results,
const stl_vector_mp<uint32_t>& func_in_tet,
const stl_vector_mp<uint32_t>& start_index_of_tet,
const tetrahedron_mesh_t& background_mesh,
const stl_vector_mp<stl_vector_mp<double>>& func_vals,
stl_vector_mp<raw_point_t>& iso_pts,
stl_vector_mp<iso_vertex_t>& iso_verts,
stl_vector_mp<polygon_face_t>& iso_faces)
ISNP_API void extract_iso_mesh(uint32_t num_1_func,
uint32_t num_2_func,
uint32_t num_more_func,
const stl_vector_mp<std::optional<arrangement_t>>& cut_results,
const stl_vector_mp<uint32_t>& func_in_tet,
const stl_vector_mp<uint32_t>& start_index_of_tet,
const tetrahedron_mesh_t& background_mesh,
const stl_vector_mp<stl_vector_mp<double>>& func_vals,
stl_vector_mp<raw_point_t>& iso_pts,
stl_vector_mp<iso_vertex_t>& iso_verts,
stl_vector_mp<polygon_face_t>& iso_faces)
{
const auto& pts = background_mesh.vertices;
const auto& tets = background_mesh.indices;
@ -56,8 +56,8 @@ ISNP_API void extract_iso_mesh(uint32_t
//
for (uint32_t i = 0; i < n_tets; i++) {
if (cut_results[i]) {
const auto& arrangement = *cut_results[i].get();
if (cut_results[i].has_value()) {
const auto& arrangement = cut_results[i].value();
const auto& vertices = arrangement.vertices;
const auto& faces = arrangement.faces;
auto start_index = start_index_of_tet[i];

30
network_process/src/pair_faces.cpp

@ -9,7 +9,7 @@ ISNP_API void compute_patch_order(const iso_edge_t
const stl_vector_mp<tetrahedron_vertex_indices_t> &tets,
const stl_vector_mp<iso_vertex_t> &iso_verts,
const stl_vector_mp<polygon_face_t> &iso_faces,
const stl_vector_mp<std::shared_ptr<arrangement_t>> &cut_results,
const stl_vector_mp<std::optional<arrangement_t>> &cut_results,
const stl_vector_mp<uint32_t> &func_in_tet,
const stl_vector_mp<uint32_t> &start_index_of_tet,
const flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>> &incident_tets,
@ -31,7 +31,7 @@ ISNP_API void compute_patch_order(const iso_edge_t
if (containing_tets.size() == 1) {
// std::cout << ">>>>>>>> iso-edge in tet" << std::endl;
auto tet_id = *containing_tets.begin();
pair_patches_in_one_tet(*cut_results[tet_id].get(), iso_faces, iso_edge, patch_of_face_mapping, half_patch_adj_list);
pair_patches_in_one_tet(cut_results[tet_id].value(), iso_faces, iso_edge, patch_of_face_mapping, half_patch_adj_list);
} else {
const auto v1 = iso_edge.v1;
const auto v2 = iso_edge.v2;
@ -201,16 +201,16 @@ ISNP_API void pair_patches_in_one_tet(const arrangement_t &te
// ===============================================================================================
ISNP_API void pair_patches_in_tets(const iso_edge_t &iso_edge,
const stl_vector_mp<uint32_t> &containing_simplex,
const stl_vector_mp<uint32_t> &containing_tetIds,
const stl_vector_mp<tetrahedron_vertex_indices_t> &tets,
const stl_vector_mp<polygon_face_t> &iso_faces,
const stl_vector_mp<std::shared_ptr<arrangement_t>> &cut_results,
const stl_vector_mp<uint32_t> &func_in_tet,
const stl_vector_mp<uint32_t> &start_index_of_tet,
const stl_vector_mp<uint32_t> &patch_of_face_mapping,
stl_vector_mp<stl_vector_mp<uint32_t>> &half_patch_adj_list)
ISNP_API void pair_patches_in_tets(const iso_edge_t &iso_edge,
const stl_vector_mp<uint32_t> &containing_simplex,
const stl_vector_mp<uint32_t> &containing_tetIds,
const stl_vector_mp<tetrahedron_vertex_indices_t> &tets,
const stl_vector_mp<polygon_face_t> &iso_faces,
const stl_vector_mp<std::optional<arrangement_t>> &cut_results,
const stl_vector_mp<uint32_t> &func_in_tet,
const stl_vector_mp<uint32_t> &start_index_of_tet,
const stl_vector_mp<uint32_t> &patch_of_face_mapping,
stl_vector_mp<stl_vector_mp<uint32_t>> &half_patch_adj_list)
{
//// pre-processing
// collect all iso-faces incident to the iso-edge
@ -321,7 +321,7 @@ ISNP_API void pair_patches_in_tets(const iso_edge_t
}
} else {
// non-empty tet i
const auto &arrangement = *cut_results[i].get();
const auto &arrangement = cut_results[i].value();
const auto &vertices = arrangement.vertices;
const auto &faces = arrangement.faces;
auto start_index = start_index_of_tet[i];
@ -442,7 +442,7 @@ ISNP_API void pair_patches_in_tets(const iso_edge_t
// the orientation of an iso-face is defined by the smallest-index implicit function passing the iso-face
auto get_half_iso_face = [&](face_header_t tet_face, int8_t orient, uint32_t &iso_face_id, int8_t &iso_orient) {
iso_face_id = iso_face_Id_of_face[tet_face];
const auto &cell_complex = *cut_results[tet_face.volume_index].get();
const auto &cell_complex = cut_results[tet_face.volume_index].value();
const auto &faces = cell_complex.faces;
auto supp_pId = faces[tet_face.local_face_index].supporting_plane;
if (supp_pId > 3) { // plane 0,1,2,3 are tet boundary planes
@ -486,7 +486,7 @@ ISNP_API void pair_patches_in_tets(const iso_edge_t
}
} else {
// non-empty tet
const auto &cell_complex = *cut_results[tet_id].get();
const auto &cell_complex = cut_results[tet_id].value();
uint32_t cell_id =
(orient == 1 ? cell_complex.faces[tet_face_id].positive_cell : cell_complex.faces[tet_face_id].negative_cell);
if (cell_id != invalid_index) {

34
network_process/src/topology_ray_shooting.cpp

@ -1,17 +1,17 @@
#include <topology_ray_shooting.hpp>
#include <patch_connectivity.hpp>
ISNP_API void topo_ray_shooting(const tetrahedron_mesh_t &tet_mesh,
const stl_vector_mp<std::shared_ptr<arrangement_t>> &cut_results,
const stl_vector_mp<iso_vertex_t> &iso_verts,
const stl_vector_mp<polygon_face_t> &iso_faces,
const stl_vector_mp<stl_vector_mp<uint32_t>> &patches,
const stl_vector_mp<uint32_t> &patch_of_face,
const stl_vector_mp<stl_vector_mp<uint32_t>> &shells,
const stl_vector_mp<uint32_t> &shell_of_half_patch,
const stl_vector_mp<stl_vector_mp<uint32_t>> &components,
const stl_vector_mp<uint32_t> &component_of_patch,
stl_vector_mp<std::pair<uint32_t, uint32_t>> &shell_links)
ISNP_API void topo_ray_shooting(const tetrahedron_mesh_t &tet_mesh,
const stl_vector_mp<std::optional<arrangement_t>> &cut_results,
const stl_vector_mp<iso_vertex_t> &iso_verts,
const stl_vector_mp<polygon_face_t> &iso_faces,
const stl_vector_mp<stl_vector_mp<uint32_t>> &patches,
const stl_vector_mp<uint32_t> &patch_of_face,
const stl_vector_mp<stl_vector_mp<uint32_t>> &shells,
const stl_vector_mp<uint32_t> &shell_of_half_patch,
const stl_vector_mp<stl_vector_mp<uint32_t>> &components,
const stl_vector_mp<uint32_t> &component_of_patch,
stl_vector_mp<std::pair<uint32_t, uint32_t>> &shell_links)
{
// map: tet vert index --> index of next vert (with smaller (x,y,z))
stl_vector_mp<uint32_t> next_vert{};
@ -50,7 +50,7 @@ ISNP_API void topo_ray_shooting(const tetrahedron_mesh_t
const auto extreme_v2 = extremal_edge_of_component[2 * i + 1];
const auto iso_vId = iso_vert_on_v_v_next[extreme_v1];
const auto tetId = iso_verts[iso_vId].header.volume_index;
const auto &tet_cut_result = *cut_results[tetId].get();
const auto &tet_cut_result = cut_results[tetId].value();
// get local index of v1 and v2 in the tet
uint32_t local_v1, local_v2;
for (uint32_t j = 0; j < 4; ++j) {
@ -107,7 +107,7 @@ ISNP_API void topo_ray_shooting(const tetrahedron_mesh_t
// reached iso-vert at end of the ray
const auto iso_vId_end = iso_vert_on_v_v_next[v_curr];
const auto end_tetId = iso_verts[iso_vId_end].header.volume_index;
const auto &end_tet_cut_result = *cut_results[end_tetId].get();
const auto &end_tet_cut_result = cut_results[end_tetId].value();
auto v_next = next_vert[v_curr];
// find local vertex indices in the end tetrahedron
for (uint32_t j = 0; j < 4; ++j) {
@ -307,8 +307,8 @@ ISNP_API void compute_edge_intersection_order(const arrangement_t &tet_cut_r
const auto num_vert = face.vertices.size();
for (uint32_t i = 0; i < num_vert; ++i) {
const auto i_next = (i + 1) % num_vert;
const auto vi = tet_cut_result.vertices[fId][i];
const auto vi_next = tet_cut_result.vertices[fId][i_next];
const auto vi = face.vertices[i];
const auto vi_next = face.vertices[i_next];
// add fId to edge (vi, vi_next)
auto iter_inserted = faces_of_edge.try_emplace(std::make_pair(vi, vi_next), std::make_pair(fId, invalid_index));
if (!iter_inserted.second) { // inserted before
@ -359,8 +359,8 @@ ISNP_API void compute_edge_intersection_order(const arrangement_t &tet_cut_r
// visit all edges of face, find edge_prev, edge_next and edge_on_vu
for (uint32_t i = 0; i < num_vert; ++i) {
const auto i_next = (i + 1) % num_vert;
const auto vi = tet_cut_result.vertices[f_curr][i];
const auto vi_next = tet_cut_result.vertices[f_curr][i_next];
const auto vi = face.vertices[i];
const auto vi_next = face.vertices[i_next];
if (is_on_edge_vu[vi] && !is_on_edge_vu[vi_next]) {
auto &two_faces = faces_of_edge[std::make_pair(vi, vi_next)];
auto other_face = (two_faces.first == f_curr) ? two_faces.second : two_faces.first;

Loading…
Cancel
Save