93 lines
4.6 KiB
C++
93 lines
4.6 KiB
C++
#include <gtest/gtest.h>
|
||
#include "core/algo/GprVolumeBuilder.hpp"
|
||
#include "io/gpr/RadarVolumeAssembler.hpp"
|
||
|
||
using geopro::io::gpr::RadarCubeDesc;
|
||
using geopro::io::gpr::assembleRadarVolume;
|
||
|
||
// 2 道 × 3 通道 × 4 采样,值 = 100*c + 10*t + s。不插值(chXOffsets 空)、coarse=1。
|
||
TEST(RadarVolumeAssembler, AxisMapAndQuantRoundTrip) {
|
||
RadarCubeDesc d;
|
||
d.channels = 3; d.traces = 2; d.samples = 4;
|
||
d.dxBase = 0.1; d.dyWhenNotInterpolated = 0.5; d.dz = 0.05;
|
||
auto sampler = [](int c, int t, int s) { return 100.0 * c + 10.0 * t + s; };
|
||
|
||
const geopro::core::BuiltI16 b = assembleRadarVolume(d, sampler, /*coarse=*/1, /*targetDy=*/0.0);
|
||
|
||
EXPECT_EQ(b.vol.nx(), 2); // 道
|
||
EXPECT_EQ(b.vol.ny(), 3); // 通道(未插值=原通道数)
|
||
EXPECT_EQ(b.vol.nz(), 4); // 采样
|
||
EXPECT_DOUBLE_EQ(b.spacing[0], 0.1);
|
||
EXPECT_DOUBLE_EQ(b.spacing[1], 0.5);
|
||
EXPECT_DOUBLE_EQ(b.spacing[2], 0.05);
|
||
EXPECT_NEAR(b.vminPhys, 0.0, 1e-9); // c0,t0,s0
|
||
EXPECT_NEAR(b.vmaxPhys, 213.0, 1e-9); // c2,t1,s3 = 200+10+3
|
||
// 反量化对位:体素(道 t=1, 通道 c=2, 采样 s=3) 应≈213(量化误差内)。
|
||
const double recon = b.quant.toPhys(b.vol.at(1, 2, 3));
|
||
EXPECT_NEAR(recon, 213.0, b.quant.scale);
|
||
}
|
||
|
||
// coarse=2:4 道 → nxOut=2,dx×2。
|
||
TEST(RadarVolumeAssembler, CoarseDownsamplesTracesAndScalesDx) {
|
||
RadarCubeDesc d;
|
||
d.channels = 1; d.traces = 4; d.samples = 2; d.dxBase = 0.1;
|
||
auto sampler = [](int, int t, int s) { return 10.0 * t + s; };
|
||
const geopro::core::BuiltI16 b = assembleRadarVolume(d, sampler, /*coarse=*/2, 0.0);
|
||
EXPECT_EQ(b.vol.nx(), 2);
|
||
EXPECT_DOUBLE_EQ(b.spacing[0], 0.2);
|
||
EXPECT_NEAR(b.quant.toPhys(b.vol.at(1, 0, 0)), 20.0, b.quant.scale); // 输出道1 = 源道2
|
||
}
|
||
|
||
// ── 合成靶标:在【装配出的体】里验通道插值的几何忠实度 ──────────────────────
|
||
// 现有 test_gpr_geometry 只验 planChannelInterpolation 的【行规划】;这两个测试验
|
||
// assembleRadarVolume 把规划【应用到体】是否正确——即用户要判断的"通道插值在体里
|
||
// 对不对、会不会造缝"。
|
||
// 布局:3 通道偏移 {0, 0.10, 0.20},targetDy=0.05 → ny=round(0.2/0.05)+1=5:
|
||
// 行 j0=ch0 / j1=blend(ch0,ch1,0.5) / j2=ch1 / j3=blend(ch1,ch2,0.5) / j4=ch2。
|
||
namespace {
|
||
RadarCubeDesc make3ChDesc() {
|
||
RadarCubeDesc d;
|
||
d.channels = 3; d.traces = 2; d.samples = 3;
|
||
d.dxBase = 0.1; d.dz = 0.05;
|
||
d.chXOffsets = {0.0, 0.10, 0.20}; // 触发通道插值
|
||
return d;
|
||
}
|
||
} // namespace
|
||
|
||
// 平层反射(同一深度 s=2 全通道等值 500)穿过通道插值后【全部行仍等于 500】——
|
||
// 不出现"插值行衰减/锯齿/横向缝"(用户最担心的 10cm 缝就是这条若失败)。
|
||
TEST(RadarVolumeAssembler, FlatReflectorStaysFlatAcrossInterpolatedRows) {
|
||
const RadarCubeDesc d = make3ChDesc();
|
||
// s==2:平层反射(全通道 500);s==0:逐通道阶梯(ch0=100/ch1=200/ch2=300)验混合;其余 0。
|
||
auto sampler = [](int c, int /*t*/, int s) {
|
||
if (s == 2) return 500.0;
|
||
if (s == 0) return 100.0 * (c + 1);
|
||
return 0.0;
|
||
};
|
||
const geopro::core::BuiltI16 b = assembleRadarVolume(d, sampler, /*coarse=*/1, /*targetDy=*/0.05);
|
||
ASSERT_EQ(b.vol.ny(), 5); // 3 通道 → 5 行(含 2 条插值)
|
||
ASSERT_EQ(b.vol.nx(), 2);
|
||
ASSERT_EQ(b.vol.nz(), 3);
|
||
EXPECT_DOUBLE_EQ(b.spacing[1], 0.05); // 插值后 dy=targetDy
|
||
// 平层在【每一行、每一道】都应保持 500(插值不破坏横向连续)。
|
||
for (int j = 0; j < b.vol.ny(); ++j)
|
||
for (int to = 0; to < b.vol.nx(); ++to)
|
||
EXPECT_NEAR(b.quant.toPhys(b.vol.at(to, j, 2)), 500.0, b.quant.scale)
|
||
<< "行 j=" << j << " 道 to=" << to << " 处平层被插值破坏";
|
||
}
|
||
|
||
// 插值行 = 相邻两通道的正确线性混合(j1 在 ch0=100/ch1=200 之间 wb=0.5 → 150);
|
||
// 纯通道行 = 原通道值(j0=100 / j2=200 / j4=300)。验"插值没造假峰、没错位"。
|
||
TEST(RadarVolumeAssembler, InterpolatedRowIsCorrectLinearBlend) {
|
||
const RadarCubeDesc d = make3ChDesc();
|
||
auto sampler = [](int c, int /*t*/, int s) { return s == 0 ? 100.0 * (c + 1) : 0.0; };
|
||
const geopro::core::BuiltI16 b = assembleRadarVolume(d, sampler, /*coarse=*/1, /*targetDy=*/0.05);
|
||
ASSERT_EQ(b.vol.ny(), 5);
|
||
const double tol = b.quant.scale;
|
||
EXPECT_NEAR(b.quant.toPhys(b.vol.at(0, 0, 0)), 100.0, tol); // j0 = ch0
|
||
EXPECT_NEAR(b.quant.toPhys(b.vol.at(0, 1, 0)), 150.0, tol); // j1 = blend(100,200,0.5)
|
||
EXPECT_NEAR(b.quant.toPhys(b.vol.at(0, 2, 0)), 200.0, tol); // j2 = ch1
|
||
EXPECT_NEAR(b.quant.toPhys(b.vol.at(0, 3, 0)), 250.0, tol); // j3 = blend(200,300,0.5)
|
||
EXPECT_NEAR(b.quant.toPhys(b.vol.at(0, 4, 0)), 300.0, tol); // j4 = ch2
|
||
}
|