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
5 changed files with 36 additions and 1 deletions
Showing only changes of commit b2904c211e - Show all commits

View File

@ -368,7 +368,7 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
auto* drawer = new geopro::app::ColumnDrawer(centerWidget, fieldDict);
auto* viewToolbar = new geopro::app::VtkViewToolbar(centerWidget); // VTK 画布全局视图控制竖排工具条
// 拉装置类型枚举(全局,登录后一次)→ 填字典;电阻率/视电阻率段装置下拉据此显示 + 过滤spec §6/§10
cmdRepo.listArrayTypes([fieldDict](bool ok, QJsonArray list, QString) {
cmdRepo.listArrayTypes([fieldDict, drawer](bool ok, QJsonArray list, QString) {
if (!ok) return;
std::map<std::string, std::string> e;
for (const auto& v : list) {
@ -378,6 +378,8 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
if (!iv.empty()) e[iv] = o.value(QStringLiteral("name")).toString().toStdString();
}
fieldDict->setArrayTypeEnum(std::move(e));
// 枚举到达(异步,可能晚于已加载的数据)→ 重填各段装置下拉,避免下拉为空。
drawer->analysisTab()->refreshArrayFilters();
});
// 左侧抽屉 | 右侧画布用 QSplitter左面板可拖改宽工具条悬浮于画布上不占布局
auto* split = new QSplitter(Qt::Horizontal);
@ -397,6 +399,10 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
// 坐标轴设置抽屉面板:叠加 vtkWidget、工具条右侧滑出默认隐藏点设置 toggle
auto* axesPanel = new geopro::app::AxesSettingsPanel(vtkWidget);
axesPanel->hide();
// 预热:首次打开前先完成样式表解析 + 布局尺寸计算(含 spinbox/滑块/中文标签首次字体解析),
// 避免用户第一次点开时同步做这些导致 UI 卡顿。
axesPanel->ensurePolished();
axesPanel->adjustSize();
// 3b三维分析栏勾选的已保存切片(dd_slice) id 集合 + 调和函数。
// syncSlices按"当前活动体 dsId"调和 InteractionManager 上显示的已保存切片——
@ -912,6 +918,17 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
sceneView->setAnomalyVisible(id.toStdString(), vis);
renderWindowPtr->Render();
});
// 树选中切片/异常 → VTK 高亮联动(正向 list→VTK反向 VTK→list 需拾取回调,见 OPT-002
QObject::connect(analysisTab, &geopro::app::CategoryAnalysisTab::datasetSelected, vtkWidget,
[sceneView, interactionMgr, renderWindowPtr](const QString& dsId,
const QString& ddCode) {
const std::string id = dsId.toStdString();
if (ddCode == QStringLiteral("dd_anomaly"))
sceneView->setSelectedAnomaly(id);
else if (ddCode == QStringLiteral("dd_slice"))
interactionMgr->selectSavedSlice(id); // 选中已渲染的该切片(高亮)
renderWindowPtr->Render();
});
// 异常双击属性(R83)/右键删除已并入 analysisTab 的 detailRequested(dd_anomaly) /
// deleteDatasetRequested(dd_anomaly)列表选中→VTK高亮(R84)随旧栏退役暂缺,待新段补 anomalySelected。

View File

@ -49,6 +49,7 @@ CategoryAnalysisTab::CategoryAnalysisTab(geopro::data::DatasetFieldDictionary* d
&CategoryAnalysisTab::sliceExportDatRequested);
connect(sec, &CategorySection::anomalyVisibilityChanged, this,
&CategoryAnalysisTab::anomalyVisibilityChanged);
connect(sec, &CategorySection::datasetSelected, this, &CategoryAnalysisTab::datasetSelected);
// #7各段等分 stretch → 内容都少时四段平分高度填满面板(初始与 VTK 区等高、不出滚动条)
// 某段内容增多时其最小高度(=内容总高)撑大,超出视口则由外层 QScrollArea 统一出纵向滚动条。
col->addWidget(sec, 1);
@ -71,6 +72,10 @@ void CategoryAnalysisTab::setStructure(const std::vector<geopro::data::StructNod
for (auto& [id, sec] : sections_) sec->setStructure(nodes);
}
void CategoryAnalysisTab::refreshArrayFilters() {
for (auto& [id, sec] : sections_) sec->refreshArrayFilter();
}
CategorySection* CategoryAnalysisTab::section(const std::string& id) const {
const auto it = sections_.find(id);
return it != sections_.end() ? it->second : nullptr;

View File

@ -25,6 +25,7 @@ public:
void setBuckets(const CategoryBuckets& b); // 分发到 5 段(与 categoryConfigs 同序)
void setStructure(const std::vector<geopro::data::StructNode>& nodes); // 转发各段
void refreshArrayFilters(); // 装置枚举异步加载后,重填各段装置筛选下拉
CategorySection* section(const std::string& id) const; // 按 CategorySpec.id 取段
signals:
@ -40,6 +41,7 @@ signals:
void sliceExportImageRequested(const QString& dsId);
void sliceExportDatRequested(const QString& dsId);
void anomalyVisibilityChanged(const QString& dsId, bool vis);
void datasetSelected(const QString& dsId, const QString& ddCode); // 树选中→VTK 高亮联动
private:
void recomputeCheckedUnion();

View File

@ -101,6 +101,15 @@ CategorySection::CategorySection(const CategorySpec& spec, geopro::data::Dataset
if (spec_.id == "voxel") { // 仅三维体段提供右键操作菜单(体/切片/异常)
list_->setContextMenuPolicy(Qt::CustomContextMenu);
connect(list_, &QTreeWidget::customContextMenuRequested, this, &CategorySection::showContextMenu);
// 树选中切片/异常 → VTK 高亮联动(正向 list→VTK
connect(list_, &QTreeWidget::itemSelectionChanged, this, [this] {
const auto items = list_->selectedItems();
if (items.isEmpty()) return;
QTreeWidgetItem* it = items.first();
const QString id = it->data(0, kDsIdRole).toString();
const QString dd = it->data(0, kDsDdCodeRole).toString();
if (!id.isEmpty() && dd != QStringLiteral("container")) emit datasetSelected(id, dd);
});
}
body->addWidget(list_, 1);

View File

@ -34,6 +34,7 @@ public:
void setDatasets(const std::vector<geopro::data::DsRow>& rows);
void setChecked(const QString& dsId, bool on); // 按 dsId 勾选/取消(新建切片自动勾选等场景)
QStringList checkedIds() const { return checkedDsIds(); } // 当前勾选 ds异常显隐同步用
void refreshArrayFilter() { refreshArrayCombo(); } // 装置枚举异步加载后重填下拉
const CategorySpec& spec() const { return spec_; }
signals:
@ -49,6 +50,7 @@ signals:
void sliceExportImageRequested(const QString& dsId); // 切片→导出图片
void sliceExportDatRequested(const QString& dsId); // 切片→导出 dat
void anomalyVisibilityChanged(const QString& dsId, bool vis); // 异常→显示/隐藏
void datasetSelected(const QString& dsId, const QString& ddCode); // 树选中行→VTK 高亮联动(切片/异常)
private:
void showContextMenu(const QPoint& pos); // 段体树右键菜单(详情 + 删除)