You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
142 lines
6.2 KiB
142 lines
6.2 KiB
#include <container/hashmap.hpp>
|
|
#include <algorithm/glue_algorithm.hpp>
|
|
|
|
#include "ia_cut_face.hpp"
|
|
#include "implicit_arrangement.hpp"
|
|
#include "robust_assert.hpp"
|
|
|
|
std::array<uint32_t, 3> ia_cut_2_face(ia_complex_t& ia_complex,
|
|
uint32_t fid,
|
|
uint32_t plane_index,
|
|
const stl_vector_mp<int8_t>& orientations,
|
|
const stl_vector_mp<std::array<uint32_t, 3>>& subedges)
|
|
{
|
|
auto& edges = ia_complex.edges;
|
|
auto& faces = ia_complex.faces;
|
|
edges.reserve(edges.size() + 1);
|
|
faces.reserve(faces.size() + 2);
|
|
|
|
auto& f = faces[fid];
|
|
const size_t num_boundary_edges = f.edges.size();
|
|
|
|
stl_vector_mp<uint32_t> positive_subedges{}, negative_subedges{};
|
|
positive_subedges.reserve(num_boundary_edges);
|
|
negative_subedges.reserve(num_boundary_edges);
|
|
|
|
ia_edge_t cut_edge;
|
|
uint32_t cut_edge_index = INVALID_INDEX;
|
|
bool face_is_coplanar = true;
|
|
uint32_t cut_edge_positive_location = INVALID_INDEX;
|
|
uint32_t cut_edge_negative_location = INVALID_INDEX;
|
|
|
|
auto get_end_vertex = [&](uint32_t local_eid) {
|
|
auto curr_eid = f.edges[local_eid];
|
|
auto next_eid = f.edges[(local_eid + 1) % num_boundary_edges];
|
|
const auto& e0 = edges[curr_eid];
|
|
const auto& e1 = edges[next_eid];
|
|
if (e0.vertices[0] == e1.vertices[0] || e0.vertices[0] == e1.vertices[1]) {
|
|
return e0.vertices[0];
|
|
} else {
|
|
ROBUST_ASSERT(e0.vertices[1] == e1.vertices[0] || e0.vertices[1] == e1.vertices[1]);
|
|
return e0.vertices[1];
|
|
}
|
|
};
|
|
|
|
for (size_t j = 0; j < num_boundary_edges; j++) {
|
|
const auto eid = f.edges[j];
|
|
|
|
bool last_positive = false;
|
|
bool last_negative = false;
|
|
auto intersection_point = subedges[eid][2];
|
|
auto positive_subedge = subedges[eid][0];
|
|
auto negative_subedge = subedges[eid][1];
|
|
|
|
if (positive_subedge == INVALID_INDEX && negative_subedge == INVALID_INDEX) {
|
|
// Edge is coplanar with the plane.
|
|
cut_edge_index = eid;
|
|
} else {
|
|
if (positive_subedge != INVALID_INDEX) {
|
|
positive_subedges.emplace_back(positive_subedge);
|
|
auto end_vid = get_end_vertex(static_cast<uint32_t>(j));
|
|
if (orientations[end_vid] <= 0) {
|
|
// This edge is the last edge with positive subedge.
|
|
cut_edge_positive_location = positive_subedges.size();
|
|
last_positive = true;
|
|
}
|
|
}
|
|
if (negative_subedge != INVALID_INDEX) {
|
|
negative_subedges.emplace_back(negative_subedge);
|
|
auto end_vid = get_end_vertex(static_cast<uint32_t>(j));
|
|
if (orientations[end_vid] >= 0) {
|
|
// This edge is the last edge with negative subedge.
|
|
cut_edge_negative_location = negative_subedges.size();
|
|
last_negative = true;
|
|
}
|
|
}
|
|
face_is_coplanar = false;
|
|
}
|
|
if (intersection_point != INVALID_INDEX) {
|
|
if (last_positive) {
|
|
cut_edge.vertices[0] = intersection_point;
|
|
} else if (last_negative) {
|
|
cut_edge.vertices[1] = intersection_point;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (face_is_coplanar) { return {INVALID_INDEX, INVALID_INDEX, INVALID_INDEX}; }
|
|
|
|
if (positive_subedges.empty() || negative_subedges.empty()) {
|
|
// No cut.
|
|
if (positive_subedges.empty()) {
|
|
ROBUST_ASSERT(!negative_subedges.empty());
|
|
return {INVALID_INDEX, fid, cut_edge_index};
|
|
} else {
|
|
ROBUST_ASSERT(!positive_subedges.empty());
|
|
ROBUST_ASSERT(negative_subedges.empty());
|
|
return {fid, INVALID_INDEX, cut_edge_index};
|
|
}
|
|
}
|
|
|
|
ROBUST_ASSERT(cut_edge_index == INVALID_INDEX);
|
|
{
|
|
// Insert cut edge.
|
|
cut_edge.supporting_planes = {f.supporting_plane, plane_index};
|
|
cut_edge_index = edges.size();
|
|
edges.emplace_back(std::move(cut_edge));
|
|
}
|
|
|
|
// Create subfaces.
|
|
ia_face_t positive_subface, negative_subface;
|
|
positive_subface.supporting_plane = f.supporting_plane;
|
|
negative_subface.supporting_plane = f.supporting_plane;
|
|
positive_subface.positive_cell = f.positive_cell;
|
|
positive_subface.negative_cell = f.negative_cell;
|
|
negative_subface.positive_cell = f.positive_cell;
|
|
negative_subface.negative_cell = f.negative_cell;
|
|
|
|
ROBUST_ASSERT(cut_edge_index != INVALID_INDEX);
|
|
if (cut_edge_positive_location != positive_subedges.size()) {
|
|
algorithm::rotate<algorithm::ExecutionPolicySelector::simd_only>(positive_subedges.begin(),
|
|
positive_subedges.begin() + cut_edge_positive_location,
|
|
positive_subedges.end());
|
|
}
|
|
if (cut_edge_negative_location != negative_subedges.size()) {
|
|
algorithm::rotate<algorithm::ExecutionPolicySelector::simd_only>(negative_subedges.begin(),
|
|
negative_subedges.begin() + cut_edge_negative_location,
|
|
negative_subedges.end());
|
|
}
|
|
positive_subedges.emplace_back(cut_edge_index);
|
|
positive_subface.edges = std::move(positive_subedges);
|
|
ROBUST_ASSERT(positive_subface.edges.size() > 2);
|
|
negative_subedges.emplace_back(cut_edge_index);
|
|
negative_subface.edges = std::move(negative_subedges);
|
|
ROBUST_ASSERT(negative_subface.edges.size() > 2);
|
|
|
|
faces.emplace_back(std::move(positive_subface));
|
|
faces.emplace_back(std::move(negative_subface));
|
|
uint32_t positive_fid = static_cast<uint32_t>(faces.size() - 2);
|
|
uint32_t negative_fid = static_cast<uint32_t>(faces.size() - 1);
|
|
|
|
return {positive_fid, negative_fid, cut_edge_index};
|
|
}
|