diff --git a/src/Mod/PartDesign/App/FeaturePad.cpp b/src/Mod/PartDesign/App/FeaturePad.cpp index b2b700de92..dc2edbe054 100644 --- a/src/Mod/PartDesign/App/FeaturePad.cpp +++ b/src/Mod/PartDesign/App/FeaturePad.cpp @@ -56,7 +56,7 @@ using namespace PartDesign; -const char* Pad::TypeEnums[]= {"Length","UpToLast","UpToFirst","UpToFace","TwoLengths",NULL}; +const char* Pad::TypeEnums[]= {"Length", "UpToLast", "UpToFirst", "UpToFace", "TwoLengths", NULL}; PROPERTY_SOURCE(PartDesign::Pad, PartDesign::ProfileBased) @@ -70,6 +70,7 @@ Pad::Pad() 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(AlongCustomVector, (1), "Pad", App::Prop_None, "Measure length along custom 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}; @@ -88,6 +89,7 @@ short Pad::mustExecute() const Length2.isTouched() || UseCustomVector.isTouched() || Direction.isTouched() || + AlongCustomVector.isTouched() || Offset.isTouched() || UpToFace.isTouched()) return 1; @@ -104,6 +106,12 @@ App::DocumentObjectExecReturn *Pad::execute(void) if ((std::string(Type.getValueAsString()) == "TwoLengths") && (L < Precision::Confusion())) return new App::DocumentObjectExecReturn("Second length of pad too small"); + // if midplane is true, disable reversed and vice versa + bool hasMidplane = Midplane.getValue(); + bool hasReversed = Reversed.getValue(); + Midplane.setReadOnly(hasReversed); + Reversed.setReadOnly(hasMidplane); + Part::Feature* obj = 0; TopoDS_Shape sketchshape; try { @@ -133,12 +141,13 @@ App::DocumentObjectExecReturn *Pad::execute(void) base.Move(invObjLoc); Base::Vector3d paddingDirection; - - // use the given vector if necessary + if (!UseCustomVector.getValue()) { + // use sketch's normal vector for direction paddingDirection = SketchVector; } else { + // use the given vector // if null vector, use SketchVector if ( (fabs(Direction.getValue().x) < Precision::Confusion()) && (fabs(Direction.getValue().y) < Precision::Confusion()) @@ -168,9 +177,15 @@ App::DocumentObjectExecReturn *Pad::execute(void) 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; - L2 = L2 / factor; + // perform the length correction if not along custom vector + if (AlongCustomVector.getValue()) { + L = L / factor; + L2 = L2 / factor; + } + + // explicitly set the Direction so that the dialog shows also the used direction + // if the sketch's normal vector was used + Direction.setValue(paddingDirection); dir.Transform(invObjLoc.Transformation()); @@ -306,7 +321,7 @@ App::DocumentObjectExecReturn *Pad::execute(void) } } else { generatePrism(prism, sketchshape, method, dir, L, L2, - Midplane.getValue(), Reversed.getValue()); + hasMidplane, hasReversed); } if (prism.IsNull()) diff --git a/src/Mod/PartDesign/App/FeaturePad.h b/src/Mod/PartDesign/App/FeaturePad.h index a4d1172865..9c646d2c27 100644 --- a/src/Mod/PartDesign/App/FeaturePad.h +++ b/src/Mod/PartDesign/App/FeaturePad.h @@ -45,6 +45,7 @@ public: App::PropertyLength Length2; App::PropertyBool UseCustomVector; App::PropertyVector Direction; + App::PropertyBool AlongCustomVector; App::PropertyLength Offset; /** @name methods override feature */ diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.cpp b/src/Mod/PartDesign/App/FeatureSketchBased.cpp index 01141a2a80..bc6169fa3d 100644 --- a/src/Mod/PartDesign/App/FeatureSketchBased.cpp +++ b/src/Mod/PartDesign/App/FeatureSketchBased.cpp @@ -587,8 +587,11 @@ void ProfileBased::generatePrism(TopoDS_Shape& prism, if (method == "TwoLengths") { // midplane makes no sense here - Loffset = -L2; Ltotal += L2; + if (reversed) + Loffset = -L; + else + Loffset = -L2; } else if (midplane) Loffset = -Ltotal/2; diff --git a/src/Mod/PartDesign/Gui/TaskPadParameters.cpp b/src/Mod/PartDesign/Gui/TaskPadParameters.cpp index 2604b60aad..f2e927fe47 100644 --- a/src/Mod/PartDesign/Gui/TaskPadParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPadParameters.cpp @@ -34,15 +34,15 @@ #include "TaskPadParameters.h" #include #include +#include #include #include -#include #include +#include +#include +#include #include #include -#include -#include -#include #include #include #include "TaskSketchBasedParameters.h" @@ -75,6 +75,7 @@ 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 alongCustom = pcPad->AlongCustomVector.getValue(); bool useCustom = pcPad->UseCustomVector.getValue(); double xs = pcPad->Direction.getValue().x; double ys = pcPad->Direction.getValue().y; @@ -93,10 +94,18 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView, QWidget *parent, faceId = std::atoi(&upToFace[4]); } + // set decimals for the direction edits + // do this here before the edits are filed to avoid rounding mistakes + int UserDecimals = Base::UnitsApi::getDecimals(); + ui->XDirectionEdit->setDecimals(UserDecimals); + ui->YDirectionEdit->setDecimals(UserDecimals); + ui->ZDirectionEdit->setDecimals(UserDecimals); + // Fill data into dialog elements ui->lengthEdit->setValue(l); ui->lengthEdit2->setValue(l2); ui->groupBoxDirection->setChecked(useCustom); + ui->checkBoxAlongDirection->setChecked(alongCustom); ui->XDirectionEdit->setValue(xs); ui->YDirectionEdit->setValue(ys); ui->ZDirectionEdit->setValue(zs); @@ -105,23 +114,16 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView, QWidget *parent, // 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())); @@ -138,7 +140,6 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView, QWidget *parent, ui->lineFaceName->clear(); ui->lineFaceName->setProperty("FeatureName", QVariant()); } - ui->lineFaceName->setProperty("FaceName", QByteArray(upToFace.c_str())); ui->changeMode->clear(); @@ -155,6 +156,8 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView, QWidget *parent, this, SLOT(onLengthChanged(double))); connect(ui->lengthEdit2, SIGNAL(valueChanged(double)), this, SLOT(onLength2Changed(double))); + connect(ui->checkBoxAlongDirection, SIGNAL(toggled(bool)), + this, SLOT(onCBAlongDirectionChanged(bool))); connect(ui->groupBoxDirection, SIGNAL(toggled(bool)), this, SLOT(onGBDirectionChanged(bool))); connect(ui->XDirectionEdit, SIGNAL(valueChanged(double)), @@ -197,16 +200,17 @@ 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; + bool isLengthEditVisible = false; + bool isLengthEdit2Visible = false; + bool isOffsetEditVisible = false; bool isMidplateEnabled = false; - bool isReversedEnabled = false; + bool isReversedEnabled = true; + bool isReversedVisible = true; bool isFaceEditEnabled = false; // dimension if (index == 0) { - isLengthEditVisable = true; + isLengthEditVisible = true; ui->lengthEdit->selectNumber(); // Make sure that the spin box has the focus to get key events // Calling setFocus() directly doesn't work because the spin box is not @@ -218,13 +222,16 @@ void TaskPadParameters::updateUI(int index) } // up to first/last else if (index == 1 || index == 2) { - isOffsetEditVisable = true; - isReversedEnabled = true; + isOffsetEditVisible = true; + isReversedEnabled = false; + isReversedVisible = false; } // up to face else if (index == 3) { - isOffsetEditVisable = true; - isFaceEditEnabled = true; + isOffsetEditVisible = true; + isFaceEditEnabled = true; + isReversedEnabled = false; + isReversedVisible = false; QMetaObject::invokeMethod(ui->lineFaceName, "setFocus", Qt::QueuedConnection); // Go into reference selection mode if no face has been selected yet if (ui->lineFaceName->property("FeatureName").isNull()) @@ -232,25 +239,27 @@ void TaskPadParameters::updateUI(int index) } // two dimensions else { - isLengthEditVisable = true; - isLengthEdit2Visable = true; + isLengthEditVisible = true; + isLengthEdit2Visible = true; } - ui->lengthEdit->setVisible( isLengthEditVisable ); - ui->lengthEdit->setEnabled( isLengthEditVisable ); - ui->labelLength->setVisible( isLengthEditVisable ); + ui->lengthEdit->setVisible( isLengthEditVisible ); + ui->lengthEdit->setEnabled( isLengthEditVisible ); + ui->labelLength->setVisible( isLengthEditVisible ); + ui->checkBoxAlongDirection->setVisible( isLengthEditVisible ); - ui->offsetEdit->setVisible( isOffsetEditVisable ); - ui->offsetEdit->setEnabled( isOffsetEditVisable ); - ui->labelOffset->setVisible( isOffsetEditVisable ); + ui->offsetEdit->setVisible( isOffsetEditVisible ); + ui->offsetEdit->setEnabled( isOffsetEditVisible ); + ui->labelOffset->setVisible( isOffsetEditVisible ); ui->checkBoxMidplane->setEnabled( isMidplateEnabled ); ui->checkBoxReversed->setEnabled( isReversedEnabled ); + ui->checkBoxReversed->setVisible( isReversedVisible ); - ui->lengthEdit2->setVisible( isLengthEdit2Visable ); - ui->lengthEdit2->setEnabled( isLengthEdit2Visable ); - ui->labelLength2->setVisible( isLengthEdit2Visable ); + ui->lengthEdit2->setVisible( isLengthEdit2Visible ); + ui->lengthEdit2->setEnabled( isLengthEdit2Visible ); + ui->labelLength2->setVisible( isLengthEdit2Visible ); ui->buttonFace->setEnabled( isFaceEditEnabled ); ui->lineFaceName->setEnabled( isFaceEditEnabled ); @@ -301,11 +310,26 @@ void TaskPadParameters::onLength2Changed(double len) recomputeFeature(); } +void TaskPadParameters::onCBAlongDirectionChanged(bool on) +{ + PartDesign::Pad* pcPad = static_cast(vp->getObject()); + pcPad->AlongCustomVector.setValue(on); + recomputeFeature(); +} + void TaskPadParameters::onGBDirectionChanged(bool on) { PartDesign::Pad* pcPad = static_cast(vp->getObject()); pcPad->UseCustomVector.setValue(on); + // dis/enable length direction + ui->checkBoxAlongDirection->setEnabled(on); + if (!on) + ui->checkBoxAlongDirection->setChecked(!on); recomputeFeature(); + // the calculation of the sketch's normal vector is done in FeaturePad.cpp + // if this vector was used for the recomputation we must fill the direction + // vector edit fields. Therefore update + updateDirectionEdits(); } void TaskPadParameters::onXDirectionEditChanged(double len) @@ -319,7 +343,6 @@ void TaskPadParameters::onXDirectionEditChanged(double len) updateDirectionEdits(); } - void TaskPadParameters::onYDirectionEditChanged(double len) { PartDesign::Pad* pcPad = static_cast(vp->getObject()); @@ -339,9 +362,16 @@ void TaskPadParameters::onZDirectionEditChanged(double len) void TaskPadParameters::updateDirectionEdits(void) { PartDesign::Pad* pcPad = static_cast(vp->getObject()); + // we don't want to execute the onChanged edits, but just update their contents + ui->XDirectionEdit->blockSignals(true); + ui->YDirectionEdit->blockSignals(true); + ui->ZDirectionEdit->blockSignals(true); ui->XDirectionEdit->setValue(pcPad->Direction.getValue().x); ui->YDirectionEdit->setValue(pcPad->Direction.getValue().y); ui->ZDirectionEdit->setValue(pcPad->Direction.getValue().z); + ui->XDirectionEdit->blockSignals(false); + ui->YDirectionEdit->blockSignals(false); + ui->ZDirectionEdit->blockSignals(false); } void TaskPadParameters::onOffsetChanged(double len) @@ -355,6 +385,7 @@ void TaskPadParameters::onMidplaneChanged(bool on) { PartDesign::Pad* pcPad = static_cast(vp->getObject()); pcPad->Midplane.setValue(on); + // reversed is not sensible when midplane ui->checkBoxReversed->setEnabled(!on); recomputeFeature(); } @@ -363,6 +394,8 @@ void TaskPadParameters::onReversedChanged(bool on) { PartDesign::Pad* pcPad = static_cast(vp->getObject()); pcPad->Reversed.setValue(on); + // midplane is not sensible when reversed + ui->checkBoxMidplane->setEnabled(!on); recomputeFeature(); } @@ -391,6 +424,7 @@ void TaskPadParameters::onButtonFace(const bool pressed) { this->blockConnection(!pressed); + // only faces are allowed TaskSketchBasedParameters::onSelectReference(pressed, false, true, false); // Update button if onButtonFace() is called explicitly @@ -432,6 +466,11 @@ double TaskPadParameters::getLength2(void) const return ui->lengthEdit2->value().getValue(); } +bool TaskPadParameters::getAlongCustom(void) const +{ + return ui->checkBoxAlongDirection->isChecked(); +} + bool TaskPadParameters::getCustom(void) const { return ui->groupBoxDirection->isChecked(); @@ -563,6 +602,7 @@ void TaskPadParameters::apply() FCMD_OBJ_CMD(obj, "UseCustomVector = " << (getCustom() ? 1 : 0)); FCMD_OBJ_CMD(obj, "Direction = (" << getXDirection() << ", " << getYDirection() << ", " << getZDirection() << ")"); + FCMD_OBJ_CMD(obj, "AlongCustomVector = " << (getAlongCustom() ? 1 : 0)); FCMD_OBJ_CMD(obj,"Type = " << getMode()); QString facename = getFaceName(); FCMD_OBJ_CMD(obj,"UpToFace = " << facename.toLatin1().data()); diff --git a/src/Mod/PartDesign/Gui/TaskPadParameters.h b/src/Mod/PartDesign/Gui/TaskPadParameters.h index 17172344ed..ede9b7278c 100644 --- a/src/Mod/PartDesign/Gui/TaskPadParameters.h +++ b/src/Mod/PartDesign/Gui/TaskPadParameters.h @@ -58,6 +58,7 @@ public: private Q_SLOTS: void onLengthChanged(double); void onLength2Changed(double); + void onCBAlongDirectionChanged(bool); void onGBDirectionChanged(bool); void onXDirectionEditChanged(double); void onYDirectionEditChanged(double); @@ -75,6 +76,7 @@ protected: private: double getLength(void) const; double getLength2(void) const; + bool getAlongCustom(void) const; bool getCustom(void) const; double getXDirection(void) const; double getYDirection(void) const; diff --git a/src/Mod/PartDesign/Gui/TaskPadParameters.ui b/src/Mod/PartDesign/Gui/TaskPadParameters.ui index 5a040a832d..a2c73db1c2 100644 --- a/src/Mod/PartDesign/Gui/TaskPadParameters.ui +++ b/src/Mod/PartDesign/Gui/TaskPadParameters.ui @@ -7,13 +7,13 @@ 0 0 280 - 350 + 373 Form - + @@ -66,97 +66,114 @@ the sketch plane's normal vector will be used 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 - - - - - - + + + + + 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 + + + + + + + + + + true + + + If unchecked, the length will be +measured along the specified direction + + + Length along sketch normal + + + true + + + diff --git a/src/Mod/PartDesign/PartDesignTests/TestPad.py b/src/Mod/PartDesign/PartDesignTests/TestPad.py index 28f6e9ba6c..16d0f16345 100644 --- a/src/Mod/PartDesign/PartDesignTests/TestPad.py +++ b/src/Mod/PartDesign/PartDesignTests/TestPad.py @@ -159,8 +159,8 @@ class TestPad(unittest.TestCase): self.Body.addObject(self.Pad1) self.Pad1.Profile = self.PadSketch1 self.Pad1.Type = 4 - self.Pad1.Length = 2.0 - self.Pad1.Length2 = 1.0 + self.Pad1.Length = 1.0 + self.Pad1.Length2 = 2.0 self.Pad1.Reversed = 1 self.Doc.recompute() self.assertAlmostEqual(self.Pad1.Shape.Volume, 4.0)