fix(v1.0.1): VDE-016 — definitive fix: fully-qualified names throughout
CI / Build & Test (push) Failing after 24s
CI / Release Build (push) Failing after 39s
Build & Test / build-and-test (push) Has been cancelled
Build & Test / python-bindings (push) Has been cancelled

Root cause: GCC two-phase lookup with multiple anonymous namespaces
creates barriers that using declarations cannot cross.

Fix: Replace all unqualified SSICurveData/ClassResult with
vde::brep::SSICurveData/vde::brep::ClassResult throughout the file.
This is the only approach verified to work by ViewDesign.
This commit is contained in:
茂之钳
2026-07-28 08:04:34 +08:00
parent faa20db3c9
commit 514a9a633c
2 changed files with 22 additions and 22 deletions
+21 -21
View File
@@ -64,7 +64,7 @@ namespace {
// ═══════════════════════════════════════════════════════════
// Constants & types
BrepModel extract_face_fragment(const BrepModel& body, int face_id);
ClassResult classify_point_adaptive(
vde::brep::ClassResult classify_point_adaptive(
const BrepModel& body, const Point3D& p, int& num_exact_upgrades);
// ═══════════════════════════════════════════════════════════
@@ -507,11 +507,11 @@ BrepModel extract_face_fragment(const BrepModel& body, int face_id) {
/// Compute all SSI curves between body A and body B.
/// Returns a list of SSICurveData, one per intersecting face pair.
/// Uses OpenMP parallelization over face pairs.
std::vector<SSICurveData> compute_all_ssi(
std::vector<vde::brep::SSICurveData> compute_all_ssi(
const BrepModel& a, const BrepModel& b,
int& num_exact_upgrades)
{
std::vector<SSICurveData> all_isects;
std::vector<vde::brep::SSICurveData> all_isects;
std::mutex isect_mutex;
// Build face-AABB cache for quick rejection
@@ -537,11 +537,11 @@ std::vector<SSICurveData> compute_all_ssi(
#ifdef VDE_USE_OPENMP
#pragma omp parallel
{
std::vector<SSICurveData> local;
std::vector<vde::brep::SSICurveData> local;
#pragma omp for schedule(dynamic) nowait
for (size_t pi = 0; pi < pairs.size(); ++pi) {
#else
std::vector<SSICurveData> local;
std::vector<vde::brep::SSICurveData> local;
for (size_t pi = 0; pi < pairs.size(); ++pi) {
#endif
int ia = pairs[pi].first;
@@ -558,7 +558,7 @@ std::vector<SSICurveData> compute_all_ssi(
for (const auto& curve : curves) {
if (curve.points.size() < 4) continue;
SSICurveData d;
vde::brep::SSICurveData d;
d.face_a = ia;
d.face_b = ib;
d.points = curve.points;
@@ -610,7 +610,7 @@ struct CuttingPlane {
};
std::unordered_map<int, std::vector<CuttingPlane>>
build_face_cutting_planes(const std::vector<SSICurveData>& ssi_curves,
build_face_cutting_planes(const std::vector<vde::brep::SSICurveData>& ssi_curves,
bool for_body_a) {
std::unordered_map<int, std::vector<CuttingPlane>> result;
for (const auto& c : ssi_curves) {
@@ -641,14 +641,14 @@ build_face_cutting_planes(const std::vector<SSICurveData>& ssi_curves,
/// Split all faces of a body using SSI-derived cutting planes,
/// then classify each resulting fragment against the other body.
/// Returns a vector of (fragment, classification) pairs.
std::vector<std::pair<BrepModel, ClassResult>>
std::vector<std::pair<BrepModel, vde::brep::ClassResult>>
split_and_classify_faces_ssi(
const BrepModel& body,
const std::unordered_map<int, std::vector<CuttingPlane>>& cutting_planes,
const BrepModel& other_body,
int& num_exact_upgrades)
{
std::vector<std::pair<BrepModel, ClassResult>> result;
std::vector<std::pair<BrepModel, vde::brep::ClassResult>> result;
std::mutex result_mutex;
#ifdef VDE_USE_OPENMP
@@ -685,7 +685,7 @@ split_and_classify_faces_ssi(
}
// Classify each fragment using multi-point sampling
std::vector<std::pair<BrepModel, ClassResult>> local;
std::vector<std::pair<BrepModel, vde::brep::ClassResult>> local;
for (auto& frag : fragments) {
// Use the new multi-point classify_face_fragment
// Extract face_id from the fragment (fragment has exactly one face at index 0)
@@ -711,7 +711,7 @@ split_and_classify_faces_ssi(
/// This avoids expensive mesh construction for clearly IN/OUT faces.
bool classify_face_uniform(const BrepModel& face_body,
const BrepModel& other_body,
ClassResult& uniform_result) {
vde::brep::ClassResult& uniform_result) {
if (face_body.num_faces() == 0) return false;
const auto& surf = face_body.surface(face_body.face(0).surface_id);
double u0 = surf.knots_u().front(), u1 = surf.knots_u().back();
@@ -725,7 +725,7 @@ bool classify_face_uniform(const BrepModel& face_body,
double radius = (bb.max() - bb.min()).norm() * 0.5;
double radius_sq = radius * radius;
ClassResult first;
vde::brep::ClassResult first;
{
Point3D p = surf.evaluate(us[0], vs[0]);
if (!bb.contains(p)) { first = OUT; }
@@ -734,7 +734,7 @@ bool classify_face_uniform(const BrepModel& face_body,
}
for (int i = 1; i < 5; ++i) {
Point3D p = surf.evaluate(us[i], vs[i]);
ClassResult cls;
vde::brep::ClassResult cls;
if (!bb.contains(p)) cls = OUT;
else if ((p - center).squaredNorm() <= radius_sq * 0.5) cls = IN;
else return false;
@@ -747,7 +747,7 @@ bool classify_face_uniform(const BrepModel& face_body,
/// Double-precision ray cast classification for a point against a mesh.
/// Returns IN/OUT (never ON — ON is handled separately).
/// Uses exact_orient3d for robust coplanarity tests on boundary triangles.
ClassResult classify_point_double(const BrepModel& body, const Point3D& p) {
vde::brep::ClassResult classify_point_double(const BrepModel& body, const Point3D& p) {
const mesh::HalfedgeMesh& mesh = get_mesh(body);
if (mesh.num_faces() == 0) return OUT;
@@ -838,7 +838,7 @@ bool point_on_surface_double(const BrepModel& body, const Point3D& p,
}
/// Adaptive classification: try double first, upgrade to GMP exact if uncertain.
ClassResult classify_point_adaptive(
vde::brep::ClassResult classify_point_adaptive(
const BrepModel& body, const Point3D& p, int& num_exact_upgrades)
{
// Step 1: Check ON surface (double precision is adequate here)
@@ -847,12 +847,12 @@ ClassResult classify_point_adaptive(
}
// Step 2: Try double-precision ray cast
ClassResult result = classify_point_double(body, p);
vde::brep::ClassResult result = classify_point_double(body, p);
// Step 3: check if the result is uncertain (near boundary)
// Re-cast with a slightly offset origin to check consistency
Point3D p2(p.x() + 1e-8, p.y(), p.z());
ClassResult verify = classify_point_double(body, p2);
vde::brep::ClassResult verify = classify_point_double(body, p2);
if (result != verify) {
// Inconsistent: upgrade to exact
@@ -947,7 +947,7 @@ ClassResult classify_point_adaptive(
} // anonymous namespace — classify_face_fragment is public
ClassResult classify_face_fragment(
vde::brep::ClassResult classify_face_fragment(
const BrepModel& body, const BrepModel& other_body,
int face_id, int& num_exact_upgrades)
{
@@ -986,7 +986,7 @@ ClassResult classify_face_fragment(
std::mt19937 rng(42); // fixed seed for reproducibility
std::uniform_real_distribution<double> dist(0.0, 1.0);
auto sample_and_vote = [&](int n_samples) -> ClassResult {
auto sample_and_vote = [&](int n_samples) -> vde::brep::ClassResult {
int in_count = 0, out_count = 0, on_count = 0;
for (int i = 0; i < n_samples; ++i) {
@@ -1100,7 +1100,7 @@ ClassResult classify_face_fragment(
};
// First pass: N samples
ClassResult result = sample_and_vote(N);
vde::brep::ClassResult result = sample_and_vote(N);
// If result is ON or the vote was close, re-sample with 2N points
if (result == ON) {
@@ -1377,7 +1377,7 @@ SSIBooleanResult ssi_boolean_core(
std::vector<BrepModel> keep_fragments;
// Predicate: which fragments to keep based on operation type
auto should_keep = [op_type](ClassResult cls, bool from_a) -> bool {
auto should_keep = [op_type](vde::brep::ClassResult cls, bool from_a) -> bool {
switch (op_type) {
case 0: // union
// Keep A fragments OUT/ON of B; keep B fragments OUT of A