feat(radar): 规范化体 bridge buildLineVolumeFromNormalized

将 RadarVolumeAssembler.cpp 从 geopro_gpr3dv_bridge 迁入纯 geopro_io_gpr,
避免 io_gpr 反链 bridge 形成循环依赖。新增 NormalizedRadarVolumeBridge
组合 reader(.head/.data) + assembleRadarVolume → BuiltI16(X=道/Y=通道/Z=采样)。
This commit is contained in:
gaozheng 2026-06-29 12:46:08 +08:00
parent d2e7314ffb
commit 241319b84b
5 changed files with 107 additions and 2 deletions

View File

@ -1,6 +1,7 @@
add_library(geopro_io_gpr STATIC
IprHeader.cpp IprbReader.cpp GprGeometry.cpp GprSurveyAssembler.cpp
GpsTrack.cpp NormalizedRadarReader.cpp)
GpsTrack.cpp NormalizedRadarReader.cpp
RadarVolumeAssembler.cpp NormalizedRadarVolumeBridge.cpp)
target_include_directories(geopro_io_gpr PUBLIC ${CMAKE_SOURCE_DIR}/src)
target_compile_features(geopro_io_gpr PUBLIC cxx_std_17)
# GprSurveyAssembler geopro::core::GprSurvey include
@ -16,7 +17,6 @@ set_target_properties(geopro_io_gpr PROPERTIES AUTOMOC OFF AUTOUIC OFF AUTORCC O
# GpsTrack(geopro_io_gpr) .gps
add_library(geopro_gpr3dv_bridge STATIC
Gpr3dvVolumeBridge.cpp
RadarVolumeAssembler.cpp
Gpr3dvSurveyVolumeBridge.cpp)
target_include_directories(geopro_gpr3dv_bridge PUBLIC ${CMAKE_SOURCE_DIR}/src)
target_compile_features(geopro_gpr3dv_bridge PUBLIC cxx_std_17)

View File

@ -0,0 +1,55 @@
#include "io/gpr/NormalizedRadarVolumeBridge.hpp"
#include <cstddef>
#include <cstdint>
#include <fstream>
#include <sstream>
#include <stdexcept>
#include <vector>
#include "io/gpr/NormalizedRadarReader.hpp"
#include "io/gpr/RadarVolumeAssembler.hpp"
namespace geopro::io::gpr {
geopro::core::BuiltI16 buildLineVolumeFromNormalized(const std::string& lineDir,
const std::string& linePrefix,
int coarse, double targetDy) {
const std::string head = lineDir + "/" + linePrefix + ".head";
const std::string data = lineDir + "/" + linePrefix + ".data";
std::string headText;
{
std::ifstream f(head);
if (!f) throw std::runtime_error("打开 .head 失败: " + head);
std::stringstream ss;
ss << f.rdbuf();
headText = ss.str();
}
const RadarHeader h = parseRadarHead(headText);
const std::vector<std::int16_t> cube = readRadarDataCube(data, h);
const int M = h.channels;
const int N = h.samples;
RadarCubeDesc d;
d.channels = M;
d.traces = h.traces;
d.samples = N;
d.chXOffsets = h.chXOffsets;
d.dxBase = h.distanceInterval > 1e-9 ? h.distanceInterval : 1.0;
d.dyWhenNotInterpolated =
(h.chXOffsets.size() >= 2 && M > 1)
? (h.chXOffsets.back() - h.chXOffsets.front()) / (M - 1)
: 1.0;
d.dz = depthSpacingZ(h) > 1e-12 ? depthSpacingZ(h) : 1.0;
// position-major 立方体索引 ((t*M + c)*N + s),与 readRadarDataCube 一致。
CubeSampler sample = [&cube, M, N](int c, int t, int s) {
return static_cast<double>(cube[(static_cast<std::size_t>(t) * M + c) * N + s]);
};
return assembleRadarVolume(d, sample, coarse, targetDy);
}
} // namespace geopro::io::gpr

View File

@ -0,0 +1,20 @@
#ifndef GEOPRO_IO_GPR_NORMALIZED_RADAR_VOLUME_BRIDGE_HPP
#define GEOPRO_IO_GPR_NORMALIZED_RADAR_VOLUME_BRIDGE_HPP
#include <string>
#include "core/algo/GprVolumeBuilder.hpp" // geopro::core::BuiltI16
namespace geopro::io::gpr {
// 读 {lineDir}/{linePrefix}.head + .data → assembleRadarVolume → BuiltI16
// (轴 X=道/Y=通道/Z=采样)。coarse 沿道下采样targetDy 线内通道插值(读 .head
// CH_X_OFFSETS)。打开/解析失败抛 std::runtime_error。
geopro::core::BuiltI16 buildLineVolumeFromNormalized(const std::string& lineDir,
const std::string& linePrefix,
int coarse = 4,
double targetDy = 0.025);
} // namespace geopro::io::gpr
#endif // GEOPRO_IO_GPR_NORMALIZED_RADAR_VOLUME_BRIDGE_HPP

View File

@ -228,6 +228,8 @@ target_sources(geopro_tests PRIVATE io/gpr/test_gpr_survey_assembler.cpp)
target_sources(geopro_tests PRIVATE io/gpr/test_gps_track.cpp)
# NormalizedRadarReader .head(KEY:VALUE) 解析(维度/字节序/通道偏移/波速/深度间距,纯 C++17)
target_sources(geopro_tests PRIVATE io/gpr/test_normalized_radar_reader.cpp)
# NormalizedRadarVolumeBridge reader(.head/.data) + assembleRadarVolume BuiltI16( X=道/Y=通道/Z=采样)
target_sources(geopro_tests PRIVATE io/gpr/test_normalized_radar_bridge.cpp)
target_link_libraries(geopro_tests PRIVATE geopro_io_gpr)
# Gpr3dvVolumeBridge(P2)gpr3dv geopro 量化体( X=道/Y=通道/Z=样本)

View File

@ -0,0 +1,28 @@
#include <gtest/gtest.h>
#include <cstdint>
#include <filesystem>
#include <fstream>
#include "core/algo/GprVolumeBuilder.hpp"
#include "io/gpr/NormalizedRadarVolumeBridge.hpp"
namespace fs = std::filesystem;
TEST(NormalizedRadarBridge, BuildsVolumeWithExpectedAxes) {
// K=4 道, M=2 通道, N=3 采样, 无通道偏移(不插值), coarse=1。
fs::path dir = fs::temp_directory_path() / "radar_bridge_test";
fs::create_directories(dir);
{ std::ofstream f(dir / "L.head");
f << "SAMPLES:3\nNUMBER_OF_CH:2\nLAST_TRACE:8\nBITS:16\nENDIAN_TYPE:1\n"
"DISTANCE_INTERVAL:0.1\nTIMEWINDOW:30\nDIELECTRIC:9\n"; }
{ std::ofstream f(dir / "L.data", std::ios::binary);
for (int t = 0; t < 4; ++t) for (int c = 0; c < 2; ++c) for (int s = 0; s < 3; ++s) {
std::int16_t v = static_cast<std::int16_t>(t * 10 + c * 100 + s);
f.write(reinterpret_cast<const char*>(&v), 2); } }
const auto b = geopro::io::gpr::buildLineVolumeFromNormalized(
(dir).string(), "L", /*coarse=*/1, /*targetDy=*/0.0); // targetDy=0 不插值
EXPECT_EQ(b.vol.nx(), 4); // 道
EXPECT_EQ(b.vol.ny(), 2); // 通道
EXPECT_EQ(b.vol.nz(), 3); // 采样
EXPECT_DOUBLE_EQ(b.spacing[0], 0.1); // dx=DISTANCE_INTERVAL
EXPECT_GT(b.spacing[2], 0.0); // dz 由 timewindow/dielectric 求得 >0
EXPECT_NEAR(b.quant.toPhys(b.vol.at(3, 1, 2)), 132.0, b.quant.scale); // t3c1s2=30+100+2
}