diff --git a/src/Mod/PartDesign/App/FeatureRevolution.cpp b/src/Mod/PartDesign/App/FeatureRevolution.cpp index 57312f172b..d6f3d96518 100644 --- a/src/Mod/PartDesign/App/FeatureRevolution.cpp +++ b/src/Mod/PartDesign/App/FeatureRevolution.cpp @@ -25,6 +25,7 @@ #ifndef _PreComp_ # include # include +# include # include # include # include @@ -42,6 +43,7 @@ using namespace PartDesign; namespace PartDesign { +const char* Revolution::TypeEnums[]= {"Angle", "UpToLast", "UpToFirst", "UpToFace", "TwoAngles", nullptr}; PROPERTY_SOURCE(PartDesign::Revolution, PartDesign::ProfileBased) @@ -51,9 +53,14 @@ Revolution::Revolution() { addSubType = FeatureAddSub::Additive; + ADD_PROPERTY_TYPE(Type, (0L), "Revolution", App::Prop_None, "Revolution type"); + Type.setEnums(TypeEnums); ADD_PROPERTY_TYPE(Base,(Base::Vector3d(0.0,0.0,0.0)),"Revolution", App::Prop_ReadOnly, "Base"); ADD_PROPERTY_TYPE(Axis,(Base::Vector3d(0.0,1.0,0.0)),"Revolution", App::Prop_ReadOnly, "Axis"); ADD_PROPERTY_TYPE(Angle,(360.0),"Revolution", App::Prop_None, "Angle"); + ADD_PROPERTY_TYPE(UpToFace, (nullptr), "Revolution", App::Prop_None, "Face where revolution will end"); + ADD_PROPERTY_TYPE(Angle2, (60.0), "Revolution", App::Prop_None, "Revolution length in 2nd direction"); + Angle.setConstraints(&floatAngle); ADD_PROPERTY_TYPE(ReferenceAxis,(nullptr),"Revolution",(App::Prop_None),"Reference axis of revolution"); } @@ -64,7 +71,9 @@ short Revolution::mustExecute() const ReferenceAxis.isTouched() || Axis.isTouched() || Base.isTouched() || - Angle.isTouched()) + UpToFace.isTouched() || + Angle.isTouched() || + Angle2.isTouched()) return 1; return ProfileBased::mustExecute(); } @@ -140,11 +149,46 @@ App::DocumentObjectExecReturn *Revolution::execute() return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Revolve axis intersects the sketch")); } - // revolve the face to a solid - BRepPrimAPI_MakeRevol RevolMaker(sketchshape, gp_Ax1(pnt, dir), angle); + TopoDS_Shape result; - if (RevolMaker.IsDone()) { - TopoDS_Shape result = RevolMaker.Shape(); + std::string method(Type.getValueAsString()); + if (method == "UpToFace") { + TopoDS_Face supportface = getSupportFace(); + supportface.Move(invObjLoc); + + TopoDS_Face upToFace; + if (method == "UpToFace") { + getFaceFromLinkSub(upToFace, UpToFace); + upToFace.Move(invObjLoc); + } + getUpToFace(upToFace, base, sketchshape, method, dir); + + // TODO: Make enum + int mode = 2; + BRepFeat_MakeRevol RevolMaker; + for (TopExp_Explorer xp(sketchshape, TopAbs_FACE); xp.More(); xp.Next()) { + RevolMaker.Init(base, xp.Current(), supportface, gp_Ax1(pnt, dir), mode, Standard_True); + RevolMaker.Perform(upToFace); + + if (!RevolMaker.IsDone()) + throw Base::RuntimeError("ProfileBased: Up to face: Could not revolve the sketch!"); + + base = RevolMaker.Shape(); + if (mode == 2) + mode = 1; + } + + result = base; + } + else { + // revolve the face to a solid + BRepPrimAPI_MakeRevol RevolMaker(sketchshape, gp_Ax1(pnt, dir), angle); + + if (RevolMaker.IsDone()) + result = RevolMaker.Shape(); + } + + if (!result.IsNull()) { result = refineShapeIfActive(result); // set the additive shape property for later usage in e.g. pattern this->AddSubShape.setValue(result); diff --git a/src/Mod/PartDesign/App/FeatureRevolution.h b/src/Mod/PartDesign/App/FeatureRevolution.h index 23478f46c2..210156f2ad 100644 --- a/src/Mod/PartDesign/App/FeatureRevolution.h +++ b/src/Mod/PartDesign/App/FeatureRevolution.h @@ -37,9 +37,11 @@ class PartDesignExport Revolution : public ProfileBased public: Revolution(); + App::PropertyEnumeration Type; App::PropertyVector Base; App::PropertyVector Axis; App::PropertyAngle Angle; + App::PropertyAngle Angle2; /** if this property is set to a valid link, both Axis and Base properties * are calculated according to the linked line @@ -65,11 +67,15 @@ public: /// suggests a value for Reversed flag so that material is always added to the support bool suggestReversed(); + protected: /// updates Axis from ReferenceAxis void updateAxis(); static const App::PropertyAngle::Constraints floatAngle; + +private: + static const char* TypeEnums[]; }; } //namespace PartDesign diff --git a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp index 134bd92399..61c32d9cf5 100644 --- a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp @@ -59,10 +59,13 @@ TaskRevolutionParameters::TaskRevolutionParameters(PartDesignGui::ViewProvider* // bind property mirrors if (auto *rev = dynamic_cast(vp->getObject())) { this->propAngle = &(rev->Angle); + this->propAngle2 = &(rev->Angle2); this->propMidPlane = &(rev->Midplane); this->propReferenceAxis = &(rev->ReferenceAxis); this->propReversed = &(rev->Reversed); + this->propUpToFace = &(rev->UpToFace); ui->revolveAngle->bind(rev->Angle); + ui->revolveAngle2->bind(rev->Angle2); } else if (auto *rev = dynamic_cast(vp->getObject())) { this->propAngle = &(rev->Angle); @@ -75,18 +78,13 @@ TaskRevolutionParameters::TaskRevolutionParameters(PartDesignGui::ViewProvider* throw Base::TypeError("The object is neither a Groove nor a Revolution."); } - ui->checkBoxMidplane->setChecked(propMidPlane->getValue()); - ui->checkBoxReversed->setChecked(propReversed->getValue()); - - ui->revolveAngle->setValue(propAngle->getValue()); - ui->revolveAngle->setMaximum(propAngle->getMaximum()); - ui->revolveAngle->setMinimum(propAngle->getMinimum()); + setupDialog(); blockUpdate = false; updateUI(); connectSignals(); - setFocus (); + setFocus(); // show the parts coordinate system axis for selection PartDesign::Body * body = PartDesign::Body::findBodyOf ( vp->getObject () ); @@ -103,6 +101,31 @@ TaskRevolutionParameters::TaskRevolutionParameters(PartDesignGui::ViewProvider* } } +void TaskRevolutionParameters::setupDialog() +{ + PartDesign::ProfileBased* pcFeat = static_cast(vp->getObject()); + ui->checkBoxMidplane->setChecked(propMidPlane->getValue()); + ui->checkBoxReversed->setChecked(propReversed->getValue()); + + ui->revolveAngle->setValue(propAngle->getValue()); + ui->revolveAngle->setMaximum(propAngle->getMaximum()); + ui->revolveAngle->setMinimum(propAngle->getMinimum()); + + int index = 0; + + // TODO: This should also be implemented for groove + if (pcFeat->isDerivedFrom(PartDesign::Revolution::getClassTypeId())) { + PartDesign::Revolution* rev = static_cast(vp->getObject()); + ui->revolveAngle2->setValue(propAngle2->getValue()); + ui->revolveAngle2->setMaximum(propAngle2->getMaximum()); + ui->revolveAngle2->setMinimum(propAngle2->getMinimum()); + + index = rev->Type.getValue(); + } + + translateModeList(index); +} + void TaskRevolutionParameters::fillAxisCombo(bool forceRefill) { Base::StateLocker lock(blockUpdate, true); @@ -217,6 +240,18 @@ void TaskRevolutionParameters::onSelectionChanged(const Gui::SelectionChanges& m } } +void TaskRevolutionParameters::translateModeList(int index) +{ + // Must correspond to values from PartDesign::Revolution::TypeEnums + ui->changeMode->clear(); + ui->changeMode->addItem(tr("Dimension")); + // ui->changeMode->addItem(tr("To last")); + // ui->changeMode->addItem(tr("To first")); + ui->changeMode->addItem(tr("Up to face")); + ui->changeMode->addItem(tr("Two dimensions")); + ui->changeMode->setCurrentIndex(index); +} + void TaskRevolutionParameters::onAngleChanged(double len) { @@ -354,6 +389,9 @@ void TaskRevolutionParameters::changeEvent(QEvent *event) TaskBox::changeEvent(event); if (event->type() == QEvent::LanguageChange) { ui->retranslateUi(proxy); + + // Translate mode items + translateModeList(ui->changeMode->currentIndex()); } } diff --git a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.h b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.h index 1d81ea59a4..07b574f1f7 100644 --- a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.h +++ b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.h @@ -49,6 +49,15 @@ public: void apply() override; + enum class Modes { + Dimension, + ThroughAll, + ToLast = ThroughAll, + ToFirst, + ToFace, + TwoDimensions + }; + /** * @brief fillAxisCombo fills the combo and selects the item according to * current value of revolution object's axis reference. @@ -71,17 +80,21 @@ protected: void getReferenceAxis(App::DocumentObject *&obj, std::vector &sub) const; bool getMidplane() const; bool getReversed() const; + void setupDialog(void); //mirrors of revolution's or groove's properties //should have been done by inheriting revolution and groove from common class... App::PropertyAngle* propAngle; + App::PropertyAngle* propAngle2; App::PropertyBool* propReversed; App::PropertyBool* propMidPlane; App::PropertyLinkSub* propReferenceAxis; + App::PropertyLinkSub* propUpToFace; private: void connectSignals(); void updateUI(); + void translateModeList(int index); private: std::unique_ptr ui; diff --git a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.ui b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.ui index 5f55ae1e12..36affd62b4 100644 --- a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.ui +++ b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.ui @@ -14,6 +14,26 @@ Form + + + + + + Type + + + + + + + + Dimension + + + + + + @@ -109,6 +129,53 @@ + + + + + + 2nd angle + + + + + + + false + + + deg + + + 0.000000000000000 + + + 360.000000000000000 + + + 10.000000000000000 + + + 60.000000000000000 + + + + + + + + + + + Face + + + + + + + +