geopro/tests/render/test_camera_preset.cpp

153 lines
4.7 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 <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),视线朝 -ZviewUp=+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视线朝 +YviewUp=+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);
}