diff --git a/src/app/DatasetCategory.cpp b/src/app/DatasetCategory.cpp index bca33cc..db88af0 100644 --- a/src/app/DatasetCategory.cpp +++ b/src/app/DatasetCategory.cpp @@ -1,21 +1,15 @@ #include "DatasetCategory.hpp" +#include "repo/CategoryDescriptor.hpp" namespace geopro::app { CategoryBuckets splitByCategory(const std::vector& 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(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(i); - if (hit >= 0) b.segments[static_cast(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; } diff --git a/src/data/CMakeLists.txt b/src/data/CMakeLists.txt index 58d4560..1c025cd 100644 --- a/src/data/CMakeLists.txt +++ b/src/data/CMakeLists.txt @@ -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 diff --git a/src/data/repo/CategoryDescriptor.cpp b/src/data/repo/CategoryDescriptor.cpp new file mode 100644 index 0000000..d179f80 --- /dev/null +++ b/src/data/repo/CategoryDescriptor.cpp @@ -0,0 +1,47 @@ +#include "repo/CategoryDescriptor.hpp" +#include + +namespace geopro::data { + +std::function byDdCode(std::initializer_list codes) { + std::vector cs(codes); + return [cs](const DsRow& r) { + for (const auto& c : cs) if (r.ddCode == c) return true; + return false; + }; +} +std::function byDsTypeCode(std::initializer_list codes) { + std::vector cs(codes); + return [cs](const DsRow& r) { + for (const auto& c : cs) if (r.dsTypeCode == c) return true; + return false; + }; +} + +const std::vector& categoryCatalog() { + static const std::vector 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 diff --git a/src/data/repo/CategoryDescriptor.hpp b/src/data/repo/CategoryDescriptor.hpp new file mode 100644 index 0000000..8513578 --- /dev/null +++ b/src/data/repo/CategoryDescriptor.hpp @@ -0,0 +1,30 @@ +#pragma once +#include +#include +#include +#include +#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 classify; // 轴1 数据来源/分类 + std::vector filters; // 轴2 筛选器 + std::vector operations; // 轴3 段头图标操作 + std::string renderStrategyId; // 轴4 渲染策略键 +}; + +// classify 便捷构造器(常见按 ddCode / dsTypeCode 接入) +std::function byDdCode(std::initializer_list codes); +std::function byDsTypeCode(std::initializer_list codes); + +const std::vector& categoryCatalog(); + +} // namespace geopro::data diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index e55bd49..cb66ab2 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -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 + 边缘块 + 压缩生效)。 diff --git a/tests/app/test_dataset_category.cpp b/tests/app/test_dataset_category.cpp index 82876f2..b5c7737 100644 --- a/tests/app/test_dataset_category.cpp +++ b/tests/app/test_dataset_category.cpp @@ -1,5 +1,6 @@ #include #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"); diff --git a/tests/data/test_category_descriptor.cpp b/tests/data/test_category_descriptor.cpp new file mode 100644 index 0000000..ef4708a --- /dev/null +++ b/tests/data/test_category_descriptor.cpp @@ -0,0 +1,35 @@ +#include +#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"); +}