fcf25e561d
v4.1 收尾: - IncrementalUpdateEngine: dirty flag propagation, cache invalidation - LargeAssembly: InstanceCache, assembly instancing - STEP import: robust/graceful parsing with skip tracking v4.3 分析工具: - Mass properties (volume, centroid, inertia tensor) - Clearance analysis, wall thickness analysis - Enhanced drawing: hidden-line removal, offset sections, BOM - DXF import (LINE/CIRCLE/ARC/LWPOLYLINE/SPLINE → B-Rep extrusion) v4.4 地基加固: - ToleranceChain: RSS cumulative tolerance propagation (7 tests) - Euler operations: MEV/KEV/MEF/KEF/KEMR/MEKR (20 tests) - Replace hardcoded tolerances with ToleranceConfig in validate - Fix incremental_update test API mismatch (15/15 pass on Linux) Docs: - v4.1-v4.4 development plans + roadmap updated - v4.4 marked complete on Linux 30 files, +3424/-210
159 lines
4.1 KiB
C++
159 lines
4.1 KiB
C++
#include <gtest/gtest.h>
|
|
#include "vde/brep/tolerance.h"
|
|
#include "vde/brep/modeling.h"
|
|
|
|
using namespace vde::brep;
|
|
using namespace vde::core;
|
|
|
|
TEST(ToleranceTest, FuzzyEqual_Exact) {
|
|
EXPECT_TRUE(fuzzy_equal(1.0, 1.0));
|
|
}
|
|
|
|
TEST(ToleranceTest, FuzzyEqual_WithinTol) {
|
|
EXPECT_TRUE(fuzzy_equal(1.0, 1.0 + 1e-10));
|
|
}
|
|
|
|
TEST(ToleranceTest, FuzzyEqual_OutsideTol) {
|
|
EXPECT_FALSE(fuzzy_equal(1.0, 1.0 + 1e-3, 1e-6));
|
|
}
|
|
|
|
TEST(ToleranceTest, FuzzyZero) {
|
|
EXPECT_TRUE(fuzzy_zero(0.0));
|
|
EXPECT_TRUE(fuzzy_zero(1e-10));
|
|
EXPECT_FALSE(fuzzy_zero(1e-3, 1e-6));
|
|
}
|
|
|
|
TEST(ToleranceTest, FuzzyVec) {
|
|
Vector3D a(1, 2, 3);
|
|
Vector3D b(1 + 1e-10, 2, 3 - 1e-10);
|
|
EXPECT_TRUE(fuzzy_equal_vec(a, b, 1e-8));
|
|
}
|
|
|
|
TEST(ToleranceTest, FuzzyPoint) {
|
|
Point3D a(0, 0, 0);
|
|
Point3D b(1e-10, 0, 0);
|
|
EXPECT_TRUE(fuzzy_equal_point(a, b, 1e-8));
|
|
}
|
|
|
|
TEST(ToleranceTest, FuzzyParallel) {
|
|
Vector3D a(1, 0, 0);
|
|
Vector3D b(1, 1e-11, 0);
|
|
EXPECT_TRUE(fuzzy_parallel(a, b));
|
|
}
|
|
|
|
TEST(ToleranceTest, FuzzyPerpendicular) {
|
|
Vector3D a(1, 0, 0);
|
|
Vector3D b(0, 1, 0);
|
|
EXPECT_TRUE(fuzzy_perpendicular(a, b));
|
|
}
|
|
|
|
TEST(ToleranceTest, AdaptiveTolerance) {
|
|
double t1 = adaptive_tolerance(1.0); // 1mm model
|
|
double t2 = adaptive_tolerance(1000.0); // 1m model
|
|
EXPECT_GE(t2, t1); // larger model → larger tolerance
|
|
}
|
|
|
|
TEST(ToleranceTest, ModelTolerance_Box) {
|
|
auto box = make_box(100, 100, 100);
|
|
double t = model_tolerance(box);
|
|
EXPECT_GT(t, 0.0);
|
|
}
|
|
|
|
TEST(ToleranceTest, GlobalConfig) {
|
|
auto& cfg = ToleranceConfig::global();
|
|
EXPECT_GT(cfg.vertex_merge, 0.0);
|
|
|
|
ToleranceConfig custom;
|
|
custom.vertex_merge = 1e-4;
|
|
ToleranceConfig::set_global(custom);
|
|
EXPECT_EQ(ToleranceConfig::global().vertex_merge, 1e-4);
|
|
|
|
// Reset
|
|
ToleranceConfig::set_global(ToleranceConfig{});
|
|
}
|
|
|
|
TEST(ToleranceTest, FuzzyGTE) {
|
|
EXPECT_TRUE(fuzzy_gte(1.0, 1.0 - 1e-10));
|
|
EXPECT_TRUE(fuzzy_gte(1.0, 1.0));
|
|
EXPECT_FALSE(fuzzy_gte(1.0, 1.1, 1e-6));
|
|
}
|
|
|
|
TEST(ToleranceTest, FuzzyLTE) {
|
|
EXPECT_TRUE(fuzzy_lte(1.0, 1.0 + 1e-10));
|
|
EXPECT_TRUE(fuzzy_lte(1.0, 1.0));
|
|
EXPECT_FALSE(fuzzy_lte(1.0, 0.9, 1e-6));
|
|
}
|
|
|
|
TEST(ToleranceTest, ToleranceConfig_AllDefaultPositive) {
|
|
ToleranceConfig cfg;
|
|
EXPECT_GT(cfg.vertex_merge, 0);
|
|
EXPECT_GT(cfg.edge_merge, 0);
|
|
EXPECT_GT(cfg.boolean, 0);
|
|
EXPECT_GT(cfg.angular, 0);
|
|
}
|
|
|
|
// ── ToleranceChain tests ──
|
|
|
|
TEST(ToleranceChainTest, EmptyChain) {
|
|
ToleranceChain chain;
|
|
EXPECT_EQ(chain.depth(), 0u);
|
|
EXPECT_EQ(chain.cumulative(), 0.0);
|
|
EXPECT_EQ(chain.max_step(), 0.0);
|
|
}
|
|
|
|
TEST(ToleranceChainTest, SingleStep) {
|
|
ToleranceChain chain;
|
|
chain.push("intersect", 1e-6);
|
|
EXPECT_EQ(chain.depth(), 1u);
|
|
EXPECT_DOUBLE_EQ(chain.cumulative(), 1e-6);
|
|
EXPECT_DOUBLE_EQ(chain.max_step(), 1e-6);
|
|
}
|
|
|
|
TEST(ToleranceChainTest, MultiStepRSS) {
|
|
ToleranceChain chain;
|
|
chain.push("a", 3e-6);
|
|
chain.push("b", 4e-6);
|
|
// RSS: sqrt(3² + 4²) * 1e-6 = 5e-6
|
|
EXPECT_DOUBLE_EQ(chain.cumulative(), 5e-6);
|
|
}
|
|
|
|
TEST(ToleranceChainTest, MaxStep) {
|
|
ToleranceChain chain;
|
|
chain.push("small", 1e-8);
|
|
chain.push("large", 1e-4);
|
|
chain.push("med", 1e-6);
|
|
EXPECT_DOUBLE_EQ(chain.max_step(), 1e-4);
|
|
}
|
|
|
|
TEST(ToleranceChainTest, ClearResets) {
|
|
ToleranceChain chain;
|
|
chain.push("x", 1e-6);
|
|
chain.clear();
|
|
EXPECT_EQ(chain.depth(), 0u);
|
|
EXPECT_EQ(chain.cumulative(), 0.0);
|
|
}
|
|
|
|
TEST(ToleranceChainTest, StepsAccess) {
|
|
ToleranceChain chain;
|
|
chain.push("op1", 1e-9);
|
|
chain.push("op2", 2e-9);
|
|
auto& steps = chain.steps();
|
|
ASSERT_EQ(steps.size(), 2u);
|
|
EXPECT_EQ(steps[0].first, "op1");
|
|
EXPECT_DOUBLE_EQ(steps[0].second, 1e-9);
|
|
EXPECT_EQ(steps[1].first, "op2");
|
|
EXPECT_DOUBLE_EQ(steps[1].second, 2e-9);
|
|
}
|
|
|
|
TEST(ToleranceChainTest, BooleanChainSimulation) {
|
|
ToleranceChain chain;
|
|
chain.push("intersect", 1e-6);
|
|
chain.push("split", 1e-6);
|
|
chain.push("classify", 1e-7);
|
|
chain.push("sew", 1e-5);
|
|
// Cumulative should be dominated by the sewer step
|
|
double cum = chain.cumulative();
|
|
EXPECT_GT(cum, 1e-5);
|
|
EXPECT_LT(cum, 1.5e-5);
|
|
}
|