From 7185ee93f22485a0ea015d0fbead1a0a80738a09 Mon Sep 17 00:00:00 2001 From: donovaly Date: Mon, 5 Apr 2021 14:35:50 +0200 Subject: [PATCH] [PartDesign] add direction to cylinder primitive We already have the possibility to create skewed prisms. I recently stumbled upon that I would need this feature for cylinders too. This PR takes the existing prism extrude direction feature and use it for cylinders too --- src/Mod/PartDesign/App/FeaturePrimitive.cpp | 13 +++- src/Mod/PartDesign/App/FeaturePrimitive.h | 5 +- .../Gui/TaskPrimitiveParameters.cpp | 48 ++++++++++++- .../PartDesign/Gui/TaskPrimitiveParameters.h | 2 + .../PartDesign/Gui/TaskPrimitiveParameters.ui | 68 ++++++++++++++++--- 5 files changed, 120 insertions(+), 16 deletions(-) diff --git a/src/Mod/PartDesign/App/FeaturePrimitive.cpp b/src/Mod/PartDesign/App/FeaturePrimitive.cpp index 444b61ddc2..b97eb878dd 100644 --- a/src/Mod/PartDesign/App/FeaturePrimitive.cpp +++ b/src/Mod/PartDesign/App/FeaturePrimitive.cpp @@ -33,6 +33,7 @@ # include # include # include +# include # include # include # include @@ -242,6 +243,8 @@ Cylinder::Cylinder() Radius.setConstraints(&quantityRange); Height.setConstraints(&quantityRange); + Part::PrismExtension::initExtension(this); + primitiveType = FeaturePrimitive::Cylinder; } @@ -252,12 +255,18 @@ App::DocumentObjectExecReturn* Cylinder::execute(void) return new App::DocumentObjectExecReturn("Radius of cylinder too small"); if (Height.getValue() < Precision::Confusion()) return new App::DocumentObjectExecReturn("Height of cylinder too small"); + if (Angle.getValue() < Precision::Confusion()) + return new App::DocumentObjectExecReturn("Rotation angle of cylinder too small"); try { BRepPrimAPI_MakeCylinder mkCylr(Radius.getValue(), Height.getValue(), - Angle.getValue()/180.0f*M_PI); + Base::toRadians(Angle.getValue())); - return FeaturePrimitive::execute(mkCylr.Shape()); + // the direction vector for the prism is the height for z and the given angle + BRepPrim_Cylinder prim = mkCylr.Cylinder(); + TopoDS_Shape result = makePrism(Height.getValue(), prim.BottomFace()); + + return FeaturePrimitive::execute(result); } catch (Standard_Failure& e) { diff --git a/src/Mod/PartDesign/App/FeaturePrimitive.h b/src/Mod/PartDesign/App/FeaturePrimitive.h index 6b4dc7a713..1c8a656369 100644 --- a/src/Mod/PartDesign/App/FeaturePrimitive.h +++ b/src/Mod/PartDesign/App/FeaturePrimitive.h @@ -107,7 +107,7 @@ class PartDesignExport SubtractiveBox : public Box { }; -class PartDesignExport Cylinder : public PartDesign::FeaturePrimitive { +class PartDesignExport Cylinder : public PartDesign::FeaturePrimitive, public Part::PrismExtension { PROPERTY_HEADER(PartDesign::Cylinder); @@ -124,9 +124,6 @@ public: /// recalculate the Feature App::DocumentObjectExecReturn *execute(void); short mustExecute() const; - -protected: - }; class PartDesignExport AdditiveCylinder : public Cylinder { diff --git a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp index e9a4e8923f..c8f9e40f89 100644 --- a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.cpp @@ -87,6 +87,10 @@ TaskBoxPrimitives::TaskBoxPrimitives(ViewProviderPrimitive* vp, QWidget* parent) ui->cylinderHeight->bind(static_cast(vp->getObject())->Height); ui->cylinderRadius->setValue(static_cast(vp->getObject())->Radius.getValue()); ui->cylinderRadius->bind(static_cast(vp->getObject())->Radius); + ui->cylinderXSkew->setValue(static_cast(vp->getObject())->FirstAngle.getValue()); + ui->cylinderXSkew->bind(static_cast(vp->getObject())->FirstAngle); + ui->cylinderYSkew->setValue(static_cast(vp->getObject())->SecondAngle.getValue()); + 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); @@ -278,6 +282,8 @@ TaskBoxPrimitives::TaskBoxPrimitives(ViewProviderPrimitive* vp, QWidget* parent) // cylinder connect(ui->cylinderRadius, SIGNAL(valueChanged(double)), this, SLOT(onCylinderRadiusChanged(double))); connect(ui->cylinderHeight, SIGNAL(valueChanged(double)), this, SLOT(onCylinderHeightChanged(double))); + connect(ui->cylinderXSkew, SIGNAL(valueChanged(double)), this, SLOT(onCylinderXSkewChanged(double))); + connect(ui->cylinderYSkew, SIGNAL(valueChanged(double)), this, SLOT(onCylinderYSkewChanged(double))); connect(ui->cylinderAngle, SIGNAL(valueChanged(double)), this, SLOT(onCylinderAngleChanged(double))); // cone @@ -388,6 +394,40 @@ void TaskBoxPrimitives::onCylinderRadiusChanged(double v) { vp->getObject()->getDocument()->recomputeFeature(vp->getObject()); } +void TaskBoxPrimitives::onCylinderXSkewChanged(double v) { + PartDesign::Cylinder* cyl = static_cast(vp->getObject()); + // we must assure that if the user incremented from e.g. 85 degree with the + // spin buttons he does not end at 90.0 but 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()); + } + vp->getObject()->getDocument()->recomputeFeature(vp->getObject()); +} + +void TaskBoxPrimitives::onCylinderYSkewChanged(double v) { + PartDesign::Cylinder* cyl = static_cast(vp->getObject()); + // we must assure that if the user incremented from e.g. 85 degree with the + // spin buttons he does not end at 90.0 but 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()); + } + vp->getObject()->getDocument()->recomputeFeature(vp->getObject()); +} + void TaskBoxPrimitives::onSphereAngle1Changed(double v) { PartDesign::Sphere* sph = static_cast(vp->getObject()); ui->sphereAngle2->setMinimum(v); // Angle1 must geometrically be <= than Angle2 @@ -665,11 +705,15 @@ void TaskBoxPrimitives::setPrimitive(App::DocumentObject *obj) cmd = QString::fromLatin1( "%1.Radius=%2\n" "%1.Height=%3\n" - "%1.Angle=%4\n") + "%1.Angle=%4\n" + "%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->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()); break; case 3: // cone diff --git a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.h b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.h index 0049d2017f..11c079fc2f 100644 --- a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.h +++ b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.h @@ -63,6 +63,8 @@ public Q_SLOTS: void onBoxHeightChanged(double); void onCylinderRadiusChanged(double); void onCylinderHeightChanged(double); + void onCylinderXSkewChanged(double); + void onCylinderYSkewChanged(double); void onCylinderAngleChanged(double); void onSphereRadiusChanged(double); void onSphereAngle1Changed(double); diff --git a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.ui b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.ui index bcacdbd4dd..ba04ef99e8 100644 --- a/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.ui +++ b/src/Mod/PartDesign/Gui/TaskPrimitiveParameters.ui @@ -264,7 +264,7 @@ - Angle: + Rotation angle: @@ -333,6 +333,19 @@ + + + + false + + + mm + + + 2.000000000000000 + + + @@ -353,16 +366,55 @@ - - + + + + Angle in first direction: + + + + + + + Angle in first direction + false - mm + deg - - 2.000000000000000 + + -90.000000000000000 + + + 90.000000000000000 + + + + + + + Angle in second direction: + + + + + + + Angle in second direction + + + false + + + deg + + + -90.000000000000000 + + + 90.000000000000000 @@ -1201,7 +1253,7 @@ - + Angle in first direction: @@ -1227,7 +1279,7 @@ - + Angle in second direction: