fix: SDF nan/edge cases + B-Rep vertex index → ID fix + IGES 1-based DE + STEP cleanup
CI / Build & Test (push) Failing after 16m57s
CI / Release Build (push) Failing after 2m59s

This commit is contained in:
茂之钳
2026-07-24 08:42:53 +00:00
parent ebc47a25c9
commit a323776fd3
12 changed files with 139 additions and 70 deletions
+49 -18
View File
@@ -14,13 +14,19 @@ curves::NurbsSurface make_plane_surface(const Point3D& p0, const Point3D& p1,
}
// Offset a vertex along its normal (average of adjacent face normals)
Point3D offset_vertex(const BrepModel& body, int vertex_id, double dist) {
Point3D p = body.vertex(vertex_id).point;
auto edges = body.vertex_edges(vertex_id);
// vertex_idx = vertex array index (0..num_vertices-1)
Point3D offset_vertex(const BrepModel& body, int vertex_idx, double dist) {
const auto& v = body.vertex(vertex_idx);
Point3D p = v.point;
int vid = v.id; // Actual vertex ID (for matching edge v_start/v_end)
Vector3D avg_normal(0,0,0);
int count = 0;
for (int ei : edges) {
auto efs = body.edge_faces(ei);
// Iterate all edges by INDEX and check v_start/v_end against vertex ID
for (size_t ei = 0; ei < body.num_edges(); ++ei) {
const auto& e = body.edge(static_cast<int>(ei));
if (e.v_start != vid && e.v_end != vid) continue;
auto efs = body.edge_faces(static_cast<int>(ei));
for (int fi : efs) {
const auto& face = body.face(fi);
const auto& surf = body.surface(face.surface_id);
@@ -43,9 +49,10 @@ Vector3D compute_face_normal(const BrepModel& body, int face_id) {
if (es.size() < 3) return Vector3D::UnitZ();
const auto& e0 = body.edge(es[0]);
const auto& e1 = body.edge(es[1]);
Point3D p0 = body.vertex(e0.v_start).point;
Point3D p1 = body.vertex(e0.v_end).point;
Point3D p2 = body.vertex(e1.v_end).point;
// v_start/v_end store vertex IDs — use vertex_by_id for proper lookup
Point3D p0 = body.vertex_by_id(e0.v_start).point;
Point3D p1 = body.vertex_by_id(e0.v_end).point;
Point3D p2 = body.vertex_by_id(e1.v_end).point;
Vector3D n = (p1 - p0).cross(p2 - p0);
if (n.norm() > 1e-12) return n.normalized();
return Vector3D::UnitZ();
@@ -301,10 +308,33 @@ BrepModel fillet(const BrepModel& body, int edge_id, double radius) {
if (edge_id < 0 || edge_id >= num_edges) return body;
if (radius <= 0.0) return body;
// Find adjacent faces — in this implementation edges are not shared,
// so edge_faces only returns 1 face. Find the other face geometrically.
auto efs = body.edge_faces(edge_id);
if (efs.size() != 2) return body; // Only handle manifold edges with 2 adjacent faces
if (efs.empty()) return body;
int face_a = efs[0];
int face_a = efs[0], face_b = efs[1];
// Find face_b: searches for a face with an edge at the same geometric position
const auto& edge = body.edge(edge_id);
Point3D ep0 = body.vertex_by_id(edge.v_start).point;
Point3D ep1 = body.vertex_by_id(edge.v_end).point;
int face_b = -1;
for (size_t fi = 0; fi < body.num_faces(); ++fi) {
if (static_cast<int>(fi) == face_a) continue;
auto f_edges = body.face_edges(static_cast<int>(fi));
for (int ei : f_edges) {
const auto& e2 = body.edge(ei);
Point3D q0 = body.vertex_by_id(e2.v_start).point;
Point3D q1 = body.vertex_by_id(e2.v_end).point;
bool same_edge = ((ep0-q0).norm() < 1e-7 && (ep1-q1).norm() < 1e-7) ||
((ep0-q1).norm() < 1e-7 && (ep1-q0).norm() < 1e-7);
if (same_edge) { face_b = static_cast<int>(fi); break; }
}
if (face_b >= 0) break;
}
if (face_b < 0) return body; // No adjacent face found
int face_a_id = face_a, face_b_id = face_b;
const auto& edge = body.edge(edge_id);
const auto& curve = *edge.curve;
@@ -370,8 +400,8 @@ BrepModel fillet(const BrepModel& body, int edge_id, double radius) {
std::vector<int> new_es;
for (int ei : lop.edges) {
const auto& e_src = body.edge(ei);
Point3D p0 = body.vertex(e_src.v_start).point;
Point3D p1 = body.vertex(e_src.v_end).point;
Point3D p0 = body.vertex_by_id(e_src.v_start).point;
Point3D p1 = body.vertex_by_id(e_src.v_end).point;
int nv0 = result.add_vertex(p0);
int nv1 = result.add_vertex(p1);
new_es.push_back(result.add_edge(nv0, nv1));
@@ -444,8 +474,8 @@ BrepModel fillet(const BrepModel& body, int edge_id, double radius) {
for (size_t j = 1; j < sorted_edges.size(); ++j) {
int old_ei = sorted_edges[j];
const auto& e_src = body.edge(old_ei);
Point3D p0 = body.vertex(e_src.v_start).point;
Point3D p1 = body.vertex(e_src.v_end).point;
Point3D p0 = body.vertex_by_id(e_src.v_start).point;
Point3D p1 = body.vertex_by_id(e_src.v_end).point;
// If either endpoint is on the filleted edge, offset it
bool v0_on_edge = (e_src.v_start == edge_src.v_start ||
@@ -594,8 +624,8 @@ BrepModel chamfer(const BrepModel& body, int edge_id, double dist) {
std::vector<int> new_es;
for (int ei : lop.edges) {
const auto& e_src = body.edge(ei);
Point3D p0 = body.vertex(e_src.v_start).point;
Point3D p1 = body.vertex(e_src.v_end).point;
Point3D p0 = body.vertex_by_id(e_src.v_start).point;
Point3D p1 = body.vertex_by_id(e_src.v_end).point;
new_es.push_back(result.add_edge(
result.add_vertex(p0), result.add_vertex(p1)));
}
@@ -633,8 +663,8 @@ BrepModel chamfer(const BrepModel& body, int edge_id, double dist) {
int oe_idx = static_cast<int>((ei + j) % lop.edges.size());
int old_ei = lop.edges[oe_idx];
const auto& e_src = body.edge(old_ei);
Point3D p0 = body.vertex(e_src.v_start).point;
Point3D p1 = body.vertex(e_src.v_end).point;
Point3D p0 = body.vertex_by_id(e_src.v_start).point;
Point3D p1 = body.vertex_by_id(e_src.v_end).point;
bool v0_on = (e_src.v_start == edge_src.v_start ||
e_src.v_start == edge_src.v_end);
@@ -698,6 +728,7 @@ BrepModel chamfer(const BrepModel& body, int edge_id, double dist) {
// ── Shell ──
BrepModel shell(const BrepModel& body, int open_face, double thickness) {
BrepModel result;
body.num_vertices(), body.num_faces(), open_face, thickness);
// ── 1. Offset all vertices inward ──
std::vector<int> outer_vid(body.num_vertices()); // map old id → new outer id