Files
ViewDesignEngine/bench/bench_boolean.cpp
T
茂之钳 9bf673e337
CI / Build & Test (push) Failing after 37s
CI / Release Build (push) Failing after 43s
fix: Delaunay3D circumcenter 完整实现 + 测试恢复
2026-07-23 23:22:35 +00:00

107 lines
3.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/// 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);