Skip to content

Commit

Permalink
Part/PartDesign: support inner taper angle for extrude/pad/pocket
Browse files Browse the repository at this point in the history
  • Loading branch information
realthunder committed Nov 27, 2020
1 parent 123c428 commit f4fbc8c
Show file tree
Hide file tree
Showing 12 changed files with 310 additions and 44 deletions.
72 changes: 48 additions & 24 deletions src/Mod/Part/App/FeatureExtrusion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@
# include <TopExp_Explorer.hxx>
# include <TopTools_IndexedMapOfShape.hxx>
# include <BRepLib_FindSurface.hxx>
# include <BRepTools.hxx>
#endif


#include "TopoShapeOpCode.h"
#include "FeatureExtrusion.h"
#include <Base/Tools.h>
#include <Base/Exception.h>
#include <App/Application.h>
#include <App/Document.h>
#include "Part2DObject.h"

Expand Down Expand Up @@ -79,6 +81,8 @@ Extrusion::Extrusion()
ADD_PROPERTY_TYPE(Symmetric,(false), "Extrude", App::Prop_None, "If true, extrusion is done in both directions to a total of LengthFwd. LengthRev is ignored.");
ADD_PROPERTY_TYPE(TaperAngle,(0.0), "Extrude", App::Prop_None, "Sets the angle of slope (draft) to apply to the sides. The angle is for outward taper; negative value yields inward tapering.");
ADD_PROPERTY_TYPE(TaperAngleRev,(0.0), "Extrude", App::Prop_None, "Taper angle of reverse part of extrusion.");
ADD_PROPERTY_TYPE(InnerTaperAngle,(0.0), "Extrude", App::Prop_None, "Taper angle of inner holes.");
ADD_PROPERTY_TYPE(InnerTaperAngleRev,(0.0), "Extrude", App::Prop_None, "Taper angle of the reverse part for inner holes.");
ADD_PROPERTY_TYPE(FaceMakerClass,("Part::FaceMakerExtrusion"), "Extrude", App::Prop_None, "If Solid is true, this sets the facemaker class to use when converting wires to faces. Otherwise, ignored."); //default for old documents. See setupObject for default for new extrusions.
}

Expand Down Expand Up @@ -186,6 +190,12 @@ Extrusion::ExtrusionParameters Extrusion::computeFinalParameters()
result.taperAngleRev = this->TaperAngleRev.getValue() * M_PI / 180.0;
if (fabs(result.taperAngleRev) > M_PI * 0.5 - Precision::Angular() )
throw Base::ValueError("Magnitude of taper angle matches or exceeds 90 degrees. That is too much.");
result.innerTaperAngleFwd = this->InnerTaperAngle.getValue() * M_PI / 180.0;
if (fabs(result.innerTaperAngleFwd) > M_PI * 0.5 - Precision::Angular() )
throw Base::ValueError("Magnitude of inner taper angle matches or exceeds 90 degrees. That is too much.");
result.innerTaperAngleRev = this->InnerTaperAngleRev.getValue() * M_PI / 180.0;
if (fabs(result.innerTaperAngleRev) > M_PI * 0.5 - Precision::Angular() )
throw Base::ValueError("Magnitude of inner taper angle matches or exceeds 90 degrees. That is too much.");

result.faceMakerClass = this->FaceMakerClass.getValue();

Expand Down Expand Up @@ -325,46 +335,60 @@ void Extrusion::makeDraft(const ExtrusionParameters& params, const TopoShape& _s
bool bRev = fabs(params.lengthRev) > Precision::Confusion();
bool bMid = !bFwd || !bRev || params.lengthFwd*params.lengthRev > 0.0; //include the source shape as loft section?

const auto &shape = _shape.getShape();
TopoDS_Shape shape = _shape.getShape();
TopoShape sourceWire;
if (shape.IsNull())
Standard_Failure::Raise("Not a valid shape");
if (shape.ShapeType() == TopAbs_WIRE || shape.ShapeType() == TopAbs_FACE) {
if (shape.ShapeType() == TopAbs_WIRE) {
ShapeFix_Wire aFix;
aFix.Load(TopoDS::Wire(shape));
aFix.FixReorder();
aFix.FixConnected();
aFix.FixClosed();
sourceWire.setShape(aFix.Wire());
} else {
TopoDS_Wire outerWire = ShapeAnalysis::OuterWire(TopoDS::Face(shape));
sourceWire.setShape(outerWire);

if (shape.ShapeType() == TopAbs_FACE) {
shape = BRepTools::OuterWire(TopoDS::Face(shape));
if (shape.IsNull())
Standard_Failure::Raise("No outer wire found");
std::vector<TopoShape> wires;
TopoShape outerWire = _shape.getOuterWire(&wires);
if (outerWire.isNull())
Standard_Failure::Raise("Missing outer wire");
if (wires.size()) {
unsigned pos = drafts.size();
makeDraft(params, outerWire, drafts, hasher);
if (drafts.size() != pos+1)
Standard_Failure::Raise("Failed to make drafted extrusion");
std::vector<TopoShape> inner;
TopoShape innerWires(0, hasher);
innerWires.makECompound(wires,"",false);
ExtrusionParameters copy = params;
copy.taperAngleFwd = params.innerTaperAngleFwd;
copy.taperAngleRev = params.innerTaperAngleRev;
makeDraft(copy, innerWires, inner, hasher);
if (inner.empty())
Standard_Failure::Raise("Failed to make drafted extrusion with inner hole");
inner.insert(inner.begin(), drafts.back());
drafts.back().makECut(inner);
return;
}
}

if (shape.ShapeType() == TopAbs_WIRE) {
ShapeFix_Wire aFix;
aFix.Load(TopoDS::Wire(shape));
aFix.FixReorder();
aFix.FixConnected();
aFix.FixClosed();
sourceWire.setShape(aFix.Wire());
sourceWire.Tag = _shape.Tag;
sourceWire.mapSubElement(_shape);
}
else if (shape.ShapeType() == TopAbs_COMPOUND) {
for(auto &s : _shape.getSubTopoShapes()) {
for(auto &s : _shape.getSubTopoShapes())
makeDraft(params, s, drafts, hasher);
}
}
else {
Standard_Failure::Raise("Only a wire or a face is supported");
}

if (!sourceWire.isNull()) {
std::vector<TopoShape> list_of_sections;

// if the wire consists of a single edge which has applied a placement
// then this placement must be reset because otherwise the
// BRepOffsetAPI_MakeOffset shows weird behaviour by applying the placement
// twice on the output shape
//
// count all edges of the wire
int numEdges = sourceWire.countSubShapes(TopAbs_EDGE);

auto makeOffset = [&numEdges,&sourceWire](const gp_Vec& translation, double offset) -> TopoShape {
auto makeOffset = [&sourceWire](const gp_Vec& translation, double offset) -> TopoShape {
gp_Trsf mat;
mat.SetTranslation(translation);
TopoShape offsetShape(sourceWire.makETransform(mat,"RV"));
Expand Down
16 changes: 14 additions & 2 deletions src/Mod/Part/App/FeatureExtrusion.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,10 @@ class PartExport Extrusion : public Part::Feature
App::PropertyBool Symmetric;
App::PropertyAngle TaperAngle;
App::PropertyAngle TaperAngleRev;
App::PropertyAngle InnerTaperAngle;
App::PropertyAngle InnerTaperAngleRev;
App::PropertyString FaceMakerClass;


/**
* @brief The ExtrusionParameters struct is supposed to be filled with final
* extrusion parameters, after resolving links, applying mode logic,
Expand All @@ -65,10 +66,21 @@ class PartExport Extrusion : public Part::Feature
double lengthFwd;
double lengthRev;
bool solid;
bool innertaper;
double taperAngleFwd; //in radians
double taperAngleRev;
double innerTaperAngleFwd; //in radians
double innerTaperAngleRev;
std::string faceMakerClass;
ExtrusionParameters(): lengthFwd(0), lengthRev(0), solid(false), taperAngleFwd(0), taperAngleRev(0) {}// constructor to keep garbage out
ExtrusionParameters()
: lengthFwd(0)
, lengthRev(0)
, solid(false)
, taperAngleFwd(0)
, taperAngleRev(0)
, innerTaperAngleFwd(0)
, innerTaperAngleRev(0)
{}// constructor to keep garbage out
};

/** @name methods override feature */
Expand Down
20 changes: 15 additions & 5 deletions src/Mod/PartDesign/App/FeaturePad.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ Pad::Pad()

ADD_PROPERTY_TYPE(TaperAngle,(0.0), "Pad", App::Prop_None, "Sets the angle of slope (draft) to apply to the sides. The angle is for outward taper; negative value yields inward tapering.");
ADD_PROPERTY_TYPE(TaperAngleRev,(0.0), "Pad", App::Prop_None, "Taper angle of reverse part of padding.");
ADD_PROPERTY_TYPE(InnerTaperAngle,(0.0), "Pad", App::Prop_None, "Taper angle of inner holes.");
ADD_PROPERTY_TYPE(InnerTaperAngleRev,(0.0), "Pad", App::Prop_None, "Taper angle of the reverse part for inner holes.");
}

short Pad::mustExecute() const
Expand Down Expand Up @@ -351,8 +353,11 @@ App::DocumentObjectExecReturn *Pad::_execute(bool makeface, bool fuse)
} else {
Part::Extrusion::ExtrusionParameters params;
params.dir = dir;
params.solid = true;
params.taperAngleFwd = this->TaperAngle.getValue() * M_PI / 180.0;
params.taperAngleRev = this->TaperAngleRev.getValue() * M_PI / 180.0;
params.innerTaperAngleFwd = this->InnerTaperAngle.getValue() * M_PI / 180.0;
params.innerTaperAngleRev = this->InnerTaperAngleRev.getValue() * M_PI / 180.0;
if (L2 == 0.0 && Midplane.getValue()) {
params.lengthFwd = L/2;
params.lengthRev = L/2;
Expand All @@ -362,13 +367,18 @@ App::DocumentObjectExecReturn *Pad::_execute(bool makeface, bool fuse)
params.lengthFwd = L;
params.lengthRev = L2;
}
params.solid = true;
if (std::fabs(params.taperAngleFwd) >= Precision::Angular() ||
std::fabs(params.taperAngleRev) >= Precision::Angular() ) {
if (std::fabs(params.taperAngleFwd) >= Precision::Angular()
|| std::fabs(params.taperAngleRev) >= Precision::Angular()
|| std::fabs(params.innerTaperAngleFwd) >= Precision::Angular()
|| std::fabs(params.innerTaperAngleRev) >= Precision::Angular()) {
if (fabs(params.taperAngleFwd) > M_PI * 0.5 - Precision::Angular()
|| fabs(params.taperAngleRev) > M_PI * 0.5 - Precision::Angular())
return new App::DocumentObjectExecReturn("Magnitude of taper angle matches or exceeds 90 degrees. That is too much.");

return new App::DocumentObjectExecReturn(
"Magnitude of taper angle matches or exceeds 90 degrees");
if (fabs(params.innerTaperAngleFwd) > M_PI * 0.5 - Precision::Angular()
|| fabs(params.innerTaperAngleRev) > M_PI * 0.5 - Precision::Angular())
return new App::DocumentObjectExecReturn(
"Magnitude of inner taper angle matches or exceeds 90 degrees");
if (Reversed.getValue())
params.dir.Reverse();
std::vector<TopoShape> drafts;
Expand Down
2 changes: 2 additions & 0 deletions src/Mod/PartDesign/App/FeaturePad.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class PartDesignExport Pad : public ProfileBased
App::PropertyLength Offset;
App::PropertyAngle TaperAngle;
App::PropertyAngle TaperAngleRev;
App::PropertyAngle InnerTaperAngle;
App::PropertyAngle InnerTaperAngleRev;

/** @name methods override feature */
//@{
Expand Down
20 changes: 15 additions & 5 deletions src/Mod/PartDesign/App/FeaturePocket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ Pocket::Pocket()

ADD_PROPERTY_TYPE(TaperAngle,(0.0), "Pocket", App::Prop_None, "Sets the angle of slope (draft) to apply to the sides. The angle is for outward taper; negative value yields inward tapering.");
ADD_PROPERTY_TYPE(TaperAngleRev,(0.0), "Pocket", App::Prop_None, "Taper angle of reverse part of pocketing.");
ADD_PROPERTY_TYPE(InnerTaperAngle,(0.0), "Pocket", App::Prop_None, "Taper angle of inner holes.");
ADD_PROPERTY_TYPE(InnerTaperAngleRev,(0.0), "Pocket", App::Prop_None, "Taper angle of the reverse part for inner holes.");
}

short Pocket::mustExecute() const
Expand Down Expand Up @@ -218,8 +220,11 @@ App::DocumentObjectExecReturn *Pocket::execute(void)

Part::Extrusion::ExtrusionParameters params;
params.dir = dir;
params.solid = true;
params.taperAngleFwd = this->TaperAngle.getValue() * M_PI / 180.0;
params.taperAngleRev = this->TaperAngleRev.getValue() * M_PI / 180.0;
params.innerTaperAngleFwd = this->InnerTaperAngle.getValue() * M_PI / 180.0;
params.innerTaperAngleRev = this->InnerTaperAngleRev.getValue() * M_PI / 180.0;
if (L2 == 0.0 && Midplane.getValue()) {
params.lengthFwd = L/2;
params.lengthRev = L/2;
Expand All @@ -229,13 +234,18 @@ App::DocumentObjectExecReturn *Pocket::execute(void)
params.lengthFwd = L;
params.lengthRev = L2;
}
params.solid = true;
if (std::fabs(params.taperAngleFwd) >= Precision::Angular() ||
std::fabs(params.taperAngleRev) >= Precision::Angular() ) {
if (std::fabs(params.taperAngleFwd) >= Precision::Angular()
|| std::fabs(params.taperAngleRev) >= Precision::Angular()
|| std::fabs(params.innerTaperAngleFwd) >= Precision::Angular()
|| std::fabs(params.innerTaperAngleRev) >= Precision::Angular()) {
if (fabs(params.taperAngleFwd) > M_PI * 0.5 - Precision::Angular()
|| fabs(params.taperAngleRev) > M_PI * 0.5 - Precision::Angular())
return new App::DocumentObjectExecReturn("Magnitude of taper angle matches or exceeds 90 degrees. That is too much.");

return new App::DocumentObjectExecReturn(
"Magnitude of taper angle matches or exceeds 90 degrees");
if (fabs(params.innerTaperAngleFwd) > M_PI * 0.5 - Precision::Angular()
|| fabs(params.innerTaperAngleRev) > M_PI * 0.5 - Precision::Angular())
return new App::DocumentObjectExecReturn(
"Magnitude of inner taper angle matches or exceeds 90 degrees");
if (Reversed.getValue())
params.dir.Reverse();
std::vector<TopoShape> drafts;
Expand Down
6 changes: 4 additions & 2 deletions src/Mod/PartDesign/App/FeaturePocket.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ class PartDesignExport Pocket : public ProfileBased
App::PropertyLength Length;
App::PropertyLength Length2;
App::PropertyLength Offset;
App::PropertyAngle TaperAngle;
App::PropertyAngle TaperAngleRev;
App::PropertyAngle TaperAngle;
App::PropertyAngle TaperAngleRev;
App::PropertyAngle InnerTaperAngle;
App::PropertyAngle InnerTaperAngleRev;

/** @name methods override feature */
//@{
Expand Down
38 changes: 38 additions & 0 deletions src/Mod/PartDesign/Gui/TaskPadParameters.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,16 @@ void TaskPadParameters::setupUI(bool newObj)
ui->offsetEdit->setParamGrpPath(QByteArray("User parameter:BaseApp/History/PadOffset"));
ui->taperAngleEdit->setParamGrpPath(QByteArray("User parameter:BaseApp/History/TaperAngle"));
ui->taperAngleEdit2->setParamGrpPath(QByteArray("User parameter:BaseApp/History/TaperAngle2"));
ui->innerTaperAngleEdit->setParamGrpPath(QByteArray("User parameter:BaseApp/History/InnerTaperAngle"));
ui->innerTaperAngleEdit2->setParamGrpPath(QByteArray("User parameter:BaseApp/History/InnerTaperAngle2"));

// Bind input fields to properties
ui->lengthEdit->bind(pcPad->Length);
ui->lengthEdit2->bind(pcPad->Length2);
ui->taperAngleEdit->bind(pcPad->TaperAngle);
ui->taperAngleEdit2->bind(pcPad->TaperAngleRev);
ui->innerTaperAngleEdit->bind(pcPad->InnerTaperAngle);
ui->innerTaperAngleEdit2->bind(pcPad->InnerTaperAngleRev);

ui->XDirectionEdit->bind(App::ObjectIdentifier::parse(pcPad, std::string("Direction.x")));
ui->YDirectionEdit->bind(App::ObjectIdentifier::parse(pcPad, std::string("Direction.y")));
Expand Down Expand Up @@ -136,6 +140,10 @@ void TaskPadParameters::setupUI(bool newObj)
this, SLOT(onAngleChanged(double)));
connect(ui->taperAngleEdit2, SIGNAL(valueChanged(double)),
this, SLOT(onAngle2Changed(double)));
connect(ui->innerTaperAngleEdit, SIGNAL(valueChanged(double)),
this, SLOT(onInnerAngleChanged(double)));
connect(ui->innerTaperAngleEdit2, SIGNAL(valueChanged(double)),
this, SLOT(onInnerAngle2Changed(double)));
connect(ui->groupBoxDirection, SIGNAL(toggled(bool)),
this, SLOT(onGBDirectionChanged(bool)));
connect(ui->XDirectionEdit, SIGNAL(valueChanged(double)),
Expand Down Expand Up @@ -172,6 +180,10 @@ void TaskPadParameters::setupUI(bool newObj)
ui->taperAngleEdit->selectNumber();
ui->taperAngleEdit2->setToLastUsedValue();
ui->taperAngleEdit2->selectNumber();
ui->innerTaperAngleEdit->setToLastUsedValue();
ui->innerTaperAngleEdit->selectNumber();
ui->innerTaperAngleEdit2->setToLastUsedValue();
ui->innerTaperAngleEdit2->selectNumber();
}
}

Expand All @@ -194,6 +206,8 @@ void TaskPadParameters::refresh()
int index = pcPad->Type.getValue(); // must extract value here, clear() kills it!
double angle = pcPad->TaperAngle.getValue();
double angle2 = pcPad->TaperAngleRev.getValue();
double innerAngle = pcPad->InnerTaperAngle.getValue();
double innerAngle2 = pcPad->InnerTaperAngleRev.getValue();

// Temporarily prevent unnecessary feature recomputes
for (QWidget* child : proxy->findChildren<QWidget*>())
Expand All @@ -209,6 +223,8 @@ void TaskPadParameters::refresh()
ui->offsetEdit->setValue(off);
ui->taperAngleEdit->setValue(angle);
ui->taperAngleEdit2->setValue(angle2);
ui->innerTaperAngleEdit->setValue(innerAngle);
ui->innerTaperAngleEdit2->setValue(innerAngle2);

ui->checkBoxMidplane->setChecked(midplane);
// According to bug #0000521 the reversed option
Expand Down Expand Up @@ -311,6 +327,12 @@ void TaskPadParameters::updateUI(int index)
ui->taperAngleEdit2->setVisible( angleVisible );
ui->taperAngleEdit2->setEnabled( angleVisible );
ui->labelTaperAngle2->setVisible( angleVisible );
ui->innerTaperAngleEdit->setVisible( angleVisible );
ui->innerTaperAngleEdit->setEnabled( angleVisible );
ui->labelInnerTaperAngle->setVisible( angleVisible );
ui->innerTaperAngleEdit2->setVisible( angleVisible );
ui->innerTaperAngleEdit2->setEnabled( angleVisible );
ui->labelInnerTaperAngle2->setVisible( angleVisible );

ui->buttonFace->setEnabled( isFaceEditEnabled );
ui->lineFaceName->setEnabled( isFaceEditEnabled );
Expand Down Expand Up @@ -375,6 +397,20 @@ void TaskPadParameters::onAngle2Changed(double angle)
recomputeFeature();
}

void TaskPadParameters::onInnerAngleChanged(double angle)
{
PartDesign::Pad* pcPad = static_cast<PartDesign::Pad*>(vp->getObject());
pcPad->InnerTaperAngle.setValue(angle);
recomputeFeature();
}

void TaskPadParameters::onInnerAngle2Changed(double angle)
{
PartDesign::Pad* pcPad = static_cast<PartDesign::Pad*>(vp->getObject());
pcPad->InnerTaperAngleRev.setValue(angle);
recomputeFeature();
}

void TaskPadParameters::onGBDirectionChanged(bool on)
{
PartDesign::Pad* pcPad = static_cast<PartDesign::Pad*>(vp->getObject());
Expand Down Expand Up @@ -632,6 +668,8 @@ void TaskPadParameters::saveHistory(void)
ui->offsetEdit->pushToHistory();
ui->taperAngleEdit->pushToHistory();
ui->taperAngleEdit2->pushToHistory();
ui->innerTaperAngleEdit->pushToHistory();
ui->innerTaperAngleEdit2->pushToHistory();

TaskSketchBasedParameters::saveHistory();
}
Expand Down
2 changes: 2 additions & 0 deletions src/Mod/PartDesign/Gui/TaskPadParameters.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,8 @@ private Q_SLOTS:
void onModeChanged(int);
void onAngleChanged(double);
void onAngle2Changed(double);
void onInnerAngleChanged(double);
void onInnerAngle2Changed(double);

protected:
void changeEvent(QEvent *e) override;
Expand Down
Loading

0 comments on commit f4fbc8c

Please sign in to comment.