114 lines
4.2 KiB
C++
114 lines
4.2 KiB
C++
#include "data/store/ChunkedVolumeStore.hpp"
|
||
#include "core/algo/GprVolumeBuilder.hpp"
|
||
#include <gtest/gtest.h>
|
||
#include <filesystem>
|
||
#include <cstdint>
|
||
using namespace geopro::data;
|
||
namespace {
|
||
geopro::core::BuiltI16 makeRamp(int n) {
|
||
geopro::core::BuiltI16 b;
|
||
b.vol = geopro::core::ScalarVolumeI16(n, n, n);
|
||
for (int k = 0; k < n; k++)
|
||
for (int j = 0; j < n; j++)
|
||
for (int i = 0; i < n; i++) b.vol.at(i, j, k) = (short)(i); // 沿 x 斜坡
|
||
b.quant = {1.0, 0.0};
|
||
b.origin = {{0, 0, 0}};
|
||
b.spacing = {{1, 1, 1}};
|
||
b.vminPhys = 0;
|
||
b.vmaxPhys = n;
|
||
return b;
|
||
}
|
||
} // namespace
|
||
|
||
TEST(Pyramid, BuildsHalfResLevelsAndRanges) {
|
||
auto dir = (std::filesystem::temp_directory_path() / "gpr_pyr").string();
|
||
std::filesystem::remove_all(dir);
|
||
ChunkedVolumeStore::write(dir, makeRamp(64), 32);
|
||
ChunkedVolumeStore s(dir);
|
||
s.buildPyramid(2); // level 0(64³),1(32³),2(16³)
|
||
EXPECT_GE(s.levels(), 3);
|
||
int nx, ny, nz;
|
||
s.dims(1, nx, ny, nz);
|
||
EXPECT_EQ(nx, 32);
|
||
EXPECT_EQ(ny, 32);
|
||
EXPECT_EQ(nz, 32);
|
||
// level0 块0 的 range:x 斜坡 0..31(brick32) → min=0,max=31
|
||
auto r0 = s.brickRange(0, 0, 0, 0);
|
||
EXPECT_EQ(r0.first, 0);
|
||
EXPECT_EQ(r0.second, 31);
|
||
auto blk1 = s.readBrick(1, 0, 0, 0); // level1 块,降采样后非空
|
||
EXPECT_FALSE(blk1.empty());
|
||
std::filesystem::remove_all(dir);
|
||
}
|
||
|
||
TEST(Pyramid, Level0ReadCompatUnchanged) {
|
||
auto dir = (std::filesystem::temp_directory_path() / "gpr_pyr_compat").string();
|
||
std::filesystem::remove_all(dir);
|
||
ChunkedVolumeStore::write(dir, makeRamp(64), 32);
|
||
ChunkedVolumeStore s(dir);
|
||
s.buildPyramid(1);
|
||
EXPECT_EQ(s.readBrick(0, 0, 0), s.readBrick(0, 0, 0, 0)); // 兼容重载等价
|
||
std::filesystem::remove_all(dir);
|
||
}
|
||
|
||
// 降采样语义:level1(0,0,0) 由 level0 每 2×2×2 平均得到。
|
||
// x 斜坡:level1 体素 i 来自 level0 的 (2i, 2i+1) 平均 = round((2i + 2i+1)/2) = 2i(取整向偶或截断,
|
||
// 这里两值差 1,平均 2i+0.5,round→2i+1 或 2i 取决实现;仅校验单调与范围)。
|
||
TEST(Pyramid, DownsampledRangeWithinSource) {
|
||
auto dir = (std::filesystem::temp_directory_path() / "gpr_pyr_ds").string();
|
||
std::filesystem::remove_all(dir);
|
||
ChunkedVolumeStore::write(dir, makeRamp(64), 32);
|
||
ChunkedVolumeStore s(dir);
|
||
s.buildPyramid(2);
|
||
// level1 维度 32³;以 brick32 仍是 1 块(覆盖 i=0..31 → 源 i=0..63)。
|
||
int nx, ny, nz;
|
||
s.dims(1, nx, ny, nz);
|
||
EXPECT_EQ(nx, 32);
|
||
auto r1 = s.brickRange(1, 0, 0, 0);
|
||
// 降采样值落在源范围 [0,63] 内,且块覆盖全 x → min≈0, max≈63 附近(round 后)。
|
||
EXPECT_GE(r1.first, 0);
|
||
EXPECT_LE(r1.second, 63);
|
||
EXPECT_LT(r1.first, r1.second); // 斜坡降采样后仍有跨度
|
||
// level1 块尺寸 = 32³。
|
||
auto blk1 = s.readBrick(1, 0, 0, 0);
|
||
EXPECT_EQ(blk1.size(), 32u * 32 * 32);
|
||
std::filesystem::remove_all(dir);
|
||
}
|
||
|
||
// 全 blank 块 → range 记 (kBlank,kBlank),降采样后该区域仍 blank。
|
||
TEST(Pyramid, AllBlankBrickRange) {
|
||
auto dir = (std::filesystem::temp_directory_path() / "gpr_pyr_blank").string();
|
||
std::filesystem::remove_all(dir);
|
||
geopro::core::BuiltI16 b;
|
||
b.vol = geopro::core::ScalarVolumeI16(64, 64, 64);
|
||
for (auto& v : b.vol.data()) v = geopro::core::ScalarVolumeI16::kBlank;
|
||
b.quant = {1.0, 0.0};
|
||
b.origin = {{0, 0, 0}};
|
||
b.spacing = {{1, 1, 1}};
|
||
b.vminPhys = 0;
|
||
b.vmaxPhys = 0;
|
||
ChunkedVolumeStore::write(dir, b, 32);
|
||
ChunkedVolumeStore s(dir);
|
||
s.buildPyramid(2);
|
||
auto r0 = s.brickRange(0, 0, 0, 0);
|
||
EXPECT_EQ(r0.first, geopro::core::ScalarVolumeI16::kBlank);
|
||
EXPECT_EQ(r0.second, geopro::core::ScalarVolumeI16::kBlank);
|
||
auto r1 = s.brickRange(1, 0, 0, 0);
|
||
EXPECT_EQ(r1.first, geopro::core::ScalarVolumeI16::kBlank);
|
||
std::filesystem::remove_all(dir);
|
||
}
|
||
|
||
// 老 store(未 buildPyramid):levels()==1;brickRange(0,...) 仍可惰性算。
|
||
TEST(Pyramid, LegacyStoreNoPyramidLevelsIsOne) {
|
||
auto dir = (std::filesystem::temp_directory_path() / "gpr_pyr_legacy").string();
|
||
std::filesystem::remove_all(dir);
|
||
ChunkedVolumeStore::write(dir, makeRamp(64), 32);
|
||
ChunkedVolumeStore s(dir); // 未调用 buildPyramid
|
||
EXPECT_EQ(s.levels(), 1);
|
||
EXPECT_EQ(s.bricksX(), s.bricksX(0));
|
||
auto r0 = s.brickRange(0, 0, 0, 0); // 惰性算
|
||
EXPECT_EQ(r0.first, 0);
|
||
EXPECT_EQ(r0.second, 31);
|
||
std::filesystem::remove_all(dir);
|
||
}
|