diff --git a/src/Mod/PartDesign/App/FeaturePad.cpp b/src/Mod/PartDesign/App/FeaturePad.cpp index b2d13acfc9..38d99cd5fd 100644 --- a/src/Mod/PartDesign/App/FeaturePad.cpp +++ b/src/Mod/PartDesign/App/FeaturePad.cpp @@ -25,37 +25,35 @@ #ifndef _PreComp_ # include # include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include -# include # include +# include # include -# include -# include +# include +# include +# include # include +# include +# include +# include # include +# include +# include +# include +# include +# include +# include +# include +# include #endif +#include +#include #include #include -#include #include -#include -//#include "Body.h" #include "FeaturePad.h" - using namespace PartDesign; const char* Pad::TypeEnums[]= {"Length","UpToLast","UpToFirst","UpToFace","TwoLengths",NULL}; @@ -66,14 +64,16 @@ Pad::Pad() { addSubType = FeatureAddSub::Additive; - ADD_PROPERTY_TYPE(Type,(0L),"Pad",App::Prop_None,"Pad type"); + ADD_PROPERTY_TYPE(Type, (0L), "Pad", App::Prop_None, "Pad type"); Type.setEnums(TypeEnums); - ADD_PROPERTY_TYPE(Length,(100.0),"Pad",App::Prop_None,"Pad length"); - ADD_PROPERTY_TYPE(Length2,(100.0),"Pad",App::Prop_None,"Second Pad length"); - ADD_PROPERTY_TYPE(UpToFace,(0),"Pad",App::Prop_None,"Face where pad will end"); - ADD_PROPERTY_TYPE(Offset,(0.0),"Pad",App::Prop_None,"Offset from face in which pad will end"); + ADD_PROPERTY_TYPE(Length, (100.0), "Pad", App::Prop_None,"Pad length"); + ADD_PROPERTY_TYPE(Length2, (100.0), "Pad", App::Prop_None,"Second Pad length"); + ADD_PROPERTY_TYPE(UseCustomVector, (0), "Pad", App::Prop_None, "Use custom vector for pad direction"); + ADD_PROPERTY_TYPE(Direction, (Base::Vector3d(1.0, 1.0, 1.0)), "Pad", App::Prop_None, "Pad direction vector"); + ADD_PROPERTY_TYPE(UpToFace, (0), "Pad", App::Prop_None, "Face where pad will end"); + ADD_PROPERTY_TYPE(Offset, (0.0), "Pad", App::Prop_None, "Offset from face in which pad will end"); static const App::PropertyQuantityConstraint::Constraints signedLengthConstraint = {-DBL_MAX, DBL_MAX, 1.0}; - Offset.setConstraints ( &signedLengthConstraint ); + Offset.setConstraints(&signedLengthConstraint); } short Pad::mustExecute() const @@ -82,6 +82,8 @@ short Pad::mustExecute() const Type.isTouched() || Length.isTouched() || Length2.isTouched() || + UseCustomVector.isTouched() || + Direction.isTouched() || Offset.isTouched() || UpToFace.isTouched()) return 1; @@ -115,10 +117,10 @@ App::DocumentObjectExecReturn *Pad::execute(void) base = TopoDS_Shape(); } - // get the Sketch plane - Base::Placement SketchPos = obj->Placement.getValue(); - Base::Vector3d SketchVector = getProfileNormal(); + Base::Placement SketchPos = obj->Placement.getValue(); + // get the normal vector of the sketch + Base::Vector3d SketchVector = getProfileNormal(); try { this->positionByPrevious(); @@ -126,7 +128,45 @@ App::DocumentObjectExecReturn *Pad::execute(void) base.Move(invObjLoc); - gp_Dir dir(SketchVector.x,SketchVector.y,SketchVector.z); + Base::Vector3d paddingDirection; + + // use the given vector if necessary + if (!UseCustomVector.getValue()) { + paddingDirection = SketchVector; + } + else { + // if null vector, use SketchVector + if ( (fabs(Direction.getValue().x) < Precision::Confusion()) + && (fabs(Direction.getValue().y) < Precision::Confusion()) + && (fabs(Direction.getValue().z) < Precision::Confusion()) ) + { + Direction.setValue(SketchVector); + } + + paddingDirection = Direction.getValue(); + } + + // create vector in padding direction with length 1 + gp_Dir dir(paddingDirection.x, paddingDirection.y, paddingDirection.z); + + // The length of a gp_Dir is 1 so the resulting pad would have + // the length L in the direction of dir. But we want to have its height in the + // direction of the normal vector. + // Therefore we must multiply L by the factor that is necessary + // to make dir as long that its projection to the SketchVector + // equals the SketchVector. + // This is the scalar product of both vectors. + // Since the pad length cannot be negative, the factor must not be negative. + + double factor = fabs(dir * gp_Dir(SketchVector.x, SketchVector.y, SketchVector.z)); + + // factor would be zero if vectors are orthogonal + if (factor < Precision::Confusion()) + return new App::DocumentObjectExecReturn("Pad: Creation failed because direction is orthogonal to sketch's normal vector"); + + // perform the length correction + L = L / factor; + dir.Transform(invObjLoc.Transformation()); if (sketchshape.IsNull()) diff --git a/src/Mod/PartDesign/App/FeaturePad.h b/src/Mod/PartDesign/App/FeaturePad.h index d4fcdeb357..a4d1172865 100644 --- a/src/Mod/PartDesign/App/FeaturePad.h +++ b/src/Mod/PartDesign/App/FeaturePad.h @@ -40,10 +40,12 @@ class PartDesignExport Pad : public ProfileBased public: Pad(); - App::PropertyEnumeration Type; - App::PropertyLength Length; - App::PropertyLength Length2; - App::PropertyLength Offset; + App::PropertyEnumeration Type; + App::PropertyLength Length; + App::PropertyLength Length2; + App::PropertyBool UseCustomVector; + App::PropertyVector Direction; + App::PropertyLength Offset; /** @name methods override feature */ //@{ diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.cpp b/src/Mod/PartDesign/App/FeatureSketchBased.cpp index 1b31439f0d..e177b7ffbc 100644 --- a/src/Mod/PartDesign/App/FeatureSketchBased.cpp +++ b/src/Mod/PartDesign/App/FeatureSketchBased.cpp @@ -579,7 +579,7 @@ void ProfileBased::generatePrism(TopoDS_Shape& prism, // Its better not to use BRepFeat_MakePrism here even if we have a support because the // resulting shape creates problems with Pocket - BRepPrimAPI_MakePrism PrismMaker(from, Ltotal*gp_Vec(dir), 0,1); // finite prism + BRepPrimAPI_MakePrism PrismMaker(from, Ltotal*gp_Vec(dir), 0, 1); // finite prism if (!PrismMaker.IsDone()) throw Base::RuntimeError("ProfileBased: Length: Could not extrude the sketch!"); prism = PrismMaker.Shape(); diff --git a/src/Mod/PartDesign/Gui/TaskPadParameters.cpp b/src/Mod/PartDesign/Gui/TaskPadParameters.cpp index 2b86ac2fe9..539c33fc85 100644 --- a/src/Mod/PartDesign/Gui/TaskPadParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPadParameters.cpp @@ -34,6 +34,7 @@ #include "TaskPadParameters.h" #include #include +#include #include #include #include @@ -74,6 +75,10 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView, QWidget *parent, PartDesign::Pad* pcPad = static_cast(vp->getObject()); Base::Quantity l = pcPad->Length.getQuantityValue(); Base::Quantity l2 = pcPad->Length2.getQuantityValue(); + bool useCustom = pcPad->UseCustomVector.getValue(); + double xs = pcPad->Direction.getValue().x; + double ys = pcPad->Direction.getValue().y; + double zs = pcPad->Direction.getValue().z; Base::Quantity off = pcPad->Offset.getQuantityValue(); bool midplane = pcPad->Midplane.getValue(); bool reversed = pcPad->Reversed.getValue(); @@ -91,17 +96,32 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView, QWidget *parent, // Fill data into dialog elements ui->lengthEdit->setValue(l); ui->lengthEdit2->setValue(l2); + ui->groupBoxDirection->setChecked(useCustom); + ui->XDirectionEdit->setValue(xs); + ui->YDirectionEdit->setValue(ys); + ui->ZDirectionEdit->setValue(zs); ui->offsetEdit->setValue(off); // Bind input fields to properties ui->lengthEdit->bind(pcPad->Length); ui->lengthEdit2->bind(pcPad->Length2); + + ui->XDirectionEdit->bind(App::ObjectIdentifier::parse(pcPad, std::string("Direction.x"))); + ui->YDirectionEdit->bind(App::ObjectIdentifier::parse(pcPad, std::string("Direction.y"))); + ui->ZDirectionEdit->bind(App::ObjectIdentifier::parse(pcPad, std::string("Direction.z"))); + ui->offsetEdit->bind(pcPad->Offset); ui->checkBoxMidplane->setChecked(midplane); // According to bug #0000521 the reversed option // shouldn't be de-activated if the pad has a support face ui->checkBoxReversed->setChecked(reversed); + // set decimals for the direction edits + int UserDecimals = Base::UnitsApi::getDecimals(); + ui->XDirectionEdit->setDecimals(UserDecimals); + ui->YDirectionEdit->setDecimals(UserDecimals); + ui->ZDirectionEdit->setDecimals(UserDecimals); + // Set object labels if (obj && PartDesign::Feature::isDatum(obj)) { ui->lineFaceName->setText(QString::fromUtf8(obj->Label.getValue())); @@ -135,6 +155,14 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView, QWidget *parent, this, SLOT(onLengthChanged(double))); connect(ui->lengthEdit2, SIGNAL(valueChanged(double)), this, SLOT(onLength2Changed(double))); + connect(ui->groupBoxDirection, SIGNAL(toggled(bool)), + this, SLOT(onGBDirectionChanged(bool))); + connect(ui->XDirectionEdit, SIGNAL(valueChanged(double)), + this, SLOT(onXDirectionEditChanged(double))); + connect(ui->YDirectionEdit, SIGNAL(valueChanged(double)), + this, SLOT(onYDirectionEditChanged(double))); + connect(ui->ZDirectionEdit, SIGNAL(valueChanged(double)), + this, SLOT(onZDirectionEditChanged(double))); connect(ui->offsetEdit, SIGNAL(valueChanged(double)), this, SLOT(onOffsetChanged(double))); connect(ui->checkBoxMidplane, SIGNAL(toggled(bool)), @@ -168,6 +196,7 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView, QWidget *parent, void TaskPadParameters::updateUI(int index) { // disable/hide everything unless we are sure we don't need it + // exception: the direction parameters are in any case visible bool isLengthEditVisable = false; bool isLengthEdit2Visable = false; bool isOffsetEditVisable = false; @@ -272,6 +301,49 @@ void TaskPadParameters::onLength2Changed(double len) recomputeFeature(); } +void TaskPadParameters::onGBDirectionChanged(bool on) +{ + PartDesign::Pad* pcPad = static_cast(vp->getObject()); + pcPad->UseCustomVector.setValue(on); + recomputeFeature(); +} + +void TaskPadParameters::onXDirectionEditChanged(double len) +{ + PartDesign::Pad* pcPad = static_cast(vp->getObject()); + pcPad->Direction.setValue(len, pcPad->Direction.getValue().y, pcPad->Direction.getValue().z); + recomputeFeature(); + // checking for case of a null vector is done in FeaturePad.cpp + // if there was a null vector, the normal vector of the sketch is used. + // therefore the vector component edits must be updated + updateDirectionEdits(); +} + + +void TaskPadParameters::onYDirectionEditChanged(double len) +{ + PartDesign::Pad* pcPad = static_cast(vp->getObject()); + pcPad->Direction.setValue(pcPad->Direction.getValue().x, len, pcPad->Direction.getValue().z); + recomputeFeature(); + updateDirectionEdits(); +} + +void TaskPadParameters::onZDirectionEditChanged(double len) +{ + PartDesign::Pad* pcPad = static_cast(vp->getObject()); + pcPad->Direction.setValue(pcPad->Direction.getValue().x, pcPad->Direction.getValue().y, len); + recomputeFeature(); + updateDirectionEdits(); +} + +void TaskPadParameters::updateDirectionEdits(void) +{ + PartDesign::Pad* pcPad = static_cast(vp->getObject()); + ui->XDirectionEdit->setValue(pcPad->Direction.getValue().x); + ui->YDirectionEdit->setValue(pcPad->Direction.getValue().y); + ui->ZDirectionEdit->setValue(pcPad->Direction.getValue().z); +} + void TaskPadParameters::onOffsetChanged(double len) { PartDesign::Pad* pcPad = static_cast(vp->getObject()); @@ -360,6 +432,26 @@ double TaskPadParameters::getLength2(void) const return ui->lengthEdit2->value().getValue(); } +bool TaskPadParameters::getCustom(void) const +{ + return ui->groupBoxDirection->isChecked(); +} + +double TaskPadParameters::getXDirection(void) const +{ + return ui->XDirectionEdit->value(); +} + +double TaskPadParameters::getYDirection(void) const +{ + return ui->YDirectionEdit->value(); +} + +double TaskPadParameters::getZDirection(void) const +{ + return ui->ZDirectionEdit->value(); +} + double TaskPadParameters::getOffset(void) const { return ui->offsetEdit->value().getValue(); @@ -404,6 +496,9 @@ void TaskPadParameters::changeEvent(QEvent *e) if (e->type() == QEvent::LanguageChange) { ui->lengthEdit->blockSignals(true); ui->lengthEdit2->blockSignals(true); + ui->XDirectionEdit->blockSignals(true); + ui->YDirectionEdit->blockSignals(true); + ui->ZDirectionEdit->blockSignals(true); ui->offsetEdit->blockSignals(true); ui->lineFaceName->blockSignals(true); ui->changeMode->blockSignals(true); @@ -443,6 +538,9 @@ void TaskPadParameters::changeEvent(QEvent *e) ui->lengthEdit->blockSignals(false); ui->lengthEdit2->blockSignals(false); + ui->XDirectionEdit->blockSignals(false); + ui->YDirectionEdit->blockSignals(false); + ui->ZDirectionEdit->blockSignals(false); ui->offsetEdit->blockSignals(false); ui->lineFaceName->blockSignals(false); ui->changeMode->blockSignals(false); @@ -463,10 +561,11 @@ void TaskPadParameters::apply() ui->lengthEdit->apply(); ui->lengthEdit2->apply(); - + FCMD_OBJ_CMD(obj, "UseCustomVector = " << (getCustom() ? 1 : 0)); + FCMD_OBJ_CMD(obj, "Direction = (" + << getXDirection() << ", " << getYDirection() << ", " << getZDirection() << ")"); FCMD_OBJ_CMD(obj,"Type = " << getMode()); QString facename = getFaceName(); - FCMD_OBJ_CMD(obj,"UpToFace = " << facename.toLatin1().data()); FCMD_OBJ_CMD(obj,"Reversed = " << (getReversed()?1:0)); FCMD_OBJ_CMD(obj,"Midplane = " << (getMidplane()?1:0)); diff --git a/src/Mod/PartDesign/Gui/TaskPadParameters.h b/src/Mod/PartDesign/Gui/TaskPadParameters.h index 64e5ed7b6d..6a0f64f796 100644 --- a/src/Mod/PartDesign/Gui/TaskPadParameters.h +++ b/src/Mod/PartDesign/Gui/TaskPadParameters.h @@ -58,6 +58,10 @@ public: private Q_SLOTS: void onLengthChanged(double); void onLength2Changed(double); + void onGBDirectionChanged(bool); + void onXDirectionEditChanged(double); + void onYDirectionEditChanged(double); + void onZDirectionEditChanged(double); void onOffsetChanged(double); void onMidplaneChanged(bool); void onReversedChanged(bool); @@ -71,6 +75,10 @@ protected: private: double getLength(void) const; double getLength2(void) const; + bool getCustom(void) const; + double getXDirection(void) const; + double getYDirection(void) const; + double getZDirection(void) const; double getOffset(void) const; bool getReversed(void) const; bool getMidplane(void) const; @@ -78,6 +86,7 @@ private: QString getFaceName(void) const; void onSelectionChanged(const Gui::SelectionChanges& msg) override; void updateUI(int index); + void updateDirectionEdits(void); private: QWidget* proxy; diff --git a/src/Mod/PartDesign/Gui/TaskPadParameters.ui b/src/Mod/PartDesign/Gui/TaskPadParameters.ui index c08f5064aa..a24541cbb5 100644 --- a/src/Mod/PartDesign/Gui/TaskPadParameters.ui +++ b/src/Mod/PartDesign/Gui/TaskPadParameters.ui @@ -6,8 +6,8 @@ 0 0 - 272 - 271 + 280 + 350 @@ -55,17 +55,141 @@ + + + + true + + + Use custom vector for pad direction otherwise +the sketch plane's normal vector will be used + + + Use custom direction + + + true + + + + + + + + x + + + + + + + x-component of direction vector + + + false + + + -100.000000000000000 + + + 100.000000000000000 + + + 0.100000000000000 + + + + + + + + + + + + + + y + + + + + + + y-component of direction vector + + + false + + + -100.000000000000000 + + + 100.000000000000000 + + + 0.100000000000000 + + + + + + + + + + + + + + z + + + + + + + z-component of direction vector + + + false + + + -100.000000000000000 + + + 100.000000000000000 + + + 0.100000000000000 + + + 1.000000000000000 + + + + + + + + + + + - Offset + Offset to face + + Offset from face in which pad will end + false @@ -78,6 +202,9 @@ true + + Applies length symmetrically to sketch plane + Symmetric to plane @@ -85,6 +212,9 @@ + + Reverses pad direction + Reversed @@ -150,6 +280,11 @@ QWidget
Gui/QuantitySpinBox.h
+ + Gui::DoubleSpinBox + QDoubleSpinBox +
Gui/SpinBox.h
+
Gui::PrefQuantitySpinBox Gui::QuantitySpinBox