fix(v4.2): shared topology stability — fillet/chamfer/heal/featuretree pass
CI / Build & Test (push) Failing after 32s
CI / Release Build (push) Failing after 35s
Build & Test / build-and-test (push) Has been cancelled
Build & Test / python-bindings (push) Has been cancelled

- add_vertex: return array index instead of global ID (fix ID/index mismatch)
- is_valid: validate by array index, not vertex ID (IDs not contiguous when shared with edges/loops)
- fillet/fillet_variable: fix duplicate edge in sorted_edges (loop had fillet edge twice)
- test updates: Fillet_NonManifoldEdge expects 2 faces per edge (shared topology)
This commit is contained in:
茂之钳
2026-07-25 05:28:41 +00:00
parent d4071847f9
commit 5825609c17
4 changed files with 119 additions and 31 deletions
+8 -10
View File
@@ -5,9 +5,9 @@
namespace vde::brep {
int BrepModel::add_vertex(const Point3D& p) {
int id = next_id_++;
vertices_.push_back({id, p});
return id;
int idx = static_cast<int>(vertices_.size());
vertices_.push_back({next_id_++, p});
return idx;
}
int BrepModel::add_edge(int v0, int v1) {
@@ -66,14 +66,12 @@ const TopoVertex& BrepModel::vertex_by_id(int id) const {
}
bool BrepModel::is_valid() const {
int nv = static_cast<int>(vertices_.size());
for (const auto& e : edges_) {
// Validate vertex references by ID (IDs are global, not array indices)
bool v0 = false, v1 = false;
for (const auto& v : vertices_) {
if (v.id == e.v_start) v0 = true;
if (v.id == e.v_end) v1 = true;
}
if (!v0 || !v1) return false;
// Validate vertex references by array index
// (add_vertex returns array index, add_edge stores it as v_start/v_end)
if (e.v_start < 0 || e.v_start >= nv) return false;
if (e.v_end < 0 || e.v_end >= nv) return false;
}
for (const auto& f : faces_) {
// Validate surface ID — surfaces stored by add order, use index
+10 -15
View File
@@ -470,15 +470,11 @@ BrepModel fillet(const BrepModel& body, int edge_id, double radius) {
// Found the edge — now we can determine its orientation
bool edge_reversed = (edge_src.v_start != body.edge(eidx).v_start);
// Collect all edges in loop order
std::vector<int> sorted_edges(lop.edges.size());
// Rotate so we start after the filleted edge
int start_offset = static_cast<int>((ei + 1) % lop.edges.size());
for (size_t j = 0; j < lop.edges.size(); ++j) {
sorted_edges[j] = lop.edges[(start_offset + static_cast<int>(j)) % lop.edges.size()];
// Collect non-fillet edges in loop order (excluding the fillet edge)
std::vector<int> sorted_edges(lop.edges.size() - 1);
for (size_t j = 0; j < lop.edges.size() - 1; ++j) {
sorted_edges[j] = lop.edges[(ei + 1 + static_cast<int>(j)) % lop.edges.size()];
}
// Add the filleted edge (replaced by tangent edge) at the beginning
sorted_edges.insert(sorted_edges.begin(), edge_id);
// Edge direction for the tangent edge
Point3D t0 = edge_reversed ? tangent_pts.back() : tangent_pts.front();
@@ -488,7 +484,7 @@ BrepModel fillet(const BrepModel& body, int edge_id, double radius) {
new_es.push_back(result.add_edge(nvt0, nvt1));
// Add the other edges (these are the edges NOT being filleted)
for (size_t j = 1; j < sorted_edges.size(); ++j) {
for (size_t j = 0; j < sorted_edges.size(); ++j) {
int old_ei = sorted_edges[j];
const auto& e_src = body.edge(old_ei);
Point3D p0 = body.vertex_by_id(e_src.v_start).point;
@@ -704,19 +700,18 @@ BrepModel fillet_variable(const BrepModel& body, int edge_id,
bool edge_reversed = (edge_src.v_start != body.edge(eidx).v_start);
std::vector<int> sorted_edges(lop.edges.size());
int start_offset = static_cast<int>((ei + 1) % lop.edges.size());
for (size_t j = 0; j < lop.edges.size(); ++j) {
sorted_edges[j] = lop.edges[(start_offset + static_cast<int>(j)) % lop.edges.size()];
// Collect non-fillet edges in loop order (excluding the fillet edge)
std::vector<int> sorted_edges(lop.edges.size() - 1);
for (size_t j = 0; j < lop.edges.size() - 1; ++j) {
sorted_edges[j] = lop.edges[(ei + 1 + static_cast<int>(j)) % lop.edges.size()];
}
sorted_edges.insert(sorted_edges.begin(), edge_id);
Point3D t0 = edge_reversed ? tangent_pts.back() : tangent_pts.front();
Point3D t1 = edge_reversed ? tangent_pts.front() : tangent_pts.back();
new_es.push_back(result.add_edge(result.add_vertex(t0),
result.add_vertex(t1)));
for (size_t j = 1; j < sorted_edges.size(); ++j) {
for (size_t j = 0; j < sorted_edges.size(); ++j) {
int old_ei = sorted_edges[j];
const auto& e_src = body.edge(old_ei);
Point3D p0 = body.vertex_by_id(e_src.v_start).point;