[PD] allow to pad in any direction

It saves a lot of work if one can directly pad in any direction and OCC allows this.

This PR adds the possibility to define a custom vector for the padding direction.
This commit is contained in:
donovaly
2020-08-09 16:23:07 +02:00
committed by wmayer
parent 6bbab49723
commit 91ef59fdbe
6 changed files with 324 additions and 39 deletions

View File

@@ -25,37 +25,35 @@
#ifndef _PreComp_
# include <BRep_Builder.hxx>
# include <BRep_Tool.hxx>
# include <BRepBndLib.hxx>
# include <BRepFeat_MakePrism.hxx>
# include <BRepBuilderAPI_MakeFace.hxx>
# include <Geom_Surface.hxx>
# include <TopoDS.hxx>
# include <TopoDS_Solid.hxx>
# include <TopoDS_Face.hxx>
# include <TopoDS_Wire.hxx>
# include <TopoDS_Compound.hxx>
# include <TopExp_Explorer.hxx>
# include <BRepAlgoAPI_Fuse.hxx>
# include <Precision.hxx>
# include <BRepPrimAPI_MakeHalfSpace.hxx>
# include <BRepAlgoAPI_Common.hxx>
# include <BRepAlgoAPI_Fuse.hxx>
# include <BRepAdaptor_Surface.hxx>
# include <gp_Pln.hxx>
# include <GeomAPI_ProjectPointOnSurf.hxx>
# include <BRepBndLib.hxx>
# include <BRepBuilderAPI_MakeFace.hxx>
# include <BRepFeat_MakePrism.hxx>
# include <BRepLProp_SLProps.hxx>
# include <BRepPrimAPI_MakeHalfSpace.hxx>
# include <Geom_Surface.hxx>
# include <GeomAPI_ProjectPointOnSurf.hxx>
# include <GeomLib_IsPlanarSurface.hxx>
# include <gp_Pln.hxx>
# include <Precision.hxx>
# include <TopoDS.hxx>
# include <TopoDS_Compound.hxx>
# include <TopoDS_Face.hxx>
# include <TopoDS_Solid.hxx>
# include <TopoDS_Wire.hxx>
# include <TopExp_Explorer.hxx>
#endif
#include <App/Document.h>
#include <Base/Console.h>
#include <Base/Exception.h>
#include <Base/Placement.h>
#include <Base/Console.h>
#include <Base/Reader.h>
#include <App/Document.h>
//#include "Body.h"
#include "FeaturePad.h"
using namespace PartDesign;
const char* Pad::TypeEnums[]= {"Length","UpToLast","UpToFirst","UpToFace","TwoLengths",NULL};
@@ -66,14 +64,16 @@ Pad::Pad()
{
addSubType = FeatureAddSub::Additive;
ADD_PROPERTY_TYPE(Type,(0L),"Pad",App::Prop_None,"Pad type");
ADD_PROPERTY_TYPE(Type, (0L), "Pad", App::Prop_None, "Pad type");
Type.setEnums(TypeEnums);
ADD_PROPERTY_TYPE(Length,(100.0),"Pad",App::Prop_None,"Pad length");
ADD_PROPERTY_TYPE(Length2,(100.0),"Pad",App::Prop_None,"Second Pad length");
ADD_PROPERTY_TYPE(UpToFace,(0),"Pad",App::Prop_None,"Face where pad will end");
ADD_PROPERTY_TYPE(Offset,(0.0),"Pad",App::Prop_None,"Offset from face in which pad will end");
ADD_PROPERTY_TYPE(Length, (100.0), "Pad", App::Prop_None,"Pad length");
ADD_PROPERTY_TYPE(Length2, (100.0), "Pad", App::Prop_None,"Second Pad length");
ADD_PROPERTY_TYPE(UseCustomVector, (0), "Pad", App::Prop_None, "Use custom vector for pad direction");
ADD_PROPERTY_TYPE(Direction, (Base::Vector3d(1.0, 1.0, 1.0)), "Pad", App::Prop_None, "Pad direction vector");
ADD_PROPERTY_TYPE(UpToFace, (0), "Pad", App::Prop_None, "Face where pad will end");
ADD_PROPERTY_TYPE(Offset, (0.0), "Pad", App::Prop_None, "Offset from face in which pad will end");
static const App::PropertyQuantityConstraint::Constraints signedLengthConstraint = {-DBL_MAX, DBL_MAX, 1.0};
Offset.setConstraints ( &signedLengthConstraint );
Offset.setConstraints(&signedLengthConstraint);
}
short Pad::mustExecute() const
@@ -82,6 +82,8 @@ short Pad::mustExecute() const
Type.isTouched() ||
Length.isTouched() ||
Length2.isTouched() ||
UseCustomVector.isTouched() ||
Direction.isTouched() ||
Offset.isTouched() ||
UpToFace.isTouched())
return 1;
@@ -115,10 +117,10 @@ App::DocumentObjectExecReturn *Pad::execute(void)
base = TopoDS_Shape();
}
// get the Sketch plane
Base::Placement SketchPos = obj->Placement.getValue();
Base::Vector3d SketchVector = getProfileNormal();
Base::Placement SketchPos = obj->Placement.getValue();
// get the normal vector of the sketch
Base::Vector3d SketchVector = getProfileNormal();
try {
this->positionByPrevious();
@@ -126,7 +128,45 @@ App::DocumentObjectExecReturn *Pad::execute(void)
base.Move(invObjLoc);
gp_Dir dir(SketchVector.x,SketchVector.y,SketchVector.z);
Base::Vector3d paddingDirection;
// use the given vector if necessary
if (!UseCustomVector.getValue()) {
paddingDirection = SketchVector;
}
else {
// if null vector, use SketchVector
if ( (fabs(Direction.getValue().x) < Precision::Confusion())
&& (fabs(Direction.getValue().y) < Precision::Confusion())
&& (fabs(Direction.getValue().z) < Precision::Confusion()) )
{
Direction.setValue(SketchVector);
}
paddingDirection = Direction.getValue();
}
// create vector in padding direction with length 1
gp_Dir dir(paddingDirection.x, paddingDirection.y, paddingDirection.z);
// The length of a gp_Dir is 1 so the resulting pad would have
// the length L in the direction of dir. But we want to have its height in the
// direction of the normal vector.
// Therefore we must multiply L by the factor that is necessary
// to make dir as long that its projection to the SketchVector
// equals the SketchVector.
// This is the scalar product of both vectors.
// Since the pad length cannot be negative, the factor must not be negative.
double factor = fabs(dir * gp_Dir(SketchVector.x, SketchVector.y, SketchVector.z));
// factor would be zero if vectors are orthogonal
if (factor < Precision::Confusion())
return new App::DocumentObjectExecReturn("Pad: Creation failed because direction is orthogonal to sketch's normal vector");
// perform the length correction
L = L / factor;
dir.Transform(invObjLoc.Transformation());
if (sketchshape.IsNull())

View File

@@ -40,10 +40,12 @@ class PartDesignExport Pad : public ProfileBased
public:
Pad();
App::PropertyEnumeration Type;
App::PropertyLength Length;
App::PropertyLength Length2;
App::PropertyLength Offset;
App::PropertyEnumeration Type;
App::PropertyLength Length;
App::PropertyLength Length2;
App::PropertyBool UseCustomVector;
App::PropertyVector Direction;
App::PropertyLength Offset;
/** @name methods override feature */
//@{

View File

@@ -579,7 +579,7 @@ void ProfileBased::generatePrism(TopoDS_Shape& prism,
// Its better not to use BRepFeat_MakePrism here even if we have a support because the
// resulting shape creates problems with Pocket
BRepPrimAPI_MakePrism PrismMaker(from, Ltotal*gp_Vec(dir), 0,1); // finite prism
BRepPrimAPI_MakePrism PrismMaker(from, Ltotal*gp_Vec(dir), 0, 1); // finite prism
if (!PrismMaker.IsDone())
throw Base::RuntimeError("ProfileBased: Length: Could not extrude the sketch!");
prism = PrismMaker.Shape();

View File

@@ -34,6 +34,7 @@
#include "TaskPadParameters.h"
#include <App/Application.h>
#include <App/Document.h>
#include <Base/UnitsApi.h>
#include <Gui/Application.h>
#include <Gui/Document.h>
#include <Gui/BitmapFactory.h>
@@ -74,6 +75,10 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView, QWidget *parent,
PartDesign::Pad* pcPad = static_cast<PartDesign::Pad*>(vp->getObject());
Base::Quantity l = pcPad->Length.getQuantityValue();
Base::Quantity l2 = pcPad->Length2.getQuantityValue();
bool useCustom = pcPad->UseCustomVector.getValue();
double xs = pcPad->Direction.getValue().x;
double ys = pcPad->Direction.getValue().y;
double zs = pcPad->Direction.getValue().z;
Base::Quantity off = pcPad->Offset.getQuantityValue();
bool midplane = pcPad->Midplane.getValue();
bool reversed = pcPad->Reversed.getValue();
@@ -91,17 +96,32 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView, QWidget *parent,
// Fill data into dialog elements
ui->lengthEdit->setValue(l);
ui->lengthEdit2->setValue(l2);
ui->groupBoxDirection->setChecked(useCustom);
ui->XDirectionEdit->setValue(xs);
ui->YDirectionEdit->setValue(ys);
ui->ZDirectionEdit->setValue(zs);
ui->offsetEdit->setValue(off);
// Bind input fields to properties
ui->lengthEdit->bind(pcPad->Length);
ui->lengthEdit2->bind(pcPad->Length2);
ui->XDirectionEdit->bind(App::ObjectIdentifier::parse(pcPad, std::string("Direction.x")));
ui->YDirectionEdit->bind(App::ObjectIdentifier::parse(pcPad, std::string("Direction.y")));
ui->ZDirectionEdit->bind(App::ObjectIdentifier::parse(pcPad, std::string("Direction.z")));
ui->offsetEdit->bind(pcPad->Offset);
ui->checkBoxMidplane->setChecked(midplane);
// According to bug #0000521 the reversed option
// shouldn't be de-activated if the pad has a support face
ui->checkBoxReversed->setChecked(reversed);
// set decimals for the direction edits
int UserDecimals = Base::UnitsApi::getDecimals();
ui->XDirectionEdit->setDecimals(UserDecimals);
ui->YDirectionEdit->setDecimals(UserDecimals);
ui->ZDirectionEdit->setDecimals(UserDecimals);
// Set object labels
if (obj && PartDesign::Feature::isDatum(obj)) {
ui->lineFaceName->setText(QString::fromUtf8(obj->Label.getValue()));
@@ -135,6 +155,14 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView, QWidget *parent,
this, SLOT(onLengthChanged(double)));
connect(ui->lengthEdit2, SIGNAL(valueChanged(double)),
this, SLOT(onLength2Changed(double)));
connect(ui->groupBoxDirection, SIGNAL(toggled(bool)),
this, SLOT(onGBDirectionChanged(bool)));
connect(ui->XDirectionEdit, SIGNAL(valueChanged(double)),
this, SLOT(onXDirectionEditChanged(double)));
connect(ui->YDirectionEdit, SIGNAL(valueChanged(double)),
this, SLOT(onYDirectionEditChanged(double)));
connect(ui->ZDirectionEdit, SIGNAL(valueChanged(double)),
this, SLOT(onZDirectionEditChanged(double)));
connect(ui->offsetEdit, SIGNAL(valueChanged(double)),
this, SLOT(onOffsetChanged(double)));
connect(ui->checkBoxMidplane, SIGNAL(toggled(bool)),
@@ -168,6 +196,7 @@ TaskPadParameters::TaskPadParameters(ViewProviderPad *PadView, QWidget *parent,
void TaskPadParameters::updateUI(int index)
{
// disable/hide everything unless we are sure we don't need it
// exception: the direction parameters are in any case visible
bool isLengthEditVisable = false;
bool isLengthEdit2Visable = false;
bool isOffsetEditVisable = false;
@@ -272,6 +301,49 @@ void TaskPadParameters::onLength2Changed(double len)
recomputeFeature();
}
void TaskPadParameters::onGBDirectionChanged(bool on)
{
PartDesign::Pad* pcPad = static_cast<PartDesign::Pad*>(vp->getObject());
pcPad->UseCustomVector.setValue(on);
recomputeFeature();
}
void TaskPadParameters::onXDirectionEditChanged(double len)
{
PartDesign::Pad* pcPad = static_cast<PartDesign::Pad*>(vp->getObject());
pcPad->Direction.setValue(len, pcPad->Direction.getValue().y, pcPad->Direction.getValue().z);
recomputeFeature();
// checking for case of a null vector is done in FeaturePad.cpp
// if there was a null vector, the normal vector of the sketch is used.
// therefore the vector component edits must be updated
updateDirectionEdits();
}
void TaskPadParameters::onYDirectionEditChanged(double len)
{
PartDesign::Pad* pcPad = static_cast<PartDesign::Pad*>(vp->getObject());
pcPad->Direction.setValue(pcPad->Direction.getValue().x, len, pcPad->Direction.getValue().z);
recomputeFeature();
updateDirectionEdits();
}
void TaskPadParameters::onZDirectionEditChanged(double len)
{
PartDesign::Pad* pcPad = static_cast<PartDesign::Pad*>(vp->getObject());
pcPad->Direction.setValue(pcPad->Direction.getValue().x, pcPad->Direction.getValue().y, len);
recomputeFeature();
updateDirectionEdits();
}
void TaskPadParameters::updateDirectionEdits(void)
{
PartDesign::Pad* pcPad = static_cast<PartDesign::Pad*>(vp->getObject());
ui->XDirectionEdit->setValue(pcPad->Direction.getValue().x);
ui->YDirectionEdit->setValue(pcPad->Direction.getValue().y);
ui->ZDirectionEdit->setValue(pcPad->Direction.getValue().z);
}
void TaskPadParameters::onOffsetChanged(double len)
{
PartDesign::Pad* pcPad = static_cast<PartDesign::Pad*>(vp->getObject());
@@ -360,6 +432,26 @@ double TaskPadParameters::getLength2(void) const
return ui->lengthEdit2->value().getValue();
}
bool TaskPadParameters::getCustom(void) const
{
return ui->groupBoxDirection->isChecked();
}
double TaskPadParameters::getXDirection(void) const
{
return ui->XDirectionEdit->value();
}
double TaskPadParameters::getYDirection(void) const
{
return ui->YDirectionEdit->value();
}
double TaskPadParameters::getZDirection(void) const
{
return ui->ZDirectionEdit->value();
}
double TaskPadParameters::getOffset(void) const
{
return ui->offsetEdit->value().getValue();
@@ -404,6 +496,9 @@ void TaskPadParameters::changeEvent(QEvent *e)
if (e->type() == QEvent::LanguageChange) {
ui->lengthEdit->blockSignals(true);
ui->lengthEdit2->blockSignals(true);
ui->XDirectionEdit->blockSignals(true);
ui->YDirectionEdit->blockSignals(true);
ui->ZDirectionEdit->blockSignals(true);
ui->offsetEdit->blockSignals(true);
ui->lineFaceName->blockSignals(true);
ui->changeMode->blockSignals(true);
@@ -443,6 +538,9 @@ void TaskPadParameters::changeEvent(QEvent *e)
ui->lengthEdit->blockSignals(false);
ui->lengthEdit2->blockSignals(false);
ui->XDirectionEdit->blockSignals(false);
ui->YDirectionEdit->blockSignals(false);
ui->ZDirectionEdit->blockSignals(false);
ui->offsetEdit->blockSignals(false);
ui->lineFaceName->blockSignals(false);
ui->changeMode->blockSignals(false);
@@ -463,10 +561,11 @@ void TaskPadParameters::apply()
ui->lengthEdit->apply();
ui->lengthEdit2->apply();
FCMD_OBJ_CMD(obj, "UseCustomVector = " << (getCustom() ? 1 : 0));
FCMD_OBJ_CMD(obj, "Direction = ("
<< getXDirection() << ", " << getYDirection() << ", " << getZDirection() << ")");
FCMD_OBJ_CMD(obj,"Type = " << getMode());
QString facename = getFaceName();
FCMD_OBJ_CMD(obj,"UpToFace = " << facename.toLatin1().data());
FCMD_OBJ_CMD(obj,"Reversed = " << (getReversed()?1:0));
FCMD_OBJ_CMD(obj,"Midplane = " << (getMidplane()?1:0));

View File

@@ -58,6 +58,10 @@ public:
private Q_SLOTS:
void onLengthChanged(double);
void onLength2Changed(double);
void onGBDirectionChanged(bool);
void onXDirectionEditChanged(double);
void onYDirectionEditChanged(double);
void onZDirectionEditChanged(double);
void onOffsetChanged(double);
void onMidplaneChanged(bool);
void onReversedChanged(bool);
@@ -71,6 +75,10 @@ protected:
private:
double getLength(void) const;
double getLength2(void) const;
bool getCustom(void) const;
double getXDirection(void) const;
double getYDirection(void) const;
double getZDirection(void) const;
double getOffset(void) const;
bool getReversed(void) const;
bool getMidplane(void) const;
@@ -78,6 +86,7 @@ private:
QString getFaceName(void) const;
void onSelectionChanged(const Gui::SelectionChanges& msg) override;
void updateUI(int index);
void updateDirectionEdits(void);
private:
QWidget* proxy;

View File

@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>272</width>
<height>271</height>
<width>280</width>
<height>350</height>
</rect>
</property>
<property name="windowTitle">
@@ -55,17 +55,141 @@
</item>
</layout>
</item>
<item>
<widget class="QGroupBox" name="groupBoxDirection">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>Use custom vector for pad direction otherwise
the sketch plane's normal vector will be used</string>
</property>
<property name="title">
<string>Use custom direction</string>
</property>
<property name="checkable">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3">
<item>
<layout class="QHBoxLayout" name="horizontalLayout_6">
<item>
<widget class="QLabel" name="labelXSkew">
<property name="text">
<string>x</string>
</property>
</widget>
</item>
<item>
<widget class="Gui::DoubleSpinBox" name="XDirectionEdit">
<property name="toolTip">
<string>x-component of direction vector</string>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="minimum">
<double>-100.000000000000000</double>
</property>
<property name="maximum">
<double>100.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="unit" stdset="0">
<string notr="true"/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<item>
<widget class="QLabel" name="labelYSkew">
<property name="text">
<string>y</string>
</property>
</widget>
</item>
<item>
<widget class="Gui::DoubleSpinBox" name="YDirectionEdit">
<property name="toolTip">
<string>y-component of direction vector</string>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="minimum">
<double>-100.000000000000000</double>
</property>
<property name="maximum">
<double>100.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="unit" stdset="0">
<string notr="true"/>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_18">
<item>
<widget class="QLabel" name="labelZSkew">
<property name="text">
<string>z</string>
</property>
</widget>
</item>
<item>
<widget class="Gui::DoubleSpinBox" name="ZDirectionEdit">
<property name="toolTip">
<string>z-component of direction vector</string>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="minimum">
<double>-100.000000000000000</double>
</property>
<property name="maximum">
<double>100.000000000000000</double>
</property>
<property name="singleStep">
<double>0.100000000000000</double>
</property>
<property name="value">
<double>1.000000000000000</double>
</property>
<property name="unit" stdset="0">
<string notr="true"/>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<item>
<widget class="QLabel" name="labelOffset">
<property name="text">
<string>Offset</string>
<string>Offset to face</string>
</property>
</widget>
</item>
<item>
<widget class="Gui::PrefQuantitySpinBox" name="offsetEdit">
<property name="toolTip">
<string>Offset from face in which pad will end</string>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
@@ -78,6 +202,9 @@
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>Applies length symmetrically to sketch plane</string>
</property>
<property name="text">
<string>Symmetric to plane</string>
</property>
@@ -85,6 +212,9 @@
</item>
<item>
<widget class="QCheckBox" name="checkBoxReversed">
<property name="toolTip">
<string>Reverses pad direction</string>
</property>
<property name="text">
<string>Reversed</string>
</property>
@@ -150,6 +280,11 @@
<extends>QWidget</extends>
<header>Gui/QuantitySpinBox.h</header>
</customwidget>
<customwidget>
<class>Gui::DoubleSpinBox</class>
<extends>QDoubleSpinBox</extends>
<header>Gui/SpinBox.h</header>
</customwidget>
<customwidget>
<class>Gui::PrefQuantitySpinBox</class>
<extends>Gui::QuantitySpinBox</extends>