You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2412 lines
107 KiB
2412 lines
107 KiB
/**
|
|
* @file test_geometric_modeling.cpp
|
|
* @brief 几何建模系统综合测试套件 (扩展版)
|
|
*
|
|
* 覆盖范围:
|
|
* Part 1 - 独立图元建模测试 (TC-P-*)
|
|
* Part 2 - 变换操作测试 (TC-T-*)
|
|
* Part 3 - 布尔运算测试 (TC-B-*)
|
|
* Part 4 - Polyline 拉伸体扩展测试 (TC-PE-*)
|
|
* Part 5 - Helixline 拉伸体扩展测试 (TC-HE-*)
|
|
* Part 6 - 布尔运算扩展测试 (TC-BE-*)
|
|
*
|
|
* 编译方式 (示例):
|
|
* cl /std:c++17 /EHsc test_geometric_modeling.cpp -I<include_dir> -L<lib_dir> -lPE
|
|
*
|
|
* 依赖:
|
|
* - solve.h : create_blobtree / bake_blobtree / create_solver / generate_polymesh / ...
|
|
* - primitive_descriptor.h : 所有 descriptor 类型
|
|
* - math/math_defs.hpp : pi / two_pi
|
|
*/
|
|
|
|
#include <iostream>
|
|
#include <sstream>
|
|
#include <vector>
|
|
#include <cmath>
|
|
#include <cassert>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
#include <functional>
|
|
#include <fstream>
|
|
#include <filesystem>
|
|
#include <random>
|
|
#include <array>
|
|
|
|
#include <solve.h>
|
|
#include <math/math_defs.hpp>
|
|
#include <primitive_descriptor.h>
|
|
#include <../primitive_process/interface/base/primitive.hpp>
|
|
#include "SDF_Visualize/sdf_visualizer.hpp"
|
|
|
|
// ============================================================
|
|
// 轻量测试框架
|
|
// ============================================================
|
|
namespace test_fw
|
|
{
|
|
|
|
struct Result {
|
|
bool passed;
|
|
std::string name;
|
|
std::string message;
|
|
};
|
|
|
|
static std::vector<Result> g_results; // 修复原代码中的类型错误 (原为 std::vector<r>)
|
|
static int g_pass = 0;
|
|
static int g_fail = 0;
|
|
|
|
void run(const std::string& name, std::function<void()> test_fn)
|
|
{
|
|
std::cout << "[RUN ] " << name << std::endl;
|
|
try {
|
|
test_fn();
|
|
g_results.push_back({true, name, "OK"});
|
|
++g_pass;
|
|
std::cout << "[PASS] " << name << "\n\n";
|
|
} catch (const std::exception& ex) {
|
|
g_results.push_back({false, name, ex.what()});
|
|
++g_fail;
|
|
std::cout << "[FAIL] " << name << "\n reason: " << ex.what() << "\n\n";
|
|
} catch (...) {
|
|
g_results.push_back({false, name, "unknown exception"});
|
|
++g_fail;
|
|
std::cout << "[FAIL] " << name << "\n reason: unknown exception\n\n";
|
|
}
|
|
}
|
|
|
|
void print_summary()
|
|
{
|
|
std::cout << "============================\n";
|
|
std::cout << " TOTAL : " << (g_pass + g_fail) << "\n";
|
|
std::cout << " PASSED : " << g_pass << "\n";
|
|
std::cout << " FAILED : " << g_fail << "\n";
|
|
std::cout << "============================\n";
|
|
if (g_fail > 0) {
|
|
std::cout << "\nFailed tests:\n";
|
|
for (const auto& r : g_results) {
|
|
if (!r.passed) std::cout << " - " << r.name << " : " << r.message << "\n";
|
|
}
|
|
}
|
|
}
|
|
|
|
#define EXPECT_TRUE(cond) \
|
|
do { \
|
|
if (!(cond)) throw std::runtime_error("EXPECT_TRUE failed: " #cond " at line " + std::to_string(__LINE__)); \
|
|
} while (0)
|
|
|
|
#define EXPECT_NE_NULL(ptr) \
|
|
do { \
|
|
if ((ptr) == nullptr) \
|
|
throw std::runtime_error("Expected non-null pointer: " #ptr " at line " + std::to_string(__LINE__)); \
|
|
} while (0)
|
|
|
|
#define EXPECT_NO_THROW(expr) \
|
|
do { \
|
|
try { \
|
|
expr; \
|
|
} catch (...) { \
|
|
throw std::runtime_error("Unexpected exception in: " #expr " at line " + std::to_string(__LINE__)); \
|
|
} \
|
|
} while (0)
|
|
|
|
} // namespace test_fw
|
|
|
|
// ============================================================
|
|
// 公共辅助函数
|
|
// ============================================================
|
|
static s_settings make_default_settings(int resolution = 36)
|
|
{
|
|
s_settings s{};
|
|
s.resolution = resolution;
|
|
s.scene_aabb_margin = 1e-5;
|
|
s.restricted_primitive_bounding_test = true;
|
|
return s;
|
|
}
|
|
|
|
/** 单图元 → 完整流水线 */
|
|
static auto run_pipeline_single(primitive* prim, int resolution = 72)
|
|
{
|
|
auto rt = create_blobtree();
|
|
blobtree_add_primitive_node(rt, prim);
|
|
auto baked = bake_blobtree(rt);
|
|
destroy_blobtree(rt);
|
|
|
|
auto solver = create_solver(baked, make_default_settings(resolution));
|
|
auto result = generate_polymesh(solver);
|
|
print_statistics(solver);
|
|
destroy_solver(solver);
|
|
destroy_baked_blobtree(baked);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief 两图元布尔运算 — 含 SDF 可视化输出(原版,保留兼容)
|
|
*/
|
|
static auto run_pipeline_boolean(primitive* prim_a, primitive* prim_b, int bool_op, int resolution = 36)
|
|
{
|
|
auto rt = create_blobtree();
|
|
auto iter_a = blobtree_add_primitive_node(rt, prim_a);
|
|
auto iter_b = blobtree_add_primitive_node(rt, prim_b);
|
|
blobtree_add_operation_node(rt, iter_a, iter_b, static_cast<node_operation>(bool_op));
|
|
auto baked = bake_blobtree(rt);
|
|
destroy_blobtree(rt);
|
|
|
|
// std::filesystem::path base_dir = "E:\\projects\\ImplicitSurfaceNetwork-xj\\application\\SDF_Visualize";
|
|
// std::filesystem::path xy_file_path = base_dir / "sdf_slice_xy.txt";
|
|
// std::string sdf_xy_path = xy_file_path.string();
|
|
// dump_sdf_slice_xy(*baked, sdf_xy_path, 0.5, 256, 0.2);
|
|
// std::cout << "Profile (XY) SDF 数据已保存到: " << sdf_xy_path << std::endl;
|
|
|
|
auto solver = create_solver(baked, make_default_settings(resolution));
|
|
auto result = generate_polymesh(solver);
|
|
print_statistics(solver);
|
|
destroy_solver(solver);
|
|
destroy_baked_blobtree(baked);
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* @brief 两图元布尔运算 — 无 SDF 文件输出(扩展测试专用)
|
|
* 避免在无对应目录的环境中出现路径错误
|
|
*/
|
|
static auto run_pipeline_boolean_clean(primitive* prim_a, primitive* prim_b, node_operation op, int resolution = 36)
|
|
{
|
|
auto rt = create_blobtree();
|
|
auto iter_a = blobtree_add_primitive_node(rt, prim_a);
|
|
auto iter_b = blobtree_add_primitive_node(rt, prim_b);
|
|
blobtree_add_operation_node(rt, iter_a, iter_b, op);
|
|
auto baked = bake_blobtree(rt);
|
|
destroy_blobtree(rt);
|
|
|
|
auto solver = create_solver(baked, make_default_settings(resolution));
|
|
auto result = generate_polymesh(solver);
|
|
print_statistics(solver);
|
|
destroy_solver(solver);
|
|
destroy_baked_blobtree(baked);
|
|
return result;
|
|
}
|
|
|
|
// ============================================================
|
|
// ────────────────────────────────────────────────────────────
|
|
// Descriptor 构建辅助(避免重复样板代码)
|
|
// ────────────────────────────────────────────────────────────
|
|
|
|
/**
|
|
* @brief 构建一个直线轴 descriptor(两点,无弯折)
|
|
* @param from 起点
|
|
* @param to 终点
|
|
* @param pts 外部持有的点数组(生命周期需 >= descriptor 使用期)
|
|
* @param buls 外部持有的 bulge 数组
|
|
* @param ref_normal 参考法向(Frenet 帧的 "up" 方向)
|
|
*/
|
|
static polyline_descriptor_t make_straight_axis(vector3d from,
|
|
vector3d to,
|
|
std::vector<vector3d>& pts,
|
|
std::vector<double>& buls,
|
|
vector3d ref_normal = {1.0, 0.0, 0.0})
|
|
{
|
|
pts = {from, to};
|
|
buls = {0.0};
|
|
polyline_descriptor_t axis{};
|
|
axis.point_number = 2;
|
|
axis.points = pts.data();
|
|
axis.bulge_number = 1;
|
|
axis.bulges = buls.data();
|
|
axis.reference_normal = ref_normal;
|
|
axis.is_close = false;
|
|
return axis;
|
|
}
|
|
|
|
/**
|
|
* @brief 构建一个规则多边形 profile(凸多边形,N 边,内切圆半径 r)
|
|
* @param n 边数(≥3)
|
|
* @param r 外接圆半径
|
|
* @param pts 外部持有的点数组
|
|
* @param buls 外部持有的 bulge 数组(全 0 = 纯直线边)
|
|
*/
|
|
static polyline_descriptor_t make_regular_polygon_profile(int n,
|
|
double r,
|
|
std::vector<vector3d>& pts,
|
|
std::vector<double>& buls)
|
|
{
|
|
pts.clear();
|
|
buls.clear();
|
|
for (int i = 0; i < n; ++i) {
|
|
double angle = 2.0 * pi * i / n;
|
|
pts.push_back({r * std::cos(angle), r * std::sin(angle), 0.0});
|
|
buls.push_back(0.0);
|
|
}
|
|
polyline_descriptor_t p{};
|
|
p.point_number = static_cast<uint32_t>(n);
|
|
p.points = pts.data();
|
|
p.bulge_number = static_cast<uint32_t>(n);
|
|
p.bulges = buls.data();
|
|
p.reference_normal = {0.0, 0.0, 1.0};
|
|
p.is_close = true;
|
|
return p;
|
|
}
|
|
|
|
// ============================================================
|
|
// ============================================================
|
|
// PART 1 : 独立图元建模测试 (TC-P-*) [原有测试,保持不变]
|
|
// ============================================================
|
|
// ============================================================
|
|
|
|
void tc_p_01_default_sphere()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto sph = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
EXPECT_NE_NULL(sph);
|
|
auto result = run_pipeline_single(sph);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(sph);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_p_02_default_cylinder()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto cyl = create_primitive(dc, PRIMITIVE_TYPE_CYLINDER);
|
|
EXPECT_NE_NULL(cyl);
|
|
auto result = run_pipeline_single(cyl);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(cyl);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_p_03_default_extrude_polyline()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_p_04_default_extrude_helixline()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_HELIXLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_p_05_circular_profile_extrude()
|
|
{
|
|
static std::vector<vector3d> circle_pts = {
|
|
{1.0, 0.0, 0.0},
|
|
{0.0, 1.0, 0.0},
|
|
{-1.0, 0.0, 0.0},
|
|
{0.0, -1.0, 0.0}
|
|
};
|
|
constexpr double b90 = 0.41421356237;
|
|
static std::vector<double> circle_bulges = {b90, b90, b90, b90};
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 4;
|
|
profile.points = circle_pts.data();
|
|
profile.bulge_number = 4;
|
|
profile.bulges = circle_bulges.data();
|
|
profile.reference_normal = {0, 0, 1};
|
|
profile.is_close = true;
|
|
|
|
static std::vector<vector3d> axis_pts = {
|
|
{0.0, 0.0, 0.0},
|
|
{0.0, 0.0, 3.0}
|
|
};
|
|
static std::vector<double> axis_bul = {0.0};
|
|
|
|
polyline_descriptor_t axis{};
|
|
axis.point_number = 2;
|
|
axis.points = axis_pts.data();
|
|
axis.bulge_number = 1;
|
|
axis.bulges = axis_bul.data();
|
|
axis.reference_normal = {1, 0, 0};
|
|
axis.is_close = false;
|
|
|
|
extrude_polyline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_p_06_triangle_profile_extrude()
|
|
{
|
|
const double H = 0.5 * std::sqrt(3.0);
|
|
static std::vector<vector3d> tri_pts = {
|
|
{0.0, H * 2.0 / 3.0, 0.0},
|
|
{-0.5, -H / 3.0, 0.0},
|
|
{0.5, -H / 3.0, 0.0}
|
|
};
|
|
static std::vector<double> tri_bulges = {0.0, 0.0, 0.0};
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 3;
|
|
profile.points = tri_pts.data();
|
|
profile.bulge_number = 3;
|
|
profile.bulges = tri_bulges.data();
|
|
profile.reference_normal = {0, 0, 1};
|
|
profile.is_close = true;
|
|
|
|
static std::vector<vector3d> axis_pts = {
|
|
{0.0, 0.0, 0.0},
|
|
{0.0, 0.0, 2.0}
|
|
};
|
|
static std::vector<double> axis_bul = {0.0};
|
|
|
|
polyline_descriptor_t axis{};
|
|
axis.point_number = 2;
|
|
axis.points = axis_pts.data();
|
|
axis.bulge_number = 1;
|
|
axis.bulges = axis_bul.data();
|
|
axis.reference_normal = {1, 0, 0};
|
|
axis.is_close = false;
|
|
|
|
extrude_polyline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_p_07_custom_helixline_extrude()
|
|
{
|
|
// Profile 必须定义在螺旋起始截面的 (B, N) 坐标系内。
|
|
// 对于 radius=1.5, advance_per_round=3.0, start_direction=(1,0,0) 的右旋螺旋:
|
|
// N = -start_direction = (-1, 0, 0)
|
|
// k = radius * 2π / advance_per_round = π
|
|
// B = (0, 1/√(k²+1), -k/√(k²+1)) ≈ (0, +0.30331447, -0.95289051)
|
|
// 所以 profile 点坐标 = local_x * B + local_y * N(其中 local_x=±1, local_y=±0.430871)
|
|
static std::vector<vector3d> profile_pts = {
|
|
{+0.43087100, -0.30331447, +0.95289051}, // (-1, -0.430871) in (B,N) space
|
|
{+0.43087100, +0.30331447, -0.95289051}, // (+1, -0.430871)
|
|
{-0.43087100, +0.30331447, -0.95289051}, // (+1, +0.430871)
|
|
{-0.43087100, -0.30331447, +0.95289051} // (-1, +0.430871)
|
|
};
|
|
static std::vector<double> profile_bulges = {0.0, 0.0, 0.0, 0.0};
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 4;
|
|
profile.points = profile_pts.data();
|
|
profile.bulge_number = 4;
|
|
profile.bulges = profile_bulges.data();
|
|
profile.reference_normal = {0, 0, 1};
|
|
profile.is_close = true;
|
|
|
|
helixline_descriptor_t axis{};
|
|
axis.axis_start = {0.0, 0.0, 0.0};
|
|
axis.axis_end = {0.0, 0.0, 10.0};
|
|
axis.radius = 1.5;
|
|
axis.advance_per_round = 3.0;
|
|
axis.start_direction = {1.0, 0.0, 0.0};
|
|
axis.is_righthanded = true;
|
|
|
|
extrude_helixline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_HELIXLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_p_08_degenerate_tiny_sphere()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto sph = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
EXPECT_NE_NULL(sph);
|
|
primitive_apply_scale(sph, {0.001, 0.001, 0.001});
|
|
EXPECT_NO_THROW(run_pipeline_single(sph, 16));
|
|
destroy_primitive(sph);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ============================================================
|
|
// ============================================================
|
|
// PART 2 : 变换操作测试 (TC-T-*) [原有测试,保持不变]
|
|
// ============================================================
|
|
// ============================================================
|
|
|
|
void tc_t_01_sphere_translation()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto sph = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
primitive_apply_translation(sph, {2.0, 0.0, 0.0});
|
|
auto aabb = sph->fetch_aabb();
|
|
auto center = aabb.center();
|
|
EXPECT_TRUE(std::abs(center.x() - 2.0) < 1e-6);
|
|
EXPECT_TRUE(std::abs(center.y()) < 1e-6);
|
|
EXPECT_TRUE(std::abs(center.z()) < 1e-6);
|
|
auto result = run_pipeline_single(sph);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(sph);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_t_02_cylinder_multi_axis_translation()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto cyl = create_primitive(dc, PRIMITIVE_TYPE_CYLINDER);
|
|
primitive_apply_translation(cyl, {1.0, 0.0, 0.0});
|
|
primitive_apply_translation(cyl, {0.0, -2.0, 0.0});
|
|
primitive_apply_translation(cyl, {0.0, 0.0, 3.0});
|
|
auto aabb = cyl->fetch_aabb();
|
|
auto center = aabb.center();
|
|
EXPECT_TRUE(std::abs(center.x() - 1.0) < 1e-6);
|
|
EXPECT_TRUE(std::abs(center.y() + 2.0) < 1e-6);
|
|
EXPECT_TRUE(std::abs(center.z() - 3.5) < 1e-6);
|
|
auto result = run_pipeline_single(cyl);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(cyl);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_t_03_sphere_uniform_scale()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto sph = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
primitive_apply_scale(sph, {2.0, 2.0, 2.0});
|
|
auto aabb = sph->fetch_aabb();
|
|
auto sizes = aabb.sizes();
|
|
EXPECT_TRUE(std::abs(sizes.x() - 4.0) < 1e-6);
|
|
EXPECT_TRUE(std::abs(sizes.y() - 4.0) < 1e-6);
|
|
EXPECT_TRUE(std::abs(sizes.z() - 4.0) < 1e-6);
|
|
auto result = run_pipeline_single(sph);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(sph);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_t_04_cylinder_nonuniform_scale()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto cyl = create_primitive(dc, PRIMITIVE_TYPE_CYLINDER);
|
|
primitive_apply_scale(cyl, {0.5, 1.0, 2.0});
|
|
auto aabb = cyl->fetch_aabb();
|
|
auto sizes = aabb.sizes();
|
|
EXPECT_TRUE(std::abs(sizes.x() - 1.0) < 1e-5);
|
|
EXPECT_TRUE(std::abs(sizes.y() - 2.0) < 1e-5);
|
|
EXPECT_TRUE(std::abs(sizes.z() - 2.0) < 1e-5);
|
|
auto result = run_pipeline_single(cyl);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(cyl);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_t_05_rotation_90deg_x()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
double ay = 90.0 * pi / 180.0;
|
|
primitive_apply_rotation(ext, {std::sin(ay / 2.0), 0.0, 0.0, std::cos(ay / 2.0)});
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_t_06_rotation_45deg_y()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
double ay = 45.0 * pi / 180.0;
|
|
primitive_apply_rotation(ext, {0.0, std::sin(ay / 2.0), 0.0, std::cos(ay / 2.0)});
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_t_07_combined_transform()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto sph = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
primitive_apply_scale(sph, {1.5, 2.0, 0.8});
|
|
double az = 30.0 * pi / 180.0;
|
|
primitive_apply_rotation(sph, {0.0, 0.0, std::sin(az / 2.0), std::cos(az / 2.0)});
|
|
primitive_apply_translation(sph, {3.0, -1.0, 0.5});
|
|
auto aabb = sph->fetch_aabb();
|
|
auto c = aabb.center();
|
|
EXPECT_TRUE(std::abs(c.x() - 3.0) < 0.5);
|
|
EXPECT_TRUE(std::abs(c.y() + 1.0) < 0.5);
|
|
auto result = run_pipeline_single(sph);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(sph);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_t_08_large_scale()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto sph = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
primitive_apply_scale(sph, {100.0, 100.0, 100.0});
|
|
auto aabb = sph->fetch_aabb();
|
|
auto sizes = aabb.sizes();
|
|
EXPECT_TRUE(std::abs(sizes.x() - 200.0) < 1e-3);
|
|
EXPECT_NO_THROW(run_pipeline_single(sph, 24));
|
|
destroy_primitive(sph);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_t_09_four_rotations_identity()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto cyl = create_primitive(dc, PRIMITIVE_TYPE_CYLINDER);
|
|
auto aabb_init = cyl->fetch_aabb();
|
|
double az = 90.0 * pi / 180.0;
|
|
for (int i = 0; i < 4; ++i) primitive_apply_rotation(cyl, {0.0, 0.0, std::sin(az / 2.0), std::cos(az / 2.0)});
|
|
auto aabb_final = cyl->fetch_aabb();
|
|
EXPECT_TRUE((aabb_final.min() - aabb_init.min()).norm() < 1e-5);
|
|
EXPECT_TRUE((aabb_final.max() - aabb_init.max()).norm() < 1e-5);
|
|
destroy_primitive(cyl);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ============================================================
|
|
// ============================================================
|
|
// PART 3 : 布尔运算测试 (TC-B-*) [原有测试,保持不变]
|
|
// ============================================================
|
|
// ============================================================
|
|
|
|
void tc_b_01_sphere_sphere_union()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto sph1 = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
auto sph2 = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
primitive_apply_translation(sph2, {1.2, 0.0, 0.0});
|
|
auto rt = create_blobtree();
|
|
auto it1 = blobtree_add_primitive_node(rt, sph1);
|
|
auto it2 = blobtree_add_primitive_node(rt, sph2);
|
|
blobtree_add_operation_node(rt, it1, it2, UNION_OP);
|
|
auto baked = bake_blobtree(rt);
|
|
destroy_blobtree(rt);
|
|
auto solver = create_solver(baked, make_default_settings());
|
|
auto result = generate_polymesh(solver);
|
|
EXPECT_TRUE(result.success);
|
|
print_statistics(solver);
|
|
destroy_solver(solver);
|
|
destroy_baked_blobtree(baked);
|
|
destroy_primitive(sph1);
|
|
destroy_primitive(sph2);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_b_02_sphere_sphere_intersection()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto sph1 = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
auto sph2 = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
primitive_apply_translation(sph2, {1.0, 0.0, 0.0});
|
|
auto result = run_pipeline_boolean(sph1, sph2, INTERSECTION_OP);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(sph1);
|
|
destroy_primitive(sph2);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_b_03_sphere_sphere_difference()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto sph1 = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
auto sph2 = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
primitive_apply_scale(sph1, {2.0, 2.0, 2.0});
|
|
primitive_apply_translation(sph2, {1.2, 0.0, 0.0});
|
|
auto result = run_pipeline_boolean(sph1, sph2, DIFFERENCE_OP);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(sph1);
|
|
destroy_primitive(sph2);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_b_04_sphere_minus_cylinder_drill()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto sph = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
auto cyl = create_primitive(dc, PRIMITIVE_TYPE_CYLINDER);
|
|
primitive_apply_scale(cyl, {0.4, 0.4, 4.0});
|
|
double ax = 90.0 * pi / 180.0;
|
|
primitive_apply_rotation(cyl, {std::sin(ax / 2.0), 0.0, 0.0, std::cos(ax / 2.0)});
|
|
primitive_apply_translation(cyl, {0.0, 1.5, -0.2});
|
|
auto result = run_pipeline_boolean(sph, cyl, DIFFERENCE_OP);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(sph);
|
|
destroy_primitive(cyl);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_b_05_three_sphere_union_chain()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto sph1 = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
auto sph2 = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
auto sph3 = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
primitive_apply_translation(sph2, {1.5, 0.0, 0.0});
|
|
primitive_apply_translation(sph3, {3.0, 0.0, 0.0});
|
|
auto rt = create_blobtree();
|
|
auto it1 = blobtree_add_primitive_node(rt, sph1);
|
|
auto it2 = blobtree_add_primitive_node(rt, sph2);
|
|
auto it3 = blobtree_add_primitive_node(rt, sph3);
|
|
auto op1 = blobtree_add_operation_node(rt, it1, it2, UNION_OP);
|
|
blobtree_add_operation_node(rt, op1, it3, UNION_OP);
|
|
auto baked = bake_blobtree(rt);
|
|
destroy_blobtree(rt);
|
|
auto solver = create_solver(baked, make_default_settings());
|
|
auto result = generate_polymesh(solver);
|
|
EXPECT_TRUE(result.success);
|
|
print_statistics(solver);
|
|
destroy_solver(solver);
|
|
destroy_baked_blobtree(baked);
|
|
destroy_primitive(sph1);
|
|
destroy_primitive(sph2);
|
|
destroy_primitive(sph3);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_b_06_cylinder_cylinder_intersection()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto cyl1 = create_primitive(dc, PRIMITIVE_TYPE_CYLINDER);
|
|
auto cyl2 = create_primitive(dc, PRIMITIVE_TYPE_CYLINDER);
|
|
primitive_apply_translation(cyl1, {0.0, 0.0, -0.5});
|
|
double ax = 90.0 * pi / 180.0;
|
|
primitive_apply_rotation(cyl2, {std::sin(ax / 2.0), 0.0, 0.0, std::cos(ax / 2.0)});
|
|
auto result = run_pipeline_boolean(cyl1, cyl2, INTERSECTION_OP);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(cyl1);
|
|
destroy_primitive(cyl2);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_b_07_extrude_union_sphere()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
auto sph = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
primitive_apply_scale(sph, {0.8, 0.8, 0.8});
|
|
primitive_apply_translation(sph, {0.8, 2.0, 0.2});
|
|
auto result = run_pipeline_boolean(ext, sph, UNION_OP);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive(sph);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_b_08_disjoint_spheres_intersection()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto sph1 = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
auto sph2 = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
primitive_apply_translation(sph2, {10.0, 0.0, 0.0});
|
|
EXPECT_NO_THROW(run_pipeline_boolean(sph1, sph2, INTERSECTION_OP));
|
|
destroy_primitive(sph1);
|
|
destroy_primitive(sph2);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_b_09_contained_sphere_difference()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto small = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
auto big = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
primitive_apply_scale(big, {3.0, 3.0, 3.0});
|
|
EXPECT_NO_THROW(run_pipeline_boolean(small, big, DIFFERENCE_OP));
|
|
destroy_primitive(small);
|
|
destroy_primitive(big);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
void tc_b_10_complex_four_primitive_tree()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto cyl1 = create_primitive(dc, PRIMITIVE_TYPE_CYLINDER);
|
|
auto sph1 = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
auto sph2 = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
auto cyl2 = create_primitive(dc, PRIMITIVE_TYPE_CYLINDER);
|
|
primitive_apply_translation(cyl1, {1.0, 0.0, 0.0});
|
|
primitive_apply_translation(sph1, {1.0, 0.0, 0.0});
|
|
primitive_apply_scale(sph2, {0.5, 1.0, 1.5});
|
|
// primitive_apply_translation(cyl2, {-1.0, 0.0, 0.0});
|
|
primitive_apply_translation(cyl2, {-1.0, 0.0, 0.1});
|
|
|
|
auto rt = create_blobtree();
|
|
auto it_c1 = blobtree_add_primitive_node(rt, cyl1);
|
|
auto it_s1 = blobtree_add_primitive_node(rt, sph1);
|
|
auto it_s2 = blobtree_add_primitive_node(rt, sph2);
|
|
auto it_c2 = blobtree_add_primitive_node(rt, cyl2);
|
|
auto op1 = blobtree_add_operation_node(rt, it_c1, it_s1, INTERSECTION_OP);
|
|
auto op2 = blobtree_add_operation_node(rt, op1, it_s2, UNION_OP);
|
|
blobtree_add_operation_node(rt, it_c2, op2, DIFFERENCE_OP);
|
|
|
|
auto baked = bake_blobtree(rt);
|
|
destroy_blobtree(rt);
|
|
EXPECT_NO_THROW({
|
|
auto solver = create_solver(baked, make_default_settings());
|
|
auto result = generate_polymesh(solver);
|
|
EXPECT_TRUE(result.success);
|
|
print_statistics(solver);
|
|
destroy_solver(solver);
|
|
});
|
|
destroy_baked_blobtree(baked);
|
|
destroy_primitive(cyl1);
|
|
destroy_primitive(sph1);
|
|
destroy_primitive(sph2);
|
|
destroy_primitive(cyl2);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ============================================================
|
|
// ============================================================
|
|
// PART 4 : Polyline 拉伸体扩展测试 (TC-PE-*)
|
|
// ============================================================
|
|
// ============================================================
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-PE-01 : 五边形截面 + 沿 Z 轴拉伸(凸多边形)
|
|
// 目标 : 验证奇数多边形(5 边)的凸轮廓能正确建模
|
|
// 输入 : 正五边形 (r=0.8), 直线轴 (0,0,0)→(0,0,2)
|
|
// 预期 : 网格生成正常;结果为五棱柱
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_pe_01_pentagon_profile_straight_z_axis()
|
|
{
|
|
static std::vector<vector3d> pts;
|
|
static std::vector<double> buls;
|
|
auto profile = make_regular_polygon_profile(5, 0.8, pts, buls);
|
|
|
|
static std::vector<vector3d> axis_pts;
|
|
static std::vector<double> axis_buls;
|
|
auto axis = make_straight_axis({0.0, 0.0, 0.0}, {0.0, 0.0, 2.0}, axis_pts, axis_buls, {1.0, 0.0, 0.0});
|
|
|
|
extrude_polyline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
EXPECT_TRUE(result.mesh.num_vertices > 0);
|
|
EXPECT_TRUE(result.mesh.num_faces > 0);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-PE-02 : 六边形截面 + 斜向轴(非坐标轴方向)
|
|
// 目标 : 验证轴方向不对齐坐标轴时的拉伸建模
|
|
// 输入 : 正六边形截面; 轴 (0,0,0)→(1,1,1) 对角方向
|
|
// 预期 : 网格正常生成
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_pe_02_hexagon_profile_diagonal_axis()
|
|
{
|
|
static std::vector<vector3d> pts;
|
|
static std::vector<double> buls;
|
|
auto profile = make_regular_polygon_profile(6, 0.6, pts, buls);
|
|
|
|
// [已修复] 原始轴终点 {1.5, 1.5, 1.5} 的 y=1.5≠0,违反 polyline extrude axis 必须在 ZX 平面内的约束。
|
|
// 修复:将终点改为 {1.5, 0.0, 1.5}(去除 y 分量),轴方向变为 (1,0,1)。
|
|
// 同步将 reference_normal 更新为 {0,1,0},以确保其与新轴方向 (1,0,1) 正交。
|
|
static std::vector<vector3d> axis_pts;
|
|
static std::vector<double> axis_buls;
|
|
auto axis = make_straight_axis({0.0, 0.0, 0.0},
|
|
{1.5, 0.0, 1.5},
|
|
axis_pts,
|
|
axis_buls,
|
|
{0.0, 1.0, 0.0}); // 轴在 ZX 平面内,参考法向 Y 轴
|
|
|
|
extrude_polyline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-PE-03 : L 形凹多边形截面 + 短轴
|
|
// 目标 : 验证凹(非凸)截面能正确建模(6 顶点 L 形)
|
|
// 输入 : L 形截面; 轴 (0,0,0)→(0,0,1.5)
|
|
// 预期 : 网格正常生成
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_pe_03_L_shape_concave_profile()
|
|
{
|
|
// 顶点顺序 (CCW 看 -Z 方向):
|
|
// (0,0) → (2,0) → (2,1) → (1,1) → (1,2) → (0,2)
|
|
static std::vector<vector3d> pts = {
|
|
{0.0, 0.0, 0.0},
|
|
{2.0, 0.0, 0.0},
|
|
{2.0, 1.0, 0.0},
|
|
{1.0, 1.0, 0.0},
|
|
{1.0, 2.0, 0.0},
|
|
{0.0, 2.0, 0.0}
|
|
};
|
|
static std::vector<double> buls = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 6;
|
|
profile.points = pts.data();
|
|
profile.bulge_number = 6;
|
|
profile.bulges = buls.data();
|
|
profile.reference_normal = {0.0, 0.0, 1.0};
|
|
profile.is_close = true;
|
|
|
|
static std::vector<vector3d> axis_pts;
|
|
static std::vector<double> axis_buls;
|
|
auto axis = make_straight_axis({0.0, 0.0, 0.0}, {0.0, 0.0, 1.5}, axis_pts, axis_buls, {1.0, 0.0, 0.0});
|
|
|
|
extrude_polyline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-PE-04 : 含圆弧边(正 bulge)的截面 + 直线轴 (扇形截面)
|
|
// 目标 : 验证正 bulge(凸弧)截面可正确建模
|
|
// 输入 : 3 顶点扇形截面, 每段均为 60° 圆弧 (bulge = tan(π/12) ≈ 0.268)
|
|
// 预期 : 网格正常生成
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_pe_04_arc_positive_bulge_profile()
|
|
{
|
|
const double r = 0.8;
|
|
const double b60 = std::tan(pi / 12.0); // tan(15°),对应 60° 弧
|
|
|
|
// 正三角形的三个顶点
|
|
static std::vector<vector3d> pts = {
|
|
{r, 0.0, 0.0},
|
|
{r * std::cos(2.0 * pi / 3.0), r * std::sin(2.0 * pi / 3.0), 0.0},
|
|
{r * std::cos(4.0 * pi / 3.0), r * std::sin(4.0 * pi / 3.0), 0.0}
|
|
};
|
|
static std::vector<double> buls = {b60, b60, b60}; // 全正 bulge → 凸弧
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 3;
|
|
profile.points = pts.data();
|
|
profile.bulge_number = 3;
|
|
profile.bulges = buls.data();
|
|
profile.reference_normal = {0.0, 0.0, 1.0};
|
|
profile.is_close = true;
|
|
|
|
static std::vector<vector3d> axis_pts;
|
|
static std::vector<double> axis_buls;
|
|
auto axis = make_straight_axis({0.0, 0.0, 0.0}, {0.0, 0.0, 2.0}, axis_pts, axis_buls, {1.0, 0.0, 0.0});
|
|
|
|
extrude_polyline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-PE-05 : 含负 bulge 截面(内凹弧)+ 直线轴
|
|
// 目标 : 验证负 bulge(凹弧)截面可正确建模(类似齿轮齿槽轮廓)
|
|
// 输入 : 正方形轮廓, 其中两条边有负 bulge (-0.3)
|
|
// 预期 : 网格正常生成
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_pe_05_arc_negative_bulge_profile()
|
|
{
|
|
static std::vector<vector3d> pts = {
|
|
{-0.7, -0.7, 0.0},
|
|
{0.7, -0.7, 0.0},
|
|
{0.7, 0.7, 0.0},
|
|
{-0.7, 0.7, 0.0}
|
|
};
|
|
static std::vector<double> buls = {-0.3, 0.0, -0.3, 0.0}; // 两边内凹弧
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 4;
|
|
profile.points = pts.data();
|
|
profile.bulge_number = 4;
|
|
profile.bulges = buls.data();
|
|
profile.reference_normal = {0.0, 0.0, 1.0};
|
|
profile.is_close = true;
|
|
|
|
static std::vector<vector3d> axis_pts;
|
|
static std::vector<double> axis_buls;
|
|
auto axis = make_straight_axis({0.0, 0.0, 0.0}, {0.0, 0.0, 1.8}, axis_pts, axis_buls, {1.0, 0.0, 0.0});
|
|
|
|
extrude_polyline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-PE-06 : 含锐角顶点的截面 + 直线轴(剪刀形轮廓)
|
|
// 目标 : 验证截面包含约 30° 锐角顶点时系统稳健性
|
|
// 输入 : 细长菱形 (纵横比约 6:1), 顶角约 18°
|
|
// 预期 : 不崩溃;网格生成(可能退化)
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_pe_06_sharp_acute_angle_profile()
|
|
{
|
|
// 细长菱形:顶角约 20°
|
|
static std::vector<vector3d> pts = {
|
|
{0.0, 0.9, 0.0}, // 顶点 (极尖)
|
|
{-0.15, 0.0, 0.0}, // 右侧宽点
|
|
{0.0, -0.9, 0.0}, // 底顶点 (极尖)
|
|
{0.15, 0.0, 0.0} // 左侧宽点
|
|
};
|
|
static std::vector<double> buls = {0.0, 0.0, 0.0, 0.0};
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 4;
|
|
profile.points = pts.data();
|
|
profile.bulge_number = 4;
|
|
profile.bulges = buls.data();
|
|
profile.reference_normal = {0.0, 0.0, 1.0};
|
|
profile.is_close = true;
|
|
|
|
static std::vector<vector3d> axis_pts;
|
|
static std::vector<double> axis_buls;
|
|
auto axis = make_straight_axis({0.0, 0.0, 0.0}, {0.0, 0.0, 2.0}, axis_pts, axis_buls, {1.0, 0.0, 0.0});
|
|
|
|
extrude_polyline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
EXPECT_NO_THROW(run_pipeline_single(ext, 24));
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-PE-07 : 矩形截面 + L 形折线轴(单次 90° 弯折)
|
|
// 目标 : 验证折线轴(单弯折)的建模
|
|
// 输入 : 小矩形截面 (0.3×0.4); 轴: (0,0,0)→(2,0,0)→(2,0,2)
|
|
// 预期 : 网格生成正常;结果为 L 形管状体
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_pe_07_rectangular_profile_L_shape_axis()
|
|
{
|
|
// 小矩形截面(宽 0.6, 高 0.8)
|
|
static std::vector<vector3d> prof_pts = {
|
|
{-0.3, -0.4, 0.0},
|
|
{0.3, -0.4, 0.0},
|
|
{0.3, 0.4, 0.0},
|
|
{-0.3, 0.4, 0.0}
|
|
};
|
|
static std::vector<double> prof_buls = {0.0, 0.0, 0.0, 0.0};
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 4;
|
|
profile.points = prof_pts.data();
|
|
profile.bulge_number = 4;
|
|
profile.bulges = prof_buls.data();
|
|
profile.reference_normal = {0.0, 0.0, 1.0};
|
|
profile.is_close = true;
|
|
|
|
// L 形轴:沿 X 轴走 2 个单位,再沿 Z 轴走 2 个单位
|
|
static std::vector<vector3d> axis_pts = {
|
|
{0.0, 0.0, 0.0},
|
|
{2.0, 0.0, 0.0},
|
|
{2.0, 0.0, 2.0}
|
|
};
|
|
static std::vector<double> axis_buls = {0.0, 0.0}; // 直线段
|
|
|
|
polyline_descriptor_t axis{};
|
|
axis.point_number = 3;
|
|
axis.points = axis_pts.data();
|
|
axis.bulge_number = 2;
|
|
axis.bulges = axis_buls.data();
|
|
axis.reference_normal = {0.0, 1.0, 0.0}; // Y 轴作参考法向
|
|
axis.is_close = false;
|
|
|
|
extrude_polyline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0); // ERROR !!
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-PE-08 : 圆截面 + Z 形折线轴(多次弯折)
|
|
// 目标 : 验证轴包含多个弯折点时建模的稳健性
|
|
// 输入 : 圆形截面 (r=0.25); 轴: Z 形 (5 点,4 段)
|
|
// 预期 : 网格正常生成
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_pe_08_circular_profile_Z_shape_axis()
|
|
{
|
|
// 圆形截面(4 段 90° 圆弧近似)
|
|
const double b90 = 0.41421356237;
|
|
static std::vector<vector3d> prof_pts = {
|
|
{0.25, 0.0, 0.0},
|
|
{0.0, 0.25, 0.0},
|
|
{-0.25, 0.0, 0.0},
|
|
{0.0, -0.25, 0.0}
|
|
};
|
|
static std::vector<double> prof_buls = {b90, b90, b90, b90};
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 4;
|
|
profile.points = prof_pts.data();
|
|
profile.bulge_number = 4;
|
|
profile.bulges = prof_buls.data();
|
|
profile.reference_normal = {0.0, 0.0, 1.0};
|
|
profile.is_close = true;
|
|
|
|
// Z 形轴:(0,0,0)→(1,0,0)→(1,0,1)→(2,0,1)→(2,0,2)
|
|
static std::vector<vector3d> axis_pts = {
|
|
{0.0, 0.0, 0.0},
|
|
{1.0, 0.0, 0.0},
|
|
{1.0, 0.0, 1.0},
|
|
{2.0, 0.0, 1.0},
|
|
{2.0, 0.0, 2.0}
|
|
};
|
|
static std::vector<double> axis_buls = {0.0, 0.0, 0.0, 0.0};
|
|
|
|
polyline_descriptor_t axis{};
|
|
axis.point_number = 5;
|
|
axis.points = axis_pts.data();
|
|
axis.bulge_number = 4;
|
|
axis.bulges = axis_buls.data();
|
|
axis.reference_normal = {0.0, 1.0, 0.0};
|
|
axis.is_close = false;
|
|
|
|
extrude_polyline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-PE-09 : 矩形截面 + 弧线轴(轴本身有 bulge)
|
|
// 目标 : 验证当拉伸路径为曲线(非折线)时的建模
|
|
// 输入 : 小矩形截面; 轴: 单段弧线 (bulge=0.5, 近似 90° 弧)
|
|
// 预期 : 网格正常生成
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_pe_09_rectangular_profile_arc_axis()
|
|
{
|
|
static std::vector<vector3d> prof_pts = {
|
|
{-0.2, -0.2, 0.0},
|
|
{0.2, -0.2, 0.0},
|
|
{0.2, 0.2, 0.0},
|
|
{-0.2, 0.2, 0.0}
|
|
};
|
|
static std::vector<double> prof_buls = {0.0, 0.0, 0.0, 0.0};
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 4;
|
|
profile.points = prof_pts.data();
|
|
profile.bulge_number = 4;
|
|
profile.bulges = prof_buls.data();
|
|
profile.reference_normal = {0.0, 0.0, 1.0};
|
|
profile.is_close = true;
|
|
|
|
// 弧线轴: 从 (0,0,0) 到 (2,0,2),bulge=0.5 产生圆弧路径
|
|
static std::vector<vector3d> axis_pts = {
|
|
{0.0, 0.0, 0.0},
|
|
{2.0, 0.0, 2.0}
|
|
};
|
|
static std::vector<double> axis_buls = {0.5};
|
|
|
|
polyline_descriptor_t axis{};
|
|
axis.point_number = 2;
|
|
axis.points = axis_pts.data();
|
|
axis.bulge_number = 1;
|
|
axis.bulges = axis_buls.data();
|
|
axis.reference_normal = {0.0, 1.0, 0.0};
|
|
axis.is_close = false;
|
|
|
|
extrude_polyline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-PE-10 : 参数化测试 — 不同边数凸多边形 (N=3..8)
|
|
// 目标 : 系统性验证各种凸多边形截面 (三角形到八边形)
|
|
// 预期 : 所有情况下网格生成正常
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_pe_10_parametric_polygon_n_sides()
|
|
{
|
|
for (int n = 3; n <= 8; ++n) {
|
|
std::vector<vector3d> pts;
|
|
std::vector<double> buls;
|
|
auto profile = make_regular_polygon_profile(n, 0.7, pts, buls);
|
|
|
|
std::vector<vector3d> axis_pts;
|
|
std::vector<double> axis_buls;
|
|
auto axis = make_straight_axis({0.0, 0.0, 0.0}, {0.0, 0.0, 1.5}, axis_pts, axis_buls, {1.0, 0.0, 0.0});
|
|
|
|
extrude_polyline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
|
|
std::string sub_name = "TC-PE-10 N=" + std::to_string(n) + " 边形";
|
|
auto result = run_pipeline_single(ext, 24);
|
|
if (!result.success) {
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
throw std::runtime_error(sub_name + " mesh generation failed");
|
|
}
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-PE-11 : 高纵横比拉伸体(细长管)
|
|
// 目标 : 验证极端细长几何(长轴/截面尺寸 >> 1)下的数值稳定性
|
|
// 输入 : 小圆形截面 (r=0.1); 轴长度 = 10.0
|
|
// 预期 : 不崩溃;网格生成成功
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_pe_11_high_aspect_ratio_extrusion()
|
|
{
|
|
const double b90 = 0.41421356237;
|
|
static std::vector<vector3d> prof_pts = {
|
|
{0.1, 0.0, 0.0},
|
|
{0.0, 0.1, 0.0},
|
|
{-0.1, 0.0, 0.0},
|
|
{0.0, -0.1, 0.0}
|
|
};
|
|
static std::vector<double> prof_buls = {b90, b90, b90, b90};
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 4;
|
|
profile.points = prof_pts.data();
|
|
profile.bulge_number = 4;
|
|
profile.bulges = prof_buls.data();
|
|
profile.reference_normal = {0.0, 0.0, 1.0};
|
|
profile.is_close = true;
|
|
|
|
static std::vector<vector3d> axis_pts;
|
|
static std::vector<double> axis_buls;
|
|
auto axis = make_straight_axis({0.0, 0.0, 0.0}, {0.0, 0.0, 10.0}, axis_pts, axis_buls, {1.0, 0.0, 0.0});
|
|
|
|
extrude_polyline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
EXPECT_NO_THROW(run_pipeline_single(ext, 24));
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ============================================================
|
|
// ============================================================
|
|
// PART 5 : Helixline 拉伸体扩展测试 (TC-HE-*)
|
|
// ============================================================
|
|
// ============================================================
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-HE-01 : 单圈螺旋(360°)+ 方形截面
|
|
// 目标 : 验证恰好一圈螺旋(total angle = 2π)的建模
|
|
// 输入 : 方形截面 (0.2×0.2); radius=1.0, advance_per_round=1.0
|
|
// 预期 : 网格正常生成
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_he_01_single_turn_square_profile()
|
|
{
|
|
// Profile 必须定义在螺旋起始截面的 (B, N) 坐标系内,使截面与切向量 T 垂直。
|
|
// 参数: radius=1.0, advance_per_round=1.0 → k = 2π, L = √(k²+1) ≈ 6.3623
|
|
// N = (-1, 0, 0) (指向螺旋轴心的内法向)
|
|
// B = (0, +0.15717673, -0.98757049)
|
|
// profile 点 = local_x * B + local_y * N,local_(x,y) ∈ {±0.1}
|
|
static std::vector<vector3d> prof_pts = {
|
|
{+0.10000000, -0.01571767, +0.09875705}, // (-0.1, -0.1) in (B,N) space
|
|
{+0.10000000, +0.01571767, -0.09875705}, // (+0.1, -0.1)
|
|
{-0.10000000, +0.01571767, -0.09875705}, // (+0.1, +0.1)
|
|
{-0.10000000, -0.01571767, +0.09875705} // (-0.1, +0.1)
|
|
};
|
|
static std::vector<double> prof_buls = {0.0, 0.0, 0.0, 0.0};
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 4;
|
|
profile.points = prof_pts.data();
|
|
profile.bulge_number = 4;
|
|
profile.bulges = prof_buls.data();
|
|
profile.reference_normal = {0.0, 0.0, 1.0};
|
|
profile.is_close = true;
|
|
|
|
helixline_descriptor_t axis{};
|
|
axis.axis_start = {0.0, 0.0, 0.0};
|
|
axis.axis_end = {0.0, 0.0, 1.0}; // 高度 = advance_per_round × 1圈 = 1.0
|
|
axis.radius = 1.0;
|
|
axis.advance_per_round = 1.0; // 每圈上升 1.0 → 1 圈后到 axis_end
|
|
axis.start_direction = {1.0, 0.0, 0.0};
|
|
axis.is_righthanded = true;
|
|
|
|
extrude_helixline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_HELIXLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-HE-02 : 三圈螺旋(1080°)+ 方形截面
|
|
// 目标 : 验证多圈螺旋(3 turns)的建模完整性
|
|
// 输入 : 方形截面 (0.15×0.15); radius=0.8, 3 圈
|
|
// 预期 : 网格正常生成;顶点数相比单圈显著增多
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_he_02_three_turns_square_profile()
|
|
{
|
|
// radius=0.8, advance_per_round=1.0 → k = 1.6π, L ≈ 5.1249
|
|
// B = (0, +0.19511986, -0.98077940), N = (-1, 0, 0)
|
|
// profile 点 = local_x * B + local_y * N,local_(x,y) ∈ {±0.075}
|
|
static std::vector<vector3d> prof_pts = {
|
|
{+0.07500000, -0.01463399, +0.07355846}, // (-0.075, -0.075)
|
|
{+0.07500000, +0.01463399, -0.07355846}, // (+0.075, -0.075)
|
|
{-0.07500000, +0.01463399, -0.07355846}, // (+0.075, +0.075)
|
|
{-0.07500000, -0.01463399, +0.07355846} // (-0.075, +0.075)
|
|
};
|
|
static std::vector<double> prof_buls = {0.0, 0.0, 0.0, 0.0};
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 4;
|
|
profile.points = prof_pts.data();
|
|
profile.bulge_number = 4;
|
|
profile.bulges = prof_buls.data();
|
|
profile.reference_normal = {0.0, 0.0, 1.0};
|
|
profile.is_close = true;
|
|
|
|
helixline_descriptor_t axis{};
|
|
axis.axis_start = {0.0, 0.0, 0.0};
|
|
axis.axis_end = {0.0, 0.0, 3.0}; // 3 圈 × advance 1.0 = 3.0
|
|
axis.radius = 0.8;
|
|
axis.advance_per_round = 1.0;
|
|
axis.start_direction = {1.0, 0.0, 0.0};
|
|
axis.is_righthanded = true;
|
|
|
|
extrude_helixline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_HELIXLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-HE-03 : 左旋螺旋 (is_righthanded = false)
|
|
// 目标 : 验证左手螺旋与右手螺旋均可正确建模
|
|
// 输入 : 方形截面; radius=1.0, 2 圈, 左旋
|
|
// 预期 : 网格正常生成
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_he_03_left_handed_helix()
|
|
{
|
|
// radius=1.0, advance_per_round=1.0 → 与 TC-HE-01 相同的 k=2π
|
|
// 左旋不改变 B/N(start_direction 未变),截面坐标系相同。
|
|
// B = (0, +0.15717673, -0.98757049), N = (-1, 0, 0)
|
|
// profile 点 = local_x * B + local_y * N,local_(x,y) ∈ {±0.12}
|
|
static std::vector<vector3d> prof_pts = {
|
|
{+0.12000000, -0.01886121, +0.11850846}, // (-0.12, -0.12)
|
|
{+0.12000000, +0.01886121, -0.11850846}, // (+0.12, -0.12)
|
|
{-0.12000000, +0.01886121, -0.11850846}, // (+0.12, +0.12)
|
|
{-0.12000000, -0.01886121, +0.11850846} // (-0.12, +0.12)
|
|
};
|
|
static std::vector<double> prof_buls = {0.0, 0.0, 0.0, 0.0};
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 4;
|
|
profile.points = prof_pts.data();
|
|
profile.bulge_number = 4;
|
|
profile.bulges = prof_buls.data();
|
|
profile.reference_normal = {0.0, 0.0, 1.0};
|
|
profile.is_close = true;
|
|
|
|
helixline_descriptor_t axis{};
|
|
axis.axis_start = {0.0, 0.0, 0.0};
|
|
axis.axis_end = {0.0, 0.0, 2.0};
|
|
axis.radius = 1.0;
|
|
axis.advance_per_round = 1.0;
|
|
axis.start_direction = {1.0, 0.0, 0.0};
|
|
axis.is_righthanded = false; // ← 左旋
|
|
|
|
extrude_helixline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_HELIXLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-HE-04 : 密排螺旋(小节距)
|
|
// 目标 : 验证 advance_per_round 极小(接近截面尺寸)时的建模
|
|
// 输入 : 方形截面 (0.1×0.1); advance_per_round=0.13 (节距仅略大于截面)
|
|
// 预期 : 不崩溃;网格生成(可能有数值挑战)
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_he_04_tight_pitch_helix()
|
|
{
|
|
// radius=0.6, advance_per_round=0.12 → k = 10π ≈ 31.4159, L ≈ 31.432
|
|
// B = (0, +0.03181488, -0.99949378), N = (-1, 0, 0)
|
|
// profile 点 = local_x * B + local_y * N,local_(x,y) ∈ {±0.05}
|
|
static std::vector<vector3d> prof_pts = {
|
|
{+0.05000000, -0.00159074, +0.04997469}, // (-0.05, -0.05)
|
|
{+0.05000000, +0.00159074, -0.04997469}, // (+0.05, -0.05)
|
|
{-0.05000000, +0.00159074, -0.04997469}, // (+0.05, +0.05)
|
|
{-0.05000000, -0.00159074, +0.04997469} // (-0.05, +0.05)
|
|
};
|
|
static std::vector<double> prof_buls = {0.0, 0.0, 0.0, 0.0};
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 4;
|
|
profile.points = prof_pts.data();
|
|
profile.bulge_number = 4;
|
|
profile.bulges = prof_buls.data();
|
|
profile.reference_normal = {0.0, 0.0, 1.0};
|
|
profile.is_close = true;
|
|
|
|
helixline_descriptor_t axis{};
|
|
axis.axis_start = {0.0, 0.0, 0.0};
|
|
axis.axis_end = {0.0, 0.0, 0.65}; // 5 圈,节距极小
|
|
axis.radius = 0.6;
|
|
axis.advance_per_round = 0.13;
|
|
axis.start_direction = {1.0, 0.0, 0.0};
|
|
axis.is_righthanded = true;
|
|
|
|
extrude_helixline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_HELIXLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
EXPECT_NO_THROW(run_pipeline_single(ext, 30));
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-HE-05 : 大节距螺旋(稀疏螺旋)
|
|
// 目标 : 验证 advance_per_round 很大(弹簧感)时的建模
|
|
// 输入 : 方形截面 (0.2×0.2); advance_per_round=3.0 (每圈上升 3 倍直径)
|
|
// 预期 : 网格正常生成
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_he_05_large_pitch_helix()
|
|
{
|
|
// radius=1.0, advance_per_round=3.0 → k = 2π/3 ≈ 2.0944, L ≈ 2.3228
|
|
// B = (0, +0.43087077, -0.90241364), N = (-1, 0, 0)
|
|
// profile 点 = local_x * B + local_y * N,local_(x,y) ∈ {±0.1}
|
|
static std::vector<vector3d> prof_pts = {
|
|
{+0.10000000, -0.04308708, +0.09024136}, // (-0.1, -0.1)
|
|
{+0.10000000, +0.04308708, -0.09024136}, // (+0.1, -0.1)
|
|
{-0.10000000, +0.04308708, -0.09024136}, // (+0.1, +0.1)
|
|
{-0.10000000, -0.04308708, +0.09024136} // (-0.1, +0.1)
|
|
};
|
|
static std::vector<double> prof_buls = {0.0, 0.0, 0.0, 0.0};
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 4;
|
|
profile.points = prof_pts.data();
|
|
profile.bulge_number = 4;
|
|
profile.bulges = prof_buls.data();
|
|
profile.reference_normal = {0.0, 0.0, 1.0};
|
|
profile.is_close = true;
|
|
|
|
helixline_descriptor_t axis{};
|
|
axis.axis_start = {0.0, 0.0, 0.0};
|
|
axis.axis_end = {0.0, 0.0, 6.0}; // 2 圈, advance=3.0
|
|
axis.radius = 1.0;
|
|
axis.advance_per_round = 3.0;
|
|
axis.start_direction = {1.0, 0.0, 0.0};
|
|
axis.is_righthanded = true;
|
|
|
|
extrude_helixline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_HELIXLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-HE-06 : 螺旋线 + 圆形截面(圆管弹簧)
|
|
// 目标 : 验证圆形截面(bulge 近似)在螺旋路径上的建模
|
|
// 输入 : 4 点圆弧近似截面 (r=0.15); 2 圈螺旋
|
|
// 预期 : 网格正常生成;外形类似弹簧
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_he_06_circular_profile_helix_spring()
|
|
{
|
|
// radius=0.9, advance_per_round=1.0 → k = 1.8π ≈ 5.6549, L ≈ 5.7434
|
|
// B = (0, +0.17413698, -0.98472144), N = (-1, 0, 0)
|
|
// 圆形截面 4 点(外接圆 r=0.15),依次对应 2D 方向 +B, +N, -B, -N
|
|
// 点坐标 = local_x * B + local_y * N
|
|
const double b90 = 0.41421356237;
|
|
static std::vector<vector3d> prof_pts = {
|
|
{+0.00000000, +0.02612055, -0.14770822}, // ( 0.15, 0 ) in (B,N)
|
|
{-0.15000000, +0.00000000, 0.00000000 }, // ( 0, 0.15)
|
|
{-0.00000000, -0.02612055, +0.14770822}, // (-0.15, 0 )
|
|
{+0.15000000, +0.00000000, 0.00000000 } // ( 0, -0.15)
|
|
};
|
|
static std::vector<double> prof_buls = {b90, b90, b90, b90};
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 4;
|
|
profile.points = prof_pts.data();
|
|
profile.bulge_number = 4;
|
|
profile.bulges = prof_buls.data();
|
|
profile.reference_normal = {0.0, 0.0, 1.0};
|
|
profile.is_close = true;
|
|
|
|
helixline_descriptor_t axis{};
|
|
axis.axis_start = {0.0, 0.0, 0.0};
|
|
axis.axis_end = {0.0, 0.0, 2.0};
|
|
axis.radius = 0.9;
|
|
axis.advance_per_round = 1.0;
|
|
axis.start_direction = {1.0, 0.0, 0.0};
|
|
axis.is_righthanded = true;
|
|
|
|
extrude_helixline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_HELIXLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-HE-07 : 螺旋线 + 三角形截面
|
|
// 目标 : 验证非矩形截面(三角形)在螺旋路径上的建模
|
|
// 输入 : 等边三角形截面 (边长 0.25); 2 圈螺旋
|
|
// 预期 : 网格正常生成
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_he_07_triangular_profile_helix()
|
|
{
|
|
// radius=0.8, advance_per_round=1.0 → k = 1.6π ≈ 5.0265, L ≈ 5.1249
|
|
// B = (0, +0.19511986, -0.98077940), N = (-1, 0, 0)
|
|
// 等边三角形(外接圆 r3=0.15),顶点方向 0°、120°、240° in (B,N) space
|
|
// 点坐标 = local_x * B + local_y * N
|
|
const double r3 = 0.15;
|
|
static std::vector<vector3d> prof_pts = {
|
|
{+0.00000000, +0.02926798, -0.14711691}, // (r3, 0 ) in (B,N)
|
|
{-0.12990381, -0.01463399, +0.07355846}, // r3*(cos120°, sin120°)
|
|
{+0.12990381, -0.01463399, +0.07355846} // r3*(cos240°, sin240°)
|
|
};
|
|
static std::vector<double> prof_buls = {0.0, 0.0, 0.0};
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 3;
|
|
profile.points = prof_pts.data();
|
|
profile.bulge_number = 3;
|
|
profile.bulges = prof_buls.data();
|
|
profile.reference_normal = {0.0, 0.0, 1.0};
|
|
profile.is_close = true;
|
|
|
|
helixline_descriptor_t axis{};
|
|
axis.axis_start = {0.0, 0.0, 0.0};
|
|
axis.axis_end = {0.0, 0.0, 2.0};
|
|
axis.radius = 0.8;
|
|
axis.advance_per_round = 1.0;
|
|
axis.start_direction = {1.0, 0.0, 0.0};
|
|
axis.is_righthanded = true;
|
|
|
|
extrude_helixline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_HELIXLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-HE-08 : 大半径螺旋(轴从大半径切入)
|
|
// 目标 : 验证螺旋半径相对截面尺寸很大时的几何建模
|
|
// 输入 : 小方形截面 (0.1×0.1); radius=3.0 (远大于截面)
|
|
// 预期 : 网格正常生成
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_he_08_large_radius_helix()
|
|
{
|
|
// radius=3.0, advance_per_round=1.0 → k = 6π ≈ 18.850, L ≈ 18.877
|
|
// B = (0, +0.05297715, -0.99859572), N = (-1, 0, 0)
|
|
// profile 点 = local_x * B + local_y * N,local_(x,y) ∈ {±0.05}
|
|
static std::vector<vector3d> prof_pts = {
|
|
{+0.05000000, -0.00264886, +0.04992979}, // (-0.05, -0.05)
|
|
{+0.05000000, +0.00264886, -0.04992979}, // (+0.05, -0.05)
|
|
{-0.05000000, +0.00264886, -0.04992979}, // (+0.05, +0.05)
|
|
{-0.05000000, -0.00264886, +0.04992979} // (-0.05, +0.05)
|
|
};
|
|
static std::vector<double> prof_buls = {0.0, 0.0, 0.0, 0.0};
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 4;
|
|
profile.points = prof_pts.data();
|
|
profile.bulge_number = 4;
|
|
profile.bulges = prof_buls.data();
|
|
profile.reference_normal = {0.0, 0.0, 1.0};
|
|
profile.is_close = true;
|
|
|
|
helixline_descriptor_t axis{};
|
|
axis.axis_start = {0.0, 0.0, 0.0};
|
|
axis.axis_end = {0.0, 0.0, 2.0};
|
|
axis.radius = 3.0;
|
|
axis.advance_per_round = 1.0;
|
|
axis.start_direction = {1.0, 0.0, 0.0};
|
|
axis.is_righthanded = true;
|
|
|
|
extrude_helixline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_HELIXLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-HE-09 : 参数化测试 — 不同圈数 (0.5, 1, 2, 4 圈)
|
|
// 目标 : 系统性验证各种圈数下的螺旋建模
|
|
// 预期 : 所有情况下不崩溃;网格生成成功
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_he_09_parametric_turns()
|
|
{
|
|
// 各测试: {advance_per_round, height} 决定圈数 = height / advance_per_round
|
|
const std::vector<std::pair<double, double>> cases = {
|
|
{2.0, 1.0}, // 0.5 圈
|
|
{1.0, 1.0}, // 1 圈
|
|
{1.0, 2.0}, // 2 圈
|
|
{1.0, 4.0}, // 4 圈
|
|
};
|
|
|
|
for (auto& [adv, h] : cases) {
|
|
// Profile 点必须在螺旋起始截面的 (B,N) 坐标系内。
|
|
// radius=0.8, start_direction=(1,0,0) → N=(-1,0,0)
|
|
// k = radius * 2π / adv, L = √(k²+1)
|
|
// B = (0, 1/L, -k/L)
|
|
// 对于 adv=2.0: k≈2.5133, B≈(0,+0.36970,-0.92915)
|
|
// 对于 adv=1.0: k≈5.0265, B≈(0,+0.19512,-0.98078)
|
|
const double r_helix = 0.8;
|
|
const double k = r_helix * 2.0 * pi / adv;
|
|
const double L = std::sqrt(k * k + 1.0);
|
|
// B = (0, 1/L, -k/L), N = (-1, 0, 0)
|
|
// point = local_x * B + local_y * N, (local_x, local_y) ∈ {±0.1}
|
|
const double By = 1.0 / L, Bz = -k / L;
|
|
std::vector<vector3d> prof_pts = {
|
|
{+0.1, -0.1 * By, +0.1 * Bz}, // (-0.1, -0.1) in (B,N) space → local_y→x=-(-0.1)=+0.1
|
|
{+0.1, +0.1 * By, -0.1 * Bz}, // (+0.1, -0.1)
|
|
{-0.1, +0.1 * By, -0.1 * Bz}, // (+0.1, +0.1)
|
|
{-0.1, -0.1 * By, +0.1 * Bz} // (-0.1, +0.1)
|
|
};
|
|
std::vector<double> prof_buls = {0.0, 0.0, 0.0, 0.0};
|
|
|
|
polyline_descriptor_t profile{};
|
|
profile.point_number = 4;
|
|
profile.points = prof_pts.data();
|
|
profile.bulge_number = 4;
|
|
profile.bulges = prof_buls.data();
|
|
profile.reference_normal = {0.0, 0.0, 1.0};
|
|
profile.is_close = true;
|
|
|
|
helixline_descriptor_t axis{};
|
|
axis.axis_start = {0.0, 0.0, 0.0};
|
|
axis.axis_end = {0.0, 0.0, h};
|
|
axis.radius = 0.8;
|
|
axis.advance_per_round = adv;
|
|
axis.start_direction = {1.0, 0.0, 0.0};
|
|
axis.is_righthanded = true;
|
|
|
|
extrude_helixline_descriptor_t desc{};
|
|
desc.profile_number = 1;
|
|
desc.profiles = &profile;
|
|
desc.axis = axis;
|
|
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_HELIXLINE);
|
|
|
|
std::cout << "descriptor: turns=" << h / adv << ", adv=" << adv << ", height=" << h << std::endl;
|
|
std::cout << "profile points: \np1:" << desc.profiles[0].points[0].x << ", " << desc.profiles[0].points[0].y << ", "
|
|
<< desc.profiles[0].points[0].z << "\np2:" << desc.profiles[0].points[1].x << ", "
|
|
<< desc.profiles[0].points[1].y << ", " << desc.profiles[0].points[1].z
|
|
<< "\np3:" << desc.profiles[0].points[2].x << ", " << desc.profiles[0].points[2].y << ", "
|
|
<< desc.profiles[0].points[2].z << "\np4:" << desc.profiles[0].points[3].x << ", "
|
|
<< desc.profiles[0].points[3].y << ", " << desc.profiles[0].points[3].z << std::endl;
|
|
|
|
ext->update_geometry(static_cast<const void*>(&desc), 0);
|
|
|
|
double turns = h / adv;
|
|
auto result = run_pipeline_single(ext, 28);
|
|
if (!result.success) {
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
throw std::runtime_error("TC-HE-09 failed for turns=" + std::to_string(turns));
|
|
}
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-HE-10 : 螺旋轴经过缩放变换后的建模
|
|
// 目标 : 验证在 primitive 级别施加缩放后螺旋体的建模
|
|
// 输入 : 默认螺旋体 (default extrude_helixline); scale (2, 2, 1)
|
|
// 预期 : 变换后网格仍然正常生成
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_he_10_helix_with_scale_transform()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_HELIXLINE);
|
|
EXPECT_NE_NULL(ext);
|
|
|
|
primitive_apply_scale(ext, {2.0, 2.0, 1.0});
|
|
auto result = run_pipeline_single(ext);
|
|
EXPECT_TRUE(result.success);
|
|
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ============================================================
|
|
// ============================================================
|
|
// PART 6 : 布尔运算扩展测试 (TC-BE-*)
|
|
// ============================================================
|
|
// ============================================================
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-BE-01 : 两 Polyline 拉伸体并集(并排管道)
|
|
// 目标 : 验证两个相同类型拉伸体的 UNION 运算
|
|
// 输入 : ext_A @ (0,0,0), ext_B @ (2.5,0,0),部分重叠
|
|
// 预期 : 网格正常生成
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_be_01_two_extrude_polyline_union()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto ext_a = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
auto ext_b = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
|
|
primitive_apply_translation(ext_b, {2.5, 0.0, 0.0});
|
|
|
|
auto result = run_pipeline_boolean_clean(ext_a, ext_b, UNION_OP);
|
|
EXPECT_TRUE(result.success);
|
|
|
|
destroy_primitive(ext_a);
|
|
destroy_primitive(ext_b);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-BE-02 : 两 Polyline 拉伸体交集(正交截取)
|
|
// 目标 : 验证两拉伸体交集(INTERSECTION)运算
|
|
// 输入 : ext_A 沿 Z 轴; ext_B 绕 Y 轴旋转 90° (沿 X 轴), 均在 origin 附近
|
|
// 预期 : 网格生成正常(结果为截面处的交叠体)
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_be_02_two_extrude_polyline_intersection()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto ext_a = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
auto ext_b = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
|
|
// ext_b 绕 Y 轴旋转 90° 使其方向改变
|
|
const double ay = 90.0 * pi / 180.0;
|
|
primitive_apply_rotation(ext_b, {0.0, std::sin(ay / 2.0), 0.0, std::cos(ay / 2.0)});
|
|
|
|
auto result = run_pipeline_boolean_clean(ext_a, ext_b, INTERSECTION_OP);
|
|
EXPECT_TRUE(result.success);
|
|
|
|
destroy_primitive(ext_a);
|
|
destroy_primitive(ext_b);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-BE-03 : Polyline 拉伸体减去拉伸体(槽口切割)
|
|
// 目标 : 大拉伸体减去小拉伸体,结果为开槽形状
|
|
// 输入 : ext_A (大,默认); ext_B (小,缩放 0.3×0.3×2.5) 穿过 ext_A
|
|
// 预期 : 网格正常生成;结果包含开槽特征
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_be_03_extrude_difference_slot()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto ext_a = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
auto ext_b = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
|
|
// ext_b 缩小成一个细长体穿入 ext_a
|
|
primitive_apply_scale(ext_b, {0.3, 0.3, 2.5});
|
|
primitive_apply_translation(ext_b, {0.5, 0.5, 0.0});
|
|
|
|
auto result = run_pipeline_boolean_clean(ext_a, ext_b, DIFFERENCE_OP);
|
|
EXPECT_TRUE(result.success);
|
|
|
|
destroy_primitive(ext_a);
|
|
destroy_primitive(ext_b);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-BE-04 : 螺旋线拉伸体并集球体(混合类型组合)
|
|
// 目标 : 不同图元类型(helixline + sphere)的 UNION
|
|
// 输入 : helixline ext @ origin; sphere (r=0.5) @ (0,0,3)(螺旋末端)
|
|
// 预期 : 网格正常生成
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_be_04_helixline_extrude_union_sphere()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto hel = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_HELIXLINE);
|
|
auto sph = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
|
|
primitive_apply_scale(sph, {0.5, 0.5, 0.5});
|
|
primitive_apply_translation(sph, {0.0, 0.0, 1.5});
|
|
|
|
auto result = run_pipeline_boolean_clean(hel, sph, UNION_OP);
|
|
EXPECT_TRUE(result.success);
|
|
|
|
destroy_primitive(hel);
|
|
destroy_primitive(sph);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-BE-05 : 圆柱减去螺旋线拉伸体(螺纹切割仿真)
|
|
// 目标 : 模拟在圆柱上切割螺纹的操作(cylinder - helix extrude)
|
|
// 输入 : 圆柱 (r=1, h=3); 螺旋拉伸体 (小方截面, 嵌入圆柱表面)
|
|
// 预期 : 网格正常生成;结果为带螺纹槽的圆柱
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_be_05_cylinder_minus_helixline_thread()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto cyl = create_primitive(dc, PRIMITIVE_TYPE_CYLINDER);
|
|
auto hel = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_HELIXLINE);
|
|
|
|
// 将圆柱拉伸到合适高度
|
|
primitive_apply_scale(cyl, {2.0, 2.0, 3.0});
|
|
// 螺旋体配置已在 initialize 中为默认值(半径约 1.5, 2 圈等)
|
|
// 将螺旋轴心对齐圆柱中心
|
|
primitive_apply_translation(hel, {0.0, 0.0, 0.0});
|
|
|
|
auto result = run_pipeline_boolean_clean(cyl, hel, DIFFERENCE_OP);
|
|
EXPECT_TRUE(result.success);
|
|
|
|
destroy_primitive(cyl);
|
|
destroy_primitive(hel);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-BE-06 : 三个 Polyline 拉伸体链式并集 (A ∪ B) ∪ C
|
|
// 目标 : 验证三个拉伸体的多级布尔树
|
|
// 输入 : 三个拉伸体分别沿 X 轴排列,部分重叠
|
|
// 预期 : 网格正常生成;结果为三段相连的管道
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_be_06_three_extrude_polyline_chain_union()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto ext_a = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
auto ext_b = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
auto ext_c = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
|
|
primitive_apply_translation(ext_b, {3.0, 0.0, 0.0});
|
|
primitive_apply_translation(ext_c, {6.0, 0.0, 0.0});
|
|
|
|
auto rt = create_blobtree();
|
|
auto it_a = blobtree_add_primitive_node(rt, ext_a);
|
|
auto it_b = blobtree_add_primitive_node(rt, ext_b);
|
|
auto it_c = blobtree_add_primitive_node(rt, ext_c);
|
|
auto op_ab = blobtree_add_operation_node(rt, it_a, it_b, UNION_OP);
|
|
blobtree_add_operation_node(rt, op_ab, it_c, UNION_OP);
|
|
|
|
auto baked = bake_blobtree(rt);
|
|
destroy_blobtree(rt);
|
|
|
|
auto solver = create_solver(baked, make_default_settings());
|
|
auto result = generate_polymesh(solver);
|
|
EXPECT_TRUE(result.success);
|
|
print_statistics(solver);
|
|
destroy_solver(solver);
|
|
destroy_baked_blobtree(baked);
|
|
destroy_primitive(ext_a);
|
|
destroy_primitive(ext_b);
|
|
destroy_primitive(ext_c);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-BE-07 : 布尔链(先并集后差集): (Poly ∪ Sphere) - Cylinder
|
|
// 目标 : 验证先 UNION 再 DIFFERENCE 的多步布尔链
|
|
// 预期 : 网格正常生成;三图元参与
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_be_07_boolean_chain_union_then_difference()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
auto sph = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
auto cyl = create_primitive(dc, PRIMITIVE_TYPE_CYLINDER);
|
|
|
|
// ext @ origin; sph @ (2, 0, 0) (部分与 ext 重叠)
|
|
primitive_apply_translation(sph, {2.0, 0.0, 0.0});
|
|
// cyl 作为钻孔: 沿 X 轴旋转后穿过结合体
|
|
primitive_apply_scale(cyl, {0.5, 0.5, 4.0});
|
|
const double ax = 90.0 * pi / 180.0;
|
|
primitive_apply_rotation(cyl, {std::sin(ax / 2.0), 0.0, 0.0, std::cos(ax / 2.0)});
|
|
primitive_apply_translation(cyl, {1.0, 0.0, 0.0});
|
|
|
|
auto rt = create_blobtree();
|
|
auto it_e = blobtree_add_primitive_node(rt, ext);
|
|
auto it_s = blobtree_add_primitive_node(rt, sph);
|
|
auto it_c = blobtree_add_primitive_node(rt, cyl);
|
|
auto op_es = blobtree_add_operation_node(rt, it_e, it_s, UNION_OP);
|
|
blobtree_add_operation_node(rt, op_es, it_c, DIFFERENCE_OP);
|
|
|
|
auto baked = bake_blobtree(rt);
|
|
destroy_blobtree(rt);
|
|
auto solver = create_solver(baked, make_default_settings());
|
|
auto result = generate_polymesh(solver);
|
|
EXPECT_TRUE(result.success);
|
|
print_statistics(solver);
|
|
destroy_solver(solver);
|
|
destroy_baked_blobtree(baked);
|
|
destroy_primitive(ext);
|
|
destroy_primitive(sph);
|
|
destroy_primitive(cyl);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-BE-08 : 多类型混合并集(圆柱 + Polyline 拉伸体)
|
|
// 目标 : 验证不同类型图元的混合 UNION
|
|
// 输入 : cylinder 沿 Z 轴; extrude_polyline 旋转 90° 与之正交
|
|
// 预期 : 网格正常生成
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_be_08_cylinder_union_extrude_polyline()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto cyl = create_primitive(dc, PRIMITIVE_TYPE_CYLINDER);
|
|
auto ext = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
|
|
// 默认圆柱沿 Z; ext 旋转使其沿 X 轴延伸
|
|
const double ay = 90.0 * pi / 180.0;
|
|
primitive_apply_rotation(ext, {0.0, std::sin(ay / 2.0), 0.0, std::cos(ay / 2.0)});
|
|
primitive_apply_translation(ext, {0.0, 0.0, 0.5}); // 居中到圆柱高度中部
|
|
|
|
auto result = run_pipeline_boolean_clean(cyl, ext, UNION_OP);
|
|
EXPECT_TRUE(result.success);
|
|
|
|
destroy_primitive(cyl);
|
|
destroy_primitive(ext);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-BE-09 : 相切球(边界接触情形)
|
|
// 目标 : 验证两球恰好外切(表面相切、内部不重叠)时的 UNION
|
|
// 输入 : sph_A (r=1) @ (0,0,0); sph_B (r=1) @ (2,0,0)(恰好相切)
|
|
// 预期 : 不崩溃;网格生成(结果含切点特征)
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_be_09_tangent_spheres_boundary()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto sph1 = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
auto sph2 = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
|
|
primitive_apply_translation(sph2, {2.0, 0.0, 0.0}); // 恰好外切
|
|
|
|
EXPECT_NO_THROW(run_pipeline_boolean_clean(sph1, sph2, UNION_OP));
|
|
|
|
destroy_primitive(sph1);
|
|
destroy_primitive(sph2);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-BE-10 : 薄壁交集(近重合面的交集)
|
|
// 目标 : 验证两个拉伸体仅轻微重叠(薄层交集)时系统稳健性
|
|
// 输入 : ext_A (2×2 截面); ext_B 偏移 (1.95,0,0)(两者仅 0.05 重叠)
|
|
// 预期 : 不崩溃;网格生成(结果为极薄片)
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_be_10_thin_wall_intersection()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto ext_a = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
auto ext_b = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
|
|
// 默认拉伸体 x 范围约 [-2,2],平移 3.95 后两者仅 0.05 重叠
|
|
primitive_apply_translation(ext_b, {3.95, 0.0, 0.0});
|
|
|
|
EXPECT_NO_THROW(run_pipeline_boolean_clean(ext_a, ext_b, INTERSECTION_OP));
|
|
|
|
destroy_primitive(ext_a);
|
|
destroy_primitive(ext_b);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-BE-11 : 极端尺寸差异布尔运算(大比例 vs. 小比例)
|
|
// 目标 : 验证图元尺寸相差悬殊(100×)时的布尔运算稳健性
|
|
// 输入 : sph_big (scale×5) @ origin; sph_small (scale×0.3) @ (3,0,0)
|
|
// sph_small 完全在 sph_big 外部(分离)—— UNION 应产生两个独立体
|
|
// 预期 : 不崩溃;网格生成成功
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_be_11_extreme_size_ratio_union()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto big = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
auto small = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
|
|
primitive_apply_scale(big, {5.0, 5.0, 5.0});
|
|
primitive_apply_scale(small, {0.5, 0.5, 0.5});
|
|
primitive_apply_translation(small, {6.0, 0.0, 0.0}); // 在大球外侧
|
|
|
|
EXPECT_NO_THROW(run_pipeline_boolean_clean(big, small, UNION_OP));
|
|
|
|
destroy_primitive(big);
|
|
destroy_primitive(small);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-BE-12 : 完全包含差集(大球 - 小球 = 挖空球壳)
|
|
// 目标 : 验证 A 完全包含 B,A - B 的结果为球壳
|
|
// 输入 : big (r=2) @ origin; small (r=0.8) @ origin(同心)
|
|
// 预期 : 网格正常生成;顶点/面数 > 0(球壳结构)
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_be_12_concentric_sphere_shell()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto big = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
auto sml = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
|
|
primitive_apply_scale(big, {2.0, 2.0, 2.0});
|
|
primitive_apply_scale(sml, {0.8, 0.8, 0.8});
|
|
|
|
auto result = run_pipeline_boolean_clean(big, sml, DIFFERENCE_OP);
|
|
EXPECT_TRUE(result.success);
|
|
EXPECT_TRUE(result.mesh.num_vertices > 0);
|
|
EXPECT_TRUE(result.mesh.num_faces > 0);
|
|
|
|
destroy_primitive(big);
|
|
destroy_primitive(sml);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-BE-13 : 螺旋线与圆柱交集(螺纹嵌合仿真)
|
|
// 目标 : 模拟螺纹嵌合(helix extrude ∩ cylinder)的几何建模
|
|
// 输入 : helixline ext 与一个同轴圆柱做交集
|
|
// 预期 : 网格正常生成;结果为嵌合在圆柱表面的螺旋带
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_be_13_helixline_intersection_cylinder()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto hel = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_HELIXLINE);
|
|
auto cyl = create_primitive(dc, PRIMITIVE_TYPE_CYLINDER);
|
|
|
|
// 圆柱沿 Z 轴,高度与螺旋线高度相近,半径略大于螺旋半径
|
|
primitive_apply_scale(cyl, {2.0, 2.0, 3.0}); // 半径 2, 高度 3
|
|
|
|
auto result = run_pipeline_boolean_clean(hel, cyl, INTERSECTION_OP);
|
|
EXPECT_TRUE(result.success);
|
|
|
|
destroy_primitive(hel);
|
|
destroy_primitive(cyl);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-BE-14 : 复杂 5 图元混合布尔树
|
|
// 目标 : 验证包含多种图元类型的深层布尔树 (depth=3)
|
|
// 运算 : ((ext_poly ∪ sphere) ∩ cylinder) - (helix ∪ sphere2)
|
|
// 预期 : 不崩溃;网格生成正常
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_be_14_complex_five_primitive_tree()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto ext_p = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
auto sph1 = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
auto cyl = create_primitive(dc, PRIMITIVE_TYPE_CYLINDER);
|
|
auto hel = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_HELIXLINE);
|
|
auto sph2 = create_primitive(dc, PRIMITIVE_TYPE_SPHERE);
|
|
|
|
// 对各图元施加适当变换使其在空间上产生交叠
|
|
primitive_apply_scale(sph1, {1.5, 1.5, 1.5});
|
|
primitive_apply_scale(cyl, {2.5, 2.5, 2.5});
|
|
primitive_apply_scale(sph2, {0.5, 0.5, 0.5});
|
|
primitive_apply_translation(sph2, {1.0, 0.0, 1.0});
|
|
|
|
auto rt = create_blobtree();
|
|
auto it_ep = blobtree_add_primitive_node(rt, ext_p);
|
|
auto it_s1 = blobtree_add_primitive_node(rt, sph1);
|
|
auto it_c = blobtree_add_primitive_node(rt, cyl);
|
|
auto it_h = blobtree_add_primitive_node(rt, hel);
|
|
auto it_s2 = blobtree_add_primitive_node(rt, sph2);
|
|
|
|
// (ext_p ∪ sph1)
|
|
auto op_union1 = blobtree_add_operation_node(rt, it_ep, it_s1, UNION_OP);
|
|
// ∩ cylinder
|
|
auto op_isect = blobtree_add_operation_node(rt, op_union1, it_c, INTERSECTION_OP);
|
|
// (hel ∪ sph2)
|
|
auto op_union2 = blobtree_add_operation_node(rt, it_h, it_s2, UNION_OP);
|
|
// - (hel ∪ sph2)
|
|
blobtree_add_operation_node(rt, op_isect, op_union2, DIFFERENCE_OP);
|
|
|
|
auto baked = bake_blobtree(rt);
|
|
destroy_blobtree(rt);
|
|
|
|
EXPECT_NO_THROW({
|
|
auto solver = create_solver(baked, make_default_settings(28));
|
|
auto result = generate_polymesh(solver);
|
|
EXPECT_TRUE(result.success);
|
|
print_statistics(solver);
|
|
destroy_solver(solver);
|
|
});
|
|
|
|
destroy_baked_blobtree(baked);
|
|
destroy_primitive(ext_p);
|
|
destroy_primitive(sph1);
|
|
destroy_primitive(cyl);
|
|
destroy_primitive(hel);
|
|
destroy_primitive(sph2);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-BE-15 : 拉伸体与自身并集(幂等性验证)
|
|
// 目标 : 两个完全相同的拉伸体做 UNION,结果与单图元相同
|
|
// 输入 : 两个完全相同的默认 extrude_polyline
|
|
// 预期 : 网格正常生成;不崩溃
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_be_15_identical_primitives_union()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto ext_a = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
auto ext_b = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
// 不做任何变换,两图元完全重合
|
|
|
|
EXPECT_NO_THROW(run_pipeline_boolean_clean(ext_a, ext_b, UNION_OP));
|
|
|
|
destroy_primitive(ext_a);
|
|
destroy_primitive(ext_b);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-BE-16 : 随机参数压力测试(Polyline Extrude 布尔运算)
|
|
// 目标 : 以不同随机偏移对两个 extrude_polyline 做所有三种布尔运算
|
|
// 验证在随机参数下系统不崩溃
|
|
// 运算 : 分别测试 UNION / INTERSECTION / DIFFERENCE
|
|
// 预期 : 三种运算均不抛出异常
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_be_16_random_offset_all_boolean_ops()
|
|
{
|
|
// 固定种子确保可复现性
|
|
std::mt19937 rng(42);
|
|
std::uniform_real_distribution<> dist_offset(-1.5, 1.5);
|
|
std::uniform_real_distribution<> dist_scale(0.5, 2.0);
|
|
|
|
const std::vector<node_operation> ops = {UNION_OP, INTERSECTION_OP, DIFFERENCE_OP};
|
|
const std::vector<std::string> opname = {"UNION", "INTERSECTION", "DIFFERENCE"};
|
|
|
|
for (size_t op_idx = 0; op_idx < ops.size(); ++op_idx) {
|
|
auto dc = create_primitive_data_center();
|
|
auto ext_a = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
auto ext_b = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_POLYLINE);
|
|
|
|
vector3d offset = {dist_offset(rng), dist_offset(rng), dist_offset(rng)};
|
|
vector3d scale_b = {dist_scale(rng), dist_scale(rng), dist_scale(rng)};
|
|
|
|
primitive_apply_scale(ext_b, scale_b);
|
|
primitive_apply_translation(ext_b, offset);
|
|
|
|
try {
|
|
run_pipeline_boolean_clean(ext_a, ext_b, ops[op_idx], 24);
|
|
} catch (const std::exception& e) {
|
|
destroy_primitive(ext_a);
|
|
destroy_primitive(ext_b);
|
|
destroy_primitive_data_center(dc);
|
|
throw std::runtime_error(std::string("TC-BE-16 ") + opname[op_idx] + " failed: " + e.what());
|
|
}
|
|
|
|
destroy_primitive(ext_a);
|
|
destroy_primitive(ext_b);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
}
|
|
|
|
// ──────────────────────────────────────────────────────────────
|
|
// TC-BE-17 : 螺旋线拉伸体差集(两个螺旋线,交叉抵消)
|
|
// 目标 : 两个螺旋线拉伸体(一右旋一左旋)做差集
|
|
// 预期 : 网格正常生成
|
|
// ──────────────────────────────────────────────────────────────
|
|
void tc_be_17_two_helixlines_difference()
|
|
{
|
|
auto dc = create_primitive_data_center();
|
|
auto hel_rh = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_HELIXLINE); // 右旋 (默认)
|
|
auto hel_lh = create_primitive(dc, PRIMITIVE_TYPE_EXTRUDE_HELIXLINE); // 左旋 (通过自定义 desc)
|
|
|
|
// 构建左旋螺旋描述符
|
|
static std::vector<vector3d> prof_pts = {
|
|
{-0.1, -0.1, 0.0},
|
|
{0.1, -0.1, 0.0},
|
|
{0.1, 0.1, 0.0},
|
|
{-0.1, 0.1, 0.0}
|
|
};
|
|
static std::vector<double> prof_buls = {0.0, 0.0, 0.0, 0.0};
|
|
|
|
polyline_descriptor_t profile_lh{};
|
|
profile_lh.point_number = 4;
|
|
profile_lh.points = prof_pts.data();
|
|
profile_lh.bulge_number = 4;
|
|
profile_lh.bulges = prof_buls.data();
|
|
profile_lh.reference_normal = {0.0, 0.0, 1.0};
|
|
profile_lh.is_close = true;
|
|
|
|
helixline_descriptor_t axis_lh{};
|
|
axis_lh.axis_start = {0.0, 0.0, 0.0};
|
|
axis_lh.axis_end = {0.0, 0.0, 2.0};
|
|
axis_lh.radius = 1.5;
|
|
axis_lh.advance_per_round = 0.5;
|
|
axis_lh.start_direction = {1.0, 0.0, 0.0};
|
|
axis_lh.is_righthanded = false; // ← 左旋
|
|
|
|
extrude_helixline_descriptor_t desc_lh{};
|
|
desc_lh.profile_number = 1;
|
|
desc_lh.profiles = &profile_lh;
|
|
desc_lh.axis = axis_lh;
|
|
hel_lh->update_geometry(static_cast<const void*>(&desc_lh), 0);
|
|
|
|
auto result = run_pipeline_boolean_clean(hel_rh, hel_lh, DIFFERENCE_OP);
|
|
EXPECT_TRUE(result.success);
|
|
|
|
destroy_primitive(hel_rh);
|
|
destroy_primitive(hel_lh);
|
|
destroy_primitive_data_center(dc);
|
|
}
|
|
|
|
// ============================================================
|
|
// 主函数 : 注册并执行所有测试
|
|
// ============================================================
|
|
int main()
|
|
{
|
|
using namespace test_fw;
|
|
|
|
std::cout << "====================================================\n";
|
|
std::cout << " 几何建模系统 · 综合测试套件 (扩展版)\n";
|
|
std::cout << "====================================================\n\n";
|
|
|
|
//// ---- Part 1: 独立图元建模 ----
|
|
// std::cout << "--- Part 1: 独立图元建模测试 ---\n\n";
|
|
// run("TC-P-01 默认单位球", tc_p_01_default_sphere);
|
|
// run("TC-P-02 默认单位圆柱", tc_p_02_default_cylinder);
|
|
// run("TC-P-03 默认Polyline拉伸体", tc_p_03_default_extrude_polyline);
|
|
// run("TC-P-04 默认Helixline拉伸体", tc_p_04_default_extrude_helixline); // 自相交
|
|
// run("TC-P-05 圆形截面Polyline拉伸体", tc_p_05_circular_profile_extrude);
|
|
// run("TC-P-06 三角形截面Polyline拉伸体", tc_p_06_triangle_profile_extrude);
|
|
// run("TC-P-07 自定义螺旋线拉伸体", tc_p_07_custom_helixline_extrude); // 自相交
|
|
// run("TC-P-08 极端情况: 极小球", tc_p_08_degenerate_tiny_sphere);
|
|
|
|
//// ---- Part 2: 变换操作 ----
|
|
// std::cout << "--- Part 2: 变换操作测试 ---\n\n";
|
|
// run("TC-T-01 球体平移", tc_t_01_sphere_translation);
|
|
// run("TC-T-02 圆柱多轴平移", tc_t_02_cylinder_multi_axis_translation);
|
|
// run("TC-T-03 球体均匀缩放", tc_t_03_sphere_uniform_scale);
|
|
// run("TC-T-04 圆柱非均匀缩放", tc_t_04_cylinder_nonuniform_scale);
|
|
run("TC-T-05 绕X轴旋转90°", tc_t_05_rotation_90deg_x);
|
|
run("TC-T-06 绕Y轴旋转45°", tc_t_06_rotation_45deg_y);
|
|
//run("TC-T-07 组合变换(缩放→旋转→平移)", tc_t_07_combined_transform);
|
|
// run("TC-T-08 极端缩放(×100)", tc_t_08_large_scale);
|
|
//run("TC-T-09 四次90°旋转=恒等变换", tc_t_09_four_rotations_identity);
|
|
|
|
//// ---- Part 3: 布尔运算 (原有) ----
|
|
// std::cout << "--- Part 3: 布尔运算测试 (基础) ---\n\n";
|
|
// run("TC-B-01 球-球 并集(重叠)", tc_b_01_sphere_sphere_union);
|
|
// run("TC-B-02 球-球 交集(部分重叠)", tc_b_02_sphere_sphere_intersection);
|
|
// run("TC-B-03 球-球 差集", tc_b_03_sphere_sphere_difference);
|
|
// run("TC-B-04 球-圆柱 差集(钻孔)", tc_b_04_sphere_minus_cylinder_drill);
|
|
// run("TC-B-05 三球链式并集 (A∪B)∪C", tc_b_05_three_sphere_union_chain);
|
|
// run("TC-B-06 正交圆柱-圆柱 交集", tc_b_06_cylinder_cylinder_intersection);
|
|
//run("TC-B-07 拉伸体∪球(混合类型)", tc_b_07_extrude_union_sphere);
|
|
// run("TC-B-08 不相交球 交集(空集边界)", tc_b_08_disjoint_spheres_intersection);
|
|
// run("TC-B-09 包含关系球 差集(空集边界)", tc_b_09_contained_sphere_difference);
|
|
// run("TC-B-10 复杂四图元混合布尔树", tc_b_10_complex_four_primitive_tree);
|
|
|
|
//// ---- Part 4: Polyline 拉伸体扩展 ----
|
|
// std::cout << "--- Part 4: Polyline 拉伸体扩展测试 ---\n\n";
|
|
//run("TC-PE-01 五边形截面+直线Z轴", tc_pe_01_pentagon_profile_straight_z_axis);
|
|
// run("TC-PE-02 六边形截面+斜向轴", tc_pe_02_hexagon_profile_diagonal_axis);
|
|
// run("TC-PE-03 L形凹多边形截面", tc_pe_03_L_shape_concave_profile);
|
|
// run("TC-PE-04 正bulge圆弧截面(扇形)", tc_pe_04_arc_positive_bulge_profile);
|
|
// run("TC-PE-05 负bulge圆弧截面(内凹弧)", tc_pe_05_arc_negative_bulge_profile);
|
|
// run("TC-PE-06 锐角截面(细长菱形)", tc_pe_06_sharp_acute_angle_profile);
|
|
// run("TC-PE-07 矩形截面+L形折线轴", tc_pe_07_rectangular_profile_L_shape_axis);
|
|
// run("TC-PE-08 圆截面+Z形折线轴(多弯折)", tc_pe_08_circular_profile_Z_shape_axis);
|
|
// run("TC-PE-09 矩形截面+弧线轴", tc_pe_09_rectangular_profile_arc_axis);
|
|
// run("TC-PE-10 参数化多边形截面(N=3~8)", tc_pe_10_parametric_polygon_n_sides);
|
|
// run("TC-PE-11 高纵横比细长拉伸体", tc_pe_11_high_aspect_ratio_extrusion);
|
|
|
|
//// ---- Part 5: Helixline 拉伸体扩展 ---- // ERROR
|
|
// std::cout << "--- Part 5: Helixline 拉伸体扩展测试 ---\n\n";
|
|
//run("TC-HE-01 单圈螺旋+方形截面", tc_he_01_single_turn_square_profile);
|
|
// run("TC-HE-02 三圈螺旋+方形截面", tc_he_02_three_turns_square_profile);
|
|
// run("TC-HE-03 左旋螺旋", tc_he_03_left_handed_helix);
|
|
// run("TC-HE-04 密排螺旋(小节距)", tc_he_04_tight_pitch_helix);
|
|
// run("TC-HE-05 稀疏螺旋(大节距)", tc_he_05_large_pitch_helix);
|
|
// run("TC-HE-06 圆形截面螺旋弹簧", tc_he_06_circular_profile_helix_spring);
|
|
// run("TC-HE-07 三角形截面螺旋", tc_he_07_triangular_profile_helix);
|
|
// run("TC-HE-08 大半径螺旋", tc_he_08_large_radius_helix);
|
|
// run("TC-HE-09 参数化圈数(0.5/1/2/4圈)", tc_he_09_parametric_turns); // error
|
|
//run("TC-HE-10 螺旋体+缩放变换", tc_he_10_helix_with_scale_transform);
|
|
|
|
//// ---- Part 6: 布尔运算扩展 ----
|
|
// std::cout << "--- Part 6: 布尔运算扩展测试 ---\n\n";
|
|
// run("TC-BE-01 两Polyline拉伸体 UNION", tc_be_01_two_extrude_polyline_union); // 自相交
|
|
//run("TC-BE-02 两Polyline拉伸体 INTERSECTION", tc_be_02_two_extrude_polyline_intersection);
|
|
// run("TC-BE-03 拉伸体差集(槽口切割)", tc_be_03_extrude_difference_slot);
|
|
//run("TC-BE-04 螺旋拉伸体∪球(混合类型)", tc_be_04_helixline_extrude_union_sphere);
|
|
//run("TC-BE-05 圆柱-螺旋拉伸体(螺纹切割)", tc_be_05_cylinder_minus_helixline_thread); // error?
|
|
// run("TC-BE-06 三拉伸体链式并集(A∪B)∪C", tc_be_06_three_extrude_polyline_chain_union);
|
|
// run("TC-BE-07 布尔链 (Poly∪Sphere)-Cyl", tc_be_07_boolean_chain_union_then_difference);
|
|
// run("TC-BE-08 圆柱∪Polyline拉伸体(正交混合)", tc_be_08_cylinder_union_extrude_polyline);
|
|
// run("TC-BE-09 相切球(边界接触) UNION", tc_be_09_tangent_spheres_boundary);
|
|
// run("TC-BE-10 薄壁交集(近重合面)", tc_be_10_thin_wall_intersection);
|
|
//run("TC-BE-11 极端尺寸差异 UNION", tc_be_11_extreme_size_ratio_union);
|
|
// run("TC-BE-12 同心球壳(完全包含差集)", tc_be_12_concentric_sphere_shell);
|
|
//run("TC-BE-13 螺旋∩圆柱(螺纹嵌合)", tc_be_13_helixline_intersection_cylinder); // error?
|
|
// run("TC-BE-14 复杂5图元混合布尔树", tc_be_14_complex_five_primitive_tree); // error?
|
|
// run("TC-BE-15 完全重合图元 UNION(幂等性)", tc_be_15_identical_primitives_union);
|
|
// run("TC-BE-16 随机偏移压力测试(三种布尔运算)", tc_be_16_random_offset_all_boolean_ops);
|
|
//run("TC-BE-17 两螺旋线拉伸体差集", tc_be_17_two_helixlines_difference);
|
|
|
|
print_summary();
|
|
return (test_fw::g_fail > 0) ? 1 : 0;
|
|
}
|