|
|
|
@ -3,9 +3,9 @@ |
|
|
|
|
|
|
|
#include <connect_by_topo.hpp> |
|
|
|
|
|
|
|
void compute_patch_edges(const stl_vector_mp<polygon_face_t>& patch_faces, |
|
|
|
stl_vector_mp<stl_vector_mp<uint32_t>>& edges_of_face, |
|
|
|
stl_vector_mp<iso_edge_t>& patch_edges) |
|
|
|
void compute_patch_edges(const stl_vector_mp<polygon_face_t>& patch_faces, |
|
|
|
stl_vector_mp<stl_vector_mp<edge_key_t>>& edges_of_face, |
|
|
|
flat_hash_map_mp<edge_key_t, edge_header_t>& patch_edges) |
|
|
|
{ |
|
|
|
uint32_t max_num_edge = 0; |
|
|
|
for (const auto& iso_face : patch_faces) { max_num_edge += static_cast<uint32_t>(iso_face.vertex_indices.size()); } |
|
|
|
@ -24,29 +24,29 @@ void compute_patch_edges(const stl_vector_mp<polygon_face_t>& patch_faces, |
|
|
|
auto v2 = face.vertex_indices[(j + 1) % num_edge]; |
|
|
|
// swap if v1 > v2
|
|
|
|
if (v1 > v2) std::swap(v1, v2); |
|
|
|
//
|
|
|
|
num_iso_edge = static_cast<uint32_t>(patch_edges.size()); |
|
|
|
auto iter_inserted = edge_id.try_emplace(std::make_pair(v1, v2), num_iso_edge); |
|
|
|
if (iter_inserted.second) { // new iso-edge
|
|
|
|
auto& edge = patch_edges.emplace_back(); |
|
|
|
edge.v1 = v1; |
|
|
|
edge.v2 = v2; |
|
|
|
edge.headers.emplace_back(edge_header_t{i, j}); |
|
|
|
face_edges[j] = num_iso_edge; |
|
|
|
} else { // existing iso-edge
|
|
|
|
uint32_t eId = iter_inserted.first->second; |
|
|
|
patch_edges[eId].headers.emplace_back(edge_header_t{i, j}); |
|
|
|
face_edges[j] = eId; |
|
|
|
} |
|
|
|
patch_edges[{v1, v2}].face_indices.emplace_back(i); |
|
|
|
face_edges[j] = {v1, v2}; |
|
|
|
// //
|
|
|
|
// num_iso_edge = static_cast<uint32_t>(patch_edges.size());
|
|
|
|
// auto iter_inserted = edge_id.try_emplace(std::make_pair(v1, v2), num_iso_edge);
|
|
|
|
// if (iter_inserted.second) { // new iso-edge
|
|
|
|
// patch_edges[{v1, v2}].face_indices.emplace_back(i);
|
|
|
|
// face_edges[j] = {v1, v2};
|
|
|
|
// } else { // existing iso-edge
|
|
|
|
// uint32_t eId = iter_inserted.first->second;
|
|
|
|
// patch_edges[eId].headers.emplace_back(edge_header_t{i, j});
|
|
|
|
// face_edges[j] = {v1, v2};
|
|
|
|
// }
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
void compute_patches(const stl_vector_mp<stl_vector_mp<uint32_t>>& edges_of_face, |
|
|
|
const stl_vector_mp<iso_edge_t>& patch_edges, |
|
|
|
const stl_vector_mp<polygon_face_t>& patch_faces, |
|
|
|
stl_vector_mp<stl_vector_mp<uint32_t>>& patches, |
|
|
|
stl_vector_mp<uint32_t>& patch_of_face_mapping) |
|
|
|
void compute_patches(const stl_vector_mp<stl_vector_mp<edge_key_t>>& edges_of_face, |
|
|
|
const flat_hash_map_mp<edge_key_t, edge_header_t>& patch_edges, |
|
|
|
const stl_vector_mp<polygon_face_t>& patch_faces, |
|
|
|
stl_vector_mp<stl_vector_mp<uint32_t>>& patches, |
|
|
|
stl_vector_mp<uint32_t>& patch_of_face_mapping, |
|
|
|
flat_hash_set_mp<edge_key_t>& patch_boundary_edges) |
|
|
|
{ |
|
|
|
stl_vector_mp<bool> visited_face(edges_of_face.size(), false); |
|
|
|
for (uint32_t i = 0; i < edges_of_face.size(); i++) { |
|
|
|
@ -63,16 +63,18 @@ void compute_patches(const stl_vector_mp<stl_vector_mp<uint32_t>>& edges_of_face |
|
|
|
const auto fId = Q.front(); |
|
|
|
Q.pop(); |
|
|
|
for (const auto eId : edges_of_face[fId]) { |
|
|
|
if (patch_edges[eId].headers.size() == 2) { // manifold edge
|
|
|
|
const auto other_fId = (patch_edges[eId].headers[0].face_index == fId) |
|
|
|
? patch_edges[eId].headers[1].face_index |
|
|
|
: patch_edges[eId].headers[0].face_index; |
|
|
|
const auto& edge_header = patch_edges.at(eId); |
|
|
|
if (edge_header.face_indices.size() == 2) { // manifold edge
|
|
|
|
const auto other_fId = |
|
|
|
(edge_header.face_indices[0] == fId) ? edge_header.face_indices[1] : edge_header.face_indices[0]; |
|
|
|
if (!visited_face[other_fId]) { |
|
|
|
Q.emplace(other_fId); |
|
|
|
patch.emplace_back(other_fId); |
|
|
|
patch_of_face_mapping[other_fId] = patch_id; |
|
|
|
visited_face[other_fId] = true; |
|
|
|
} |
|
|
|
} else if (edge_header.face_indices.size() > 2) { // non-manifold edge
|
|
|
|
patch_boundary_edges.emplace(eId); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
@ -80,57 +82,71 @@ 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, |
|
|
|
void compute_chains(const flat_hash_map_mp<edge_key_t, edge_header_t>& patch_edges, |
|
|
|
const flat_hash_set_mp<edge_key_t>& patch_boundary_edges, |
|
|
|
const stl_vector_mp<polygon_face_t>& iso_faces, |
|
|
|
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<boundary_edge_header_t>& chain_edge_headers, |
|
|
|
stl_vector_mp<chain_header_t>& chain_headers) |
|
|
|
{ |
|
|
|
stl_vector_mp<stl_vector_mp<uint32_t>> non_manifold_edges_of_vert{}; |
|
|
|
stl_vector_mp<uint32_t> non_manifold_edges{}; |
|
|
|
non_manifold_edges_of_vert.resize(iso_vert_count); |
|
|
|
non_manifold_edges.reserve(patch_edges.size() / 2); |
|
|
|
flat_hash_map_mp<uint32_t, stl_vector_mp<uint32_t>> non_manifold_edges_of_vert{}; |
|
|
|
non_manifold_edges_of_vert.reserve(patch_boundary_edges.size() / 2); |
|
|
|
// get incident non-manifold edges for iso-vertices
|
|
|
|
for (uint32_t i = 0; i < patch_edges.size(); i++) { |
|
|
|
if (patch_edges[i].headers.size() > 2) { // non-manifold edge (not a boundary edge)
|
|
|
|
// there is only one patch incident to a boundary edge, so there is no need to figure out the "order" of patches
|
|
|
|
// around a boundary edge
|
|
|
|
non_manifold_edges_of_vert[patch_edges[i].v1].emplace_back(i); |
|
|
|
non_manifold_edges_of_vert[patch_edges[i].v2].emplace_back(i); |
|
|
|
non_manifold_edges.emplace_back(i); |
|
|
|
} |
|
|
|
for (const auto& eId : patch_boundary_edges) { |
|
|
|
// there is only one patch incident to a boundary edge, so there is no need to figure out the "order" of patches
|
|
|
|
// around a boundary edge
|
|
|
|
non_manifold_edges_of_vert[eId.v1].emplace_back(eId.v2); |
|
|
|
non_manifold_edges_of_vert[eId.v2].emplace_back(eId.v1); |
|
|
|
} |
|
|
|
|
|
|
|
stl_vector_mp<bool> visited_edge(patch_edges.size(), false); |
|
|
|
flat_hash_map_mp<edge_key_t, bool> visited_edge{}; |
|
|
|
visited_edge.reserve(patch_boundary_edges.size()); |
|
|
|
stl_list_mp<uint32_t> chain{}; |
|
|
|
for (const auto& i : non_manifold_edges) { |
|
|
|
if (!visited_edge[i]) { |
|
|
|
for (const auto& start_eId : patch_boundary_edges) { |
|
|
|
if (!visited_edge[start_eId]) { |
|
|
|
// unvisited non-manifold iso-edge (not a boundary edge)
|
|
|
|
// new chain
|
|
|
|
auto& new_chain_vertices = chain_vertices.emplace_back(); |
|
|
|
auto& new_chain_headers = chain_headers.emplace_back(); |
|
|
|
auto& new_chain_vertices = chain_vertices.emplace_back(); |
|
|
|
auto& new_chain_headers = chain_headers.emplace_back(); |
|
|
|
auto& new_chain_edge_headers = chain_edge_headers.emplace_back(); |
|
|
|
chain.clear(); |
|
|
|
|
|
|
|
std::queue<uint32_t> Q{}; |
|
|
|
Q.emplace(i); |
|
|
|
chain.emplace_back(patch_edges[i].v1); |
|
|
|
chain.emplace_back(patch_edges[i].v2); |
|
|
|
new_chain_headers = patch_edges[i]; |
|
|
|
visited_edge[i] = true; |
|
|
|
new_chain_headers.v1 = start_eId.v1; |
|
|
|
new_chain_headers.v2 = start_eId.v2; |
|
|
|
new_chain_headers.face_indices = std::move(patch_edges.at(start_eId).face_indices); |
|
|
|
flat_hash_set_mp<uint32_t> unique_volume_indices{}; |
|
|
|
new_chain_edge_headers.subface_indices.reserve(new_chain_headers.face_indices.size()); |
|
|
|
for (const auto& face_index : new_chain_headers.face_indices) { |
|
|
|
std::transform(iso_faces[face_index].headers.begin(), |
|
|
|
iso_faces[face_index].headers.end(), |
|
|
|
std::back_inserter(unique_volume_indices), |
|
|
|
[](const face_header_t& header) { return header.volume_index; }); |
|
|
|
new_chain_edge_headers.subface_indices.emplace_back(iso_faces[face_index].subface_index); |
|
|
|
} |
|
|
|
std::move(unique_volume_indices.begin(), |
|
|
|
unique_volume_indices.end(), |
|
|
|
std::back_inserter(new_chain_headers.volume_indices)); |
|
|
|
new_chain_edge_headers.subface_indices.shrink_to_fit(); |
|
|
|
|
|
|
|
std::queue<edge_key_t> Q{}; |
|
|
|
Q.emplace(start_eId); |
|
|
|
chain.emplace_back(start_eId.v1); |
|
|
|
chain.emplace_back(start_eId.v2); |
|
|
|
visited_edge[start_eId] = true; |
|
|
|
while (!Q.empty()) { |
|
|
|
const auto eId = Q.front(); |
|
|
|
Q.pop(); |
|
|
|
const auto v1 = eId.v1; |
|
|
|
const auto v2 = eId.v2; |
|
|
|
// v1
|
|
|
|
auto v = patch_edges[eId].v1; |
|
|
|
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 (non_manifold_edges_of_vert[v1].size() == 2) { |
|
|
|
const auto other_vId = (non_manifold_edges_of_vert[v1][0] == v2) ? non_manifold_edges_of_vert[v1][1] |
|
|
|
: non_manifold_edges_of_vert[v1][0]; |
|
|
|
const edge_key_t other_eId = v1 < other_vId ? edge_key_t{v1, other_vId} : edge_key_t{other_vId, v1}; |
|
|
|
if (!visited_edge[other_eId]) { |
|
|
|
Q.emplace(other_eId); |
|
|
|
visited_edge[other_eId] = true; |
|
|
|
if (v == chain.front()) { |
|
|
|
if (v1 == chain.front()) { |
|
|
|
chain.emplace_front(other_vId); |
|
|
|
} else { |
|
|
|
chain.emplace_back(other_vId); |
|
|
|
@ -138,16 +154,14 @@ void compute_chains(size_t iso_ver |
|
|
|
} |
|
|
|
} |
|
|
|
// v2
|
|
|
|
v = patch_edges[eId].v2; |
|
|
|
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 (non_manifold_edges_of_vert[v2].size() == 2) { |
|
|
|
const auto other_vId = (non_manifold_edges_of_vert[v2][0] == v1) ? non_manifold_edges_of_vert[v2][1] |
|
|
|
: non_manifold_edges_of_vert[v2][0]; |
|
|
|
const edge_key_t other_eId = v2 < other_vId ? edge_key_t{v2, other_vId} : edge_key_t{other_vId, v2}; |
|
|
|
if (!visited_edge[other_eId]) { |
|
|
|
Q.emplace(other_eId); |
|
|
|
visited_edge[other_eId] = true; |
|
|
|
if (v == chain.front()) { |
|
|
|
if (v2 == chain.front()) { |
|
|
|
chain.emplace_front(other_vId); |
|
|
|
} else { |
|
|
|
chain.emplace_back(other_vId); |
|
|
|
@ -157,43 +171,43 @@ void compute_chains(size_t iso_ver |
|
|
|
} |
|
|
|
|
|
|
|
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); |
|
|
|
} |
|
|
|
// 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(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)); |
|
|
|
} |
|
|
|
// 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));
|
|
|
|
// }
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|