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 76 additions and 1 deletions
Showing only changes of commit 0bbed9c0c3 - Show all commits

View File

@ -1,4 +1,4 @@
add_library(geopro_io_gpr STATIC IprHeader.cpp IprbReader.cpp) add_library(geopro_io_gpr STATIC IprHeader.cpp IprbReader.cpp GprGeometry.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)

View File

@ -0,0 +1,33 @@
#include "io/gpr/GprGeometry.hpp"
#include <sstream>
#include <string>
#include <vector>
namespace geopro::io::gpr {
std::vector<double> parseChannelXOffsets(const std::string& ordText) {
std::vector<double> offsets;
std::istringstream lines(ordText);
std::string line;
while (std::getline(lines, line)) {
std::istringstream tok(line);
std::vector<std::string> cols;
std::string col;
while (tok >> col) cols.push_back(col);
if (cols.size() < 4) continue; // 空行/列数不足,跳过
if (cols.back() != "1") continue; // 末列==1 才是有效通道
offsets.push_back(std::stod(cols[1]));
}
return offsets;
}
double depthOfSample(int s, const IprHeader& h) {
if (h.samples <= 1) return 0.0; // 防除零
const double timeNs = static_cast<double>(s) * h.timeWindowNs /
static_cast<double>(h.samples - 1);
const double timeSec = timeNs * 1e-9;
return h.soilVelocity * timeSec / 2.0;
}
} // namespace geopro::io::gpr

View File

@ -0,0 +1,20 @@
#ifndef GEOPRO_IO_GPR_GPRGEOMETRY_HPP
#define GEOPRO_IO_GPR_GPRGEOMETRY_HPP
#include <string>
#include <vector>
#include "io/gpr/IprHeader.hpp"
namespace geopro::io::gpr {
// 解析 .ord 文本,返回末列==1 的有效通道的横向偏移(第 2 列),按文件顺序。
std::vector<double> parseChannelXOffsets(const std::string& ordText);
// 采样序号 s → 深度(米)。depth = soilVelocity[m/s] * (s * timeWindowNs/(samples-1) * 1e-9) / 2。
// samples<=1 时返回 0 防除零。
double depthOfSample(int s, const IprHeader& h);
} // namespace geopro::io::gpr
#endif // GEOPRO_IO_GPR_GPRGEOMETRY_HPP

View File

@ -171,6 +171,7 @@ target_link_libraries(geopro_tests PRIVATE geopro_controller Qt6::Test)
# io/gpr .iprh + .iprb B-scan 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_sources(geopro_tests PRIVATE io/gpr/test_iprb_reader.cpp)
target_sources(geopro_tests PRIVATE io/gpr/test_gpr_geometry.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,21 @@
#include "io/gpr/GprGeometry.hpp"
#include "io/gpr/IprHeader.hpp"
#include <gtest/gtest.h>
using namespace geopro::io::gpr;
TEST(GprGeometry, ParsesActiveChannelOffsets) {
const std::string ord = "0 -0.686000 -1.5 1\n1 -0.581000 -1.5 1\n14 0 -1.5 0\n";
auto xs = parseChannelXOffsets(ord);
ASSERT_EQ(xs.size(), 2u); // 仅 2 个有效(末列=1)
EXPECT_NEAR(xs[0], -0.686, 1e-6);
EXPECT_NEAR(xs[1], -0.581, 1e-6);
}
TEST(GprGeometry, DepthOfLastSampleMatchesPhysics) {
IprHeader h{};
h.samples = 821;
h.timeWindowNs = 160.352;
h.soilVelocity = 1e8; // m/s
EXPECT_NEAR(depthOfSample(820, h), 8.0, 0.05); // ~8m
EXPECT_NEAR(depthOfSample(0, h), 0.0, 1e-9);
}