193 lines
7.4 KiB
C++
193 lines
7.4 KiB
C++
#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:回调收到有效 VolumeGrid(nx>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
|
||
|
||
// volumeInfo:createVolume 后、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");
|
||
}
|
||
|
||
// loadMapLine(Api):loadAsync 返回空句柄 → 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 空 → 回退"异常"
|
||
}
|