fix(v4.2): boolean/validate/heal/step_export use vertex array index, not v.id
Root cause: add_vertex returns array index but copy_brep/merge_brep/extract_face_fragment keyed by v.id (next_id_ value). When vertices and edges are interleaved, v.id != array index → map lookup fails → OOB access. Fixes in brep_boolean.cpp: - copy_brep: key by vertex index (vi) instead of v.id - merge_brep: key by vi, value = best_idx (array index) not result.vertex(id).id - extract_face_fragment: use body.vertex(e.v_start) directly (e.v_start is array index) - face_bounds/face_centroid/faces_intersect: same direct access pattern Also fixed same pattern in brep_heal.cpp, brep_validate.cpp, step_export.cpp
This commit is contained in:
+15
-31
@@ -238,12 +238,8 @@ Point3D face_centroid(const BrepModel& body, int face_id) {
|
||||
int count = 0;
|
||||
for (int ei : edges) {
|
||||
const auto& e = body.edge(ei);
|
||||
for (size_t vi = 0; vi < body.num_vertices(); ++vi) {
|
||||
auto& v = body.vertex(static_cast<int>(vi));
|
||||
if (v.id == e.v_start || v.id == e.v_end) {
|
||||
c += v.point; count++;
|
||||
}
|
||||
}
|
||||
c += body.vertex(e.v_start).point; count++;
|
||||
c += body.vertex(e.v_end).point; count++;
|
||||
}
|
||||
if (count > 0) c /= static_cast<double>(count);
|
||||
return c;
|
||||
@@ -257,18 +253,14 @@ bool faces_intersect(const BrepModel& body_a, int face_a,
|
||||
auto ea = body_a.face_edges(face_a);
|
||||
for (int ei : ea) {
|
||||
auto& e = body_a.edge(ei);
|
||||
for (size_t vi = 0; vi < body_a.num_vertices(); ++vi) {
|
||||
auto& v = body_a.vertex(static_cast<int>(vi));
|
||||
if (v.id == e.v_start || v.id == e.v_end) bb_a.expand(v.point);
|
||||
}
|
||||
bb_a.expand(body_a.vertex(e.v_start).point);
|
||||
bb_a.expand(body_a.vertex(e.v_end).point);
|
||||
}
|
||||
auto eb = body_b.face_edges(face_b);
|
||||
for (int ei : eb) {
|
||||
auto& e = body_b.edge(ei);
|
||||
for (size_t vi = 0; vi < body_b.num_vertices(); ++vi) {
|
||||
auto& v = body_b.vertex(static_cast<int>(vi));
|
||||
if (v.id == e.v_start || v.id == e.v_end) bb_b.expand(v.point);
|
||||
}
|
||||
bb_b.expand(body_b.vertex(e.v_start).point);
|
||||
bb_b.expand(body_b.vertex(e.v_end).point);
|
||||
}
|
||||
return bb_a.intersects(bb_b);
|
||||
}
|
||||
@@ -306,9 +298,9 @@ BrepModel sew_faces(const std::vector<BrepModel>& face_bodies) {
|
||||
if (d < best_dist) { best_dist = d; best_idx = static_cast<int>(ri); }
|
||||
}
|
||||
if (best_idx >= 0) {
|
||||
old_to_new[v.id] = result.vertex(static_cast<int>(best_idx)).id;
|
||||
old_to_new[static_cast<int>(vi)] = best_idx;
|
||||
} else {
|
||||
old_to_new[v.id] = result.add_vertex(v.point);
|
||||
old_to_new[static_cast<int>(vi)] = result.add_vertex(v.point);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,21 +345,15 @@ BrepModel extract_face_fragment(const BrepModel& body, int face_id) {
|
||||
auto& f = body.face(face_id);
|
||||
auto es = body.face_edges(face_id);
|
||||
|
||||
// Map original vertex IDs to new vertex IDs in fragment
|
||||
// Map original vertex indices to new vertex indices in fragment
|
||||
std::map<int, int> old_to_new;
|
||||
for (int ei : es) {
|
||||
auto& e = body.edge(ei);
|
||||
if (old_to_new.find(e.v_start) == old_to_new.end()) {
|
||||
for (size_t vi = 0; vi < body.num_vertices(); ++vi) {
|
||||
auto& tv = body.vertex(static_cast<int>(vi));
|
||||
if (tv.id == e.v_start) { old_to_new[e.v_start] = frag.add_vertex(tv.point); break; }
|
||||
}
|
||||
old_to_new[e.v_start] = frag.add_vertex(body.vertex(e.v_start).point);
|
||||
}
|
||||
if (old_to_new.find(e.v_end) == old_to_new.end()) {
|
||||
for (size_t vi = 0; vi < body.num_vertices(); ++vi) {
|
||||
auto& tv = body.vertex(static_cast<int>(vi));
|
||||
if (tv.id == e.v_end) { old_to_new[e.v_end] = frag.add_vertex(tv.point); break; }
|
||||
}
|
||||
old_to_new[e.v_end] = frag.add_vertex(body.vertex(e.v_end).point);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,11 +413,11 @@ split_and_classify_faces(const BrepModel& a, const BrepModel& b) {
|
||||
/// Create a deep copy of a BrepModel, preserving all topology exactly.
|
||||
BrepModel copy_brep(const BrepModel& src) {
|
||||
BrepModel result;
|
||||
// Copy vertices
|
||||
// Copy vertices (key by array index, since e.v_start/e.v_end store indices)
|
||||
std::map<int, int> old_vid_to_new_idx;
|
||||
for (size_t vi = 0; vi < src.num_vertices(); ++vi) {
|
||||
auto& v = src.vertex(static_cast<int>(vi));
|
||||
old_vid_to_new_idx[v.id] = result.add_vertex(v.point);
|
||||
old_vid_to_new_idx[static_cast<int>(vi)] = result.add_vertex(v.point);
|
||||
}
|
||||
// Copy surfaces
|
||||
std::map<int, int> old_sid_to_new_idx;
|
||||
@@ -468,10 +454,8 @@ core::AABB3D face_bounds(const BrepModel& body, int face_id) {
|
||||
auto es = body.face_edges(face_id);
|
||||
for (int ei : es) {
|
||||
const auto& e = body.edge(ei);
|
||||
for (size_t vi = 0; vi < body.num_vertices(); ++vi) {
|
||||
const auto& v = body.vertex(static_cast<int>(vi));
|
||||
if (v.id == e.v_start || v.id == e.v_end) bb.expand(v.point);
|
||||
}
|
||||
bb.expand(body.vertex(e.v_start).point);
|
||||
bb.expand(body.vertex(e.v_end).point);
|
||||
}
|
||||
return bb;
|
||||
}
|
||||
|
||||
@@ -250,11 +250,8 @@ Point3D face_centroid(const BrepModel& body, const TopoFace& face) {
|
||||
for (int ei : loop.edges) {
|
||||
if (ei < 0 || ei >= static_cast<int>(body.num_edges())) continue;
|
||||
const auto& e = body.edge(ei);
|
||||
for (size_t vi = 0; vi < body.num_vertices(); ++vi) {
|
||||
const auto& v = body.vertex(static_cast<int>(vi));
|
||||
if (v.id == e.v_start) { sum = sum + v.point; count++; }
|
||||
if (v.id == e.v_end) { sum = sum + v.point; count++; }
|
||||
}
|
||||
sum = sum + body.vertex(e.v_start).point; count++;
|
||||
sum = sum + body.vertex(e.v_end).point; count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,17 +14,9 @@ using core::AABB3D;
|
||||
namespace {
|
||||
|
||||
/// Compute edge length by looking up vertices
|
||||
double edge_length(const BrepModel& body, int edge_idx) {
|
||||
static double edge_length(const BrepModel& body, int edge_idx) {
|
||||
auto& e = body.edge(edge_idx);
|
||||
Point3D p0(0,0,0), p1(0,0,0);
|
||||
bool found0 = false, found1 = false;
|
||||
for (size_t vi = 0; vi < body.num_vertices(); ++vi) {
|
||||
auto& v = body.vertex(static_cast<int>(vi));
|
||||
if (v.id == e.v_start) { p0 = v.point; found0 = true; }
|
||||
if (v.id == e.v_end) { p1 = v.point; found1 = true; }
|
||||
}
|
||||
if (!found0 || !found1) return 0.0;
|
||||
return (p1 - p0).norm();
|
||||
return (body.vertex(e.v_end).point - body.vertex(e.v_start).point).norm();
|
||||
}
|
||||
|
||||
/// Check if two faces share an edge
|
||||
@@ -60,10 +52,8 @@ bool faces_self_intersect(const BrepModel& body, int fa, int fb) {
|
||||
auto ea = body.face_edges(fa);
|
||||
for (int ei : ea) {
|
||||
auto& e = body.edge(ei);
|
||||
for (size_t vi = 0; vi < body.num_vertices(); ++vi) {
|
||||
auto& v = body.vertex(static_cast<int>(vi));
|
||||
if (v.id == e.v_start || v.id == e.v_end) bb_a.expand(v.point);
|
||||
}
|
||||
bb_a.expand(body.vertex(e.v_start).point);
|
||||
bb_a.expand(body.vertex(e.v_end).point);
|
||||
}
|
||||
// Expand slightly to account for numerical error
|
||||
auto ext_a = bb_a.extent();
|
||||
@@ -73,10 +63,8 @@ bool faces_self_intersect(const BrepModel& body, int fa, int fb) {
|
||||
auto eb = body.face_edges(fb);
|
||||
for (int ei : eb) {
|
||||
auto& e = body.edge(ei);
|
||||
for (size_t vi = 0; vi < body.num_vertices(); ++vi) {
|
||||
auto& v = body.vertex(static_cast<int>(vi));
|
||||
if (v.id == e.v_start || v.id == e.v_end) bb_b.expand(v.point);
|
||||
}
|
||||
bb_b.expand(body.vertex(e.v_start).point);
|
||||
bb_b.expand(body.vertex(e.v_end).point);
|
||||
}
|
||||
return bb_a.intersects(bb_b);
|
||||
}
|
||||
|
||||
@@ -355,13 +355,8 @@ std::string export_step(const std::vector<BrepModel>& bodies) {
|
||||
|
||||
for (int ei : face_edges) {
|
||||
auto& e = body.edge(ei);
|
||||
core::Point3D p0 = body.vertex(0).point;
|
||||
core::Point3D p1 = body.vertex(0).point;
|
||||
for (size_t vi = 0; vi < body.num_vertices(); ++vi) {
|
||||
auto& v = body.vertex(static_cast<int>(vi));
|
||||
if (v.id == e.v_start) p0 = v.point;
|
||||
if (v.id == e.v_end) p1 = v.point;
|
||||
}
|
||||
core::Point3D p0 = body.vertex(e.v_start).point;
|
||||
core::Point3D p1 = body.vertex(e.v_end).point;
|
||||
|
||||
// Write VERTEX_POINT for start vertex
|
||||
int vp_start = writer.write_cartesian_point(p0);
|
||||
|
||||
Reference in New Issue
Block a user