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
4 changed files with 32 additions and 13 deletions
Showing only changes of commit f3a1ba9f99 - Show all commits

View File

@ -543,7 +543,6 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
auto* btnSliceFrontBack = new QPushButton(QStringLiteral("前后"));
auto* btnSliceLeftRight = new QPushButton(QStringLiteral("左右"));
auto* btnSliceOblique = new QPushButton(QStringLiteral("任意"));
auto* btnSliceFace = new QPushButton(QStringLiteral("正视")); // 正视选中切片(E54)
auto* btnSliceFlip = new QPushButton(QStringLiteral("翻转"));
auto* btnSliceClose = new QPushButton(QStringLiteral("关闭"));
sliceLayout->addWidget(sliceLabel);
@ -551,7 +550,6 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
sliceLayout->addWidget(btnSliceFrontBack);
sliceLayout->addWidget(btnSliceLeftRight);
sliceLayout->addWidget(btnSliceOblique);
sliceLayout->addWidget(btnSliceFace);
sliceLayout->addWidget(btnSliceFlip);
sliceLayout->addWidget(btnSliceClose);
sliceBar->setVisible(false); // 默认二维,不显示
@ -559,14 +557,13 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
// 切片按钮可用性:仅三维 + 有体素时创建/翻转可用;关闭仅在有切片时可用。
auto updateSliceButtons = [interactionMgr, btnSliceUpDown, btnSliceFrontBack, btnSliceLeftRight,
btnSliceOblique, btnSliceFace, btnSliceFlip, btnSliceClose, sceneView]() {
btnSliceOblique, btnSliceFlip, btnSliceClose, sceneView]() {
const bool canSlice = sceneView->hasVolume() && interactionMgr->hasVolume();
btnSliceUpDown->setEnabled(canSlice);
btnSliceFrontBack->setEnabled(canSlice);
btnSliceLeftRight->setEnabled(canSlice);
btnSliceOblique->setEnabled(canSlice);
btnSliceFlip->setEnabled(canSlice);
btnSliceFace->setEnabled(interactionMgr->hasSlices()); // 正视需有(选中)切片
btnSliceClose->setEnabled(interactionMgr->hasSlices());
};
updateSliceButtons();
@ -584,8 +581,6 @@ void buildWorkbench(QMainWindow& window, geopro::data::LocalSampleRepository& re
[addSlice]() { addSlice(SliceAxis::LeftRight); });
QObject::connect(btnSliceOblique, &QPushButton::clicked, vtkWidget,
[addSlice]() { addSlice(SliceAxis::Oblique); });
QObject::connect(btnSliceFace, &QPushButton::clicked, vtkWidget,
[interactionMgr]() { interactionMgr->faceSelected(); });
QObject::connect(btnSliceFlip, &QPushButton::clicked, vtkWidget,
[interactionMgr]() { interactionMgr->flipView(); });
QObject::connect(btnSliceClose, &QPushButton::clicked, vtkWidget,

View File

@ -1,6 +1,7 @@
#include "interact/InteractionManager.hpp"
#include <algorithm>
#include <chrono>
#include <cmath>
#include <cstddef>
@ -87,14 +88,27 @@ void InteractionManager::addSlice(SliceAxis axis) {
}
void InteractionManager::selectByTool(const SliceTool* tool) {
for (std::size_t i = 0; i < slices_.size(); ++i) {
if (slices_[i].get() == tool) {
selected_ = static_cast<int>(i);
updateSelectionVisual();
safeRender();
return;
}
int idx = -1;
for (std::size_t i = 0; i < slices_.size(); ++i)
if (slices_[i].get() == tool) { idx = static_cast<int>(i); break; }
if (idx < 0) return;
selected_ = idx;
updateSelectionVisual();
// 双击切片正视(D40):同一切片在 350ms 内两次交互 → 视为双击 → 正视。
const double now = std::chrono::duration<double, std::milli>(
std::chrono::steady_clock::now().time_since_epoch())
.count();
const bool dbl = (tool == lastInteractTool_) && lastInteractMs_ >= 0.0 &&
(now - lastInteractMs_) < 350.0;
lastInteractMs_ = now;
lastInteractTool_ = tool;
if (dbl) {
lastInteractMs_ = -1.0; // 重置避免三连判
faceSlice(idx);
return;
}
safeRender();
}
void InteractionManager::closeSelected() {

View File

@ -98,6 +98,11 @@ private:
// 析构进行中closeAll() 跳过 renderWindow_->Render()Qt 拆台时窗口可能已半析构,
// 析构期再 Render 易崩,评审 M3
bool destroying_ = false;
// 双击切片正视(D40)检测:同一切片在阈值内两次交互(StartInteractionEvent)视为双击 → 正视。
// 因 widget 开启交互后独占切面事件,双击靠监听 widget 交互判定,而非 InteractorStyle。
double lastInteractMs_ = -1.0;
const SliceTool* lastInteractTool_ = nullptr;
};
} // namespace geopro::render::interact

View File

@ -78,6 +78,11 @@ SliceTool::SliceTool(vtkImageData* image, vtkRenderWindowInteractor* interactor,
}
}
// 照原型配置(f57291a):左键拖动=移动切面(默认左键是窗位调整,无用);中键=取值光标。
// 切面边缘(margins)拖动可旋转切面 → 任意切片"可任意调整角度"(F25)。
widget_->SetLeftButtonAction(vtkImagePlaneWidget::VTK_SLICE_MOTION_ACTION);
widget_->SetMiddleButtonAction(vtkImagePlaneWidget::VTK_CURSOR_ACTION);
widget_->On();
// 保持 widget 交互开启:任意切片可拖动调整角度/位置(F25 '可任意调整')。
// 监听其交互开始事件 → 触碰本切片即回调 onInteract(上层据此设为选中)。