feat/vtk-3d-view #7
|
|
@ -1,4 +1,4 @@
|
||||||
add_library(geopro_io_gpr STATIC IprHeader.cpp)
|
add_library(geopro_io_gpr STATIC IprHeader.cpp IprbReader.cpp)
|
||||||
target_include_directories(geopro_io_gpr PUBLIC ${CMAKE_SOURCE_DIR}/src)
|
target_include_directories(geopro_io_gpr PUBLIC ${CMAKE_SOURCE_DIR}/src)
|
||||||
target_compile_features(geopro_io_gpr PUBLIC cxx_std_17)
|
target_compile_features(geopro_io_gpr PUBLIC cxx_std_17)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
#include "io/gpr/IprbReader.hpp"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <fstream>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace geopro::io::gpr {
|
||||||
|
|
||||||
|
BScan readIprb(const std::string& path, const IprHeader& h) {
|
||||||
|
std::ifstream f(path, std::ios::binary | std::ios::ate);
|
||||||
|
if (!f) {
|
||||||
|
throw std::runtime_error("readIprb: 无法打开文件: " + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::streamsize fileSize = f.tellg();
|
||||||
|
const long traces = h.lastTrace + 1;
|
||||||
|
const long count = static_cast<long>(h.samples) * traces;
|
||||||
|
const std::streamsize expected = static_cast<std::streamsize>(count) * 2;
|
||||||
|
if (fileSize != expected) {
|
||||||
|
throw std::runtime_error("readIprb: 文件大小与 samples*traces*2 不符: " + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
BScan b;
|
||||||
|
b.samples = h.samples;
|
||||||
|
b.traces = traces;
|
||||||
|
b.data.resize(static_cast<std::size_t>(count));
|
||||||
|
|
||||||
|
f.seekg(0, std::ios::beg);
|
||||||
|
f.read(reinterpret_cast<char*>(b.data.data()), expected);
|
||||||
|
if (!f) {
|
||||||
|
throw std::runtime_error("readIprb: 读取数据失败: " + path);
|
||||||
|
}
|
||||||
|
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace geopro::io::gpr
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef GEOPRO_IO_GPR_IPRBREADER_HPP
|
||||||
|
#define GEOPRO_IO_GPR_IPRBREADER_HPP
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "io/gpr/IprHeader.hpp"
|
||||||
|
|
||||||
|
namespace geopro::io::gpr {
|
||||||
|
|
||||||
|
// 一个通道一条测线的雷达 B-scan 剖面(int16 存储,布局 [trace*samples + s],s 最快)。
|
||||||
|
struct BScan {
|
||||||
|
int samples = 0;
|
||||||
|
long traces = 0;
|
||||||
|
std::vector<int16_t> data; // 大小 = samples*traces
|
||||||
|
};
|
||||||
|
|
||||||
|
// 读取 .iprb 二进制 B-scan:traces = h.lastTrace+1;
|
||||||
|
// 校验 samples*traces*2 == 文件字节数,不符抛 std::runtime_error;文件打不开抛 std::runtime_error。
|
||||||
|
BScan readIprb(const std::string& path, const IprHeader& h);
|
||||||
|
|
||||||
|
} // namespace geopro::io::gpr
|
||||||
|
|
||||||
|
#endif // GEOPRO_IO_GPR_IPRBREADER_HPP
|
||||||
|
|
@ -168,8 +168,9 @@ target_sources(geopro_tests PRIVATE controller/test_workbench_nav_controller.cpp
|
||||||
target_sources(geopro_tests PRIVATE controller/test_vtk_scene_controller.cpp)
|
target_sources(geopro_tests PRIVATE controller/test_vtk_scene_controller.cpp)
|
||||||
target_link_libraries(geopro_tests PRIVATE geopro_controller Qt6::Test)
|
target_link_libraries(geopro_tests PRIVATE geopro_controller Qt6::Test)
|
||||||
|
|
||||||
# io/gpr 层:.iprh 头解析(纯 C++17,零 Qt/VTK)。
|
# io/gpr 层:.iprh 头解析 + .iprb B-scan 读取(纯 C++17,零 Qt/VTK)。
|
||||||
target_sources(geopro_tests PRIVATE io/gpr/test_ipr_header.cpp)
|
target_sources(geopro_tests PRIVATE io/gpr/test_ipr_header.cpp)
|
||||||
|
target_sources(geopro_tests PRIVATE io/gpr/test_iprb_reader.cpp)
|
||||||
target_link_libraries(geopro_tests PRIVATE geopro_io_gpr)
|
target_link_libraries(geopro_tests PRIVATE geopro_io_gpr)
|
||||||
|
|
||||||
add_subdirectory(spike) # spike S3: banded contour 渲染验证
|
add_subdirectory(spike) # spike S3: banded contour 渲染验证
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
#include "io/gpr/IprbReader.hpp"
|
||||||
|
#include "io/gpr/IprHeader.hpp"
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <cstdio>
|
||||||
|
namespace {
|
||||||
|
std::string writeTmp(const std::vector<int16_t>& v) {
|
||||||
|
std::string p = std::tmpnam(nullptr);
|
||||||
|
std::ofstream f(p, std::ios::binary);
|
||||||
|
f.write(reinterpret_cast<const char*>(v.data()),
|
||||||
|
static_cast<std::streamsize>(v.size()*sizeof(int16_t)));
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
using namespace geopro::io::gpr;
|
||||||
|
TEST(IprbReader, ReadsInt16AndLayout) {
|
||||||
|
std::vector<int16_t> raw{0,1,2, 10,11,12, 20,21,22, 30,31,32}; // 4 道×3 采样
|
||||||
|
auto path = writeTmp(raw);
|
||||||
|
IprHeader h{}; h.samples = 3; h.lastTrace = 3; // traces = 4
|
||||||
|
auto b = readIprb(path, h);
|
||||||
|
EXPECT_EQ(b.samples, 3);
|
||||||
|
EXPECT_EQ(b.traces, 4);
|
||||||
|
EXPECT_EQ(b.data.size(), 12u);
|
||||||
|
EXPECT_EQ(b.data[1*3 + 2], 12); // 第1道第2采样
|
||||||
|
std::remove(path.c_str());
|
||||||
|
}
|
||||||
|
TEST(IprbReader, ThrowsOnSizeMismatch) {
|
||||||
|
std::vector<int16_t> raw{0,1,2,3,4}; // 5 个,与 samples*traces 不符
|
||||||
|
auto path = writeTmp(raw);
|
||||||
|
IprHeader h{}; h.samples = 3; h.lastTrace = 3; // 期望 12
|
||||||
|
EXPECT_THROW(readIprb(path, h), std::runtime_error);
|
||||||
|
std::remove(path.c_str());
|
||||||
|
}
|
||||||
|
TEST(IprbReader, ThrowsOnMissingFile) {
|
||||||
|
IprHeader h{}; h.samples = 3; h.lastTrace = 3;
|
||||||
|
EXPECT_THROW(readIprb("____no_such_file____.iprb", h), std::runtime_error);
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue