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 15 additions and 5 deletions
Showing only changes of commit d7ab7705c9 - Show all commits

View File

@ -510,7 +510,10 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
QAction* aAnoPoint = anomMenu->addAction(QStringLiteral(""));
QAction* aAnoLine = anomMenu->addAction(QStringLiteral("线"));
QAction* aAnoFace = anomMenu->addAction(QStringLiteral(""));
QAction* aSave = menu.addAction(QStringLiteral("保存"));
// 「保存」仅对未保存(临时)切片显示——已保存切片定稿锁定、不可再改/再存(用户要求)。
QAction* aSave = interactionMgr->selectedSliceDsId().empty()
? menu.addAction(QStringLiteral("保存"))
: nullptr;
QMenu* expMenu = menu.addMenu(QStringLiteral("导出"));
QAction* aImg = expMenu->addAction(QStringLiteral("图片"));
QAction* aDat = expMenu->addAction(QStringLiteral("dat"));
@ -630,7 +633,7 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
[]() { /* onCancel放弃无需处理 */ });
return;
}
if (chosen == aSave) {
if (aSave != nullptr && chosen == aSave) {
int axis = 3;
geopro::render::interact::Vec3 o{}, p1{}, p2{};
if (!interactionMgr->selectedSlicePlane(axis, o, p1, p2)) return;

View File

@ -344,9 +344,7 @@ void CategorySection::showContextMenu(const QPoint& pos) {
sl->addAction(QStringLiteral("左右"), this, [this, id] { emit sliceRequested(SliceAxis::LeftRight, id); });
sl->addAction(QStringLiteral("任意"), this, [this, id] { emit sliceRequested(SliceAxis::Oblique, id); });
menu.addAction(QStringLiteral("色阶"), this, [this, id] { emit colorScaleRequested(id); });
} else if (ddCode == QStringLiteral("dd_slice")) { // 切片
menu.addAction(QStringLiteral("保存"), this, [this, id] { emit sliceSaveRequested(id); });
menu.addAction(QStringLiteral("另存为"), this, [this, id] { emit sliceSaveAsRequested(id); });
} else if (ddCode == QStringLiteral("dd_slice")) { // 切片(列表中均为已保存=定稿锁定,无保存/另存)
QMenu* ex = menu.addMenu(QStringLiteral("导出"));
ex->addAction(QStringLiteral("图片"), this, [this, id] { emit sliceExportImageRequested(id); });
ex->addAction(QStringLiteral("dat"), this, [this, id] { emit sliceExportDatRequested(id); });

View File

@ -168,6 +168,7 @@ void InteractionManager::showSavedSlice(const std::string& dsId, int axis, const
tool->setVolumeDsId(volumeDsId);
SliceTool* tp = tool.get();
tool->onInteract = [this, tp]() { selectByTool(tp); };
tool->setInteractive(false); // 已保存切片定稿锁定:不可移动/旋转(用户要求);仍可拾取选中/右键
slices_.push_back(std::move(tool));
selected_ = static_cast<int>(slices_.size()) - 1;
updateSelectionVisual(); // 程序化显示(syncSlices):不发 onSliceSelectionChanged避免列表选中被刷
@ -289,6 +290,7 @@ std::string InteractionManager::selectedSliceVolumeDsId() const {
void InteractionManager::tagSelectedSlice(const std::string& dsId) {
if (selected_ < 0 || selected_ >= static_cast<int>(slices_.size())) return;
slices_[static_cast<std::size_t>(selected_)]->setDsId(dsId);
slices_[static_cast<std::size_t>(selected_)]->setInteractive(false); // 保存即定稿锁定(不可改)
}
vtkImageData* InteractionManager::selectedSliceImage() const {

View File

@ -171,6 +171,10 @@ vtkImageData* SliceTool::reslicedOutput() const {
return widget_ ? widget_->GetResliceOutput() : nullptr;
}
void SliceTool::setInteractive(bool on) {
if (widget_) widget_->SetInteraction(on ? 1 : 0); // 关=锁移动/旋转/光标,纹理仍显示
}
vtkSmartPointer<vtkImageData> SliceTool::coloredResliceImage() const {
if (!widget_) return nullptr;
vtkImageMapToColors* cm = widget_->GetColorMap(); // widget 内部把 reslice 经 LUT 上色 → 纹理

View File

@ -80,6 +80,9 @@ public:
// 与屏幕切片纹理同源的着色输出(widget 自己的 ColorMap 输出, RGBA, 逐像素一致, 外区透明)。
// 异常截图/导出用它而非另建 LUT避免与屏幕配色不一致(用户实测差异大)。
vtkSmartPointer<vtkImageData> coloredResliceImage() const;
// 开/关 widget 鼠标交互(移动/旋转/光标)。关=锁定但仍显示(已保存切片定稿不可改)
// 拾取选中/右键菜单由 PickInteractorStyle 独立处理,不受此影响。
void setInteractive(bool on);
// 关闭Off() 并解除 interactor 绑定(幂等)。
void close();