From b9b42a52f435080ec1ab24bbd34a381842180084 Mon Sep 17 00:00:00 2001 From: donovaly Date: Sun, 11 Apr 2021 21:39:28 +0200 Subject: [PATCH] [PD] fix primitives issues - to avoid invalid results: - don't allow to set equal radii for cones - don't allow to set equal wedge parameters - don't allow zero quantities like e.g. the box width - use full internal precision because it must be possible to create an e.g. 23.5 um wide box and using the default 2 displayed digits - take spinbox limits from App - add missing tooltips - remove disturbing commented out line from Workbench.cpp - some coding style issues fixed automatically by the MSVC IDE --- src/Mod/PartDesign/App/FeaturePrimitive.cpp | 76 ++++--- .../Gui/TaskPrimitiveParameters.cpp | 201 ++++++++++-------- .../PartDesign/Gui/TaskPrimitiveParameters.h | 2 +- .../PartDesign/Gui/TaskPrimitiveParameters.ui | 28 ++- src/Mod/PartDesign/Gui/Workbench.cpp | 1 - 5 files changed, 174 insertions(+), 134 deletions(-) diff --git a/src/Mod/PartDesign/App/FeaturePrimitive.cpp b/src/Mod/PartDesign/App/FeaturePrimitive.cpp index b97eb878dd08..93ae307c8036 100644 --- a/src/Mod/PartDesign/App/FeaturePrimitive.cpp +++ b/src/Mod/PartDesign/App/FeaturePrimitive.cpp @@ -56,10 +56,13 @@ using namespace PartDesign; namespace PartDesign { -const App::PropertyQuantityConstraint::Constraints torusRangeV = {-180.0,180.0,1.0}; -const App::PropertyQuantityConstraint::Constraints angleRangeU = {0.0,360.0,1.0}; -const App::PropertyQuantityConstraint::Constraints angleRangeV = {-90.0,90.0,1.0}; -const App::PropertyQuantityConstraint::Constraints quantityRange = {0.0,FLT_MAX,0.1}; +const App::PropertyQuantityConstraint::Constraints torusRangeV = { -180.0, 180.0, 1.0 }; +const App::PropertyQuantityConstraint::Constraints angleRangeU = { 0.0, 360.0, 1.0 }; +const App::PropertyQuantityConstraint::Constraints angleRangeV = { -90.0, 90.0, 1.0 }; +// it turned out that OCC cannot e.g. create a box with a width of Precision::Confusion() +// with two times Precision::Confusion() all geometric primitives can be created +const App::PropertyQuantityConstraint::Constraints quantityRange = { 2 * Precision::Confusion(), FLT_MAX, 0.1 }; +const App::PropertyQuantityConstraint::Constraints quantityRangeZero = { 0.0, FLT_MAX, 0.1 }; PROPERTY_SOURCE_WITH_EXTENSIONS(PartDesign::FeaturePrimitive, PartDesign::FeatureAddSub) @@ -77,12 +80,12 @@ App::DocumentObjectExecReturn* FeaturePrimitive::execute(const TopoDS_Shape& pri //if we have no base we just add the standard primitive shape TopoDS_Shape base; - try{ + try { //if we have a base shape we need to make sure that it does not get our transformation to BRepBuilderAPI_Transform trsf(getBaseShape(), getLocation().Transformation().Inverted(), true); base = trsf.Shape(); } - catch(const Base::Exception&) { + catch (const Base::Exception&) { //as we use this for preview we can add it even if useless for subtractive AddSubShape.setValue(primitiveShape); @@ -95,7 +98,7 @@ App::DocumentObjectExecReturn* FeaturePrimitive::execute(const TopoDS_Shape& pri return App::DocumentObject::StdReturn; } - if(getAddSubType() == FeatureAddSub::Additive) { + if (getAddSubType() == FeatureAddSub::Additive) { BRepAlgoAPI_Fuse mkFuse(base, primitiveShape); if (!mkFuse.IsDone()) @@ -115,7 +118,7 @@ App::DocumentObjectExecReturn* FeaturePrimitive::execute(const TopoDS_Shape& pri Shape.setValue(getSolid(boolOp)); AddSubShape.setValue(primitiveShape); } - else if(getAddSubType() == FeatureAddSub::Subtractive) { + else if (getAddSubType() == FeatureAddSub::Subtractive) { BRepAlgoAPI_Cut mkCut(base, primitiveShape); if (!mkCut.IsDone()) @@ -200,10 +203,8 @@ App::DocumentObjectExecReturn* Box::execute(void) if (L < Precision::Confusion()) return new App::DocumentObjectExecReturn("Length of box too small"); - if (W < Precision::Confusion()) return new App::DocumentObjectExecReturn("Width of box too small"); - if (H < Precision::Confusion()) return new App::DocumentObjectExecReturn("Height of box too small"); @@ -213,7 +214,6 @@ App::DocumentObjectExecReturn* Box::execute(void) return FeaturePrimitive::execute(mkBox.Shape()); } catch (Standard_Failure& e) { - return new App::DocumentObjectExecReturn(e.GetMessageString()); } } @@ -269,7 +269,6 @@ App::DocumentObjectExecReturn* Cylinder::execute(void) return FeaturePrimitive::execute(result); } catch (Standard_Failure& e) { - return new App::DocumentObjectExecReturn(e.GetMessageString()); } @@ -313,13 +312,12 @@ App::DocumentObjectExecReturn* Sphere::execute(void) return new App::DocumentObjectExecReturn("Radius of sphere too small"); try { BRepPrimAPI_MakeSphere mkSphere(Radius.getValue(), - Angle1.getValue()/180.0f*M_PI, - Angle2.getValue()/180.0f*M_PI, - Angle3.getValue()/180.0f*M_PI); + Base::toRadians(Angle1.getValue()), + Base::toRadians(Angle2.getValue()), + Base::toRadians(Angle3.getValue())); return FeaturePrimitive::execute(mkSphere.Shape()); } catch (Standard_Failure& e) { - return new App::DocumentObjectExecReturn(e.GetMessageString()); } @@ -350,8 +348,8 @@ Cone::Cone() ADD_PROPERTY_TYPE(Height,(10.0),"Cone",App::Prop_None,"The height of the cone"); ADD_PROPERTY_TYPE(Angle,(360.0),"Cone",App::Prop_None,"The angle of the cone"); Angle.setConstraints(&angleRangeU); - Radius1.setConstraints(&quantityRange); - Radius2.setConstraints(&quantityRange); + Radius1.setConstraints(&quantityRangeZero); + Radius2.setConstraints(&quantityRangeZero); Height.setConstraints(&quantityRange); primitiveType = FeaturePrimitive::Cone; @@ -359,10 +357,12 @@ Cone::Cone() App::DocumentObjectExecReturn* Cone::execute(void) { - if (Radius1.getValue() < 0) - return new App::DocumentObjectExecReturn("Radius of cone too small"); - if (Radius2.getValue() < 0) - return new App::DocumentObjectExecReturn("Radius of cone too small"); + if (Radius1.getValue() < 0.0) + return new App::DocumentObjectExecReturn("Radius of cone cannot be negative"); + if (Radius2.getValue() < 0.0) + return new App::DocumentObjectExecReturn("Radius of cone cannot be negative"); + if (Radius1.getValue() == Radius2.getValue()) + return new App::DocumentObjectExecReturn("The radii for cones must not be equal"); if (Height.getValue() < Precision::Confusion()) return new App::DocumentObjectExecReturn("Height of cone too small"); try { @@ -370,12 +370,11 @@ App::DocumentObjectExecReturn* Cone::execute(void) BRepPrimAPI_MakeCone mkCone(Radius1.getValue(), Radius2.getValue(), Height.getValue(), - Angle.getValue()/180.0f*M_PI); + Base::toRadians(Angle.getValue())); return FeaturePrimitive::execute(mkCone.Shape()); } catch (Standard_Failure& e) { - return new App::DocumentObjectExecReturn(e.GetMessageString()); } @@ -402,12 +401,12 @@ PROPERTY_SOURCE(PartDesign::Ellipsoid, PartDesign::FeaturePrimitive) Ellipsoid::Ellipsoid() { - ADD_PROPERTY_TYPE(Radius1,(2.0),"Ellipsoid",App::Prop_None,"The radius of the ellipsoid"); + ADD_PROPERTY_TYPE(Radius1,(2.0),"Ellipsoid",App::Prop_None,"Radius in local z-direction"); Radius1.setConstraints(&quantityRange); - ADD_PROPERTY_TYPE(Radius2,(4.0),"Ellipsoid",App::Prop_None,"The radius of the ellipsoid"); + ADD_PROPERTY_TYPE(Radius2,(4.0),"Ellipsoid",App::Prop_None,"Radius in local x-direction"); Radius2.setConstraints(&quantityRange); - ADD_PROPERTY_TYPE(Radius3,(0.0),"Ellipsoid",App::Prop_None,"The radius of the ellipsoid"); - Radius3.setConstraints(&quantityRange); + ADD_PROPERTY_TYPE(Radius3,(0.0),"Ellipsoid",App::Prop_None,"Radius in local y-direction\nIf zero, it is equal to Radius2"); + Radius3.setConstraints(&quantityRangeZero); ADD_PROPERTY_TYPE(Angle1,(-90.0f),"Ellipsoid",App::Prop_None,"The angle of the ellipsoid"); Angle1.setConstraints(&angleRangeV); ADD_PROPERTY_TYPE(Angle2,(90.0f),"Ellipsoid",App::Prop_None,"The angle of the ellipsoid"); @@ -432,9 +431,9 @@ App::DocumentObjectExecReturn* Ellipsoid::execute(void) gp_Ax2 ax2(pnt,dir); BRepPrimAPI_MakeSphere mkSphere(ax2, Radius2.getValue(), - Angle1.getValue()/180.0f*M_PI, - Angle2.getValue()/180.0f*M_PI, - Angle3.getValue()/180.0f*M_PI); + Base::toRadians(Angle1.getValue()), + Base::toRadians(Angle2.getValue()), + Base::toRadians(Angle3.getValue())); Standard_Real scaleX = 1.0; Standard_Real scaleZ = Radius1.getValue()/Radius2.getValue(); // issue #1798: A third radius has been introduced. To be backward @@ -457,7 +456,6 @@ App::DocumentObjectExecReturn* Ellipsoid::execute(void) return FeaturePrimitive::execute(mkTrsf.Shape()); } catch (Standard_Failure& e) { - return new App::DocumentObjectExecReturn(e.GetMessageString()); } @@ -490,9 +488,9 @@ PROPERTY_SOURCE(PartDesign::Torus, PartDesign::FeaturePrimitive) Torus::Torus() { - ADD_PROPERTY_TYPE(Radius1,(10.0),"Torus",App::Prop_None,"The radius of the torus"); + ADD_PROPERTY_TYPE(Radius1,(10.0),"Torus",App::Prop_None,"Radius in local xy-plane"); Radius1.setConstraints(&quantityRange); - ADD_PROPERTY_TYPE(Radius2,(2.0),"Torus",App::Prop_None,"The radius of the torus"); + ADD_PROPERTY_TYPE(Radius2,(2.0),"Torus",App::Prop_None,"Radius in local xz-plane"); Radius2.setConstraints(&quantityRange); ADD_PROPERTY_TYPE(Angle1,(-180.0),"Torus",App::Prop_None,"The angle of the torus"); Angle1.setConstraints(&torusRangeV); @@ -515,9 +513,9 @@ App::DocumentObjectExecReturn* Torus::execute(void) #if 0 BRepPrimAPI_MakeTorus mkTorus(Radius1.getValue(), Radius2.getValue(), - Angle1.getValue()/180.0f*M_PI, - Angle2.getValue()/180.0f*M_PI, - Angle3.getValue()/180.0f*M_PI); + Base::toRadians(Angle1.getValue()), + Base::toRadians(Angle2.getValue()), + Base::toRadians(Angle3.getValue())); return FeaturePrimitive::execute(mkTorus.Solid()); #else Part::TopoShape shape; @@ -639,7 +637,7 @@ Wedge::Wedge() App::DocumentObjectExecReturn* Wedge::execute(void) { - double xmin = Xmin.getValue(); + double xmin = Xmin.getValue(); double ymin = Ymin.getValue(); double zmin = Zmin.getValue(); double z2min = Z2min.getValue(); @@ -650,7 +648,6 @@ App::DocumentObjectExecReturn* Wedge::execute(void) double z2max = Z2max.getValue(); double x2max = X2max.getValue(); - double dx = xmax-xmin; double dy = ymax-ymin; double dz = zmax-zmin; @@ -683,7 +680,6 @@ App::DocumentObjectExecReturn* Wedge::execute(void) return FeaturePrimitive::execute(mkSolid.Solid()); } catch (Standard_Failure& e) { - return new App::DocumentObjectExecReturn(e.GetMessageString()); } diff --git a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp index c8f9e40f89a6..9563e773cf36 100644 --- a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -72,12 +73,12 @@ TaskBoxPrimitives::TaskBoxPrimitives(ViewProviderPrimitive* vp, QWidget* parent) ui->boxHeight->bind(static_cast(vp->getObject())->Height); ui->boxWidth->setValue(static_cast(vp->getObject())->Width.getValue()); ui->boxWidth->bind(static_cast(vp->getObject())->Width); - ui->boxLength->setMinimum(0.0); - ui->boxLength->setMaximum(INT_MAX); - ui->boxWidth->setMinimum(0.0); - ui->boxWidth->setMaximum(INT_MAX); - ui->boxHeight->setMinimum(0.0); - ui->boxHeight->setMaximum(INT_MAX); + ui->boxLength->setMinimum(static_cast(vp->getObject())->Length.getMinimum()); + ui->boxLength->setMaximum(static_cast(vp->getObject())->Length.getMaximum()); + ui->boxWidth->setMinimum(static_cast(vp->getObject())->Width.getMinimum()); + ui->boxWidth->setMaximum(static_cast(vp->getObject())->Width.getMaximum()); + ui->boxHeight->setMinimum(static_cast(vp->getObject())->Height.getMinimum()); + ui->boxHeight->setMaximum(static_cast(vp->getObject())->Height.getMaximum()); break; case PartDesign::FeaturePrimitive::Cylinder: index = 2; @@ -93,10 +94,10 @@ TaskBoxPrimitives::TaskBoxPrimitives(ViewProviderPrimitive* vp, QWidget* parent) ui->cylinderYSkew->bind(static_cast(vp->getObject())->SecondAngle); ui->cylinderAngle->setMaximum(static_cast(vp->getObject())->Angle.getMaximum()); ui->cylinderAngle->setMinimum(static_cast(vp->getObject())->Angle.getMinimum()); - ui->cylinderHeight->setMaximum(INT_MAX); - ui->cylinderHeight->setMinimum(0.0); - ui->cylinderRadius->setMaximum(INT_MAX); - ui->cylinderRadius->setMinimum(0.0); + ui->cylinderHeight->setMaximum(static_cast(vp->getObject())->Height.getMaximum()); + ui->cylinderHeight->setMinimum(static_cast(vp->getObject())->Height.getMinimum()); + ui->cylinderRadius->setMaximum(static_cast(vp->getObject())->Radius.getMaximum()); + ui->cylinderRadius->setMinimum(static_cast(vp->getObject())->Radius.getMinimum()); break; case PartDesign::FeaturePrimitive::Sphere: index = 4; @@ -114,8 +115,8 @@ TaskBoxPrimitives::TaskBoxPrimitives(ViewProviderPrimitive* vp, QWidget* parent) ui->sphereAngle2->setMinimum(ui->sphereAngle1->rawValue()); ui->sphereAngle3->setMaximum(static_cast(vp->getObject())->Angle3.getMaximum()); ui->sphereAngle3->setMinimum(static_cast(vp->getObject())->Angle3.getMinimum()); - ui->sphereRadius->setMaximum(INT_MAX); - ui->sphereRadius->setMinimum(0.0); + ui->sphereRadius->setMaximum(static_cast(vp->getObject())->Radius.getMaximum()); + ui->sphereRadius->setMinimum(static_cast(vp->getObject())->Radius.getMinimum()); break; case PartDesign::FeaturePrimitive::Cone: index = 3; @@ -129,12 +130,12 @@ TaskBoxPrimitives::TaskBoxPrimitives(ViewProviderPrimitive* vp, QWidget* parent) ui->coneRadius2->bind(static_cast(vp->getObject())->Radius2); ui->coneAngle->setMaximum(static_cast(vp->getObject())->Angle.getMaximum()); ui->coneAngle->setMinimum(static_cast(vp->getObject())->Angle.getMinimum()); - ui->coneHeight->setMaximum(INT_MAX); - ui->coneHeight->setMinimum(0.0); - ui->coneRadius1->setMaximum(INT_MAX); - ui->coneRadius1->setMinimum(0.0); - ui->coneRadius2->setMaximum(INT_MAX); - ui->coneRadius2->setMinimum(0.0); + ui->coneHeight->setMaximum(static_cast(vp->getObject())->Height.getMaximum()); + ui->coneHeight->setMinimum(static_cast(vp->getObject())->Height.getMinimum()); + ui->coneRadius1->setMaximum(static_cast(vp->getObject())->Radius1.getMaximum()); + ui->coneRadius1->setMinimum(static_cast(vp->getObject())->Radius1.getMinimum()); + ui->coneRadius2->setMaximum(static_cast(vp->getObject())->Radius2.getMaximum()); + ui->coneRadius2->setMinimum(static_cast(vp->getObject())->Radius2.getMinimum()); break; case PartDesign::FeaturePrimitive::Ellipsoid: index = 5; @@ -156,12 +157,12 @@ TaskBoxPrimitives::TaskBoxPrimitives(ViewProviderPrimitive* vp, QWidget* parent) ui->ellipsoidAngle2->setMinimum(ui->ellipsoidAngle1->rawValue()); ui->ellipsoidAngle3->setMaximum(static_cast(vp->getObject())->Angle3.getMaximum()); ui->ellipsoidAngle3->setMinimum(static_cast(vp->getObject())->Angle3.getMinimum()); - ui->ellipsoidRadius1->setMinimum(0.0); - ui->ellipsoidRadius1->setMaximum(INT_MAX); - ui->ellipsoidRadius2->setMinimum(0.0); - ui->ellipsoidRadius2->setMaximum(INT_MAX); - ui->ellipsoidRadius3->setMinimum(0.0); - ui->ellipsoidRadius3->setMaximum(INT_MAX); + ui->ellipsoidRadius1->setMinimum(static_cast(vp->getObject())->Radius1.getMinimum()); + ui->ellipsoidRadius1->setMaximum(static_cast(vp->getObject())->Radius1.getMaximum()); + ui->ellipsoidRadius2->setMinimum(static_cast(vp->getObject())->Radius2.getMinimum()); + ui->ellipsoidRadius2->setMaximum(static_cast(vp->getObject())->Radius2.getMaximum()); + ui->ellipsoidRadius3->setMinimum(static_cast(vp->getObject())->Radius3.getMinimum()); + ui->ellipsoidRadius3->setMaximum(static_cast(vp->getObject())->Radius3.getMaximum()); break; case PartDesign::FeaturePrimitive::Torus: index = 6; @@ -184,10 +185,10 @@ TaskBoxPrimitives::TaskBoxPrimitives(ViewProviderPrimitive* vp, QWidget* parent) // 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.freecadweb.org/viewtopic.php?f=3&t=44467 - ui->torusRadius1->setMaximum(INT_MAX); + ui->torusRadius1->setMaximum(static_cast(vp->getObject())->Radius1.getMaximum()); ui->torusRadius1->setMinimum(ui->torusRadius2->rawValue()); ui->torusRadius2->setMaximum(ui->torusRadius1->rawValue()); - ui->torusRadius2->setMinimum(0.0); + ui->torusRadius2->setMinimum(static_cast(vp->getObject())->Radius2.getMinimum()); break; case PartDesign::FeaturePrimitive::Prism: index = 7; @@ -200,10 +201,10 @@ TaskBoxPrimitives::TaskBoxPrimitives(ViewProviderPrimitive* vp, QWidget* parent) ui->prismXSkew->bind(static_cast(vp->getObject())->FirstAngle); ui->prismYSkew->setValue(static_cast(vp->getObject())->SecondAngle.getValue()); ui->prismYSkew->bind(static_cast(vp->getObject())->SecondAngle); - ui->prismCircumradius->setMaximum(INT_MAX); - ui->prismCircumradius->setMinimum(0.0); - ui->prismHeight->setMaximum(INT_MAX); - ui->prismHeight->setMinimum(0.0); + ui->prismCircumradius->setMaximum(static_cast(vp->getObject())->Circumradius.getMaximum()); + ui->prismCircumradius->setMinimum(static_cast(vp->getObject())->Circumradius.getMinimum()); + ui->prismHeight->setMaximum(static_cast(vp->getObject())->Height.getMaximum()); + ui->prismHeight->setMinimum(static_cast(vp->getObject())->Height.getMinimum()); break; case PartDesign::FeaturePrimitive::Wedge: index = 8; @@ -228,11 +229,11 @@ TaskBoxPrimitives::TaskBoxPrimitives(ViewProviderPrimitive* vp, QWidget* parent) ui->wedgeZ2min->setValue(static_cast(vp->getObject())->Z2min.getValue()); ui->wedgeZ2min->bind(static_cast(vp->getObject())->Z2min); ui->wedgeXmin->setMinimum(INT_MIN); - ui->wedgeXmin->setMaximum(ui->wedgeXmax->rawValue()); // must be <= than wedgeXmax + ui->wedgeXmin->setMaximum(ui->wedgeXmax->rawValue()); // must be < than wedgeXmax ui->wedgeYmin->setMinimum(INT_MIN); - ui->wedgeYmin->setMaximum(ui->wedgeYmax->rawValue()); // must be <= than wedgeYmax + ui->wedgeYmin->setMaximum(ui->wedgeYmax->rawValue()); // must be < than wedgeYmax ui->wedgeZmin->setMinimum(INT_MIN); - ui->wedgeZmin->setMaximum(ui->wedgeZmax->rawValue()); // must be <= than wedgeZmax + ui->wedgeZmin->setMaximum(ui->wedgeZmax->rawValue()); // must be < than wedgeZmax ui->wedgeX2min->setMinimum(INT_MIN); ui->wedgeX2min->setMaximum(ui->wedgeX2max->rawValue()); // must be <= than wedgeXmax ui->wedgeZ2min->setMinimum(INT_MIN); @@ -468,12 +469,14 @@ void TaskBoxPrimitives::onConeHeightChanged(double v) { } void TaskBoxPrimitives::onConeRadius1Changed(double v) { + PartDesign::Cone* sph = static_cast(vp->getObject()); sph->Radius1.setValue(v); vp->getObject()->getDocument()->recomputeFeature(vp->getObject()); } void TaskBoxPrimitives::onConeRadius2Changed(double v) { + PartDesign::Cone* sph = static_cast(vp->getObject()); sph->Radius2.setValue(v); vp->getObject()->getDocument()->recomputeFeature(vp->getObject()); @@ -630,65 +633,65 @@ void TaskBoxPrimitives::onWedgeXminChanged(double v) { void TaskBoxPrimitives::onWedgeXmaxChanged(double v) { PartDesign::Wedge* sph = static_cast(vp->getObject()); - ui->wedgeXmin->setMaximum(v); // must be <= than wedgeXmax + ui->wedgeXmin->setMaximum(v); // must be < than wedgeXmax sph->Xmax.setValue(v); vp->getObject()->getDocument()->recomputeFeature(vp->getObject()); } void TaskBoxPrimitives::onWedgeYminChanged(double v) { PartDesign::Wedge* sph = static_cast(vp->getObject()); - ui->wedgeYmax->setMinimum(v); + ui->wedgeYmax->setMinimum(v); // must be > than wedgeYmin sph->Ymin.setValue(v); vp->getObject()->getDocument()->recomputeFeature(vp->getObject()); } void TaskBoxPrimitives::onWedgeYmaxChanged(double v) { PartDesign::Wedge* sph = static_cast(vp->getObject()); - ui->wedgeYmin->setMaximum(v); + ui->wedgeYmin->setMaximum(v); // must be < than wedgeYmax sph->Ymax.setValue(v); vp->getObject()->getDocument()->recomputeFeature(vp->getObject()); } void TaskBoxPrimitives::onWedgeZ2minChanged(double v) { PartDesign::Wedge* sph = static_cast(vp->getObject()); - ui->wedgeZ2max->setMinimum(v); + ui->wedgeZ2max->setMinimum(v); // must be >= than wedgeZ2min sph->Z2min.setValue(v); vp->getObject()->getDocument()->recomputeFeature(vp->getObject()); } void TaskBoxPrimitives::onWedgeZ2maxChanged(double v) { PartDesign::Wedge* sph = static_cast(vp->getObject()); - ui->wedgeZ2min->setMaximum(v); // must be <= than wedgeXmax + ui->wedgeZ2min->setMaximum(v); // must be <= than wedgeZ2max sph->Z2max.setValue(v); vp->getObject()->getDocument()->recomputeFeature(vp->getObject()); } void TaskBoxPrimitives::onWedgeZminChanged(double v) { PartDesign::Wedge* sph = static_cast(vp->getObject()); - ui->wedgeZmax->setMinimum(v); + ui->wedgeZmax->setMinimum(v); // must be > than wedgeZmin sph->Zmin.setValue(v); vp->getObject()->getDocument()->recomputeFeature(vp->getObject()); } void TaskBoxPrimitives::onWedgeZmaxChanged(double v) { PartDesign::Wedge* sph = static_cast(vp->getObject()); - ui->wedgeZmin->setMaximum(v); + ui->wedgeZmin->setMaximum(v); // must be < than wedgeZmax sph->Zmax.setValue(v); vp->getObject()->getDocument()->recomputeFeature(vp->getObject()); } - - -void TaskBoxPrimitives::setPrimitive(App::DocumentObject *obj) +bool TaskBoxPrimitives::setPrimitive(App::DocumentObject *obj) { try { QString name(QString::fromLatin1(Gui::Command::getObjectCmd(obj).c_str())); QString cmd; App::Document* doc = App::GetApplication().getActiveDocument(); if (!doc) { - return; + return false; } + + Base::QuantityFormat format(Base::QuantityFormat::Default, Base::UnitsApi::getDecimals()); switch(ui->widgetStack->currentIndex()) { case 1: // box cmd = QString::fromLatin1( @@ -696,9 +699,9 @@ void TaskBoxPrimitives::setPrimitive(App::DocumentObject *obj) "%1.Width=%3\n" "%1.Height=%4\n") .arg(name) - .arg(ui->boxLength->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->boxWidth->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->boxHeight->value().getValue(),0,'f',Base::UnitsApi::getDecimals()); + .arg(Base::UnitsApi::toNumber(ui->boxLength->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->boxWidth->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->boxHeight->value(), format)); break; case 2: // cylinder @@ -709,24 +712,30 @@ void TaskBoxPrimitives::setPrimitive(App::DocumentObject *obj) "%1.FirstAngle=%5\n" "%1.SecondAngle=%6\n") .arg(name) - .arg(ui->cylinderRadius->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->cylinderHeight->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->cylinderAngle->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->cylinderXSkew->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->cylinderYSkew->value().getValue(),0,'f',Base::UnitsApi::getDecimals()); + .arg(Base::UnitsApi::toNumber(ui->cylinderRadius->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->cylinderHeight->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->cylinderAngle->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->cylinderXSkew->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->cylinderYSkew->value(), format)); break; case 3: // cone + // the cone radii must not be equal + if (ui->coneRadius1->value().getValue() == ui->coneRadius2->value().getValue()) { + QMessageBox::warning(Gui::getMainWindow(), tr("Cone radii are equal"), + tr("The radii for cones must not be equal!")); + return false; + } cmd = QString::fromLatin1( "%1.Radius1=%2\n" "%1.Radius2=%3\n" "%1.Height=%4\n" "%1.Angle=%5\n") .arg(name) - .arg(ui->coneRadius1->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->coneRadius2->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->coneHeight->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->coneAngle->value().getValue(),0,'f',Base::UnitsApi::getDecimals()); + .arg(Base::UnitsApi::toNumber(ui->coneRadius1->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->coneRadius2->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->coneHeight->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->coneAngle->value(), format)); break; case 4: // sphere @@ -736,10 +745,10 @@ void TaskBoxPrimitives::setPrimitive(App::DocumentObject *obj) "%1.Angle2=%4\n" "%1.Angle3=%5\n") .arg(name) - .arg(ui->sphereRadius->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->sphereAngle1->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->sphereAngle2->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->sphereAngle3->value().getValue(),0,'f',Base::UnitsApi::getDecimals()); + .arg(Base::UnitsApi::toNumber(ui->sphereRadius->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->sphereAngle1->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->sphereAngle2->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->sphereAngle3->value(), format)); break; case 5: // ellipsoid cmd = QString::fromLatin1( @@ -750,12 +759,12 @@ void TaskBoxPrimitives::setPrimitive(App::DocumentObject *obj) "%1.Angle2=%6\n" "%1.Angle3=%7\n") .arg(name) - .arg(ui->ellipsoidRadius1->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->ellipsoidRadius2->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->ellipsoidRadius3->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->ellipsoidAngle1->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->ellipsoidAngle2->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->ellipsoidAngle3->value().getValue(),0,'f',Base::UnitsApi::getDecimals()); + .arg(Base::UnitsApi::toNumber(ui->ellipsoidRadius1->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->ellipsoidRadius2->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->ellipsoidRadius3->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->ellipsoidAngle1->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->ellipsoidAngle2->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->ellipsoidAngle3->value(), format)); break; case 6: // torus @@ -766,11 +775,11 @@ void TaskBoxPrimitives::setPrimitive(App::DocumentObject *obj) "%1.Angle2=%5\n" "%1.Angle3=%6\n") .arg(name) - .arg(ui->torusRadius1->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->torusRadius2->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->torusAngle1->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->torusAngle2->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->torusAngle3->value().getValue(),0,'f',Base::UnitsApi::getDecimals()); + .arg(Base::UnitsApi::toNumber(ui->torusRadius1->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->torusRadius2->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->torusAngle1->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->torusAngle2->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->torusAngle3->value(), format)); break; case 7: // prism cmd = QString::fromLatin1( @@ -781,12 +790,28 @@ void TaskBoxPrimitives::setPrimitive(App::DocumentObject *obj) "%1.SecondAngle=%6\n") .arg(name) .arg(ui->prismPolygon->value()) - .arg(ui->prismCircumradius->value().getValue(), 0, 'f', Base::UnitsApi::getDecimals()) - .arg(ui->prismHeight->value().getValue(), 0, 'f', Base::UnitsApi::getDecimals()) - .arg(ui->prismXSkew->value().getValue(), 0, 'f', Base::UnitsApi::getDecimals()) - .arg(ui->prismYSkew->value().getValue(), 0, 'f', Base::UnitsApi::getDecimals()); + .arg(Base::UnitsApi::toNumber(ui->prismCircumradius->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->prismHeight->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->prismXSkew->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->prismYSkew->value(), format)); 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 = QString::fromLatin1( "%1.Xmin=%2\n" "%1.Ymin=%3\n" @@ -799,16 +824,16 @@ void TaskBoxPrimitives::setPrimitive(App::DocumentObject *obj) "%1.X2max=%10\n" "%1.Z2max=%11\n") .arg(name) - .arg(ui->wedgeXmin->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->wedgeYmin->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->wedgeZmin->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->wedgeX2min->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->wedgeZ2min->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->wedgeXmax->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->wedgeYmax->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->wedgeZmax->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->wedgeX2max->value().getValue(),0,'f',Base::UnitsApi::getDecimals()) - .arg(ui->wedgeZ2max->value().getValue(),0,'f',Base::UnitsApi::getDecimals()); + .arg(Base::UnitsApi::toNumber(ui->wedgeXmin->value())) + .arg(Base::UnitsApi::toNumber(ui->wedgeYmin->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->wedgeZmin->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->wedgeX2min->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->wedgeZ2min->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->wedgeXmax->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->wedgeYmax->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->wedgeZmax->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->wedgeX2max->value(), format)) + .arg(Base::UnitsApi::toNumber(ui->wedgeZ2max->value(), format)); break; default: @@ -823,7 +848,9 @@ void TaskBoxPrimitives::setPrimitive(App::DocumentObject *obj) } catch (const Base::PyException& e) { QMessageBox::warning(this, tr("Create primitive"), QString::fromLatin1(e.what())); + return false; } + return true; } TaskPrimitiveParameters::TaskPrimitiveParameters(ViewProviderPrimitive* PrimitiveView) : vp_prm(PrimitiveView) @@ -881,7 +908,9 @@ TaskPrimitiveParameters::~TaskPrimitiveParameters() bool TaskPrimitiveParameters::accept() { - primitive->setPrimitive(vp_prm->getObject()); + 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()"); diff --git a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.h b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.h index 11c079fc2ffd..b6f49a0e8691 100644 --- a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.h +++ b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.h @@ -55,7 +55,7 @@ class TaskBoxPrimitives : public Gui::TaskView::TaskBox, TaskBoxPrimitives(ViewProviderPrimitive* vp, QWidget* parent = 0); ~TaskBoxPrimitives(); - void setPrimitive(App::DocumentObject *); + bool setPrimitive(App::DocumentObject *); public Q_SLOTS: void onBoxLengthChanged(double); diff --git a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.ui b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.ui index 77f0b7b46d52..70e89795fb5f 100644 --- a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.ui +++ b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.ui @@ -225,7 +225,7 @@ - + @@ -755,7 +755,7 @@ - + @@ -800,6 +800,9 @@ + + Radius in local z-direction + false @@ -820,6 +823,9 @@ + + Radius in local x-direction + false @@ -840,6 +846,10 @@ + + Radius in local y-direction +If zero, it is equal to Radius2 + false @@ -964,7 +974,7 @@ - + @@ -1009,6 +1019,9 @@ + + Radius in local xy-plane + false @@ -1029,6 +1042,9 @@ + + Radius in local xz-plane + false @@ -1156,7 +1172,7 @@ - + @@ -1651,7 +1667,7 @@ - + @@ -1762,7 +1778,7 @@ - + diff --git a/src/Mod/PartDesign/Gui/Workbench.cpp b/src/Mod/PartDesign/Gui/Workbench.cpp index 73b7576c1685..b07911a55e0f 100644 --- a/src/Mod/PartDesign/Gui/Workbench.cpp +++ b/src/Mod/PartDesign/Gui/Workbench.cpp @@ -540,7 +540,6 @@ Gui::MenuItem* Workbench::setupMenuBar() const << "Separator" << "PartDesign_Boolean" << "Separator" - //<< "PartDesign_Hole" << "PartDesign_Migrate" << "PartDesign_Sprocket" << "PartDesign_InvoluteGear";