#include #include "vde/brep/auto_dimensioning.h" #include "vde/brep/modeling.h" #include using namespace vde::brep; using namespace vde::core; // ═══════════════════════════════════════════════════════════ // StandardConfig / DrawingStandard // ═══════════════════════════════════════════════════════════ TEST(AutoDimTest, StandardConfig_ISODefaults) { auto cfg = standard_defaults(DrawingStandard::ISO); EXPECT_EQ(cfg.standard, DrawingStandard::ISO); EXPECT_GT(cfg.text_height, 0.0); EXPECT_GT(cfg.arrow_size, 0.0); EXPECT_EQ(cfg.standard_name(), "ISO 129"); } TEST(AutoDimTest, StandardConfig_ANSIDefaults) { auto cfg = standard_defaults(DrawingStandard::ANSI); EXPECT_EQ(cfg.standard, DrawingStandard::ANSI); EXPECT_GT(cfg.text_height, 0.0); EXPECT_EQ(cfg.standard_name(), "ANSI Y14.5"); } TEST(AutoDimTest, StandardConfig_JISDefaults) { auto cfg = standard_defaults(DrawingStandard::JIS); EXPECT_EQ(cfg.standard, DrawingStandard::JIS); EXPECT_GT(cfg.text_height, 0.0); EXPECT_EQ(cfg.standard_name(), "JIS B 0001"); } // ═══════════════════════════════════════════════════════════ // apply_standard // ═══════════════════════════════════════════════════════════ TEST(AutoDimTest, ApplyStandard_ChangesConfig) { DrawingSettings ds; ds.config = standard_defaults(DrawingStandard::JIS); EXPECT_EQ(ds.config.standard, DrawingStandard::JIS); apply_standard(ds, DrawingStandard::ISO); EXPECT_EQ(ds.config.standard, DrawingStandard::ISO); EXPECT_EQ(ds.config.standard_name(), "ISO 129"); } TEST(AutoDimTest, ApplyStandardWithOverrides_PreservesOverrides) { DrawingSettings ds; StandardConfig overrides; overrides.text_height = 5.0; apply_standard_with_overrides(ds, DrawingStandard::ISO, overrides); EXPECT_EQ(ds.config.standard, DrawingStandard::ISO); EXPECT_DOUBLE_EQ(ds.config.text_height, 5.0); } // ═══════════════════════════════════════════════════════════ // auto_dimension — box // ═══════════════════════════════════════════════════════════ TEST(AutoDimTest, AutoDimension_Box_ReturnsDimensions) { auto box = make_box(10, 5, 3); auto dims = auto_dimension(box, Vector3D(0, 0, -1)); EXPECT_GE(dims.size(), 1u) << "Should detect at least one dimension"; } TEST(AutoDimTest, AutoDimension_Box_HasLinearDimensions) { auto box = make_box(10, 5, 3); auto dims = auto_dimension(box, Vector3D(0, 0, -1)); bool has_linear = false; for (const auto& d : dims) { if (d.type == DimensionType::Linear) { has_linear = true; EXPECT_GT(d.value, 0.0); break; } } EXPECT_TRUE(has_linear) << "Box should produce linear dimensions"; } TEST(AutoDimTest, AutoDimension_SmallValueDimensions_Filtered) { auto box = make_box(0.0001, 0.0001, 0.0001); auto dims = auto_dimension(box, Vector3D(0, 0, -1)); // Very small box — dimensions should be filtered (below threshold) // At minimum, it should not crash SUCCEED(); } // ═══════════════════════════════════════════════════════════ // auto_dimension — cylinder // ═══════════════════════════════════════════════════════════ TEST(AutoDimTest, AutoDimension_Cylinder_ReturnsDimensions) { auto cyl = make_cylinder(3.0, 10.0, 16); auto dims = auto_dimension(cyl, Vector3D(0, 0, -1)); EXPECT_GE(dims.size(), 1u) << "Cylinder should produce dimensions"; } TEST(AutoDimTest, AutoDimension_Cylinder_HasRadialDimension) { auto cyl = make_cylinder(3.0, 10.0, 32); auto dims = auto_dimension(cyl, Vector3D(0, 0, -1)); // Polygonal cylinder edges are straight line segments, not NURBS arcs. // Arc detection requires NURBS curve degree == 2 on edges. // The cylinder should still produce linear dimensions. bool has_linear_or_radial = false; for (const auto& d : dims) { if (d.type == DimensionType::Radius || d.type == DimensionType::Diameter || d.type == DimensionType::Linear) { has_linear_or_radial = true; break; } } EXPECT_TRUE(has_linear_or_radial) << "Cylinder should produce dimensions"; } // ═══════════════════════════════════════════════════════════ // auto_dimension — edge cases // ═══════════════════════════════════════════════════════════ TEST(AutoDimTest, AutoDimension_EmptyModel_ReturnsEmpty) { BrepModel empty; auto dims = auto_dimension(empty, Vector3D(0, 0, -1)); EXPECT_TRUE(dims.empty()); } TEST(AutoDimTest, AutoDimension_DifferentViewDirections) { auto box = make_box(10, 5, 3); auto dims_front = auto_dimension(box, Vector3D(0, 0, -1)); auto dims_top = auto_dimension(box, Vector3D(0, -1, 0)); auto dims_right = auto_dimension(box, Vector3D(-1, 0, 0)); // All views should produce some dimensions EXPECT_GE(dims_front.size(), 1u); EXPECT_GE(dims_top.size(), 1u); EXPECT_GE(dims_right.size(), 1u); } // ═══════════════════════════════════════════════════════════ // Dimension text formatting // ═══════════════════════════════════════════════════════════ TEST(AutoDimTest, Dimension_ToText_Basic) { Dimension dim; dim.type = DimensionType::Linear; dim.value = 10.0; dim.prefix = ""; dim.suffix = "mm"; auto text = dim.to_text(); EXPECT_NE(text.find("10.00"), std::string::npos); EXPECT_NE(text.find("mm"), std::string::npos); } TEST(AutoDimTest, Dimension_ToText_WithTolerance) { Dimension dim; dim.type = DimensionType::Linear; dim.value = 25.0; dim.tolerance_upper = 0.1; dim.tolerance_lower = -0.05; auto text = dim.to_text(); EXPECT_NE(text.find("+0.100"), std::string::npos); } TEST(AutoDimTest, Dimension_ToText_Diameter) { Dimension dim; dim.type = DimensionType::Diameter; dim.value = 20.0; dim.prefix = "\xC3\x98"; // UTF-8 for Ø auto text = dim.to_text(); EXPECT_FALSE(text.empty()); } TEST(AutoDimTest, Dimension_ToDxfText_ContainsPosition) { Dimension dim; dim.value = 15.0; dim.text_position = Point3D(100, 200, 0); auto text = dim.to_dxf_text(); EXPECT_NE(text.find("100"), std::string::npos); EXPECT_NE(text.find("200"), std::string::npos); } // ═══════════════════════════════════════════════════════════ // smart_placement // ═══════════════════════════════════════════════════════════ TEST(AutoDimTest, SmartPlacement_DoesNotCrash) { std::vector dims; for (int i = 0; i < 10; ++i) { Dimension d; d.type = DimensionType::Linear; d.value = static_cast(i); d.text_position = Point3D(0, static_cast(i * 5), 0); dims.push_back(d); } smart_placement(dims, Vector3D(0, 0, -1)); // Should have rearranged positions, all still valid for (const auto& d : dims) { EXPECT_TRUE(std::isfinite(d.text_position.x())); EXPECT_TRUE(std::isfinite(d.text_position.y())); } } // ═══════════════════════════════════════════════════════════ // baseline_dimensions // ═══════════════════════════════════════════════════════════ TEST(AutoDimTest, BaselineDimensions_Box_ReturnsDimensions) { auto box = make_box(10, 5, 3); auto dims = baseline_dimensions(box, 0, Vector3D(0, 0, -1)); EXPECT_GE(dims.size(), 1u); } TEST(AutoDimTest, BaselineDimensions_InvalidFace_ReturnsEmpty) { auto box = make_box(10, 5, 3); auto dims = baseline_dimensions(box, -1, Vector3D(0, 0, -1)); EXPECT_TRUE(dims.empty()); auto dims2 = baseline_dimensions(box, 9999, Vector3D(0, 0, -1)); EXPECT_TRUE(dims2.empty()); } // ═══════════════════════════════════════════════════════════ // chain_dimensions // ═══════════════════════════════════════════════════════════ TEST(AutoDimTest, ChainDimensions_TwoFaces_ReturnsDimension) { auto box = make_box(10, 5, 3); auto dims = chain_dimensions(box, {0, 1}, Vector3D(0, 0, -1)); EXPECT_GE(dims.size(), 1u); } TEST(AutoDimTest, ChainDimensions_SingleFace_ReturnsEmpty) { auto box = make_box(10, 5, 3); auto dims = chain_dimensions(box, {0}, Vector3D(0, 0, -1)); EXPECT_TRUE(dims.empty()); } TEST(AutoDimTest, ChainDimensions_EmptyList_ReturnsEmpty) { auto box = make_box(10, 5, 3); auto dims = chain_dimensions(box, {}, Vector3D(0, 0, -1)); EXPECT_TRUE(dims.empty()); } // ═══════════════════════════════════════════════════════════ // Dimension type enum coverage // ═══════════════════════════════════════════════════════════ TEST(AutoDimTest, DimensionType_CoversAllTypes) { // Verify all dimension types can be constructed and used Dimension linear; linear.type = DimensionType::Linear; EXPECT_EQ(linear.type, DimensionType::Linear); Dimension angular; angular.type = DimensionType::Angular; EXPECT_EQ(angular.type, DimensionType::Angular); Dimension radius; radius.type = DimensionType::Radius; EXPECT_EQ(radius.type, DimensionType::Radius); Dimension diameter; diameter.type = DimensionType::Diameter; EXPECT_EQ(diameter.type, DimensionType::Diameter); Dimension ordinate; ordinate.type = DimensionType::Ordinate; EXPECT_EQ(ordinate.type, DimensionType::Ordinate); }