Add function to Close Part.Loft (Gui & scripting)
This commit is contained in:
parent
9a52d06dd5
commit
d13946da11
|
@ -1281,14 +1281,19 @@ static PyObject * makeLoft(PyObject *self, PyObject *args)
|
|||
PyObject *pcObj;
|
||||
PyObject *psolid=Py_False;
|
||||
PyObject *pruled=Py_False;
|
||||
if (!PyArg_ParseTuple(args, "O|O!O!", &pcObj,
|
||||
PyObject *pclosed=Py_False;
|
||||
if (!PyArg_ParseTuple(args, "O|O!O!O!", &pcObj,
|
||||
&(PyBool_Type), &psolid,
|
||||
&(PyBool_Type), &pruled))
|
||||
&(PyBool_Type), &pruled,
|
||||
&(PyBool_Type), &pclosed)) {
|
||||
Base::Console().Message("Part.makeLoft Parameter Error\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
try {
|
||||
TopTools_ListOfShape profiles;
|
||||
Py::Sequence list(pcObj);
|
||||
|
||||
for (Py::Sequence::iterator it = list.begin(); it != list.end(); ++it) {
|
||||
if (PyObject_TypeCheck((*it).ptr(), &(Part::TopoShapePy::Type))) {
|
||||
const TopoDS_Shape& sh = static_cast<TopoShapePy*>((*it).ptr())->
|
||||
|
@ -1300,11 +1305,13 @@ static PyObject * makeLoft(PyObject *self, PyObject *args)
|
|||
TopoShape myShape;
|
||||
Standard_Boolean anIsSolid = PyObject_IsTrue(psolid) ? Standard_True : Standard_False;
|
||||
Standard_Boolean anIsRuled = PyObject_IsTrue(pruled) ? Standard_True : Standard_False;
|
||||
TopoDS_Shape aResult = myShape.makeLoft(profiles, anIsSolid, anIsRuled);
|
||||
Standard_Boolean anIsClosed = PyObject_IsTrue(pclosed) ? Standard_True : Standard_False;
|
||||
TopoDS_Shape aResult = myShape.makeLoft(profiles, anIsSolid, anIsRuled,anIsClosed);
|
||||
return new TopoShapePy(new TopoShape(aResult));
|
||||
}
|
||||
catch (Standard_Failure) {
|
||||
Handle_Standard_Failure e = Standard_Failure::Caught();
|
||||
Base::Console().Message("debug: Part.makeLoft catching 'Standard_Failure' msg: '%s'\n", e->GetMessageString());
|
||||
PyErr_SetString(PyExc_Exception, e->GetMessageString());
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -207,6 +207,7 @@ Loft::Loft()
|
|||
Sections.setSize(0);
|
||||
ADD_PROPERTY_TYPE(Solid,(false),"Loft",App::Prop_None,"Create solid");
|
||||
ADD_PROPERTY_TYPE(Ruled,(false),"Loft",App::Prop_None,"Ruled surface");
|
||||
ADD_PROPERTY_TYPE(Closed,(false),"Loft",App::Prop_None,"Close Last to First Profile");
|
||||
}
|
||||
|
||||
short Loft::mustExecute() const
|
||||
|
@ -217,6 +218,8 @@ short Loft::mustExecute() const
|
|||
return 1;
|
||||
if (Ruled.isTouched())
|
||||
return 1;
|
||||
if (Closed.isTouched())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -262,9 +265,10 @@ App::DocumentObjectExecReturn *Loft::execute(void)
|
|||
|
||||
Standard_Boolean isSolid = Solid.getValue() ? Standard_True : Standard_False;
|
||||
Standard_Boolean isRuled = Ruled.getValue() ? Standard_True : Standard_False;
|
||||
Standard_Boolean isClosed = Closed.getValue() ? Standard_True : Standard_False;
|
||||
|
||||
TopoShape myShape;
|
||||
this->Shape.setValue(myShape.makeLoft(profiles, isSolid, isRuled));
|
||||
this->Shape.setValue(myShape.makeLoft(profiles, isSolid, isRuled,isClosed));
|
||||
return App::DocumentObject::StdReturn;
|
||||
}
|
||||
catch (Standard_Failure) {
|
||||
|
|
|
@ -69,6 +69,7 @@ public:
|
|||
App::PropertyLinkList Sections;
|
||||
App::PropertyBool Solid;
|
||||
App::PropertyBool Ruled;
|
||||
App::PropertyBool Closed;
|
||||
|
||||
/** @name methods override feature */
|
||||
//@{
|
||||
|
|
|
@ -74,6 +74,7 @@
|
|||
# include <BRepTools.hxx>
|
||||
# include <BRepTools_ReShape.hxx>
|
||||
# include <BRepTools_ShapeSet.hxx>
|
||||
#include <BRepFill_CompatibleWires.hxx>
|
||||
# include <GCE2d_MakeSegment.hxx>
|
||||
# include <Geom2d_Line.hxx>
|
||||
# include <Geom2d_TrimmedCurve.hxx>
|
||||
|
@ -154,6 +155,8 @@
|
|||
#include <Base/FileInfo.h>
|
||||
#include <Base/Exception.h>
|
||||
#include <Base/Tools.h>
|
||||
#include <Base/Console.h>
|
||||
|
||||
|
||||
#include "TopoShape.h"
|
||||
#include "CrossSection.h"
|
||||
|
@ -1788,13 +1791,14 @@ TopoDS_Shape TopoShape::makeThread(Standard_Real pitch,
|
|||
|
||||
TopoDS_Shape TopoShape::makeLoft(const TopTools_ListOfShape& profiles,
|
||||
Standard_Boolean isSolid,
|
||||
Standard_Boolean isRuled) const
|
||||
Standard_Boolean isRuled,
|
||||
Standard_Boolean isClosed) const
|
||||
{
|
||||
// http://opencascade.blogspot.com/2010/01/surface-modeling-part5.html
|
||||
BRepOffsetAPI_ThruSections aGenerator (isSolid,isRuled);
|
||||
|
||||
int countShapes = 0;
|
||||
TopTools_ListIteratorOfListOfShape it;
|
||||
int countShapes = 0;
|
||||
for (it.Initialize(profiles); it.More(); it.Next()) {
|
||||
const TopoDS_Shape& item = it.Value();
|
||||
if (!item.IsNull() && item.ShapeType() == TopAbs_VERTEX) {
|
||||
|
@ -1812,15 +1816,44 @@ TopoDS_Shape TopoShape::makeLoft(const TopTools_ListOfShape& profiles,
|
|||
}
|
||||
}
|
||||
|
||||
if (countShapes < 2)
|
||||
Standard_Failure::Raise("Need at least two vertices, edges or wires to create loft face");
|
||||
if (countShapes < 2) {
|
||||
Standard_Failure::Raise("Need at least two vertices, edges or wires to create loft face"); }
|
||||
else {
|
||||
// close loft by duplicating initial profile as last profile. not perfect.
|
||||
if (isClosed) {
|
||||
/* can only close loft in certain combinations of Vertex/Wire(Edge):
|
||||
- V1-W1-W2-W3-V2 ==> V1-W1-W2-W3-V2-V1 invalid closed
|
||||
- V1-W1-W2-W3 ==> V1-W1-W2-W3-V1 valid closed
|
||||
- W1-W2-W3-V1 ==> W1-W2-W3-V1-W1 invalid closed
|
||||
- W1-W2-W3 ==> W1-W2-W3-W1 valid closed*/
|
||||
if (profiles.Last().ShapeType() == TopAbs_VERTEX) {
|
||||
Base::Console().Message("TopoShape::makeLoft: can't close Loft with Vertex as last profile. 'Closed' ignored.\n"); }
|
||||
else {
|
||||
// repeat Add logic above for first profile
|
||||
const TopoDS_Shape& firstProfile = profiles.First();
|
||||
if (firstProfile.ShapeType() == TopAbs_VERTEX) {
|
||||
aGenerator.AddVertex(TopoDS::Vertex (firstProfile));
|
||||
countShapes++;
|
||||
}
|
||||
else if (firstProfile.ShapeType() == TopAbs_EDGE) {
|
||||
aGenerator.AddWire(TopoDS::Wire (firstProfile));
|
||||
countShapes++;
|
||||
}
|
||||
else if (firstProfile.ShapeType() == TopAbs_WIRE) {
|
||||
aGenerator.AddWire(TopoDS::Wire (firstProfile));
|
||||
countShapes++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Standard_Boolean anIsCheck = Standard_True;
|
||||
aGenerator.CheckCompatibility (anIsCheck);
|
||||
aGenerator.CheckCompatibility (anIsCheck); // use BRepFill_CompatibleWires on profiles. force #edges, orientation, "origin" to match.
|
||||
aGenerator.Build();
|
||||
if (!aGenerator.IsDone())
|
||||
Standard_Failure::Raise("Failed to create loft face");
|
||||
|
||||
|
||||
//Base::Console().Message("DEBUG: TopoShape::makeLoft returns.\n");
|
||||
return aGenerator.Shape();
|
||||
}
|
||||
|
||||
|
|
|
@ -170,7 +170,7 @@ public:
|
|||
TopoDS_Shape makeThread(Standard_Real pitch, Standard_Real depth,
|
||||
Standard_Real height, Standard_Real radius) const;
|
||||
TopoDS_Shape makeLoft(const TopTools_ListOfShape& profiles, Standard_Boolean isSolid,
|
||||
Standard_Boolean isRuled) const;
|
||||
Standard_Boolean isRuled, Standard_Boolean isClosed = Standard_False) const;
|
||||
TopoDS_Shape makeOffsetShape(double offset, double tol,
|
||||
bool intersection = false, bool selfInter = false,
|
||||
short offsetMode = 0, short join = 0, bool fill = false) const;
|
||||
|
|
|
@ -118,7 +118,7 @@ void LoftWidget::findShapes()
|
|||
|
||||
bool LoftWidget::accept()
|
||||
{
|
||||
QString list, solid, ruled;
|
||||
QString list, solid, ruled, closed;
|
||||
if (d->ui.checkSolid->isChecked())
|
||||
solid = QString::fromAscii("True");
|
||||
else
|
||||
|
@ -129,6 +129,11 @@ bool LoftWidget::accept()
|
|||
else
|
||||
ruled = QString::fromAscii("False");
|
||||
|
||||
if (d->ui.checkClosed->isChecked())
|
||||
closed = QString::fromAscii("True");
|
||||
else
|
||||
closed = QString::fromAscii("False");
|
||||
|
||||
QTextStream str(&list);
|
||||
|
||||
int count = d->ui.selector->selectedTreeWidget()->topLevelItemCount();
|
||||
|
@ -145,11 +150,12 @@ bool LoftWidget::accept()
|
|||
try {
|
||||
QString cmd;
|
||||
cmd = QString::fromAscii(
|
||||
"App.getDocument('%4').addObject('Part::Loft','Loft')\n"
|
||||
"App.getDocument('%4').ActiveObject.Sections=[%1]\n"
|
||||
"App.getDocument('%4').ActiveObject.Solid=%2\n"
|
||||
"App.getDocument('%4').ActiveObject.Ruled=%3\n"
|
||||
).arg(list).arg(solid).arg(ruled).arg(QString::fromAscii(d->document.c_str()));
|
||||
"App.getDocument('%5').addObject('Part::Loft','Loft')\n"
|
||||
"App.getDocument('%5').ActiveObject.Sections=[%1]\n"
|
||||
"App.getDocument('%5').ActiveObject.Solid=%2\n"
|
||||
"App.getDocument('%5').ActiveObject.Ruled=%3\n"
|
||||
"App.getDocument('%5').ActiveObject.Closed=%4\n"
|
||||
).arg(list).arg(solid).arg(ruled).arg(closed).arg(QString::fromAscii(d->document.c_str()));
|
||||
|
||||
Gui::Document* doc = Gui::Application::Instance->getDocument(d->document.c_str());
|
||||
if (!doc) throw Base::Exception("Document doesn't exist anymore");
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
<string>Loft</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0" colspan="3">
|
||||
<item row="0" column="0" colspan="4">
|
||||
<widget class="Gui::ActionSelector" name="selector"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
|
@ -31,7 +31,7 @@
|
|||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<item row="1" column="3">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
|
@ -44,6 +44,13 @@
|
|||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QCheckBox" name="checkClosed">
|
||||
<property name="text">
|
||||
<string>Closed</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
|
|
Loading…
Reference in New Issue
Block a user