diff --git a/src/Mod/PartDesign/App/Feature.cpp b/src/Mod/PartDesign/App/Feature.cpp index e8ccbd849..aa4cd3267 100644 --- a/src/Mod/PartDesign/App/Feature.cpp +++ b/src/Mod/PartDesign/App/Feature.cpp @@ -45,7 +45,7 @@ Feature::Feature() { } -TopoDS_Shape Feature::getSolid(const TopoDS_Shape& shape) const +TopoDS_Shape Feature::getSolid(const TopoDS_Shape& shape) { if (shape.IsNull()) Standard_Failure::Raise("Shape is null"); @@ -58,7 +58,7 @@ TopoDS_Shape Feature::getSolid(const TopoDS_Shape& shape) const return TopoDS_Shape(); } -const gp_Pnt Feature::getPointFromFace(const TopoDS_Face& f) const +const gp_Pnt Feature::getPointFromFace(const TopoDS_Face& f) { if (!f.Infinite()) { TopExp_Explorer exp; diff --git a/src/Mod/PartDesign/App/Feature.h b/src/Mod/PartDesign/App/Feature.h index f3658c0db..42c9a3173 100644 --- a/src/Mod/PartDesign/App/Feature.h +++ b/src/Mod/PartDesign/App/Feature.h @@ -49,10 +49,10 @@ protected: /** * Get a solid of the given shape. If no solid is found an exception is raised. */ - TopoDS_Shape getSolid(const TopoDS_Shape&) const; + static TopoDS_Shape getSolid(const TopoDS_Shape&); /// Grab any point from the given face - const gp_Pnt getPointFromFace(const TopoDS_Face& f) const; + static const gp_Pnt getPointFromFace(const TopoDS_Face& f); }; diff --git a/src/Mod/PartDesign/App/FeatureTransformed.cpp b/src/Mod/PartDesign/App/FeatureTransformed.cpp index 278f6f866..f871f89a0 100644 --- a/src/Mod/PartDesign/App/FeatureTransformed.cpp +++ b/src/Mod/PartDesign/App/FeatureTransformed.cpp @@ -28,6 +28,7 @@ # include # include # include +# include # include # include # include @@ -50,7 +51,7 @@ namespace PartDesign { PROPERTY_SOURCE(PartDesign::Transformed, PartDesign::Feature) -Transformed::Transformed() +Transformed::Transformed() : rejected(0) { ADD_PROPERTY(Originals,(0)); Originals.setSize(0); @@ -58,12 +59,12 @@ Transformed::Transformed() void Transformed::positionBySupport(void) { - Part::Feature *support = static_cast(getOriginalObject()); + Part::Feature *support = static_cast(getSupportObject()); if ((support != NULL) && support->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) this->Placement.setValue(support->Placement.getValue()); } -App::DocumentObject* Transformed::getOriginalObject() const +App::DocumentObject* Transformed::getSupportObject() const { if (!Originals.getValues().empty()) return Originals.getValues().front(); @@ -80,6 +81,8 @@ short Transformed::mustExecute() const App::DocumentObjectExecReturn *Transformed::execute(void) { + rejected.clear(); + std::vector originals = Originals.getValues(); if (originals.empty()) // typically InsideMultiTransform return App::DocumentObject::StdReturn; @@ -101,10 +104,10 @@ App::DocumentObjectExecReturn *Transformed::execute(void) // NOTE: Because of the way we define the support, FeatureTransformed can only work on // one Body feature at a time // TODO: Currently, the support is simply the first Original. Change this to the Body feature later - Part::Feature* supportFeature = static_cast(originals.front()); + Part::Feature* supportFeature = static_cast(getSupportObject()); const Part::TopoShape& supportTopShape = supportFeature->Shape.getShape(); if (supportTopShape._Shape.IsNull()) - return new App::DocumentObjectExecReturn("Cannot transform invalid shape"); + return new App::DocumentObjectExecReturn("Cannot transform invalid support shape"); // create an untransformed copy of the support shape Part::TopoShape supportShape(supportTopShape); @@ -162,9 +165,10 @@ App::DocumentObjectExecReturn *Transformed::execute(void) Bnd_Box transformed_bb; BRepBndLib::Add(mkTrf.Shape(), transformed_bb); if (support_bb.Distance(transformed_bb) > Precision::Confusion()) { - Base::Console().Warning("Transformed shape does not intersect original %s: Removed\n", (*o)->getNameInDocument()); + Base::Console().Warning("Transformed shape does not intersect support %s: Removed\n", (*o)->getNameInDocument()); // Note: The removal happens in getSolid() after the fuse. If we remove here, // the histories get messed up and we get a crash + rejected.push_back(*t); } builder.Add(transformedShapes, mkTrf.Shape()); v_transformedShapes.push_back(mkTrf.Shape()); @@ -178,7 +182,7 @@ App::DocumentObjectExecReturn *Transformed::execute(void) Bnd_Box transformed_bb; BRepBndLib::Add(trfShape, transformed_bb); if (support_bb.Distance(transformed_bb) > Precision::Confusion()) { - Base::Console().Warning("Transformed shape does not intersect original %s: Removed\n", (*o)->getNameInDocument()); + Base::Console().Warning("Transformed shape does not intersect support %s: Removed\n", (*o)->getNameInDocument()); // Note: The removal happens in getSolid() after the fuse. If we remove here, // the histories get messed up and we get a crash } @@ -231,8 +235,14 @@ App::DocumentObjectExecReturn *Transformed::execute(void) result = this->getSolid(mkFuse.Shape()); // lets check if the result is a solid if (result.IsNull()) - return new App::DocumentObjectExecReturn("Transformed: Resulting shape is not a solid", *o); - + return new App::DocumentObjectExecReturn("Resulting shape is not a solid", *o); + // check if mkFuse created more than one solids + TopExp_Explorer xp; + xp.Init(mkFuse.Shape(),TopAbs_SOLID); + if (xp.More()) + xp.Next(); + if (!xp.More()) // There are no rejected transformations even + rejected.clear(); // if the bb check guessed that there would be } else { BRepAlgoAPI_Cut mkCut(support, transformedShapes); if (!mkCut.IsDone()) diff --git a/src/Mod/PartDesign/App/FeatureTransformed.h b/src/Mod/PartDesign/App/FeatureTransformed.h index 099e6dd29..6bb89f50a 100644 --- a/src/Mod/PartDesign/App/FeatureTransformed.h +++ b/src/Mod/PartDesign/App/FeatureTransformed.h @@ -45,11 +45,12 @@ public: Transformed(); /** The shapes to be transformed - if Originals is empty the instance is just a container for storing transformation data */ + * if Originals is empty the instance is just a container for storing transformation data + */ App::PropertyLinkList Originals; /// Return first original, which serves as "Support" until Body feature becomes functional - App::DocumentObject* getOriginalObject() const; + App::DocumentObject* getSupportObject() const; /// Get the list of transformations describing the members of the pattern // Note: Only the Scaled feature requires the originals @@ -72,11 +73,13 @@ public: void positionBySupport(void); + /** returns a list of the transformations that where rejected during the last execute + * because they did not ovelap with the support + */ + const std::list getRejectedTransformations(void) { return rejected; } + protected: - void buildTransformHistory(BRepBuilderAPI_MakeShape& mkFuse, - const TopoDS_Shape& newShape, - const TopoDS_Shape& oldShape, - const int index); + std::list rejected; }; } //namespace PartDesign diff --git a/src/Mod/PartDesign/Gui/CMakeLists.txt b/src/Mod/PartDesign/Gui/CMakeLists.txt index 97b9b8e5f..07d2bfe02 100644 --- a/src/Mod/PartDesign/Gui/CMakeLists.txt +++ b/src/Mod/PartDesign/Gui/CMakeLists.txt @@ -32,6 +32,7 @@ set(PartDesignGui_MOC_HDRS TaskHoleParameters.h TaskRevolutionParameters.h TaskGrooveParameters.h + TaskTransformedMessages.h TaskTransformedParameters.h TaskMirroredParameters.h TaskLinearPatternParameters.h @@ -52,6 +53,7 @@ set(PartDesignGui_UIC_SRCS TaskHoleParameters.ui TaskRevolutionParameters.ui TaskGrooveParameters.ui + TaskTransformedMessages.ui TaskMirroredParameters.ui TaskLinearPatternParameters.ui TaskPolarPatternParameters.ui @@ -111,8 +113,11 @@ SET(PartDesignGuiTaskDlgs_SRCS TaskGrooveParameters.ui TaskGrooveParameters.cpp TaskGrooveParameters.h - TaskTransformedParameters.h + TaskTransformedMessages.ui + TaskTransformedMessages.cpp + TaskTransformedMessages.h TaskTransformedParameters.cpp + TaskTransformedParameters.h TaskMirroredParameters.ui TaskMirroredParameters.cpp TaskMirroredParameters.h diff --git a/src/Mod/PartDesign/Gui/TaskTransformedMessages.cpp b/src/Mod/PartDesign/Gui/TaskTransformedMessages.cpp new file mode 100644 index 000000000..2c15ec528 --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskTransformedMessages.cpp @@ -0,0 +1,68 @@ +/*************************************************************************** + * Copyright (c) 2012 Jürgen Riegel * + * * + * 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_ +#endif + +#include "ui_TaskTransformedMessages.h" +#include "TaskTransformedMessages.h" +#include +#include +#include + +#include + +#include "ViewProviderTransformed.h" + +using namespace PartDesignGui; +using namespace Gui::TaskView; + +TaskTransformedMessages::TaskTransformedMessages(ViewProviderTransformed *transformedView_) + : TaskBox(Gui::BitmapFactory().pixmap("document-new"),tr("Transformed feature messages"),true, 0), + transformedView(transformedView_) +{ + // we need a separate container widget to add all controls to + proxy = new QWidget(this); + ui = new Ui_TaskTransformedMessages(); + ui->setupUi(proxy); + QMetaObject::connectSlotsByName(this); + + this->groupLayout()->addWidget(proxy); + + connectionDiagnosis = transformedView->signalDiagnosis.connect(boost::bind(&PartDesignGui::TaskTransformedMessages::slotDiagnosis, this,_1)); +} + +TaskTransformedMessages::~TaskTransformedMessages() +{ + connectionDiagnosis.disconnect(); + delete ui; +} + +void TaskTransformedMessages::slotDiagnosis(QString msg) +{ + ui->labelTransformationStatus->setText(msg); +} + +#include "moc_TaskTransformedMessages.cpp" diff --git a/src/Mod/PartDesign/Gui/TaskTransformedMessages.h b/src/Mod/PartDesign/Gui/TaskTransformedMessages.h new file mode 100644 index 000000000..afeadb31e --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskTransformedMessages.h @@ -0,0 +1,64 @@ +/*************************************************************************** + * Copyright (c) 2012 Jürgen Riegel * + * * + * 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 GUI_TASKVIEW_TaskTransformedMessages_H +#define GUI_TASKVIEW_TaskTransformedMessages_H + +#include +#include + +class Ui_TaskTransformedMessages; +typedef boost::signals::connection Connection; + +namespace App { +class Property; +} + +namespace PartDesignGui { + +class ViewProviderTransformed; + +class TaskTransformedMessages : public Gui::TaskView::TaskBox +{ + Q_OBJECT + +public: + TaskTransformedMessages(ViewProviderTransformed *transformedView); + ~TaskTransformedMessages(); + + void slotDiagnosis(QString msg); + +private Q_SLOTS: + +protected: + ViewProviderTransformed *transformedView; + Connection connectionDiagnosis; + +private: + QWidget* proxy; + Ui_TaskTransformedMessages* ui; +}; + +} //namespace PartDesignGui + +#endif // GUI_TASKVIEW_TaskTransformedMessages_H diff --git a/src/Mod/PartDesign/Gui/TaskTransformedMessages.ui b/src/Mod/PartDesign/Gui/TaskTransformedMessages.ui new file mode 100644 index 000000000..203f4577b --- /dev/null +++ b/src/Mod/PartDesign/Gui/TaskTransformedMessages.ui @@ -0,0 +1,37 @@ + + + TaskTransformedMessages + + + + 0 + 0 + 228 + 89 + + + + Form + + + + + + + Bitstream Charter + 9 + + + + No message + + + true + + + + + + + + diff --git a/src/Mod/PartDesign/Gui/TaskTransformedParameters.cpp b/src/Mod/PartDesign/Gui/TaskTransformedParameters.cpp index 2b53b150b..8d6123530 100644 --- a/src/Mod/PartDesign/Gui/TaskTransformedParameters.cpp +++ b/src/Mod/PartDesign/Gui/TaskTransformedParameters.cpp @@ -111,8 +111,7 @@ void TaskTransformedParameters::recomputeFeature() // redirect recompute and let the parent decide if recompute has to be blocked parentTask->recomputeFeature(); } else if (!blockUpdate) { - PartDesign::Transformed* pcTransformed = static_cast(TransformedView->getObject()); - pcTransformed->getDocument()->recomputeFeature(pcTransformed); + TransformedView->recomputeFeature(); } } @@ -134,7 +133,7 @@ App::DocumentObject* TaskTransformedParameters::getSupportObject() const return parentTask->getSupportObject(); } else { PartDesign::Transformed* pcTransformed = static_cast(TransformedView->getObject()); - return pcTransformed->getOriginalObject(); + return pcTransformed->getSupportObject(); } } @@ -186,10 +185,13 @@ void TaskTransformedParameters::showOriginals() // TaskDialog //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ -TaskDlgTransformedParameters::TaskDlgTransformedParameters(ViewProviderTransformed *TransformedView) - : TaskDialog(),TransformedView(TransformedView) +TaskDlgTransformedParameters::TaskDlgTransformedParameters(ViewProviderTransformed *TransformedView_) + : TaskDialog(), TransformedView(TransformedView_) { assert(TransformedView); + message = new TaskTransformedMessages(TransformedView); + + Content.push_back(message); } //==== calls from the TaskView =============================================================== diff --git a/src/Mod/PartDesign/Gui/TaskTransformedParameters.h b/src/Mod/PartDesign/Gui/TaskTransformedParameters.h index edff128c7..a531de4f8 100644 --- a/src/Mod/PartDesign/Gui/TaskTransformedParameters.h +++ b/src/Mod/PartDesign/Gui/TaskTransformedParameters.h @@ -28,6 +28,7 @@ #include #include +#include "TaskTransformedMessages.h" #include "ViewProviderTransformed.h" namespace PartDesign { @@ -133,6 +134,7 @@ protected: ViewProviderTransformed *TransformedView; TaskTransformedParameters *parameter; + TaskTransformedMessages *message; }; } //namespace PartDesignGui diff --git a/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp b/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp index d413a8372..9efe20aa4 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp +++ b/src/Mod/PartDesign/Gui/ViewProviderTransformed.cpp @@ -112,3 +112,30 @@ const bool ViewProviderTransformed::checkDlgOpen(TaskDlgTransformedParameters* t // Continue (usually in virtual method setEdit()) return true; } + +void ViewProviderTransformed::recomputeFeature(void) +{ + PartDesign::Transformed* pcTransformed = static_cast(getObject()); + pcTransformed->getDocument()->recomputeFeature(pcTransformed); + const std::vector log = pcTransformed->getDocument()->getRecomputeLog(); + unsigned rejected = pcTransformed->getRejectedTransformations().size(); + QString msg = QString::fromAscii("%1"); + if (rejected > 0) { + msg = QString::fromLatin1("%1
\r\n%2"); + if (rejected == 1) + msg = msg.arg(QObject::tr("One transformed shape does not intersect support")); + else { + msg = msg.arg(QObject::tr("%1 transformed shapes do not intersect support")); + msg = msg.arg(rejected); + } + } + if (log.size() > 0) { + msg = msg.arg(QString::fromLatin1("%1
")); + msg = msg.arg(QString::fromStdString(log.back()->Why)); + } else { + msg = msg.arg(QString::fromLatin1("%1
")); + msg = msg.arg(QObject::tr("Transformation succeeded")); + } + signalDiagnosis(msg); +} + diff --git a/src/Mod/PartDesign/Gui/ViewProviderTransformed.h b/src/Mod/PartDesign/Gui/ViewProviderTransformed.h index 4a29865ee..39b7b099c 100644 --- a/src/Mod/PartDesign/Gui/ViewProviderTransformed.h +++ b/src/Mod/PartDesign/Gui/ViewProviderTransformed.h @@ -48,6 +48,9 @@ public: virtual bool onDelete(const std::vector &); + /// signals if the transformation contains errors + boost::signal signalDiagnosis; + // The feature name of the subclass std::string featureName; @@ -56,6 +59,8 @@ protected: virtual void unsetEdit(int ModNum); const bool checkDlgOpen(TaskDlgTransformedParameters* transformedDlg); +public: + void recomputeFeature(); };