feat/vtk-merged-dataset-column #10
|
|
@ -1,21 +1,15 @@
|
|||
#include "DatasetCategory.hpp"
|
||||
#include "repo/CategoryDescriptor.hpp"
|
||||
|
||||
namespace geopro::app {
|
||||
|
||||
CategoryBuckets splitByCategory(const std::vector<geopro::data::DsRow>& rows) {
|
||||
const auto& cfg = categoryConfigs();
|
||||
const auto& cat = geopro::data::categoryCatalog();
|
||||
CategoryBuckets b;
|
||||
b.segments.resize(cfg.size());
|
||||
for (const auto& r : rows) {
|
||||
int hit = -1;
|
||||
// 先按 ddCode(三维体/切片)——它们无 dsTypeCode(来自 Api3dRepository mock 行)。
|
||||
for (std::size_t i = 0; i < cfg.size() && hit < 0; ++i)
|
||||
if (!cfg[i].ddCode.empty() && r.ddCode == cfg[i].ddCode) hit = static_cast<int>(i);
|
||||
// 再按 dsTypeCode。
|
||||
for (std::size_t i = 0; i < cfg.size() && hit < 0; ++i)
|
||||
if (!cfg[i].dsTypeCode.empty() && r.dsTypeCode == cfg[i].dsTypeCode) hit = static_cast<int>(i);
|
||||
if (hit >= 0) b.segments[static_cast<std::size_t>(hit)].push_back(r);
|
||||
}
|
||||
b.segments.resize(cat.size());
|
||||
for (const auto& r : rows)
|
||||
for (std::size_t i = 0; i < cat.size(); ++i)
|
||||
if (cat[i].classify && cat[i].classify(r)) { b.segments[i].push_back(r); break; }
|
||||
return b;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ add_library(geopro_data STATIC
|
|||
repo/LocalSampleRepository.cpp
|
||||
repo/LocalSample3dRepository.cpp
|
||||
repo/DatasetFieldDictionary.cpp
|
||||
repo/CategoryDescriptor.cpp
|
||||
dto/NavDto.cpp
|
||||
dto/Vtk3dRequests.cpp
|
||||
dto/DatasetChartDto.cpp
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
#include "repo/CategoryDescriptor.hpp"
|
||||
#include <vector>
|
||||
|
||||
namespace geopro::data {
|
||||
|
||||
std::function<bool(const DsRow&)> byDdCode(std::initializer_list<std::string> codes) {
|
||||
std::vector<std::string> cs(codes);
|
||||
return [cs](const DsRow& r) {
|
||||
for (const auto& c : cs) if (r.ddCode == c) return true;
|
||||
return false;
|
||||
};
|
||||
}
|
||||
std::function<bool(const DsRow&)> byDsTypeCode(std::initializer_list<std::string> codes) {
|
||||
std::vector<std::string> cs(codes);
|
||||
return [cs](const DsRow& r) {
|
||||
for (const auto& c : cs) if (r.dsTypeCode == c) return true;
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
const std::vector<CategoryDescriptor>& categoryCatalog() {
|
||||
static const std::vector<CategoryDescriptor> kCat = {
|
||||
{"resistivity", "电阻率数据", SceneKind::Curtain3D,
|
||||
byDsTypeCode({"ERT platform inversion data"}),
|
||||
{FilterKind::DateRange, FilterKind::ArrayType},
|
||||
{OpKind::GenerateVolume, OpKind::Filter}, "curtain"},
|
||||
{"apparent", "视电阻率数据", SceneKind::Curtain3D,
|
||||
byDsTypeCode({"visual resistivity data"}),
|
||||
{FilterKind::DateRange, FilterKind::ArrayType},
|
||||
{OpKind::GenerateVolume, OpKind::Filter}, "curtain"},
|
||||
{"transient", "瞬变电磁数据", SceneKind::Curtain3D,
|
||||
byDsTypeCode({"DD TRANSIENT ELECTROMAGNETIC INVERSION"}),
|
||||
{FilterKind::DateRange},
|
||||
{OpKind::GenerateVolume, OpKind::Filter}, "curtain"},
|
||||
{"voxel", "三维体", SceneKind::Volume3D,
|
||||
byDdCode({"dd_voxel"}),
|
||||
{FilterKind::DateRange},
|
||||
{OpKind::Filter}, "volume"},
|
||||
{"trajectory", "轨迹数据", SceneKind::Plane2D,
|
||||
byDdCode({"dd_trajectory_data"}),
|
||||
{FilterKind::DateRange},
|
||||
{OpKind::PlaneZ, OpKind::Filter, OpKind::Basemap}, "plane2d"},
|
||||
};
|
||||
return kCat;
|
||||
}
|
||||
|
||||
} // namespace geopro::data
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
#include <functional>
|
||||
#include <initializer_list>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include "repo/RepoTypes.hpp" // DsRow
|
||||
|
||||
namespace geopro::data {
|
||||
|
||||
enum class SceneKind { Volume3D, Curtain3D, Plane2D }; // 渲染语义/共存规则
|
||||
enum class FilterKind { DateRange, ArrayType }; // 筛选器契约(可扩展)
|
||||
enum class OpKind { GenerateVolume, Filter, PlaneZ, Basemap }; // 段操作契约(可扩展)
|
||||
|
||||
struct CategoryDescriptor {
|
||||
std::string id;
|
||||
std::string title;
|
||||
SceneKind sceneKind;
|
||||
std::function<bool(const DsRow&)> classify; // 轴1 数据来源/分类
|
||||
std::vector<FilterKind> filters; // 轴2 筛选器
|
||||
std::vector<OpKind> operations; // 轴3 段头图标操作
|
||||
std::string renderStrategyId; // 轴4 渲染策略键
|
||||
};
|
||||
|
||||
// classify 便捷构造器(常见按 ddCode / dsTypeCode 接入)
|
||||
std::function<bool(const DsRow&)> byDdCode(std::initializer_list<std::string> codes);
|
||||
std::function<bool(const DsRow&)> byDsTypeCode(std::initializer_list<std::string> codes);
|
||||
|
||||
const std::vector<CategoryDescriptor>& categoryCatalog();
|
||||
|
||||
} // namespace geopro::data
|
||||
|
|
@ -59,6 +59,8 @@ target_sources(geopro_tests PRIVATE data/test_nav_request.cpp)
|
|||
# GprVolumeRepository:逐线 GPR int16 量化体(BuiltI16)→ app 渲染链 float 体(VolumeGrid)。
|
||||
# 纯适配器逐值反量化 + 全链(合成多通道 .iprb 走真 P1/P2)产出有效 VolumeGrid。
|
||||
target_sources(geopro_tests PRIVATE data/test_gpr_volume_repository.cpp)
|
||||
# CategoryDescriptor:类目描述符目录 categoryCatalog(classify谓词+扩展契约) + splitByCategory 遍历路由。
|
||||
target_sources(geopro_tests PRIVATE data/test_category_descriptor.cpp)
|
||||
target_link_libraries(geopro_tests PRIVATE geopro_data)
|
||||
|
||||
# store 层:ChunkedVolumeStore(GPR 三维体分块压缩落盘 round-trip + 边缘块 + 压缩生效)。
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include "DatasetCategory.hpp"
|
||||
#include "repo/CategoryDescriptor.hpp"
|
||||
using geopro::data::DsRow;
|
||||
using namespace geopro::app;
|
||||
|
||||
|
|
@ -23,7 +24,8 @@ TEST(SplitByCategory, RoutesByDsTypeCodeAndDdCode) {
|
|||
row("x", "dd_ert_measurement_gr_data", "earth resistance"), // 接地电阻 → 丢弃
|
||||
};
|
||||
const CategoryBuckets b = splitByCategory(rows);
|
||||
ASSERT_EQ(b.segments.size(), categoryConfigs().size());
|
||||
// splitByCategory 现走 categoryCatalog()(5 段,含 trajectory);旧 categoryConfigs 暂保留供 UI。
|
||||
ASSERT_EQ(b.segments.size(), geopro::data::categoryCatalog().size());
|
||||
EXPECT_EQ(b.segments[0].size(), 1u); EXPECT_EQ(b.segments[0][0].id, "a");
|
||||
EXPECT_EQ(b.segments[1].size(), 1u); EXPECT_EQ(b.segments[1][0].id, "b");
|
||||
EXPECT_EQ(b.segments[2].size(), 1u); EXPECT_EQ(b.segments[2][0].id, "c");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
#include <gtest/gtest.h>
|
||||
#include "repo/CategoryDescriptor.hpp"
|
||||
#include "DatasetCategory.hpp"
|
||||
|
||||
using namespace geopro::data;
|
||||
|
||||
TEST(CategoryCatalog, HasFiveSegmentsInOrder) {
|
||||
const auto& cat = categoryCatalog();
|
||||
ASSERT_EQ(cat.size(), 5u);
|
||||
EXPECT_EQ(cat[0].id, "resistivity");
|
||||
EXPECT_EQ(cat[3].id, "voxel");
|
||||
EXPECT_EQ(cat[4].id, "trajectory");
|
||||
EXPECT_EQ(cat[4].sceneKind, SceneKind::Plane2D);
|
||||
EXPECT_EQ(cat[4].renderStrategyId, "plane2d");
|
||||
}
|
||||
|
||||
TEST(CategoryCatalog, TrajectoryClassifiesByDdCode) {
|
||||
const auto& cat = categoryCatalog();
|
||||
DsRow traj; traj.id = "t1"; traj.ddCode = "dd_trajectory_data";
|
||||
EXPECT_TRUE(cat[4].classify(traj));
|
||||
DsRow vox; vox.ddCode = "dd_voxel";
|
||||
EXPECT_FALSE(cat[4].classify(vox));
|
||||
}
|
||||
|
||||
TEST(SplitByCategory, RoutesRowToFirstMatchingDescriptor) {
|
||||
DsRow traj; traj.id = "t1"; traj.ddCode = "dd_trajectory_data";
|
||||
DsRow ert; ert.id = "e1"; ert.dsTypeCode = "ERT platform inversion data";
|
||||
auto b = geopro::app::splitByCategory({traj, ert});
|
||||
const auto& cat = categoryCatalog();
|
||||
ASSERT_EQ(b.segments.size(), cat.size());
|
||||
EXPECT_EQ(b.segments[0].size(), 1u); // resistivity ← ert
|
||||
EXPECT_EQ(b.segments[0][0].id, "e1");
|
||||
EXPECT_EQ(b.segments[4].size(), 1u); // trajectory ← traj
|
||||
EXPECT_EQ(b.segments[4][0].id, "t1");
|
||||
}
|
||||
Loading…
Reference in New Issue