Browse Source

first valid version of chain post processing

V2-integral
Zhicheng Wang 2 weeks ago
parent
commit
ac6f039f17
  1. 12
      network_process/include/connect_by_topo/patch_connectivity.hpp
  2. 3
      network_process/include/post_topo.hpp
  3. 29
      network_process/include/post_topo/chain_post_processing.hpp
  4. 9
      network_process/include/post_topo/filter_polygon_faces.hpp
  5. 20
      network_process/interface/process.hpp
  6. 2
      network_process/src/connect_by_topo/pair_faces.cpp
  7. 78
      network_process/src/connect_by_topo/patch_connectivity.cpp
  8. 43
      network_process/src/post_topo/filter_chains.cpp
  9. 39
      network_process/src/post_topo/filter_polygon_faces.cpp
  10. 77
      network_process/src/post_topo/identify_chain_properties.cpp
  11. 53
      network_process/src/post_topo/map_chains.cpp
  12. 86
      network_process/src/process.cpp
  13. 1
      primitive_process/interface/base/subface.hpp
  14. 1
      primitive_process/interface/subface/simple/cylinder_face.hpp
  15. 1
      primitive_process/interface/subface/simple/plane.hpp
  16. 1
      primitive_process/interface/subface/simple/sphere_face.hpp
  17. 10
      primitive_process/src/subface/simple/cylinder_face.cpp
  18. 10
      primitive_process/src/subface/simple/plane.cpp
  19. 12
      primitive_process/src/subface/simple/sphere_face.cpp
  20. 39
      shared_module/container/wrapper/flat_index_group.hpp

12
network_process/include/connect_by_topo/patch_connectivity.hpp

@ -29,11 +29,15 @@ void compute_patches(const stl_vector_mp<stl_vector_mp<uint32_t>> &edges_of_face
* @brief Group non-manifold iso-edges into chains
* @param[in] iso_vert_count the count of iso-vertices
* @param[in] patch_edges the list of edges on the patch.
* @param[out] chains Chains of non-manifold edges; encoded by a vector of edge indices.
* @param[out] chain_vertices the list of chains which contain a list of vertices' indices.
* @param[out] chain_headers the list of chains' headers which contain a list of infos.
* @param[out] chain_of_mid_face map: face index --> list of chain indices (the chain passes through the face)
*/
void compute_chains(size_t iso_vert_count,
stl_vector_mp<iso_edge_t> &patch_edges,
stl_vector_mp<stl_list_mp<iso_edge_t>> &chains);
void compute_chains(size_t iso_vert_count,
stl_vector_mp<iso_edge_t> &patch_edges,
stl_vector_mp<stl_vector_mp<uint32_t>> &chain_vertices,
stl_vector_mp<iso_edge_t> &chain_headers,
flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>> &chain_of_mid_face);
/**
* @brief compute shells and connected components of isosurfaces, and build maps: half-patch --> shell, patch --> component

3
network_process/include/post_topo.hpp

@ -1,4 +1,5 @@
#pragma once
#include <post_topo/patch_propagation.hpp>
#include <post_topo/filter_polygon_faces.hpp>
#include <post_topo/filter_polygon_faces.hpp>
#include <post_topo/chain_post_processing.hpp>

29
network_process/include/post_topo/chain_post_processing.hpp

@ -0,0 +1,29 @@
#pragma once
#include <fwd_types.hpp>
struct baked_blobtree_t;
struct parameteric_plane_t;
// return: active chain label
dynamic_bitset_mp<> filter_chains(const stl_vector_mp<polygon_face_t>& faces,
const stl_vector_mp<stl_vector_mp<uint32_t>>& patches,
const dynamic_bitset_mp<>& active_patch_label,
size_t chain_size,
flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>>& chain_of_patch);
// return: is chain end vertices signular
dynamic_bitset_mp<> identify_chain_signular(const stl_vector_mp<polygon_face_t>& faces,
const stl_vector_mp<stl_vector_mp<uint32_t>>& patches,
const stl_vector_mp<stl_vector_mp<uint32_t>>& chains,
const flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>>& chain_of_patch,
size_t chain_size);
void identify_chain_near_parallel(flat_hash_map_mp<uint32_t, parameteric_plane_t>& parameteric_planes);
void map_chain_to_parameteric_plane(const baked_blobtree_t& tree,
const stl_vector_mp<Eigen::Vector3d>& vertices,
const stl_vector_mp<polygon_face_t>& faces,
const stl_vector_mp<stl_vector_mp<uint32_t>>& patches,
const stl_vector_mp<stl_vector_mp<uint32_t>>& chains,
const flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>>& chain_of_patch,
const flat_hash_map_mp<uint32_t, uint32_t>& vertex_old_index_to_unique_index,
const dynamic_bitset_mp<>& chain_end_vertex_signular_flag,
flat_hash_map_mp<uint32_t, parameteric_plane_t>& parameteric_planes);

9
network_process/include/post_topo/filter_polygon_faces.hpp

@ -2,7 +2,7 @@
#include <fwd_types.hpp>
// return: active face label
// return: active patch label
dynamic_bitset_mp<> filter_polygon_faces(const stl_vector_mp<polygon_face_t>& faces,
const stl_vector_mp<stl_vector_mp<uint32_t>>& patches,
const stl_vector_mp<stl_vector_mp<uint32_t>>& arrangement_cells,
@ -13,6 +13,7 @@ dynamic_bitset_mp<> filter_polygon_faces(const stl_vector_mp<polygon_face_t>&
stl_vector_mp<uint32_t>& output_polygon_faces,
stl_vector_mp<uint32_t>& output_vertex_counts_of_face);
void filter_active_vertices(stl_vector_mp<Eigen::Vector3d>& iso_pts,
stl_vector_mp<Eigen::Vector3d>& vertices,
stl_vector_mp<uint32_t>& output_polygon_faces);
void calculate_vertex_mapping(stl_vector_mp<Eigen::Vector3d>& iso_pts,
stl_vector_mp<Eigen::Vector3d>& output_vertices,
stl_vector_mp<uint32_t>& output_polygon_faces,
flat_hash_map_mp<uint32_t, uint32_t>& vertex_old_index_to_unique_index);

20
network_process/interface/process.hpp

@ -4,8 +4,18 @@
#include "settings.h"
ISNP_API void build_implicit_network_by_blobtree(const s_settings& settings,
const baked_blobtree_t& tree,
stl_vector_mp<Eigen::Vector3d>& output_vertices,
stl_vector_mp<uint32_t>& output_polygon_faces,
stl_vector_mp<uint32_t>& output_vertex_counts_of_face);
struct parameteric_plane_t {
stl_vector_mp<stl_vector_mp<Eigen::Vector2d>> chain_vertices{};
stl_vector_mp<uint32_t> chain_group_start_indices{};
// iff start/end vertex, then this is signular or not; else this is polar or not
stl_vector_mp<dynamic_bitset_mp<>> vertex_special_flags{};
// format: total length is N - 1, and i identifies whether edge [i, i+1) is near parallel or not
stl_vector_mp<dynamic_bitset_mp<>> edge_near_parallel_flags{};
};
ISNP_API void build_implicit_network_by_blobtree(const s_settings& settings,
const baked_blobtree_t& tree,
stl_vector_mp<Eigen::Vector3d>& output_vertices,
stl_vector_mp<uint32_t>& output_polygon_faces,
stl_vector_mp<uint32_t>& output_vertex_counts_of_face,
flat_hash_map_mp<uint32_t, parameteric_plane_t>& output_parameteric_planes);

2
network_process/src/connect_by_topo/pair_faces.cpp

@ -1,7 +1,7 @@
#include <connect_by_topo.hpp>
void compute_patch_order(const stl_vector_mp<std::array<uint32_t, 4>> &tetrahedrons,
const iso_edge_t &iso_edge,
const stl_vector_mp<uint32_t> &iso_edge,
const stl_vector_mp<iso_vertex_t> &iso_verts,
const stl_vector_mp<polygon_face_t> &iso_faces,
const stl_vector_mp<arrangement_t> &tetrahedron_arrangements,

78
network_process/src/connect_by_topo/patch_connectivity.cpp

@ -1,3 +1,4 @@
#include <cstdint>
#include <queue>
#include <connect_by_topo.hpp>
@ -79,9 +80,11 @@ void compute_patches(const stl_vector_mp<stl_vector_mp<uint32_t>>& edges_of_face
}
}
void compute_chains(size_t iso_vert_count,
stl_vector_mp<iso_edge_t>& patch_edges,
stl_vector_mp<stl_list_mp<iso_edge_t>>& chains)
void compute_chains(size_t iso_vert_count,
stl_vector_mp<iso_edge_t>& patch_edges,
stl_vector_mp<stl_vector_mp<uint32_t>>& chain_vertices,
stl_vector_mp<iso_edge_t>& chain_headers,
flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>>& chain_of_mid_face)
{
stl_vector_mp<stl_vector_mp<uint32_t>> non_manifold_edges_of_vert{};
stl_vector_mp<uint32_t> non_manifold_edges{};
@ -98,16 +101,22 @@ void compute_chains(size_t iso_vert_count,
}
}
stl_vector_mp<bool> visited_edge(patch_edges.size(), false);
stl_vector_mp<bool> visited_edge(patch_edges.size(), false);
stl_list_mp<uint32_t> chain{};
for (const auto& i : non_manifold_edges) {
if (!visited_edge[i]) {
// unvisited non-manifold iso-edge (not a boundary edge)
// new chain
auto& chain = chains.emplace_back();
auto& new_chain_vertices = chain_vertices.emplace_back();
auto& new_chain_headers = chain_headers.emplace_back();
chain.clear();
std::queue<uint32_t> Q{};
Q.emplace(i);
chain.emplace_back(std::move(patch_edges[i]));
visited_edge[i] = true;
chain.emplace_back(patch_edges[i].v1);
chain.emplace_back(patch_edges[i].v2);
new_chain_headers = patch_edges[i];
visited_edge[i] = true;
while (!Q.empty()) {
const auto eId = Q.front();
Q.pop();
@ -116,10 +125,16 @@ void compute_chains(size_t iso_vert_count,
if (non_manifold_edges_of_vert[v].size() == 2) {
const auto other_eId = (non_manifold_edges_of_vert[v][0] == eId) ? non_manifold_edges_of_vert[v][1]
: non_manifold_edges_of_vert[v][0];
const auto other_vId =
(patch_edges[other_eId].v1 == v) ? patch_edges[other_eId].v2 : patch_edges[other_eId].v1;
if (!visited_edge[other_eId]) {
Q.emplace(other_eId);
chain.emplace_back(std::move(patch_edges[other_eId]));
visited_edge[other_eId] = true;
if (v == chain.front()) {
chain.emplace_front(other_vId);
} else {
chain.emplace_back(other_vId);
}
}
}
// v2
@ -127,13 +142,58 @@ void compute_chains(size_t iso_vert_count,
if (non_manifold_edges_of_vert[v].size() == 2) {
const auto other_eId = (non_manifold_edges_of_vert[v][0] == eId) ? non_manifold_edges_of_vert[v][1]
: non_manifold_edges_of_vert[v][0];
const auto other_vId =
(patch_edges[other_eId].v1 == v) ? patch_edges[other_eId].v2 : patch_edges[other_eId].v1;
if (!visited_edge[other_eId]) {
Q.emplace(other_eId);
chain.emplace_back(std::move(patch_edges[other_eId]));
visited_edge[other_eId] = true;
if (v == chain.front()) {
chain.emplace_front(other_vId);
} else {
chain.emplace_back(other_vId);
}
}
}
}
new_chain_vertices.insert(new_chain_vertices.end(), chain.begin(), chain.end());
if (new_chain_vertices.size() > 2) {
const auto mid_vert = *(new_chain_vertices.begin() + 1);
stl_vector_mp<uint32_t> face_indices{};
face_indices.reserve(non_manifold_edges_of_vert[mid_vert].size() * 2);
for (const auto& eId : non_manifold_edges_of_vert[mid_vert]) {
for (const auto& header : patch_edges[eId].headers) face_indices.emplace_back(header.face_index);
}
std::sort(face_indices.begin(), face_indices.end());
auto iter = std::unique(face_indices.begin(), face_indices.end());
for (auto it = face_indices.begin(); it != iter; ++it)
chain_of_mid_face[*it].emplace_back(static_cast<uint32_t>(chain_vertices.size() - 1));
} else {
stl_vector_mp<uint32_t> start_face_indices{};
stl_vector_mp<uint32_t> end_face_indices{};
start_face_indices.reserve(non_manifold_edges_of_vert[new_chain_vertices.front()].size() * 2);
end_face_indices.reserve(non_manifold_edges_of_vert[new_chain_vertices.back()].size() * 2);
for (const auto& eId : non_manifold_edges_of_vert[new_chain_vertices.front()]) {
for (const auto& header : patch_edges[eId].headers) start_face_indices.emplace_back(header.face_index);
}
for (const auto& eId : non_manifold_edges_of_vert[new_chain_vertices.back()]) {
for (const auto& header : patch_edges[eId].headers) end_face_indices.emplace_back(header.face_index);
}
std::sort(start_face_indices.begin(), start_face_indices.end());
std::sort(end_face_indices.begin(), end_face_indices.end());
auto iter_start = std::unique(start_face_indices.begin(), start_face_indices.end());
auto iter_end = std::unique(end_face_indices.begin(), end_face_indices.end());
stl_vector_mp<uint32_t> unique_face_indices{};
std::set_intersection(start_face_indices.begin(),
iter_start,
end_face_indices.begin(),
iter_end,
std::back_inserter(unique_face_indices));
for (auto it = unique_face_indices.begin(); it != unique_face_indices.end(); ++it)
chain_of_mid_face[*it].emplace_back(static_cast<uint32_t>(chain_vertices.size() - 1));
}
}
}
}

43
network_process/src/post_topo/filter_chains.cpp

@ -0,0 +1,43 @@
#include <post_topo.hpp>
dynamic_bitset_mp<> filter_chains(const stl_vector_mp<polygon_face_t>& faces,
const stl_vector_mp<stl_vector_mp<uint32_t>>& patches,
const dynamic_bitset_mp<>& active_patch_label,
size_t chain_size,
flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>>& chain_of_patch)
{
flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>> filtered_chain_of_patch{};
flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>> active_prim_of_chain{};
for (uint32_t i = 0; i < chain_of_patch.size(); ++i) {
if (active_patch_label[i]) {
auto& cIds_of_patch = filtered_chain_of_patch[i];
cIds_of_patch = std::move(chain_of_patch.at(i));
for (auto chain_index : cIds_of_patch) { active_prim_of_chain[chain_index].emplace_back(i); }
}
}
dynamic_bitset_mp<> active_chain_label(chain_size);
for (auto& [chain_index, patch_indices] : active_prim_of_chain) {
auto label = active_chain_label[chain_index];
if (patch_indices.size() > 2) label = true;
// transform patch index to subface index
for (auto& patch_index : patch_indices) patch_index = faces[patches[patch_index][0]].subface_index;
std::sort(patch_indices.begin(), patch_indices.end());
auto iter = std::unique(patch_indices.begin(), patch_indices.end());
// turn it off iff only one subface is incident
if (std::distance(patch_indices.begin(), iter) <= 1) label = false;
}
stl_vector_mp<uint32_t> temp_filtered_chain_indices{};
chain_of_patch.clear();
for (auto& [patch_index, chain_indices] : filtered_chain_of_patch) {
temp_filtered_chain_indices.clear();
for (auto chain_index : chain_indices) {
if (active_chain_label[chain_index]) temp_filtered_chain_indices.emplace_back(chain_index);
}
temp_filtered_chain_indices.shrink_to_fit();
if (!temp_filtered_chain_indices.empty()) chain_of_patch[patch_index] = std::move(temp_filtered_chain_indices);
}
return active_chain_label;
}

39
network_process/src/post_topo/filter_polygon_faces.cpp

@ -12,7 +12,7 @@ dynamic_bitset_mp<> filter_polygon_faces(const stl_vector_mp<polygon_face_t>&
stl_vector_mp<uint32_t>& output_polygon_faces,
stl_vector_mp<uint32_t>& output_vertex_counts_of_face)
{
dynamic_bitset_mp<> active_face_label(faces.size(), false);
dynamic_bitset_mp<> active_patch_label(patches.size(), false);
output_polygon_faces.reserve(faces.size() * 3);
output_vertex_counts_of_face.reserve(faces.size());
@ -37,6 +37,7 @@ dynamic_bitset_mp<> filter_polygon_faces(const stl_vector_mp<polygon_face_t>&
for (auto half_patch : shells[shell]) {
bool sign = (half_patch % 2 == 0) ? 0 : 1;
auto oppose_cell = shell_to_cell[shell_of_half_patch[!sign ? (half_patch + 1) : (half_patch - 1)]];
active_patch_label[half_patch / 2] = true;
// iff not interior patch, we do surface propagation
if (!active_cell_label[oppose_cell]) {
@ -51,7 +52,6 @@ dynamic_bitset_mp<> filter_polygon_faces(const stl_vector_mp<polygon_face_t>&
// outside of that surface, so it is also right
if (!sign) {
for (const auto face_index : patches[half_patch / 2]) {
active_face_label[face_index] = true;
const auto& face_vertices = faces[face_index].vertex_indices;
output_vertex_counts_of_face.emplace_back(face_vertices.size());
output_polygon_faces.insert(output_polygon_faces.end(),
@ -60,7 +60,6 @@ dynamic_bitset_mp<> filter_polygon_faces(const stl_vector_mp<polygon_face_t>&
}
} else {
for (const auto face_index : patches[half_patch / 2]) {
active_face_label[face_index] = true;
const auto& face_vertices = faces[face_index].vertex_indices;
output_vertex_counts_of_face.emplace_back(face_vertices.size());
output_polygon_faces.insert(output_polygon_faces.end(),
@ -79,31 +78,27 @@ dynamic_bitset_mp<> filter_polygon_faces(const stl_vector_mp<polygon_face_t>&
output_polygon_faces.shrink_to_fit();
output_vertex_counts_of_face.shrink_to_fit();
return active_face_label;
return active_patch_label;
}
void filter_active_vertices(stl_vector_mp<Eigen::Vector3d>& iso_pts,
stl_vector_mp<Eigen::Vector3d>& output_vertices,
stl_vector_mp<uint32_t>& output_polygon_faces)
void calculate_vertex_mapping(stl_vector_mp<Eigen::Vector3d>& iso_pts,
stl_vector_mp<Eigen::Vector3d>& output_vertices,
stl_vector_mp<uint32_t>& output_polygon_faces,
flat_hash_map_mp<uint32_t, uint32_t>& vertex_old_index_to_unique_index)
{
stl_vector_mp<uint32_t> unique_vertex_indices{};
dynamic_bitset_mp<> vertex_visited(iso_pts.size(), false);
for (const auto& vertex_index : output_polygon_faces) {
if (!vertex_visited[vertex_index]) {
unique_vertex_indices.emplace_back(vertex_index);
vertex_visited[vertex_index] = true;
}
}
auto unique_vertex_indices = output_polygon_faces;
std::sort(unique_vertex_indices.begin(), unique_vertex_indices.end());
auto iter = std::unique(unique_vertex_indices.begin(), unique_vertex_indices.end());
flat_hash_map_mp<uint32_t, uint32_t> vertex_old_index_to_unique_index{};
for (uint32_t i = 0; i < unique_vertex_indices.size(); ++i) {
vertex_old_index_to_unique_index[unique_vertex_indices[i]] = i;
stl_vector_mp<Eigen::Vector3d> unique_vertices{};
unique_vertices.reserve(unique_vertex_indices.size());
for (uint32_t i = 0; i < std::distance(unique_vertex_indices.begin(), iter); ++i) {
auto vertex_index = unique_vertex_indices[i];
vertex_old_index_to_unique_index[vertex_index] = i;
unique_vertices.emplace_back(iso_pts[vertex_index]);
}
for (auto& vertex_index : output_polygon_faces) { vertex_index = vertex_old_index_to_unique_index[vertex_index]; }
for (auto& vertex_index : output_polygon_faces) vertex_index = vertex_old_index_to_unique_index[vertex_index];
stl_vector_mp<Eigen::Vector3d> unique_vertices{};
unique_vertices.reserve(unique_vertex_indices.size());
for (const auto& vertex_index : unique_vertex_indices) { unique_vertices.emplace_back(iso_pts[vertex_index]); }
std::swap(output_vertices, unique_vertices);
}

77
network_process/src/post_topo/identify_chain_properties.cpp

@ -0,0 +1,77 @@
#include <process.hpp>
#include <post_topo.hpp>
dynamic_bitset_mp<> identify_chain_signular(const stl_vector_mp<polygon_face_t>& faces,
const stl_vector_mp<stl_vector_mp<uint32_t>>& patches,
const stl_vector_mp<stl_vector_mp<uint32_t>>& chains,
const flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>>& chain_of_patch,
size_t chain_size)
{
dynamic_bitset_mp<> chain_end_vertex_signular_flag(chain_size * 2);
flat_hash_map_mp<uint32_t, flat_hash_set_mp<uint32_t>> vertex_subface_indices{};
flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>> start_vertex_to_chain_indices{};
flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>> end_vertex_to_chain_indices{};
for (const auto& [patch_index, chain_indices] : chain_of_patch) {
const auto subface_index = faces[patches[patch_index][0]].subface_index;
for (const auto& face_index : patches[patch_index]) {
const auto& face = faces[face_index];
for (const auto& vertex_index : face.vertex_indices) {
for (const auto& chain_index : chain_indices) {
const auto start_vertex = chains[chain_index].front();
const auto end_vertex = chains[chain_index].back();
if (vertex_index == start_vertex) {
vertex_subface_indices[vertex_index].emplace(subface_index);
start_vertex_to_chain_indices[vertex_index].emplace_back(chain_index);
break;
} else if (vertex_index == end_vertex) {
vertex_subface_indices[vertex_index].emplace(subface_index);
end_vertex_to_chain_indices[vertex_index].emplace_back(chain_index);
break;
}
}
}
}
}
for (const auto& [vertex_index, subface_set] : vertex_subface_indices) {
if (subface_set.size() >= 3) {
if (auto iter = start_vertex_to_chain_indices.find(vertex_index); iter != start_vertex_to_chain_indices.end()) {
for (const auto& chain_index : iter->second) chain_end_vertex_signular_flag[chain_index * 2] = true;
}
if (auto iter = end_vertex_to_chain_indices.find(vertex_index); iter != end_vertex_to_chain_indices.end()) {
for (const auto& chain_index : iter->second) chain_end_vertex_signular_flag[chain_index * 2 + 1] = true;
}
}
}
return chain_end_vertex_signular_flag;
}
void identify_chain_near_parallel(flat_hash_map_mp<uint32_t, parameteric_plane_t>& parameteric_planes)
{
for (auto& [_, parameteric_plane] : parameteric_planes) {
parameteric_plane.edge_near_parallel_flags.reserve(parameteric_plane.chain_vertices.size());
for (size_t i = 0; i < parameteric_plane.chain_vertices.size(); ++i) {
const auto& vertices = parameteric_plane.chain_vertices[i];
auto& vertex_flags = parameteric_plane.vertex_special_flags[i];
auto& edge_flags = parameteric_plane.edge_near_parallel_flags.emplace_back();
edge_flags.resize(vertices.size() - 1);
// identify edge near parallel first
for (auto iter = vertices.begin(); iter != vertices.end() - 1; ++iter) {
if (std::abs(iter->x() - (iter + 1)->x()) <= epsilon || //
std::abs(iter->y() - (iter + 1)->y()) <= epsilon)
edge_flags[std::distance(vertices.begin(), iter)] = true;
}
// then identify polar vertex
if (vertices.size() >= 3) {
for (auto iter = vertices.begin() + 1; iter != vertices.end() - 1; ++iter) {
auto vec1 = *iter - *(iter - 1);
auto vec2 = *(iter + 1) - *iter;
if (vec1.dot(vec2) < 0) vertex_flags[std::distance(vertices.begin(), iter)] = true;
}
}
}
}
}

53
network_process/src/post_topo/map_chains.cpp

@ -0,0 +1,53 @@
#include <process.hpp>
#include <post_topo.hpp>
void map_chain_to_parameteric_plane(const baked_blobtree_t& tree,
const stl_vector_mp<Eigen::Vector3d>& vertices,
const stl_vector_mp<polygon_face_t>& faces,
const stl_vector_mp<stl_vector_mp<uint32_t>>& patches,
const stl_vector_mp<stl_vector_mp<uint32_t>>& chains,
const flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>>& chain_of_patch,
const flat_hash_map_mp<uint32_t, uint32_t>& vertex_old_index_to_unique_index,
const dynamic_bitset_mp<>& chain_end_vertex_signular_flag,
flat_hash_map_mp<uint32_t, parameteric_plane_t>& parameteric_planes)
{
flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>> patch_of_subface{};
for (const auto& [patch_index, _] : chain_of_patch) {
const auto& subface_index = faces[patches[patch_index][0]].subface_index;
patch_of_subface[subface_index].emplace_back(patch_index);
}
const auto& subfaces = tree.subfaces;
for (const auto& [subface_index, patch_indices] : patch_of_subface) {
const auto& subface = *subfaces[subface_index].object_ptr;
auto mapping_func = subface.fetch_param_mapping_evaluator();
auto& parameteric_plane = parameteric_planes[subface_index];
auto& chain_vertices = parameteric_plane.chain_vertices;
auto& chain_group_start_indices = parameteric_plane.chain_group_start_indices;
auto& chain_vertex_flags = parameteric_plane.vertex_special_flags;
chain_group_start_indices.reserve(patch_indices.size());
chain_group_start_indices.emplace_back(0);
for (const auto& patch_index : patch_indices) {
const auto& chain_indices = chain_of_patch.at(patch_index);
chain_group_start_indices.emplace_back(chain_indices.size() + chain_group_start_indices.back());
chain_vertices.reserve(chain_vertices.size() + chain_indices.size());
chain_vertex_flags.reserve(chain_vertex_flags.size() + chain_indices.size());
for (const auto& chain_index : chain_indices) {
const auto& chain = chains[chain_index];
auto& chain_vertices_ = chain_vertices.emplace_back();
chain_vertices_.resize(chain.size());
std::transform(chain.begin(), chain.end(), chain_vertices_.begin(), [&](uint32_t vertex_index) {
auto mapped_vertex_index = vertex_old_index_to_unique_index.at(vertex_index);
return mapping_func(vertices[mapped_vertex_index]);
});
auto& chain_vertex_flags_ = chain_vertex_flags.emplace_back();
chain_vertex_flags_.resize(chain.size());
chain_vertex_flags_[0] = chain_end_vertex_signular_flag[2 * chain_index];
chain_vertex_flags_[chain.size() - 1] = chain_end_vertex_signular_flag[2 * chain_index + 1];
}
}
}
}

86
network_process/src/process.cpp

@ -4,11 +4,12 @@
#include <connect_by_topo.hpp>
#include <post_topo.hpp>
ISNP_API void build_implicit_network_by_blobtree(const s_settings& settings,
const baked_blobtree_t& tree,
stl_vector_mp<Eigen::Vector3d>& output_vertices,
stl_vector_mp<uint32_t>& output_polygon_faces,
stl_vector_mp<uint32_t>& output_vertex_counts_of_face)
ISNP_API void build_implicit_network_by_blobtree(const s_settings& settings,
const baked_blobtree_t& tree,
stl_vector_mp<Eigen::Vector3d>& output_vertices,
stl_vector_mp<uint32_t>& output_polygon_faces,
stl_vector_mp<uint32_t>& output_vertex_counts_of_face,
flat_hash_map_mp<uint32_t, parameteric_plane_t>& output_parameteric_planes)
{
// load LUT for implicit arrangement
load_lut();
@ -71,27 +72,36 @@ ISNP_API void build_implicit_network_by_blobtree(const s_settings&
iso_faces);
}
// connect components by topology
stl_vector_mp<uint32_t> patch_of_face(iso_faces.size());
stl_vector_mp<uint32_t> shell_of_half_patch{};
stl_vector_mp<uint32_t> component_of_patch{};
stl_vector_mp<stl_vector_mp<uint32_t>> patches{};
stl_vector_mp<stl_list_mp<iso_edge_t>> chains{};
stl_vector_mp<stl_vector_mp<uint32_t>> shells{};
stl_vector_mp<stl_vector_mp<uint32_t>> components{};
stl_vector_mp<stl_vector_mp<uint32_t>> arrangement_cells{};
stl_vector_mp<uint32_t> shell_to_cell{};
stl_vector_mp<uint32_t> patch_of_face(iso_faces.size());
stl_vector_mp<uint32_t> shell_of_half_patch{};
stl_vector_mp<uint32_t> component_of_patch{};
flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>> chain_of_patch{};
stl_vector_mp<stl_vector_mp<uint32_t>> patches{};
stl_vector_mp<stl_vector_mp<uint32_t>> chain_vertices{};
stl_vector_mp<stl_vector_mp<uint32_t>> shells{};
stl_vector_mp<stl_vector_mp<uint32_t>> components{};
stl_vector_mp<stl_vector_mp<uint32_t>> arrangement_cells{};
stl_vector_mp<uint32_t> shell_to_cell{};
{
stl_vector_mp<iso_edge_t> chain_headers{};
{
stl_vector_mp<stl_vector_mp<uint32_t>> edges_of_iso_face{};
stl_vector_mp<iso_edge_t> iso_edges{};
stl_vector_mp<stl_vector_mp<uint32_t>> edges_of_iso_face{};
flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>> chain_of_mid_face{};
stl_vector_mp<iso_edge_t> iso_edges{};
compute_patch_edges(iso_faces, edges_of_iso_face, iso_edges);
compute_patches(edges_of_iso_face, iso_edges, iso_faces, patches, patch_of_face);
compute_chains(iso_verts.size(), iso_edges, chains);
compute_chains(iso_verts.size(), iso_edges, chain_vertices, chain_headers, chain_of_mid_face);
for (const auto& [face_index, chain_indices] : chain_of_mid_face) {
auto& chain_indices_ = chain_of_patch[patch_of_face[face_index]];
chain_indices_ = std::move(chain_indices);
std::sort(chain_indices_.begin(), chain_indices_.end());
chain_indices_.erase(std::unique(chain_indices_.begin(), chain_indices_.end()), chain_indices_.end());
}
}
stl_vector_mp<stl_vector_mp<uint32_t>> half_patch_adj_list(2 * patches.size());
for (size_t i = 0; i < chains.size(); ++i)
for (size_t i = 0; i < chain_headers.size(); ++i)
compute_patch_order(tetrahedrons,
chains[i].front(),
chain_headers[i],
iso_verts,
iso_faces,
tetrahedron_arrangements,
@ -150,16 +160,34 @@ ISNP_API void build_implicit_network_by_blobtree(const s_settings&
}
active_cell_label = filter_cells_by_boolean(tree, cell_primitive_signs);
}
filter_polygon_faces(iso_faces,
patches,
arrangement_cells,
shell_of_half_patch,
shells,
shell_to_cell,
active_cell_label,
output_polygon_faces,
output_vertex_counts_of_face);
filter_active_vertices(iso_pts, output_vertices, output_polygon_faces);
{
auto active_patch_label = filter_polygon_faces(iso_faces,
patches,
arrangement_cells,
shell_of_half_patch,
shells,
shell_to_cell,
active_cell_label,
output_polygon_faces,
output_vertex_counts_of_face);
flat_hash_map_mp<uint32_t, uint32_t> vertex_old_index_to_unique_index{};
calculate_vertex_mapping(iso_pts, output_vertices, output_polygon_faces, vertex_old_index_to_unique_index);
// chain postprocessing
auto active_chain_label =
filter_chains(iso_faces, patches, active_patch_label, chain_vertices.size(), chain_of_patch);
auto is_chain_end_vertices_signular =
identify_chain_signular(iso_faces, patches, chain_vertices, chain_of_patch, chain_vertices.size());
map_chain_to_parameteric_plane(tree,
iso_pts,
iso_faces,
patches,
chain_vertices,
chain_of_patch,
vertex_old_index_to_unique_index,
is_chain_end_vertices_signular,
output_parameteric_planes);
identify_chain_near_parallel(output_parameteric_planes);
}
}
}
}

1
primitive_process/interface/base/subface.hpp

@ -57,6 +57,7 @@ EXTERN_C struct PE_API subface {
virtual std::function<double(Eigen::Vector3d)> fetch_sdf_evaluator() const = 0;
virtual std::function<Eigen::Vector3d(Eigen::Vector3d)> fetch_sdf_grad_evaluator() const = 0;
virtual std::function<Eigen::Vector4d(double, double)> fetch_point_by_param_evaluator() const = 0;
virtual std::function<Eigen::Vector2d(Eigen::Vector3d)> fetch_param_mapping_evaluator() const = 0;
virtual std::function<internal::constraint_curve_intermediate(double)> fetch_curve_constraint_evaluator(
internal::parameter_u_t constraint_var_type,

1
primitive_process/interface/subface/simple/cylinder_face.hpp

@ -15,6 +15,7 @@ struct cylinder_face_t final : subface {
// u: planar angle from x-axis to z-axis
// v: depth/height from xz-plane to y-axis
std::function<Eigen::Vector4d(double, double)> fetch_point_by_param_evaluator() const override;
std::function<Eigen::Vector2d(Eigen::Vector3d)> fetch_param_mapping_evaluator() const override;
std::function<constraint_curve_intermediate(double)> fetch_curve_constraint_evaluator(parameter_u_t constraint_var_type,
double u) const override;

1
primitive_process/interface/subface/simple/plane.hpp

@ -15,6 +15,7 @@ struct plane_t final : subface {
// u: planar local x-axis
// v: planar local y-axis
std::function<Eigen::Vector4d(double, double)> fetch_point_by_param_evaluator() const override;
std::function<Eigen::Vector2d(Eigen::Vector3d)> fetch_param_mapping_evaluator() const override;
std::function<constraint_curve_intermediate(double)> fetch_curve_constraint_evaluator(parameter_u_t constraint_var_type,
double u) const override;

1
primitive_process/interface/subface/simple/sphere_face.hpp

@ -15,6 +15,7 @@ struct sphere_face_t final : subface {
// u: planar angle from x-axis to z-axis
// v: polar angle from xz-plane to y-axis
std::function<Eigen::Vector4d(double, double)> fetch_point_by_param_evaluator() const override;
std::function<Eigen::Vector2d(Eigen::Vector3d)> fetch_param_mapping_evaluator() const override;
std::function<constraint_curve_intermediate(double)> fetch_curve_constraint_evaluator(parameter_u_t constraint_var_type,
double u) const override;

10
primitive_process/src/subface/simple/cylinder_face.cpp

@ -41,6 +41,16 @@ auto cylinder_face_t::fetch_point_by_param_evaluator() const -> std::function<Ei
return std::bind(functor, std::placeholders::_1, std::placeholders::_2, std::ref(this->raw_local_to_world()));
}
auto cylinder_face_t::fetch_param_mapping_evaluator() const -> std::function<Eigen::Vector2d(Eigen::Vector3d)>
{
auto functor = [](Eigen::Vector3d p, const transform_block* _world_to_local) {
Eigen::Vector4d local_p = *_world_to_local * Eigen::Vector4d{p.x(), p.y(), p.z(), 1.0};
return Eigen::Vector2d(std::atan2(local_p.y(), local_p.x()), local_p.z());
};
return std::bind(functor, std::placeholders::_1, &this->raw_world_to_local());
}
auto cylinder_face_t::fetch_curve_constraint_evaluator(parameter_u_t constraint_var_type, double u) const
-> std::function<constraint_curve_intermediate(double)>
{

10
primitive_process/src/subface/simple/plane.cpp

@ -30,6 +30,16 @@ auto plane_t::fetch_point_by_param_evaluator() const -> std::function<Eigen::Vec
return std::bind(functor, std::placeholders::_1, std::placeholders::_2, std::ref(this->raw_local_to_world()));
}
auto plane_t::fetch_param_mapping_evaluator() const -> std::function<Eigen::Vector2d(Eigen::Vector3d)>
{
auto functor = [](Eigen::Vector3d p, const transform_block* _world_to_local) {
Eigen::Vector4d local_p = *_world_to_local * Eigen::Vector4d{p.x(), p.y(), p.z(), 1.0};
return Eigen::Vector2d{local_p.y(), local_p.z()};
};
return std::bind(functor, std::placeholders::_1, &this->raw_world_to_local());
}
auto plane_t::fetch_curve_constraint_evaluator(parameter_u_t constraint_var_type, double u) const
-> std::function<constraint_curve_intermediate(double)>
{

12
primitive_process/src/subface/simple/sphere_face.cpp

@ -43,6 +43,18 @@ auto sphere_face_t::fetch_point_by_param_evaluator() const -> std::function<Eige
return std::bind(functor, std::placeholders::_1, std::placeholders::_2, std::ref(this->raw_local_to_world()));
}
auto sphere_face_t::fetch_param_mapping_evaluator() const -> std::function<Eigen::Vector2d(Eigen::Vector3d)>
{
auto functor = [](Eigen::Vector3d p, const transform_block* _world_to_local) {
Eigen::Vector4d local_p = (*_world_to_local * Eigen::Vector4d{p.x(), p.y(), p.z(), 1.0}).normalized();
const auto u = std::atan2(local_p.z(), local_p.x());
const auto v = std::asin(local_p.y());
return Eigen::Vector2d{u, v};
};
return std::bind(functor, std::placeholders::_1, &this->raw_world_to_local());
}
auto sphere_face_t::fetch_curve_constraint_evaluator(parameter_u_t constraint_var_type, double u) const
-> std::function<constraint_curve_intermediate(double)>
{

39
shared_module/container/wrapper/flat_index_group.hpp

@ -0,0 +1,39 @@
#pragma once
#include "../stl_alias.hpp"
struct flat_index_group {
stl_vector_mp<uint32_t> index_group{}; /// a list of indices in the group
stl_vector_mp<uint32_t> start_indices{}; /// a list of start indices for each group in the flat index group
inline size_t size() const { return start_indices.size() - 1; }
// f(group_index, element_index_in_group, elemenet)
template <typename F>
inline void foreach (F&& f) const
{
for (uint32_t group_idx = 0; group_idx < size(); ++group_idx) {
for (uint32_t elem_idx = 0; elem_idx < start_indices[group_idx + 1] - start_indices[group_idx]; ++elem_idx) {
f(group_idx, elem_idx, index_group[start_indices[group_idx] + elem_idx]);
}
}
}
// f(group_index, group_start_index, group_end_index)
template <typename F>
inline void group_foreach(F&& f) const
{
for (uint32_t group_idx = 0; group_idx < size(); ++group_idx) {
f(group_idx, start_indices[group_idx], start_indices[group_idx + 1]);
}
}
// f(element_index_in_group, element)
template <typename F>
inline void loop_on_group(uint32_t group_idx, F&& f) const
{
for (uint32_t elem_idx = 0; elem_idx < start_indices[group_idx + 1] - start_indices[group_idx]; ++elem_idx) {
f(elem_idx, index_group[start_indices[group_idx] + elem_idx]);
}
}
};
Loading…
Cancel
Save