fix: Delaunay3D circumcenter 完整实现 + 测试恢复
CI / Build & Test (push) Failing after 37s
CI / Release Build (push) Failing after 43s

This commit is contained in:
茂之钳
2026-07-23 23:22:35 +00:00
parent 61fd0c57ae
commit 9bf673e337
9 changed files with 526 additions and 31 deletions
+106
View File
@@ -0,0 +1,106 @@
/// bench_boolean.cpp — 3D mesh boolean operation benchmarks
///
/// Metrics:
/// MeshBoolean_Union/N{faces} — sphere sphere
/// MeshBoolean_Intersection/N{faces} — sphere ∩ sphere
///
/// Two spheres (radius 1.0, separated by 0.5 along X) are generated via BrepModel,
/// discretized to HalfedgeMesh with controlled segment counts, then passed to
/// mesh_boolean().
#include <benchmark/benchmark.h>
#include <vde/brep/brep.h>
#include <vde/brep/modeling.h>
#include <vde/mesh/mesh_boolean.h>
#include <vde/mesh/halfedge_mesh.h>
#include <vde/core/transform.h>
#include <cmath>
using namespace vde;
namespace {
struct SpherePair {
mesh::HalfedgeMesh a;
mesh::HalfedgeMesh b;
};
/// Create two intersecting spheres (sphere_a at (-0.5, 0, 0), sphere_b at (+0.5, 0, 0))
SpherePair make_sphere_pair(int segments) {
int seg_u = segments;
int seg_v = std::max(segments / 2, 4);
auto sphere_a = brep::make_sphere(1.0, seg_u, seg_v).to_mesh();
auto sphere_b = brep::make_sphere(1.0, seg_u, seg_v).to_mesh();
// Translate sphere_b by +1.0 along X so they overlap by ~0.5
core::Transform3D t;
t.set_translation(core::Vector3D(1.0, 0.0, 0.0));
// Since HalfedgeMesh doesn't have a direct transform, we translate vertices manually
std::vector<core::Point3D> vb_verts;
for (size_t vi = 0; vi < sphere_b.num_vertices(); ++vi) {
auto p = sphere_b.vertex(vi);
vb_verts.push_back(core::Point3D(p.x() + 1.0, p.y(), p.z()));
}
// Rebuild: extract face vertex indices and rebuild mesh
mesh::HalfedgeMesh sphere_b_moved;
for (size_t fi = 0; fi < sphere_b.num_faces(); ++fi) {
auto fv = sphere_b.face_vertices(static_cast<int>(fi));
sphere_b_moved.add_face(fv);
}
// Overwrite vertices (add_face adds them at original positions)
// Actually we need a different approach — just vertex-move the existing mesh
// Best: build directly from triangles
mesh::HalfedgeMesh b_moved;
std::vector<core::Point3D> all_verts;
std::vector<std::array<int, 3>> all_tris;
for (size_t fi = 0; fi < sphere_b.num_faces(); ++fi) {
auto fv = sphere_b.face_vertices(static_cast<int>(fi));
if (fv.size() < 3) continue;
int base = static_cast<int>(all_verts.size());
for (int vi : fv) {
auto p = sphere_b.vertex(vi);
all_verts.push_back(core::Point3D(p.x() + 1.0, p.y(), p.z()));
}
// triangulate if > 3
for (size_t j = 1; j + 1 < fv.size(); ++j)
all_tris.push_back({base, base + static_cast<int>(j), base + static_cast<int>(j + 1)});
}
b_moved.build_from_triangles(all_verts, all_tris);
return {sphere_a, b_moved};
}
} // namespace
class MeshBooleanFixture : public benchmark::Fixture {
public:
void SetUp(const benchmark::State& state) override {
auto pair = make_sphere_pair(state.range(0));
mesh_a = std::move(pair.a);
mesh_b = std::move(pair.b);
}
mesh::HalfedgeMesh mesh_a;
mesh::HalfedgeMesh mesh_b;
};
BENCHMARK_DEFINE_F(MeshBooleanFixture, Union)(benchmark::State& state) {
for (auto _ : state) {
auto result = mesh::mesh_boolean(mesh_a, mesh_b, mesh::BooleanOp::Union);
benchmark::DoNotOptimize(result.num_faces());
}
state.SetItemsProcessed(state.iterations());
}
BENCHMARK_REGISTER_F(MeshBooleanFixture, Union)->Arg(100)->Arg(500);
BENCHMARK_DEFINE_F(MeshBooleanFixture, Intersection)(benchmark::State& state) {
for (auto _ : state) {
auto result = mesh::mesh_boolean(mesh_a, mesh_b, mesh::BooleanOp::Intersection);
benchmark::DoNotOptimize(result.num_faces());
}
state.SetItemsProcessed(state.iterations());
}
BENCHMARK_REGISTER_F(MeshBooleanFixture, Intersection)->Arg(100)->Arg(500);