feat/vtk-3d-view #7

Merged
gaozheng merged 301 commits from feat/vtk-3d-view into main 2026-06-27 18:43:52 +08:00
3 changed files with 183 additions and 0 deletions
Showing only changes of commit 2d155c864c - Show all commits

View File

@ -12,6 +12,7 @@ add_library(geopro_data STATIC
dto/GridDto.cpp
api/ApiProjectRepository.cpp
api/ApiDatasetRepository.cpp
api/Api3dRepository.cpp
api/DatasetLoadHandles.cpp
api/NavRequest.cpp)
target_include_directories(geopro_data PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

View File

@ -0,0 +1,120 @@
#include "api/Api3dRepository.hpp"
#include <QObject>
#include <QString>
#include <QVariant>
#include <utility>
#include "api/DatasetLoadHandles.hpp"
#include "model/detail/DetailPayloads.hpp"
#include "repo/IAsyncDatasetRepository.hpp"
namespace geopro::data {
namespace {
constexpr const char* kNotReady = "后端三维端点未就绪";
} // namespace
Api3dRepository::Api3dRepository(IAsyncDatasetRepository& dsRepo) : dsRepo_(dsRepo) {}
DsDimension Api3dRepository::dimensionOf(const DsRow& ds) const {
// 与 LocalSample3dRepository::dimensionOf 同口径spec §6.1 ddCode→维度
// TODO(P3): 与 LocalSample3dRepository 重复,宜提取共享映射(后续清理)。
const std::string& c = ds.ddCode;
if (c == "dd_voxel" || c == "dd_Structual3D" || c == "dd_Property3D" || c == "dd_section" ||
c == "dd_inversion_data") {
return DsDimension::Dim3D;
}
if (c == "dd_slice") return DsDimension::Analysis3D;
if (c == "dd_trajectory_data") return DsDimension::Dim2D;
return DsDimension::Other;
}
void Api3dRepository::loadSection(const std::string& dsId, std::function<void(SectionData)> onOk,
OnError onErr) {
// 真实帘面:复用 ApiDatasetRepository 的 ERT 反演网格端点(loaderKey="inversion.grid")。
// 命中载荷 = core::ContourPayload{grid, scale, anomalies};取 grid+scale 填 SectionData。
DetailLoad* load = dsRepo_.loadAsync("inversion.grid", dsId);
if (load == nullptr) {
onErr("Api3dRepository::loadSection: loadAsync 返回空句柄");
return;
}
// 以 load 为连接上下文 → 它 deleteLater 时自动断开;单线程下创建后立即连接安全。
QObject::connect(load, &DetailLoad::done, load,
[onOk = std::move(onOk)](const QVariant& payload) {
const auto cp = qvariant_cast<core::ContourPayload>(payload);
SectionData s;
s.grid = cp.grid;
s.scale = cp.scale;
onOk(std::move(s));
});
QObject::connect(load, &DetailLoad::failed, load,
[onErr = std::move(onErr)](const QString& message) {
onErr(message.toStdString());
});
}
void Api3dRepository::loadVolume(const std::string& /*dsId*/,
std::function<void(VolumeGrid)> /*onOk*/, OnError onErr) {
onErr(kNotReady); // 后端三维体端点未就绪
}
void Api3dRepository::loadTerrainPaths(std::function<void(TerrainPaths)> /*onOk*/, OnError onErr) {
onErr(kNotReady); // 后端地形 DEM/影像端点未就绪
}
// ── 切片 CRUD后端未就绪 → 变更走 onErr给用户明确"未实现")──────────────
void Api3dRepository::createSlice(const SliceSpec& /*spec*/, const std::string& /*name*/,
std::function<void(std::string)> /*onOk*/, OnError onErr) {
onErr(kNotReady);
}
void Api3dRepository::saveSlice(const std::string& /*dsId*/, const SliceSpec& /*spec*/,
std::function<void()> /*onOk*/, OnError onErr) {
onErr(kNotReady);
}
void Api3dRepository::deleteSlice(const std::string& /*dsId*/, std::function<void()> /*onOk*/,
OnError onErr) {
onErr(kNotReady);
}
// ── 异常 / 异常体load 回空树避免 UI 崩;变更走 onErr─────────────────────
void Api3dRepository::loadAnomalyTree(const std::string& /*objectId*/,
std::function<void(AnomalyTree)> onOk, OnError /*onErr*/) {
onOk(AnomalyTree{}); // 后端未就绪 → 空树
}
void Api3dRepository::saveAnomaly(const geopro::core::Anomaly& /*a*/,
const std::string& /*screenshotPngPath*/,
std::function<void(std::string)> /*onOk*/, OnError onErr) {
onErr(kNotReady);
}
void Api3dRepository::deleteAnomaly(const std::string& /*anomalyId*/,
std::function<void()> /*onOk*/, OnError onErr) {
onErr(kNotReady);
}
void Api3dRepository::deleteAnomalyGroup(const std::string& /*bodyId*/,
std::function<void()> /*onOk*/, OnError onErr) {
onErr(kNotReady);
}
// ── 任务管理load 回空列表避免 UI 崩)──────────────────────────────────────
void Api3dRepository::loadTaskRecords(const std::string& /*dsId*/,
std::function<void(std::vector<TaskRecord>)> onOk,
OnError /*onErr*/) {
onOk({}); // 后端未就绪 → 空记录
}
void Api3dRepository::loadUsableTasks(const std::string& /*ddCode*/,
std::function<void(std::vector<UsableTask>)> onOk,
OnError /*onErr*/) {
onOk({}); // 后端未就绪 → 空列表
}
} // namespace geopro::data

View File

@ -0,0 +1,62 @@
#pragma once
#include <functional>
#include <string>
#include <vector>
#include "repo/I3dSceneRepository.hpp"
namespace geopro::data {
class IAsyncDatasetRepository;
// 真实后端实现 I3dSceneRepository
// loadSection(帘面) 走真实 ERT 反演端点 —— 复用 ApiDatasetRepository(loaderKey="inversion.grid")
// 不重复网络层;命中 core::ContourPayload{grid, scale, anomalies},取 grid+scale 填 SectionData。
// dimensionOf 同步纯函数(ddCode→维度同 LocalSample3dRepository 映射)。
// 三维体/地形/切片/异常/任务端点后端尚未就绪 → 暂 stub
// - load 类(loadTree/loadRecords/loadTasks) 回调空,避免 UI 崩;
// - loadVolume/loadTerrainPaths 及一切 create/save/delete 变更 → 走 onErr("后端未就绪")
// 给用户明确"未实现"而非假成功。
class Api3dRepository : public I3dSceneRepository {
public:
explicit Api3dRepository(IAsyncDatasetRepository& dsRepo);
DsDimension dimensionOf(const DsRow& ds) const override;
void loadVolume(const std::string& dsId, std::function<void(VolumeGrid)> onOk,
OnError onErr) override;
void loadSection(const std::string& dsId, std::function<void(SectionData)> onOk,
OnError onErr) override;
void loadTerrainPaths(std::function<void(TerrainPaths)> onOk, OnError onErr) override;
// 切片 CRUD后端未就绪 → 变更走 onErr
void createSlice(const SliceSpec& spec, const std::string& name,
std::function<void(std::string)> onOk, OnError onErr) override;
void saveSlice(const std::string& dsId, const SliceSpec& spec,
std::function<void()> onOk, OnError onErr) override;
void deleteSlice(const std::string& dsId,
std::function<void()> onOk, OnError onErr) override;
// 异常 / 异常体(后端未就绪 → load 回空树,变更走 onErr
void loadAnomalyTree(const std::string& objectId,
std::function<void(AnomalyTree)> onOk, OnError onErr) override;
void saveAnomaly(const geopro::core::Anomaly& a, const std::string& screenshotPngPath,
std::function<void(std::string)> onOk, OnError onErr) override;
void deleteAnomaly(const std::string& anomalyId,
std::function<void()> onOk, OnError onErr) override;
void deleteAnomalyGroup(const std::string& bodyId,
std::function<void()> onOk, OnError onErr) override;
// 任务管理(后端未就绪 → load 回空列表)
void loadTaskRecords(const std::string& dsId,
std::function<void(std::vector<TaskRecord>)> onOk,
OnError onErr) override;
void loadUsableTasks(const std::string& ddCode,
std::function<void(std::vector<UsableTask>)> onOk,
OnError onErr) override;
private:
IAsyncDatasetRepository& dsRepo_;
};
} // namespace geopro::data