From 43ee59c82f45b4544760a0eeafaf890ce2251543 Mon Sep 17 00:00:00 2001 From: wmayer Date: Fri, 31 Mar 2023 11:39:06 +0200 Subject: [PATCH] Gui: interactive image scaling: * add option to allow points outside of image * after starting the interactive scaling allow to cancel it immediately --- src/Gui/TaskView/TaskImageScale.cpp | 102 ++++++++++++++++++++-------- src/Gui/TaskView/TaskImageScale.h | 15 ++-- src/Gui/TaskView/TaskImageScale.ui | 26 ++++++- 3 files changed, 109 insertions(+), 34 deletions(-) diff --git a/src/Gui/TaskView/TaskImageScale.cpp b/src/Gui/TaskView/TaskImageScale.cpp index a0734912be..f485a63a2f 100644 --- a/src/Gui/TaskView/TaskImageScale.cpp +++ b/src/Gui/TaskView/TaskImageScale.cpp @@ -26,6 +26,7 @@ # include # include # include +# include # include # include # include @@ -136,8 +137,6 @@ void TaskImageScale::selectedPoints(size_t num) else if (num == 2) { ui->labelInstruction->setText(tr("Enter desired distance between the points")); ui->pushButtonScale->setEnabled(true); - ui->pushButtonScale->setText(tr("Accept")); - ui->pushButtonCancel->show(); ui->quantitySpinBox->setEnabled(true); ui->quantitySpinBox->setValue(scale->getDistance()); } @@ -158,10 +157,17 @@ void TaskImageScale::scaleImage(double factor) void TaskImageScale::startScale() { - scale->activate(); - ui->labelInstruction->setText(tr("Select two points in the 3d view")); + scale->activate(ui->checkBoxOutside->isChecked()); + if (ui->checkBoxOutside->isChecked()) { + ui->labelInstruction->setText(tr("Select two points in the 3d view")); + } + else { + ui->labelInstruction->setText(tr("Select two points on the image")); + } + ui->checkBoxOutside->setEnabled(false); ui->pushButtonScale->setEnabled(false); - ui->pushButtonCancel->hide(); + ui->pushButtonScale->setText(tr("Accept")); + ui->pushButtonCancel->show(); ui->quantitySpinBox->setEnabled(false); } @@ -175,9 +181,11 @@ void TaskImageScale::rejectScale() { scale->deactivate(); ui->labelInstruction->clear(); + ui->pushButtonScale->setEnabled(true); ui->pushButtonScale->setText(tr("Interactive")); ui->pushButtonCancel->hide(); ui->quantitySpinBox->setEnabled(false); + ui->checkBoxOutside->setEnabled(true); scale->clearPoints(); } @@ -187,7 +195,8 @@ void TaskImageScale::onInteractiveScale() if (!feature.expired() && !scale) { View3DInventorViewer* viewer = getViewer(); if (viewer) { - scale = new InteractiveScale(viewer); + auto vp = Application::Instance->getViewProvider(feature.get()); + scale = new InteractiveScale(viewer, vp); connect(scale, &InteractiveScale::selectedPoints, this, &TaskImageScale::selectedPoints); } @@ -205,9 +214,11 @@ void TaskImageScale::onInteractiveScale() // ---------------------------------------------------------------------------- -InteractiveScale::InteractiveScale(View3DInventorViewer* view) +InteractiveScale::InteractiveScale(View3DInventorViewer* view, ViewProvider* vp) : active{false} + , allowOutsideImage{false} , viewer{view} + , viewProv{vp} { coords = new SoCoordinate3; coords->ref(); @@ -228,7 +239,7 @@ InteractiveScale::~InteractiveScale() root->unref(); } -void InteractiveScale::activate() +void InteractiveScale::activate(bool allowOutside) { if (viewer) { static_cast(viewer->getSceneGraph())->addChild(root); @@ -238,6 +249,7 @@ void InteractiveScale::activate() viewer->setSelectionEnabled(false); viewer->getWidget()->setCursor(QCursor(Qt::CrossCursor)); active = true; + allowOutsideImage = allowOutside; } } @@ -276,33 +288,67 @@ void InteractiveScale::clearPoints() coords->point.setNum(0); } +void InteractiveScale::findPointOnPlane(SoEventCallback * ecb) +{ + if (allowOutsideImage) { + findPointOnFocalPlane(ecb); + } + else { + findPointOnImagePlane(ecb); + } +} + +void InteractiveScale::findPointOnImagePlane(SoEventCallback * ecb) +{ + const SoMouseButtonEvent * mbe = static_cast(ecb->getEvent()); + Gui::View3DInventorViewer* view = static_cast(ecb->getUserData()); + std::unique_ptr pp(view->getPointOnRay(mbe->getPosition(), viewProv)); + if (pp.get()) { + auto pos3d = pp->getPoint(); + + collectPoint(pos3d); + } +} + +void InteractiveScale::findPointOnFocalPlane(SoEventCallback * ecb) +{ + const SoMouseButtonEvent * mbe = static_cast(ecb->getEvent()); + Gui::View3DInventorViewer* view = static_cast(ecb->getUserData()); + + auto pos2d = mbe->getPosition(); + auto pos3d = view->getPointOnFocalPlane(pos2d); + + collectPoint(pos3d); +} + +void InteractiveScale::collectPoint(const SbVec3f& pos3d) +{ + if (points.empty()) { + points.push_back(pos3d); + coords->point.set1Value(0, pos3d); + } + else if (points.size() == 1) { + double distance = getDistance(pos3d); + if (distance > Base::Precision::Confusion()) { + points.push_back(pos3d); + coords->point.set1Value(1, pos3d); + } + else { + Base::Console().Warning(std::string("Image scale"), "The second point is too close. Retry!\n"); + } + } + + Q_EMIT selectedPoints(points.size()); +} + void InteractiveScale::getMouseClick(void * ud, SoEventCallback * ecb) { InteractiveScale* scale = static_cast(ud); const SoMouseButtonEvent * mbe = static_cast(ecb->getEvent()); - Gui::View3DInventorViewer* view = static_cast(ecb->getUserData()); if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) { ecb->setHandled(); - auto pos2d = mbe->getPosition(); - auto pos3d = view->getPointOnFocalPlane(pos2d); - - if (scale->points.empty()) { - scale->points.push_back(pos3d); - scale->coords->point.set1Value(0, pos3d); - } - else if (scale->points.size() == 1) { - double distance = scale->getDistance(pos3d); - if (distance > Base::Precision::Confusion()) { - scale->points.push_back(pos3d); - scale->coords->point.set1Value(1, pos3d); - } - else { - Base::Console().Warning(std::string("Image scale"), "The second point is too close. Retry!\n"); - } - } - - Q_EMIT scale->selectedPoints(scale->points.size()); + scale->findPointOnPlane(ecb); } } diff --git a/src/Gui/TaskView/TaskImageScale.h b/src/Gui/TaskView/TaskImageScale.h index 657e83e5cd..4327abee4c 100644 --- a/src/Gui/TaskView/TaskImageScale.h +++ b/src/Gui/TaskView/TaskImageScale.h @@ -40,14 +40,15 @@ class SoLineSet; namespace Gui { class View3DInventorViewer; +class ViewProvider; class InteractiveScale : public QObject { Q_OBJECT public: - explicit InteractiveScale(View3DInventorViewer* view); + explicit InteractiveScale(View3DInventorViewer* view, ViewProvider* vp); ~InteractiveScale(); - void activate(); + void activate(bool allowOutside); void deactivate(); bool isActive() const { return active; @@ -57,17 +58,23 @@ public: void clearPoints(); private: - static void getMouseClick(void * ud, SoEventCallback * n); - static void getMousePosition(void * ud, SoEventCallback * n); + static void getMouseClick(void * ud, SoEventCallback * ecb); + static void getMousePosition(void * ud, SoEventCallback * ecb); + void findPointOnPlane(SoEventCallback * ecb); + void findPointOnImagePlane(SoEventCallback * ecb); + void findPointOnFocalPlane(SoEventCallback * ecb); + void collectPoint(const SbVec3f&); Q_SIGNALS: void selectedPoints(size_t); private: bool active; + bool allowOutsideImage; SoCoordinate3* coords; SoSeparator* root; QPointer viewer; + ViewProvider* viewProv; std::vector points; }; diff --git a/src/Gui/TaskView/TaskImageScale.ui b/src/Gui/TaskView/TaskImageScale.ui index 8427bf1bb8..bc51452a36 100644 --- a/src/Gui/TaskView/TaskImageScale.ui +++ b/src/Gui/TaskView/TaskImageScale.ui @@ -6,8 +6,8 @@ 0 0 - 293 - 266 + 421 + 267 @@ -115,6 +115,19 @@ + + + + + 0 + 0 + + + + Allow points outside the image + + + @@ -157,6 +170,15 @@
Gui/QuantitySpinBox.h
+ + spinBoxWidth + spinBoxHeight + checkBoxRatio + pushButtonScale + pushButtonCancel + checkBoxOutside + quantitySpinBox +