/*************************************************************************** * Copyright (c) 2015 Stefan Tröger * * * * This file is part of the FreeCAD CAx development system. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Library General Public * * License as published by the Free Software Foundation; either * * version 2 of the License, or (at your option) any later version. * * * * This library 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 Library General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this library; see the file COPYING.LIB. If not, * * write to the Free Software Foundation, Inc., 59 Temple Place, * * Suite 330, Boston, MA 02111-1307, USA * * * ***************************************************************************/ #include "PreCompiled.h" #ifndef _PreComp_ #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include "TaskPrimitiveParameters.h" #include "ui_TaskPrimitiveParameters.h" using namespace PartDesignGui; // clang-format off TaskBoxPrimitives::TaskBoxPrimitives(ViewProviderPrimitive* vp, QWidget* parent) : TaskBox(QPixmap(),tr("Primitive Parameters"), true, parent) , ui(new Ui_DlgPrimitives) , vp(vp) { vp->showPreview(true); vp->showPreviousFeature(true); proxy = new QWidget(this); ui->setupUi(proxy); this->groupLayout()->addWidget(proxy); int index = 0; switch(getObject()->getPrimitiveType()) { case PartDesign::FeaturePrimitive::Box: index = 1; ui->boxLength->setValue(getObject()->Length.getValue()); ui->boxLength->bind(getObject()->Length); ui->boxHeight->setValue(getObject()->Height.getValue()); ui->boxHeight->bind(getObject()->Height); ui->boxWidth->setValue(getObject()->Width.getValue()); ui->boxWidth->bind(getObject()->Width); ui->boxLength->setMinimum(getObject()->Length.getMinimum()); ui->boxLength->setMaximum(getObject()->Length.getMaximum()); ui->boxWidth->setMinimum(getObject()->Width.getMinimum()); ui->boxWidth->setMaximum(getObject()->Width.getMaximum()); ui->boxHeight->setMinimum(getObject()->Height.getMinimum()); ui->boxHeight->setMaximum(getObject()->Height.getMaximum()); break; case PartDesign::FeaturePrimitive::Cylinder: index = 2; ui->cylinderAngle->setValue(getObject()->Angle.getValue()); ui->cylinderAngle->bind(getObject()->Angle); ui->cylinderHeight->setValue(getObject()->Height.getValue()); ui->cylinderHeight->bind(getObject()->Height); ui->cylinderRadius->setValue(getObject()->Radius.getValue()); ui->cylinderRadius->bind(getObject()->Radius); ui->cylinderXSkew->setValue(getObject()->FirstAngle.getValue()); ui->cylinderXSkew->bind(getObject()->FirstAngle); ui->cylinderYSkew->setValue(getObject()->SecondAngle.getValue()); ui->cylinderYSkew->bind(getObject()->SecondAngle); ui->cylinderAngle->setMaximum(getObject()->Angle.getMaximum()); ui->cylinderAngle->setMinimum(getObject()->Angle.getMinimum()); ui->cylinderHeight->setMaximum(getObject()->Height.getMaximum()); ui->cylinderHeight->setMinimum(getObject()->Height.getMinimum()); ui->cylinderRadius->setMaximum(getObject()->Radius.getMaximum()); ui->cylinderRadius->setMinimum(getObject()->Radius.getMinimum()); break; case PartDesign::FeaturePrimitive::Sphere: index = 4; ui->sphereAngle1->setValue(getObject()->Angle1.getValue()); ui->sphereAngle1->bind(getObject()->Angle1); ui->sphereAngle2->setValue(getObject()->Angle2.getValue()); ui->sphereAngle2->bind(getObject()->Angle2); ui->sphereAngle3->setValue(getObject()->Angle3.getValue()); ui->sphereAngle3->bind(getObject()->Angle3); ui->sphereRadius->setValue(getObject()->Radius.getValue()); ui->sphereRadius->bind(getObject()->Radius); ui->sphereAngle1->setMaximum(ui->sphereAngle2->rawValue()); // must geometrically be <= than sphereAngle2 ui->sphereAngle1->setMinimum(getObject()->Angle1.getMinimum()); ui->sphereAngle2->setMaximum(getObject()->Angle2.getMaximum()); ui->sphereAngle2->setMinimum(ui->sphereAngle1->rawValue()); ui->sphereAngle3->setMaximum(getObject()->Angle3.getMaximum()); ui->sphereAngle3->setMinimum(getObject()->Angle3.getMinimum()); ui->sphereRadius->setMaximum(getObject()->Radius.getMaximum()); ui->sphereRadius->setMinimum(getObject()->Radius.getMinimum()); break; case PartDesign::FeaturePrimitive::Cone: index = 3; ui->coneAngle->setValue(getObject()->Angle.getValue()); ui->coneAngle->bind(getObject()->Angle); ui->coneHeight->setValue(getObject()->Height.getValue()); ui->coneHeight->bind(getObject()->Height); ui->coneRadius1->setValue(getObject()->Radius1.getValue()); ui->coneRadius1->bind(getObject()->Radius1); ui->coneRadius2->setValue(getObject()->Radius2.getValue()); ui->coneRadius2->bind(getObject()->Radius2); ui->coneAngle->setMaximum(getObject()->Angle.getMaximum()); ui->coneAngle->setMinimum(getObject()->Angle.getMinimum()); ui->coneHeight->setMaximum(getObject()->Height.getMaximum()); ui->coneHeight->setMinimum(getObject()->Height.getMinimum()); ui->coneRadius1->setMaximum(getObject()->Radius1.getMaximum()); ui->coneRadius1->setMinimum(getObject()->Radius1.getMinimum()); ui->coneRadius2->setMaximum(getObject()->Radius2.getMaximum()); ui->coneRadius2->setMinimum(getObject()->Radius2.getMinimum()); break; case PartDesign::FeaturePrimitive::Ellipsoid: index = 5; ui->ellipsoidAngle1->setValue(getObject()->Angle1.getValue()); ui->ellipsoidAngle1->bind(getObject()->Angle1); ui->ellipsoidAngle2->setValue(getObject()->Angle2.getValue()); ui->ellipsoidAngle2->bind(getObject()->Angle2); ui->ellipsoidAngle3->setValue(getObject()->Angle3.getValue()); ui->ellipsoidAngle3->bind(getObject()->Angle3); ui->ellipsoidRadius1->setValue(getObject()->Radius1.getValue()); ui->ellipsoidRadius1->bind(getObject()->Radius1); ui->ellipsoidRadius2->setValue(getObject()->Radius2.getValue()); ui->ellipsoidRadius2->bind(getObject()->Radius2); ui->ellipsoidRadius3->setValue(getObject()->Radius3.getValue()); ui->ellipsoidRadius3->bind(getObject()->Radius3); ui->ellipsoidAngle1->setMaximum(ui->ellipsoidAngle2->rawValue()); // must geometrically be <= than sphereAngle2 ui->ellipsoidAngle1->setMinimum(getObject()->Angle1.getMinimum()); ui->ellipsoidAngle2->setMaximum(getObject()->Angle2.getMaximum()); ui->ellipsoidAngle2->setMinimum(ui->ellipsoidAngle1->rawValue()); ui->ellipsoidAngle3->setMaximum(getObject()->Angle3.getMaximum()); ui->ellipsoidAngle3->setMinimum(getObject()->Angle3.getMinimum()); ui->ellipsoidRadius1->setMinimum(getObject()->Radius1.getMinimum()); ui->ellipsoidRadius1->setMaximum(getObject()->Radius1.getMaximum()); ui->ellipsoidRadius2->setMinimum(getObject()->Radius2.getMinimum()); ui->ellipsoidRadius2->setMaximum(getObject()->Radius2.getMaximum()); ui->ellipsoidRadius3->setMinimum(getObject()->Radius3.getMinimum()); ui->ellipsoidRadius3->setMaximum(getObject()->Radius3.getMaximum()); break; case PartDesign::FeaturePrimitive::Torus: index = 6; ui->torusAngle1->setValue(getObject()->Angle1.getValue()); ui->torusAngle1->bind(getObject()->Angle1); ui->torusAngle2->setValue(getObject()->Angle2.getValue()); ui->torusAngle2->bind(getObject()->Angle2); ui->torusAngle3->setValue(getObject()->Angle3.getValue()); ui->torusAngle3->bind(getObject()->Angle3); ui->torusRadius1->setValue(getObject()->Radius1.getValue()); ui->torusRadius1->bind(getObject()->Radius1); ui->torusRadius2->setValue(getObject()->Radius2.getValue()); ui->torusRadius2->bind(getObject()->Radius2); ui->torusAngle1->setMaximum(ui->torusAngle2->rawValue()); // must geometrically be <= than sphereAngle2 ui->torusAngle1->setMinimum(getObject()->Angle1.getMinimum()); ui->torusAngle2->setMaximum(getObject()->Angle2.getMaximum()); ui->torusAngle2->setMinimum(ui->torusAngle1->rawValue()); ui->torusAngle3->setMaximum(getObject()->Angle3.getMaximum()); ui->torusAngle3->setMinimum(getObject()->Angle3.getMinimum()); // this is the outer radius that must not be smaller than the inner one // otherwise the geometry is impossible and we can even get a crash: // https://forum.freecad.org/viewtopic.php?f=3&t=44467 ui->torusRadius1->setMaximum(getObject()->Radius1.getMaximum()); ui->torusRadius1->setMinimum(ui->torusRadius2->rawValue()); ui->torusRadius2->setMaximum(ui->torusRadius1->rawValue()); ui->torusRadius2->setMinimum(getObject()->Radius2.getMinimum()); break; case PartDesign::FeaturePrimitive::Prism: index = 7; ui->prismPolygon->setValue(getObject()->Polygon.getValue()); ui->prismCircumradius->setValue(getObject()->Circumradius.getValue()); ui->prismCircumradius->bind(getObject()->Circumradius); ui->prismHeight->setValue(getObject()->Height.getValue()); ui->prismHeight->bind(getObject()->Height); ui->prismXSkew->setValue(getObject()->FirstAngle.getValue()); ui->prismXSkew->bind(getObject()->FirstAngle); ui->prismYSkew->setValue(getObject()->SecondAngle.getValue()); ui->prismYSkew->bind(getObject()->SecondAngle); ui->prismCircumradius->setMaximum(getObject()->Circumradius.getMaximum()); ui->prismCircumradius->setMinimum(getObject()->Circumradius.getMinimum()); ui->prismHeight->setMaximum(getObject()->Height.getMaximum()); ui->prismHeight->setMinimum(getObject()->Height.getMinimum()); break; case PartDesign::FeaturePrimitive::Wedge: index = 8; ui->wedgeXmax->setValue(getObject()->Xmax.getValue()); ui->wedgeXmax->bind(getObject()->Xmax); ui->wedgeXmin->setValue(getObject()->Xmin.getValue()); ui->wedgeXmin->bind(getObject()->Xmin); ui->wedgeX2max->setValue(getObject()->X2max.getValue()); ui->wedgeX2max->bind(getObject()->X2max); ui->wedgeX2min->setValue(getObject()->X2min.getValue()); ui->wedgeX2min->bind(getObject()->X2min); ui->wedgeYmax->setValue(getObject()->Ymax.getValue()); ui->wedgeYmax->bind(getObject()->Ymax); ui->wedgeYmin->setValue(getObject()->Ymin.getValue()); ui->wedgeYmin->bind(getObject()->Ymin); ui->wedgeZmax->setValue(getObject()->Zmax.getValue()); ui->wedgeZmax->bind(getObject()->Zmax); ui->wedgeZmin->setValue(getObject()->Zmin.getValue()); ui->wedgeZmin->bind(getObject()->Zmin); ui->wedgeZ2max->setValue(getObject()->Z2max.getValue()); ui->wedgeZ2max->bind(getObject()->Z2max); ui->wedgeZ2min->setValue(getObject()->Z2min.getValue()); ui->wedgeZ2min->bind(getObject()->Z2min); ui->wedgeXmin->setMinimum(std::numeric_limits::min()); ui->wedgeXmin->setMaximum(ui->wedgeXmax->rawValue()); // must be < than wedgeXmax ui->wedgeYmin->setMinimum(std::numeric_limits::min()); ui->wedgeYmin->setMaximum(ui->wedgeYmax->rawValue()); // must be < than wedgeYmax ui->wedgeZmin->setMinimum(std::numeric_limits::min()); ui->wedgeZmin->setMaximum(ui->wedgeZmax->rawValue()); // must be < than wedgeZmax ui->wedgeX2min->setMinimum(std::numeric_limits::min());; ui->wedgeX2min->setMaximum(ui->wedgeX2max->rawValue()); // must be <= than wedgeXmax ui->wedgeZ2min->setMinimum(std::numeric_limits::min());; ui->wedgeZ2min->setMaximum(ui->wedgeZ2max->rawValue()); // must be <= than wedgeXmax ui->wedgeXmax->setMinimum(ui->wedgeXmin->rawValue()); ui->wedgeXmax->setMaximum(std::numeric_limits::max()); ui->wedgeYmax->setMinimum(ui->wedgeYmin->rawValue()); ui->wedgeYmax->setMaximum(std::numeric_limits::max()); ui->wedgeZmax->setMinimum(ui->wedgeZmin->rawValue()); ui->wedgeZmax->setMaximum(std::numeric_limits::max()); ui->wedgeX2max->setMinimum(ui->wedgeX2min->rawValue()); ui->wedgeX2max->setMaximum(std::numeric_limits::max()); ui->wedgeZ2max->setMinimum(ui->wedgeZ2min->rawValue()); ui->wedgeZ2max->setMaximum(std::numeric_limits::max()); break; } ui->widgetStack->setCurrentIndex(index); ui->widgetStack->setMinimumSize(ui->widgetStack->widget(index)->minimumSize()); for(int i=0; iwidgetStack->count(); ++i) { if(i != index) ui->widgetStack->widget(i)->setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored)); } Gui::Document* doc = vp->getDocument(); this->attachDocument(doc); //show the parts coordinate system axis for selection if(PartDesign::Body * body = PartDesign::Body::findBodyOf(getObject())) { try { App::Origin *origin = body->getOrigin(); Gui::ViewProviderCoordinateSystem* vpOrigin {}; vpOrigin = static_cast(Gui::Application::Instance->getViewProvider(origin)); vpOrigin->setTemporaryVisibility(Gui::DatumElement::Planes | Gui::DatumElement::Axes); } catch (const Base::Exception &ex) { Base::Console().error ("%s\n", ex.what () ); } } // box connect(ui->boxLength, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onBoxLengthChanged); connect(ui->boxWidth, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onBoxWidthChanged); connect(ui->boxHeight, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onBoxHeightChanged); // cylinder connect(ui->cylinderRadius, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onCylinderRadiusChanged); connect(ui->cylinderHeight, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onCylinderHeightChanged); connect(ui->cylinderXSkew, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onCylinderXSkewChanged); connect(ui->cylinderYSkew, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onCylinderYSkewChanged); connect(ui->cylinderAngle, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onCylinderAngleChanged); // cone connect(ui->coneRadius1, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onConeRadius1Changed); connect(ui->coneRadius2, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onConeRadius2Changed); connect(ui->coneAngle, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onConeAngleChanged); connect(ui->coneHeight, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onConeHeightChanged); // sphere connect(ui->sphereRadius, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onSphereRadiusChanged); connect(ui->sphereAngle1, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onSphereAngle1Changed); connect(ui->sphereAngle2, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onSphereAngle2Changed); connect(ui->sphereAngle3, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onSphereAngle3Changed); // ellipsoid connect(ui->ellipsoidRadius1, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onEllipsoidRadius1Changed); connect(ui->ellipsoidRadius2, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onEllipsoidRadius2Changed); connect(ui->ellipsoidRadius3, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onEllipsoidRadius3Changed); connect(ui->ellipsoidAngle1, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onEllipsoidAngle1Changed); connect(ui->ellipsoidAngle2, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onEllipsoidAngle2Changed); connect(ui->ellipsoidAngle3, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onEllipsoidAngle3Changed); // torus connect(ui->torusRadius1, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onTorusRadius1Changed); connect(ui->torusRadius2, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onTorusRadius2Changed); connect(ui->torusAngle1, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onTorusAngle1Changed); connect(ui->torusAngle2, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onTorusAngle2Changed); connect(ui->torusAngle3, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onTorusAngle3Changed); //prism connect(ui->prismCircumradius, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onPrismCircumradiusChanged); connect(ui->prismHeight, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onPrismHeightChanged); connect(ui->prismXSkew, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onPrismXSkewChanged); connect(ui->prismYSkew, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onPrismYSkewChanged); connect(ui->prismPolygon, qOverload(&QSpinBox::valueChanged), this, &TaskBoxPrimitives::onPrismPolygonChanged); // wedge connect(ui->wedgeXmax, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onWedgeXmaxChanged); connect(ui->wedgeXmin, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onWedgeXminChanged); connect(ui->wedgeYmax, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onWedgeYmaxChanged); connect(ui->wedgeYmin, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onWedgeYminChanged); connect(ui->wedgeZmax, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onWedgeZmaxChanged); connect(ui->wedgeZmin, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onWedgeZminChanged); connect(ui->wedgeX2max, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onWedgeX2maxChanged); connect(ui->wedgeX2min, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onWedgeX2minChanged); connect(ui->wedgeZ2max, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onWedgeZ2maxChanged); connect(ui->wedgeZ2min, qOverload(&Gui::QuantitySpinBox::valueChanged), this, &TaskBoxPrimitives::onWedgeZ2minChanged); } // clang-format on /* * Destroys the object and frees any allocated resources */ TaskBoxPrimitives::~TaskBoxPrimitives() { // hide the parts coordinate system axis for selection try { auto obj = getObject(); if (PartDesign::Body* body = obj ? PartDesign::Body::findBodyOf(obj) : nullptr) { App::Origin* origin = body->getOrigin(); Gui::ViewProviderCoordinateSystem* vpOrigin; vpOrigin = static_cast( Gui::Application::Instance->getViewProvider(origin)); vpOrigin->resetTemporaryVisibility(); } } catch (const Base::Exception& ex) { Base::Console().error("%s\n", ex.what()); } } void TaskBoxPrimitives::slotDeletedObject(const Gui::ViewProviderDocumentObject& Obj) { if (this->vp == &Obj) { this->vp = nullptr; } } void TaskBoxPrimitives::onBoxHeightChanged(double v) { if (auto box = getObject()) { box->Height.setValue(v); box->recomputeFeature(); } } void TaskBoxPrimitives::onBoxWidthChanged(double v) { if (auto box = getObject()) { box->Width.setValue(v); box->recomputeFeature(); } } void TaskBoxPrimitives::onBoxLengthChanged(double v) { if (auto box = getObject()) { box->Length.setValue(v); box->recomputeFeature(); } } void TaskBoxPrimitives::onCylinderAngleChanged(double v) { if (auto cyl = getObject()) { cyl->Angle.setValue(v); cyl->recomputeFeature(); } } void TaskBoxPrimitives::onCylinderHeightChanged(double v) { if (auto cyl = getObject()) { cyl->Height.setValue(v); cyl->recomputeFeature(); } } void TaskBoxPrimitives::onCylinderRadiusChanged(double v) { if (auto cyl = getObject()) { cyl->Radius.setValue(v); cyl->recomputeFeature(); } } void TaskBoxPrimitives::onCylinderXSkewChanged(double v) { if (auto cyl = getObject()) { // we must assure that if the user incremented from e.g. 85 degree with the // spin buttons, they do not end at 90.0 but at 89.9999 which is shown rounded to 90 degree if ((v < 90.0) && (v > -90.0)) { cyl->FirstAngle.setValue(v); } else { if (v == 90.0) { cyl->FirstAngle.setValue(cyl->FirstAngle.getMaximum()); } else if (v == -90.0) { cyl->FirstAngle.setValue(cyl->FirstAngle.getMinimum()); } ui->cylinderXSkew->setValue(cyl->FirstAngle.getQuantityValue()); } cyl->recomputeFeature(); } } void TaskBoxPrimitives::onCylinderYSkewChanged(double v) { if (auto cyl = getObject()) { // we must assure that if the user incremented from e.g. 85 degree with the // spin buttons, they do not end at 90.0 but at 89.9999 which is shown rounded to 90 degree if ((v < 90.0) && (v > -90.0)) { cyl->SecondAngle.setValue(v); } else { if (v == 90.0) { cyl->SecondAngle.setValue(cyl->SecondAngle.getMaximum()); } else if (v == -90.0) { cyl->SecondAngle.setValue(cyl->SecondAngle.getMinimum()); } ui->cylinderYSkew->setValue(cyl->SecondAngle.getQuantityValue()); } cyl->recomputeFeature(); } } void TaskBoxPrimitives::onSphereAngle1Changed(double v) { if (auto sph = getObject()) { ui->sphereAngle2->setMinimum(v); // Angle1 must geometrically be <= than Angle2 sph->Angle1.setValue(v); sph->recomputeFeature(); } } void TaskBoxPrimitives::onSphereAngle2Changed(double v) { if (auto sph = getObject()) { ui->sphereAngle1->setMaximum(v); // Angle1 must geometrically be <= than Angle2 sph->Angle2.setValue(v); sph->recomputeFeature(); } } void TaskBoxPrimitives::onSphereAngle3Changed(double v) { if (auto sph = getObject()) { sph->Angle3.setValue(v); sph->recomputeFeature(); } } void TaskBoxPrimitives::onSphereRadiusChanged(double v) { if (auto sph = getObject()) { sph->Radius.setValue(v); sph->recomputeFeature(); } } void TaskBoxPrimitives::onConeAngleChanged(double v) { if (auto cone = getObject()) { cone->Angle.setValue(v); cone->recomputeFeature(); } } void TaskBoxPrimitives::onConeHeightChanged(double v) { if (auto cone = getObject()) { cone->Height.setValue(v); cone->recomputeFeature(); } } void TaskBoxPrimitives::onConeRadius1Changed(double v) { if (auto cone = getObject()) { cone->Radius1.setValue(v); cone->recomputeFeature(); } } void TaskBoxPrimitives::onConeRadius2Changed(double v) { if (auto cone = getObject()) { cone->Radius2.setValue(v); cone->recomputeFeature(); } } void TaskBoxPrimitives::onEllipsoidAngle1Changed(double v) { if (auto ell = getObject()) { ui->ellipsoidAngle2->setMinimum(v); // Angle1 must geometrically be <= than Angle2 ell->Angle1.setValue(v); ell->recomputeFeature(); } } void TaskBoxPrimitives::onEllipsoidAngle2Changed(double v) { if (auto ell = getObject()) { ui->ellipsoidAngle1->setMaximum(v); // Angle1 must geometrically be <= than Angle22 ell->Angle2.setValue(v); ell->recomputeFeature(); } } void TaskBoxPrimitives::onEllipsoidAngle3Changed(double v) { if (auto ell = getObject()) { ell->Angle3.setValue(v); ell->recomputeFeature(); } } void TaskBoxPrimitives::onEllipsoidRadius1Changed(double v) { if (auto ell = getObject()) { ell->Radius1.setValue(v); ell->recomputeFeature(); } } void TaskBoxPrimitives::onEllipsoidRadius2Changed(double v) { if (auto ell = getObject()) { ell->Radius2.setValue(v); ell->recomputeFeature(); } } void TaskBoxPrimitives::onEllipsoidRadius3Changed(double v) { if (auto ell = getObject()) { ell->Radius3.setValue(v); ell->recomputeFeature(); } } void TaskBoxPrimitives::onTorusAngle1Changed(double v) { if (auto tor = getObject()) { ui->torusAngle2->setMinimum(v); // Angle1 must geometrically be <= than Angle2 tor->Angle1.setValue(v); tor->recomputeFeature(); } } void TaskBoxPrimitives::onTorusAngle2Changed(double v) { if (auto tor = getObject()) { ui->torusAngle1->setMaximum(v); // Angle1 must geometrically be <= than Angle2 tor->Angle2.setValue(v); tor->recomputeFeature(); } } void TaskBoxPrimitives::onTorusAngle3Changed(double v) { if (auto tor = getObject()) { tor->Angle3.setValue(v); tor->recomputeFeature(); } } void TaskBoxPrimitives::onTorusRadius1Changed(double v) { if (auto tor = getObject()) { // this is the outer radius that must not be smaller than the inner one // otherwise the geometry is impossible and we can even get a crash: // https://forum.freecad.org/viewtopic.php?f=3&t=44467 ui->torusRadius2->setMaximum(v); tor->Radius1.setValue(v); tor->recomputeFeature(); } } void TaskBoxPrimitives::onTorusRadius2Changed(double v) { if (auto tor = getObject()) { ui->torusRadius1->setMinimum(v); tor->Radius2.setValue(v); tor->recomputeFeature(); } } void TaskBoxPrimitives::onPrismCircumradiusChanged(double v) { if (auto prim = getObject()) { prim->Circumradius.setValue(v); prim->recomputeFeature(); } } void TaskBoxPrimitives::onPrismHeightChanged(double v) { if (auto prim = getObject()) { prim->Height.setValue(v); prim->recomputeFeature(); } } void TaskBoxPrimitives::onPrismXSkewChanged(double v) { if (auto prim = getObject()) { // we must assure that if the user incremented from e.g. 85 degree with the // spin buttons, they do not end at 90.0 but at 89.9999 which is shown rounded to 90 degree if ((v < 90.0) && (v > -90.0)) { prim->FirstAngle.setValue(v); } else { if (v == 90.0) { prim->FirstAngle.setValue(89.99999); } else if (v == -90.0) { prim->FirstAngle.setValue(-89.99999); } ui->prismXSkew->setValue(prim->FirstAngle.getQuantityValue()); } prim->recomputeFeature(); } } void TaskBoxPrimitives::onPrismYSkewChanged(double v) { if (auto prim = getObject()) { // we must assure that if the user incremented from e.g. 85 degree with the // spin buttons, they do not end at 90.0 but at 89.9999 which is shown rounded to 90 degree if ((v < 90.0) && (v > -90.0)) { prim->SecondAngle.setValue(v); } else { if (v == 90.0) { prim->SecondAngle.setValue(89.99999); } else if (v == -90.0) { prim->SecondAngle.setValue(-89.99999); } ui->prismYSkew->setValue(prim->SecondAngle.getQuantityValue()); } prim->recomputeFeature(); } } void TaskBoxPrimitives::onPrismPolygonChanged(int v) { if (auto prim = getObject()) { prim->Polygon.setValue(v); prim->recomputeFeature(); } } void TaskBoxPrimitives::onWedgeX2minChanged(double v) { if (auto wedge = getObject()) { ui->wedgeX2max->setMinimum(v); // wedgeX2min must be <= than wedgeX2max wedge->X2min.setValue(v); wedge->recomputeFeature(); } } void TaskBoxPrimitives::onWedgeX2maxChanged(double v) { if (auto wedge = getObject()) { ui->wedgeX2min->setMaximum(v); // wedgeX2min must be <= than wedgeX2max wedge->X2max.setValue(v); wedge->recomputeFeature(); } } void TaskBoxPrimitives::onWedgeXminChanged(double v) { if (auto wedge = getObject()) { ui->wedgeXmax->setMinimum(v); wedge->Xmin.setValue(v); wedge->recomputeFeature(); } } void TaskBoxPrimitives::onWedgeXmaxChanged(double v) { if (auto wedge = getObject()) { ui->wedgeXmin->setMaximum(v); // must be < than wedgeXmax wedge->Xmax.setValue(v); wedge->recomputeFeature(); } } void TaskBoxPrimitives::onWedgeYminChanged(double v) { if (auto wedge = getObject()) { ui->wedgeYmax->setMinimum(v); // must be > than wedgeYmin wedge->Ymin.setValue(v); wedge->recomputeFeature(); } } void TaskBoxPrimitives::onWedgeYmaxChanged(double v) { if (auto wedge = getObject()) { ui->wedgeYmin->setMaximum(v); // must be < than wedgeYmax wedge->Ymax.setValue(v); wedge->recomputeFeature(); } } void TaskBoxPrimitives::onWedgeZ2minChanged(double v) { if (auto wedge = getObject()) { ui->wedgeZ2max->setMinimum(v); // must be >= than wedgeZ2min wedge->Z2min.setValue(v); wedge->recomputeFeature(); } } void TaskBoxPrimitives::onWedgeZ2maxChanged(double v) { if (auto wedge = getObject()) { ui->wedgeZ2min->setMaximum(v); // must be <= than wedgeZ2max wedge->Z2max.setValue(v); wedge->recomputeFeature(); } } void TaskBoxPrimitives::onWedgeZminChanged(double v) { if (auto wedge = getObject()) { ui->wedgeZmax->setMinimum(v); // must be > than wedgeZmin wedge->Zmin.setValue(v); wedge->recomputeFeature(); } } void TaskBoxPrimitives::onWedgeZmaxChanged(double v) { if (auto wedge = getObject()) { ui->wedgeZmin->setMaximum(v); // must be < than wedgeZmax wedge->Zmax.setValue(v); wedge->recomputeFeature(); } } bool TaskBoxPrimitives::setPrimitive(App::DocumentObject* obj) { try { App::Document* doc = App::GetApplication().getActiveDocument(); if (!doc) { return false; } std::string cmd; std::string name(Gui::Command::getObjectCmd(obj)); Base::QuantityFormat format(Base::QuantityFormat::Fixed, Base::UnitsApi::getDecimals()); switch (ui->widgetStack->currentIndex()) { case 1: // box cmd = fmt::format("{0}.Length='{1}'\n" "{0}.Width='{2}'\n" "{0}.Height='{3}'\n", name, ui->boxLength->value().getSafeUserString(), ui->boxWidth->value().getSafeUserString(), ui->boxHeight->value().getSafeUserString()); break; case 2: // cylinder cmd = fmt::format("{0}.Radius='{1}'\n" "{0}.Height='{2}'\n" "{0}.Angle='{3}'\n" "{0}.FirstAngle='{4}'\n" "{0}.SecondAngle='{5}'\n", name, ui->cylinderRadius->value().getSafeUserString(), ui->cylinderHeight->value().getSafeUserString(), ui->cylinderAngle->value().getSafeUserString(), ui->cylinderXSkew->value().getSafeUserString(), ui->cylinderYSkew->value().getSafeUserString()); break; case 3: // cone cmd = fmt::format("{0}.Radius1='{1}'\n" "{0}.Radius2='{2}'\n" "{0}.Height='{3}'\n" "{0}.Angle='{4}'\n", name, ui->coneRadius1->value().getSafeUserString(), ui->coneRadius2->value().getSafeUserString(), ui->coneHeight->value().getSafeUserString(), ui->coneAngle->value().getSafeUserString()); break; case 4: // sphere cmd = fmt::format("{0}.Radius='{1}'\n" "{0}.Angle1='{2}'\n" "{0}.Angle2='{3}'\n" "{0}.Angle3='{4}'\n", name, ui->sphereRadius->value().getSafeUserString(), ui->sphereAngle1->value().getSafeUserString(), ui->sphereAngle2->value().getSafeUserString(), ui->sphereAngle3->value().getSafeUserString()); break; case 5: // ellipsoid cmd = fmt::format("{0}.Radius1='{1}'\n" "{0}.Radius2='{2}'\n" "{0}.Radius3='{3}'\n" "{0}.Angle1='{4}'\n" "{0}.Angle2='{5}'\n" "{0}.Angle3='{6}'\n", name, ui->ellipsoidRadius1->value().getSafeUserString(), ui->ellipsoidRadius2->value().getSafeUserString(), ui->ellipsoidRadius3->value().getSafeUserString(), ui->ellipsoidAngle1->value().getSafeUserString(), ui->ellipsoidAngle2->value().getSafeUserString(), ui->ellipsoidAngle3->value().getSafeUserString()); break; case 6: // torus cmd = fmt::format("{0}.Radius1='{1}'\n" "{0}.Radius2='{2}'\n" "{0}.Angle1='{3}'\n" "{0}.Angle2='{4}'\n" "{0}.Angle3='{5}'\n", name, ui->torusRadius1->value().getSafeUserString(), ui->torusRadius2->value().getSafeUserString(), ui->torusAngle1->value().getSafeUserString(), ui->torusAngle2->value().getSafeUserString(), ui->torusAngle3->value().getSafeUserString()); break; case 7: // prism cmd = fmt::format("{0}.Polygon={1}\n" "{0}.Circumradius='{2}'\n" "{0}.Height='{3}'\n" "{0}.FirstAngle='{4}'\n" "{0}.SecondAngle='{5}'\n", name, ui->prismPolygon->value(), ui->prismCircumradius->value().getSafeUserString(), ui->prismHeight->value().getSafeUserString(), ui->prismXSkew->value().getSafeUserString(), ui->prismYSkew->value().getSafeUserString()); break; case 8: // wedge // Xmin/max, Ymin/max and Zmin/max must each not be equal if (ui->wedgeXmin->value().getValue() == ui->wedgeXmax->value().getValue()) { QMessageBox::warning(Gui::getMainWindow(), tr("Invalid wedge parameters"), tr("X min must not be equal to X max!")); return false; } else if (ui->wedgeYmin->value().getValue() == ui->wedgeYmax->value().getValue()) { QMessageBox::warning(Gui::getMainWindow(), tr("Invalid wedge parameters"), tr("Y min must not be equal to Y max!")); return false; } else if (ui->wedgeZmin->value().getValue() == ui->wedgeZmax->value().getValue()) { QMessageBox::warning(Gui::getMainWindow(), tr("Invalid wedge parameters"), tr("Z min must not be equal to Z max!")); return false; } cmd = fmt::format("{0}.Xmin='{1}'\n" "{0}.Ymin='{2}'\n" "{0}.Zmin='{3}'\n" "{0}.X2min='{4}'\n" "{0}.Z2min='{5}'\n" "{0}.Xmax='{6}'\n" "{0}.Ymax='{7}'\n" "{0}.Zmax='{8}'\n" "{0}.X2max='{9}'\n" "{0}.Z2max='{10}'\n", name, ui->wedgeXmin->value().getSafeUserString(), ui->wedgeYmin->value().getSafeUserString(), ui->wedgeZmin->value().getSafeUserString(), ui->wedgeX2min->value().getSafeUserString(), ui->wedgeZ2min->value().getSafeUserString(), ui->wedgeXmax->value().getSafeUserString(), ui->wedgeYmax->value().getSafeUserString(), ui->wedgeZmax->value().getSafeUserString(), ui->wedgeX2max->value().getSafeUserString(), ui->wedgeZ2max->value().getSafeUserString()); break; default: break; } // Execute the Python block // No need to open a transaction because this is already done in the command // class or when starting to edit a primitive. Gui::Command::runCommand(Gui::Command::Doc, cmd.c_str()); Gui::Command::runCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); } catch (const Base::PyException& e) { QMessageBox::warning(this, tr("Create primitive"), QApplication::translate("Exception", e.what())); return false; } return true; } TaskDlgPrimitiveParameters::TaskDlgPrimitiveParameters(ViewProviderPrimitive* PrimitiveView) : TaskDlgFeatureParameters(PrimitiveView) , vp_prm(PrimitiveView) { assert(PrimitiveView); primitive = new TaskBoxPrimitives(PrimitiveView); Content.push_back(primitive); parameter = new PartGui::TaskAttacher(PrimitiveView, nullptr, QString(), tr("Attachment")); Content.push_back(parameter); Content.push_back(preview); } TaskDlgPrimitiveParameters::~TaskDlgPrimitiveParameters() = default; bool TaskDlgPrimitiveParameters::accept() { bool primitiveOK = primitive->setPrimitive(vp_prm->getObject()); if (!primitiveOK) { return primitiveOK; } Gui::Command::doCommand(Gui::Command::Doc, "App.ActiveDocument.recompute()"); Gui::Command::doCommand(Gui::Command::Gui, "Gui.activeDocument().resetEdit()"); return true; } bool TaskDlgPrimitiveParameters::reject() { // roll back the done things Gui::Command::abortCommand(); Gui::Command::doCommand(Gui::Command::Gui, "Gui.activeDocument().resetEdit()"); return true; } QDialogButtonBox::StandardButtons TaskDlgPrimitiveParameters::getStandardButtons() const { return Gui::TaskView::TaskDialog::getStandardButtons(); } #include "moc_TaskPrimitiveParameters.cpp"