geopro/tests/render/test_slice_plane_math.cpp

137 lines
5.8 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <gtest/gtest.h>
#include <cmath>
#include <vector>
#include "interact/SlicePlaneMath.hpp"
using namespace geopro::render::interact;
namespace {
void expectVec(const Vec3& a, double x, double y, double z, double eps = 1e-9) {
EXPECT_NEAR(a[0], x, eps);
EXPECT_NEAR(a[1], y, eps);
EXPECT_NEAR(a[2], z, eps);
}
} // namespace
// ── axisNormal轴向法向spec F22F24+ 任意 45°F25──
TEST(SlicePlaneMath, AxisNormalUpDownIsZ) { expectVec(axisNormal(SliceAxis::UpDown), 0, 0, 1); }
TEST(SlicePlaneMath, AxisNormalFrontBackIsY) { expectVec(axisNormal(SliceAxis::FrontBack), 0, 1, 0); }
TEST(SlicePlaneMath, AxisNormalLeftRightIsX) { expectVec(axisNormal(SliceAxis::LeftRight), 1, 0, 0); }
TEST(SlicePlaneMath, AxisNormalObliqueIs45) {
const auto n = axisNormal(SliceAxis::Oblique);
const double s = std::sqrt(0.5);
expectVec(n, s, 0, s);
EXPECT_NEAR(norm(n), 1.0, 1e-9); // 单位向量
}
// ── boundsCenter ──
TEST(SlicePlaneMath, BoundsCenter) {
expectVec(boundsCenter({0, 10, -4, 4, 0, 6}), 5, 0, 3);
}
// ── advanceOrigin沿法向平移滚轮推进D46──
TEST(SlicePlaneMath, AdvanceAlongZ) {
expectVec(advanceOrigin({1, 2, 3}, {0, 0, 1}, 5.0), 1, 2, 8);
}
TEST(SlicePlaneMath, AdvanceBackward) {
expectVec(advanceOrigin({1, 2, 3}, {0, 0, 1}, -2.0), 1, 2, 1);
}
TEST(SlicePlaneMath, AdvanceNormalizesDirection) {
// 非单位法向:先归一化再推进,步长为世界距离。
expectVec(advanceOrigin({0, 0, 0}, {0, 0, 5}, 3.0), 0, 0, 3);
}
TEST(SlicePlaneMath, AdvanceObliqueMovesAlong45) {
const auto o = advanceOrigin({0, 0, 0}, {1, 0, 1}, std::sqrt(2.0));
expectVec(o, 1, 0, 1); // 沿 45° 推进 √2 → (1,0,1)
}
// ── clampToBounds推进出体外被夹回滚轮限位──
TEST(SlicePlaneMath, ClampInsideUnchanged) {
expectVec(clampToBounds({5, 0, 3}, {0, 10, -4, 4, 0, 6}), 5, 0, 3);
}
TEST(SlicePlaneMath, ClampOutsideHigh) {
expectVec(clampToBounds({5, 0, 99}, {0, 10, -4, 4, 0, 6}), 5, 0, 6);
}
TEST(SlicePlaneMath, ClampOutsideLow) {
expectVec(clampToBounds({-5, 0, -1}, {0, 10, -4, 4, 0, 6}), 0, 0, 0);
}
// ── faceOnCamera双击正视E54──
// 法向 +Y相机退到 focal+Y*dist视线 = -YviewUp = +Z切面内向上
TEST(SlicePlaneMath, FaceOnFrontBackNormal) {
const auto cam = faceOnCamera({0, 0, 0}, {0, 1, 0}, 10.0);
expectVec(cam.position, 0, 10, 0);
// viewUp 与法向正交且偏 +Z。
EXPECT_NEAR(dot(cam.viewUp, Vec3{0, 1, 0}), 0.0, 1e-9);
EXPECT_GT(cam.viewUp[2], 0.5);
}
// 法向 +Xposition=focal+X*distviewUp 偏 +Z。
TEST(SlicePlaneMath, FaceOnLeftRightNormal) {
const auto cam = faceOnCamera({1, 2, 3}, {1, 0, 0}, 5.0);
expectVec(cam.position, 6, 2, 3);
EXPECT_NEAR(dot(cam.viewUp, Vec3{1, 0, 0}), 0.0, 1e-9);
EXPECT_GT(cam.viewUp[2], 0.5);
}
// 法向竖直 +Z上下切片viewUp 不能再取 +Z与法向共线兜底取 +Y。
TEST(SlicePlaneMath, FaceOnVerticalNormalFallsBackToY) {
const auto cam = faceOnCamera({0, 0, 0}, {0, 0, 1}, 8.0);
expectVec(cam.position, 0, 0, 8);
// viewUp 与法向(+Z)正交z≈0且非零。
EXPECT_NEAR(cam.viewUp[2], 0.0, 1e-9);
EXPECT_NEAR(norm(cam.viewUp), 1.0, 1e-9);
}
// 法向竖直 -Z 同样兜底。
TEST(SlicePlaneMath, FaceOnVerticalDownNormalFallsBack) {
const auto cam = faceOnCamera({0, 0, 0}, {0, 0, -1}, 4.0);
expectVec(cam.position, 0, 0, -4);
EXPECT_NEAR(cam.viewUp[2], 0.0, 1e-9);
EXPECT_NEAR(norm(cam.viewUp), 1.0, 1e-9);
}
// 非单位法向position 用归一化法向 → 距焦点恰为 dist。
TEST(SlicePlaneMath, FaceOnNormalizesNormal) {
const auto cam = faceOnCamera({0, 0, 0}, {0, 3, 0}, 6.0);
expectVec(cam.position, 0, 6, 0);
}
// ── wheelStep步长 = 沿法向体素间距 × voxels × 方向spacing=三轴间距X法向取X间距──
TEST(SlicePlaneMath, WheelStepForwardPositive) {
EXPECT_GT(wheelStep({0.1, 0.1, 0.05}, {1, 0, 0}, 2, +1), 0.0);
}
TEST(SlicePlaneMath, WheelStepBackwardNegative) {
EXPECT_LT(wheelStep({0.1, 0.1, 0.05}, {1, 0, 0}, 2, -1), 0.0);
}
TEST(SlicePlaneMath, WheelStepScalesWithVoxels) {
const double fine = wheelStep({0.1, 0.1, 0.05}, {1, 0, 0}, 1, 1);
const double coarse = wheelStep({0.1, 0.1, 0.05}, {1, 0, 0}, 10, 1);
EXPECT_GT(coarse, fine); // voxels 越大步长越大(Shift 粗调)
}
// 只取法向那条轴的【间距】(非总长):长轴间距大也不影响 Z 法向步长1 体素 = Z 间距 0.05。
TEST(SlicePlaneMath, WheelStepUsesNormalAxisSpacing) {
const double zStep = wheelStep({100.0, 0.1, 0.05}, {0, 0, 1}, 1, 1); // Z 法向 → 取 Z 间距 0.05
EXPECT_NEAR(zStep, 0.05, 1e-9); // 与 X 间距 100 无关
}
// ── nearestPlane找点所在切片按到平面距离最小──
TEST(SlicePlaneMath, NearestPlaneEmptyIsMinusOne) {
EXPECT_EQ(nearestPlane({}, {}, {0, 0, 0}), -1);
}
TEST(SlicePlaneMath, NearestPlanePicksClosest) {
// 两张水平切片 z=0 与 z=10法向 +Z点 z=8 → 更近 z=10索引 1
std::vector<Vec3> centers{{0, 0, 0}, {0, 0, 10}};
std::vector<Vec3> normals{{0, 0, 1}, {0, 0, 1}};
EXPECT_EQ(nearestPlane(centers, normals, {5, 5, 8}), 1);
EXPECT_EQ(nearestPlane(centers, normals, {5, 5, 2}), 0);
}
TEST(SlicePlaneMath, NearestPlaneIgnoresInPlaneOffset) {
// 单张 z=0 水平面:点无论 x/y 多远,只要 z=0 距离为 0 → 命中。
std::vector<Vec3> centers{{0, 0, 0}};
std::vector<Vec3> normals{{0, 0, 1}};
EXPECT_EQ(nearestPlane(centers, normals, {999, -999, 0}), 0);
}
// ── 向量工具 ──
TEST(SlicePlaneMath, NormalizeZeroFallsBack) { expectVec(normalize({0, 0, 0}), 0, 0, 1); }
TEST(SlicePlaneMath, CrossBasic) { expectVec(cross({1, 0, 0}, {0, 1, 0}), 0, 0, 1); }