From 51f2a0efc6d880b35224c0e9c952adbf3b6b719a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Tr=C3=B6ger?= Date: Fri, 6 Nov 2015 22:05:37 +0100 Subject: [PATCH] FEM Post: Detail filter infrastructure --- src/Mod/Fem/App/AppFem.cpp | 2 + src/Mod/Fem/App/AppFem.cpp.orig | 14 +- src/Mod/Fem/App/FemPostFilter.cpp | 121 ++++- src/Mod/Fem/App/FemPostFilter.h | 43 +- src/Mod/Fem/App/FemPostFunction.cpp | 34 ++ src/Mod/Fem/App/FemPostFunction.h | 27 +- src/Mod/Fem/App/FemPostPipeline.cpp | 4 + src/Mod/Fem/Gui/AppFemGui.cpp | 4 + src/Mod/Fem/Gui/CMakeLists.txt | 31 ++ src/Mod/Fem/Gui/Command.cpp | 91 +++- src/Mod/Fem/Gui/Command.cpp.orig | 317 +++++++++++- src/Mod/Fem/Gui/PlaneWidget.ui | 196 ++++++++ src/Mod/Fem/Gui/SphereWidget.ui | 164 +++++++ src/Mod/Fem/Gui/TaskPostBoxes.cpp | 452 ++++++++++++++++++ src/Mod/Fem/Gui/TaskPostBoxes.h | 188 ++++++++ src/Mod/Fem/Gui/TaskPostClip.ui | 92 ++++ src/Mod/Fem/Gui/TaskPostDisplay.ui | 180 +++++++ src/Mod/Fem/Gui/TaskPostScalarClip.ui | 215 +++++++++ src/Mod/Fem/Gui/ViewProviderFemPostFilter.cpp | 71 +++ src/Mod/Fem/Gui/ViewProviderFemPostFilter.h | 61 +++ .../Fem/Gui/ViewProviderFemPostFunction.cpp | 283 +++++++++++ src/Mod/Fem/Gui/ViewProviderFemPostFunction.h | 129 ++++- src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp | 171 +++++-- src/Mod/Fem/Gui/ViewProviderFemPostObject.h | 17 +- src/Mod/Fem/Gui/Workbench.cpp | 3 + 25 files changed, 2827 insertions(+), 83 deletions(-) create mode 100644 src/Mod/Fem/Gui/PlaneWidget.ui create mode 100644 src/Mod/Fem/Gui/SphereWidget.ui create mode 100644 src/Mod/Fem/Gui/TaskPostBoxes.cpp create mode 100644 src/Mod/Fem/Gui/TaskPostBoxes.h create mode 100644 src/Mod/Fem/Gui/TaskPostClip.ui create mode 100644 src/Mod/Fem/Gui/TaskPostDisplay.ui create mode 100644 src/Mod/Fem/Gui/TaskPostScalarClip.ui create mode 100644 src/Mod/Fem/Gui/ViewProviderFemPostFilter.cpp create mode 100644 src/Mod/Fem/Gui/ViewProviderFemPostFilter.h diff --git a/src/Mod/Fem/App/AppFem.cpp b/src/Mod/Fem/App/AppFem.cpp index 2ce88a60c..a6fe0ccbc 100644 --- a/src/Mod/Fem/App/AppFem.cpp +++ b/src/Mod/Fem/App/AppFem.cpp @@ -156,8 +156,10 @@ PyMODINIT_FUNC initFem() Fem::FemPostPipeline ::init(); Fem::FemPostFilter ::init(); Fem::FemPostClipFilter ::init(); + Fem::FemPostScalarClipFilter ::init(); Fem::FemPostFunction ::init(); Fem::FemPostFunctionProvider ::init(); Fem::FemPostPlaneFunction ::init(); + Fem::FemPostSphereFunction ::init(); #endif } diff --git a/src/Mod/Fem/App/AppFem.cpp.orig b/src/Mod/Fem/App/AppFem.cpp.orig index b247959bc..4292d473a 100644 --- a/src/Mod/Fem/App/AppFem.cpp.orig +++ b/src/Mod/Fem/App/AppFem.cpp.orig @@ -1,4 +1,4 @@ -<<<<<<< eec6f7aee8b6e5979a799358e2ae69bdc5a7af5b +<<<<<<< 387862dfe753cf0cb062032e97840353b14dcbae /*************************************************************************** * Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) * * * @@ -55,8 +55,12 @@ #include "FemResultObject.h" #include "FemSolverObject.h" + +#ifdef FC_USE_VTK #include "FemPostPipeline.h" #include "FemPostFilter.h" +#include "FemPostFunction.h" +#endif namespace Fem { extern PyObject* initModule(); @@ -152,6 +156,10 @@ PyMODINIT_FUNC initFem() Fem::FemPostObject ::init(); Fem::FemPostPipeline ::init(); Fem::FemPostFilter ::init(); + Fem::FemPostClipFilter ::init(); + Fem::FemPostFunction ::init(); + Fem::FemPostFunctionProvider ::init(); + Fem::FemPostPlaneFunction ::init(); #endif } ======= @@ -313,9 +321,11 @@ PyMODINIT_FUNC initFem() Fem::FemPostPipeline ::init(); Fem::FemPostFilter ::init(); Fem::FemPostClipFilter ::init(); + Fem::FemPostScalarClipFilter ::init(); Fem::FemPostFunction ::init(); Fem::FemPostFunctionProvider ::init(); Fem::FemPostPlaneFunction ::init(); + Fem::FemPostSphereFunction ::init(); #endif } ->>>>>>> Basic implementation of filter framework +>>>>>>> Detail filter infrastructure diff --git a/src/Mod/Fem/App/FemPostFilter.cpp b/src/Mod/Fem/App/FemPostFilter.cpp index 7950009e8..92d5492df 100644 --- a/src/Mod/Fem/App/FemPostFilter.cpp +++ b/src/Mod/Fem/App/FemPostFilter.cpp @@ -30,6 +30,8 @@ #include "FemPostPipeline.h" #include #include +#include +#include using namespace Fem; using namespace App; @@ -44,6 +46,9 @@ FemPostFilter::FemPostFilter() FemPostFilter::~FemPostFilter() { + //we need to make sure that all vtk filters are disconnected + //as the would stay alive and connected otherwise + clearInput(); } bool FemPostFilter::valid() { @@ -173,11 +178,11 @@ FemPostClipFilter::FemPostClipFilter(void) : FemPostFilter() { ADD_PROPERTY_TYPE(Function, (0), "Clip", App::Prop_None, "The function object which defines the clip regions"); ADD_PROPERTY_TYPE(InsideOut, (false), "Clip", App::Prop_None, "Invert the clip direction"); ADD_PROPERTY_TYPE(CutCells, (false), "Clip", App::Prop_None, "Decides if cells are cuttet and interpolated or if the cells are kept as a whole"); - + polyDataSource = vtkGeometryFilter::New(); FilterPipeline clip; - m_clipper = vtkClipDataSet::New(); + m_clipper = vtkTableBasedClipDataSet::New(); clip.source = m_clipper; clip.target = m_clipper; clip.visualisation = m_clipper; @@ -224,3 +229,115 @@ void FemPostClipFilter::onChanged(const Property* prop) { } + + +PROPERTY_SOURCE(Fem::FemPostScalarClipFilter, Fem::FemPostFilter) + +FemPostScalarClipFilter::FemPostScalarClipFilter(void) : FemPostFilter() { + + ADD_PROPERTY_TYPE(Value, (0), "Clip", App::Prop_None, "The scalar value used to clip the selected field"); + ADD_PROPERTY_TYPE(Scalars, (long(0)), "Clip", App::Prop_None, "The field used to clip"); + ADD_PROPERTY_TYPE(InsideOut, (false), "Clip", App::Prop_None, "Invert the clip direction"); + + Value.setConstraints(&m_constraints); + + polyDataSource = vtkGeometryFilter::New(); + + FilterPipeline clip; + m_clipper = vtkTableBasedClipDataSet::New(); + clip.source = m_clipper; + clip.target = m_clipper; + clip.visualisation = m_clipper; + addFilterPipeline(clip, "clip"); + setActiveFilterPipeline("clip"); +} + +FemPostScalarClipFilter::~FemPostScalarClipFilter() { + +} + +DocumentObjectExecReturn* FemPostScalarClipFilter::execute(void) { + + //update the available fields and set the correct input field data for clipping + if(!isConnected()) + return StdReturn; + + std::string val; + if(m_scalarFields.getEnums() && Scalars.getValue() >= 0) + val = Scalars.getValueAsString(); + + std::vector array; + + vtkDataObject* data; + if(hasInputAlgorithmConnected()) { + getConnectedInputAlgorithm()->Update(); + data = getConnectedInputAlgorithm()->GetOutputDataObject(0); + } + else + data = getConnectedInputData(); + + vtkDataSet* dset = dynamic_cast(data); + if(!dset) + return StdReturn; + + vtkPointData* pd = dset->GetPointData(); + + for(int i=0; iGetNumberOfArrays(); ++i) { + if(pd->GetArray(i)->GetNumberOfComponents()==1) + array.push_back(pd->GetArrayName(i)); + } + + App::Enumeration empty; + Scalars.setValue(empty); + m_scalarFields.setEnums(array); + Scalars.setValue(m_scalarFields); + + std::vector::iterator it = std::find(array.begin(), array.end(), val); + if(!val.empty() && it != array.end()) + Scalars.setValue(val.c_str()); + + //recalculate the filter + return Fem::FemPostFilter::execute(); +} + + +void FemPostScalarClipFilter::onChanged(const Property* prop) { + + if(prop == &Value) { + m_clipper->SetValue(Value.getValue()); + } + else if(prop == &InsideOut) { + m_clipper->SetInsideOut(InsideOut.getValue()); + } + else if(prop == &Scalars && (Scalars.getValue() >= 0)) { + m_clipper->SetInputArrayToProcess(0, 0, 0, + vtkDataObject::FIELD_ASSOCIATION_POINTS, Scalars.getValueAsString() ); + setConstraintForField(); + } + + Fem::FemPostFilter::onChanged(prop); +} + +void FemPostScalarClipFilter::setConstraintForField() { + + vtkDataObject* data; + if(hasInputAlgorithmConnected()) { + getConnectedInputAlgorithm()->Update(); + data = getConnectedInputAlgorithm()->GetOutputDataObject(0); + } + else + data = getConnectedInputData(); + + vtkDataSet* dset = dynamic_cast(data); + if(!dset) + return; + + vtkDataArray* pdata = dset->GetPointData()->GetArray(Scalars.getValueAsString()); + double p[2]; + pdata->GetRange(p); + m_constraints.LowerBound = p[0]; + m_constraints.UpperBound = p[1]; + m_constraints.StepSize = (p[1]-p[0])/100.; +} + + diff --git a/src/Mod/Fem/App/FemPostFilter.h b/src/Mod/Fem/App/FemPostFilter.h index 8b2e7e939..5bd209067 100644 --- a/src/Mod/Fem/App/FemPostFilter.h +++ b/src/Mod/Fem/App/FemPostFilter.h @@ -25,9 +25,10 @@ #define Fem_FemPostFilter_H #include "FemPostObject.h" +#include #include -#include +#include #include #include #include @@ -92,18 +93,50 @@ public: FemPostClipFilter(void); virtual ~FemPostClipFilter(); - App::PropertyLink Function; - App::PropertyBool InsideOut; - App::PropertyBool CutCells; + App::PropertyLink Function; + App::PropertyBool InsideOut; + App::PropertyBool CutCells; + + virtual const char* getViewProviderName(void) const { + return "FemGui::ViewProviderFemPostClip"; + } protected: virtual void onChanged(const App::Property* prop); private: - vtkSmartPointer m_clipper; + vtkSmartPointer m_clipper; vtkSmartPointer m_extractor; }; + +class AppFemExport FemPostScalarClipFilter : public FemPostFilter { + + PROPERTY_HEADER(Fem::FemPostScalarClipFilter); + +public: + FemPostScalarClipFilter(void); + virtual ~FemPostScalarClipFilter(); + + App::PropertyBool InsideOut; + App::PropertyFloatConstraint Value; + App::PropertyEnumeration Scalars; + + virtual const char* getViewProviderName(void) const { + return "FemGui::ViewProviderFemPostScalarClip"; + } + +protected: + virtual App::DocumentObjectExecReturn* execute(void); + virtual void onChanged(const App::Property* prop); + void setConstraintForField(); + +private: + vtkSmartPointer m_clipper; + App::Enumeration m_scalarFields; + App::PropertyFloatConstraint::Constraints m_constraints; +}; + } //namespace Fem diff --git a/src/Mod/Fem/App/FemPostFunction.cpp b/src/Mod/Fem/App/FemPostFunction.cpp index d1172eacd..1c7749209 100644 --- a/src/Mod/Fem/App/FemPostFunction.cpp +++ b/src/Mod/Fem/App/FemPostFunction.cpp @@ -96,3 +96,37 @@ void FemPostPlaneFunction::onChanged(const Property* prop) { Fem::FemPostFunction::onChanged(prop); } + + + + +PROPERTY_SOURCE(Fem::FemPostSphereFunction, Fem::FemPostFunction) + +FemPostSphereFunction::FemPostSphereFunction(void): FemPostFunction() { + + ADD_PROPERTY(Radius,(5)); + ADD_PROPERTY(Center,(Base::Vector3d(1.0,0.0,0.0))); + + m_sphere = vtkSphere::New(); + m_implicit = m_sphere; + + m_sphere->SetCenter(0., 0., 0.); + m_sphere->SetRadius(5); +} + +FemPostSphereFunction::~FemPostSphereFunction() { + +} + +void FemPostSphereFunction::onChanged(const Property* prop) { + + if(prop == &Center) { + const Base::Vector3d& vec = Center.getValue(); + m_sphere->SetCenter(vec[0], vec[1], vec[2]); + } + else if(prop == &Radius) { + m_sphere->SetRadius(Radius.getValue()); + } + + Fem::FemPostFunction::onChanged(prop); +} diff --git a/src/Mod/Fem/App/FemPostFunction.h b/src/Mod/Fem/App/FemPostFunction.h index 81e90fed0..58f3a232e 100644 --- a/src/Mod/Fem/App/FemPostFunction.h +++ b/src/Mod/Fem/App/FemPostFunction.h @@ -25,11 +25,12 @@ #define Fem_FemPostFunction_H #include "FemPostObject.h" +#include #include #include #include -#include +#include namespace Fem { @@ -103,6 +104,30 @@ protected: vtkSmartPointer m_plane; }; +//////////////////////////////////////////////////////////////////////////////////////////// + +class AppFemExport FemPostSphereFunction : public FemPostFunction +{ + PROPERTY_HEADER(Fem::FemPostSphereFunction); + +public: + + FemPostSphereFunction(void); + virtual ~FemPostSphereFunction(); + + App::PropertyDistance Radius; + App::PropertyVectorDistance Center; + + virtual const char* getViewProviderName(void) const { + return "FemGui::ViewProviderFemPostSphereFunction"; + } + +protected: + virtual void onChanged(const App::Property* prop); + + vtkSmartPointer m_sphere; +}; + } //namespace Fem diff --git a/src/Mod/Fem/App/FemPostPipeline.cpp b/src/Mod/Fem/App/FemPostPipeline.cpp index 608f6fc69..dc5c2ff8c 100644 --- a/src/Mod/Fem/App/FemPostPipeline.cpp +++ b/src/Mod/Fem/App/FemPostPipeline.cpp @@ -134,6 +134,10 @@ void FemPostPipeline::onChanged(const Property* prop) //we check if all connections are right and add new ones if needed std::vector objs = Filter.getValues(); + + if(objs.empty()) + return; + std::vector::iterator it = objs.begin(); FemPostFilter* filter = static_cast(*it); diff --git a/src/Mod/Fem/Gui/AppFemGui.cpp b/src/Mod/Fem/Gui/AppFemGui.cpp index 1b8340587..34832cc6c 100644 --- a/src/Mod/Fem/Gui/AppFemGui.cpp +++ b/src/Mod/Fem/Gui/AppFemGui.cpp @@ -59,6 +59,7 @@ #include "ViewProviderFemPostObject.h" #include "ViewProviderFemPostPipeline.h" #include "ViewProviderFemPostFunction.h" +#include "ViewProviderFemPostFilter.h" #endif #ifdef FC_USE_VTK @@ -126,6 +127,9 @@ PyMODINIT_FUNC initFemGui() FemGui::ViewProviderFemPostFunction ::init(); FemGui::ViewProviderFemPostFunctionProvider::init(); FemGui::ViewProviderFemPostPlaneFunction ::init(); + FemGui::ViewProviderFemPostSphereFunction ::init(); + FemGui::ViewProviderFemPostClip ::init(); + FemGui::ViewProviderFemPostScalarClip ::init(); #endif diff --git a/src/Mod/Fem/Gui/CMakeLists.txt b/src/Mod/Fem/Gui/CMakeLists.txt index 9d4d9b9f7..fcb10dabc 100755 --- a/src/Mod/Fem/Gui/CMakeLists.txt +++ b/src/Mod/Fem/Gui/CMakeLists.txt @@ -67,6 +67,13 @@ set(FemGui_MOC_HDRS TaskDlgAnalysis.h TaskDlgMeshShapeNetgen.h ) +if(BUILD_FEM_VTK) + set(FemGui_MOC_HDRS + ${FemGui_MOC_HDRS} + TaskPostBoxes.h + ViewProviderFemPostFunction.h + ) +endif(BUILD_FEM_VTK) fc_wrap_cpp(FemGui_MOC_SRCS ${FemGui_MOC_HDRS}) SOURCE_GROUP("Moc" FILES ${FemGui_MOC_SRCS}) @@ -84,6 +91,16 @@ set(FemGui_UIC_SRCS TaskAnalysisInfo.ui TaskDriver.ui ) +if(BUILD_FEM_VTK) + set(FemGui_UIC_SRCS + ${FemGui_UIC_SRCS} + TaskPostDisplay.ui + TaskPostClip.ui + TaskPostScalarClip.ui + PlaneWidget.ui + SphereWidget.ui + ) +endif(BUILD_FEM_VTK) qt4_wrap_ui(FemGui_UIC_HDRS ${FemGui_UIC_SRCS}) SET(FemGui_DLG_SRCS @@ -179,6 +196,18 @@ SET(FemGui_SRCS_TaskBoxes TaskTetParameter.cpp TaskTetParameter.h ) +if(BUILD_FEM_VTK) + SET(FemGui_SRCS_TaskBoxes + ${FemGui_SRCS_TaskBoxes} + PlaneWidget.ui + SphereWidget.ui + TaskPostClip.ui + TaskPostScalarClip.ui + TaskPostDisplay.ui + TaskPostBoxes.h + TaskPostBoxes.cpp + ) +endif(BUILD_FEM_VTK) SOURCE_GROUP("Task_Boxes" FILES ${FemGui_SRCS_TaskBoxes}) SET(FemGui_SRCS_TaskDlg @@ -217,6 +246,8 @@ if(BUILD_FEM_VTK) ViewProviderFemPostPipeline.cpp ViewProviderFemPostFunction.h ViewProviderFemPostFunction.cpp + ViewProviderFemPostFilter.h + ViewProviderFemPostFilter.cpp ) SOURCE_GROUP("PostObjects" FILES ${FemGui_SRCS_Post}) endif(BUILD_FEM_VTK) diff --git a/src/Mod/Fem/Gui/Command.cpp b/src/Mod/Fem/Gui/Command.cpp index e5fae8ca8..9a53ad21c 100644 --- a/src/Mod/Fem/Gui/Command.cpp +++ b/src/Mod/Fem/Gui/Command.cpp @@ -775,8 +775,8 @@ CmdFemPostCreateClipFilter::CmdFemPostCreateClipFilter() { sAppModule = "Fem"; sGroup = QT_TR_NOOP("Fem"); - sMenuText = QT_TR_NOOP("Define/create a clip filter for a post processing pipeline..."); - sToolTipText = QT_TR_NOOP("Define/create a clip filter for a post processing pipeline..."); + sMenuText = QT_TR_NOOP("Define/create a clip filter which uses functions to define the cliped region"); + sToolTipText = QT_TR_NOOP("Define/create a clip filter which uses functions to define the cliped region"); sWhatsThis = "Fem_PostCreateClipFilter"; sStatusTip = sToolTipText; sPixmap = "fem-fem-mesh-create-node-by-poly"; @@ -784,10 +784,9 @@ CmdFemPostCreateClipFilter::CmdFemPostCreateClipFilter() void CmdFemPostCreateClipFilter::activated(int iMsg) { - Gui::SelectionFilter ObjectFilter("SELECT Fem::FemPostPipeline COUNT 1"); - - if (ObjectFilter.match()) { - Fem::FemPostPipeline *pipeline = static_cast(ObjectFilter.Result[0][0].getObject()); + std::vector pipelines = App::GetApplication().getActiveDocument()->getObjectsOfType(); + if (!pipelines.empty()) { + Fem::FemPostPipeline *pipeline = pipelines.front(); std::string FeatName = getUniqueObjectName("Clip"); @@ -799,6 +798,8 @@ void CmdFemPostCreateClipFilter::activated(int iMsg) doCommand(Doc,"del __list__"); this->updateActive(); + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); + } else { QMessageBox::warning(Gui::getMainWindow(), @@ -812,6 +813,50 @@ bool CmdFemPostCreateClipFilter::isActive(void) return hasActiveDocument(); } +DEF_STD_CMD_A(CmdFemPostCreateScalarClipFilter); + +CmdFemPostCreateScalarClipFilter::CmdFemPostCreateScalarClipFilter() + : Command("Fem_PostCreateScalarClipFilter") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Define/create a clip filter which clips a field with a scalar value"); + sToolTipText = QT_TR_NOOP("Define/create a clip filter which clips a field with a scalar value"); + sWhatsThis = "Fem_PostCreateScalarClipFilter"; + sStatusTip = sToolTipText; + sPixmap = "fem-fem-mesh-create-node-by-poly"; +} + +void CmdFemPostCreateScalarClipFilter::activated(int iMsg) +{ + std::vector pipelines = App::GetApplication().getActiveDocument()->getObjectsOfType(); + if (!pipelines.empty()) { + Fem::FemPostPipeline *pipeline = pipelines.front(); + + std::string FeatName = getUniqueObjectName("ScalarClip"); + + openCommand("Create scalar clip filter"); + doCommand(Doc,"App.activeDocument().addObject('Fem::FemPostScalarClipFilter','%s')",FeatName.c_str()); + doCommand(Doc,"__list__ = App.ActiveDocument.%s.Filter", pipeline->getNameInDocument()); + doCommand(Doc,"__list__.append(App.ActiveDocument.%s)", FeatName.c_str()); + doCommand(Doc,"App.ActiveDocument.%s.Filter = __list__", pipeline->getNameInDocument()); + doCommand(Doc,"del __list__"); + + this->updateActive(); + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); + } + else { + QMessageBox::warning(Gui::getMainWindow(), + qApp->translate("CmdFemPostCreateScalarClipFilter", "Wrong selection"), + qApp->translate("CmdFemPostCreateScalarClipFilter", "Select a pipeline, please.")); + } +} + +bool CmdFemPostCreateScalarClipFilter::isActive(void) +{ + return hasActiveDocument(); +} + // ##################################################################################################### @@ -826,31 +871,30 @@ CmdFemPostFunctions::CmdFemPostFunctions() sToolTipText = QT_TR_NOOP("Functions for use in postprocessing filter..."); sWhatsThis = "Fem_PostCreateFunctions"; sStatusTip = sToolTipText; + eType = eType|ForEdit; } void CmdFemPostFunctions::activated(int iMsg) { - Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); + std::string name; if (iMsg==0) name = "Plane"; else if (iMsg==1) - rcCmdMgr.runCommandByName("Part_JoinEmbed"); - else if (iMsg==2) - rcCmdMgr.runCommandByName("Part_JoinCutout"); + name = "Sphere"; else return; //create the object - Gui::SelectionFilter ObjectFilter("SELECT Fem::FemPostPipeline COUNT 1"); - if (ObjectFilter.match()) { - Fem::FemPostPipeline *pipeline = static_cast(ObjectFilter.Result[0][0].getObject()); + std::vector pipelines = App::GetApplication().getActiveDocument()->getObjectsOfType(); + if (!pipelines.empty()) { + Fem::FemPostPipeline *pipeline = pipelines.front(); openCommand("Create function"); //check if the pipeline has a filter provider and add one if needed Fem::FemPostFunctionProvider* provider; - if(!pipeline->Function.getValue() || pipeline->Function.getValue()->getTypeId() == Fem::FemPostFunctionProvider::getClassTypeId()) { + if(!pipeline->Function.getValue() || pipeline->Function.getValue()->getTypeId() != Fem::FemPostFunctionProvider::getClassTypeId()) { std::string FuncName = getUniqueObjectName("Functions"); doCommand(Doc,"App.ActiveDocument.addObject('Fem::FemPostFunctionProvider','%s')", FuncName.c_str()); doCommand(Doc,"App.ActiveDocument.%s.Function = App.ActiveDocument.%s", pipeline->getNameInDocument(), FuncName.c_str()); @@ -868,6 +912,7 @@ void CmdFemPostFunctions::activated(int iMsg) doCommand(Doc,"del __list__"); this->updateActive(); + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); } else { QMessageBox::warning(Gui::getMainWindow(), @@ -891,7 +936,7 @@ Gui::Action * CmdFemPostFunctions::createAction(void) applyCommandData(this->className(), pcAction); QAction* cmd0 = pcAction->addAction(QString()); - //cmd0->setIcon(Gui::BitmapFactory().pixmap("Part_JoinConnect")); + pcAction->addAction(QString()); _pcAction = pcAction; languageChange(); @@ -912,10 +957,15 @@ void CmdFemPostFunctions::languageChange() Gui::ActionGroup* pcAction = qobject_cast(_pcAction); QList a = pcAction->actions(); - QAction* cmd0 = a[0]; - cmd0->setText(QApplication::translate("CmdFemPostFunctions","Plane")); - cmd0->setToolTip(QApplication::translate("Fem_PostCreateFunctions","Create a plane function, defined by its orgin and normal")); - cmd0->setStatusTip(cmd0->toolTip()); + QAction* cmd = a[0]; + cmd->setText(QApplication::translate("CmdFemPostFunctions","Plane")); + cmd->setToolTip(QApplication::translate("Fem_PostCreateFunctions","Create a plane function, defined by its orgin and normal")); + cmd->setStatusTip(cmd->toolTip()); + + cmd = a[1]; + cmd->setText(QApplication::translate("CmdFemPostFunctions","Sphere")); + cmd->setToolTip(QApplication::translate("Fem_PostCreateFunctions","Create a phere function, defined by its center and radius")); + cmd->setStatusTip(cmd->toolTip()); } @@ -927,6 +977,7 @@ bool CmdFemPostFunctions::isActive(void) return false; } + DEF_STD_CMD_AC(CmdFemPostApllyChanges); CmdFemPostApllyChanges::CmdFemPostApllyChanges() @@ -939,6 +990,7 @@ CmdFemPostApllyChanges::CmdFemPostApllyChanges() sWhatsThis = "Fem_PostApplyChanges"; sStatusTip = sToolTipText; sPixmap = "view-refresh"; + eType = eType|ForEdit; } void CmdFemPostApllyChanges::activated(int iMsg) @@ -992,6 +1044,7 @@ void CreateFemCommands(void) #ifdef FC_USE_VTK rcCmdMgr.addCommand(new CmdFemPostCreateClipFilter); + rcCmdMgr.addCommand(new CmdFemPostCreateScalarClipFilter); rcCmdMgr.addCommand(new CmdFemPostFunctions); rcCmdMgr.addCommand(new CmdFemPostApllyChanges); #endif diff --git a/src/Mod/Fem/Gui/Command.cpp.orig b/src/Mod/Fem/Gui/Command.cpp.orig index e891aab6d..ee2618df2 100644 --- a/src/Mod/Fem/Gui/Command.cpp.orig +++ b/src/Mod/Fem/Gui/Command.cpp.orig @@ -1,4 +1,4 @@ -<<<<<<< eec6f7aee8b6e5979a799358e2ae69bdc5a7af5b +<<<<<<< 387862dfe753cf0cb062032e97840353b14dcbae /*************************************************************************** * Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) * * * @@ -27,6 +27,7 @@ # include # include # include +#include #endif #include @@ -48,6 +49,7 @@ #include #include #include +#include #include #include @@ -59,9 +61,12 @@ #include #include #include - #include "ActiveAnalysisObserver.h" +#ifdef FC_USE_VTK +#include +#endif + using namespace std; @@ -758,6 +763,215 @@ bool CmdFemCreateNodesSet::isActive(void) return hasActiveDocument(); } + +// ##################################################################################################### + +#ifdef FC_USE_VTK + + +DEF_STD_CMD_A(CmdFemPostCreateClipFilter); + +CmdFemPostCreateClipFilter::CmdFemPostCreateClipFilter() + : Command("Fem_PostCreateClipFilter") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Define/create a clip filter for a post processing pipeline..."); + sToolTipText = QT_TR_NOOP("Define/create a clip filter for a post processing pipeline..."); + sWhatsThis = "Fem_PostCreateClipFilter"; + sStatusTip = sToolTipText; + sPixmap = "fem-fem-mesh-create-node-by-poly"; +} + +void CmdFemPostCreateClipFilter::activated(int iMsg) +{ + Gui::SelectionFilter ObjectFilter("SELECT Fem::FemPostPipeline COUNT 1"); + + if (ObjectFilter.match()) { + Fem::FemPostPipeline *pipeline = static_cast(ObjectFilter.Result[0][0].getObject()); + + std::string FeatName = getUniqueObjectName("Clip"); + + openCommand("Create clip filter"); + doCommand(Doc,"App.activeDocument().addObject('Fem::FemPostClipFilter','%s')",FeatName.c_str()); + doCommand(Doc,"__list__ = App.ActiveDocument.%s.Filter", pipeline->getNameInDocument()); + doCommand(Doc,"__list__.append(App.ActiveDocument.%s)", FeatName.c_str()); + doCommand(Doc,"App.ActiveDocument.%s.Filter = __list__", pipeline->getNameInDocument()); + doCommand(Doc,"del __list__"); + + this->updateActive(); + } + else { + QMessageBox::warning(Gui::getMainWindow(), + qApp->translate("CmdFemPostCreateClipFilter", "Wrong selection"), + qApp->translate("CmdFemPostCreateClipFilter", "Select a pipeline, please.")); + } +} + +bool CmdFemPostCreateClipFilter::isActive(void) +{ + return hasActiveDocument(); +} + +// ##################################################################################################### + + +DEF_STD_CMD_ACL(CmdFemPostFunctions); + +CmdFemPostFunctions::CmdFemPostFunctions() + : Command("Fem_PostCreateFunctions") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Functions for use in postprocessing filter..."); + sToolTipText = QT_TR_NOOP("Functions for use in postprocessing filter..."); + sWhatsThis = "Fem_PostCreateFunctions"; + sStatusTip = sToolTipText; +} + +void CmdFemPostFunctions::activated(int iMsg) +{ + Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); + std::string name; + if (iMsg==0) + name = "Plane"; + else if (iMsg==1) + rcCmdMgr.runCommandByName("Part_JoinEmbed"); + else if (iMsg==2) + rcCmdMgr.runCommandByName("Part_JoinCutout"); + else + return; + + //create the object + Gui::SelectionFilter ObjectFilter("SELECT Fem::FemPostPipeline COUNT 1"); + if (ObjectFilter.match()) { + Fem::FemPostPipeline *pipeline = static_cast(ObjectFilter.Result[0][0].getObject()); + + openCommand("Create function"); + + //check if the pipeline has a filter provider and add one if needed + Fem::FemPostFunctionProvider* provider; + if(!pipeline->Function.getValue() || pipeline->Function.getValue()->getTypeId() == Fem::FemPostFunctionProvider::getClassTypeId()) { + std::string FuncName = getUniqueObjectName("Functions"); + doCommand(Doc,"App.ActiveDocument.addObject('Fem::FemPostFunctionProvider','%s')", FuncName.c_str()); + doCommand(Doc,"App.ActiveDocument.%s.Function = App.ActiveDocument.%s", pipeline->getNameInDocument(), FuncName.c_str()); + provider = static_cast(getDocument()->getObject(FuncName.c_str())); + } + else + provider = static_cast(pipeline->Function.getValue()); + + //build the object + std::string FeatName = getUniqueObjectName(name.c_str()); + doCommand(Doc,"App.activeDocument().addObject('Fem::FemPost%sFunction','%s')", name.c_str(), FeatName.c_str()); + doCommand(Doc,"__list__ = App.ActiveDocument.%s.Functions", provider->getNameInDocument()); + doCommand(Doc,"__list__.append(App.ActiveDocument.%s)", FeatName.c_str()); + doCommand(Doc,"App.ActiveDocument.%s.Functions = __list__", provider->getNameInDocument()); + doCommand(Doc,"del __list__"); + + this->updateActive(); + } + else { + QMessageBox::warning(Gui::getMainWindow(), + qApp->translate("CmdFemPostCreateClipFilter", "Wrong selection"), + qApp->translate("CmdFemPostCreateClipFilter", "Select a pipeline, please.")); + } + + // Since the default icon is reset when enabing/disabling the command we have + // to explicitly set the icon of the used command. + Gui::ActionGroup* pcAction = qobject_cast(_pcAction); + QList a = pcAction->actions(); + + assert(iMsg < a.size()); + pcAction->setIcon(a[iMsg]->icon()); +} + +Gui::Action * CmdFemPostFunctions::createAction(void) +{ + Gui::ActionGroup* pcAction = new Gui::ActionGroup(this, Gui::getMainWindow()); + pcAction->setDropDownMenu(true); + applyCommandData(this->className(), pcAction); + + QAction* cmd0 = pcAction->addAction(QString()); + //cmd0->setIcon(Gui::BitmapFactory().pixmap("Part_JoinConnect")); + + _pcAction = pcAction; + languageChange(); + + pcAction->setIcon(cmd0->icon()); + int defaultId = 0; + pcAction->setProperty("defaultAction", QVariant(defaultId)); + + return pcAction; +} + +void CmdFemPostFunctions::languageChange() +{ + Command::languageChange(); + + if (!_pcAction) + return; + Gui::ActionGroup* pcAction = qobject_cast(_pcAction); + QList a = pcAction->actions(); + + QAction* cmd0 = a[0]; + cmd0->setText(QApplication::translate("CmdFemPostFunctions","Plane")); + cmd0->setToolTip(QApplication::translate("Fem_PostCreateFunctions","Create a plane function, defined by its orgin and normal")); + cmd0->setStatusTip(cmd0->toolTip()); + +} + +bool CmdFemPostFunctions::isActive(void) +{ + if (getActiveGuiDocument()) + return true; + else + return false; +} + +DEF_STD_CMD_AC(CmdFemPostApllyChanges); + +CmdFemPostApllyChanges::CmdFemPostApllyChanges() + : Command("Fem_PostApplyChanges") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Apply changes to parameters directly and not on recompute only..."); + sToolTipText = QT_TR_NOOP("Apply changes to parameters directly and not on recompute only..."); + sWhatsThis = "Fem_PostApplyChanges"; + sStatusTip = sToolTipText; + sPixmap = "view-refresh"; +} + +void CmdFemPostApllyChanges::activated(int iMsg) +{ + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Fem"); + + if (iMsg == 1) + hGrp->SetBool("PostAutoRecompute", true); + else + hGrp->SetBool("PostAutoRecompute", false); +} + +bool CmdFemPostApllyChanges::isActive(void) +{ + if (getActiveGuiDocument()) + return true; + else + return false; +} + +Gui::Action * CmdFemPostApllyChanges::createAction(void) +{ + Gui::Action *pcAction = Command::createAction(); + pcAction->setCheckable(true); + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Fem"); + pcAction->setChecked(hGrp->GetBool("PostAutoRecompute", false)); + + return pcAction; +} + +#endif + //-------------------------------------------------------------------------------------- @@ -776,6 +990,12 @@ void CreateFemCommands(void) rcCmdMgr.addCommand(new CmdFemConstraintGear()); rcCmdMgr.addCommand(new CmdFemConstraintPulley()); rcCmdMgr.addCommand(new CmdFemConstraintDisplacement()); + +#ifdef FC_USE_VTK + rcCmdMgr.addCommand(new CmdFemPostCreateClipFilter); + rcCmdMgr.addCommand(new CmdFemPostFunctions); + rcCmdMgr.addCommand(new CmdFemPostApllyChanges); +#endif } ======= /*************************************************************************** @@ -1555,8 +1775,8 @@ CmdFemPostCreateClipFilter::CmdFemPostCreateClipFilter() { sAppModule = "Fem"; sGroup = QT_TR_NOOP("Fem"); - sMenuText = QT_TR_NOOP("Define/create a clip filter for a post processing pipeline..."); - sToolTipText = QT_TR_NOOP("Define/create a clip filter for a post processing pipeline..."); + sMenuText = QT_TR_NOOP("Define/create a clip filter which uses functions to define the cliped region"); + sToolTipText = QT_TR_NOOP("Define/create a clip filter which uses functions to define the cliped region"); sWhatsThis = "Fem_PostCreateClipFilter"; sStatusTip = sToolTipText; sPixmap = "fem-fem-mesh-create-node-by-poly"; @@ -1564,10 +1784,9 @@ CmdFemPostCreateClipFilter::CmdFemPostCreateClipFilter() void CmdFemPostCreateClipFilter::activated(int iMsg) { - Gui::SelectionFilter ObjectFilter("SELECT Fem::FemPostPipeline COUNT 1"); - - if (ObjectFilter.match()) { - Fem::FemPostPipeline *pipeline = static_cast(ObjectFilter.Result[0][0].getObject()); + std::vector pipelines = App::GetApplication().getActiveDocument()->getObjectsOfType(); + if (!pipelines.empty()) { + Fem::FemPostPipeline *pipeline = pipelines.front(); std::string FeatName = getUniqueObjectName("Clip"); @@ -1579,6 +1798,8 @@ void CmdFemPostCreateClipFilter::activated(int iMsg) doCommand(Doc,"del __list__"); this->updateActive(); + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); + } else { QMessageBox::warning(Gui::getMainWindow(), @@ -1592,6 +1813,50 @@ bool CmdFemPostCreateClipFilter::isActive(void) return hasActiveDocument(); } +DEF_STD_CMD_A(CmdFemPostCreateScalarClipFilter); + +CmdFemPostCreateScalarClipFilter::CmdFemPostCreateScalarClipFilter() + : Command("Fem_PostCreateScalarClipFilter") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Define/create a clip filter which clips a field with a scalar value"); + sToolTipText = QT_TR_NOOP("Define/create a clip filter which clips a field with a scalar value"); + sWhatsThis = "Fem_PostCreateScalarClipFilter"; + sStatusTip = sToolTipText; + sPixmap = "fem-fem-mesh-create-node-by-poly"; +} + +void CmdFemPostCreateScalarClipFilter::activated(int iMsg) +{ + std::vector pipelines = App::GetApplication().getActiveDocument()->getObjectsOfType(); + if (!pipelines.empty()) { + Fem::FemPostPipeline *pipeline = pipelines.front(); + + std::string FeatName = getUniqueObjectName("ScalarClip"); + + openCommand("Create scalar clip filter"); + doCommand(Doc,"App.activeDocument().addObject('Fem::FemPostScalarClipFilter','%s')",FeatName.c_str()); + doCommand(Doc,"__list__ = App.ActiveDocument.%s.Filter", pipeline->getNameInDocument()); + doCommand(Doc,"__list__.append(App.ActiveDocument.%s)", FeatName.c_str()); + doCommand(Doc,"App.ActiveDocument.%s.Filter = __list__", pipeline->getNameInDocument()); + doCommand(Doc,"del __list__"); + + this->updateActive(); + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); + } + else { + QMessageBox::warning(Gui::getMainWindow(), + qApp->translate("CmdFemPostCreateScalarClipFilter", "Wrong selection"), + qApp->translate("CmdFemPostCreateScalarClipFilter", "Select a pipeline, please.")); + } +} + +bool CmdFemPostCreateScalarClipFilter::isActive(void) +{ + return hasActiveDocument(); +} + // ##################################################################################################### @@ -1606,31 +1871,30 @@ CmdFemPostFunctions::CmdFemPostFunctions() sToolTipText = QT_TR_NOOP("Functions for use in postprocessing filter..."); sWhatsThis = "Fem_PostCreateFunctions"; sStatusTip = sToolTipText; + eType = eType|ForEdit; } void CmdFemPostFunctions::activated(int iMsg) { - Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); + std::string name; if (iMsg==0) name = "Plane"; else if (iMsg==1) - rcCmdMgr.runCommandByName("Part_JoinEmbed"); - else if (iMsg==2) - rcCmdMgr.runCommandByName("Part_JoinCutout"); + name = "Sphere"; else return; //create the object - Gui::SelectionFilter ObjectFilter("SELECT Fem::FemPostPipeline COUNT 1"); - if (ObjectFilter.match()) { - Fem::FemPostPipeline *pipeline = static_cast(ObjectFilter.Result[0][0].getObject()); + std::vector pipelines = App::GetApplication().getActiveDocument()->getObjectsOfType(); + if (!pipelines.empty()) { + Fem::FemPostPipeline *pipeline = pipelines.front(); openCommand("Create function"); //check if the pipeline has a filter provider and add one if needed Fem::FemPostFunctionProvider* provider; - if(!pipeline->Function.getValue() || pipeline->Function.getValue()->getTypeId() == Fem::FemPostFunctionProvider::getClassTypeId()) { + if(!pipeline->Function.getValue() || pipeline->Function.getValue()->getTypeId() != Fem::FemPostFunctionProvider::getClassTypeId()) { std::string FuncName = getUniqueObjectName("Functions"); doCommand(Doc,"App.ActiveDocument.addObject('Fem::FemPostFunctionProvider','%s')", FuncName.c_str()); doCommand(Doc,"App.ActiveDocument.%s.Function = App.ActiveDocument.%s", pipeline->getNameInDocument(), FuncName.c_str()); @@ -1648,6 +1912,7 @@ void CmdFemPostFunctions::activated(int iMsg) doCommand(Doc,"del __list__"); this->updateActive(); + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); } else { QMessageBox::warning(Gui::getMainWindow(), @@ -1671,7 +1936,7 @@ Gui::Action * CmdFemPostFunctions::createAction(void) applyCommandData(this->className(), pcAction); QAction* cmd0 = pcAction->addAction(QString()); - //cmd0->setIcon(Gui::BitmapFactory().pixmap("Part_JoinConnect")); + pcAction->addAction(QString()); _pcAction = pcAction; languageChange(); @@ -1692,10 +1957,15 @@ void CmdFemPostFunctions::languageChange() Gui::ActionGroup* pcAction = qobject_cast(_pcAction); QList a = pcAction->actions(); - QAction* cmd0 = a[0]; - cmd0->setText(QApplication::translate("CmdFemPostFunctions","Plane")); - cmd0->setToolTip(QApplication::translate("Fem_PostCreateFunctions","Create a plane function, defined by its orgin and normal")); - cmd0->setStatusTip(cmd0->toolTip()); + QAction* cmd = a[0]; + cmd->setText(QApplication::translate("CmdFemPostFunctions","Plane")); + cmd->setToolTip(QApplication::translate("Fem_PostCreateFunctions","Create a plane function, defined by its orgin and normal")); + cmd->setStatusTip(cmd->toolTip()); + + cmd = a[1]; + cmd->setText(QApplication::translate("CmdFemPostFunctions","Sphere")); + cmd->setToolTip(QApplication::translate("Fem_PostCreateFunctions","Create a phere function, defined by its center and radius")); + cmd->setStatusTip(cmd->toolTip()); } @@ -1707,6 +1977,7 @@ bool CmdFemPostFunctions::isActive(void) return false; } + DEF_STD_CMD_AC(CmdFemPostApllyChanges); CmdFemPostApllyChanges::CmdFemPostApllyChanges() @@ -1719,6 +1990,7 @@ CmdFemPostApllyChanges::CmdFemPostApllyChanges() sWhatsThis = "Fem_PostApplyChanges"; sStatusTip = sToolTipText; sPixmap = "view-refresh"; + eType = eType|ForEdit; } void CmdFemPostApllyChanges::activated(int iMsg) @@ -1772,8 +2044,9 @@ void CreateFemCommands(void) #ifdef FC_USE_VTK rcCmdMgr.addCommand(new CmdFemPostCreateClipFilter); + rcCmdMgr.addCommand(new CmdFemPostCreateScalarClipFilter); rcCmdMgr.addCommand(new CmdFemPostFunctions); rcCmdMgr.addCommand(new CmdFemPostApllyChanges); #endif } ->>>>>>> Basic implementation of filter framework +>>>>>>> Detail filter infrastructure diff --git a/src/Mod/Fem/Gui/PlaneWidget.ui b/src/Mod/Fem/Gui/PlaneWidget.ui new file mode 100644 index 000000000..c150cfb5c --- /dev/null +++ b/src/Mod/Fem/Gui/PlaneWidget.ui @@ -0,0 +1,196 @@ + + + PlaneWidget + + + + 0 + 0 + 287 + 84 + + + + Form + + + + 2 + + + 6 + + + 0 + + + + + Origin + + + Qt::AlignCenter + + + + + + + 2 + + + + + + 0 + 0 + + + + + 70 + 0 + + + + -999999999.000000000000000 + + + 999999999.000000000000000 + + + + + + + + 0 + 0 + + + + + 70 + 0 + + + + -999999999.000000000000000 + + + 0.000000000000000 + + + + + + + + 0 + 0 + + + + + 70 + 0 + + + + -999999999.000000000000000 + + + 999999999.000000000000000 + + + + + + + + + Normal + + + Qt::AlignCenter + + + + + + + 2 + + + + + + 0 + 0 + + + + + 70 + 0 + + + + -999999999.000000000000000 + + + 999999999.000000000000000 + + + + + + + + 0 + 0 + + + + + 70 + 0 + + + + -999999999.000000000000000 + + + 999999999.000000000000000 + + + + + + + + 0 + 0 + + + + + 70 + 0 + + + + -999999999.000000000000000 + + + 999999999.000000000000000 + + + + + + + + + + diff --git a/src/Mod/Fem/Gui/SphereWidget.ui b/src/Mod/Fem/Gui/SphereWidget.ui new file mode 100644 index 000000000..1c559ff4d --- /dev/null +++ b/src/Mod/Fem/Gui/SphereWidget.ui @@ -0,0 +1,164 @@ + + + SphereWidget + + + + 0 + 0 + 346 + 84 + + + + Form + + + + 2 + + + 6 + + + 0 + + + + + Radius + + + Qt::AlignCenter + + + + + + + 2 + + + + + + 0 + 0 + + + + + 70 + 0 + + + + false + + + -999999999.000000000000000 + + + 999999999.000000000000000 + + + + + + + + + Center + + + Qt::AlignCenter + + + + + + + 2 + + + + + + 0 + 0 + + + + + 70 + 0 + + + + false + + + -999999999.000000000000000 + + + 999999999.000000000000000 + + + + + + + + 0 + 0 + + + + + 70 + 0 + + + + false + + + -999999999.000000000000000 + + + 999999999.000000000000000 + + + + + + + + 0 + 0 + + + + + 70 + 0 + + + + false + + + -999999999.000000000000000 + + + 999999999.000000000000000 + + + + + + + + + + diff --git a/src/Mod/Fem/Gui/TaskPostBoxes.cpp b/src/Mod/Fem/Gui/TaskPostBoxes.cpp new file mode 100644 index 000000000..91ae9fc6a --- /dev/null +++ b/src/Mod/Fem/Gui/TaskPostBoxes.cpp @@ -0,0 +1,452 @@ +/*************************************************************************** + * Copyright (c) 2015 Stefan Tröger * + * * + * 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_TaskPostDisplay.h" +#include "ui_TaskPostClip.h" +#include "ui_TaskPostScalarClip.h" +#include "TaskPostBoxes.h" +#include "ViewProviderFemPostObject.h" +#include "ViewProviderFemPostFunction.h" +#include "ViewProviderFemPostFilter.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace FemGui; +using namespace Gui; + +//************************************************************************** +//************************************************************************** +// TaskDialog +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TaskDlgPost::TaskDlgPost(Gui::ViewProviderDocumentObject *view,bool newObj) + : TaskDialog(), m_view(view) +{ + assert(view); +} + +TaskDlgPost::~TaskDlgPost() +{ + +} + +QDialogButtonBox::StandardButtons TaskDlgPost::getStandardButtons(void) const { + + //check if we only have gui task boxes + bool guionly = true; + for(std::vector::const_iterator it = m_boxes.begin(); it != m_boxes.end(); ++it) + guionly = guionly && (*it)->isGuiTaskOnly(); + + if(!guionly) + return QDialogButtonBox::Apply|QDialogButtonBox::Ok|QDialogButtonBox::Cancel; + else + return QDialogButtonBox::Ok; +} + + +void TaskDlgPost::appendBox(TaskPostBox* box) { + + m_boxes.push_back(box); + Content.push_back(box); +} + +void TaskDlgPost::open() +{ + // a transaction is already open at creation time of the pad + QString msg = QObject::tr("Edit post processing object"); + Gui::Command::openCommand((const char*)msg.toUtf8()); +} + +void TaskDlgPost::clicked(int button) +{ + if(button == QDialogButtonBox::Apply) + getView()->getObject()->getDocument()->recompute(); +} + +bool TaskDlgPost::accept() +{ + + try { + std::vector::iterator it = m_boxes.begin(); + for(;it != m_boxes.end(); ++it) + (*it)->applyPythonCode(); + } + catch (const Base::Exception& e) { + QMessageBox::warning(NULL, tr("Input error"), QString::fromAscii(e.what())); + return false; + } + + Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); + return true; +} + +bool TaskDlgPost::reject() +{ + // roll back the done things + Gui::Command::abortCommand(); + Gui::Command::doCommand(Gui::Command::Gui,"Gui.activeDocument().resetEdit()"); + + return true; +} + +void TaskDlgPost::modifyStandardButtons(QDialogButtonBox* box) { + + box->button(QDialogButtonBox::Apply)->setDefault(true); +} + + +//############################################################################################ + +TaskPostBox::TaskPostBox(Gui::ViewProviderDocumentObject* view, const QPixmap &icon, const QString &title, QWidget* parent) + : TaskBox(icon, title, true, parent) { + + m_view = view; + m_object = view->getObject(); +} + +TaskPostBox::~TaskPostBox() { + +} + +bool TaskPostBox::autoApply() { + + ParameterGrp::handle pGroup = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Fem"); + return pGroup->GetBool("PostAutoRecompute", false); +} + +void TaskPostBox::recompute() { + + if(autoApply()) + App::GetApplication().getActiveDocument()->recompute(); +} + +void TaskPostBox::updateEnumerationList(App::PropertyEnumeration& prop, QComboBox* box) { + + box->clear(); + QStringList list; + std::vector vec = prop.getEnumVector(); + for(std::vector::iterator it = vec.begin(); it != vec.end(); ++it ) + list.push_back(QString::fromStdString(*it)); + + box->insertItems(0, list); + box->setCurrentIndex(prop.getValue()); +} + +//########################################################################################################### + +TaskPostDisplay::TaskPostDisplay(Gui::ViewProviderDocumentObject* view, QWidget *parent) + : TaskPostBox(view, Gui::BitmapFactory().pixmap("fem-fem-mesh-create-node-by-poly"), tr("Display options"), parent) +{ + //we need a separate container widget to add all controls to + proxy = new QWidget(this); + ui = new Ui_TaskPostDisplay(); + ui->setupUi(proxy); + QMetaObject::connectSlotsByName(this); + + this->groupLayout()->addWidget(proxy); + + //update all fields + updateEnumerationList(getTypedView()->DisplayMode, ui->Representation); + updateEnumerationList(getTypedView()->Field, ui->Field); + updateEnumerationList(getTypedView()->VectorMode, ui->VectorMode); +} + +TaskPostDisplay::~TaskPostDisplay() +{ + delete ui; +} + +void TaskPostDisplay::on_Representation_activated(int i) { + + getTypedView()->DisplayMode.setValue(i); + updateEnumerationList(getTypedView()->Field, ui->Field); + updateEnumerationList(getTypedView()->VectorMode, ui->VectorMode); +} + +void TaskPostDisplay::on_Field_activated(int i) { + + getTypedView()->Field.setValue(i); + updateEnumerationList(getTypedView()->VectorMode, ui->VectorMode); +} + +void TaskPostDisplay::on_VectorMode_activated(int i) { + + getTypedView()->VectorMode.setValue(i); +} + +void TaskPostDisplay::on_Transparency_valueChanged(int i) { + + getTypedView()->Transperency.setValue(i); +} + +void TaskPostDisplay::applyPythonCode() { + +} + +//############################################################################################ + +TaskPostFunction::TaskPostFunction(ViewProviderDocumentObject* view, QWidget* parent): TaskPostBox(view, Gui::BitmapFactory().pixmap("fem-fem-mesh-create-node-by-poly"), tr("Implicit function"), parent) { + + assert(view->isDerivedFrom(ViewProviderFemPostFunction::getClassTypeId())); + + //we load the views widget + FunctionWidget* w = getTypedView()->createControlWidget(); + w->setParent(this); + w->setViewProvider(getTypedView()); + this->groupLayout()->addWidget(w); +} + +TaskPostFunction::~TaskPostFunction() { + +} + +void TaskPostFunction::applyPythonCode() { + + //we apply the views widgets python code +} + +//############################################################################################ + +TaskPostClip::TaskPostClip(ViewProviderDocumentObject* view, App::PropertyLink* function, QWidget* parent) + : TaskPostBox(view,Gui::BitmapFactory().pixmap("fem-fem-mesh-create-node-by-poly"), tr("Choose implicit function"), parent) { + + assert(view->isDerivedFrom(ViewProviderFemPostClip::getClassTypeId())); + assert(function); + + fwidget = NULL; + + //we load the views widget + proxy = new QWidget(this); + ui = new Ui_TaskPostClip(); + ui->setupUi(proxy); + QMetaObject::connectSlotsByName(this); + this->groupLayout()->addWidget(proxy); + + //the layout for the container widget + QVBoxLayout *layout = new QVBoxLayout(); + ui->Container->setLayout(layout); + + //fill up the combo box with possible functions + collectImplicitFunctions(); + + //add the function creation command + Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); + rcCmdMgr.getCommandByName("Fem_PostCreateFunctions")->getAction()->addTo(ui->CreateButton); + ui->CreateButton->setPopupMode(QToolButton::InstantPopup); + + //load the default values + ui->CutCells->setChecked(static_cast(getObject())->CutCells.getValue()); + ui->InsideOut->setChecked(static_cast(getObject())->InsideOut.getValue()); +} + +TaskPostClip::~TaskPostClip() { + +} + +void TaskPostClip::applyPythonCode() { + +} + +void TaskPostClip::collectImplicitFunctions() { + + std::vector pipelines; + pipelines = App::GetApplication().getActiveDocument()->getObjectsOfType(); + if (!pipelines.empty()) { + Fem::FemPostPipeline *pipeline = pipelines.front(); + if(pipeline->Function.getValue() && + pipeline->Function.getValue()->getTypeId() == Fem::FemPostFunctionProvider::getClassTypeId()) { + + ui->FunctionBox->clear(); + QStringList items; + const std::vector& funcs = static_cast( + pipeline->Function.getValue())->Functions.getValues(); + for(std::size_t i=0; igetNameInDocument())); + + ui->FunctionBox->addItems(items); + } + } +} + +void TaskPostClip::on_CreateButton_triggered(QAction* a) { + + collectImplicitFunctions(); + recompute(); +} + +void TaskPostClip::on_FunctionBox_currentIndexChanged(int idx) { + + //set the correct property + std::vector pipelines; + pipelines = App::GetApplication().getActiveDocument()->getObjectsOfType(); + if (!pipelines.empty()) { + Fem::FemPostPipeline *pipeline = pipelines.front(); + if(pipeline->Function.getValue() && + pipeline->Function.getValue()->getTypeId() == Fem::FemPostFunctionProvider::getClassTypeId()) { + + const std::vector& funcs = static_cast( + pipeline->Function.getValue())->Functions.getValues(); + if(idx>=0) + static_cast(getObject())->Function.setValue(funcs[idx]); + else + static_cast(getObject())->Function.setValue(NULL); + } + } + + //load the correct view + Fem::FemPostFunction* fobj = static_cast( + static_cast(getObject())->Function.getValue()); + Gui::ViewProvider* view = NULL; + if(fobj) + view = Gui::Application::Instance->activeDocument()->getViewProvider(fobj); + + if(fwidget) + fwidget->deleteLater(); + + if(view) { + fwidget = static_cast(view)->createControlWidget(); + fwidget->setParent(ui->Container); + fwidget->setViewProvider(static_cast(view)); + ui->Container->layout()->addWidget(fwidget); + } + recompute(); +} + +void TaskPostClip::on_CutCells_toggled(bool val) { + + static_cast(getObject())->CutCells.setValue(val); + recompute(); +} + +void TaskPostClip::on_InsideOut_toggled(bool val) { + + static_cast(getObject())->InsideOut.setValue(val); + recompute(); +} + +//############################################################################################ + +TaskPostScalarClip::TaskPostScalarClip(ViewProviderDocumentObject* view, QWidget* parent) : + TaskPostBox(view, Gui::BitmapFactory().pixmap("fem-fem-mesh-create-node-by-poly"), tr("Clip options"), parent) { + + assert(view->isDerivedFrom(ViewProviderFemPostScalarClip::getClassTypeId())); + + //we load the views widget + proxy = new QWidget(this); + ui = new Ui_TaskPostScalarClip(); + ui->setupUi(proxy); + QMetaObject::connectSlotsByName(this); + this->groupLayout()->addWidget(proxy); + + //load the default values + updateEnumerationList(getTypedObject()->Scalars, ui->Scalar); + ui->InsideOut->setChecked(static_cast(getObject())->InsideOut.getValue()); + + App::PropertyFloatConstraint& value = static_cast(getObject())->Value; + //don't forget to sync the slider + ui->Value->blockSignals(true); + ui->Value->setValue( value.getValue()); + ui->Value->blockSignals(false); + //don't forget to sync the slider + ui->Value->blockSignals(true); + ui->Value->setValue( value.getConstraints()->UpperBound * (1-double(value.getValue())/100.) + + double(value.getValue())/100.*value.getConstraints()->UpperBound); + ui->Value->blockSignals(false); +} + +TaskPostScalarClip::~TaskPostScalarClip() { + +} + +void TaskPostScalarClip::applyPythonCode() { + +} + +void TaskPostScalarClip::on_Scalar_currentIndexChanged(int idx) { + + static_cast(getObject())->Scalars.setValue(idx); + recompute(); + + //update constraints and values + App::PropertyFloatConstraint& value = static_cast(getObject())->Value; + ui->Maximum->setText(QString::number(value.getConstraints()->UpperBound)); + ui->Minimum->setText(QString::number(value.getConstraints()->LowerBound)); + + //don't forget to sync the slider + ui->Value->blockSignals(true); + ui->Value->setValue( value.getValue()); + ui->Value->blockSignals(false); + //don't forget to sync the slider + ui->Value->blockSignals(true); + ui->Value->setValue( value.getConstraints()->UpperBound * (1-double(value.getValue())/100.) + + double(value.getValue())/100.*value.getConstraints()->UpperBound); + ui->Value->blockSignals(false); +} + +void TaskPostScalarClip::on_Slider_valueChanged(int v) { + + App::PropertyFloatConstraint& value = static_cast(getObject())->Value; + double val = value.getConstraints()->LowerBound * (1-double(v)/100.) + double(v)/100.*value.getConstraints()->UpperBound; + + value.setValue(val); + recompute(); + + //don't forget to sync the spinbox + ui->Value->blockSignals(true); + ui->Value->setValue( val ); + ui->Value->blockSignals(false); +} + +void TaskPostScalarClip::on_Value_valueChanged(double v) { + + App::PropertyFloatConstraint& value = static_cast(getObject())->Value; + value.setValue(v); + recompute(); + + //don't forget to sync the slider + ui->Slider->blockSignals(true); + ui->Slider->setValue(int(((v- value.getConstraints()->LowerBound)/(value.getConstraints()->UpperBound - value.getConstraints()->LowerBound))*100.)); + ui->Slider->blockSignals(false); +} + +void TaskPostScalarClip::on_InsideOut_toggled(bool val) { + + static_cast(getObject())->InsideOut.setValue(val); + recompute(); +} + + +#include "moc_TaskPostBoxes.cpp" diff --git a/src/Mod/Fem/Gui/TaskPostBoxes.h b/src/Mod/Fem/Gui/TaskPostBoxes.h new file mode 100644 index 000000000..7894ebcce --- /dev/null +++ b/src/Mod/Fem/Gui/TaskPostBoxes.h @@ -0,0 +1,188 @@ +/*************************************************************************** + * Copyright (c) 2015 Stefan Tröger * + * * + * 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_TaskPostDisplay_H +#define GUI_TASKVIEW_TaskPostDisplay_H + +#include +#include +#include +#include +#include +#include "ViewProviderFemPostFunction.h" + +class QComboBox; +class Ui_TaskPostDisplay; +class Ui_TaskPostClip; +class Ui_TaskPostScalarClip; + + +namespace FemGui { + +class TaskPostBox : public Gui::TaskView::TaskBox { + + Q_OBJECT + +public: + TaskPostBox(Gui::ViewProviderDocumentObject* view, const QPixmap &icon, const QString &title, QWidget *parent = 0); + ~TaskPostBox(); + + virtual void applyPythonCode() = 0; + virtual bool isGuiTaskOnly() {return false;}; //return true if only gui properties are manipulated + +protected: + App::DocumentObject* getObject() {return m_object;}; + template + T* getTypedObject() {return static_cast(m_object);}; + Gui::ViewProviderDocumentObject* getView() {return m_view;}; + template + T* getTypedView() {return static_cast(m_view);}; + + bool autoApply(); + void recompute(); + + static void updateEnumerationList(App::PropertyEnumeration&, QComboBox* box); + +private: + App::DocumentObject* m_object; + Gui::ViewProviderDocumentObject* m_view; +}; + +/// simulation dialog for the TaskView +class TaskDlgPost : public Gui::TaskView::TaskDialog +{ + Q_OBJECT + +public: + TaskDlgPost(Gui::ViewProviderDocumentObject *view, bool newObj=false); + ~TaskDlgPost(); + + void appendBox(TaskPostBox* box); + Gui::ViewProviderDocumentObject* getView() const + { return m_view; } + +public: + /// is called the TaskView when the dialog is opened + virtual void open(); + /// is called by the framework if an button is clicked which has no accept or reject role + virtual void clicked(int); + /// is called by the framework if the dialog is accepted (Ok) + virtual bool accept(); + /// is called by the framework if the dialog is rejected (Cancel) + virtual bool reject(); + /// is called by the framework if the user presses the help button + virtual bool isAllowedAlterDocument(void) const + { return false; } + virtual void modifyStandardButtons(QDialogButtonBox*); + + /// returns for Close and Help button + virtual QDialogButtonBox::StandardButtons getStandardButtons(void) const; + +protected: + Gui::ViewProviderDocumentObject* m_view; + std::vector m_boxes; +}; + + +class TaskPostDisplay : public TaskPostBox +{ + Q_OBJECT + +public: + TaskPostDisplay(Gui::ViewProviderDocumentObject* view, QWidget *parent = 0); + ~TaskPostDisplay(); + + virtual void applyPythonCode(); + virtual bool isGuiTaskOnly() {return true;}; + +private Q_SLOTS: + void on_Representation_activated(int i); + void on_Field_activated(int i); + void on_VectorMode_activated(int i); + void on_Transparency_valueChanged(int i); + +private: + QWidget* proxy; + Ui_TaskPostDisplay* ui; +}; + +class TaskPostFunction : public TaskPostBox { + + Q_OBJECT + +public: + TaskPostFunction(Gui::ViewProviderDocumentObject* view, QWidget* parent = 0); + virtual ~TaskPostFunction(); + + virtual void applyPythonCode(); +}; + +class TaskPostClip : public TaskPostBox { + + Q_OBJECT + +public: + TaskPostClip(Gui::ViewProviderDocumentObject* view, App::PropertyLink* function, QWidget* parent = 0); + virtual ~TaskPostClip(); + + virtual void applyPythonCode(); + +private Q_SLOTS: + void on_CreateButton_triggered(QAction* a); + void on_FunctionBox_currentIndexChanged(int idx); + void on_InsideOut_toggled(bool val); + void on_CutCells_toggled(bool val); + +private: + void collectImplicitFunctions(); + + App::PropertyLink* m_functionProperty; + QWidget* proxy; + Ui_TaskPostClip* ui; + FunctionWidget* fwidget; +}; + +class TaskPostScalarClip : public TaskPostBox { + + Q_OBJECT + +public: + TaskPostScalarClip(Gui::ViewProviderDocumentObject* view, QWidget* parent = 0); + virtual ~TaskPostScalarClip(); + + virtual void applyPythonCode(); + +private Q_SLOTS: + void on_Slider_valueChanged(int v); + void on_Value_valueChanged(double v); + void on_Scalar_currentIndexChanged(int idx); + void on_InsideOut_toggled(bool val); + +private: + QWidget* proxy; + Ui_TaskPostScalarClip* ui; +}; + +} //namespace FemGui + +#endif // GUI_TASKVIEW_TaskPostDisplay_H diff --git a/src/Mod/Fem/Gui/TaskPostClip.ui b/src/Mod/Fem/Gui/TaskPostClip.ui new file mode 100644 index 000000000..446021801 --- /dev/null +++ b/src/Mod/Fem/Gui/TaskPostClip.ui @@ -0,0 +1,92 @@ + + + TaskPostClip + + + + 0 + 0 + 413 + 184 + + + + + 0 + 0 + + + + Form + + + + + + + + + + + Create + + + + :/icons/list-add.svg:/icons/list-add.svg + + + Qt::ToolButtonTextBesideIcon + + + + + + + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + + + + + + + Inside Out + + + + + + + Cut Cells + + + + + + + + + + + + diff --git a/src/Mod/Fem/Gui/TaskPostDisplay.ui b/src/Mod/Fem/Gui/TaskPostDisplay.ui new file mode 100644 index 000000000..7fe56eac5 --- /dev/null +++ b/src/Mod/Fem/Gui/TaskPostDisplay.ui @@ -0,0 +1,180 @@ + + + TaskPostDisplay + + + + 0 + 0 + 292 + 254 + + + + Form + + + + + + + + + 0 + 0 + + + + Mode + + + + + + + + 0 + 0 + + + + + Outline + + + + + Surface + + + + + Surface with Edges + + + + + Wireframe + + + + + + + + + + + 0 + 0 + + + + Coloring + + + + + + Field + + + + + + + + 0 + 0 + + + + + Outline + + + + + Surface + + + + + Surface with Edges + + + + + Wireframe + + + + + + + + Vector + + + + + + + + 0 + 0 + + + + + Magnitute + + + + + X + + + + + Y + + + + + Z + + + + + + + + + + + Styling + + + + + + Transparency + + + + + + + Qt::Horizontal + + + + + + + + + + + diff --git a/src/Mod/Fem/Gui/TaskPostScalarClip.ui b/src/Mod/Fem/Gui/TaskPostScalarClip.ui new file mode 100644 index 000000000..d91c92f46 --- /dev/null +++ b/src/Mod/Fem/Gui/TaskPostScalarClip.ui @@ -0,0 +1,215 @@ + + + TaskPostScalarClip + + + + 0 + 0 + 326 + 172 + + + + Form + + + + + + + + + 0 + 0 + + + + Scalar + + + + + + + + 0 + 0 + + + + + Outline + + + + + Surface + + + + + Surface with Edges + + + + + Wireframe + + + + + + + + + + Qt::Horizontal + + + + + + + 100 + + + Qt::Horizontal + + + false + + + false + + + QSlider::NoTicks + + + + + + + 20 + + + + + + 0 + 0 + + + + + 50 + 0 + + + + Qt::NoFocus + + + -100000 + + + true + + + true + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + false + + + 3 + + + -999999999.000000000000000 + + + 999999999.000000000000000 + + + + + + + + 0 + 0 + + + + + 50 + 0 + + + + Qt::NoFocus + + + 0 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + + + + + + + Qt::Horizontal + + + + + + + + + InsideOut + + + + + + + layoutWidget + minimum + maximum + Slider + line + minimum + maximum + + InsideOut + horizontalSpacer + + line_2 + + + + diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostFilter.cpp b/src/Mod/Fem/Gui/ViewProviderFemPostFilter.cpp new file mode 100644 index 000000000..c4b94b5fc --- /dev/null +++ b/src/Mod/Fem/Gui/ViewProviderFemPostFilter.cpp @@ -0,0 +1,71 @@ +/*************************************************************************** + * Copyright (c) 2015 Stefan Tröger * + * * + * 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" +#include "ViewProviderFemPostFilter.h" +#include "TaskPostBoxes.h" +#include +#include + +using namespace FemGui; + + +PROPERTY_SOURCE(FemGui::ViewProviderFemPostClip, FemGui::ViewProviderFemPostObject) + +ViewProviderFemPostClip::ViewProviderFemPostClip() { + +} + +ViewProviderFemPostClip::~ViewProviderFemPostClip() { + +} + +void ViewProviderFemPostClip::setupTaskDialog(TaskDlgPost* dlg) { + + //add the function box + dlg->appendBox(new TaskPostClip(dlg->getView(), + &static_cast(dlg->getView()->getObject())->Function)); + + //add the display options + FemGui::ViewProviderFemPostObject::setupTaskDialog(dlg); +} + + +PROPERTY_SOURCE(FemGui::ViewProviderFemPostScalarClip, FemGui::ViewProviderFemPostObject) + +ViewProviderFemPostScalarClip::ViewProviderFemPostScalarClip() { + +} + +ViewProviderFemPostScalarClip::~ViewProviderFemPostScalarClip() { + +} + +void ViewProviderFemPostScalarClip::setupTaskDialog(TaskDlgPost* dlg) { + + //add the function box + dlg->appendBox(new TaskPostScalarClip(dlg->getView())); + + //add the display options + FemGui::ViewProviderFemPostObject::setupTaskDialog(dlg); +} diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostFilter.h b/src/Mod/Fem/Gui/ViewProviderFemPostFilter.h new file mode 100644 index 000000000..12efb2bb2 --- /dev/null +++ b/src/Mod/Fem/Gui/ViewProviderFemPostFilter.h @@ -0,0 +1,61 @@ +/*************************************************************************** + * Copyright (c) 2015 Stefan Tröger * + * * + * 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 FEM_VIEWPROVIDERFEMPOSTFILTER_H +#define FEM_VIEWPROVIDERFEMPOSTFILTER_H + +#include "ViewProviderFemPostObject.h" + +namespace FemGui +{ + +class FemGuiExport ViewProviderFemPostClip : public ViewProviderFemPostObject { + + PROPERTY_HEADER(FemGui::ViewProviderFemPostClip); + +public: + /// constructor. + ViewProviderFemPostClip(); + ~ViewProviderFemPostClip(); + +protected: + virtual void setupTaskDialog(TaskDlgPost* dlg); +}; + +class FemGuiExport ViewProviderFemPostScalarClip : public ViewProviderFemPostObject { + + PROPERTY_HEADER(FemGui::ViewProviderFemPostScalarClip); + +public: + /// constructor. + ViewProviderFemPostScalarClip(); + ~ViewProviderFemPostScalarClip(); + +protected: + virtual void setupTaskDialog(TaskDlgPost* dlg); +}; + +} //namespace FemGui + + +#endif // FEM_VIEWPROVIDERFEMPOSTFILTER_H \ No newline at end of file diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp b/src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp index 1f0157b55..59d9629ec 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp @@ -31,14 +31,21 @@ #include #include #include +#include #include #include +#include +#include #include #include #include +#include +#include +#include #endif #include "ViewProviderFemPostFunction.h" +#include "TaskPostBoxes.h" #include #include #include @@ -46,9 +53,31 @@ #include #include #include +#include +#include +#include + +#include + +#include "ui_PlaneWidget.h" +#include "ui_SphereWidget.h" using namespace FemGui; +void FunctionWidget::setViewProvider(ViewProviderFemPostFunction* view) { + + m_view = view; + m_object = static_cast(view->getObject()); + m_connection = m_object->getDocument()->signalChangedObject.connect(boost::bind(&FunctionWidget::onObjectsChanged, this, _1, _2)); +} + +void FunctionWidget::onObjectsChanged(const App::DocumentObject& obj, const App::Property& p) { + + if(&obj == m_object) + onChange(p); +} + + PROPERTY_SOURCE(FemGui::ViewProviderFemPostFunctionProvider, Gui::ViewProviderDocumentObject) ViewProviderFemPostFunctionProvider::ViewProviderFemPostFunctionProvider() { @@ -141,6 +170,12 @@ void ViewProviderFemPostFunction::attach(App::DocumentObject *pcObj) setDisplayMaskMode("Default"); } +bool ViewProviderFemPostFunction::doubleClicked(void) { + Gui::Application::Instance->activeDocument()->setEdit(this, (int)ViewProvider::Default); + return true; +} + + SoTransformManip* ViewProviderFemPostFunction::setupManipulator() { return new SoCenterballManip; @@ -187,6 +222,58 @@ void ViewProviderFemPostFunction::dragMotionCallback(void *data, SoDragger *drag that->getObject()->getDocument()->recompute(); } + +bool ViewProviderFemPostFunction::setEdit(int ModNum) { + + + if (ModNum == ViewProvider::Default || ModNum == 1 ) { + + Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog(); + TaskDlgPost *postDlg = qobject_cast(dlg); + if (postDlg && postDlg->getView() != this) + postDlg = 0; // another pad left open its task panel + if (dlg && !postDlg) { + QMessageBox msgBox; + msgBox.setText(QObject::tr("A dialog is already open in the task panel")); + msgBox.setInformativeText(QObject::tr("Do you want to close this dialog?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::Yes); + int ret = msgBox.exec(); + if (ret == QMessageBox::Yes) + Gui::Control().reject(); + else + return false; + } + + // start the edit dialog + if (postDlg) + Gui::Control().showDialog(postDlg); + else { + postDlg = new TaskDlgPost(this); + postDlg->appendBox(new TaskPostFunction(this)); + Gui::Control().showDialog(postDlg); + } + + return true; + } + else { + return ViewProviderDocumentObject::setEdit(ModNum); + } +} + +void ViewProviderFemPostFunction::unsetEdit(int ModNum) { + + if (ModNum == ViewProvider::Default) { + // when pressing ESC make sure to close the dialog + Gui::Control().closeDialog(); + } + else { + ViewProviderDocumentObject::unsetEdit(ModNum); + } +} + +//################################################################################################# + PROPERTY_SOURCE(FemGui::ViewProviderFemPostPlaneFunction, FemGui::ViewProviderFemPostFunction) ViewProviderFemPostPlaneFunction::ViewProviderFemPostPlaneFunction() { @@ -244,3 +331,199 @@ void ViewProviderFemPostPlaneFunction::updateData(const App::Property* p) { Gui::ViewProviderDocumentObject::updateData(p); } + + +FunctionWidget* ViewProviderFemPostPlaneFunction::createControlWidget() { + return new PlaneWidget(); +} + + +PlaneWidget::PlaneWidget() { + + ui = new Ui_PlaneWidget(); + ui->setupUi(this); + + connect(ui->originX, SIGNAL(valueChanged(double)), this, SLOT(originChanged(double))); + connect(ui->originY, SIGNAL(valueChanged(double)), this, SLOT(originChanged(double))); + connect(ui->originZ, SIGNAL(valueChanged(double)), this, SLOT(originChanged(double))); + connect(ui->normalX, SIGNAL(valueChanged(double)), this, SLOT(normalChanged(double))); + connect(ui->normalY, SIGNAL(valueChanged(double)), this, SLOT(normalChanged(double))); + connect(ui->normalZ, SIGNAL(valueChanged(double)), this, SLOT(normalChanged(double))); + +} + +PlaneWidget::~PlaneWidget() { + +} + +void PlaneWidget::applyPythonCode() { + +} + +void PlaneWidget::setViewProvider(ViewProviderFemPostFunction* view) { + + FemGui::FunctionWidget::setViewProvider(view); + onChange(static_cast(getObject())->Normal); + onChange(static_cast(getObject())->Origin); +} + +void PlaneWidget::onChange(const App::Property& p) { + + setBlockObjectUpdates(true); + if(strcmp(p.getName(), "Normal") == 0) { + const Base::Vector3d& vec = static_cast(&p)->getValue(); + ui->normalX->setValue(vec.x); + ui->normalY->setValue(vec.y); + ui->normalZ->setValue(vec.z); + } + else if(strcmp(p.getName(), "Origin") == 0) { + const Base::Vector3d& vec = static_cast(&p)->getValue(); + ui->originX->setValue(vec.x); + ui->originY->setValue(vec.y); + ui->originZ->setValue(vec.z); + } + setBlockObjectUpdates(false); +} + +void PlaneWidget::normalChanged(double val) { + + if(!blockObjectUpdates()) { + Base::Vector3d vec(ui->normalX->value(), ui->normalY->value(), ui->normalZ->value()); + static_cast(getObject())->Normal.setValue(vec); + } +} + +void PlaneWidget::originChanged(double val) { + + if(!blockObjectUpdates()) { + Base::Vector3d vec(ui->originX->value(), ui->originY->value(), ui->originZ->value()); + static_cast(getObject())->Origin.setValue(vec); + } +} + + + +//################################################################################################# + +PROPERTY_SOURCE(FemGui::ViewProviderFemPostSphereFunction, FemGui::ViewProviderFemPostFunction) + +ViewProviderFemPostSphereFunction::ViewProviderFemPostSphereFunction() { + + setAutoScale(true); + + //setup the visualisation geometry + m_sphereNode = new SoSphere; + m_sphereNode->ref(); + + getGeometryNode()->addChild(m_sphereNode); +} + +ViewProviderFemPostSphereFunction::~ViewProviderFemPostSphereFunction() { + + m_sphereNode->unref(); +} + +SoTransformManip* ViewProviderFemPostSphereFunction::setupManipulator() { + return new SoTransformBoxManip(); +} + + +void ViewProviderFemPostSphereFunction::draggerUpdate(SoDragger* m) { + + Base::Console().Message("dragger udate\n"); + + Fem::FemPostSphereFunction* func = static_cast(getObject()); + SoTransformBoxDragger* dragger = static_cast(m); + + // the new axis of the plane + SbRotation rot, scaleDir; + const SbVec3f& center = dragger->translation.getValue(); + + SbVec3f norm(0,0,1); + dragger->rotation.getValue().multVec(norm,norm); + func->Center.setValue(center[0], center[1], center[2]); + func->Radius.setValue(dragger->scaleFactor.getValue()[0]); +} + +void ViewProviderFemPostSphereFunction::updateData(const App::Property* p) { + /* + Fem::FemPostSphereFunction* func = static_cast(getObject()); + + if(!isDragging() && (p == &func->Origin || p == &func->Normal)) { + + const Base::Vector3d& trans = func->Origin.getValue(); + const Base::Vector3d& norm = func->Normal.getValue(); + SbRotation rot(SbVec3f(0.,0.,1.), SbVec3f(norm.x, norm.y, norm.z)); + + Base::Console().Message("Updated propertes\n"); + static_cast(getManipulator())->center.setValue(SbVec3f(trans[0], trans[1], trans[2])); + static_cast(getManipulator())->rotation.setValue(rot); + } + + Gui::ViewProviderDocumentObject::updateData(p);*/ +} + + +FunctionWidget* ViewProviderFemPostSphereFunction::createControlWidget() { + return new SphereWidget(); +} + + +SphereWidget::SphereWidget() { + + ui = new Ui_SphereWidget(); + ui->setupUi(this); + + connect(ui->centerX, SIGNAL(valueChanged(double)), this, SLOT(centerChanged(double))); + connect(ui->centerY, SIGNAL(valueChanged(double)), this, SLOT(centerChanged(double))); + connect(ui->centerZ, SIGNAL(valueChanged(double)), this, SLOT(centerChanged(double))); + connect(ui->radius, SIGNAL(valueChanged(double)), this, SLOT(radiusChanged(double))); +} + +SphereWidget::~SphereWidget() { + +} + +void SphereWidget::applyPythonCode() { + +} + +void SphereWidget::setViewProvider(ViewProviderFemPostFunction* view) { + + FemGui::FunctionWidget::setViewProvider(view); + onChange(static_cast(getObject())->Center); + onChange(static_cast(getObject())->Radius); +} + +void SphereWidget::onChange(const App::Property& p) { + + setBlockObjectUpdates(true); + if(strcmp(p.getName(), "Radius") == 0) { + double val = static_cast(&p)->getValue(); + ui->radius->setValue(val); + } + else if(strcmp(p.getName(), "Center") == 0) { + const Base::Vector3d& vec = static_cast(&p)->getValue(); + ui->centerX->setValue(vec.x); + ui->centerY->setValue(vec.y); + ui->centerZ->setValue(vec.z); + } + setBlockObjectUpdates(false); +} + +void SphereWidget::centerChanged(double val) { + + if(!blockObjectUpdates()) { + Base::Vector3d vec(ui->centerX->value(), ui->centerY->value(), ui->centerZ->value()); + static_cast(getObject())->Center.setValue(vec); + } +} + +void SphereWidget::radiusChanged(double val) { + + if(!blockObjectUpdates()) { + static_cast(getObject())->Radius.setValue(ui->radius->value()); + } +} + +#include "moc_ViewProviderFemPostFunction.cpp" \ No newline at end of file diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostFunction.h b/src/Mod/Fem/Gui/ViewProviderFemPostFunction.h index eb448930c..6a1b4b1dc 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostFunction.h +++ b/src/Mod/Fem/Gui/ViewProviderFemPostFunction.h @@ -25,7 +25,31 @@ #define FEM_VIEWPROVIDERFEMPOSTFUNCTION_H #include +#include #include +#include + + +#if defined(signals) && defined(QOBJECTDEFS_H) && \ + !defined(QT_MOC_CPP) +# undef signals +# define signals signals +#endif + +#include +namespace boost +{ + namespace signalslib = signals; +} + +#if defined(signals) && defined(QOBJECTDEFS_H) && \ + !defined(QT_MOC_CPP) +# undef signals +// Restore the macro definition of "signals", as it was +// defined by Qt's . +# define signals protected +#endif + class SoScale; class SoSurroundScale; @@ -33,9 +57,41 @@ class SoTransformManip; class SoComposeMatrix; class SoMatrixTransform; class SoDragger; +class SoSphere; +class Ui_PlaneWidget; +class Ui_SphereWidget; namespace FemGui { + +class ViewProviderFemPostFunction; + +class FemGuiExport FunctionWidget : public QWidget { + + Q_OBJECT +public: + FunctionWidget() {}; + virtual ~FunctionWidget() {}; + + virtual void applyPythonCode() = 0; + virtual void setViewProvider(ViewProviderFemPostFunction* view); + void onObjectsChanged(const App::DocumentObject& obj, const App::Property&); + +protected: + ViewProviderFemPostFunction* getView() {return m_view;}; + Fem::FemPostFunction* getObject(){return m_object;}; + + bool blockObjectUpdates() {return m_block;}; + void setBlockObjectUpdates(bool val) {m_block = val;}; + + virtual void onChange(const App::Property& p) = 0; + +private: + bool m_block; + ViewProviderFemPostFunction* m_view; + Fem::FemPostFunction* m_object; + boost::signalslib::scoped_connection m_connection; +}; class FemGuiExport ViewProviderFemPostFunctionProvider : public Gui::ViewProviderDocumentObject { @@ -59,9 +115,17 @@ public: ~ViewProviderFemPostFunction(); void attach(App::DocumentObject *pcObject); + bool doubleClicked(void); std::vector getDisplayModes() const; - + + //creates the widget used in the task dalogs, either for the function itself or for + //the fiter using it + virtual FunctionWidget* createControlWidget() {return NULL;}; + protected: + virtual bool setEdit(int ModNum); + virtual void unsetEdit(int ModNum); + void setAutoScale(bool value) {m_autoscale = value;}; bool autoScale() {return m_autoscale;}; @@ -83,6 +147,27 @@ private: bool m_autoscale, m_isDragging, m_autoRecompute; }; +//############################################################################################### + +class FemGuiExport PlaneWidget : public FunctionWidget { + + Q_OBJECT +public: + PlaneWidget(); + virtual ~PlaneWidget(); + + virtual void applyPythonCode(); + virtual void onChange(const App::Property& p); + virtual void setViewProvider(ViewProviderFemPostFunction* view); + +private Q_SLOTS: + void originChanged(double val); + void normalChanged(double val); + +private: + Ui_PlaneWidget* ui; +}; + class FemGuiExport ViewProviderFemPostPlaneFunction : public ViewProviderFemPostFunction { PROPERTY_HEADER(FemGui::ViewProviderFemPostPlaneFunction); @@ -91,11 +176,53 @@ public: ViewProviderFemPostPlaneFunction(); virtual ~ViewProviderFemPostPlaneFunction(); + virtual FunctionWidget* createControlWidget(); + protected: virtual void draggerUpdate(SoDragger* mat); virtual void updateData(const App::Property*); }; +//############################################################################################### + +class FemGuiExport SphereWidget : public FunctionWidget { + + Q_OBJECT +public: + SphereWidget(); + virtual ~SphereWidget(); + + virtual void applyPythonCode(); + virtual void onChange(const App::Property& p); + virtual void setViewProvider(ViewProviderFemPostFunction* view); + +private Q_SLOTS: + void centerChanged(double val); + void radiusChanged(double val); + +private: + Ui_SphereWidget* ui; +}; + +class FemGuiExport ViewProviderFemPostSphereFunction : public ViewProviderFemPostFunction { + + PROPERTY_HEADER(FemGui::ViewProviderFemPostSphereFunction); + +public: + ViewProviderFemPostSphereFunction(); + virtual ~ViewProviderFemPostSphereFunction(); + + virtual SoTransformManip* setupManipulator(); + virtual FunctionWidget* createControlWidget(); + +protected: + virtual void draggerUpdate(SoDragger* mat); + virtual void updateData(const App::Property*); + +private: + SoSphere* m_sphereNode; +}; + } //namespace FemGui diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp b/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp index 91404d391..a258f7790 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp @@ -39,13 +39,19 @@ #endif #include "ViewProviderFemPostObject.h" +#include "TaskPostBoxes.h" #include #include +#include +#include +#include +#include #include #include #include #include +#include using namespace FemGui; @@ -55,14 +61,10 @@ PROPERTY_SOURCE(FemGui::ViewProviderFemPostObject, Gui::ViewProviderDocumentObje ViewProviderFemPostObject::ViewProviderFemPostObject() : m_blockPropertyChanges(false) { //initialize the properties - ADD_PROPERTY(Coloring,((long)0)); + ADD_PROPERTY_TYPE(Field,((long)0), "Coloring", App::Prop_None, "Select the field used for calculating the color"); + ADD_PROPERTY_TYPE(VectorMode,((long)0), "Coloring", App::Prop_None, "Select what to show for a vector field"); ADD_PROPERTY(Transperency, (0)); - - m_transperencyConstraint.StepSize = 1; - m_transperencyConstraint.LowerBound = 0; - m_transperencyConstraint.UpperBound = 100; - Transperency.setConstraints(&m_transperencyConstraint); - + sPixmap = "fem-fem-mesh-from-shape"; //create the subnodes which do the visualization work @@ -177,15 +179,20 @@ void ViewProviderFemPostObject::update() { if(!setupPipeline()) return; - m_currentAlgorithm->Update(); - vtkPolyData* poly = m_currentAlgorithm->GetOutput(); + m_currentAlgorithm->Update(); + updateProperties(); + update3D(); +} + +void ViewProviderFemPostObject::updateProperties() { - //update the coloring property m_blockPropertyChanges = true; + vtkPolyData* poly = m_currentAlgorithm->GetOutput(); + //coloring std::string val; - if(Coloring.getEnums() && Coloring.getValue() >= 0) - val = Coloring.getValueAsString(); + if(Field.getEnums() && Field.getValue() >= 0) + val = Field.getValueAsString(); std::vector colorArrays; colorArrays.push_back("None"); @@ -199,23 +206,52 @@ void ViewProviderFemPostObject::update() { colorArrays.push_back(cell->GetArrayName(i)); App::Enumeration empty; - Coloring.setValue(empty); + Field.setValue(empty); m_coloringEnum.setEnums(colorArrays); - Coloring.setValue(m_coloringEnum); + Field.setValue(m_coloringEnum); std::vector::iterator it = std::find(colorArrays.begin(), colorArrays.end(), val); if(!val.empty() && it != colorArrays.end()) - Coloring.setValue(val.c_str()); + Field.setValue(val.c_str()); - Coloring.purgeTouched(); + Field.purgeTouched(); + + //Vector mode + if(VectorMode.getEnums() && VectorMode.getValue() >= 0) + val = VectorMode.getValueAsString(); + + colorArrays.clear(); + if(Field.getValue() == 0) + colorArrays.push_back("Not a vector"); + else { + int array = Field.getValue() - 1; //0 is none + vtkPolyData* pd = m_currentAlgorithm->GetOutput(); + vtkDataArray* data = pd->GetPointData()->GetArray(array); + + if(data->GetNumberOfComponents() == 1) + colorArrays.push_back("Not a vector"); + else { + colorArrays.push_back("Magnitude"); + if(data->GetNumberOfComponents() >= 2) { + colorArrays.push_back("X"); + colorArrays.push_back("Y"); + } + if(data->GetNumberOfComponents() >= 3) + colorArrays.push_back("Z"); + } + } + + VectorMode.setValue(empty); + m_vectorEnum.setEnums(colorArrays); + VectorMode.setValue(m_vectorEnum); + + it = std::find(colorArrays.begin(), colorArrays.end(), val); + if(!val.empty() && it != colorArrays.end()) + VectorMode.setValue(val.c_str()); m_blockPropertyChanges = false; - - //update the visualization - update3D(); } - void ViewProviderFemPostObject::update3D() { if(!setupPipeline()) @@ -343,11 +379,11 @@ void ViewProviderFemPostObject::WritePointData(vtkPoints* points, vtkDataArray* Base::Console().Message("\n"); m_coordinates->point.startEditing(); + m_coordinates->point.setNum(points->GetNumberOfPoints()); for (i = 0; i < points->GetNumberOfPoints(); i++) { p = points->GetPoint(i); m_coordinates->point.set1Value(i, p[0], p[1], p[2]); } - m_coordinates->point.setNum(points->GetNumberOfPoints()); m_coordinates->point.finishEditing(); // write out the point normal data @@ -355,11 +391,11 @@ void ViewProviderFemPostObject::WritePointData(vtkPoints* points, vtkDataArray* Base::Console().Message("Write normals: %i\n", normals->GetNumberOfTuples()); m_normals->vector.startEditing(); + m_normals->vector.setNum(normals->GetNumberOfTuples()); for (i = 0; i < normals->GetNumberOfTuples(); i++) { p = normals->GetTuple(i); m_normals->vector.set1Value(i, SbVec3f(p[0], p[1], p[2])); } - m_normals->vector.setNum(normals->GetNumberOfTuples()); m_normals->vector.finishEditing(); m_normalBinding->value = SoNormalBinding::PER_VERTEX_INDEXED; @@ -372,7 +408,7 @@ void ViewProviderFemPostObject::WriteColorData() { if(!setupPipeline()) return; - if(Coloring.getEnumVector().empty() || Coloring.getValue() == 0) { + if(Field.getEnumVector().empty() || Field.getValue() == 0) { m_material->diffuseColor.setValue(SbColor(0.8,0.8,0.8)); m_material->transparency.setValue(0.); @@ -382,13 +418,17 @@ void ViewProviderFemPostObject::WriteColorData() { }; - int array = Coloring.getValue() - 1; //0 is none + int array = Field.getValue() - 1; //0 is none vtkPolyData* pd = m_currentAlgorithm->GetOutput(); vtkDataArray* data = pd->GetPointData()->GetArray(array); + int component = VectorMode.getValue() - 1; //0 is either "Not a vector" or magnitude, for -1 is correct for magnitude. x y and z are one number too high + if(strcmp(VectorMode.getValueAsString(), "Not a vector")==0) + component = 0; + //build the lookuptable double range[2]; - data->GetRange(range, 0); + data->GetRange(range, component); m_lookup->SetTableRange(range[0], range[1]); m_lookup->SetScaleToLinear(); m_lookup->Build(); @@ -397,7 +437,15 @@ void ViewProviderFemPostObject::WriteColorData() { for (int i = 0; i < pd->GetNumberOfPoints(); i++) { - double value = data->GetComponent(i, 0); + double value = 0; + if(component >= 0) + value = data->GetComponent(i, component); + else { + for(int j=0; jGetNumberOfComponents(); ++j) + value += std::pow(data->GetComponent(i, j),2); + + value = std::sqrt(value); + } double c[3]; m_lookup->GetColor(value, c); m_material->diffuseColor.set1Value(i, c[0], c[1], c[2]); @@ -465,12 +513,81 @@ void ViewProviderFemPostObject::onChanged(const App::Property* prop) { return; Base::Console().Message("On Changed: %s\n", prop->getName()); - if(prop == &Coloring && setupPipeline()) { + if(prop == &Field && setupPipeline()) { + updateProperties(); WriteColorData(); + WriteTransperency(); } + else if(prop == &VectorMode && setupPipeline()) { + WriteColorData(); + WriteTransperency(); + } else if(prop == &Transperency) { WriteTransperency(); } ViewProviderDocumentObject::onChanged(prop); } + +bool ViewProviderFemPostObject::doubleClicked(void) { + Gui::Application::Instance->activeDocument()->setEdit(this, (int)ViewProvider::Default); + return true; +} + + +bool ViewProviderFemPostObject::setEdit(int ModNum) { + + if (ModNum == ViewProvider::Default || ModNum == 1 ) { + + Gui::TaskView::TaskDialog *dlg = Gui::Control().activeDialog(); + TaskDlgPost *postDlg = qobject_cast(dlg); + if (postDlg && postDlg->getView() != this) + postDlg = 0; // another pad left open its task panel + if (dlg && !postDlg) { + QMessageBox msgBox; + msgBox.setText(QObject::tr("A dialog is already open in the task panel")); + msgBox.setInformativeText(QObject::tr("Do you want to close this dialog?")); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::Yes); + int ret = msgBox.exec(); + if (ret == QMessageBox::Yes) + Gui::Control().reject(); + else + return false; + } + + // start the edit dialog + if (postDlg) + Gui::Control().showDialog(postDlg); + else { + postDlg = new TaskDlgPost(this); + setupTaskDialog(postDlg); + Gui::Control().showDialog(postDlg); + } + + return true; + } + else { + return ViewProviderDocumentObject::setEdit(ModNum); + } +} + +void ViewProviderFemPostObject::setupTaskDialog(TaskDlgPost* dlg) { + + dlg->appendBox(new TaskPostDisplay(this)); +} + +void ViewProviderFemPostObject::unsetEdit(int ModNum) { + + if (ModNum == ViewProvider::Default) { + // and update the pad + //getSketchObject()->getDocument()->recompute(); + + // when pressing ESC make sure to close the dialog + Gui::Control().closeDialog(); + } + else { + ViewProviderDocumentObject::unsetEdit(ModNum); + } +} + diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostObject.h b/src/Mod/Fem/Gui/ViewProviderFemPostObject.h index 249ce2e0f..938878708 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostObject.h +++ b/src/Mod/Fem/Gui/ViewProviderFemPostObject.h @@ -58,6 +58,8 @@ class SoIndexedTriangleStripSet; namespace FemGui { +class TaskDlgPost; + class FemGuiExport ViewProviderFemPostObject : public Gui::ViewProviderDocumentObject { PROPERTY_HEADER(FemGui::ViewProviderFemPostObject); @@ -69,8 +71,9 @@ public: /// destructor. ~ViewProviderFemPostObject(); - App::PropertyEnumeration Coloring; - App::PropertyIntegerConstraint Transperency; + App::PropertyEnumeration Field; + App::PropertyEnumeration VectorMode; + App::PropertyPercent Transperency; void attach(App::DocumentObject *pcObject); void setDisplayMode(const char* ModeName); @@ -78,6 +81,11 @@ public: void updateData(const App::Property*); void onChanged(const App::Property* prop); + //edit handling + virtual bool doubleClicked(void); + virtual bool setEdit(int ModNum); + virtual void unsetEdit(int ModNum); + /** @name Selection handling * This group of methodes do the selection handling. * Here you can define how the selection for your ViewProvider @@ -94,6 +102,7 @@ public: // //@} protected: + virtual void setupTaskDialog(TaskDlgPost* dlg); bool setupPipeline(); void update(); @@ -118,14 +127,14 @@ protected: vtkSmartPointer m_lookup; private: + void updateProperties(); void update3D(); void WritePointData(vtkPoints *points, vtkDataArray *normals, vtkDataArray *tcoords); void WriteColorData(); void WriteTransperency(); - App::Enumeration m_coloringEnum; - App::PropertyIntegerConstraint::Constraints m_transperencyConstraint; + App::Enumeration m_coloringEnum, m_vectorEnum; bool m_blockPropertyChanges; }; diff --git a/src/Mod/Fem/Gui/Workbench.cpp b/src/Mod/Fem/Gui/Workbench.cpp index 0505a9bc2..81f10435d 100755 --- a/src/Mod/Fem/Gui/Workbench.cpp +++ b/src/Mod/Fem/Gui/Workbench.cpp @@ -83,7 +83,10 @@ Gui::ToolBarItem* Workbench::setupToolBars() const Gui::ToolBarItem* post = new Gui::ToolBarItem(root); post->setCommand("Post Processing"); *post << "Fem_PostApplyChanges" + << "Separator" << "Fem_PostCreateClipFilter" + << "Fem_PostCreateScalarClipFilter" + << "Separator" << "Fem_PostCreateFunctions"; #endif