PD: Improve revolution feature
* Allow a minimum angle of 0.0 as this is needed in 'Two Angles' mode * Set the default value of Angle2 to 0.0 * Check for valid input in 'Angle' and 'Two Angles' mode * Replace the confusing enum labels 'Dimension' and 'TwoDimensions'
This commit is contained in:
@@ -30,9 +30,7 @@
|
||||
# include <TopoDS.hxx>
|
||||
|
||||
|
||||
#include <Base/Axis.h>
|
||||
#include <Base/Exception.h>
|
||||
#include <Base/Placement.h>
|
||||
#include <Base/Tools.h>
|
||||
|
||||
#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<double>(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<double>(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;
|
||||
|
||||
@@ -69,12 +69,12 @@ public:
|
||||
bool suggestReversed();
|
||||
|
||||
enum class RevolMethod {
|
||||
Dimension,
|
||||
Angle,
|
||||
ThroughAll,
|
||||
ToLast = ThroughAll,
|
||||
ToFirst,
|
||||
ToFace,
|
||||
TwoDimensions
|
||||
TwoAngles
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
@@ -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<PartDesign::Revolution>()->Type);
|
||||
|
||||
switch (static_cast<PartDesign::Revolution::RevolMethod>(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<PartDesign::Revolution::RevolMethod>(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);
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
<widget class="QComboBox" name="changeMode">
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Dimension</string>
|
||||
<string notr="true">Angle</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
@@ -139,7 +139,7 @@
|
||||
<double>10.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>60.000000000000000</double>
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
||||
Reference in New Issue
Block a user