diff --git a/src/Mod/PartDesign/App/FeatureRevolution.cpp b/src/Mod/PartDesign/App/FeatureRevolution.cpp index 62e516fb4c..9133bdda23 100644 --- a/src/Mod/PartDesign/App/FeatureRevolution.cpp +++ b/src/Mod/PartDesign/App/FeatureRevolution.cpp @@ -30,9 +30,7 @@ # include -#include #include -#include #include #include "FeatureRevolution.h" @@ -42,11 +40,13 @@ using namespace PartDesign; namespace PartDesign { +/* TRANSLATOR PartDesign::Revolution */ + const char* Revolution::TypeEnums[]= {"Angle", "UpToLast", "UpToFirst", "UpToFace", "TwoAngles", nullptr}; PROPERTY_SOURCE(PartDesign::Revolution, PartDesign::ProfileBased) -const App::PropertyAngle::Constraints Revolution::floatAngle = { Base::toDegrees(Precision::Angular()), 360.0, 1.0 }; +const App::PropertyAngle::Constraints Revolution::floatAngle = { 0.0, 360.0, 1.0 }; Revolution::Revolution() { @@ -54,14 +54,14 @@ Revolution::Revolution() 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::PropertyType(App::Prop_ReadOnly | App::Prop_Hidden), "Base"); - ADD_PROPERTY_TYPE(Axis,(Base::Vector3d(0.0,1.0,0.0)),"Revolution", App::PropertyType(App::Prop_ReadOnly | App::Prop_Hidden), "Axis"); - ADD_PROPERTY_TYPE(Angle,(360.0),"Revolution", App::Prop_None, "Angle"); - ADD_PROPERTY_TYPE(Angle2, (60.0), "Revolution", App::Prop_None, "Revolution length in 2nd direction"); + ADD_PROPERTY_TYPE(Base, (Base::Vector3d(0.0,0.0,0.0)), "Revolution", App::PropertyType(App::Prop_ReadOnly | App::Prop_Hidden), "Base"); + ADD_PROPERTY_TYPE(Axis, (Base::Vector3d(0.0,1.0,0.0)), "Revolution", App::PropertyType(App::Prop_ReadOnly | App::Prop_Hidden), "Axis"); + ADD_PROPERTY_TYPE(Angle, (360.0), "Revolution", App::Prop_None, "Angle"); + ADD_PROPERTY_TYPE(Angle2, (0.0), "Revolution", App::Prop_None, "Revolution length in 2nd direction"); ADD_PROPERTY_TYPE(UpToFace, (nullptr), "Revolution", App::Prop_None, "Face where revolution will end"); Angle.setConstraints(&floatAngle); Angle2.setConstraints(&floatAngle); - ADD_PROPERTY_TYPE(ReferenceAxis,(nullptr),"Revolution",(App::Prop_None),"Reference axis of revolution"); + ADD_PROPERTY_TYPE(ReferenceAxis, (nullptr), "Revolution", (App::Prop_None), "Reference axis of revolution"); } short Revolution::mustExecute() const @@ -82,21 +82,27 @@ App::DocumentObjectExecReturn* Revolution::execute() if (onlyHaveRefined()) { return App::DocumentObject::StdReturn; } + constexpr double maxDegree = 360.0; + auto method = methodFromString(Type.getValueAsString()); + // Validate parameters - // All angles are in radians unless explicitly stated double angleDeg = Angle.getValue(); - if (angleDeg > 360.0) { + if (angleDeg > maxDegree) { return new App::DocumentObjectExecReturn( QT_TRANSLATE_NOOP("Exception", "Angle of revolution too large")); } double angle = Base::toRadians(angleDeg); - if (angle < Precision::Angular()) { + if (angle < Precision::Angular() && method == RevolMethod::Angle) { return new App::DocumentObjectExecReturn( QT_TRANSLATE_NOOP("Exception", "Angle of revolution too small")); } double angle2 = Base::toRadians(Angle2.getValue()); + if (std::fabs(angle + angle2) < Precision::Angular() && method == RevolMethod::TwoAngles) { + return new App::DocumentObjectExecReturn( + QT_TRANSLATE_NOOP("Exception", "Angles of revolution nullify each other")); + } TopoShape sketchshape = getTopoShapeVerifiedFace(); @@ -135,10 +141,8 @@ App::DocumentObjectExecReturn* Revolution::execute() QT_TRANSLATE_NOOP("Exception", "Creating a face from sketch failed")); } - RevolMethod method = methodFromString(Type.getValueAsString()); - this->positionByPrevious(); - TopLoc_Location invObjLoc = this->getLocation().Inverted(); + auto invObjLoc = getLocation().Inverted(); pnt.Transform(invObjLoc.Transformation()); dir.Transform(invObjLoc.Transformation()); base.move(invObjLoc); @@ -166,8 +170,7 @@ App::DocumentObjectExecReturn* Revolution::execute() supportface.move(invObjLoc); - if (method == RevolMethod::ToFace || method == RevolMethod::ToFirst - || method == RevolMethod::ToLast) { + if (method == RevolMethod::ToFace || method == RevolMethod::ToFirst) { TopoShape upToFace; if (method == RevolMethod::ToFace) { getUpToFaceFromLinkSub(upToFace, UpToFace); @@ -194,7 +197,7 @@ App::DocumentObjectExecReturn* Revolution::execute() TopoDS::Face(supportface.getShape()), TopoDS::Face(upToFace.getShape()), nullptr, - Part::RevolMode::None, + Part::RevolMode::FuseWithBase, Standard_True); } catch (Standard_Failure&) { @@ -286,7 +289,7 @@ void Revolution::updateAxis() Revolution::RevolMethod Revolution::methodFromString(const std::string& methodStr) { if (methodStr == "Angle") - return RevolMethod::Dimension; + return RevolMethod::Angle; if (methodStr == "UpToLast") return RevolMethod::ToLast; if (methodStr == "ThroughAll") @@ -296,10 +299,9 @@ Revolution::RevolMethod Revolution::methodFromString(const std::string& methodSt if (methodStr == "UpToFace") return RevolMethod::ToFace; if (methodStr == "TwoAngles") - return RevolMethod::TwoDimensions; + return RevolMethod::TwoAngles; throw Base::ValueError("Revolution:: No such method"); - return RevolMethod::Dimension; } void Revolution::generateRevolution(TopoShape& revol, @@ -311,15 +313,18 @@ void Revolution::generateRevolution(TopoShape& revol, const bool reversed, RevolMethod method) { - if (method == RevolMethod::Dimension || method == RevolMethod::TwoDimensions || method == RevolMethod::ThroughAll) { + if (method == RevolMethod::Angle || method == RevolMethod::TwoAngles || method == RevolMethod::ThroughAll) { double angleTotal = angle; double angleOffset = 0.; - if (method == RevolMethod::TwoDimensions) { + if (method == RevolMethod::TwoAngles) { // Rotate the face by `angle2`/`angle` to get "second" angle angleTotal += angle2; angleOffset = angle2 * -1.0; } + else if (method == RevolMethod::ThroughAll) { + angleTotal = 2 * M_PI; + } else if (midplane) { // Rotate the face by half the angle to get Revolution symmetric to sketch plane angleOffset = -angle / 2; @@ -334,13 +339,16 @@ void Revolution::generateRevolution(TopoShape& revol, } TopoShape from = sketchshape; - if (method == RevolMethod::TwoDimensions || midplane) { + if (method == RevolMethod::TwoAngles || midplane) { gp_Trsf mov; mov.SetRotation(revolAx, angleOffset); TopLoc_Location loc(mov); from.move(loc); } + // revolve the face to a solid + // BRepPrimAPI is the only option that allows use of this shape for patterns. + // See https://forum.freecadweb.org/viewtopic.php?f=8&t=70185&p=611673#p611673. revol = from; revol = revol.makeElementRevolve(revolAx,angleTotal); revol.Tag = -getID(); @@ -381,7 +389,7 @@ void Revolution::updateProperties(RevolMethod method) bool isMidplaneEnabled = false; bool isReversedEnabled = false; bool isUpToFaceEnabled = false; - if (method == RevolMethod::Dimension) { + if (method == RevolMethod::Angle) { isAngleEnabled = true; isMidplaneEnabled = true; isReversedEnabled = !Midplane.getValue(); @@ -400,7 +408,7 @@ void Revolution::updateProperties(RevolMethod method) isReversedEnabled = true; isUpToFaceEnabled = true; } - else if (method == RevolMethod::TwoDimensions) { + else if (method == RevolMethod::TwoAngles) { isAngleEnabled = true; isAngle2Enabled = true; isReversedEnabled = true; diff --git a/src/Mod/PartDesign/App/FeatureRevolution.h b/src/Mod/PartDesign/App/FeatureRevolution.h index c6ef8336b8..95c3d64edd 100644 --- a/src/Mod/PartDesign/App/FeatureRevolution.h +++ b/src/Mod/PartDesign/App/FeatureRevolution.h @@ -69,12 +69,12 @@ public: bool suggestReversed(); enum class RevolMethod { - Dimension, + Angle, ThroughAll, ToLast = ThroughAll, ToFirst, ToFace, - TwoDimensions + TwoAngles }; protected: diff --git a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp index fdfa4f0557..1eabe7811c 100644 --- a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.cpp @@ -188,7 +188,7 @@ void TaskRevolutionParameters::setupDialog() void TaskRevolutionParameters::translateModeList(int index) { ui->changeMode->clear(); - ui->changeMode->addItem(tr("Dimension")); + ui->changeMode->addItem(tr("Angle")); if (!isGroove) { ui->changeMode->addItem(tr("To last")); } @@ -197,7 +197,7 @@ void TaskRevolutionParameters::translateModeList(int index) } ui->changeMode->addItem(tr("To first")); ui->changeMode->addItem(tr("Up to face")); - ui->changeMode->addItem(tr("Two dimensions")); + ui->changeMode->addItem(tr("Two angles")); ui->changeMode->setCurrentIndex(index); } @@ -294,7 +294,7 @@ void TaskRevolutionParameters::setCheckboxes(PartDesign::Revolution::RevolMethod bool isReversedEnabled = false; bool isFaceEditEnabled = false; - if (mode == PartDesign::Revolution::RevolMethod::Dimension) { + if (mode == PartDesign::Revolution::RevolMethod::Angle) { isRevolveAngleVisible = true; ui->revolveAngle->selectNumber(); QMetaObject::invokeMethod(ui->revolveAngle, "setFocus", Qt::QueuedConnection); @@ -320,7 +320,7 @@ void TaskRevolutionParameters::setCheckboxes(PartDesign::Revolution::RevolMethod ui->buttonFace->setChecked(true); } } - else if (mode == PartDesign::Revolution::RevolMethod::TwoDimensions) { + else if (mode == PartDesign::Revolution::RevolMethod::TwoAngles) { isRevolveAngleVisible = true; isRevolveAngle2Visible = true; isReversedEnabled = true; @@ -624,7 +624,7 @@ void TaskRevolutionParameters::onModeChanged(int index) : &(getObject()->Type); switch (static_cast(index)) { - case PartDesign::Revolution::RevolMethod::Dimension: + case PartDesign::Revolution::RevolMethod::Angle: propEnum->setValue("Angle"); break; case PartDesign::Revolution::RevolMethod::ToLast: @@ -636,7 +636,7 @@ void TaskRevolutionParameters::onModeChanged(int index) case PartDesign::Revolution::RevolMethod::ToFace: propEnum->setValue("UpToFace"); break; - case PartDesign::Revolution::RevolMethod::TwoDimensions: + case PartDesign::Revolution::RevolMethod::TwoAngles: propEnum->setValue("TwoAngles"); break; } @@ -809,12 +809,12 @@ void TaskRevolutionParameters::setGizmoVisibility() auto type = static_cast(ui->changeMode->currentIndex()); switch (type) { - case PartDesign::Revolution::RevolMethod::Dimension: + case PartDesign::Revolution::RevolMethod::Angle: gizmoContainer->visible = true; rotationGizmo->setVisibility(true); rotationGizmo2->setVisibility(false); break; - case PartDesign::Revolution::RevolMethod::TwoDimensions: + case PartDesign::Revolution::RevolMethod::TwoAngles: gizmoContainer->visible = true; rotationGizmo->setVisibility(true); rotationGizmo2->setVisibility(true); diff --git a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.ui b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.ui index e858efa474..903e59de14 100644 --- a/src/Mod/PartDesign/Gui/TaskRevolutionParameters.ui +++ b/src/Mod/PartDesign/Gui/TaskRevolutionParameters.ui @@ -27,7 +27,7 @@ - Dimension + Angle @@ -139,7 +139,7 @@ 10.000000000000000 - 60.000000000000000 + 0.000000000000000