Reworked bucket fill so that all neighboring triangles are computed based on information about triangle neighbors.
This commit is contained in:
parent
6d0e5d3b9c
commit
f577350f1f
2 changed files with 139 additions and 95 deletions
|
@ -228,7 +228,7 @@ void TriangleSelector::seed_fill_select_triangles(const Vec3f &hit, int facet_st
|
|||
}
|
||||
}
|
||||
|
||||
void TriangleSelector::precompute_all_level_neighbors_recursive(const int facet_idx, const Vec3i &neighbors, const Vec3i &neighbors_propagated, std::vector<Vec3i> &neighbors_out) const
|
||||
void TriangleSelector::precompute_all_neighbors_recursive(const int facet_idx, const Vec3i &neighbors, const Vec3i &neighbors_propagated, std::vector<Vec3i> &neighbors_out, std::vector<Vec3i> &neighbors_propagated_out) const
|
||||
{
|
||||
assert(facet_idx < int(m_triangles.size()));
|
||||
|
||||
|
@ -236,7 +236,8 @@ void TriangleSelector::precompute_all_level_neighbors_recursive(const int facet_
|
|||
if (!tr->valid())
|
||||
return;
|
||||
|
||||
neighbors_out[facet_idx] = neighbors_propagated;
|
||||
neighbors_out[facet_idx] = neighbors;
|
||||
neighbors_propagated_out[facet_idx] = neighbors_propagated;
|
||||
if (tr->is_split()) {
|
||||
assert(this->verify_triangle_neighbors(*tr, neighbors));
|
||||
|
||||
|
@ -247,67 +248,51 @@ void TriangleSelector::precompute_all_level_neighbors_recursive(const int facet_
|
|||
assert(tr->children[i] < int(m_triangles.size()));
|
||||
// Recursion, deep first search over the children of this triangle.
|
||||
// All children of this triangle were created by splitting a single source triangle of the original mesh.
|
||||
this->precompute_all_level_neighbors_recursive(tr->children[i], this->child_neighbors(*tr, neighbors, i), this->child_neighbors_propagated(*tr, neighbors_propagated, i), neighbors_out);
|
||||
this->precompute_all_neighbors_recursive(tr->children[i], this->child_neighbors(*tr, neighbors, i),
|
||||
this->child_neighbors_propagated(*tr, neighbors_propagated, i), neighbors_out,
|
||||
neighbors_propagated_out);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Vec3i> TriangleSelector::precompute_all_level_neighbors() const
|
||||
std::pair<std::vector<Vec3i>, std::vector<Vec3i>> TriangleSelector::precompute_all_neighbors() const
|
||||
{
|
||||
std::vector<Vec3i> neighbors(m_triangles.size(), Vec3i(-1, -1, -1));
|
||||
std::vector<Vec3i> neighbors_propagated(m_triangles.size(), Vec3i(-1, -1, -1));
|
||||
for (int facet_idx = 0; facet_idx < this->m_orig_size_indices; ++facet_idx) {
|
||||
neighbors[facet_idx] = root_neighbors(*m_mesh, facet_idx);
|
||||
neighbors[facet_idx] = root_neighbors(*m_mesh, facet_idx);
|
||||
neighbors_propagated[facet_idx] = neighbors[facet_idx];
|
||||
assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors[facet_idx]));
|
||||
if (m_triangles[facet_idx].is_split())
|
||||
this->precompute_all_level_neighbors_recursive(facet_idx, neighbors[facet_idx], neighbors[facet_idx], neighbors);
|
||||
this->precompute_all_neighbors_recursive(facet_idx, neighbors[facet_idx], neighbors_propagated[facet_idx], neighbors, neighbors_propagated);
|
||||
}
|
||||
return neighbors;
|
||||
return std::make_pair(std::move(neighbors), std::move(neighbors_propagated));
|
||||
}
|
||||
|
||||
bool TriangleSelector::are_triangles_touching(const int first_facet_idx, const int second_facet_idx) const
|
||||
// It appends all triangles that are touching the edge (vertexi, vertexj) of the triangle.
|
||||
// It doesn't append the triangles that are touching the triangle only by part of the edge that means the triangles are from lower depth.
|
||||
void TriangleSelector::append_touching_subtriangles(int itriangle, int vertexi, int vertexj, std::vector<int> &touching_subtriangles_out) const
|
||||
{
|
||||
std::array<Linef3, 3> sides_facet = {Linef3(m_vertices[m_triangles[first_facet_idx].verts_idxs[0]].v.cast<double>(), m_vertices[m_triangles[first_facet_idx].verts_idxs[1]].v.cast<double>()),
|
||||
Linef3(m_vertices[m_triangles[first_facet_idx].verts_idxs[1]].v.cast<double>(), m_vertices[m_triangles[first_facet_idx].verts_idxs[2]].v.cast<double>()),
|
||||
Linef3(m_vertices[m_triangles[first_facet_idx].verts_idxs[2]].v.cast<double>(), m_vertices[m_triangles[first_facet_idx].verts_idxs[0]].v.cast<double>())};
|
||||
if (itriangle == -1)
|
||||
return;
|
||||
|
||||
const Vec3d p0 = m_vertices[m_triangles[second_facet_idx].verts_idxs[0]].v.cast<double>();
|
||||
const Vec3d p1 = m_vertices[m_triangles[second_facet_idx].verts_idxs[1]].v.cast<double>();
|
||||
const Vec3d p2 = m_vertices[m_triangles[second_facet_idx].verts_idxs[2]].v.cast<double>();
|
||||
auto process_subtriangle = [this, &itriangle, &vertexi, &vertexj, &touching_subtriangles_out](const int subtriangle_idx) -> void {
|
||||
assert(subtriangle_idx == -1);
|
||||
if (!m_triangles[subtriangle_idx].is_split())
|
||||
touching_subtriangles_out.emplace_back(subtriangle_idx);
|
||||
else if (int midpoint = this->triangle_midpoint(itriangle, vertexi, vertexj); midpoint != -1)
|
||||
append_touching_subtriangles(subtriangle_idx, vertexi, midpoint, touching_subtriangles_out);
|
||||
else
|
||||
append_touching_subtriangles(subtriangle_idx, vertexi, vertexj, touching_subtriangles_out);
|
||||
};
|
||||
|
||||
for (size_t idx = 0; idx < 3; ++idx)
|
||||
if (line_alg::distance_to_squared(sides_facet[idx], p0) <= EPSILON && (line_alg::distance_to_squared(sides_facet[idx], p1) <= EPSILON || line_alg::distance_to_squared(sides_facet[idx], p2) <= EPSILON))
|
||||
return true;
|
||||
else if (line_alg::distance_to_squared(sides_facet[idx], p1) <= EPSILON && line_alg::distance_to_squared(sides_facet[idx], p2) <= EPSILON)
|
||||
return true;
|
||||
std::pair<int, int> touching = this->triangle_subtriangles(itriangle, vertexi, vertexj);
|
||||
if (touching.first != -1)
|
||||
process_subtriangle(touching.first);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<int> TriangleSelector::neighboring_triangles(const int first_facet_idx, const int second_facet_idx, EnforcerBlockerType second_facet_state) const
|
||||
{
|
||||
assert(first_facet_idx < int(m_triangles.size()));
|
||||
|
||||
const Triangle *tr = &m_triangles[first_facet_idx];
|
||||
if (!tr->valid())
|
||||
return {};
|
||||
|
||||
if (!tr->is_split() && tr->get_state() == second_facet_state && (are_triangles_touching(second_facet_idx, first_facet_idx) || are_triangles_touching(first_facet_idx, second_facet_idx)))
|
||||
return {first_facet_idx};
|
||||
|
||||
std::vector<int> neighbor_facets_out;
|
||||
int num_of_children = tr->number_of_split_sides() + 1;
|
||||
if (num_of_children != 1) {
|
||||
for (int i = 0; i < num_of_children; ++i) {
|
||||
assert(i < int(tr->children.size()));
|
||||
assert(tr->children[i] < int(m_triangles.size()));
|
||||
|
||||
if (std::vector<int> neighbor_facets = neighboring_triangles(tr->children[i], second_facet_idx, second_facet_state); !neighbor_facets.empty())
|
||||
Slic3r::append(neighbor_facets_out, std::move(neighbor_facets));
|
||||
}
|
||||
}
|
||||
|
||||
return neighbor_facets_out;
|
||||
if (touching.second != -1)
|
||||
process_subtriangle(touching.second);
|
||||
}
|
||||
|
||||
void TriangleSelector::bucket_fill_select_triangles(const Vec3f& hit, int facet_start, bool propagate)
|
||||
|
@ -326,7 +311,23 @@ void TriangleSelector::bucket_fill_select_triangles(const Vec3f& hit, int facet_
|
|||
return;
|
||||
}
|
||||
|
||||
std::vector<Vec3i> all_level_neighbors = this->precompute_all_level_neighbors();
|
||||
auto get_all_touching_triangles = [this](int facet_idx, const Vec3i &neighbors, const Vec3i &neighbors_propagated) -> std::vector<int> {
|
||||
assert(facet_idx != -1 && facet_idx < m_triangles.size());
|
||||
assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors));
|
||||
std::vector<int> touching_triangles;
|
||||
Vec3i vertices = {m_triangles[facet_idx].verts_idxs[0], m_triangles[facet_idx].verts_idxs[1], m_triangles[facet_idx].verts_idxs[2]};
|
||||
append_touching_subtriangles(neighbors(0), vertices(1), vertices(0), touching_triangles);
|
||||
append_touching_subtriangles(neighbors(1), vertices(2), vertices(1), touching_triangles);
|
||||
append_touching_subtriangles(neighbors(2), vertices(0), vertices(2), touching_triangles);
|
||||
|
||||
for (int neighbor_idx : neighbors_propagated)
|
||||
if (neighbor_idx != -1 && !m_triangles[neighbor_idx].is_split())
|
||||
touching_triangles.emplace_back(neighbor_idx);
|
||||
|
||||
return touching_triangles;
|
||||
};
|
||||
|
||||
auto [neighbors, neighbors_propagated] = this->precompute_all_neighbors();
|
||||
std::vector<bool> visited(m_triangles.size(), false);
|
||||
std::queue<int> facet_queue;
|
||||
|
||||
|
@ -338,17 +339,14 @@ void TriangleSelector::bucket_fill_select_triangles(const Vec3f& hit, int facet_
|
|||
|
||||
if (!visited[current_facet]) {
|
||||
m_triangles[current_facet].select_by_seed_fill();
|
||||
for (int neighbor_idx : all_level_neighbors[current_facet]) {
|
||||
if (neighbor_idx < 0 || visited[neighbor_idx])
|
||||
|
||||
std::vector<int> touching_triangles = get_all_touching_triangles(current_facet, neighbors[current_facet], neighbors_propagated[current_facet]);
|
||||
for(const int tr_idx : touching_triangles) {
|
||||
if (tr_idx < 0 || visited[tr_idx] || m_triangles[tr_idx].get_state() != start_facet_state)
|
||||
continue;
|
||||
|
||||
if (!m_triangles[neighbor_idx].is_split()) {
|
||||
if (m_triangles[neighbor_idx].get_state() == start_facet_state)
|
||||
facet_queue.push(neighbor_idx);
|
||||
} else {
|
||||
for (int neighbor_facet_idx : neighboring_triangles(neighbor_idx, current_facet, start_facet_state))
|
||||
facet_queue.push(neighbor_facet_idx);
|
||||
}
|
||||
assert(!m_triangles[tr_idx].is_split());
|
||||
facet_queue.push(tr_idx);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -437,6 +435,40 @@ int TriangleSelector::neighbor_child(int itriangle, int vertexi, int vertexj, Pa
|
|||
return itriangle == -1 ? -1 : this->neighbor_child(m_triangles[itriangle], vertexi, vertexj, partition);
|
||||
}
|
||||
|
||||
std::pair<int, int> TriangleSelector::triangle_subtriangles(int itriangle, int vertexi, int vertexj) const
|
||||
{
|
||||
return itriangle == -1 ? std::make_pair(-1, -1) : this->triangle_subtriangles(m_triangles[itriangle], vertexi, vertexj);
|
||||
}
|
||||
|
||||
std::pair<int, int> TriangleSelector::triangle_subtriangles(const Triangle &tr, int vertexi, int vertexj)
|
||||
{
|
||||
if (tr.number_of_split_sides() == 0)
|
||||
// If this triangle is not split, then there is no subtriangles touching the edge.
|
||||
return std::make_pair(-1, -1);
|
||||
|
||||
// Find the triangle edge.
|
||||
int edge = tr.verts_idxs[0] == vertexi ? 0 : tr.verts_idxs[1] == vertexi ? 1 : 2;
|
||||
assert(tr.verts_idxs[edge] == vertexi);
|
||||
assert(tr.verts_idxs[next_idx_modulo(edge, 3)] == vertexj);
|
||||
|
||||
if (tr.number_of_split_sides() == 1) {
|
||||
return edge == next_idx_modulo(tr.special_side(), 3) ? std::make_pair(tr.children[0], tr.children[1]) :
|
||||
std::make_pair(tr.children[edge == tr.special_side() ? 0 : 1], -1);
|
||||
} else if (tr.number_of_split_sides() == 2) {
|
||||
return edge == next_idx_modulo(tr.special_side(), 3) ? std::make_pair(tr.children[2], -1) :
|
||||
edge == tr.special_side() ? std::make_pair(tr.children[0], tr.children[1]) :
|
||||
std::make_pair(tr.children[2], tr.children[0]);
|
||||
} else {
|
||||
assert(tr.number_of_split_sides() == 3);
|
||||
assert(tr.special_side() == 0);
|
||||
return edge == 0 ? std::make_pair(tr.children[0], tr.children[1]) :
|
||||
edge == 1 ? std::make_pair(tr.children[1], tr.children[2]) :
|
||||
std::make_pair(tr.children[2], tr.children[0]);
|
||||
}
|
||||
|
||||
return std::make_pair(-1, -1);
|
||||
}
|
||||
|
||||
// Return existing midpoint of CCW oriented side (vertexi, vertexj).
|
||||
// If itriangle == -1 or if the side sharing (vertexi, vertexj) is not split, return -1.
|
||||
int TriangleSelector::triangle_midpoint(const Triangle &tr, int vertexi, int vertexj) const
|
||||
|
@ -524,12 +556,8 @@ Vec3i TriangleSelector::child_neighbors(const Triangle &tr, const Vec3i &neighbo
|
|||
|
||||
assert(child_idx >= 0 && child_idx <= tr.number_of_split_sides());
|
||||
int i = tr.special_side();
|
||||
int j = i + 1;
|
||||
if (j >= 3)
|
||||
j = 0;
|
||||
int k = j + 1;
|
||||
if (k >= 3)
|
||||
k = 0;
|
||||
int j = next_idx_modulo(i, 3);
|
||||
int k = next_idx_modulo(j, 3);
|
||||
|
||||
Vec3i out;
|
||||
switch (tr.number_of_split_sides()) {
|
||||
|
@ -612,23 +640,28 @@ Vec3i TriangleSelector::child_neighbors(const Triangle &tr, const Vec3i &neighbo
|
|||
Vec3i TriangleSelector::child_neighbors_propagated(const Triangle &tr, const Vec3i &neighbors, int child_idx) const
|
||||
{
|
||||
int i = tr.special_side();
|
||||
int j = i + 1;
|
||||
if (j >= 3) j = 0;
|
||||
int k = j + 1;
|
||||
if (k >= 3) k = 0;
|
||||
int j = next_idx_modulo(i, 3);
|
||||
int k = next_idx_modulo(j, 3);
|
||||
|
||||
Vec3i out;
|
||||
auto replace_if_not_exists = [&out](int index_to_replace, int neighbor) {
|
||||
if (out(index_to_replace) == -1)
|
||||
out(index_to_replace) = neighbor;
|
||||
};
|
||||
|
||||
switch (tr.number_of_split_sides()) {
|
||||
case 1:
|
||||
switch (child_idx) {
|
||||
case 0:
|
||||
out(0) = neighbors(i);
|
||||
out(1) = neighbors(j);
|
||||
out(1) = this->neighbor_child(neighbors(j), tr.verts_idxs[k], tr.verts_idxs[j], Partition::Second);
|
||||
replace_if_not_exists(1, neighbors(j));
|
||||
out(2) = tr.children[1];
|
||||
break;
|
||||
default:
|
||||
assert(child_idx == 1);
|
||||
out(0) = neighbors(j);
|
||||
out(0) = this->neighbor_child(neighbors(j), tr.verts_idxs[k], tr.verts_idxs[j], Partition::First);
|
||||
replace_if_not_exists(0, neighbors(j));
|
||||
out(1) = neighbors(k);
|
||||
out(2) = tr.children[0];
|
||||
break;
|
||||
|
@ -638,20 +671,24 @@ Vec3i TriangleSelector::child_neighbors_propagated(const Triangle &tr, const Vec
|
|||
case 2:
|
||||
switch (child_idx) {
|
||||
case 0:
|
||||
out(0) = neighbors(i);
|
||||
out(0) = this->neighbor_child(neighbors(i), tr.verts_idxs[j], tr.verts_idxs[i], Partition::Second);
|
||||
replace_if_not_exists(0, neighbors(i));
|
||||
out(1) = tr.children[1];
|
||||
out(2) = neighbors(k);
|
||||
out(2) = this->neighbor_child(neighbors(k), tr.verts_idxs[i], tr.verts_idxs[k], Partition::First);
|
||||
replace_if_not_exists(2, neighbors(k));
|
||||
break;
|
||||
case 1:
|
||||
assert(child_idx == 1);
|
||||
out(0) = neighbors(i);
|
||||
out(0) = this->neighbor_child(neighbors(i), tr.verts_idxs[j], tr.verts_idxs[i], Partition::First);
|
||||
replace_if_not_exists(0, neighbors(i));
|
||||
out(1) = tr.children[2];
|
||||
out(2) = tr.children[0];
|
||||
break;
|
||||
default:
|
||||
assert(child_idx == 2);
|
||||
out(0) = neighbors(j);
|
||||
out(1) = neighbors(k);
|
||||
out(1) = this->neighbor_child(neighbors(k), tr.verts_idxs[i], tr.verts_idxs[k], Partition::Second);
|
||||
replace_if_not_exists(1, neighbors(k));
|
||||
out(2) = tr.children[1];
|
||||
break;
|
||||
}
|
||||
|
@ -661,18 +698,24 @@ Vec3i TriangleSelector::child_neighbors_propagated(const Triangle &tr, const Vec
|
|||
assert(tr.special_side() == 0);
|
||||
switch (child_idx) {
|
||||
case 0:
|
||||
out(0) = neighbors(0);
|
||||
out(0) = this->neighbor_child(neighbors(0), tr.verts_idxs[1], tr.verts_idxs[0], Partition::Second);
|
||||
replace_if_not_exists(0, neighbors(0));
|
||||
out(1) = tr.children[3];
|
||||
out(2) = neighbors(2);
|
||||
out(2) = this->neighbor_child(neighbors(2), tr.verts_idxs[0], tr.verts_idxs[2], Partition::First);
|
||||
replace_if_not_exists(2, neighbors(2));
|
||||
break;
|
||||
case 1:
|
||||
out(0) = neighbors(0);
|
||||
out(1) = neighbors(1);
|
||||
out(0) = this->neighbor_child(neighbors(0), tr.verts_idxs[1], tr.verts_idxs[0], Partition::First);
|
||||
replace_if_not_exists(0, neighbors(0));
|
||||
out(1) = this->neighbor_child(neighbors(1), tr.verts_idxs[2], tr.verts_idxs[1], Partition::Second);
|
||||
replace_if_not_exists(1, neighbors(1));
|
||||
out(2) = tr.children[3];
|
||||
break;
|
||||
case 2:
|
||||
out(0) = neighbors(1);
|
||||
out(1) = neighbors(2);
|
||||
out(0) = this->neighbor_child(neighbors(1), tr.verts_idxs[2], tr.verts_idxs[1], Partition::First);
|
||||
replace_if_not_exists(0, neighbors(1));
|
||||
out(1) = this->neighbor_child(neighbors(2), tr.verts_idxs[0], tr.verts_idxs[2], Partition::Second);
|
||||
replace_if_not_exists(1, neighbors(2));
|
||||
out(2) = tr.children[3];
|
||||
break;
|
||||
default:
|
||||
|
@ -886,13 +929,13 @@ void TriangleSelector::undivide_triangle(int facet_idx)
|
|||
Triangle& tr = m_triangles[facet_idx];
|
||||
|
||||
if (tr.is_split()) {
|
||||
for (int i=0; i<=tr.number_of_split_sides(); ++i) {
|
||||
for (int i = 0; i <= tr.number_of_split_sides(); ++i) {
|
||||
int child = tr.children[i];
|
||||
Triangle &child_tr = m_triangles[child];
|
||||
assert(child_tr.valid());
|
||||
undivide_triangle(child);
|
||||
for (int i = 0; i < 3; ++ i) {
|
||||
int iv = child_tr.verts_idxs[i];
|
||||
for (int j = 0; j < 3; ++j) {
|
||||
int iv = child_tr.verts_idxs[j];
|
||||
Vertex &v = m_vertices[iv];
|
||||
assert(v.ref_cnt > 0);
|
||||
if (-- v.ref_cnt == 0) {
|
||||
|
@ -1231,7 +1274,7 @@ void TriangleSelector::get_facets_strict_recursive(
|
|||
this->get_facets_split_by_tjoints({tr.verts_idxs[0], tr.verts_idxs[1], tr.verts_idxs[2]}, neighbors, out_triangles);
|
||||
}
|
||||
|
||||
void TriangleSelector::get_facets_split_by_tjoints(const Vec3i vertices, const Vec3i neighbors, std::vector<stl_triangle_vertex_indices> &out_triangles) const
|
||||
void TriangleSelector::get_facets_split_by_tjoints(const Vec3i &vertices, const Vec3i &neighbors, std::vector<stl_triangle_vertex_indices> &out_triangles) const
|
||||
{
|
||||
// Export this triangle, but first collect the T-joint vertices along its edges.
|
||||
Vec3i midpoints(
|
||||
|
|
|
@ -22,8 +22,8 @@ public:
|
|||
POINTER
|
||||
};
|
||||
|
||||
[[nodiscard]] std::vector<Vec3i> precompute_all_level_neighbors() const;
|
||||
void precompute_all_level_neighbors_recursive(const int facet_idx, const Vec3i &neighbors, const Vec3i &neighbors_propagated, std::vector<Vec3i> &neighbors_out) const;
|
||||
std::pair<std::vector<Vec3i>, std::vector<Vec3i>> precompute_all_neighbors() const;
|
||||
void precompute_all_neighbors_recursive(int facet_idx, const Vec3i &neighbors, const Vec3i &neighbors_propagated, std::vector<Vec3i> &neighbors_out, std::vector<Vec3i> &neighbors_normal_out) const;
|
||||
|
||||
// Set a limit to the edge length, below which the edge will not be split by select_patch().
|
||||
// Called by select_patch() internally. Made public for debugging purposes, see TriangleSelectorGUI::render_debug().
|
||||
|
@ -37,10 +37,6 @@ public:
|
|||
[[nodiscard]] int select_unsplit_triangle(const Vec3f &hit, int facet_idx) const;
|
||||
[[nodiscard]] int select_unsplit_triangle(const Vec3f &hit, int facet_idx, const Vec3i &neighbors) const;
|
||||
|
||||
[[nodiscard]] bool are_triangles_touching(int first_facet_idx, int second_facet_idx) const;
|
||||
|
||||
[[nodiscard]] std::vector<int> neighboring_triangles(int first_facet_idx, int second_facet_idx, EnforcerBlockerType second_facet_state) const;
|
||||
|
||||
// Select all triangles fully inside the circle, subdivide where needed.
|
||||
void select_patch(const Vec3f &hit, // point where to start
|
||||
int facet_start, // facet of the original mesh (unsplit) that the hit point belongs to
|
||||
|
@ -60,7 +56,7 @@ public:
|
|||
bool propagate); // if bucket fill is propagated to neighbor faces or if it fills the only facet of the modified mesh that the hit point belongs to.
|
||||
|
||||
bool has_facets(EnforcerBlockerType state) const;
|
||||
static bool has_facets(const std::pair<std::vector<std::pair<int, int>>, std::vector<bool>> &data, const EnforcerBlockerType test_state);
|
||||
static bool has_facets(const std::pair<std::vector<std::pair<int, int>>, std::vector<bool>> &data, EnforcerBlockerType test_state);
|
||||
int num_facets(EnforcerBlockerType state) const;
|
||||
// Get facets at a given state. Don't triangulate T-joints.
|
||||
indexed_triangle_set get_facets(EnforcerBlockerType state) const;
|
||||
|
@ -128,11 +124,11 @@ protected:
|
|||
bool is_selected_by_seed_fill() const { assert(! is_split()); return m_selected_by_seed_fill; }
|
||||
|
||||
// Is this triangle valid or marked to be removed?
|
||||
bool valid() const throw() { return m_valid; }
|
||||
bool valid() const noexcept { return m_valid; }
|
||||
// Get info on how it's split.
|
||||
bool is_split() const throw() { return number_of_split_sides() != 0; }
|
||||
int number_of_split_sides() const throw() { return number_of_splits; }
|
||||
int special_side() const throw() { assert(is_split()); return special_side_idx; }
|
||||
bool is_split() const noexcept { return number_of_split_sides() != 0; }
|
||||
int number_of_split_sides() const noexcept { return number_of_splits; }
|
||||
int special_side() const noexcept { assert(is_split()); return special_side_idx; }
|
||||
|
||||
private:
|
||||
friend TriangleSelector;
|
||||
|
@ -205,7 +201,7 @@ private:
|
|||
void remove_useless_children(int facet_idx); // No hidden meaning. Triangles are meant.
|
||||
bool is_pointer_in_triangle(int facet_idx) const;
|
||||
bool is_edge_inside_cursor(int facet_idx) const;
|
||||
int push_triangle(int a, int b, int c, int source_triangle, const EnforcerBlockerType state = EnforcerBlockerType{0});
|
||||
int push_triangle(int a, int b, int c, int source_triangle, EnforcerBlockerType state = EnforcerBlockerType{0});
|
||||
void perform_split(int facet_idx, const Vec3i &neighbors, EnforcerBlockerType old_state);
|
||||
Vec3i child_neighbors(const Triangle &tr, const Vec3i &neighbors, int child_idx) const;
|
||||
Vec3i child_neighbors_propagated(const Triangle &tr, const Vec3i &neighbors, int child_idx) const;
|
||||
|
@ -221,6 +217,11 @@ private:
|
|||
int triangle_midpoint(int itriangle, int vertexi, int vertexj) const;
|
||||
int triangle_midpoint_or_allocate(int itriangle, int vertexi, int vertexj);
|
||||
|
||||
static std::pair<int, int> triangle_subtriangles(const Triangle &tr, int vertexi, int vertexj);
|
||||
std::pair<int, int> triangle_subtriangles(int itriangle, int vertexi, int vertexj) const;
|
||||
|
||||
void append_touching_subtriangles(int itriangle, int vertexi, int vertexj, std::vector<int> &touching_subtriangles_out) const;
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool verify_triangle_neighbors(const Triangle& tr, const Vec3i& neighbors) const;
|
||||
bool verify_triangle_midpoints(const Triangle& tr) const;
|
||||
|
@ -231,7 +232,7 @@ private:
|
|||
const Vec3i &neighbors,
|
||||
EnforcerBlockerType state,
|
||||
std::vector<stl_triangle_vertex_indices> &out_triangles) const;
|
||||
void get_facets_split_by_tjoints(const Vec3i vertices, const Vec3i neighbors, std::vector<stl_triangle_vertex_indices> &out_triangles) const;
|
||||
void get_facets_split_by_tjoints(const Vec3i &vertices, const Vec3i &neighbors, std::vector<stl_triangle_vertex_indices> &out_triangles) const;
|
||||
|
||||
int m_free_triangles_head { -1 };
|
||||
int m_free_vertices_head { -1 };
|
||||
|
|
Loading…
Reference in a new issue