geopro/tests/io/gpr/test_radar_volume_assembler...

93 lines
4.6 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 "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=24 道 → nxOut=2dx×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
}