88 lines
3.6 KiB
C++
88 lines
3.6 KiB
C++
#include "io/gpr/GprSurveyAssembler.hpp"
|
|
#include <gtest/gtest.h>
|
|
#include <fstream>
|
|
#include <filesystem>
|
|
#include <cstdint>
|
|
#include <stdexcept>
|
|
#include <vector>
|
|
using namespace geopro::io::gpr;
|
|
namespace {
|
|
void writeText(const std::string& p, const std::string& s) {
|
|
std::ofstream f(p);
|
|
f << s;
|
|
}
|
|
void writeI16(const std::string& p, const std::vector<int16_t>& v) {
|
|
std::ofstream f(p, std::ios::binary);
|
|
f.write(reinterpret_cast<const char*>(v.data()),
|
|
static_cast<std::streamsize>(v.size() * sizeof(int16_t)));
|
|
}
|
|
// samples=2, lastTrace=1 -> traces=2; CHANNELS 仅供头解析,不影响装配。
|
|
const char* HDR =
|
|
"SAMPLES: 2\nLAST TRACE: 1\nCHANNELS: 2\nTIMEWINDOW: 4.0\n"
|
|
"SOIL VELOCITY: 100.000000\nDISTANCE INTERVAL: 0.05\n";
|
|
} // namespace
|
|
|
|
TEST(GprSurveyAssembler, AssemblesTwoChannels) {
|
|
auto d = (std::filesystem::temp_directory_path() / "gpr_asm").string();
|
|
std::filesystem::create_directories(d);
|
|
// 通道 A(横偏 1.0, 值 10,11, 12,13), 通道 B(横偏 0.0, 值 20..23)。
|
|
// B 的 Y 更小, 用于验证按 Y 升序重排。
|
|
writeText(d + "/A.iprh", HDR);
|
|
writeI16(d + "/A.iprb", {10, 11, 12, 13}); // [trace*samples+s]
|
|
writeText(d + "/B.iprh", HDR);
|
|
writeI16(d + "/B.iprb", {20, 21, 22, 23});
|
|
writeText(d + "/x.ord", "0 1.0 -1.5 1\n1 0.0 -1.5 1\n"); // A->1.0, B->0.0
|
|
|
|
auto s = assembleGprSurvey({d + "/A.iprb", d + "/B.iprb"}, d + "/x.ord");
|
|
|
|
EXPECT_EQ(s.samples, 2);
|
|
EXPECT_EQ(s.ntraces, 2);
|
|
EXPECT_NEAR(s.x0, 0.0, 1e-9);
|
|
EXPECT_NEAR(s.z0, 0.0, 1e-9);
|
|
EXPECT_NEAR(s.dx, 0.05, 1e-9);
|
|
// depthOfSample(1,h) = 1e8 * (1 * 4/(2-1) * 1e-9) / 2 = 0.2
|
|
EXPECT_NEAR(s.dz, 0.2, 1e-6);
|
|
ASSERT_EQ(s.channelY.size(), 2u);
|
|
EXPECT_NEAR(s.channelY[0], 0.0, 1e-9); // 升序: B(0.0) 在前
|
|
EXPECT_NEAR(s.channelY[1], 1.0, 1e-9); // A(1.0) 在后
|
|
// 升序后通道0=B, 通道1=A
|
|
EXPECT_NEAR(s.at(0, 0, 0), 20.0, 1e-9); // B 的 (t0,s0)
|
|
EXPECT_NEAR(s.at(0, 1, 1), 23.0, 1e-9); // B 的 (t1,s1)
|
|
EXPECT_NEAR(s.at(1, 0, 0), 10.0, 1e-9); // A 的 (t0,s0)
|
|
EXPECT_NEAR(s.at(1, 1, 1), 13.0, 1e-9); // A 的 (t1,s1)
|
|
std::filesystem::remove_all(d);
|
|
}
|
|
|
|
TEST(GprSurveyAssembler, ThrowsWhenChannelCountMismatch) {
|
|
auto d = (std::filesystem::temp_directory_path() / "gpr_asm_mismatch").string();
|
|
std::filesystem::create_directories(d);
|
|
writeText(d + "/A.iprh", HDR);
|
|
writeI16(d + "/A.iprb", {10, 11, 12, 13});
|
|
// .ord 含 2 个有效通道, 但只传 1 个 iprb 路径 -> 抛错。
|
|
writeText(d + "/x.ord", "0 1.0 -1.5 1\n1 0.0 -1.5 1\n");
|
|
EXPECT_THROW(assembleGprSurvey({d + "/A.iprb"}, d + "/x.ord"),
|
|
std::runtime_error);
|
|
std::filesystem::remove_all(d);
|
|
}
|
|
|
|
TEST(GprSurveyAssembler, AlignsTracesToMinimum) {
|
|
auto d = (std::filesystem::temp_directory_path() / "gpr_asm_align").string();
|
|
std::filesystem::create_directories(d);
|
|
// 通道 A: traces=2 (lastTrace=1); 通道 B: traces=3 (lastTrace=2)。
|
|
// ntraces 应对齐为 min=2。
|
|
const char* HDR3 =
|
|
"SAMPLES: 2\nLAST TRACE: 2\nCHANNELS: 2\nTIMEWINDOW: 4.0\n"
|
|
"SOIL VELOCITY: 100.000000\nDISTANCE INTERVAL: 0.05\n";
|
|
writeText(d + "/A.iprh", HDR);
|
|
writeI16(d + "/A.iprb", {10, 11, 12, 13}); // 2 道
|
|
writeText(d + "/B.iprh", HDR3);
|
|
writeI16(d + "/B.iprb", {20, 21, 22, 23, 24, 25}); // 3 道
|
|
writeText(d + "/x.ord", "0 0.0 -1.5 1\n1 1.0 -1.5 1\n"); // A->0.0, B->1.0
|
|
auto s = assembleGprSurvey({d + "/A.iprb", d + "/B.iprb"}, d + "/x.ord");
|
|
EXPECT_EQ(s.ntraces, 2);
|
|
EXPECT_EQ(s.samples, 2);
|
|
// A(Y=0.0)=通道0, B(Y=1.0)=通道1; B 的第3道(t=2)被对齐丢弃。
|
|
EXPECT_NEAR(s.at(1, 1, 0), 22.0, 1e-9); // B 的 (t1,s0)
|
|
std::filesystem::remove_all(d);
|
|
}
|