Merge pull request #9199 from Ondsel-Development/image_task
Image: Merge taskboxes into one 'Image plane Settings'.
This commit is contained in:
@@ -342,8 +342,8 @@ SET(Gui_UIC_SRCS
|
||||
Placement.ui
|
||||
TextureMapping.ui
|
||||
TaskView/TaskAppearance.ui
|
||||
TaskView/TaskImageScale.ui
|
||||
TaskView/TaskOrientation.ui
|
||||
TaskView/TaskImage.ui
|
||||
TaskView/TaskSelectLinkProperty.ui
|
||||
TaskElementColors.ui
|
||||
DlgObjectSelection.ui
|
||||
@@ -720,12 +720,12 @@ SET(Task_View_SRCS
|
||||
TaskView/TaskAppearance.cpp
|
||||
TaskView/TaskAppearance.h
|
||||
TaskView/TaskAppearance.ui
|
||||
TaskView/TaskImageScale.cpp
|
||||
TaskView/TaskImageScale.h
|
||||
TaskView/TaskImageScale.ui
|
||||
TaskView/TaskOrientation.cpp
|
||||
TaskView/TaskOrientation.h
|
||||
TaskView/TaskOrientation.ui
|
||||
TaskView/TaskImage.cpp
|
||||
TaskView/TaskImage.h
|
||||
TaskView/TaskImage.ui
|
||||
TaskView/TaskSelectLinkProperty.cpp
|
||||
TaskView/TaskSelectLinkProperty.h
|
||||
TaskView/TaskSelectLinkProperty.ui
|
||||
@@ -968,6 +968,7 @@ SET(Inventor_CPP_SRCS
|
||||
SoNavigationDragger.cpp
|
||||
SoAxisCrossKit.cpp
|
||||
SoTextLabel.cpp
|
||||
SoDatumLabel.cpp
|
||||
SoTouchEvents.cpp
|
||||
SoMouseWheelEvent.cpp
|
||||
SoFCCSysDragger.cpp
|
||||
@@ -995,6 +996,7 @@ SET(Inventor_SRCS
|
||||
SoNavigationDragger.h
|
||||
SoAxisCrossKit.h
|
||||
SoTextLabel.h
|
||||
SoDatumLabel.h
|
||||
SoTouchEvents.h
|
||||
SoMouseWheelEvent.h
|
||||
SoFCCSysDragger.h
|
||||
@@ -1235,8 +1237,8 @@ if(MSVC)
|
||||
propertyeditor/PropertyItemDelegate.cpp
|
||||
propertyeditor/PropertyModel.cpp
|
||||
TaskView/TaskAppearance.cpp
|
||||
TaskView/TaskImageScale.cpp
|
||||
TaskView/TaskOrientation.cpp
|
||||
TaskView/TaskImage.cpp
|
||||
TaskView/TaskSelectLinkProperty.cpp
|
||||
TaskView/TaskEditControl.cpp
|
||||
TaskView/TaskView.cpp
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
|
||||
#define ZCONSTR 0.006f
|
||||
|
||||
using namespace SketcherGui;
|
||||
using namespace Gui;
|
||||
|
||||
// ------------------------------------------------------
|
||||
|
||||
@@ -615,11 +615,13 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action)
|
||||
}
|
||||
// Perp Lines
|
||||
glBegin(GL_LINES);
|
||||
if (length != 0.) {
|
||||
glVertex2f(p1[0], p1[1]);
|
||||
glVertex2f(perp1[0], perp1[1]);
|
||||
|
||||
glVertex2f(p2[0], p2[1]);
|
||||
glVertex2f(perp2[0], perp2[1]);
|
||||
}
|
||||
|
||||
glVertex2f(par1[0], par1[1]);
|
||||
glVertex2f(par2[0], par2[1]);
|
||||
@@ -1019,3 +1021,12 @@ void SoDatumLabel::GLRender(SoGLRenderAction * action)
|
||||
glPopAttrib();
|
||||
state->pop();
|
||||
}
|
||||
|
||||
void SoDatumLabel::setPoints(SbVec3f p1, SbVec3f p2)
|
||||
{
|
||||
pnts.setNum(2);
|
||||
SbVec3f* verts = pnts.startEditing();
|
||||
verts[0] = p1;
|
||||
verts[1] = p2;
|
||||
pnts.finishEditing();
|
||||
}
|
||||
@@ -20,8 +20,8 @@
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef SKETCHERGUI_SODATUMLABEL_H
|
||||
#define SKETCHERGUI_SODATUMLABEL_H
|
||||
#ifndef GUI_SODATUMLABEL_H
|
||||
#define GUI_SODATUMLABEL_H
|
||||
|
||||
#include <Inventor/SbBox3f.h>
|
||||
#include <Inventor/fields/SoSFColor.h>
|
||||
@@ -35,12 +35,12 @@
|
||||
#include <Inventor/fields/SoMFVec3f.h>
|
||||
#include <Inventor/nodes/SoShape.h>
|
||||
|
||||
#include <Mod/Sketcher/SketcherGlobal.h>
|
||||
#include <FCGlobal.h>
|
||||
|
||||
|
||||
namespace SketcherGui {
|
||||
namespace Gui {
|
||||
|
||||
class SketcherGuiExport SoDatumLabel : public SoShape {
|
||||
class GuiExport SoDatumLabel : public SoShape {
|
||||
using inherited = SoShape;
|
||||
|
||||
SO_NODE_HEADER(SoDatumLabel);
|
||||
@@ -60,6 +60,10 @@ public:
|
||||
static void initClass();
|
||||
SoDatumLabel();
|
||||
|
||||
/*The points have to be on XY plane, ie they need to be 2D points.
|
||||
To draw on other planes, you need to attach a SoTransform to the SoDatumLabel (or parent).*/
|
||||
void setPoints(SbVec3f p1, SbVec3f p2);
|
||||
|
||||
SoMFString string;
|
||||
SoSFColor textColor;
|
||||
SoSFEnum datumtype;
|
||||
@@ -99,4 +103,4 @@ private:
|
||||
}
|
||||
|
||||
|
||||
#endif // SKETCHERGUI_SODATUMLABEL_H
|
||||
#endif // GUI_SODATUMLABEL_H
|
||||
@@ -69,6 +69,7 @@
|
||||
#include "SoMouseWheelEvent.h"
|
||||
#include "SoNavigationDragger.h"
|
||||
#include "SoTextLabel.h"
|
||||
#include "SoDatumLabel.h"
|
||||
#include "Inventor/MarkerBitmaps.h"
|
||||
#include "Inventor/SmSwitchboard.h"
|
||||
#include "Inventor/SoAutoZoomTranslation.h"
|
||||
@@ -124,6 +125,7 @@ void Gui::SoFCDB::init()
|
||||
SoVRMLAction ::initClass();
|
||||
SoSkipBoundingGroup ::initClass();
|
||||
SoTextLabel ::initClass();
|
||||
SoDatumLabel ::initClass();
|
||||
SoColorBarLabel ::initClass();
|
||||
SoStringLabel ::initClass();
|
||||
SoFrameLabel ::initClass();
|
||||
|
||||
688
src/Gui/TaskView/TaskImage.cpp
Normal file
688
src/Gui/TaskView/TaskImage.cpp
Normal file
@@ -0,0 +1,688 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <QDialog>
|
||||
# include <QPushButton>
|
||||
# include <QAction>
|
||||
# include <QKeyEvent>
|
||||
# include <map>
|
||||
# include <Inventor/SoPickedPoint.h>
|
||||
# include <Inventor/events/SoLocation2Event.h>
|
||||
# include <Inventor/events/SoButtonEvent.h>
|
||||
# include <Inventor/events/SoMouseButtonEvent.h>
|
||||
# include <Inventor/events/SoKeyboardEvent.h>
|
||||
# include <Inventor/sensors/SoNodeSensor.h>
|
||||
# include <Inventor/nodes/SoOrthographicCamera.h>
|
||||
# include <Inventor/nodes/SoBaseColor.h>
|
||||
# include <Inventor/nodes/SoCoordinate3.h>
|
||||
# include <Inventor/nodes/SoLineSet.h>
|
||||
# include <Inventor/nodes/SoAnnotation.h>
|
||||
# include <Inventor/nodes/SoTransform.h>
|
||||
#endif
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Precision.h>
|
||||
#include <Base/Quantity.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <App/Document.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/BitmapFactory.h>
|
||||
#include <Gui/Camera.h>
|
||||
#include <Gui/Document.h>
|
||||
#include <Gui/SoDatumLabel.h>
|
||||
#include <Gui/View3DInventor.h>
|
||||
#include <Gui/View3DInventorViewer.h>
|
||||
#include <Gui/ViewProviderDocumentObject.h>
|
||||
#include <Gui/TaskView/TaskView.h>
|
||||
|
||||
#include "TaskImage.h"
|
||||
#include "ui_TaskImage.h"
|
||||
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
/* TRANSLATOR Gui::TaskImage */
|
||||
|
||||
TaskImage::TaskImage(Image::ImagePlane* obj, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, ui(new Ui_TaskImage)
|
||||
, feature(obj)
|
||||
, aspectRatio(1.0)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->groupBoxCalibration->hide();
|
||||
|
||||
initialiseTransparency();
|
||||
|
||||
aspectRatio = obj->XSize.getValue() / obj->YSize.getValue();
|
||||
|
||||
connectSignals();
|
||||
}
|
||||
|
||||
TaskImage::~TaskImage()
|
||||
{
|
||||
if (!feature.expired() && scale) {
|
||||
if (scale->isActive()) {
|
||||
scale->deactivate();
|
||||
}
|
||||
scale->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void TaskImage::connectSignals()
|
||||
{
|
||||
connect(ui->Reverse_checkBox, &QCheckBox::clicked,
|
||||
this, &TaskImage::onPreview);
|
||||
connect(ui->XY_radioButton, &QRadioButton::clicked,
|
||||
this, &TaskImage::onPreview);
|
||||
connect(ui->XZ_radioButton, &QRadioButton::clicked,
|
||||
this, &TaskImage::onPreview);
|
||||
connect(ui->YZ_radioButton, &QRadioButton::clicked,
|
||||
this, &TaskImage::onPreview);
|
||||
connect(ui->spinBoxZ, qOverload<double>(&QuantitySpinBox::valueChanged),
|
||||
this, &TaskImage::onPreview);
|
||||
connect(ui->spinBoxX, qOverload<double>(&QuantitySpinBox::valueChanged),
|
||||
this, &TaskImage::onPreview);
|
||||
connect(ui->spinBoxY, qOverload<double>(&QuantitySpinBox::valueChanged),
|
||||
this, &TaskImage::onPreview);
|
||||
connect(ui->spinBoxRotation, qOverload<double>(&QuantitySpinBox::valueChanged),
|
||||
this, &TaskImage::onPreview);
|
||||
connect(ui->spinBoxTransparency, qOverload<int>(&QSpinBox::valueChanged),
|
||||
this, &TaskImage::changeTransparency);
|
||||
connect(ui->sliderTransparency, qOverload<int>(&QSlider::valueChanged),
|
||||
this, &TaskImage::changeTransparency);
|
||||
|
||||
connect(ui->spinBoxWidth, qOverload<double>(&QuantitySpinBox::valueChanged),
|
||||
this, &TaskImage::changeWidth);
|
||||
connect(ui->spinBoxHeight, qOverload<double>(&QuantitySpinBox::valueChanged),
|
||||
this, &TaskImage::changeHeight);
|
||||
connect(ui->pushButtonScale, &QPushButton::clicked,
|
||||
this, &TaskImage::onInteractiveScale);
|
||||
connect(ui->pushButtonApply, &QPushButton::clicked,
|
||||
this, &TaskImage::acceptScale);
|
||||
connect(ui->pushButtonCancel, &QPushButton::clicked,
|
||||
this, &TaskImage::rejectScale);
|
||||
}
|
||||
|
||||
void TaskImage::initialiseTransparency()
|
||||
{
|
||||
auto vp = Application::Instance->getViewProvider(feature.get());
|
||||
App::Property* prop = vp->getPropertyByName("Transparency");
|
||||
if (prop && prop->getTypeId().isDerivedFrom(App::PropertyInteger::getClassTypeId())) {
|
||||
auto Transparency = static_cast<App::PropertyInteger*>(prop);
|
||||
ui->spinBoxTransparency->setValue(Transparency->getValue());
|
||||
ui->sliderTransparency->setValue(Transparency->getValue());
|
||||
}
|
||||
}
|
||||
|
||||
void TaskImage::changeTransparency(int val)
|
||||
{
|
||||
if (feature.expired())
|
||||
return;
|
||||
|
||||
auto vp = Application::Instance->getViewProvider(feature.get());
|
||||
App::Property* prop = vp->getPropertyByName("Transparency");
|
||||
if (prop && prop->getTypeId().isDerivedFrom(App::PropertyInteger::getClassTypeId())) {
|
||||
auto Transparency = static_cast<App::PropertyInteger*>(prop);
|
||||
Transparency->setValue(val);
|
||||
|
||||
QSignalBlocker block(ui->spinBoxTransparency);
|
||||
QSignalBlocker blocks(ui->sliderTransparency);
|
||||
ui->spinBoxTransparency->setValue(val);
|
||||
ui->sliderTransparency->setValue(val);
|
||||
}
|
||||
}
|
||||
|
||||
void TaskImage::changeWidth(double val)
|
||||
{
|
||||
if (!feature.expired()) {
|
||||
feature->XSize.setValue(val);
|
||||
|
||||
if (ui->checkBoxRatio->isChecked()) {
|
||||
QSignalBlocker block(ui->spinBoxWidth);
|
||||
ui->spinBoxHeight->setValue(val / aspectRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TaskImage::changeHeight(double val)
|
||||
{
|
||||
if (!feature.expired()) {
|
||||
feature->YSize.setValue(val);
|
||||
|
||||
if (ui->checkBoxRatio->isChecked()) {
|
||||
QSignalBlocker block(ui->spinBoxHeight);
|
||||
ui->spinBoxWidth->setValue(val * aspectRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
View3DInventorViewer* TaskImage::getViewer() const
|
||||
{
|
||||
if (!feature.expired()) {
|
||||
auto vp = Application::Instance->getViewProvider(feature.get());
|
||||
auto doc = static_cast<ViewProviderDocumentObject*>(vp)->getDocument();
|
||||
auto view = dynamic_cast<View3DInventor*>(doc->getViewOfViewProvider(vp));
|
||||
if (view) {
|
||||
return view->getViewer();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TaskImage::scaleImage(double factor)
|
||||
{
|
||||
if (!feature.expired()) {
|
||||
feature->XSize.setValue(feature->XSize.getValue() * factor);
|
||||
feature->YSize.setValue(feature->YSize.getValue() * factor);
|
||||
|
||||
QSignalBlocker blockW(ui->spinBoxWidth);
|
||||
ui->spinBoxWidth->setValue(feature->XSize.getValue());
|
||||
QSignalBlocker blockH(ui->spinBoxHeight);
|
||||
ui->spinBoxHeight->setValue(feature->YSize.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
void TaskImage::startScale()
|
||||
{
|
||||
scale->activate();
|
||||
ui->pushButtonScale->hide();
|
||||
ui->groupBoxCalibration->show();
|
||||
ui->pushButtonApply->setEnabled(false);
|
||||
}
|
||||
|
||||
void TaskImage::acceptScale()
|
||||
{
|
||||
scaleImage(scale->getScaleFactor());
|
||||
rejectScale();
|
||||
}
|
||||
|
||||
void TaskImage::enableApplyBtn()
|
||||
{
|
||||
ui->pushButtonApply->setEnabled(true);
|
||||
}
|
||||
|
||||
void TaskImage::rejectScale()
|
||||
{
|
||||
scale->deactivate();
|
||||
ui->pushButtonScale->show();
|
||||
ui->groupBoxCalibration->hide();
|
||||
}
|
||||
|
||||
void TaskImage::onInteractiveScale()
|
||||
{
|
||||
if (!feature.expired() && !scale) {
|
||||
View3DInventorViewer* viewer = getViewer();
|
||||
if (viewer) {
|
||||
auto vp = Application::Instance->getViewProvider(feature.get());
|
||||
scale = new InteractiveScale(viewer, vp, feature->globalPlacement());
|
||||
connect(scale, &InteractiveScale::scaleRequired,
|
||||
this, &TaskImage::acceptScale);
|
||||
connect(scale, &InteractiveScale::scaleCanceled,
|
||||
this, &TaskImage::rejectScale);
|
||||
connect(scale, &InteractiveScale::enableApplyBtn,
|
||||
this, &TaskImage::enableApplyBtn);
|
||||
}
|
||||
}
|
||||
|
||||
startScale();
|
||||
}
|
||||
|
||||
void TaskImage::open()
|
||||
{
|
||||
if (!feature.expired()) {
|
||||
App::Document* doc = feature->getDocument();
|
||||
doc->openTransaction(QT_TRANSLATE_NOOP("Command", "Edit image"));
|
||||
restore(feature->Placement.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
void TaskImage::accept()
|
||||
{
|
||||
if (!feature.expired()) {
|
||||
App::Document* doc = feature->getDocument();
|
||||
doc->commitTransaction();
|
||||
doc->recompute();
|
||||
}
|
||||
}
|
||||
|
||||
void TaskImage::reject()
|
||||
{
|
||||
if (!feature.expired()) {
|
||||
App::Document* doc = feature->getDocument();
|
||||
doc->abortTransaction();
|
||||
feature->purgeTouched();
|
||||
}
|
||||
}
|
||||
|
||||
void TaskImage::onPreview()
|
||||
{
|
||||
updateIcon();
|
||||
updatePlacement();
|
||||
}
|
||||
|
||||
void TaskImage::restore(const Base::Placement& plm)
|
||||
{
|
||||
if (feature.expired())
|
||||
return;
|
||||
|
||||
QSignalBlocker blockW(ui->spinBoxWidth);
|
||||
QSignalBlocker blockH(ui->spinBoxHeight);
|
||||
ui->spinBoxWidth->setValue(feature->XSize.getValue());
|
||||
ui->spinBoxHeight->setValue(feature->YSize.getValue());
|
||||
|
||||
Base::Rotation rot = plm.getRotation();
|
||||
Base::Vector3d pos = plm.getPosition();
|
||||
|
||||
double yaw, pitch, roll;
|
||||
rot.getYawPitchRoll(yaw, pitch, roll);
|
||||
|
||||
double tol = 1.0e-5;
|
||||
bool reverse = false;
|
||||
if (fabs(pitch) < tol && (fabs(roll) < tol || fabs(roll - 180.) < tol)) {
|
||||
if (fabs(roll - 180.) < tol)
|
||||
reverse = true;
|
||||
int inv = reverse ? -1 : 1;
|
||||
ui->XY_radioButton->setChecked(true);
|
||||
ui->spinBoxRotation->setValue(yaw * inv);
|
||||
}
|
||||
else if (fabs(roll - 90.) < tol && (fabs(yaw) < tol || fabs(yaw - 180.) < tol)) {
|
||||
if (fabs(yaw - 180.) < tol)
|
||||
reverse = true;
|
||||
int inv = reverse ? -1 : 1;
|
||||
ui->XZ_radioButton->setChecked(true);
|
||||
ui->spinBoxRotation->setValue(- pitch);
|
||||
}
|
||||
else if (fabs(roll - 90.) < tol && (fabs(yaw - 90.) < tol || fabs(yaw + 90.) < tol)) {
|
||||
if (fabs(yaw + 90.) < tol)
|
||||
reverse = true;
|
||||
int inv = reverse ? -1 : 1;
|
||||
ui->YZ_radioButton->setChecked(true);
|
||||
ui->spinBoxRotation->setValue(-pitch);
|
||||
}
|
||||
ui->Reverse_checkBox->setChecked(reverse);
|
||||
|
||||
Base::Vector3d R0(0, 0, 0), RX(1, 0, 0), RY(0, 1, 0);
|
||||
|
||||
RX = rot.multVec(RX);
|
||||
RY = rot.multVec(RY);
|
||||
pos.TransformToCoordinateSystem(R0, RX, RY);
|
||||
ui->spinBoxX->setValue(pos.x);
|
||||
ui->spinBoxY->setValue(pos.y);
|
||||
ui->spinBoxZ->setValue(pos.z);
|
||||
|
||||
onPreview();
|
||||
}
|
||||
|
||||
void TaskImage::updatePlacement()
|
||||
{
|
||||
double angle = ui->spinBoxRotation->value().getValue();
|
||||
bool reverse = ui->Reverse_checkBox->isChecked();
|
||||
|
||||
Base::Placement Pos;
|
||||
Base::Rotation rot;
|
||||
double dir = reverse ? 180. : 0.;
|
||||
int inv = reverse ? -1 : 1;
|
||||
|
||||
if (ui->XY_radioButton->isChecked()) {
|
||||
rot.setYawPitchRoll(inv * angle, 0., dir);
|
||||
}
|
||||
else if (ui->XZ_radioButton->isChecked()) {
|
||||
rot.setYawPitchRoll(dir, -angle, 90.);
|
||||
}
|
||||
else if (ui->YZ_radioButton->isChecked()) {
|
||||
rot.setYawPitchRoll(90. - dir, -angle, 90.);
|
||||
}
|
||||
|
||||
Base::Vector3d offset = Base::Vector3d(ui->spinBoxX->value().getValue(), ui->spinBoxY->value().getValue(), ui->spinBoxZ->value().getValue());
|
||||
offset = rot.multVec(offset);
|
||||
Pos = Base::Placement(offset, rot);
|
||||
|
||||
if (!feature.expired()) {
|
||||
feature->Placement.setValue(Pos);
|
||||
if(scale)
|
||||
scale->setPlacement(feature->globalPlacement());
|
||||
}
|
||||
}
|
||||
|
||||
void TaskImage::updateIcon()
|
||||
{
|
||||
std::string icon;
|
||||
bool reverse = ui->Reverse_checkBox->isChecked();
|
||||
if (ui->XY_radioButton->isChecked()) {
|
||||
icon = reverse ? "view-bottom" : "view-top";
|
||||
}
|
||||
else if (ui->XZ_radioButton->isChecked()) {
|
||||
icon = reverse ? "view-rear" : "view-front";
|
||||
}
|
||||
else if (ui->YZ_radioButton->isChecked()) {
|
||||
icon = reverse ? "view-left" : "view-right";
|
||||
}
|
||||
|
||||
ui->previewLabel->setPixmap(
|
||||
Gui::BitmapFactory().pixmapFromSvg(icon.c_str(),
|
||||
ui->previewLabel->size()));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
struct NodeData {
|
||||
InteractiveScale* scale;
|
||||
};
|
||||
|
||||
InteractiveScale::InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, Base::Placement plc)
|
||||
: active(false)
|
||||
, placement(plc)
|
||||
, viewer(view)
|
||||
, viewProv(vp)
|
||||
, midPoint(SbVec3f(0,0,0))
|
||||
{
|
||||
root = new SoAnnotation;
|
||||
root->ref();
|
||||
root->renderCaching = SoSeparator::OFF;
|
||||
|
||||
measureLabel = new SoDatumLabel();
|
||||
measureLabel->ref();
|
||||
measureLabel->string = "";
|
||||
measureLabel->textColor = SbColor(1.0f, 0.149f, 0.0f);
|
||||
measureLabel->size.setValue(17);
|
||||
measureLabel->lineWidth = 2.0;
|
||||
measureLabel->useAntialiasing = false;
|
||||
measureLabel->param1 = 0.;
|
||||
measureLabel->param2 = 0.;
|
||||
|
||||
transform = new SoTransform();
|
||||
root->addChild(transform);
|
||||
setPlacement(placement);
|
||||
|
||||
Gui::MDIView* mdi = Gui::Application::Instance->activeDocument()->getActiveView();
|
||||
distanceBox = new QuantitySpinBox(mdi);
|
||||
distanceBox->setUnit(Base::Unit::Length);
|
||||
distanceBox->setMinimum(0.0);
|
||||
distanceBox->setMaximum(INT_MAX);
|
||||
distanceBox->setButtonSymbols(QAbstractSpinBox::NoButtons);
|
||||
distanceBox->setToolTip(tr("Enter desired distance between the points"));
|
||||
distanceBox->setKeyboardTracking(false);
|
||||
distanceBox->installEventFilter(this);
|
||||
|
||||
//track camera movements to update spinbox position.
|
||||
NodeData* info = new NodeData{ this };
|
||||
cameraSensor = new SoNodeSensor([](void* data, SoSensor* sensor) {
|
||||
NodeData* info = static_cast<NodeData*>(data);
|
||||
info->scale->positionWidget();
|
||||
}, info);
|
||||
cameraSensor->attach(viewer->getCamera());
|
||||
}
|
||||
|
||||
InteractiveScale::~InteractiveScale()
|
||||
{
|
||||
root->unref();
|
||||
measureLabel->unref();
|
||||
distanceBox->deleteLater();
|
||||
cameraSensor->detach();
|
||||
}
|
||||
|
||||
void InteractiveScale::activate()
|
||||
{
|
||||
if (viewer) {
|
||||
static_cast<SoSeparator*>(viewer->getSceneGraph())->addChild(root);
|
||||
viewer->setEditing(true);
|
||||
viewer->addEventCallback(SoLocation2Event::getClassTypeId(), InteractiveScale::getMousePosition, this);
|
||||
viewer->addEventCallback(SoButtonEvent::getClassTypeId(), InteractiveScale::soEventFilter, this);
|
||||
viewer->setSelectionEnabled(false);
|
||||
viewer->getWidget()->setCursor(QCursor(Qt::CrossCursor));
|
||||
active = true;
|
||||
}
|
||||
}
|
||||
|
||||
void InteractiveScale::deactivate()
|
||||
{
|
||||
if (viewer) {
|
||||
distanceBox->hide();
|
||||
points.clear();
|
||||
root->removeChild(measureLabel);
|
||||
static_cast<SoSeparator*>(viewer->getSceneGraph())->removeChild(root);
|
||||
viewer->setEditing(false);
|
||||
viewer->removeEventCallback(SoLocation2Event::getClassTypeId(), InteractiveScale::getMousePosition, this);
|
||||
viewer->removeEventCallback(SoButtonEvent::getClassTypeId(), InteractiveScale::soEventFilter, this);
|
||||
viewer->setSelectionEnabled(true);
|
||||
viewer->getWidget()->setCursor(QCursor(Qt::ArrowCursor));
|
||||
active = false;
|
||||
}
|
||||
}
|
||||
|
||||
double InteractiveScale::getScaleFactor() const
|
||||
{
|
||||
if ((points[0] - points[1]).length() == 0.)
|
||||
return 1.0;
|
||||
|
||||
return distanceBox->value().getValue() / (points[0] - points[1]).length();
|
||||
}
|
||||
|
||||
double InteractiveScale::getDistance(const SbVec3f& pt) const
|
||||
{
|
||||
if (points.empty())
|
||||
return 0.0;
|
||||
|
||||
return (points[0] - pt).length();
|
||||
}
|
||||
|
||||
void InteractiveScale::findPointOnImagePlane(SoEventCallback * ecb)
|
||||
{
|
||||
const SoMouseButtonEvent * mbe = static_cast<const SoMouseButtonEvent *>(ecb->getEvent());
|
||||
Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(ecb->getUserData());
|
||||
std::unique_ptr<SoPickedPoint> pp(view->getPointOnRay(mbe->getPosition(), viewProv));
|
||||
if (pp.get()) {
|
||||
auto pos3d = pp->getPoint();
|
||||
|
||||
collectPoint(pos3d);
|
||||
}
|
||||
}
|
||||
|
||||
void InteractiveScale::collectPoint(const SbVec3f& pos3d)
|
||||
{
|
||||
if (points.empty()) {
|
||||
points.push_back(pos3d);
|
||||
|
||||
measureLabel->setPoints(getCoordsOnImagePlane(pos3d), getCoordsOnImagePlane(pos3d));
|
||||
root->addChild(measureLabel);
|
||||
}
|
||||
else if (points.size() == 1) {
|
||||
double distance = getDistance(pos3d);
|
||||
if (distance > Base::Precision::Confusion()) {
|
||||
points.push_back(pos3d);
|
||||
|
||||
midPoint = points[0] + (points[1] - points[0]) / 2;
|
||||
|
||||
measureLabel->string = "";
|
||||
distanceBox->show();
|
||||
QSignalBlocker block(distanceBox);
|
||||
distanceBox->setValue((points[1] - points[0]).length());
|
||||
distanceBox->adjustSize();
|
||||
positionWidget();
|
||||
distanceBox->selectNumber();
|
||||
distanceBox->setFocus();
|
||||
|
||||
Q_EMIT enableApplyBtn();
|
||||
}
|
||||
else {
|
||||
Base::Console().Warning(std::string("Image scale"), "The second point is too close. Retry!\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void InteractiveScale::positionWidget()
|
||||
{
|
||||
QSize wSize = distanceBox->size();
|
||||
QPoint pxCoord = viewer->toQPoint(viewer->getPointOnViewport(midPoint));
|
||||
pxCoord.setX(std::max(pxCoord.x() - wSize.width() / 2, 0));
|
||||
pxCoord.setY(std::max(pxCoord.y() - wSize.height() / 2, 0));
|
||||
distanceBox->move(pxCoord);
|
||||
}
|
||||
|
||||
void InteractiveScale::getMousePosition(void * ud, SoEventCallback * ecb)
|
||||
{
|
||||
InteractiveScale* scale = static_cast<InteractiveScale*>(ud);
|
||||
const SoLocation2Event * l2e = static_cast<const SoLocation2Event *>(ecb->getEvent());
|
||||
Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(ecb->getUserData());
|
||||
|
||||
if (scale->points.size() == 1) {
|
||||
ecb->setHandled();
|
||||
SbVec3f pos3d;
|
||||
|
||||
std::unique_ptr<SoPickedPoint> pp(view->getPointOnRay(l2e->getPosition(), scale->viewProv));
|
||||
if (pp.get()) {
|
||||
pos3d = pp->getPoint();
|
||||
}
|
||||
else {
|
||||
return;
|
||||
}
|
||||
|
||||
Base::Quantity quantity;
|
||||
quantity.setValue((pos3d - scale->points[0]).length());
|
||||
quantity.setUnit(Base::Unit::Length);
|
||||
|
||||
//Update the displayed distance
|
||||
double factor;
|
||||
QString unitStr, valueStr;
|
||||
valueStr = quantity.getUserString(factor, unitStr);
|
||||
scale->measureLabel->string = SbString(valueStr.toUtf8().constData());
|
||||
|
||||
scale->measureLabel->setPoints(scale->getCoordsOnImagePlane(scale->points[0]), scale->getCoordsOnImagePlane(pos3d));
|
||||
}
|
||||
}
|
||||
|
||||
void InteractiveScale::soEventFilter(void* ud, SoEventCallback* ecb)
|
||||
{
|
||||
InteractiveScale* scale = static_cast<InteractiveScale*>(ud);
|
||||
|
||||
const SoEvent* soEvent = ecb->getEvent();
|
||||
if (soEvent->isOfType(SoKeyboardEvent::getClassTypeId())) {
|
||||
/* If user press escape, then we cancel the tool.*/
|
||||
const auto kbe = static_cast<const SoKeyboardEvent*>(soEvent);
|
||||
|
||||
if (kbe->getKey() == SoKeyboardEvent::ESCAPE && kbe->getState() == SoButtonEvent::UP) {
|
||||
ecb->setHandled();
|
||||
ecb->getAction()->setHandled();
|
||||
Q_EMIT scale->scaleCanceled();
|
||||
}
|
||||
}
|
||||
else if (soEvent->isOfType(SoMouseButtonEvent::getClassTypeId())) {
|
||||
const auto mbe = static_cast<const SoMouseButtonEvent*>(soEvent);
|
||||
|
||||
if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN)
|
||||
{
|
||||
ecb->setHandled();
|
||||
scale->findPointOnImagePlane(ecb);
|
||||
}
|
||||
if (mbe->getButton() == SoMouseButtonEvent::BUTTON2 && mbe->getState() == SoButtonEvent::DOWN)
|
||||
{
|
||||
ecb->setHandled();
|
||||
Q_EMIT scale->scaleCanceled();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool InteractiveScale::eventFilter(QObject* object, QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::KeyRelease) {
|
||||
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
|
||||
|
||||
/* If user press enter in the spinbox, then we validate the tool.*/
|
||||
if (keyEvent->key() == Qt::Key_Enter && dynamic_cast<QuantitySpinBox*>(object)) {
|
||||
Q_EMIT scaleRequired();
|
||||
}
|
||||
|
||||
/* If user press escape, then we cancel the tool. Required here as well for when checkbox has focus.*/
|
||||
if (keyEvent->key() == Qt::Key_Escape) {
|
||||
Q_EMIT scaleCanceled();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void InteractiveScale::setPlacement(Base::Placement plc)
|
||||
{
|
||||
placement = plc;
|
||||
double x, y, z, w;
|
||||
placement.getRotation().getValue(x, y, z, w);
|
||||
transform->rotation.setValue(x, y, z, w);
|
||||
Base::Vector3d pos = placement.getPosition();
|
||||
transform->translation.setValue(pos.x, pos.y, pos.z);
|
||||
|
||||
Base::Vector3d RN(0, 0, 1);
|
||||
RN = placement.getRotation().multVec(RN);
|
||||
measureLabel->norm.setValue(SbVec3f(RN.x, RN.y, RN.z));
|
||||
}
|
||||
|
||||
SbVec3f InteractiveScale::getCoordsOnImagePlane(const SbVec3f& point)
|
||||
{
|
||||
// Plane form
|
||||
Base::Vector3d RX(1, 0, 0), RY(0, 1, 0);
|
||||
|
||||
// move to position of Sketch
|
||||
Base::Rotation tmp(placement.getRotation());
|
||||
RX = tmp.multVec(RX);
|
||||
RY = tmp.multVec(RY);
|
||||
Base::Vector3d pos = placement.getPosition();
|
||||
|
||||
//we use pos as the Base because in setPlacement we set transform->translation using placement.getPosition() to fix the Zoffset. But this applies the X & Y translation too.
|
||||
Base::Vector3d S(point[0], point[1], point[2]);
|
||||
S.TransformToCoordinateSystem(pos, RX, RY);
|
||||
|
||||
return SbVec3f(S.x, S.y, 0.);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
TaskImageDialog::TaskImageDialog(Image::ImagePlane* obj)
|
||||
{
|
||||
widget = new TaskImage(obj);
|
||||
Gui::TaskView::TaskBox* taskbox = new Gui::TaskView::TaskBox(
|
||||
Gui::BitmapFactory().pixmap("image-plane"), widget->windowTitle(), true, nullptr);
|
||||
taskbox->groupLayout()->addWidget(widget);
|
||||
Content.push_back(taskbox);
|
||||
}
|
||||
|
||||
void TaskImageDialog::open()
|
||||
{
|
||||
widget->open();
|
||||
}
|
||||
|
||||
bool TaskImageDialog::accept()
|
||||
{
|
||||
widget->accept();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TaskImageDialog::reject()
|
||||
{
|
||||
widget->reject();
|
||||
return true;
|
||||
}
|
||||
|
||||
#include "moc_TaskImage.cpp"
|
||||
@@ -21,11 +21,12 @@
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef GUI_TASKIMAGESCALE_H
|
||||
#define GUI_TASKIMAGESCALE_H
|
||||
#ifndef GUI_TASKIMAGE_H
|
||||
#define GUI_TASKIMAGE_H
|
||||
|
||||
#include <QPointer>
|
||||
#include <Gui/TaskView/TaskDialog.h>
|
||||
#include <Gui/QuantitySpinBox.h>
|
||||
#include <App/DocumentObserver.h>
|
||||
#include <App/ImagePlane.h>
|
||||
#include <memory>
|
||||
@@ -33,9 +34,10 @@
|
||||
|
||||
class SbVec3f;
|
||||
class SoEventCallback;
|
||||
class SoCoordinate3;
|
||||
class SoSeparator;
|
||||
class SoLineSet;
|
||||
class SoDatumLabel;
|
||||
class SoNodeSensor;
|
||||
class SoTransform;
|
||||
|
||||
namespace Gui {
|
||||
|
||||
@@ -46,65 +48,110 @@ class InteractiveScale : public QObject
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit InteractiveScale(View3DInventorViewer* view, ViewProvider* vp);
|
||||
explicit InteractiveScale(View3DInventorViewer* view, ViewProvider* vp, Base::Placement plc);
|
||||
~InteractiveScale();
|
||||
void activate(bool allowOutside);
|
||||
|
||||
bool eventFilter(QObject* object, QEvent* event);
|
||||
void activate();
|
||||
void deactivate();
|
||||
bool isActive() const {
|
||||
return active;
|
||||
}
|
||||
double getDistance() const;
|
||||
double getScaleFactor() const;
|
||||
double getDistance(const SbVec3f&) const;
|
||||
void clearPoints();
|
||||
void setPlacement(Base::Placement plc);
|
||||
|
||||
private:
|
||||
static void getMouseClick(void * ud, SoEventCallback * ecb);
|
||||
static void soEventFilter(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&);
|
||||
void positionWidget();
|
||||
|
||||
/// give the coordinates of a line on the image plane in imagePlane (2D) coordinates
|
||||
SbVec3f getCoordsOnImagePlane(const SbVec3f& point);
|
||||
|
||||
Q_SIGNALS:
|
||||
void selectedPoints(size_t);
|
||||
void scaleRequired();
|
||||
void scaleCanceled();
|
||||
void enableApplyBtn();
|
||||
|
||||
private:
|
||||
bool active;
|
||||
bool allowOutsideImage;
|
||||
SoCoordinate3* coords;
|
||||
Base::Placement placement;
|
||||
SoSeparator* root;
|
||||
SoDatumLabel* measureLabel;
|
||||
SoTransform* transform;
|
||||
QPointer<Gui::View3DInventorViewer> viewer;
|
||||
ViewProvider* viewProv;
|
||||
std::vector<SbVec3f> points;
|
||||
SbVec3f midPoint;
|
||||
QuantitySpinBox* distanceBox;
|
||||
SoNodeSensor* cameraSensor;
|
||||
};
|
||||
|
||||
class Ui_TaskImageScale;
|
||||
class TaskImageScale : public QWidget
|
||||
class Ui_TaskImage;
|
||||
class TaskImage : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TaskImageScale(Image::ImagePlane* obj, QWidget* parent = nullptr);
|
||||
~TaskImageScale() override;
|
||||
explicit TaskImage(Image::ImagePlane* obj, QWidget* parent = nullptr);
|
||||
~TaskImage() override;
|
||||
|
||||
void open();
|
||||
void accept();
|
||||
void reject();
|
||||
|
||||
private:
|
||||
void changeWidth();
|
||||
void changeHeight();
|
||||
void initialiseTransparency();
|
||||
void connectSignals();
|
||||
|
||||
void onInteractiveScale();
|
||||
View3DInventorViewer* getViewer() const;
|
||||
void selectedPoints(size_t num);
|
||||
void scaleImage(double);
|
||||
void startScale();
|
||||
void acceptScale();
|
||||
void rejectScale();
|
||||
void enableApplyBtn();
|
||||
|
||||
void restore(const Base::Placement&);
|
||||
void onPreview();
|
||||
void updateIcon();
|
||||
void updatePlacement();
|
||||
|
||||
private Q_SLOTS:
|
||||
void changeTransparency(int val);
|
||||
void changeWidth(double val);
|
||||
void changeHeight(double val);
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui_TaskImageScale> ui;
|
||||
std::unique_ptr<Ui_TaskImage> ui;
|
||||
QPointer<InteractiveScale> scale;
|
||||
App::WeakPtrT<Image::ImagePlane> feature;
|
||||
double aspectRatio;
|
||||
};
|
||||
|
||||
class TaskImageDialog : public Gui::TaskView::TaskDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TaskImageDialog(Image::ImagePlane* obj);
|
||||
|
||||
public:
|
||||
void open() override;
|
||||
bool accept() override;
|
||||
bool reject() override;
|
||||
|
||||
QDialogButtonBox::StandardButtons getStandardButtons() const override {
|
||||
return QDialogButtonBox::Ok | QDialogButtonBox::Cancel;
|
||||
}
|
||||
|
||||
private:
|
||||
TaskImage* widget;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // GUI_TASKIMAGESCALE_H
|
||||
#endif // GUI_TASKIMAGE_H
|
||||
291
src/Gui/TaskView/TaskImage.ui
Normal file
291
src/Gui/TaskView/TaskImage.ui
Normal file
@@ -0,0 +1,291 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Gui::TaskImage</class>
|
||||
<widget class="QWidget" name="Gui::TaskImage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>421</width>
|
||||
<height>267</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Image plane settings</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_5">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout_8">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Planes</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="XY_radioButton">
|
||||
<property name="text">
|
||||
<string>XY-Plane</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="XZ_radioButton">
|
||||
<property name="text">
|
||||
<string>XZ-Plane</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="YZ_radioButton">
|
||||
<property name="text">
|
||||
<string>YZ-Plane</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="previewLabel">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">Preview</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="Reverse_checkBox">
|
||||
<property name="text">
|
||||
<string>Reverse direction</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelZ">
|
||||
<property name="text">
|
||||
<string>Offset:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="Gui::QuantitySpinBox" name="spinBoxZ">
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">mm</string>
|
||||
</property>
|
||||
<property name="minimum" stdset="0">
|
||||
<double>-999999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum" stdset="0">
|
||||
<double>999999999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelX">
|
||||
<property name="text">
|
||||
<string>X distance:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="Gui::QuantitySpinBox" name="spinBoxX">
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">mm</string>
|
||||
</property>
|
||||
<property name="minimum" stdset="0">
|
||||
<double>-999999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum" stdset="0">
|
||||
<double>999999999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="labelY">
|
||||
<property name="text">
|
||||
<string>Y distance:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="Gui::QuantitySpinBox" name="spinBoxY">
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">mm</string>
|
||||
</property>
|
||||
<property name="minimum" stdset="0">
|
||||
<double>-999999999.000000000000000</double>
|
||||
</property>
|
||||
<property name="maximum" stdset="0">
|
||||
<double>999999999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="labelRotation">
|
||||
<property name="text">
|
||||
<string>Rotation :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="Gui::QuantitySpinBox" name="spinBoxRotation">
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">deg</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelTransparency">
|
||||
<property name="text">
|
||||
<string>Transparency :</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSlider" name="sliderTransparency">
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QSpinBox" name="spinBoxTransparency">
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBox1">
|
||||
<property name="title">
|
||||
<string>Image size</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Width:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="Gui::QuantitySpinBox" name="spinBoxWidth">
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">mm</string>
|
||||
</property>
|
||||
<property name="minimum" stdset="0">
|
||||
<double>0.00000001</double>
|
||||
</property>
|
||||
<property name="maximum" stdset="0">
|
||||
<double>999999999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Height:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="Gui::QuantitySpinBox" name="spinBoxHeight">
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">mm</string>
|
||||
</property>
|
||||
<property name="minimum" stdset="0">
|
||||
<double>0.00000001</double>
|
||||
</property>
|
||||
<property name="maximum" stdset="0">
|
||||
<double>999999999.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0" colspan="2">
|
||||
<widget class="QCheckBox" name="checkBoxRatio">
|
||||
<property name="text">
|
||||
<string>Keep aspect ratio</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="pushButtonScale">
|
||||
<property name="toolTip">
|
||||
<string>Interactively scale the image by setting a length between two points of the image.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Calibrate</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="2">
|
||||
<widget class="QGroupBox" name="groupBoxCalibration">
|
||||
<property name="title">
|
||||
<string>Calibration</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonApply">
|
||||
<property name="text">
|
||||
<string>Apply</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonCancel">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Gui::QuantitySpinBox</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Gui/QuantitySpinBox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,369 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-2.1-or-later
|
||||
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2023 Werner Mayer <wmayer[at]users.sourceforge.net> *
|
||||
* *
|
||||
* This file is part of FreeCAD. *
|
||||
* *
|
||||
* FreeCAD is free software: you can redistribute it and/or modify it *
|
||||
* under the terms of the GNU Lesser General Public License as *
|
||||
* published by the Free Software Foundation, either version 2.1 of the *
|
||||
* License, or (at your option) any later version. *
|
||||
* *
|
||||
* FreeCAD is distributed in the hope that it will be useful, but *
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of *
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
|
||||
* Lesser General Public License for more details. *
|
||||
* *
|
||||
* You should have received a copy of the GNU Lesser General Public *
|
||||
* License along with FreeCAD. If not, see *
|
||||
* <https://www.gnu.org/licenses/>. *
|
||||
* *
|
||||
**************************************************************************/
|
||||
|
||||
#include "PreCompiled.h"
|
||||
#ifndef _PreComp_
|
||||
# include <QDialog>
|
||||
# include <QPushButton>
|
||||
# include <map>
|
||||
# include <Inventor/SoPickedPoint.h>
|
||||
# include <Inventor/events/SoLocation2Event.h>
|
||||
# include <Inventor/events/SoMouseButtonEvent.h>
|
||||
# include <Inventor/nodes/SoBaseColor.h>
|
||||
# include <Inventor/nodes/SoCoordinate3.h>
|
||||
# include <Inventor/nodes/SoLineSet.h>
|
||||
# include <Inventor/nodes/SoAnnotation.h>
|
||||
#endif
|
||||
|
||||
#include <Base/Console.h>
|
||||
#include <Base/Precision.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <App/Document.h>
|
||||
#include <Gui/Application.h>
|
||||
#include <Gui/BitmapFactory.h>
|
||||
#include <Gui/Camera.h>
|
||||
#include <Gui/Document.h>
|
||||
#include <Gui/View3DInventor.h>
|
||||
#include <Gui/View3DInventorViewer.h>
|
||||
#include <Gui/ViewProviderDocumentObject.h>
|
||||
#include <Gui/TaskView/TaskView.h>
|
||||
|
||||
#include "TaskImageScale.h"
|
||||
#include "ui_TaskImageScale.h"
|
||||
|
||||
|
||||
using namespace Gui;
|
||||
|
||||
/* TRANSLATOR Gui::TaskImageScale */
|
||||
|
||||
TaskImageScale::TaskImageScale(Image::ImagePlane* obj, QWidget* parent)
|
||||
: QWidget(parent)
|
||||
, ui(new Ui_TaskImageScale)
|
||||
, feature(obj)
|
||||
, aspectRatio{1.0}
|
||||
{
|
||||
ui->setupUi(this);
|
||||
ui->pushButtonCancel->hide();
|
||||
ui->spinBoxWidth->setValue(obj->getXSizeInPixel());
|
||||
ui->spinBoxHeight->setValue(obj->getYSizeInPixel());
|
||||
|
||||
aspectRatio = obj->XSize.getValue() / obj->YSize.getValue();
|
||||
|
||||
connect(ui->spinBoxWidth, qOverload<int>(&QSpinBox::valueChanged),
|
||||
this, &TaskImageScale::changeWidth);
|
||||
connect(ui->spinBoxHeight, qOverload<int>(&QSpinBox::valueChanged),
|
||||
this, &TaskImageScale::changeHeight);
|
||||
connect(ui->pushButtonScale, &QPushButton::clicked,
|
||||
this, &TaskImageScale::onInteractiveScale);
|
||||
connect(ui->pushButtonCancel, &QPushButton::clicked,
|
||||
this, &TaskImageScale::rejectScale);
|
||||
}
|
||||
|
||||
TaskImageScale::~TaskImageScale()
|
||||
{
|
||||
if (scale) {
|
||||
if (scale->isActive()) {
|
||||
scale->deactivate();
|
||||
}
|
||||
scale->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
void TaskImageScale::changeWidth()
|
||||
{
|
||||
if (!feature.expired()) {
|
||||
int value = ui->spinBoxWidth->value();
|
||||
feature->setXSizeInPixel(value);
|
||||
|
||||
if (ui->checkBoxRatio->isChecked()) {
|
||||
QSignalBlocker block(ui->spinBoxWidth);
|
||||
ui->spinBoxHeight->setValue(int(double(value) / aspectRatio));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void TaskImageScale::changeHeight()
|
||||
{
|
||||
if (!feature.expired()) {
|
||||
int value = ui->spinBoxHeight->value();
|
||||
feature->setYSizeInPixel(value);
|
||||
|
||||
if (ui->checkBoxRatio->isChecked()) {
|
||||
QSignalBlocker block(ui->spinBoxHeight);
|
||||
ui->spinBoxWidth->setValue(int(double(value) * aspectRatio));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
View3DInventorViewer* TaskImageScale::getViewer() const
|
||||
{
|
||||
if (!feature.expired()) {
|
||||
auto vp = Application::Instance->getViewProvider(feature.get());
|
||||
auto doc = static_cast<ViewProviderDocumentObject*>(vp)->getDocument();
|
||||
auto view = dynamic_cast<View3DInventor*>(doc->getViewOfViewProvider(vp));
|
||||
if (view) {
|
||||
return view->getViewer();
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TaskImageScale::selectedPoints(size_t num)
|
||||
{
|
||||
if (num == 1) {
|
||||
ui->labelInstruction->setText(tr("Select second point"));
|
||||
}
|
||||
else if (num == 2) {
|
||||
ui->labelInstruction->setText(tr("Enter desired distance between the points"));
|
||||
ui->pushButtonScale->setEnabled(true);
|
||||
ui->quantitySpinBox->setEnabled(true);
|
||||
ui->quantitySpinBox->setValue(scale->getDistance());
|
||||
}
|
||||
}
|
||||
|
||||
void TaskImageScale::scaleImage(double factor)
|
||||
{
|
||||
if (!feature.expired()) {
|
||||
feature->XSize.setValue(feature->XSize.getValue() * factor);
|
||||
feature->YSize.setValue(feature->YSize.getValue() * factor);
|
||||
|
||||
QSignalBlocker blockW(ui->spinBoxWidth);
|
||||
ui->spinBoxWidth->setValue(feature->getXSizeInPixel());
|
||||
QSignalBlocker blockH(ui->spinBoxHeight);
|
||||
ui->spinBoxHeight->setValue(feature->getYSizeInPixel());
|
||||
}
|
||||
}
|
||||
|
||||
void TaskImageScale::startScale()
|
||||
{
|
||||
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->pushButtonScale->setText(tr("Accept"));
|
||||
ui->pushButtonCancel->show();
|
||||
ui->quantitySpinBox->setEnabled(false);
|
||||
}
|
||||
|
||||
void TaskImageScale::acceptScale()
|
||||
{
|
||||
scaleImage(ui->quantitySpinBox->value().getValue() / scale->getDistance());
|
||||
rejectScale();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
void TaskImageScale::onInteractiveScale()
|
||||
{
|
||||
if (!feature.expired() && !scale) {
|
||||
View3DInventorViewer* viewer = getViewer();
|
||||
if (viewer) {
|
||||
auto vp = Application::Instance->getViewProvider(feature.get());
|
||||
scale = new InteractiveScale(viewer, vp);
|
||||
connect(scale, &InteractiveScale::selectedPoints,
|
||||
this, &TaskImageScale::selectedPoints);
|
||||
}
|
||||
}
|
||||
|
||||
if (scale) {
|
||||
if (scale->isActive()) {
|
||||
acceptScale();
|
||||
}
|
||||
else {
|
||||
startScale();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
InteractiveScale::InteractiveScale(View3DInventorViewer* view, ViewProvider* vp)
|
||||
: active{false}
|
||||
, allowOutsideImage{false}
|
||||
, viewer{view}
|
||||
, viewProv{vp}
|
||||
{
|
||||
coords = new SoCoordinate3;
|
||||
coords->ref();
|
||||
root = new SoAnnotation;
|
||||
root->ref();
|
||||
|
||||
root->addChild(coords);
|
||||
|
||||
SoBaseColor* color = new SoBaseColor;
|
||||
color->rgb.setValue(1.0F, 0.0F, 0.0F);
|
||||
root->addChild(color);
|
||||
root->addChild(new SoLineSet);
|
||||
}
|
||||
|
||||
InteractiveScale::~InteractiveScale()
|
||||
{
|
||||
coords->unref();
|
||||
root->unref();
|
||||
}
|
||||
|
||||
void InteractiveScale::activate(bool allowOutside)
|
||||
{
|
||||
if (viewer) {
|
||||
static_cast<SoSeparator*>(viewer->getSceneGraph())->addChild(root);
|
||||
viewer->setEditing(true);
|
||||
viewer->addEventCallback(SoLocation2Event::getClassTypeId(), InteractiveScale::getMousePosition, this);
|
||||
viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), InteractiveScale::getMouseClick, this);
|
||||
viewer->setSelectionEnabled(false);
|
||||
viewer->getWidget()->setCursor(QCursor(Qt::CrossCursor));
|
||||
active = true;
|
||||
allowOutsideImage = allowOutside;
|
||||
}
|
||||
}
|
||||
|
||||
void InteractiveScale::deactivate()
|
||||
{
|
||||
if (viewer) {
|
||||
static_cast<SoSeparator*>(viewer->getSceneGraph())->removeChild(root);
|
||||
viewer->setEditing(false);
|
||||
viewer->removeEventCallback(SoLocation2Event::getClassTypeId(), InteractiveScale::getMousePosition, this);
|
||||
viewer->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), InteractiveScale::getMouseClick, this);
|
||||
viewer->setSelectionEnabled(true);
|
||||
viewer->getWidget()->setCursor(QCursor(Qt::ArrowCursor));
|
||||
active = false;
|
||||
}
|
||||
}
|
||||
|
||||
double InteractiveScale::getDistance() const
|
||||
{
|
||||
if (points.size() < 2)
|
||||
return 0.0;
|
||||
|
||||
return (points[0] - points[1]).length();
|
||||
}
|
||||
|
||||
double InteractiveScale::getDistance(const SbVec3f& pt) const
|
||||
{
|
||||
if (points.empty())
|
||||
return 0.0;
|
||||
|
||||
return (points[0] - pt).length();
|
||||
}
|
||||
|
||||
void InteractiveScale::clearPoints()
|
||||
{
|
||||
points.clear();
|
||||
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<const SoMouseButtonEvent *>(ecb->getEvent());
|
||||
Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(ecb->getUserData());
|
||||
std::unique_ptr<SoPickedPoint> 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<const SoMouseButtonEvent *>(ecb->getEvent());
|
||||
Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(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<InteractiveScale*>(ud);
|
||||
const SoMouseButtonEvent * mbe = static_cast<const SoMouseButtonEvent *>(ecb->getEvent());
|
||||
|
||||
if (mbe->getButton() == SoMouseButtonEvent::BUTTON1 && mbe->getState() == SoButtonEvent::DOWN) {
|
||||
ecb->setHandled();
|
||||
scale->findPointOnPlane(ecb);
|
||||
}
|
||||
}
|
||||
|
||||
void InteractiveScale::getMousePosition(void * ud, SoEventCallback * ecb)
|
||||
{
|
||||
InteractiveScale* scale = static_cast<InteractiveScale*>(ud);
|
||||
const SoLocation2Event * l2e = static_cast<const SoLocation2Event *>(ecb->getEvent());
|
||||
Gui::View3DInventorViewer* view = static_cast<Gui::View3DInventorViewer*>(ecb->getUserData());
|
||||
|
||||
if (scale->points.size() == 1) {
|
||||
ecb->setHandled();
|
||||
auto pos2d = l2e->getPosition();
|
||||
auto pos3d = view->getPointOnFocalPlane(pos2d);
|
||||
scale->coords->point.set1Value(1, pos3d);
|
||||
}
|
||||
}
|
||||
|
||||
#include "moc_TaskImageScale.cpp"
|
||||
@@ -1,184 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Gui::TaskImageScale</class>
|
||||
<widget class="QWidget" name="Gui::TaskImageScale">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>421</width>
|
||||
<height>267</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Scale image</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string>Image size</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="0" column="0">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Width:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxWidth">
|
||||
<property name="suffix">
|
||||
<string notr="true"> px</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Height:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxHeight">
|
||||
<property name="suffix">
|
||||
<string notr="true"> px</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxRatio">
|
||||
<property name="text">
|
||||
<string>Keep aspect ratio</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonScale">
|
||||
<property name="toolTip">
|
||||
<string>Interactively scale the image</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Interactive</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="pushButtonCancel">
|
||||
<property name="text">
|
||||
<string>Cancel</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>136</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxOutside">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Allow points outside the image</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelDistance">
|
||||
<property name="text">
|
||||
<string>Desired distance:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Gui::QuantitySpinBox" name="quantitySpinBox">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="unit" stdset="0">
|
||||
<string notr="true">mm</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelInstruction">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>Gui::QuantitySpinBox</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>Gui/QuantitySpinBox.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<tabstops>
|
||||
<tabstop>spinBoxWidth</tabstop>
|
||||
<tabstop>spinBoxHeight</tabstop>
|
||||
<tabstop>checkBoxRatio</tabstop>
|
||||
<tabstop>pushButtonScale</tabstop>
|
||||
<tabstop>pushButtonCancel</tabstop>
|
||||
<tabstop>checkBoxOutside</tabstop>
|
||||
<tabstop>quantitySpinBox</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -41,8 +41,7 @@
|
||||
#include <Gui/ActionFunction.h>
|
||||
#include <Gui/BitmapFactory.h>
|
||||
#include <Gui/Control.h>
|
||||
#include <Gui/TaskView/TaskOrientation.h>
|
||||
#include <Gui/TaskView/TaskImageScale.h>
|
||||
#include <Gui/TaskView/TaskImage.h>
|
||||
#include <App/ImagePlane.h>
|
||||
|
||||
#include "ViewProviderImagePlane.h"
|
||||
@@ -159,12 +158,9 @@ bool ViewProviderImagePlane::doubleClicked()
|
||||
|
||||
void ViewProviderImagePlane::manipulateImage()
|
||||
{
|
||||
auto dialog = new TaskOrientationDialog(
|
||||
dynamic_cast<App::GeoFeature*>(getObject())
|
||||
);
|
||||
dialog->addTaskBox(new TaskImageScale(
|
||||
auto dialog = new TaskImageDialog(
|
||||
dynamic_cast<Image::ImagePlane*>(getObject())
|
||||
));
|
||||
);
|
||||
|
||||
Gui::Control().showDialog(dialog);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
|
||||
#include "PropertyConstraintListItem.h"
|
||||
#include "SketcherSettings.h"
|
||||
#include "SoDatumLabel.h"
|
||||
#include "SoZoomTranslation.h"
|
||||
#include "ViewProviderPython.h"
|
||||
#include "ViewProviderSketch.h"
|
||||
@@ -125,7 +124,6 @@ PyMOD_INIT_FUNC(SketcherGui)
|
||||
SketcherGui::ViewProviderPython ::init();
|
||||
SketcherGui::ViewProviderCustom ::init();
|
||||
SketcherGui::ViewProviderCustomPython ::init();
|
||||
SketcherGui::SoDatumLabel ::initClass();
|
||||
SketcherGui::SoZoomTranslation ::initClass();
|
||||
SketcherGui::PropertyConstraintListItem ::init();
|
||||
SketcherGui::ViewProviderSketchGeometryExtension ::init();
|
||||
|
||||
@@ -87,8 +87,6 @@ SET(SketcherGui_SRCS
|
||||
PreCompiled.h
|
||||
SoZoomTranslation.cpp
|
||||
SoZoomTranslation.h
|
||||
SoDatumLabel.cpp
|
||||
SoDatumLabel.h
|
||||
PropertyConstraintListItem.h
|
||||
PropertyConstraintListItem.cpp
|
||||
TaskSketcherConstraints.ui
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include <Gui/Tools.h>
|
||||
#include <Gui/Utilities.h>
|
||||
#include <Gui/Inventor/SmSwitchboard.h>
|
||||
#include <Gui/SoDatumLabel.h>
|
||||
#include <Mod/Part/App/Geometry.h>
|
||||
#include <Mod/Sketcher/App/GeometryFacade.h>
|
||||
#include <Mod/Sketcher/App/SolverGeometryExtension.h>
|
||||
@@ -58,13 +59,13 @@
|
||||
#include <Mod/Sketcher/App/GeoList.h>
|
||||
|
||||
#include "EditModeConstraintCoinManager.h"
|
||||
#include "SoDatumLabel.h"
|
||||
#include "SoZoomTranslation.h"
|
||||
#include "ViewProviderSketch.h"
|
||||
#include "ViewProviderSketchCoinAttorney.h"
|
||||
#include "Utils.h"
|
||||
|
||||
|
||||
using namespace Gui;
|
||||
using namespace SketcherGui;
|
||||
using namespace Sketcher;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user