feat/vtk-3d-view #7

Merged
gaozheng merged 301 commits from feat/vtk-3d-view into main 2026-06-27 18:43:52 +08:00
5 changed files with 102 additions and 2 deletions
Showing only changes of commit 0d7f646941 - Show all commits

View File

@ -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)

37
src/io/gpr/IprbReader.cpp Normal file
View File

@ -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

25
src/io/gpr/IprbReader.hpp Normal file
View File

@ -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-scantraces = 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

View File

@ -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

View File

@ -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);
}