From f1b5a6044ded3529dfffb2bdff6fb86d4bf0c11d Mon Sep 17 00:00:00 2001 From: jrheinlaender Date: Wed, 10 Jul 2013 10:15:50 +0200 Subject: [PATCH] Allow extruding from a datum plane to another face or plane, optionally with an offset --- src/Mod/PartDesign/App/FeaturePad.cpp | 79 +++++++++++++------ src/Mod/PartDesign/App/FeaturePad.h | 1 + src/Mod/PartDesign/App/FeaturePocket.cpp | 3 +- src/Mod/PartDesign/App/FeaturePocket.h | 1 + src/Mod/PartDesign/App/FeatureSketchBased.cpp | 15 +++- src/Mod/PartDesign/App/FeatureSketchBased.h | 3 +- .../PartDesign/Gui/TaskDatumParameters.cpp | 6 +- .../PartDesign/Gui/TaskGrooveParameters.cpp | 2 +- src/Mod/PartDesign/Gui/TaskPadParameters.cpp | 56 ++++++++++++- src/Mod/PartDesign/Gui/TaskPadParameters.h | 2 + src/Mod/PartDesign/Gui/TaskPadParameters.ui | 31 +++++++- .../PartDesign/Gui/TaskPocketParameters.cpp | 45 ++++++++++- src/Mod/PartDesign/Gui/TaskPocketParameters.h | 2 + .../PartDesign/Gui/TaskPocketParameters.ui | 22 +++++- .../Gui/TaskRevolutionParameters.cpp | 2 +- .../Gui/TaskSketchBasedParameters.cpp | 2 +- 16 files changed, 230 insertions(+), 42 deletions(-) diff --git a/src/Mod/PartDesign/App/FeaturePad.cpp b/src/Mod/PartDesign/App/FeaturePad.cpp index 638d69828..90b524c1a 100644 --- a/src/Mod/PartDesign/App/FeaturePad.cpp +++ b/src/Mod/PartDesign/App/FeaturePad.cpp @@ -39,6 +39,9 @@ # include # include # include +# include +# include +# include #endif #include @@ -64,6 +67,7 @@ Pad::Pad() ADD_PROPERTY_TYPE(Length,(100.0),"Pad",App::Prop_None,"Pad length"); ADD_PROPERTY_TYPE(Length2,(100.0),"Pad",App::Prop_None,"P"); ADD_PROPERTY_TYPE(UpToFace,(0),"Pad",App::Prop_None,"Face where pad will end"); + ADD_PROPERTY(Offset,(0.0)); } short Pad::mustExecute() const @@ -155,12 +159,9 @@ App::DocumentObjectExecReturn *Pad::execute(void) sketchshape.Move(invObjLoc); TopoDS_Shape prism; - std::string method(Type.getValueAsString()); + std::string method(Type.getValueAsString()); if (method == "UpToFirst" || method == "UpToLast" || method == "UpToFace") { - // TODO: Write our own PrismMaker which does not depend on a solid base shape - if (base.IsNull()) - return new App::DocumentObjectExecReturn("Pad: Extruding up to a face is only possible if the sketch is located on a face"); - // Note: This will return an unlimited planar face if support is a datum plane + // Note: This will return an unlimited planar face if support is a datum plane TopoDS_Face supportface = getSupportFace(); supportface.Move(invObjLoc); @@ -173,27 +174,57 @@ App::DocumentObjectExecReturn *Pad::execute(void) getUpToFaceFromLinkSub(upToFace, UpToFace); upToFace.Move(invObjLoc); } - getUpToFace(upToFace, base, supportface, sketchshape, method, dir); + getUpToFace(upToFace, base, supportface, sketchshape, method, dir, Offset.getValue()); - // A support object is always required and we need to use BRepFeat_MakePrism - // Problem: For Pocket/UpToFirst (or an equivalent Pocket/UpToFace) the resulting shape is invalid - // because the feature does not add any material. This only happens with the "2" option, though - // Note: It might be possible to pass a shell or a compound containing multiple faces - // as the Until parameter of Perform() - // Note: Multiple independent wires are not supported, we should check for that and - // warn the user - // FIXME: If the support shape is not the previous solid in the tree, then there will be unexpected results - // Check supportface for limits, otherwise Perform() throws an exception - TopExp_Explorer Ex(supportface,TopAbs_WIRE); - if (!Ex.More()) - supportface = TopoDS_Face(); - BRepFeat_MakePrism PrismMaker; - PrismMaker.Init(base, sketchshape, supportface, dir, 2, 1); - PrismMaker.Perform(upToFace); + // TODO: Write our own PrismMaker which does not depend on a solid base shape + if (base.IsNull()) { + // Workaround because BRepFeat_MakePrism requires the base face located on a solid to be able to extrude up to a face + // Handle special case of extruding up to a face or plane parallel to the base face + BRepAdaptor_Surface adapt(upToFace); + if (adapt.GetType() != GeomAbs_Plane) + return new App::DocumentObjectExecReturn("Pad: Extruding up to a face or plane is only possible if the sketch is located on a face"); - if (!PrismMaker.IsDone()) - return new App::DocumentObjectExecReturn("Pad: Up to face: Could not extrude the sketch!"); - prism = PrismMaker.Shape(); + double angle = dir.Angle(adapt.Plane().Axis().Direction()); + if (angle > Precision::Confusion()) + return new App::DocumentObjectExecReturn("Pad: Extruding up to a face is only possible if the sketch plane is parallel to it"); + + // Project basepoint of sketch onto the UpToFace to determine distance and direction + gp_Pnt basePoint(SketchPos.getPosition().x, SketchPos.getPosition().y, SketchPos.getPosition().z); + GeomAPI_ProjectPointOnSurf prj(basePoint, adapt.Surface().Surface()); + if (prj.NbPoints() != 1) + return new App::DocumentObjectExecReturn("Pad: Extruding up to a face failed to find extrusion direction"); + // Distance + double length = prj.Distance(1) + Offset.getValue(); + if (length < Precision::Confusion()) + return new App::DocumentObjectExecReturn("Pad: Extruding up to a face failed because of zero height"); + + // Direction (the distance is always positive) + gp_Pnt prjP = prj.NearestPoint(); + dir = gp_Dir(gp_Vec(basePoint, prjP)); + dir.Transform(invObjLoc.Transformation()); + + generatePrism(prism, sketchshape, "Length", dir, length, 0.0, false, false); + } else { + // A support object is always required and we need to use BRepFeat_MakePrism + // Problem: For Pocket/UpToFirst (or an equivalent Pocket/UpToFace) the resulting shape is invalid + // because the feature does not add any material. This only happens with the "2" option, though + // Note: It might be possible to pass a shell or a compound containing multiple faces + // as the Until parameter of Perform() + // Note: Multiple independent wires are not supported, we should check for that and + // warn the user + // FIXME: If the support shape is not the previous solid in the tree, then there will be unexpected results + // Check supportface for limits, otherwise Perform() throws an exception + TopExp_Explorer Ex(supportface,TopAbs_WIRE); + if (!Ex.More()) + supportface = TopoDS_Face(); + BRepFeat_MakePrism PrismMaker; + PrismMaker.Init(base, sketchshape, supportface, dir, 2, 1); + PrismMaker.Perform(upToFace); + + if (!PrismMaker.IsDone()) + return new App::DocumentObjectExecReturn("Pad: Up to face: Could not extrude the sketch!"); + prism = PrismMaker.Shape(); + } } else { generatePrism(prism, sketchshape, method, dir, L, L2, Midplane.getValue(), Reversed.getValue()); diff --git a/src/Mod/PartDesign/App/FeaturePad.h b/src/Mod/PartDesign/App/FeaturePad.h index 510bf20fe..72b087804 100644 --- a/src/Mod/PartDesign/App/FeaturePad.h +++ b/src/Mod/PartDesign/App/FeaturePad.h @@ -42,6 +42,7 @@ public: App::PropertyEnumeration Type; App::PropertyLength Length; App::PropertyLength Length2; + App::PropertyFloat Offset; /** @name methods override feature */ //@{ diff --git a/src/Mod/PartDesign/App/FeaturePocket.cpp b/src/Mod/PartDesign/App/FeaturePocket.cpp index c7dbfcc1e..43e07b69a 100644 --- a/src/Mod/PartDesign/App/FeaturePocket.cpp +++ b/src/Mod/PartDesign/App/FeaturePocket.cpp @@ -62,6 +62,7 @@ Pocket::Pocket() Type.setEnums(TypeEnums); ADD_PROPERTY_TYPE(Length,(100.0),"Pocket",App::Prop_None,"Pocket length"); ADD_PROPERTY_TYPE(UpToFace,(0),"Pocket",App::Prop_None,"Face where pocket will end"); + ADD_PROPERTY(Offset,(0.0)); } short Pocket::mustExecute() const @@ -150,7 +151,7 @@ App::DocumentObjectExecReturn *Pocket::execute(void) getUpToFaceFromLinkSub(upToFace, UpToFace); upToFace.Move(invObjLoc); } - getUpToFace(upToFace, base, supportface, sketchshape, method, dir); + getUpToFace(upToFace, base, supportface, sketchshape, method, dir, Offset.getValue()); // Special treatment because often the created stand-alone prism is invalid (empty) because // BRepFeat_MakePrism(..., 2, 1) is buggy diff --git a/src/Mod/PartDesign/App/FeaturePocket.h b/src/Mod/PartDesign/App/FeaturePocket.h index 57b298e77..250bbca80 100644 --- a/src/Mod/PartDesign/App/FeaturePocket.h +++ b/src/Mod/PartDesign/App/FeaturePocket.h @@ -39,6 +39,7 @@ public: App::PropertyEnumeration Type; App::PropertyLength Length; + App::PropertyFloat Offset; /** @name methods override feature */ //@{ diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.cpp b/src/Mod/PartDesign/App/FeatureSketchBased.cpp index 4f0d74c21..133650146 100644 --- a/src/Mod/PartDesign/App/FeatureSketchBased.cpp +++ b/src/Mod/PartDesign/App/FeatureSketchBased.cpp @@ -494,7 +494,8 @@ void SketchBased::getUpToFace(TopoDS_Face& upToFace, const TopoDS_Face& supportface, const TopoDS_Shape& sketchshape, const std::string& method, - const gp_Dir& dir) + const gp_Dir& dir, + const double offset) { if ((method == "UpToLast") || (method == "UpToFirst")) { // Check for valid support object @@ -564,6 +565,18 @@ void SketchBased::getUpToFace(TopoDS_Face& upToFace, if (distSS.Value() < Precision::Confusion()) throw Base::Exception("SketchBased: Up to face: Must not intersect sketch!"); + // Move the face in the extrusion direction + // TODO: For non-planar faces, we could consider offsetting the surface + if (fabs(offset) > Precision::Confusion()) { + if (adapt2.GetType() == GeomAbs_Plane) { + gp_Trsf mov; + mov.SetTranslation(offset * gp_Vec(dir)); + TopLoc_Location loc(mov); + upToFace.Move(loc); + } else { + throw Base::Exception("SketchBased: Up to Face: Offset not supported yet for non-planar faces"); + } + } } void SketchBased::generatePrism(TopoDS_Shape& prism, diff --git a/src/Mod/PartDesign/App/FeatureSketchBased.h b/src/Mod/PartDesign/App/FeatureSketchBased.h index 5336b218c..aff24dac1 100644 --- a/src/Mod/PartDesign/App/FeatureSketchBased.h +++ b/src/Mod/PartDesign/App/FeatureSketchBased.h @@ -101,7 +101,8 @@ protected: const TopoDS_Face& supportface, const TopoDS_Shape& sketchshape, const std::string& method, - const gp_Dir& dir); + const gp_Dir& dir, + const double offset); /** * Generate a linear prism * It will be a stand-alone solid created with BRepPrimAPI_MakePrism diff --git a/src/Mod/PartDesign/Gui/TaskDatumParameters.cpp b/src/Mod/PartDesign/Gui/TaskDatumParameters.cpp index 6e75ea845..1c0876310 100644 --- a/src/Mod/PartDesign/Gui/TaskDatumParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskDatumParameters.cpp @@ -68,13 +68,13 @@ const QString makeRefString(const App::DocumentObject* obj, const std::string& s if ((sub.size() > 4) && (sub.substr(0,4) == "Face")) { int subId = std::atoi(&sub[4]); - return QString::fromAscii(obj->getNameInDocument()) + QObject::tr(":Face") + QString::number(subId); + return QString::fromAscii(obj->getNameInDocument()) + QString::fromAscii(":") + QObject::tr("Face") + QString::number(subId); } else if ((sub.size() > 4) && (sub.substr(0,4) == "Edge")) { int subId = std::atoi(&sub[4]); - return QString::fromAscii(obj->getNameInDocument()) + QObject::tr(":Edge") + QString::number(subId); + return QString::fromAscii(obj->getNameInDocument()) + QString::fromAscii(":") + QObject::tr("Edge") + QString::number(subId); } if ((sub.size() > 6) && (sub.substr(0,6) == "Vertex")) { int subId = std::atoi(&sub[6]); - return QString::fromAscii(obj->getNameInDocument()) + QObject::tr(":Vertex") + QString::number(subId); + return QString::fromAscii(obj->getNameInDocument()) + QString::fromAscii(":") + QObject::tr("Vertex") + QString::number(subId); } return QObject::tr("No reference selected"); diff --git a/src/Mod/PartDesign/Gui/TaskGrooveParameters.cpp b/src/Mod/PartDesign/Gui/TaskGrooveParameters.cpp index 27011e7ad..c3a7a530c 100644 --- a/src/Mod/PartDesign/Gui/TaskGrooveParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskGrooveParameters.cpp @@ -331,7 +331,7 @@ void TaskGrooveParameters::apply() ui->grooveAngle->apply(); std::vector sub; App::DocumentObject* obj; - parameter->getReferenceAxis(obj, sub); + getReferenceAxis(obj, sub); std::string axis = getPythonStr(obj, sub); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.ReferenceAxis = %s",name.c_str(),axis.c_str()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Midplane = %i",name.c_str(), getMidplane() ? 1 : 0); diff --git a/src/Mod/PartDesign/Gui/TaskPadParameters.cpp b/src/Mod/PartDesign/Gui/TaskPadParameters.cpp index 529e553d4..61df266fd 100644 --- a/src/Mod/PartDesign/Gui/TaskPadParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPadParameters.cpp @@ -72,6 +72,8 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView,bool newObj, QWidg this, SLOT(onReversed(bool))); connect(ui->lengthEdit2, SIGNAL(valueChanged(double)), this, SLOT(onLength2Changed(double))); + connect(ui->spinOffset, SIGNAL(valueChanged(double)), + this, SLOT(onOffsetChanged(double))); connect(ui->changeMode, SIGNAL(currentIndexChanged(int)), this, SLOT(onModeChanged(int))); connect(ui->buttonFace, SIGNAL(clicked()), @@ -86,6 +88,7 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView,bool newObj, QWidg // Temporarily prevent unnecessary feature recomputes ui->lengthEdit->blockSignals(true); ui->lengthEdit2->blockSignals(true); + ui->spinOffset->blockSignals(true); ui->checkBoxMidplane->blockSignals(true); ui->checkBoxReversed->blockSignals(true); ui->buttonFace->blockSignals(true); @@ -102,6 +105,7 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView,bool newObj, QWidg bool midplane = pcPad->Midplane.getValue(); bool reversed = pcPad->Reversed.getValue(); Base::Quantity l2 = pcPad->Length2.getQuantityValue(); + double off = pcPad->Offset.getValue(); int index = pcPad->Type.getValue(); // must extract value here, clear() kills it! App::DocumentObject* obj = pcPad->UpToFace.getValue(); std::vector subStrings = pcPad->UpToFace.getSubValues(); @@ -120,11 +124,13 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView,bool newObj, QWidg ui->lengthEdit2->setMinimum(0); ui->lengthEdit2->setMaximum(INT_MAX); ui->lengthEdit2->setValue(l2); + ui->spinOffset->setMaximum(INT_MAX); + ui->spinOffset->setMinimum(-INT_MAX); + ui->spinOffset->setValue(off); // Bind input fields to properties ui->lengthEdit->bind(pcPad->Length); ui->lengthEdit2->bind(pcPad->Length2); - ui->checkBoxMidplane->setChecked(midplane); // According to bug #0000521 the reversed option // shouldn't be de-activated if the pad has a support face @@ -132,7 +138,7 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView,bool newObj, QWidg if ((obj != NULL) && PartDesign::Feature::isDatum(obj)) ui->lineFaceName->setText(QString::fromAscii(obj->getNameInDocument())); else if (faceId >= 0) - ui->lineFaceName->setText(QString::fromAscii(obj->getNameInDocument()) + tr("Face") + + ui->lineFaceName->setText(QString::fromAscii(obj->getNameInDocument()) + QString::fromAscii(":") + tr("Face") + QString::number(faceId)); else ui->lineFaceName->setText(tr("No face selected")); @@ -148,6 +154,7 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView,bool newObj, QWidg // activate and de-activate dialog elements as appropriate ui->lengthEdit->blockSignals(false); ui->lengthEdit2->blockSignals(false); + ui->spinOffset->blockSignals(false); ui->checkBoxMidplane->blockSignals(false); ui->checkBoxReversed->blockSignals(false); ui->buttonFace->blockSignals(false); @@ -167,8 +174,13 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView,bool newObj, QWidg void TaskPadParameters::updateUI(int index) { if (index == 0) { // dimension + ui->lengthEdit->setVisible(true); ui->lengthEdit->setEnabled(true); ui->lengthEdit->selectNumber(); + ui->labelLength->setVisible(true); + ui->spinOffset->setVisible(false); + ui->spinOffset->setEnabled(false); + ui->labelOffset->setVisible(false); // 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 // yet visible. @@ -176,22 +188,38 @@ void TaskPadParameters::updateUI(int index) ui->checkBoxMidplane->setEnabled(true); // Reverse only makes sense if Midplane is not true ui->checkBoxReversed->setEnabled(!ui->checkBoxMidplane->isChecked()); + ui->labelLength2->setVisible(false); + ui->lengthEdit2->setVisible(false); ui->lengthEdit2->setEnabled(false); ui->buttonFace->setEnabled(false); ui->lineFaceName->setEnabled(false); onButtonFace(false); } else if (index == 1 || index == 2) { // up to first/last + ui->lengthEdit->setVisible(false); ui->lengthEdit->setEnabled(false); + ui->labelLength->setVisible(false); + ui->spinOffset->setVisible(true); + ui->spinOffset->setEnabled(true); + ui->labelOffset->setVisible(true); ui->checkBoxMidplane->setEnabled(false); ui->checkBoxReversed->setEnabled(true); + ui->labelLength2->setVisible(false); + ui->lengthEdit2->setVisible(false); ui->lengthEdit2->setEnabled(false); ui->buttonFace->setEnabled(false); ui->lineFaceName->setEnabled(false); onButtonFace(false); } else if (index == 3) { // up to face + ui->lengthEdit->setVisible(false); ui->lengthEdit->setEnabled(false); + ui->labelLength->setVisible(false); + ui->spinOffset->setVisible(true); + ui->spinOffset->setEnabled(true); + ui->labelOffset->setVisible(true); ui->checkBoxMidplane->setEnabled(false); ui->checkBoxReversed->setEnabled(false); + ui->labelLength2->setVisible(false); + ui->lengthEdit2->setVisible(false); ui->lengthEdit2->setEnabled(false); ui->buttonFace->setEnabled(true); ui->lineFaceName->setEnabled(true); @@ -201,10 +229,17 @@ void TaskPadParameters::updateUI(int index) onButtonFace(true); } else { // two dimensions ui->lengthEdit->setEnabled(true); + ui->lengthEdit->setVisible(true); ui->lengthEdit->selectNumber(); QMetaObject::invokeMethod(ui->lengthEdit, "setFocus", Qt::QueuedConnection); + ui->labelLength->setVisible(true); + ui->spinOffset->setVisible(false); + ui->spinOffset->setEnabled(false); + ui->labelOffset->setVisible(false); ui->checkBoxMidplane->setEnabled(false); ui->checkBoxReversed->setEnabled(false); + ui->labelLength2->setVisible(true); + ui->lengthEdit2->setVisible(true); ui->lengthEdit2->setEnabled(true); ui->buttonFace->setEnabled(false); ui->lineFaceName->setEnabled(false); @@ -268,6 +303,13 @@ void TaskPadParameters::onLength2Changed(double len) recomputeFeature(); } +void TaskPadParameters::onOffsetChanged(double len) +{ + PartDesign::Pad* pcPad = static_cast(vp->getObject()); + pcPad->Offset.setValue(len); + recomputeFeature(); +} + void TaskPadParameters::onModeChanged(int index) { PartDesign::Pad* pcPad = static_cast(vp->getObject()); @@ -322,6 +364,11 @@ double TaskPadParameters::getLength2(void) const return ui->lengthEdit2->value().getValue(); } +double TaskPadParameters::getOffset(void) const +{ + return ui->spinOffset->value(); +} + int TaskPadParameters::getMode(void) const { return ui->changeMode->currentIndex(); @@ -346,6 +393,7 @@ void TaskPadParameters::changeEvent(QEvent *e) if (e->type() == QEvent::LanguageChange) { ui->lengthEdit->blockSignals(true); ui->lengthEdit2->blockSignals(true); + ui->spinOffset->blockSignals(true); ui->lineFaceName->blockSignals(true); ui->changeMode->blockSignals(true); int index = ui->changeMode->currentIndex(); @@ -369,10 +417,11 @@ void TaskPadParameters::changeEvent(QEvent *e) ui->lineFaceName->setPlaceholderText(tr("No face selected")); #endif ui->lineFaceName->setText(ok ? - parts[0] + tr(":Face") + QString::number(faceId) : + parts[0] + QString::fromAscii(":") + tr("Face") + QString::number(faceId) : QString()); ui->lengthEdit->blockSignals(false); ui->lengthEdit2->blockSignals(false); + ui->spinOffset->blockSignals(false); ui->lineFaceName->blockSignals(false); ui->changeMode->blockSignals(false); } @@ -404,6 +453,7 @@ void TaskPadParameters::apply() Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.UpToFace = %s", name.c_str(), facename.c_str()); } else Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.UpToFace = None", cname); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Offset = %f", name.c_str(), getOffset()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); if (!vp->getObject()->isValid()) throw Base::Exception(vp->getObject()->getStatusString()); diff --git a/src/Mod/PartDesign/Gui/TaskPadParameters.h b/src/Mod/PartDesign/Gui/TaskPadParameters.h index 575032319..60bfe0136 100644 --- a/src/Mod/PartDesign/Gui/TaskPadParameters.h +++ b/src/Mod/PartDesign/Gui/TaskPadParameters.h @@ -53,6 +53,7 @@ public: TaskPadParameters(ViewProviderPad *PadView,bool newObj=false,QWidget *parent = 0); ~TaskPadParameters(); + double getOffset(void) const; void saveHistory(void); void apply(); @@ -61,6 +62,7 @@ private Q_SLOTS: void onMidplane(bool); void onReversed(bool); void onLength2Changed(double); + void onOffsetChanged(double); void onModeChanged(int); void onButtonFace(const bool pressed = true); void onFaceName(const QString& text); diff --git a/src/Mod/PartDesign/Gui/TaskPadParameters.ui b/src/Mod/PartDesign/Gui/TaskPadParameters.ui index aade56ebe..ee876fe8b 100644 --- a/src/Mod/PartDesign/Gui/TaskPadParameters.ui +++ b/src/Mod/PartDesign/Gui/TaskPadParameters.ui @@ -37,7 +37,7 @@ - + Length @@ -61,6 +61,33 @@ + + + + + + Offset + + + + + + + 0.000000000000000 + + + 999999999.000000000000000 + + + 5.000000000000000 + + + 0.000000000000000 + + + + + @@ -81,7 +108,7 @@ - + 2nd length diff --git a/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp b/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp index c0cc3008d..023735e2b 100644 --- a/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskPocketParameters.cpp @@ -67,6 +67,8 @@ TaskPocketParameters::TaskPocketParameters(ViewProviderPocket *PocketView,QWidge connect(ui->pocketLength, SIGNAL(valueChanged(double)), this, SLOT(onLengthChanged(double))); + connect(ui->spinOffset, SIGNAL(valueChanged(double)), + this, SLOT(onOffsetChanged(double))); connect(ui->checkBoxMidplane, SIGNAL(toggled(bool)), this, SLOT(onMidplaneChanged(bool))); connect(ui->checkBoxReversed, SIGNAL(toggled(bool)), @@ -84,6 +86,7 @@ TaskPocketParameters::TaskPocketParameters(ViewProviderPocket *PocketView,QWidge // Temporarily prevent unnecessary feature recomputes ui->pocketLength->blockSignals(true); + ui->spinOffset->blockSignals(true); ui->checkBoxMidplane->blockSignals(true); ui->checkBoxReversed->blockSignals(true); ui->buttonFace->blockSignals(true); @@ -93,6 +96,7 @@ TaskPocketParameters::TaskPocketParameters(ViewProviderPocket *PocketView,QWidge // Get the feature data PartDesign::Pocket* pcPocket = static_cast(vp->getObject()); double l = pcPocket->Length.getValue(); + double off = pcPocket->Offset.getValue(); bool midplane = pcPocket->Midplane.getValue(); bool reversed = pcPocket->Reversed.getValue(); int index = pcPocket->Type.getValue(); // must extract value here, clear() kills it! @@ -110,12 +114,15 @@ TaskPocketParameters::TaskPocketParameters(ViewProviderPocket *PocketView,QWidge ui->pocketLength->setMinimum(0); ui->pocketLength->setMaximum(INT_MAX); ui->pocketLength->setValue(l); + ui->spinOffset->setMinimum(-INT_MAX); + ui->spinOffset->setMaximum(INT_MAX); + ui->spinOffset->setValue(off); ui->checkBoxMidplane->setChecked(midplane); ui->checkBoxReversed->setChecked(reversed); if ((obj != NULL) && PartDesign::Feature::isDatum(obj)) ui->lineFaceName->setText(QString::fromAscii(obj->getNameInDocument())); else if (faceId >= 0) - ui->lineFaceName->setText(QString::fromAscii(obj->getNameInDocument()) + tr("Face") + + ui->lineFaceName->setText(QString::fromAscii(obj->getNameInDocument()) + QString::fromAscii(":") + tr("Face") + QString::number(faceId)); else ui->lineFaceName->setText(tr("No face selected")); @@ -131,6 +138,7 @@ TaskPocketParameters::TaskPocketParameters(ViewProviderPocket *PocketView,QWidge ui->pocketLength->bind(pcPocket->Length); ui->pocketLength->blockSignals(false); + ui->spinOffset->blockSignals(false); ui->checkBoxMidplane->blockSignals(false); ui->checkBoxReversed->blockSignals(false); ui->buttonFace->blockSignals(false); @@ -157,9 +165,13 @@ TaskPocketParameters::TaskPocketParameters(ViewProviderPocket *PocketView,QWidge void TaskPocketParameters::updateUI(int index) { if (index == 0) { // Only this option requires a numeric value // Dimension + ui->pocketLength->setVisible(true); ui->pocketLength->setEnabled(true); ui->pocketLength->selectAll(); QMetaObject::invokeMethod(ui->pocketLength, "setFocus", Qt::QueuedConnection); + ui->spinOffset->setVisible(false); + ui->spinOffset->setEnabled(false); + ui->spinOffset->setEnabled(false); ui->checkBoxMidplane->setEnabled(true); // Reverse only makes sense if Midplane is not true ui->checkBoxReversed->setEnabled(!ui->checkBoxMidplane->isChecked()); // Will flip direction of dimension @@ -169,21 +181,35 @@ void TaskPocketParameters::updateUI(int index) } else if (index == 1) { // Through all ui->checkBoxMidplane->setEnabled(true); ui->checkBoxReversed->setEnabled(!ui->checkBoxMidplane->isChecked()); // Will flip direction of through all + ui->pocketLength->setVisible(false); ui->pocketLength->setEnabled(false); + ui->spinOffset->setVisible(false); + ui->spinOffset->setVisible(false); + ui->spinOffset->setEnabled(false); ui->buttonFace->setEnabled(false); ui->lineFaceName->setEnabled(false); onButtonFace(false); } else if (index == 2) { // Neither value nor face required // To First ui->pocketLength->setEnabled(false); + ui->pocketLength->setVisible(false); ui->checkBoxMidplane->setEnabled(false); // Can't have a midplane to a single face ui->checkBoxReversed->setEnabled(false); // Will change the direction it seeks for its first face? // Doesnt work so is currently disabled. Fix probably lies // somwhere in IF block on line 125 of FeaturePocket.cpp + ui->labelLength->setVisible(false); + ui->spinOffset->setVisible(true); + ui->spinOffset->setEnabled(true); + ui->labelOffset->setVisible(true); ui->buttonFace->setEnabled(false); ui->lineFaceName->setEnabled(false); onButtonFace(false); } else if (index == 3) { // Only this option requires to select a face // Up to face ui->pocketLength->setEnabled(false); + ui->pocketLength->setVisible(false); + ui->labelLength->setVisible(false); + ui->spinOffset->setVisible(true); + ui->spinOffset->setEnabled(true); + ui->labelOffset->setVisible(true); ui->checkBoxMidplane->setEnabled(false); ui->checkBoxReversed->setEnabled(false); // No need for reverse since user-chosen face will dtermine direction ui->buttonFace->setEnabled(true); @@ -228,6 +254,13 @@ void TaskPocketParameters::onLengthChanged(double len) recomputeFeature(); } +void TaskPocketParameters::onOffsetChanged(double len) +{ + PartDesign::Pocket* pcPocket = static_cast(vp->getObject()); + pcPocket->Offset.setValue(len); + recomputeFeature(); +} + void TaskPocketParameters::onMidplaneChanged(bool on) { PartDesign::Pocket* pcPocket = static_cast(vp->getObject()); @@ -297,6 +330,11 @@ double TaskPocketParameters::getLength(void) const return ui->pocketLength->value().getValue(); } +double TaskPocketParameters::getOffset(void) const +{ + return ui->spinOffset->value(); +} + bool TaskPocketParameters::getReversed(void) const { return ui->checkBoxReversed->isChecked(); @@ -325,6 +363,7 @@ void TaskPocketParameters::changeEvent(QEvent *e) TaskBox::changeEvent(e); if (e->type() == QEvent::LanguageChange) { ui->pocketLength->blockSignals(true); + ui->spinOffset->blockSignals(true); ui->lineFaceName->blockSignals(true); ui->changeMode->blockSignals(true); int index = ui->changeMode->currentIndex(); @@ -344,9 +383,10 @@ void TaskPocketParameters::changeEvent(QEvent *e) faceId = upToFace.remove(0,4).toInt(&ok); } ui->lineFaceName->setText(ok ? - parts[0] + tr(":Face") + QString::number(faceId) : + parts[0] + QString::fromAscii(":") + tr("Face") + QString::number(faceId) : tr("No face selected")); ui->pocketLength->blockSignals(false); + ui->spinOffset->blockSignals(false); ui->lineFaceName->blockSignals(false); ui->changeMode->blockSignals(false); } @@ -366,6 +406,7 @@ void TaskPocketParameters::apply() } else Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.UpToFace = None", name.c_str()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Reversed = %i", name.c_str(), getReversed()?1:0); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Offset = %f", name.c_str(), getOffset()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.recompute()"); if (!vp->getObject()->isValid()) throw Base::Exception(vp->getObject()->getStatusString()); diff --git a/src/Mod/PartDesign/Gui/TaskPocketParameters.h b/src/Mod/PartDesign/Gui/TaskPocketParameters.h index 77cd96d8e..53359d2ed 100644 --- a/src/Mod/PartDesign/Gui/TaskPocketParameters.h +++ b/src/Mod/PartDesign/Gui/TaskPocketParameters.h @@ -53,12 +53,14 @@ public: TaskPocketParameters(ViewProviderPocket *PocketView,QWidget *parent = 0); ~TaskPocketParameters(); + double getOffset(void) const; bool getReversed(void) const; QByteArray getFaceName(void) const; void apply(); private Q_SLOTS: void onLengthChanged(double); + void onOffsetChanged(double); void onMidplaneChanged(bool); void onReversedChanged(bool); void onModeChanged(int); diff --git a/src/Mod/PartDesign/Gui/TaskPocketParameters.ui b/src/Mod/PartDesign/Gui/TaskPocketParameters.ui index 5a1f41c07..82f8a7f34 100644 --- a/src/Mod/PartDesign/Gui/TaskPocketParameters.ui +++ b/src/Mod/PartDesign/Gui/TaskPocketParameters.ui @@ -7,7 +7,7 @@ 0 0 241 - 188 + 233 @@ -49,7 +49,7 @@ - + Length @@ -67,6 +67,24 @@ + + + + + + Offset + + + + + + + 999999999.000000000000000 + + + + + diff --git a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp index 339592b9e..910f3cd96 100644 --- a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp @@ -332,7 +332,7 @@ void TaskRevolutionParameters::apply() ui->revolveAngle->apply(); std::vector sub; App::DocumentObject* obj; - parameter->getReferenceAxis(obj, sub); + getReferenceAxis(obj, sub); std::string axis = getPythonStr(obj, sub); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.ReferenceAxis = %s",name.c_str(),axis.c_str()); Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.%s.Midplane = %i",name.c_str(), getMidplane() ? 1 : 0); diff --git a/src/Mod/PartDesign/Gui/TaskSketchBasedParameters.cpp b/src/Mod/PartDesign/Gui/TaskSketchBasedParameters.cpp index 2cfb7f030..08097599e 100644 --- a/src/Mod/PartDesign/Gui/TaskSketchBasedParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskSketchBasedParameters.cpp @@ -79,7 +79,7 @@ const QString TaskSketchBasedParameters::onAddSelection(const Gui::SelectionChan refStr = QString::fromAscii(selObj->getNameInDocument()); } else { int faceId = std::atoi(&subname[4]); - refStr = QString::fromAscii(selObj->getNameInDocument()) + QObject::tr(":Face") + QString::number(faceId); + refStr = QString::fromAscii(selObj->getNameInDocument()) + QString::fromAscii(":") + QObject::tr("Face") + QString::number(faceId); } std::vector upToFaces(1,subname);