7b76689ea1
v11.1 — Test Infrastructure (14 files): - .github/workflows/ci.yml: Ubuntu 22.04 + GCC 11, auto ctest on push - tests/regression/: degenerate geometry, extreme coords, thin wall, large models - tests/fuzz/: SDF random CSG, random booleans, format round-trip, continuous mode - tests/benchmark/: boolean perf, MC perf, IO perf benchmarks - docs/benchmark-report.md: benchmark template v11.2 — Code Quality + Docs: - .clang-tidy: 15 check categories, 22 exclusions - .github/workflows/static-analysis.yml: clang-tidy CI scan - CODEOWNERS, SECURITY.md - docs: API overview, testing guide, contributing guide - README: module capability overview table Pending: binary formats + curve projection (retrying)
188 lines
5.0 KiB
C++
188 lines
5.0 KiB
C++
/// @file regression_thin_wall.cpp
|
|
/// @brief 薄壁件回归测试(壁厚 0.001mm)
|
|
///
|
|
/// 覆盖场景:
|
|
/// 1. 极薄壁盒子
|
|
/// 2. 薄壁壳的布尔运算
|
|
/// 3. 薄壁圆柱和球体
|
|
/// 4. 抽壳后的薄壁验证
|
|
///
|
|
/// 每个测试:构造薄壁体 → 布尔/修复/验证 → 断言不崩溃
|
|
|
|
#include <gtest/gtest.h>
|
|
#include "vde/brep/brep.h"
|
|
#include "vde/brep/modeling.h"
|
|
#include "vde/brep/brep_boolean.h"
|
|
#include "vde/brep/brep_validate.h"
|
|
#include "vde/brep/brep_heal.h"
|
|
#include "vde/core/point.h"
|
|
#include <cmath>
|
|
|
|
using namespace vde::brep;
|
|
using namespace vde::core;
|
|
|
|
// 行业标准薄壁厚度:0.001mm = 1e-6 米(假设模型单位为米)
|
|
static constexpr double THIN_WALL = 1e-6;
|
|
|
|
// ── 极薄壁盒子测试 ──
|
|
|
|
TEST(RegressionThinWall, Box_ThinWall1um) {
|
|
// 1 μm 壁厚的盒子
|
|
EXPECT_NO_THROW({
|
|
auto body = make_box(THIN_WALL, 1.0, 1.0);
|
|
EXPECT_TRUE(body.is_valid());
|
|
|
|
// 验证
|
|
auto result = validate(body);
|
|
(void)result;
|
|
|
|
// 导出网格不应崩溃
|
|
auto mesh = body.to_mesh();
|
|
(void)mesh;
|
|
});
|
|
}
|
|
|
|
TEST(RegressionThinWall, Box_ThinWallVarious) {
|
|
// 多种薄壁厚度
|
|
for (double t : {1e-3, 1e-4, 1e-5, 1e-6, 1e-7}) {
|
|
EXPECT_NO_THROW({
|
|
auto body = make_box(t, 1.0, 1.0);
|
|
body.is_valid();
|
|
auto mesh = body.to_mesh();
|
|
(void)mesh;
|
|
}) << "failed at thickness=" << t;
|
|
}
|
|
}
|
|
|
|
TEST(RegressionThinWall, Box_AllDimensionsThin) {
|
|
// 三个维度都极薄 → 几乎是一个点
|
|
EXPECT_NO_THROW({
|
|
auto body = make_box(THIN_WALL, THIN_WALL, THIN_WALL);
|
|
body.is_valid();
|
|
auto mesh = body.to_mesh();
|
|
(void)mesh;
|
|
});
|
|
}
|
|
|
|
// ── 薄壁布尔运算 ──
|
|
|
|
TEST(RegressionThinWall, Boolean_ThinWallUnion) {
|
|
auto thin = make_box(THIN_WALL, 1.0, 1.0);
|
|
auto normal = make_box(2.0, 2.0, 2.0);
|
|
|
|
EXPECT_NO_THROW({
|
|
auto u = brep_union(thin, normal);
|
|
EXPECT_TRUE(u.is_valid());
|
|
auto i = brep_intersection(thin, normal);
|
|
EXPECT_TRUE(i.is_valid());
|
|
auto d = brep_difference(normal, thin);
|
|
EXPECT_TRUE(d.is_valid());
|
|
});
|
|
}
|
|
|
|
TEST(RegressionThinWall, Boolean_TwoThinWalls) {
|
|
// 两个薄壁体之间的布尔运算
|
|
auto a = make_box(THIN_WALL, 2.0, 2.0);
|
|
auto b = make_box(2.0, THIN_WALL, 2.0);
|
|
|
|
EXPECT_NO_THROW({
|
|
auto u = brep_union(a, b);
|
|
EXPECT_TRUE(u.is_valid());
|
|
auto i = brep_intersection(a, b);
|
|
EXPECT_TRUE(i.is_valid());
|
|
});
|
|
}
|
|
|
|
// ── 薄壁圆柱 ──
|
|
|
|
TEST(RegressionThinWall, Cylinder_ThinRadius) {
|
|
// 极薄半径的圆柱(近似线)
|
|
for (double r : {1e-3, 1e-4, 1e-5, 1e-6}) {
|
|
EXPECT_NO_THROW({
|
|
auto cyl = make_cylinder(r, 2.0, 16);
|
|
EXPECT_TRUE(cyl.is_valid());
|
|
auto mesh = cyl.to_mesh();
|
|
(void)mesh;
|
|
}) << "failed at radius=" << r;
|
|
}
|
|
}
|
|
|
|
TEST(RegressionThinWall, Cylinder_ThinHeight) {
|
|
// 极薄高度的圆柱(近似圆盘)
|
|
for (double h : {1e-3, 1e-4, 1e-5, 1e-6}) {
|
|
EXPECT_NO_THROW({
|
|
auto cyl = make_cylinder(1.0, h, 16);
|
|
EXPECT_TRUE(cyl.is_valid());
|
|
auto mesh = cyl.to_mesh();
|
|
(void)mesh;
|
|
}) << "failed at height=" << h;
|
|
}
|
|
}
|
|
|
|
// ── 薄壁球体 ──
|
|
|
|
TEST(RegressionThinWall, Sphere_ThinRadius) {
|
|
for (double r : {1e-3, 1e-4, 1e-5, 1e-6}) {
|
|
EXPECT_NO_THROW({
|
|
auto sph = make_sphere(r, 16, 8);
|
|
EXPECT_TRUE(sph.is_valid());
|
|
auto mesh = sph.to_mesh();
|
|
(void)mesh;
|
|
}) << "failed at radius=" << r;
|
|
}
|
|
}
|
|
|
|
// ── 抽壳后的薄壁体 ──
|
|
|
|
TEST(RegressionThinWall, Shell_ThinThickness) {
|
|
// shell() 生成一个挖空的体 → 然后对其做薄壁操作
|
|
auto box = make_box(10.0, 10.0, 10.0);
|
|
|
|
EXPECT_NO_THROW({
|
|
auto shelled = shell(box, 0, THIN_WALL);
|
|
EXPECT_TRUE(shelled.is_valid());
|
|
|
|
auto result = validate(shelled);
|
|
(void)result;
|
|
|
|
// 壳上的布尔运算
|
|
auto cyl = make_cylinder(1.0, 20.0, 32);
|
|
auto u = brep_union(shelled, cyl);
|
|
(void)u.is_valid();
|
|
});
|
|
}
|
|
|
|
// ── 薄壁修复 ──
|
|
|
|
TEST(RegressionThinWall, Heal_ThinWall) {
|
|
auto thin = make_box(THIN_WALL, 1.0, 1.0);
|
|
|
|
EXPECT_NO_THROW({
|
|
// 使用容差修复(容差远大于壁厚的情况)
|
|
heal_gaps(thin, 1e-6);
|
|
heal_slivers(thin);
|
|
|
|
bool ok = heal_topology(thin, 1e-4);
|
|
(void)ok;
|
|
|
|
auto result = validate(thin);
|
|
(void)result;
|
|
});
|
|
}
|
|
|
|
// ── 压力测试:薄壁链式布尔 ──
|
|
|
|
TEST(RegressionThinWall, Stress_ChainedBoolean) {
|
|
auto base = make_box(5.0, 5.0, 5.0);
|
|
|
|
// 连续对薄壁体做布尔运算
|
|
for (int i = 0; i < 5; ++i) {
|
|
double t = THIN_WALL * (i + 1) * 10;
|
|
EXPECT_NO_THROW({
|
|
auto thin = make_box(t, 0.5, 0.5);
|
|
auto u = brep_union(base, thin);
|
|
(void)u.is_valid();
|
|
}) << "failed at iteration " << i;
|
|
}
|
|
}
|