153 lines
4.7 KiB
C++
153 lines
4.7 KiB
C++
#include <gtest/gtest.h>
|
||
|
||
#include <vtkActor.h>
|
||
#include <vtkCamera.h>
|
||
#include <vtkConeSource.h>
|
||
#include <vtkPolyDataMapper.h>
|
||
#include <vtkRenderer.h>
|
||
#include <vtkSmartPointer.h>
|
||
|
||
#include "CameraPreset.hpp"
|
||
|
||
using namespace geopro::render;
|
||
|
||
namespace {
|
||
|
||
// 造一个带包围盒的 renderer(一个 cone actor),使 ResetCamera 有内容可重定位。
|
||
vtkSmartPointer<vtkRenderer> rendererWithContent() {
|
||
auto cone = vtkSmartPointer<vtkConeSource>::New();
|
||
cone->SetCenter(0, 0, 0);
|
||
cone->SetHeight(2.0);
|
||
cone->SetRadius(1.0);
|
||
auto mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
|
||
mapper->SetInputConnection(cone->GetOutputPort());
|
||
auto actor = vtkSmartPointer<vtkActor>::New();
|
||
actor->SetMapper(mapper);
|
||
auto r = vtkSmartPointer<vtkRenderer>::New();
|
||
r->AddActor(actor);
|
||
return r;
|
||
}
|
||
|
||
// 相机的视线方向单位向量 = focalPoint - position(归一化)。
|
||
void viewDir(vtkRenderer* r, double out[3]) {
|
||
auto* c = r->GetActiveCamera();
|
||
double p[3], f[3];
|
||
c->GetPosition(p);
|
||
c->GetFocalPoint(f);
|
||
double d[3] = {f[0] - p[0], f[1] - p[1], f[2] - p[2]};
|
||
double n = std::sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);
|
||
out[0] = d[0] / n; out[1] = d[1] / n; out[2] = d[2] / n;
|
||
}
|
||
|
||
} // namespace
|
||
|
||
// Top:相机在焦点上方(pos.z>focal.z),视线朝 -Z,viewUp=+Y。
|
||
TEST(CameraPreset, TopLooksDown) {
|
||
auto r = rendererWithContent();
|
||
applyView(r, ViewDir::Top);
|
||
auto* c = r->GetActiveCamera();
|
||
double p[3], f[3], up[3];
|
||
c->GetPosition(p); c->GetFocalPoint(f); c->GetViewUp(up);
|
||
EXPECT_GT(p[2], f[2]); // 相机在上方
|
||
double d[3]; viewDir(r, d);
|
||
EXPECT_NEAR(d[2], -1.0, 1e-6); // 视线向下
|
||
EXPECT_NEAR(up[1], 1.0, 1e-6); // 北朝上
|
||
}
|
||
|
||
// Bottom:相机在焦点下方,视线朝 +Z。
|
||
TEST(CameraPreset, BottomLooksUp) {
|
||
auto r = rendererWithContent();
|
||
applyView(r, ViewDir::Bottom);
|
||
auto* c = r->GetActiveCamera();
|
||
double p[3], f[3];
|
||
c->GetPosition(p); c->GetFocalPoint(f);
|
||
EXPECT_LT(p[2], f[2]);
|
||
double d[3]; viewDir(r, d);
|
||
EXPECT_NEAR(d[2], 1.0, 1e-6);
|
||
}
|
||
|
||
// Front:相机在 -Y,视线朝 +Y,viewUp=+Z。
|
||
TEST(CameraPreset, FrontLooksNorth) {
|
||
auto r = rendererWithContent();
|
||
applyView(r, ViewDir::Front);
|
||
auto* c = r->GetActiveCamera();
|
||
double p[3], f[3], up[3];
|
||
c->GetPosition(p); c->GetFocalPoint(f); c->GetViewUp(up);
|
||
EXPECT_LT(p[1], f[1]);
|
||
double d[3]; viewDir(r, d);
|
||
EXPECT_NEAR(d[1], 1.0, 1e-6);
|
||
EXPECT_NEAR(up[2], 1.0, 1e-6);
|
||
}
|
||
|
||
// Back:相机在 +Y,视线朝 -Y。
|
||
TEST(CameraPreset, BackLooksSouth) {
|
||
auto r = rendererWithContent();
|
||
applyView(r, ViewDir::Back);
|
||
double d[3]; viewDir(r, d);
|
||
EXPECT_NEAR(d[1], -1.0, 1e-6);
|
||
}
|
||
|
||
// Left:相机在 -X,视线朝 +X。
|
||
TEST(CameraPreset, LeftLooksEast) {
|
||
auto r = rendererWithContent();
|
||
applyView(r, ViewDir::Left);
|
||
auto* c = r->GetActiveCamera();
|
||
double p[3], f[3];
|
||
c->GetPosition(p); c->GetFocalPoint(f);
|
||
EXPECT_LT(p[0], f[0]);
|
||
double d[3]; viewDir(r, d);
|
||
EXPECT_NEAR(d[0], 1.0, 1e-6);
|
||
}
|
||
|
||
// Right:相机在 +X,视线朝 -X。
|
||
TEST(CameraPreset, RightLooksWest) {
|
||
auto r = rendererWithContent();
|
||
applyView(r, ViewDir::Right);
|
||
double d[3]; viewDir(r, d);
|
||
EXPECT_NEAR(d[0], -1.0, 1e-6);
|
||
}
|
||
|
||
// zoomBy(>1) 放大:透视下 vtkCamera::Zoom 收窄视角(ViewAngle 变小→画面放大)。
|
||
TEST(CameraPreset, ZoomInNarrowsViewAngle) {
|
||
auto r = rendererWithContent();
|
||
applyFree3D(r);
|
||
auto* c = r->GetActiveCamera();
|
||
const double before = c->GetViewAngle();
|
||
zoomBy(r, 1.2);
|
||
EXPECT_LT(c->GetViewAngle(), before);
|
||
}
|
||
|
||
// zoomBy(<1) 缩小:透视下视角变宽(画面缩小)。
|
||
TEST(CameraPreset, ZoomOutWidensViewAngle) {
|
||
auto r = rendererWithContent();
|
||
applyFree3D(r);
|
||
auto* c = r->GetActiveCamera();
|
||
const double before = c->GetViewAngle();
|
||
zoomBy(r, 1.0 / 1.2);
|
||
EXPECT_GT(c->GetViewAngle(), before);
|
||
}
|
||
|
||
// 正交投影下 zoomBy 改 parallelScale(放大缩小可视范围)。
|
||
TEST(CameraPreset, ZoomInOrthoReducesParallelScale) {
|
||
auto r = rendererWithContent();
|
||
applyView(r, ViewDir::Top); // Top 不改投影模式;显式打开正交
|
||
auto* c = r->GetActiveCamera();
|
||
c->ParallelProjectionOn();
|
||
r->ResetCamera();
|
||
const double before = c->GetParallelScale();
|
||
zoomBy(r, 2.0);
|
||
EXPECT_LT(c->GetParallelScale(), before);
|
||
}
|
||
|
||
// 空指针/非法 factor 安全。
|
||
TEST(CameraPreset, NullAndInvalidAreSafe) {
|
||
applyView(nullptr, ViewDir::Top);
|
||
zoomBy(nullptr, 1.2);
|
||
fitView(nullptr);
|
||
auto r = rendererWithContent();
|
||
const double before = r->GetActiveCamera()->GetDistance();
|
||
zoomBy(r, 0.0); // 非法 factor 忽略
|
||
zoomBy(r, -1.0);
|
||
EXPECT_DOUBLE_EQ(r->GetActiveCamera()->GetDistance(), before);
|
||
}
|