geopro/tests/data/test_3d_repo.cpp

193 lines
7.4 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <gtest/gtest.h>
#include <memory>
#include <string>
#include "api/Api3dRepository.hpp"
#include "geo/GeoLocalFrame.hpp"
#include "repo/I3dSceneRepository.hpp"
#include "repo/IAsyncDatasetRepository.hpp"
#include "repo/LocalSample3dRepository.hpp"
#include "repo/LocalSampleRepository.hpp"
#include "repo/VolumeBuildParams.hpp"
using namespace geopro::data;
static const std::string kDir =
"D:/Git/lanbingtech/geopro/docs/剖面网格数据的色阶数据2等文件/";
static const std::string kCrs = "EPSG:4547";
namespace {
DsRow rowWith(const std::string& ddCode) {
DsRow r;
r.ddCode = ddCode;
return r;
}
} // namespace
// dimensionOf各 ddCode → 维度映射同步纯函数spec §6.1)。
TEST(LocalSample3dRepo, DimensionOfMapsDdCode) {
LocalSampleRepository base(kDir);
LocalSample3dRepository repo(base, kCrs, 22.0, 114.0);
EXPECT_EQ(repo.dimensionOf(rowWith("dd_voxel")), DsDimension::Dim3D);
EXPECT_EQ(repo.dimensionOf(rowWith("dd_Structual3D")), DsDimension::Dim3D);
EXPECT_EQ(repo.dimensionOf(rowWith("dd_Property3D")), DsDimension::Dim3D);
EXPECT_EQ(repo.dimensionOf(rowWith("dd_section")), DsDimension::Dim3D);
EXPECT_EQ(repo.dimensionOf(rowWith("dd_inversion_data")), DsDimension::Dim3D);
EXPECT_EQ(repo.dimensionOf(rowWith("dd_slice")), DsDimension::Analysis3D);
// 足迹型 → 二维:数据字典 DD0623 只 dd_trajectory_data 为统一通用轨迹「保留」;
// 瞬变电磁/雷达通道/RTK 等轨迹型字典均「删除」→ 不再归 2D落 Other
EXPECT_EQ(repo.dimensionOf(rowWith("dd_trajectory_data")), DsDimension::Dim2D);
EXPECT_EQ(repo.dimensionOf(rowWith("dd_transient_electromagnetic_trajectory_data")),
DsDimension::Other);
EXPECT_EQ(repo.dimensionOf(rowWith("dd_radar_channel_trajectory")), DsDimension::Other);
EXPECT_EQ(repo.dimensionOf(rowWith("dd_radar_rtk_trajectory")), DsDimension::Other);
EXPECT_EQ(repo.dimensionOf(rowWith("dd_unknown_xyz")), DsDimension::Other);
}
// loadMapLine本地样本取 grid1 经纬作足迹折线lat/lon 等长、>=2 点、valid
TEST(LocalSample3dRepo, LoadMapLineCallsBackWithValidLine) {
LocalSampleRepository base(kDir);
LocalSample3dRepository repo(base, kCrs, 22.0, 114.0);
bool ok = false;
std::string err;
MapLine got;
repo.loadMapLine("traj1", [&](MapLine l) { ok = true; got = std::move(l); },
[&](const std::string& m) { err = m; });
ASSERT_TRUE(ok) << "loadMapLine onErr: " << err;
EXPECT_EQ(got.lat.size(), got.lon.size());
EXPECT_GE(got.lat.size(), 2u);
EXPECT_TRUE(got.valid());
}
// loadVolume回调收到有效 VolumeGridnx>0 且 vmax>vmin需 PROJ_DATA。
TEST(LocalSample3dRepo, LoadVolumeCallsBackWithValidGrid) {
LocalSampleRepository base(kDir);
LocalSample3dRepository repo(base, kCrs, 22.0, 114.0);
bool ok = false;
std::string err;
VolumeGrid got;
repo.loadVolume("voxel1",
[&](VolumeGrid g, geopro::core::ColorScale) { ok = true; got = std::move(g); },
[&](const std::string& m) { err = m; });
ASSERT_TRUE(ok) << "loadVolume onErr: " << err;
EXPECT_GT(got.vol.nx(), 0);
EXPECT_GT(got.vol.ny(), 0);
EXPECT_GT(got.vol.nz(), 0);
EXPECT_GT(got.vmax, got.vmin);
EXPECT_TRUE(got.valid());
}
// loadTerrainPaths回调收到 dem/image 绝对路径(非空)。
TEST(LocalSample3dRepo, LoadTerrainPathsCallsBack) {
LocalSampleRepository base(kDir);
LocalSample3dRepository repo(base, kCrs, 22.0, 114.0);
bool ok = false;
TerrainPaths got;
repo.loadTerrainPaths([&](TerrainPaths p) { ok = true; got = std::move(p); },
[&](const std::string&) {});
ASSERT_TRUE(ok);
EXPECT_FALSE(got.demPath.empty());
EXPECT_FALSE(got.imagePath.empty());
}
namespace {
// 极简桩volumeInfo/createVolume 不触碰 dsRepo_loadAsync 直接回空。
struct StubAsyncRepo : IAsyncDatasetRepository {
DetailLoad* loadAsync(const std::string&, const std::string&, int, int) override {
return nullptr;
}
};
} // namespace
// volumeInfocreateVolume 后、loadVolume 前 → 返回 true参数/名称正确loaded=false、无测点数。
TEST(Api3dRepo, VolumeInfoBeforeLoad) {
StubAsyncRepo dsRepo;
auto frame = std::make_shared<geopro::core::GeoLocalFrame>(22.0, 114.0);
Api3dRepository repo(dsRepo, frame);
VolumeBuildParams p;
p.sourceDatasetIds = {"src-a", "src-b"};
p.interpModel = VolumeBuildParams::Model::Idw;
p.cellXY = 2.0;
p.cellZ = 0.5;
p.power = 3.0;
p.maxDist = 5.0;
p.colorScaleId = "src-a";
const std::string id = repo.createVolume(p, "体A");
Api3dRepository::VolumeInfo info;
ASSERT_TRUE(repo.volumeInfo(id, info));
EXPECT_EQ(info.name, "体A");
EXPECT_FALSE(info.loaded);
EXPECT_EQ(info.pointCount, 0u);
ASSERT_EQ(info.params.sourceDatasetIds.size(), 2u);
EXPECT_EQ(info.params.sourceDatasetIds[0], "src-a");
EXPECT_DOUBLE_EQ(info.params.cellXY, 2.0);
EXPECT_DOUBLE_EQ(info.params.power, 3.0);
EXPECT_DOUBLE_EQ(info.params.maxDist, 5.0);
EXPECT_EQ(info.params.colorScaleId, "src-a");
}
// loadMapLineApiloadAsync 返回空句柄 → onErr不崩给明确错误
TEST(Api3dRepo, LoadMapLineNullHandleCallsOnError) {
StubAsyncRepo dsRepo;
auto frame = std::make_shared<geopro::core::GeoLocalFrame>(22.0, 114.0);
Api3dRepository repo(dsRepo, frame);
bool errCalled = false;
repo.loadMapLine("traj1", [](MapLine) { FAIL() << "不应成功(空句柄)"; },
[&](const std::string&) { errCalled = true; });
EXPECT_TRUE(errCalled);
}
// volumeInfo未知 dsId非三维体→ 返回 false不弹空对话框。
TEST(Api3dRepo, VolumeInfoUnknownIdReturnsFalse) {
StubAsyncRepo dsRepo;
auto frame = std::make_shared<geopro::core::GeoLocalFrame>(22.0, 114.0);
Api3dRepository repo(dsRepo, frame);
Api3dRepository::VolumeInfo info;
EXPECT_FALSE(repo.volumeInfo("not-a-volume", info));
}
// anomalyRows异常按 remarkSourceId 存;行 parentId=归属实体 id挂体/挂切片各回得来)。
TEST(Api3dRepo, AnomalyRowsCarryMountAsParent) {
StubAsyncRepo dsRepo;
auto frame = std::make_shared<geopro::core::GeoLocalFrame>(22.0, 114.0);
Api3dRepository repo(dsRepo, frame);
geopro::core::Anomaly onVol;
onVol.name = "异常A"; onVol.typeName = "断层"; onVol.remarkSourceId = "vol-1";
geopro::core::Anomaly onSlice;
onSlice.name = "异常B"; onSlice.remarkSourceId = "slice-9"; // 已保存切片
std::string idV, idS;
repo.saveAnomaly(onVol, "", [&](std::string id) { idV = id; }, [](const std::string&) {});
repo.saveAnomaly(onSlice, "", [&](std::string id) { idS = id; }, [](const std::string&) {});
const auto rows = repo.anomalyRows();
ASSERT_EQ(rows.size(), 2u);
auto find = [&](const std::string& id) -> const geopro::data::DsRow* {
for (const auto& r : rows)
if (r.id == id) return &r;
return nullptr;
};
const auto* rv = find(idV);
ASSERT_NE(rv, nullptr);
EXPECT_EQ(rv->ddCode, "dd_anomaly");
EXPECT_EQ(rv->parentId, "vol-1"); // 挂体
EXPECT_EQ(rv->dsName, "异常A");
EXPECT_EQ(rv->typeName, "断层");
const auto* rs = find(idS);
ASSERT_NE(rs, nullptr);
EXPECT_EQ(rs->parentId, "slice-9"); // 挂切片
EXPECT_EQ(rs->typeName, "异常"); // typeName 空 → 回退"异常"
}