fix: remove duplicate edge declaration in modeling.cpp
CI / Build & Test (push) Failing after 33s
CI / Release Build (push) Failing after 30s

This commit is contained in:
茂之钳
2026-07-24 08:45:36 +00:00
parent a323776fd3
commit 4a07bf34dc
2 changed files with 84 additions and 40 deletions
+21 -7
View File
@@ -334,10 +334,6 @@ BrepModel fillet(const BrepModel& body, int edge_id, double radius) {
}
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;
// Compute face normals
Vector3D n_a = compute_face_normal(body, face_a);
Vector3D n_b = compute_face_normal(body, face_b);
@@ -566,10 +562,29 @@ BrepModel chamfer(const BrepModel& body, int edge_id, double dist) {
if (dist <= 0.0) return body;
auto efs = body.edge_faces(edge_id);
if (efs.size() != 2) return body;
if (efs.empty()) return body;
int face_a = efs[0];
int face_a = efs[0], face_b = efs[1];
// Find face_b geometrically (edges are not shared between faces in this impl)
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;
const auto& curve = *edge.curve;
Vector3D n_a = compute_face_normal(body, face_a);
@@ -728,7 +743,6 @@ 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
+63 -33
View File
@@ -574,12 +574,31 @@ private:
int vec_ref = to_ref(ent.args[2]);
Point3D p = (points_.count(pnt_ref)) ? points_[pnt_ref] : Point3D(0,0,0);
Vector3D v = (vectors_.count(vec_ref)) ? vectors_[vec_ref] : Vector3D(1,0,0);
// Eagerly resolve VECTOR entity if not yet cached
Vector3D v = resolve_vector(vec_ref);
std::vector<Point3D> cps = {p, p + v};
return curves::NurbsCurve(cps, {0,0,1,1}, {1,1}, 1);
}
Vector3D resolve_vector(int vec_ref) {
if (vectors_.count(vec_ref)) return vectors_[vec_ref];
if (!entities_.count(vec_ref)) return Vector3D(1, 0, 0);
const auto& vent = entities_.at(vec_ref);
// VECTOR: name, orientation (DIRECTION ref), magnitude
if (vent.args.size() >= 3) {
int dir_ref = to_ref(vent.args[1]);
double mag = to_double(vent.args[2]);
Vector3D d = (directions_.count(dir_ref))
? directions_[dir_ref].normalized()
: Vector3D(1, 0, 0);
Vector3D v = d * mag;
vectors_[vec_ref] = v;
return v;
}
return Vector3D(1, 0, 0);
}
curves::NurbsCurve build_circle_curve(int id) {
const auto& ent = entities_.at(id);
// CIRCLE args: name, placement (AXIS2_PLACEMENT_3D ref), radius
@@ -933,33 +952,23 @@ private:
// P0=(0,0,R) w=1, P1=(R,0,R)*w(?) -- wait let me use the right construction
// Sphere as surface of revolution of half-circle profile about Z:
// Profile points (half circle in XZ plane, going from +Z to -Z):
Point3D top = C + R * Z; // (0,0,R) pole
Point3D mid = C + R * (X + Z); // (R,0,R), weight=w
Point3D bot = C - R * Z; // (0,0,-R) pole
// Control grid: 3 rows in v × 9 columns in u
// Row 0 (top half-circle): revolve the half across u
// Row 1 (mid circle): revolve at equator
// Row 2 (bot half-circle): revolve the half across u
// We construct 3 rows of control points with the equator as the middle row
// and degenerate poles at top/bottom.
std::vector<std::vector<Point3D>> grid(3);
double a0 = 0, a1 = M_PI_2, a2 = M_PI, a3 = 3*M_PI_2;
for (int u = 0; u < 9; ++u) {
double theta = u * M_PI_4; // 0, π/4, π/2, ..., 2π
double theta = u * (M_PI / 4.0); // 0, π/4, π/2, ..., 2π
double cx = std::cos(theta), sy = std::sin(theta);
Vector3D rad_dir = cx * X + sy * Y;
// Top row (v=0): pole + offset towards equator
grid[0].push_back(C + R * Z); // degenerate at pole
// Top row (v=0): degenerate at north pole
grid[0].push_back(C + R * Z);
// Middle row (v=1): equator ring
grid[1].push_back(C + R * rad_dir);
// Bottom row (v=2): degenerate at south pole
grid[2].push_back(C - R * Z);
}
// Weights: row 0 (top): all 1 except corner poles need special handling
// For proper sphere, use weights [1, w, 1] in v and [1, w, 1, w, 1, w, 1, w, 1] in u
std::vector<double> u_wg = {1, w, 1, w, 1, w, 1, w, 1};
// Weights: for proper sphere, each row uses circle arc weights in u
std::vector<std::vector<double>> wg = {
{1, w, 1, w, 1, w, 1, w, 1},
{1, w, 1, w, 1, w, 1, w, 1},
@@ -987,24 +996,19 @@ private:
// Sweep minor circle around major circle
for (int u = 0; u < 9; ++u) {
double theta = u * M_PI_4; // 0 to 2π
grid[u].resize(9);
wg[u].resize(9);
double theta = u * (M_PI / 4.0); // 0 to 2π
double ct = std::cos(theta), st = std::sin(theta);
Point3D mc = C + R * (ct * X + st * Y); // major circle center
for (int v = 0; v < 9; ++v) {
double phi = v * M_PI_4;
double phi = v * (M_PI / 4.0);
double cp = std::cos(phi), sp = std::sin(phi);
// Minor circle in plane spanned by radial dir and Z
Vector3D rad = ct * X + st * Y;
Point3D pt = mc + r * (cp * rad + sp * Z);
grid[u].push_back(pt);
wg[u].push_back(w * w); // simplified weight
}
}
grid[u][v] = mc + r * (cp * rad + sp * Z);
// Fix corner weights
for (int u = 0; u < 9; ++u) {
for (int v = 0; v < 9; ++v) {
// Weight = product of circle arc weights for u and v directions
double wu = (u % 2 == 0) ? 1.0 : w;
double wv = (v % 2 == 0) ? 1.0 : w;
wg[u][v] = wu * wv;
@@ -1024,18 +1028,44 @@ private:
const auto& solid_ent = entities_.at(solid_id);
// MANIFOLD_SOLID_BREP args: name, outer (CLOSED_SHELL ref)
// SHELL_BASED_SURFACE_MODEL args: name, sbsm_boundary (SET of SHELL refs)
if (solid_ent.args.size() < 2) return model;
std::string solid_name;
if (!is_omitted(solid_ent.args[0]))
solid_name = to_string(solid_ent.args[0]);
// find CLOSED_SHELL
int shell_ref = to_ref(solid_ent.args[1]);
std::vector<int> face_ids = convert_shell(shell_ref, model);
// Look for shell refs — might be a single ref or a list of refs
std::vector<int> shell_refs;
if (solid_ent.args[1].type == StepValue::Type::Ref) {
shell_refs.push_back(to_ref(solid_ent.args[1]));
} else if (solid_ent.args[1].type == StepValue::Type::List) {
for (const auto& sv : solid_ent.args[1].list) {
int r = to_ref(sv);
if (r > 0) shell_refs.push_back(r);
}
}
if (!face_ids.empty()) {
int shell_id = model.add_shell(face_ids, true);
// Also scan all args for Ref-type shells as fallback
if (shell_refs.empty()) {
for (const auto& arg : solid_ent.args) {
int r = to_ref(arg);
if (r > 0 && entities_.count(r)) {
const auto& e = entities_.at(r);
if (e.type == "CLOSED_SHELL" || e.type == "OPEN_SHELL")
shell_refs.push_back(r);
}
}
}
std::vector<int> all_face_ids;
for (int sh_ref : shell_refs) {
auto face_ids = convert_shell(sh_ref, model);
all_face_ids.insert(all_face_ids.end(), face_ids.begin(), face_ids.end());
}
if (!all_face_ids.empty()) {
int shell_id = model.add_shell(all_face_ids, true);
model.add_body({shell_id}, solid_name);
}