From 245cae03ef6c1f30a2a1c89d955c0a383fd22f29 Mon Sep 17 00:00:00 2001 From: wmayer Date: Sat, 9 Jun 2012 13:50:33 +0200 Subject: [PATCH] 0000144: Add several tools to Part module --- src/Gui/SelectionObject.h | 6 +- src/Mod/Part/App/AppPart.cpp | 1 + src/Mod/Part/App/PartFeatures.cpp | 95 ++++++++++++ src/Mod/Part/App/PartFeatures.h | 23 +++ src/Mod/Part/Gui/CMakeLists.txt | 5 + src/Mod/Part/Gui/Command.cpp | 27 ++++ src/Mod/Part/Gui/TaskSweep.cpp | 243 ++++++++++++++++++++++++++++++ src/Mod/Part/Gui/TaskSweep.h | 81 ++++++++++ src/Mod/Part/Gui/TaskSweep.ui | 60 ++++++++ src/Mod/Part/Gui/Workbench.cpp | 2 +- 10 files changed, 539 insertions(+), 4 deletions(-) create mode 100644 src/Mod/Part/Gui/TaskSweep.cpp create mode 100644 src/Mod/Part/Gui/TaskSweep.h create mode 100644 src/Mod/Part/Gui/TaskSweep.ui diff --git a/src/Gui/SelectionObject.h b/src/Gui/SelectionObject.h index 784b89f27..5c871594c 100644 --- a/src/Gui/SelectionObject.h +++ b/src/Gui/SelectionObject.h @@ -55,11 +55,11 @@ public: /// are there any SubNames selected bool hasSubNames(void)const { return SubNames.size() != 0; } /// get the name of the Document of this SelctionObject - inline const char* getDocName(void) { return DocName.c_str(); } + inline const char* getDocName(void) const { return DocName.c_str(); } /// get the name of the Document Object of this SelectionObject - inline const char* getFeatName(void) { return FeatName.c_str(); } + inline const char* getFeatName(void) const { return FeatName.c_str(); } /// get the Type of the selcted Object - inline const char* getTypeName(void) { return TypeName.c_str(); } + inline const char* getTypeName(void) const { return TypeName.c_str(); } /// returns the selected DocumentObject or NULL if the object is already deleted const App::DocumentObject *getObject(void) const; diff --git a/src/Mod/Part/App/AppPart.cpp b/src/Mod/Part/App/AppPart.cpp index 716597e2b..4980b0be1 100644 --- a/src/Mod/Part/App/AppPart.cpp +++ b/src/Mod/Part/App/AppPart.cpp @@ -179,6 +179,7 @@ void PartExport initPart() Part::Part2DObjectPython ::init(); Part::RuledSurface ::init(); Part::Loft ::init(); + Part::Sweep ::init(); // Geometry types Part::Geometry ::init(); diff --git a/src/Mod/Part/App/PartFeatures.cpp b/src/Mod/Part/App/PartFeatures.cpp index 1f2088874..c50c854bb 100644 --- a/src/Mod/Part/App/PartFeatures.cpp +++ b/src/Mod/Part/App/PartFeatures.cpp @@ -196,3 +196,98 @@ App::DocumentObjectExecReturn *Loft::execute(void) return new App::DocumentObjectExecReturn(e->GetMessageString()); } } + +// ---------------------------------------------------------------------------- + +PROPERTY_SOURCE(Part::Sweep, Part::Feature) + +Sweep::Sweep() +{ + ADD_PROPERTY_TYPE(Sections,(0),"Sweep",App::Prop_None,"List of sections"); + Sections.setSize(0); + ADD_PROPERTY_TYPE(Spine,(0),"Sweep",App::Prop_None,"Path to sweep along"); + ADD_PROPERTY_TYPE(Solid,(false),"Sweep",App::Prop_None,"Create solid"); + ADD_PROPERTY_TYPE(Fresnet,(false),"Sweep",App::Prop_None,"Fresnet"); +} + +short Sweep::mustExecute() const +{ + if (Sections.isTouched()) + return 1; + if (Spine.isTouched()) + return 1; + if (Solid.isTouched()) + return 1; + if (Fresnet.isTouched()) + return 1; + return 0; +} + +void Sweep::onChanged(const App::Property* prop) +{ + Part::Feature::onChanged(prop); +} + +App::DocumentObjectExecReturn *Sweep::execute(void) +{ + if (Sections.getSize() == 0) + return new App::DocumentObjectExecReturn("No sections linked."); + App::DocumentObject* spine = Spine.getValue(); + if (!(spine && spine->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))) + return new App::DocumentObjectExecReturn("No shape linked."); + const std::vector& subedge = Spine.getSubValues(); + if (subedge.size() != 1) + return new App::DocumentObjectExecReturn("Not exactly one sub-shape linked."); + + TopoDS_Shape edge; + const Part::TopoShape& shape = static_cast(spine)->Shape.getValue(); + if (!shape._Shape.IsNull()) { + if (!subedge[0].empty()) { + edge = shape.getSubShape(subedge[0].c_str()); + } + else { + if (shape._Shape.ShapeType() == TopAbs_EDGE) + edge = shape._Shape; + else if (shape._Shape.ShapeType() == TopAbs_WIRE) + edge = shape._Shape; + } + } + + try { + TopTools_ListOfShape profiles; + const std::vector& shapes = Sections.getValues(); + std::vector::const_iterator it; + for (it = shapes.begin(); it != shapes.end(); ++it) { + if (!(*it)->isDerivedFrom(Part::Feature::getClassTypeId())) + return new App::DocumentObjectExecReturn("Linked object is not a shape."); + const TopoDS_Shape& shape = static_cast(*it)->Shape.getValue(); + if (shape.IsNull()) + return new App::DocumentObjectExecReturn("Linked shape is invalid."); + if (shape.ShapeType() == TopAbs_WIRE) { + profiles.Append(shape); + } + else if (shape.ShapeType() == TopAbs_EDGE) { + BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(shape)); + profiles.Append(mkWire.Wire()); + } + else if (shape.ShapeType() == TopAbs_VERTEX) { + profiles.Append(shape); + } + else { + return new App::DocumentObjectExecReturn("Linked shape is not a vertex, edge nor wire."); + } + } + + Standard_Boolean isSolid = Solid.getValue() ? Standard_True : Standard_False; + Standard_Boolean isFresnet = Fresnet.getValue() ? Standard_True : Standard_False; + + BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(edge)); + TopoShape myShape(mkWire.Wire()); + this->Shape.setValue(myShape.makePipeShell(profiles, isSolid, isFresnet)); + return App::DocumentObject::StdReturn; + } + catch (Standard_Failure) { + Handle_Standard_Failure e = Standard_Failure::Caught(); + return new App::DocumentObjectExecReturn(e->GetMessageString()); + } +} diff --git a/src/Mod/Part/App/PartFeatures.h b/src/Mod/Part/App/PartFeatures.h index f01fde575..25d2050a5 100644 --- a/src/Mod/Part/App/PartFeatures.h +++ b/src/Mod/Part/App/PartFeatures.h @@ -73,6 +73,29 @@ protected: void onChanged (const App::Property* prop); }; +class Sweep : public Part::Feature +{ + PROPERTY_HEADER(Part::Sweep); + +public: + Sweep(); + + App::PropertyLinkList Sections; + App::PropertyLinkSub Spine; + App::PropertyBool Solid; + App::PropertyBool Fresnet; + + /** @name methods override feature */ + //@{ + /// recalculate the feature + App::DocumentObjectExecReturn *execute(void); + short mustExecute() const; + //@} + +protected: + void onChanged (const App::Property* prop); +}; + } //namespace Part diff --git a/src/Mod/Part/Gui/CMakeLists.txt b/src/Mod/Part/Gui/CMakeLists.txt index d9ff99f95..ec068eb95 100644 --- a/src/Mod/Part/Gui/CMakeLists.txt +++ b/src/Mod/Part/Gui/CMakeLists.txt @@ -41,6 +41,7 @@ set(PartGui_MOC_HDRS TaskFaceColors.h TaskShapeBuilder.h TaskLoft.h + TaskSweep.h ) fc_wrap_cpp(PartGui_MOC_SRCS ${PartGui_MOC_HDRS}) SOURCE_GROUP("Moc" FILES ${PartGui_MOC_SRCS}) @@ -65,6 +66,7 @@ set(PartGui_UIC_SRCS TaskFaceColors.ui TaskShapeBuilder.ui TaskLoft.ui + TaskSweep.ui ) qt4_wrap_ui(PartGui_UIC_HDRS ${PartGui_UIC_SRCS}) @@ -155,6 +157,9 @@ SET(PartGui_SRCS TaskLoft.cpp TaskLoft.h TaskLoft.ui + TaskSweep.cpp + TaskSweep.h + TaskSweep.ui ) SET(PartGui_Scripts diff --git a/src/Mod/Part/Gui/Command.cpp b/src/Mod/Part/Gui/Command.cpp index 33cd008ee..5020e4872 100644 --- a/src/Mod/Part/Gui/Command.cpp +++ b/src/Mod/Part/Gui/Command.cpp @@ -61,6 +61,7 @@ #include "ViewProvider.h" #include "TaskShapeBuilder.h" #include "TaskLoft.h" +#include "TaskSweep.h" //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -960,6 +961,31 @@ bool CmdPartLoft::isActive(void) //-------------------------------------------------------------------------------------- +DEF_STD_CMD_A(CmdPartSweep); + +CmdPartSweep::CmdPartSweep() + : Command("Part_Sweep") +{ + sAppModule = "Part"; + sGroup = QT_TR_NOOP("Part"); + sMenuText = QT_TR_NOOP("Sweep..."); + sToolTipText = QT_TR_NOOP("Advanced utility to sweep"); + sWhatsThis = sToolTipText; + sStatusTip = sToolTipText; +} + +void CmdPartSweep::activated(int iMsg) +{ + Gui::Control().showDialog(new PartGui::TaskSweep()); +} + +bool CmdPartSweep::isActive(void) +{ + return (hasActiveDocument() && !Gui::Control().activeDialog()); +} + +//-------------------------------------------------------------------------------------- + DEF_STD_CMD_A(CmdShapeInfo); CmdShapeInfo::CmdShapeInfo() @@ -1194,5 +1220,6 @@ void CreatePartCommands(void) rcCmdMgr.addCommand(new CmdPartRuledSurface()); rcCmdMgr.addCommand(new CmdPartBuilder()); rcCmdMgr.addCommand(new CmdPartLoft()); + rcCmdMgr.addCommand(new CmdPartSweep()); } diff --git a/src/Mod/Part/Gui/TaskSweep.cpp b/src/Mod/Part/Gui/TaskSweep.cpp new file mode 100644 index 000000000..0639c28a2 --- /dev/null +++ b/src/Mod/Part/Gui/TaskSweep.cpp @@ -0,0 +1,243 @@ +/*************************************************************************** + * Copyright (c) 2011 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +# include +#endif + +#include "ui_TaskSweep.h" +#include "TaskSweep.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +using namespace PartGui; + +class SweepWidget::Private +{ +public: + Ui_TaskSweep ui; + std::string document; + Private() + { + } + ~Private() + { + } +}; + +/* TRANSLATOR PartGui::SweepWidget */ + +SweepWidget::SweepWidget(QWidget* parent) + : d(new Private()) +{ + Gui::Application::Instance->runPythonCode("from FreeCAD import Base"); + Gui::Application::Instance->runPythonCode("import Part"); + + d->ui.setupUi(this); + d->ui.selector->setAvailableLabel(tr("Vertex/Wire")); + d->ui.selector->setSelectedLabel(tr("Sweep")); + + connect(d->ui.selector->availableTreeWidget(), SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), + this, SLOT(onCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*))); + connect(d->ui.selector->selectedTreeWidget(), SIGNAL(currentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*)), + this, SLOT(onCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*))); + + findShapes(); +} + +SweepWidget::~SweepWidget() +{ + delete d; +} + +void SweepWidget::findShapes() +{ + App::Document* activeDoc = App::GetApplication().getActiveDocument(); + Gui::Document* activeGui = Gui::Application::Instance->getDocument(activeDoc); + if (!activeGui) return; + d->document = activeDoc->getName(); + + std::vector objs = activeDoc->getObjectsOfType(); + + for (std::vector::iterator it = objs.begin(); it!=objs.end(); ++it) { + const TopoDS_Shape& shape = (*it)->Shape.getValue(); + if (shape.IsNull()) continue; + + if (shape.ShapeType() == TopAbs_WIRE || + shape.ShapeType() == TopAbs_EDGE || + shape.ShapeType() == TopAbs_VERTEX) { + QString label = QString::fromUtf8((*it)->Label.getValue()); + QString name = QString::fromAscii((*it)->getNameInDocument()); + + QTreeWidgetItem* child = new QTreeWidgetItem(); + child->setText(0, label); + child->setToolTip(0, label); + child->setData(0, Qt::UserRole, name); + Gui::ViewProvider* vp = activeGui->getViewProvider(*it); + if (vp) child->setIcon(0, vp->getIcon()); + d->ui.selector->availableTreeWidget()->addTopLevelItem(child); + } + } +} + +bool SweepWidget::accept() +{ + Gui::SelectionFilter edgeFilter ("SELECT Part::Feature SUBELEMENT Edge COUNT 1"); + if (!edgeFilter.match()) { + QMessageBox::critical(this, tr("Sweep path"), tr("Select an edge you want to sweep along.")); + return false; + } + + // get the selected object + const std::vector& result = edgeFilter.Result[0]; + const std::vector& edges = result[0].getSubNames(); + + QString list, solid, fresnet; + if (d->ui.checkSolid->isChecked()) + solid = QString::fromAscii("True"); + else + solid = QString::fromAscii("False"); + + if (d->ui.checkFresnet->isChecked()) + fresnet = QString::fromAscii("True"); + else + fresnet = QString::fromAscii("False"); + + QTextStream str(&list); + + int count = d->ui.selector->selectedTreeWidget()->topLevelItemCount(); + if (count < 1) { + QMessageBox::critical(this, tr("Too few elements"), tr("At least one edge or wire is required.")); + return false; + } + for (int i=0; iui.selector->selectedTreeWidget()->topLevelItem(i); + QString name = child->data(0, Qt::UserRole).toString(); + str << "App.getDocument('" << d->document.c_str() << "')." << name << ", "; + } + + try { + QString cmd; + cmd = QString::fromAscii( + "App.getDocument('%6').addObject('Part::Sweep','Sweep')\n" + "App.getDocument('%6').ActiveObject.Sections=[%1]\n" + "App.getDocument('%6').ActiveObject.Spine=(FreeCAD.ActiveDocument.%2,['%3'])\n" + "App.getDocument('%6').ActiveObject.Solid=%4\n" + "App.getDocument('%6').ActiveObject.Fresnet=%5\n" + ) + .arg(list).arg(QLatin1String(result.front().getFeatName())) + .arg(QLatin1String(edges.front().c_str())) + .arg(solid).arg(fresnet).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"); + doc->openCommand("Sweep"); + Gui::Application::Instance->runPythonCode((const char*)cmd.toAscii(), false, false); + doc->commitCommand(); + doc->getDocument()->recompute(); + } + catch (const Base::Exception& e) { + Base::Console().Error("%s\n", e.what()); + return false; + } + + return true; +} + +bool SweepWidget::reject() +{ + return true; +} + +void SweepWidget::onCurrentItemChanged(QTreeWidgetItem* current, QTreeWidgetItem* previous) +{ + if (previous) { + Gui::Selection().rmvSelection(d->document.c_str(), + (const char*)previous->data(0,Qt::UserRole).toByteArray()); + } + if (current) { + Gui::Selection().addSelection(d->document.c_str(), + (const char*)current->data(0,Qt::UserRole).toByteArray()); + } +} + +void SweepWidget::changeEvent(QEvent *e) +{ + QWidget::changeEvent(e); + if (e->type() == QEvent::LanguageChange) { + d->ui.retranslateUi(this); + d->ui.selector->setAvailableLabel(tr("Vertex/Wire")); + d->ui.selector->setSelectedLabel(tr("Sweep")); + } +} + + +/* TRANSLATOR PartGui::TaskSweep */ + +TaskSweep::TaskSweep() +{ + widget = new SweepWidget(); + taskbox = new Gui::TaskView::TaskBox( + QPixmap(), widget->windowTitle(), true, 0); + taskbox->groupLayout()->addWidget(widget); + Content.push_back(taskbox); +} + +TaskSweep::~TaskSweep() +{ +} + +void TaskSweep::open() +{ +} + +void TaskSweep::clicked(int) +{ +} + +bool TaskSweep::accept() +{ + return widget->accept(); +} + +bool TaskSweep::reject() +{ + return widget->reject(); +} + +#include "moc_TaskSweep.cpp" diff --git a/src/Mod/Part/Gui/TaskSweep.h b/src/Mod/Part/Gui/TaskSweep.h new file mode 100644 index 000000000..f0c6fc592 --- /dev/null +++ b/src/Mod/Part/Gui/TaskSweep.h @@ -0,0 +1,81 @@ +/*************************************************************************** + * Copyright (c) 2011 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#ifndef PARTGUI_TASKSWEEP_H +#define PARTGUI_TASKSWEEP_H + +#include +#include + +class QTreeWidgetItem; + +namespace PartGui { + +class SweepWidget : public QWidget +{ + Q_OBJECT + +public: + SweepWidget(QWidget* parent = 0); + ~SweepWidget(); + + bool accept(); + bool reject(); + +private Q_SLOTS: + void onCurrentItemChanged(QTreeWidgetItem*, QTreeWidgetItem*); + +private: + void changeEvent(QEvent *e); + void findShapes(); + +private: + class Private; + Private* d; +}; + +class TaskSweep : public Gui::TaskView::TaskDialog +{ + Q_OBJECT + +public: + TaskSweep(); + ~TaskSweep(); + +public: + void open(); + bool accept(); + bool reject(); + void clicked(int); + + QDialogButtonBox::StandardButtons getStandardButtons() const + { return QDialogButtonBox::Ok|QDialogButtonBox::Cancel; } + +private: + SweepWidget* widget; + Gui::TaskView::TaskBox* taskbox; +}; + +} //namespace PartGui + +#endif // PARTGUI_TASKSWEEP_H diff --git a/src/Mod/Part/Gui/TaskSweep.ui b/src/Mod/Part/Gui/TaskSweep.ui new file mode 100644 index 000000000..f91e754f5 --- /dev/null +++ b/src/Mod/Part/Gui/TaskSweep.ui @@ -0,0 +1,60 @@ + + + PartGui::TaskSweep + + + + 0 + 0 + 336 + 326 + + + + Sweep + + + + + + + + + Create solid + + + + + + + Qt::Horizontal + + + + 130 + 20 + + + + + + + + Fresnet + + + + + + + + Gui::ActionSelector + QWidget +
Gui/Widgets.h
+
+
+ + + + +
diff --git a/src/Mod/Part/Gui/Workbench.cpp b/src/Mod/Part/Gui/Workbench.cpp index ea42cb9f3..9997750b2 100644 --- a/src/Mod/Part/Gui/Workbench.cpp +++ b/src/Mod/Part/Gui/Workbench.cpp @@ -72,7 +72,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const << "Part_RefineShape" << "Separator" << "Part_Boolean" << "Part_CrossSections" << "Part_Extrude" << "Part_Revolve" << "Part_Mirror" << "Part_Fillet" << "Part_Chamfer" - << "Part_RuledSurface" << "Part_Loft" + << "Part_RuledSurface" << "Part_Loft" << "Part_Sweep" << "Part_Builder"; //Gui::MenuItem* partSimple = new Gui::MenuItem;