Files
ViewDesignEngine/tests/brep/test_brep_drawing.cpp
T

274 lines
9.4 KiB
C++
Raw Normal View History

#include <gtest/gtest.h>
#include "vde/brep/brep_drawing.h"
#include "vde/brep/modeling.h"
#include <cmath>
#include <fstream>
#include <cstdio>
using namespace vde::brep;
using namespace vde::core;
// ═══════════════════════════════════════════════════════════
// generate_views — 基本测试
// ═══════════════════════════════════════════════════════════
TEST(BrepDrawingTest, GenerateViews_Box_ReturnsFourViews) {
auto box = make_box(2, 3, 4);
auto views = generate_views(box);
EXPECT_EQ(views.size(), 4u);
EXPECT_EQ(views[0].name, "front");
EXPECT_EQ(views[1].name, "top");
EXPECT_EQ(views[2].name, "right");
EXPECT_EQ(views[3].name, "iso");
}
TEST(BrepDrawingTest, GenerateViews_Box_EachViewHasSegments) {
auto box = make_box(2, 3, 4);
auto views = generate_views(box);
for (const auto& v : views) {
EXPECT_GT(v.total_segments(), 0u)
<< "View " << v.name << " should have segments";
}
}
TEST(BrepDrawingTest, GenerateViews_Box_FrontViewHasExpectedContent) {
auto box = make_box(2, 2, 2);
auto views = generate_views(box);
const auto& front = views[0];
EXPECT_EQ(front.name, "front");
// Front view: XY plane projection, should show X=[-1,1], Y=[-1,1]
EXPECT_GT(front.total_segments(), 0u);
}
TEST(BrepDrawingTest, GenerateViews_Box_ViewDirections) {
auto box = make_box(1, 1, 1);
auto views = generate_views(box);
// Front: looking down -Z
EXPECT_NEAR(views[0].view_direction.z(), -1.0, 1e-6);
// Top: looking down -Y
EXPECT_NEAR(views[1].view_direction.y(), -1.0, 1e-6);
// Right: looking down -X
EXPECT_NEAR(views[2].view_direction.x(), -1.0, 1e-6);
}
TEST(BrepDrawingTest, GenerateViews_EmptyBody_ReturnsEmpty) {
BrepModel empty;
auto views = generate_views(empty);
EXPECT_TRUE(views.empty());
}
TEST(BrepDrawingTest, GenerateViews_Cylinder_ReturnsFourViews) {
auto cyl = make_cylinder(1.0, 3.0, 16);
auto views = generate_views(cyl);
EXPECT_EQ(views.size(), 4u);
for (const auto& v : views) {
EXPECT_GT(v.total_segments(), 0u);
}
}
TEST(BrepDrawingTest, GenerateViews_Sphere_ReturnsFourViews) {
auto sphere = make_sphere(2.0, 16, 8);
auto views = generate_views(sphere);
EXPECT_EQ(views.size(), 4u);
// 球所有视图的主要轮廓应类似
for (const auto& v : views) {
ASSERT_GT(v.total_segments(), 0u);
}
}
// ═══════════════════════════════════════════════════════════
// section_view — 测试
// ═══════════════════════════════════════════════════════════
TEST(BrepDrawingTest, SectionView_Box_AtCenter) {
auto box = make_box(4, 4, 4);
// 截平面 z = 0(XY 平面,法向量沿 Z)
auto view = section_view(box, Point3D(0, 0, 0), Vector3D(0, 0, 1));
EXPECT_EQ(view.name, "section");
// 截面应为矩形轮廓,至少有 4 个交点形成轮廓线段
// + hatch 线,总数应 > 4
ASSERT_GT(view.total_segments(), 4u);
}
TEST(BrepDrawingTest, SectionView_Box_HorizontalPlane) {
auto box = make_box(4, 4, 4);
// z = 1 的水平截面(穿过盒子)
auto view = section_view(box, Point3D(0, 0, 1), Vector3D(0, 0, 1));
ASSERT_GT(view.total_segments(), 4u);
}
TEST(BrepDrawingTest, SectionView_Box_PlaneOutside) {
auto box = make_box(2, 2, 2);
// 截平面在盒子之外(z = 5
auto view = section_view(box, Point3D(0, 0, 5), Vector3D(0, 0, 1));
// 交点不足 3 个 → 无法形成截面
EXPECT_LT(view.total_segments(), 3u);
}
TEST(BrepDrawingTest, SectionView_EmptyBody_ReturnsEmpty) {
BrepModel empty;
auto view = section_view(empty, Point3D(0, 0, 0), Vector3D(0, 0, 1));
EXPECT_EQ(view.name, "section");
EXPECT_EQ(view.total_segments(), 0u);
}
TEST(BrepDrawingTest, SectionView_Cylinder_Midplane) {
auto cyl = make_cylinder(2.0, 6.0, 32);
// 垂直圆柱的 z=0 截面 → 圆形截面
auto view = section_view(cyl, Point3D(0, 0, 0), Vector3D(0, 0, 1));
ASSERT_GT(view.segments.size(), 3u);
}
// ═══════════════════════════════════════════════════════════
// DXF 导出 — 测试
// ═══════════════════════════════════════════════════════════
TEST(BrepDrawingTest, ExportDxf_CreatesFile) {
auto box = make_box(2, 2, 2);
auto views = generate_views(box);
const char* filepath = "test_output.dxf";
std::remove(filepath); // 清理旧文件
bool ok = export_dxf(filepath, views);
EXPECT_TRUE(ok);
// 验证文件存在
std::ifstream in(filepath);
EXPECT_TRUE(in.is_open());
std::string content((std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>());
in.close();
// 验证关键结构
EXPECT_NE(content.find("SECTION"), std::string::npos);
EXPECT_NE(content.find("ENTITIES"), std::string::npos);
EXPECT_NE(content.find("LINE"), std::string::npos);
EXPECT_NE(content.find("ENDSEC"), std::string::npos);
EXPECT_NE(content.find("EOF"), std::string::npos);
// 验证有至少一条 LINE 实体
EXPECT_NE(content.find("LINE"), std::string::npos);
std::remove(filepath);
}
TEST(BrepDrawingTest, ExportDxf_HasLayers) {
auto box = make_box(2, 2, 2);
auto views = generate_views(box);
const char* filepath = "test_layers.dxf";
std::remove(filepath);
export_dxf(filepath, views);
std::ifstream in(filepath);
std::string content((std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>());
in.close();
EXPECT_NE(content.find("visible"), std::string::npos);
EXPECT_NE(content.find("DASHED"), std::string::npos);
std::remove(filepath);
}
TEST(BrepDrawingTest, ExportDxf_EmptyViews_StillWritesSkeleton) {
std::vector<ProjectionView> empty_views;
const char* filepath = "test_empty.dxf";
std::remove(filepath);
bool ok = export_dxf(filepath, empty_views);
EXPECT_TRUE(ok);
std::ifstream in(filepath);
std::string content((std::istreambuf_iterator<char>(in)),
std::istreambuf_iterator<char>());
in.close();
EXPECT_NE(content.find("SECTION"), std::string::npos);
EXPECT_NE(content.find("EOF"), std::string::npos);
std::remove(filepath);
}
TEST(BrepDrawingTest, ExportDxf_InvalidPath_ReturnsFalse) {
auto box = make_box(1, 1, 1);
auto views = generate_views(box);
bool ok = export_dxf("/nonexistent_dir_xyz/test.dxf", views);
EXPECT_FALSE(ok);
}
// ═══════════════════════════════════════════════════════════
// 隐藏线 — 测试
// ═══════════════════════════════════════════════════════════
TEST(BrepDrawingTest, HiddenLines_Box_HasHiddenEdges) {
auto box = make_box(2, 2, 2);
auto views = generate_views(box);
// 每个标准视图均应有隐藏边
for (size_t i = 0; i < std::min(views.size(), size_t(3)); ++i) {
// 前/俯/右视图都应该有隐藏线
EXPECT_GE(views[i].hidden_lines.size() + views[i].segments.size(), 1u);
}
}
TEST(BrepDrawingTest, DrawSegment_DefaultNotHidden) {
DrawSegment seg{0, 0, 1, 1};
EXPECT_FALSE(seg.hidden);
}
TEST(BrepDrawingTest, DrawSegment_Hidden) {
DrawSegment seg{0, 0, 1, 1, true};
EXPECT_TRUE(seg.hidden);
}
TEST(BrepDrawingTest, ProjectionView_TotalSegments) {
ProjectionView v;
v.segments = {{0,0,1,0}, {1,0,1,1}};
v.hidden_lines = {{0,1,0,0, true}};
EXPECT_EQ(v.total_segments(), 3u);
}
// ═══════════════════════════════════════════════════════════
// Offset (stepped) section views
// ═══════════════════════════════════════════════════════════
TEST(OffsetSectionTest, SingleOffset) {
auto box = make_box(4, 4, 4);
auto view = offset_section_view(box, Vector3D(0, 0, 1), {0.0});
EXPECT_FALSE(view.segments.empty());
EXPECT_EQ(view.name, "offset_section");
}
TEST(OffsetSectionTest, MultipleOffsets) {
auto box = make_box(4, 4, 4);
auto view = offset_section_view(box, Vector3D(0, 0, 1), {-1.0, 0.0, 1.0});
EXPECT_GE(view.segments.size(), 3u); // section + step lines
}
TEST(OffsetSectionTest, EmptyOffsets) {
auto box = make_box(4, 4, 4);
auto view = offset_section_view(box, Vector3D(0, 0, 1), {});
EXPECT_TRUE(view.segments.empty());
}
TEST(OffsetSectionTest, CylinderSection) {
auto cyl = make_cylinder(2, 6, 32);
auto view = offset_section_view(cyl, Vector3D(0, 0, 1), {-2.0, 0.0, 2.0});
EXPECT_GE(view.total_segments(), 3u);
}