From 2b9e608501572c0c18927bba09b13bd1a57a1d90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Tr=C3=B6ger?= Date: Sat, 31 Oct 2015 18:02:53 +0100 Subject: [PATCH] FEM Post: Basic implementation of filter framework --- src/Mod/Fem/App/AppFem.cpp | 8 + src/Mod/Fem/App/AppFem.cpp.orig | 21 +- src/Mod/Fem/App/AppFemPy.cpp | 1 + src/Mod/Fem/App/AppFemPy.cpp.orig | 44 +- src/Mod/Fem/App/CMakeLists.txt | 2 + src/Mod/Fem/App/CMakeLists.txt.orig | 27 +- src/Mod/Fem/App/FemPostFilter.cpp | 186 +- src/Mod/Fem/App/FemPostFilter.h | 67 +- src/Mod/Fem/App/FemPostFunction.cpp | 98 + src/Mod/Fem/App/FemPostFunction.h | 109 + src/Mod/Fem/App/FemPostObject.cpp | 47 +- src/Mod/Fem/App/FemPostObject.h | 14 +- src/Mod/Fem/App/FemPostPipeline.cpp | 98 +- src/Mod/Fem/App/FemPostPipeline.h | 26 +- src/Mod/Fem/Gui/AppFemGui.cpp | 10 + src/Mod/Fem/Gui/CMakeLists.txt | 4 + src/Mod/Fem/Gui/Command.cpp | 222 +- src/Mod/Fem/Gui/Command.cpp.orig | 1779 +++++++++++++++++ .../Fem/Gui/ViewProviderFemPostFunction.cpp | 246 +++ src/Mod/Fem/Gui/ViewProviderFemPostFunction.h | 102 + src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp | 4 +- .../Fem/Gui/ViewProviderFemPostPipeline.cpp | 59 + src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h | 49 + src/Mod/Fem/Gui/Workbench.cpp | 241 +-- 24 files changed, 3223 insertions(+), 241 deletions(-) create mode 100644 src/Mod/Fem/App/FemPostFunction.cpp create mode 100644 src/Mod/Fem/App/FemPostFunction.h create mode 100644 src/Mod/Fem/Gui/Command.cpp.orig create mode 100644 src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp create mode 100644 src/Mod/Fem/Gui/ViewProviderFemPostFunction.h create mode 100644 src/Mod/Fem/Gui/ViewProviderFemPostPipeline.cpp create mode 100644 src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h diff --git a/src/Mod/Fem/App/AppFem.cpp b/src/Mod/Fem/App/AppFem.cpp index b3908485b..2ce88a60c 100644 --- a/src/Mod/Fem/App/AppFem.cpp +++ b/src/Mod/Fem/App/AppFem.cpp @@ -54,8 +54,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(); @@ -151,5 +155,9 @@ 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 } diff --git a/src/Mod/Fem/App/AppFem.cpp.orig b/src/Mod/Fem/App/AppFem.cpp.orig index 4428ed7c9..b247959bc 100644 --- a/src/Mod/Fem/App/AppFem.cpp.orig +++ b/src/Mod/Fem/App/AppFem.cpp.orig @@ -1,4 +1,4 @@ -<<<<<<< 09326bbbdaf756fe381d51d340e0db27fd8c452a +<<<<<<< eec6f7aee8b6e5979a799358e2ae69bdc5a7af5b /*************************************************************************** * Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) * * * @@ -55,6 +55,8 @@ #include "FemResultObject.h" #include "FemSolverObject.h" +#include "FemPostPipeline.h" +#include "FemPostFilter.h" namespace Fem { extern PyObject* initModule(); @@ -143,9 +145,14 @@ PyMODINIT_FUNC initFem() Fem::ConstraintDisplacement ::init(); Fem::FemResultObject ::init(); - Fem::FemResultObjectPython ::init(); Fem::FemSolverObject ::init(); Fem::FemSolverObjectPython ::init(); + +#ifdef FC_USE_VTK + Fem::FemPostObject ::init(); + Fem::FemPostPipeline ::init(); + Fem::FemPostFilter ::init(); +#endif } ======= /*************************************************************************** @@ -204,8 +211,12 @@ PyMODINIT_FUNC initFem() #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(); @@ -301,6 +312,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 } ->>>>>>> Move post processing to fem objects +>>>>>>> Basic implementation of filter framework diff --git a/src/Mod/Fem/App/AppFemPy.cpp b/src/Mod/Fem/App/AppFemPy.cpp index 0d6ea8325..b46b09488 100644 --- a/src/Mod/Fem/App/AppFemPy.cpp +++ b/src/Mod/Fem/App/AppFemPy.cpp @@ -187,6 +187,7 @@ private: pcFeature->Label.setValue(file.fileNamePure().c_str()); pcFeature->read(file); pcFeature->touch(); + pcDoc->recomputeFeature(pcFeature); } else throw e; diff --git a/src/Mod/Fem/App/AppFemPy.cpp.orig b/src/Mod/Fem/App/AppFemPy.cpp.orig index fb705ba00..8fa49efb5 100644 --- a/src/Mod/Fem/App/AppFemPy.cpp.orig +++ b/src/Mod/Fem/App/AppFemPy.cpp.orig @@ -1,4 +1,4 @@ -<<<<<<< 09326bbbdaf756fe381d51d340e0db27fd8c452a +<<<<<<< eec6f7aee8b6e5979a799358e2ae69bdc5a7af5b /*************************************************************************** * Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) * * * @@ -65,6 +65,7 @@ #include "FemMesh.h" #include "FemMeshObject.h" +#include "FemPostPipeline.h" #include "FemMeshPy.h" #include @@ -164,16 +165,36 @@ private: pcDoc = App::GetApplication().newDocument(DocName); } - std::auto_ptr mesh(new FemMesh); - mesh->read(EncodedName.c_str()); Base::FileInfo file(EncodedName.c_str()); - - FemMeshObject *pcFeature = static_cast - (pcDoc->addObject("Fem::FemMeshObject", file.fileNamePure().c_str())); - pcFeature->Label.setValue(file.fileNamePure().c_str()); - pcFeature->FemMesh.setValuePtr(mesh.get()); - (void)mesh.release(); - pcFeature->purgeTouched(); + + try { + std::auto_ptr mesh(new FemMesh); + mesh->read(EncodedName.c_str()); + + FemMeshObject *pcFeature = static_cast + (pcDoc->addObject("Fem::FemMeshObject", file.fileNamePure().c_str())); + pcFeature->Label.setValue(file.fileNamePure().c_str()); + pcFeature->FemMesh.setValuePtr(mesh.get()); + (void)mesh.release(); + pcFeature->purgeTouched(); + } + catch(Base::Exception& e) { +#ifdef FC_USE_VTK + if( FemPostPipeline::canRead(file) ) { + + FemPostPipeline *pcFeature = static_cast + (pcDoc->addObject("Fem::FemPostPipeline", file.fileNamePure().c_str())); + + pcFeature->Label.setValue(file.fileNamePure().c_str()); + pcFeature->read(file); + pcFeature->touch(); + } + else + throw e; +#else + throw e; +#endif + } return Py::None(); } @@ -432,6 +453,7 @@ private: pcFeature->Label.setValue(file.fileNamePure().c_str()); pcFeature->read(file); pcFeature->touch(); + pcDoc->recomputeFeature(pcFeature); } else throw e; @@ -507,4 +529,4 @@ PyObject* initModule() } } // namespace Fem ->>>>>>> Move post processing to fem objects +>>>>>>> Basic implementation of filter framework diff --git a/src/Mod/Fem/App/CMakeLists.txt b/src/Mod/Fem/App/CMakeLists.txt index cfd654b8f..805172815 100755 --- a/src/Mod/Fem/App/CMakeLists.txt +++ b/src/Mod/Fem/App/CMakeLists.txt @@ -208,6 +208,8 @@ if(BUILD_FEM_VTK) FemPostPipeline.cpp FemPostFilter.h FemPostFilter.cpp + FemPostFunction.h + FemPostFunction.cpp ) SOURCE_GROUP("PostObjects" FILES ${FemPost_SRCS}) endif(BUILD_FEM_VTK) diff --git a/src/Mod/Fem/App/CMakeLists.txt.orig b/src/Mod/Fem/App/CMakeLists.txt.orig index 9ef85bfa7..abfb11da3 100755 --- a/src/Mod/Fem/App/CMakeLists.txt.orig +++ b/src/Mod/Fem/App/CMakeLists.txt.orig @@ -189,17 +189,6 @@ SET(FemConstraints_SRCS ) SOURCE_GROUP("Constraints" FILES ${FemConstraints_SRCS}) -<<<<<<< 09326bbbdaf756fe381d51d340e0db27fd8c452a -SET(FemResult_SRCS - ) -SOURCE_GROUP("ResultObjects" FILES ${FemResult_SRCS}) - -SET(Fem_SRCS - ${FemBase_SRCS} - ${FemSet_SRCS} - ${FemConstraints_SRCS} - ${FemResult_SRCS} -======= if(BUILD_FEM_VTK) SET(FemPost_SRCS FemPostObject.h @@ -208,17 +197,23 @@ if(BUILD_FEM_VTK) FemPostPipeline.cpp FemPostFilter.h FemPostFilter.cpp +<<<<<<< eec6f7aee8b6e5979a799358e2ae69bdc5a7af5b + ) +======= + FemPostFunction.h + FemPostFunction.cpp ) +>>>>>>> Basic implementation of filter framework SOURCE_GROUP("PostObjects" FILES ${FemPost_SRCS}) endif(BUILD_FEM_VTK) SET(Fem_SRCS - ${FemBase_SRCS} - ${FemSet_SRCS} - ${FemConstraints_SRCS} - ${FemPost_SRCS} ->>>>>>> Move post processing to fem objects + ${FemBase_SRCS} + ${FemSet_SRCS} + ${FemConstraints_SRCS} + ${FemResult_SRCS} +....${FemPost_SRCS} ${Mod_SRCS} ${Python_SRCS} ) diff --git a/src/Mod/Fem/App/FemPostFilter.cpp b/src/Mod/Fem/App/FemPostFilter.cpp index c71bec98a..7950009e8 100644 --- a/src/Mod/Fem/App/FemPostFilter.cpp +++ b/src/Mod/Fem/App/FemPostFilter.cpp @@ -27,6 +27,8 @@ #endif #include "FemPostFilter.h" +#include "FemPostPipeline.h" +#include #include using namespace Fem; @@ -37,30 +39,188 @@ PROPERTY_SOURCE(Fem::FemPostFilter, Fem::FemPostObject) FemPostFilter::FemPostFilter() { + m_pass = vtkPassThrough::New(); } FemPostFilter::~FemPostFilter() { } -short FemPostFilter::mustExecute(void) const -{ - return 0; +bool FemPostFilter::valid() { + return polyDataSource && !m_pipelines.empty() && !m_activePipeline.empty(); } -PyObject *FemPostFilter::getPyObject() -{ - if (PythonObject.is(Py::_None())){ - // ref counter is set to 1 - PythonObject = Py::Object(new DocumentObjectPy(this),true); +bool FemPostFilter::isConnected() { + return valid() && (m_pipelines[m_activePipeline].source->GetTotalNumberOfInputConnections() > 0); +} + +bool FemPostFilter::providesPolyData() { + return isConnected(); +} + + +DocumentObjectExecReturn* FemPostFilter::execute(void) { + + if(isConnected()) { + + FilterPipeline& pipe = m_pipelines[m_activePipeline]; + if(pipe.source->GetTotalNumberOfInputConnections() > 0) { + pipe.target->Update(); + return Fem::FemPostObject::execute(); + } } - return Py::new_reference_to(PythonObject); + + return StdReturn; } -void FemPostFilter::onChanged(const Property* prop) -{ - App::GeoFeature::onChanged(prop); - // if the placement has changed apply the change to the grid data as well +void FemPostFilter::clearInput() { + + if(isConnected()) { + for(std::map::iterator it = m_pipelines.begin(); it != m_pipelines.end(); ++it) { + it->second.source->RemoveAllInputConnections(0); + it->second.source->RemoveAllInputs(); + } + polyDataSource->RemoveAllInputConnections(0); + } +} + +bool FemPostFilter::hasInputAlgorithmConnected() { + + return isConnected(); +} + +void FemPostFilter::connectInputAlgorithm(vtkSmartPointer< vtkAlgorithm > algo) { + + clearInput(); + if(isValid()) { + for(std::map::iterator it = m_pipelines.begin(); it != m_pipelines.end(); ++it) { + it->second.source->SetInputConnection(algo->GetOutputPort()); + } + polyDataSource->SetInputConnection(m_pipelines[m_activePipeline].visualisation->GetOutputPort()); + touch(); + } +} + +vtkSmartPointer< vtkAlgorithm > FemPostFilter::getConnectedInputAlgorithm() { + + if(!isConnected()) + return vtkSmartPointer< vtkAlgorithm >(); + + return m_pipelines[m_activePipeline].source->GetInputAlgorithm(0,0); +} + +bool FemPostFilter::hasInputDataConnected() { + + if(!isValid()) + return false; + + return (m_pipelines[m_activePipeline].source->GetInputDataObject(0,0) != NULL); +} + + +void FemPostFilter::connectInputData(vtkSmartPointer< vtkDataSet > data) { + + clearInput(); + if(isValid()) { + + for(std::map::iterator it = m_pipelines.begin(); it != m_pipelines.end(); ++it) { + it->second.source->SetInputDataObject(data); + } + polyDataSource->SetInputConnection(m_pipelines[m_activePipeline].visualisation->GetOutputPort()); + touch(); + } +} + +vtkSmartPointer< vtkDataObject > FemPostFilter::getConnectedInputData() { + + if(!isValid()) + return vtkSmartPointer< vtkDataSet >(); + + return m_pipelines[m_activePipeline].source->GetInputDataObject(0,0); +} + +vtkSmartPointer< vtkAlgorithm > FemPostFilter::getOutputAlgorithm() { + return m_pass; +} + + +void FemPostFilter::addFilterPipeline(const FemPostFilter::FilterPipeline& p, std::string name) { + m_pipelines[name] = p; +} + +FemPostFilter::FilterPipeline& FemPostFilter::getFilterPipeline(std::string name) { + return m_pipelines[name]; +} + +void FemPostFilter::setActiveFilterPipeline(std::string name) { + + if(m_activePipeline != name && isValid()) { + m_activePipeline = name; + m_pass->RemoveAllInputConnections(0); + polyDataSource->RemoveAllInputConnections(0); + polyDataSource->SetInputConnection(m_pipelines[m_activePipeline].visualisation->GetOutputPort()); + m_pass->SetInputConnection(m_pipelines[m_activePipeline].target->GetOutputPort()); + } +} + + + +PROPERTY_SOURCE(Fem::FemPostClipFilter, Fem::FemPostFilter) + +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(); + clip.source = m_clipper; + clip.target = m_clipper; + clip.visualisation = m_clipper; + addFilterPipeline(clip, "clip"); + + FilterPipeline extr; + m_extractor = vtkExtractGeometry::New(); + extr.source = m_extractor; + extr.target = m_extractor; + extr.visualisation = m_extractor; + addFilterPipeline(extr, "extract"); + + m_extractor->SetExtractInside(0); + setActiveFilterPipeline("extract"); +} + +FemPostClipFilter::~FemPostClipFilter() { } + +void FemPostClipFilter::onChanged(const Property* prop) { + + if(prop == &Function) { + + if(Function.getValue() && Function.getValue()->isDerivedFrom(FemPostFunction::getClassTypeId())) { + m_clipper->SetClipFunction(static_cast(Function.getValue())->getImplicitFunction()); + m_extractor->SetImplicitFunction(static_cast(Function.getValue())->getImplicitFunction()); + } + } + else if(prop == &InsideOut) { + + m_clipper->SetInsideOut(InsideOut.getValue()); + m_extractor->SetExtractInside( (InsideOut.getValue()) ? 1 : 0 ); + } + else if(prop == &CutCells) { + + if(!CutCells.getValue()) + setActiveFilterPipeline("extract"); + else + setActiveFilterPipeline("clip"); + }; + + Fem::FemPostFilter::onChanged(prop); +} + + diff --git a/src/Mod/Fem/App/FemPostFilter.h b/src/Mod/Fem/App/FemPostFilter.h index 40d1bb959..8b2e7e939 100644 --- a/src/Mod/Fem/App/FemPostFilter.h +++ b/src/Mod/Fem/App/FemPostFilter.h @@ -27,7 +27,11 @@ #include "FemPostObject.h" #include -#include +#include +#include +#include +#include +#include namespace Fem { @@ -40,19 +44,64 @@ public: /// Constructor FemPostFilter(void); virtual ~FemPostFilter(); + + virtual App::DocumentObjectExecReturn* execute(void); + + vtkSmartPointer getOutputAlgorithm(); + + bool hasInputAlgorithmConnected(); + void connectInputAlgorithm(vtkSmartPointer algo); + vtkSmartPointer getConnectedInputAlgorithm(); + + bool hasInputDataConnected(); + void connectInputData(vtkSmartPointer data); + vtkSmartPointer getConnectedInputData(); + void clearInput(); + + //returns true if the pipelines are set up correctly + bool valid(); + //returns true if the filter is valid and connected + bool isConnected(); + //override poly data providing to let the object know we only provide poly data if connected + //to something + virtual bool providesPolyData(); - /// returns the type name of the ViewProvider - virtual const char* getViewProviderName(void) const { - return "FemGui::ViewProviderPostPipeline"; - } - short mustExecute(void) const; - PyObject* getPyObject(); +protected: + //pipeline handling for derived filter + struct FilterPipeline { + vtkSmartPointer source, target, visualisation; + std::vector > algorithmStorage; + }; + + void addFilterPipeline(const FilterPipeline& p, std::string name); + void setActiveFilterPipeline(std::string name); + FilterPipeline& getFilterPipeline(std::string name); + +private: + //handling of multiple pipelines which can be the filter + std::map m_pipelines; + std::string m_activePipeline; + vtkSmartPointer m_pass; +}; +class AppFemExport FemPostClipFilter : public FemPostFilter { + + PROPERTY_HEADER(Fem::FemPostClipFilter); + +public: + FemPostClipFilter(void); + virtual ~FemPostClipFilter(); + + App::PropertyLink Function; + App::PropertyBool InsideOut; + App::PropertyBool CutCells; + protected: virtual void onChanged(const App::Property* prop); - //members - vtkSmartPointer source; +private: + vtkSmartPointer m_clipper; + vtkSmartPointer m_extractor; }; } //namespace Fem diff --git a/src/Mod/Fem/App/FemPostFunction.cpp b/src/Mod/Fem/App/FemPostFunction.cpp new file mode 100644 index 000000000..d1172eacd --- /dev/null +++ b/src/Mod/Fem/App/FemPostFunction.cpp @@ -0,0 +1,98 @@ +/*************************************************************************** + * 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 "FemPostFunction.h" +#include + +using namespace Fem; +using namespace App; + +PROPERTY_SOURCE(Fem::FemPostFunctionProvider, App::DocumentObject) + +FemPostFunctionProvider::FemPostFunctionProvider(void): DocumentObject() { + + ADD_PROPERTY(Functions, (0)); +} + +FemPostFunctionProvider::~FemPostFunctionProvider() { + +} + +void FemPostFunctionProvider::onChanged(const Property* prop) { + App::DocumentObject::onChanged(prop); +} + + +PROPERTY_SOURCE(Fem::FemPostFunction, App::DocumentObject) + +FemPostFunction::FemPostFunction() +{ +} + +FemPostFunction::~FemPostFunction() +{ +} + +DocumentObjectExecReturn* FemPostFunction::execute(void) { + + return DocumentObject::StdReturn; +} + + +PROPERTY_SOURCE(Fem::FemPostPlaneFunction, Fem::FemPostFunction) + +FemPostPlaneFunction::FemPostPlaneFunction(void): FemPostFunction() { + + ADD_PROPERTY(Origin,(Base::Vector3d(0.0,0.0,0.0))); + ADD_PROPERTY(Normal,(Base::Vector3d(1.0,0.0,0.0))); + + m_plane = vtkPlane::New(); + m_implicit = m_plane; + + m_plane->SetOrigin(0., 0., 0.); + m_plane->SetNormal(1., 0., 0.); +} + +FemPostPlaneFunction::~FemPostPlaneFunction() { + +} + +void FemPostPlaneFunction::onChanged(const Property* prop) { + + Base::Console().Message("Changed origin and normal\n"); + if(prop == &Origin) { + const Base::Vector3d& vec = Origin.getValue(); + m_plane->SetOrigin(vec[0], vec[1], vec[2]); + } + else if(prop == &Normal) { + const Base::Vector3d& vec = Normal.getValue(); + m_plane->SetNormal(vec[0], vec[1], vec[2]); + } + + Fem::FemPostFunction::onChanged(prop); +} diff --git a/src/Mod/Fem/App/FemPostFunction.h b/src/Mod/Fem/App/FemPostFunction.h new file mode 100644 index 000000000..81e90fed0 --- /dev/null +++ b/src/Mod/Fem/App/FemPostFunction.h @@ -0,0 +1,109 @@ +/*************************************************************************** + * 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_FemPostFunction_H +#define Fem_FemPostFunction_H + +#include "FemPostObject.h" + +#include +#include +#include +#include + +namespace Fem +{ + +class AppFemExport FemPostFunction : public App::DocumentObject +{ + PROPERTY_HEADER(Fem::FemPostFunction); + +public: + /// Constructor + FemPostFunction(void); + virtual ~FemPostFunction(); + + virtual const char* getViewProviderName(void) const { + return "FemGui::ViewProviderFemPostFunction"; + } + + virtual App::DocumentObjectExecReturn* execute(void); + + //bound box handling + void setBoundingBox(vtkBoundingBox b) {m_boundingBox = b;}; + + //get the algorithm or the data + vtkSmartPointer getImplicitFunction() {return m_implicit;}; + +protected: + vtkSmartPointer m_implicit; + vtkBoundingBox m_boundingBox; +}; + +class FemPostFunctionProvider : public App::DocumentObject { + + PROPERTY_HEADER(Fem::FemPostFunctionProvider); + +public: + FemPostFunctionProvider(void); + virtual ~FemPostFunctionProvider(); + + virtual const char* getViewProviderName(void) const { + return "FemGui::ViewProviderFemPostFunctionProvider"; + } + + App::PropertyLinkList Functions; + +protected: + virtual void onChanged(const App::Property* prop); +}; + + +//////////////////////////////////////////////////////////////////////////////////////////// + +class AppFemExport FemPostPlaneFunction : public FemPostFunction +{ + PROPERTY_HEADER(Fem::FemPostPlaneFunction); + +public: + + FemPostPlaneFunction(void); + virtual ~FemPostPlaneFunction(); + + App::PropertyVector Normal; + App::PropertyVectorDistance Origin; + + virtual const char* getViewProviderName(void) const { + return "FemGui::ViewProviderFemPostPlaneFunction"; + } + +protected: + virtual void onChanged(const App::Property* prop); + + vtkSmartPointer m_plane; +}; + +} //namespace Fem + + +#endif // Fem_FemPostFunction_H diff --git a/src/Mod/Fem/App/FemPostObject.cpp b/src/Mod/Fem/App/FemPostObject.cpp index 6fa4eefc8..e3d44a623 100644 --- a/src/Mod/Fem/App/FemPostObject.cpp +++ b/src/Mod/Fem/App/FemPostObject.cpp @@ -28,6 +28,8 @@ #include "FemPostObject.h" #include +#include +#include #include #include #include @@ -53,42 +55,25 @@ short FemPostObject::mustExecute(void) const } DocumentObjectExecReturn* FemPostObject::execute(void) { - - //analyse the data and print - Base::Console().Message("\nPoly Data Analysis:\n"); - - vtkPolyData* poly = polyDataSource->GetOutput(); - vtkPointData* point = poly->GetPointData(); - Base::Console().Message("Point components: %i\n", point->GetNumberOfComponents()); - Base::Console().Message("Point arrays: %i\n", point->GetNumberOfArrays()); - Base::Console().Message("Point tuples: %i\n", point->GetNumberOfTuples()); - - vtkCellData* cell = poly->GetCellData(); - Base::Console().Message("Cell components: %i\n", cell->GetNumberOfComponents()); - Base::Console().Message("Cell arrays: %i\n", cell->GetNumberOfArrays()); - Base::Console().Message("Point tuples: %i\n", cell->GetNumberOfTuples()); - - - if(polyDataSource && static_cast(ModificationTime.getValue()) < polyDataSource->GetMTime()) - ModificationTime.setValue(static_cast(polyDataSource->GetMTime())); + + if(providesPolyData()) { + polyDataSource->Update(); + vtkSmartPointer poly = polyDataSource->GetOutput(); + + if(static_cast(ModificationTime.getValue()) != poly->GetMTime()) { + + //update the bounding box + m_boundingBox = vtkBoundingBox(poly->GetBounds()); + + //update the modification time to let the viewprovider know something changed + ModificationTime.setValue(static_cast(poly->GetMTime())); + } + } return DocumentObject::StdReturn; } - -PyObject *FemPostObject::getPyObject() -{ - if (PythonObject.is(Py::_None())){ - // ref counter is set to 1 - PythonObject = Py::Object(new DocumentObjectPy(this),true); - } - return Py::new_reference_to(PythonObject); -} - void FemPostObject::onChanged(const Property* prop) { App::GeoFeature::onChanged(prop); - - // if the placement has changed apply the change to the grid data as well - } diff --git a/src/Mod/Fem/App/FemPostObject.h b/src/Mod/Fem/App/FemPostObject.h index ed50819c8..0907ceb05 100644 --- a/src/Mod/Fem/App/FemPostObject.h +++ b/src/Mod/Fem/App/FemPostObject.h @@ -28,6 +28,7 @@ #include #include +#include namespace Fem { @@ -52,11 +53,13 @@ public: short mustExecute(void) const; virtual App::DocumentObjectExecReturn* execute(void); - PyObject* getPyObject(); + //bounding box handling. By default the bounding box is calcualted from the poly data output + //which is visualized + virtual vtkBoundingBox getBoundingBox() {return m_boundingBox;}; - //get the algorithm or the data - vtkPolyData* getPolyData() {return polyDataSource->GetOutput();}; - vtkSmartPointer getPolyAlgorithm() {return polyDataSource;}; + //poly data algorithm handling + virtual bool providesPolyData() {return getPolyAlgorithm()!=NULL;}; + vtkSmartPointer getPolyAlgorithm() {return polyDataSource;}; protected: @@ -64,6 +67,9 @@ protected: //members vtkSmartPointer polyDataSource; + +private: + vtkBoundingBox m_boundingBox; }; } //namespace Fem diff --git a/src/Mod/Fem/App/FemPostPipeline.cpp b/src/Mod/Fem/App/FemPostPipeline.cpp index 52fa6d7e8..608f6fc69 100644 --- a/src/Mod/Fem/App/FemPostPipeline.cpp +++ b/src/Mod/Fem/App/FemPostPipeline.cpp @@ -28,21 +28,31 @@ #include "FemPostPipeline.h" #include +#include #include #include #include #include #include #include +#include using namespace Fem; using namespace App; PROPERTY_SOURCE(Fem::FemPostPipeline, Fem::FemPostObject) - +const char* FemPostPipeline::ModeEnums[]= {"Serial","Parallel",NULL}; FemPostPipeline::FemPostPipeline() { + ADD_PROPERTY_TYPE(Filter, (0), "Pipeline", App::Prop_None, "The filter used in in this pipeline"); + ADD_PROPERTY_TYPE(Function, (0), "Pipeline", App::Prop_Hidden, "The function provider which groups all pipeline functions"); + ADD_PROPERTY_TYPE(Mode,(long(0)), "Pipeline", App::Prop_None, "Selects the pipeline data transition mode. In serial every filter" + "gets the output of the previous one as input, in parrallel every" + "filter gets the pipelien source as input."); + Mode.setEnums(ModeEnums); + + source = vtkUnstructuredGrid::New(); } FemPostPipeline::~FemPostPipeline() @@ -51,27 +61,26 @@ FemPostPipeline::~FemPostPipeline() short FemPostPipeline::mustExecute(void) const { - return 1; } DocumentObjectExecReturn* FemPostPipeline::execute(void) { - Base::Console().Message("Pipeline analysis: \n"); - Base::Console().Message("Data Type: %i\n", source->GetDataObjectType()); - - if(source->GetDataObjectType() == VTK_STRUCTURED_GRID ) { - vtkStructuredGrid* poly = static_cast(source.GetPointer()); - vtkPointData* point = poly->GetPointData(); - Base::Console().Message("Point components: %i\n", point->GetNumberOfComponents()); - Base::Console().Message("Point arrays: %i\n", point->GetNumberOfArrays()); - Base::Console().Message("Point tuples: %i\n", point->GetNumberOfTuples()); - - vtkCellData* cell = poly->GetCellData(); - Base::Console().Message("Cell components: %i\n", cell->GetNumberOfComponents()); - Base::Console().Message("Cell arrays: %i\n", cell->GetNumberOfArrays()); - Base::Console().Message("Point tuples: %i\n", cell->GetNumberOfTuples()); - } +// Base::Console().Message("Pipeline analysis: \n"); +// Base::Console().Message("Data Type: %i\n", source->GetDataObjectType()); +// +// if(source->GetDataObjectType() == VTK_STRUCTURED_GRID ) { +// vtkStructuredGrid* poly = static_cast(source.GetPointer()); +// vtkPointData* point = poly->GetPointData(); +// Base::Console().Message("Point components: %i\n", point->GetNumberOfComponents()); +// Base::Console().Message("Point arrays: %i\n", point->GetNumberOfArrays()); +// Base::Console().Message("Point tuples: %i\n", point->GetNumberOfTuples()); +// +// vtkCellData* cell = poly->GetCellData(); +// Base::Console().Message("Cell components: %i\n", cell->GetNumberOfComponents()); +// Base::Console().Message("Cell arrays: %i\n", cell->GetNumberOfArrays()); +// Base::Console().Message("Point tuples: %i\n", cell->GetNumberOfTuples()); +// } return Fem::FemPostObject::execute(); } @@ -110,19 +119,54 @@ void FemPostPipeline::read(Base::FileInfo File) { } -PyObject *FemPostPipeline::getPyObject() -{ - if (PythonObject.is(Py::_None())){ - // ref counter is set to 1 - PythonObject = Py::Object(new DocumentObjectPy(this),true); - } - return Py::new_reference_to(PythonObject); -} +// PyObject *FemPostPipeline::getPyObject() +// { +// if (PythonObject.is(Py::_None())){ +// // ref counter is set to 1 +// PythonObject = Py::Object(new DocumentObjectPy(this),true); +// } +// return Py::new_reference_to(PythonObject); +// } void FemPostPipeline::onChanged(const Property* prop) { + if(prop == &Filter || prop == &Mode) { + + //we check if all connections are right and add new ones if needed + std::vector objs = Filter.getValues(); + std::vector::iterator it = objs.begin(); + FemPostFilter* filter = static_cast(*it); + + //the first one is always connected to the pipeline + if(!filter->hasInputDataConnected() || filter->getConnectedInputData() != getSource()) + filter->connectInputData(getSource()); + + //all the others need to be connected to the previous filter or the source, dependend on the mode + ++it; + for(; it != objs.end(); ++it) { + FemPostFilter* nextFilter = static_cast(*it); + + if(Mode.getValue() == 0) { + if(!nextFilter->hasInputAlgorithmConnected() || nextFilter->getConnectedInputAlgorithm() != filter->getOutputAlgorithm()) + nextFilter->connectInputAlgorithm(filter->getOutputAlgorithm()); + } + else { + if(!nextFilter->hasInputDataConnected() || nextFilter->getConnectedInputData() != getSource()) + nextFilter->connectInputData(getSource()); + } + + filter = nextFilter; + }; + } + App::GeoFeature::onChanged(prop); - // if the placement has changed apply the change to the grid data as well - +} + +FemPostObject* FemPostPipeline::getLastPostObject() { + + if(Filter.getValues().empty()) + return this; + + return static_cast(Filter.getValues().back()); } diff --git a/src/Mod/Fem/App/FemPostPipeline.h b/src/Mod/Fem/App/FemPostPipeline.h index 24d32689a..c3ad8ca52 100644 --- a/src/Mod/Fem/App/FemPostPipeline.h +++ b/src/Mod/Fem/App/FemPostPipeline.h @@ -25,6 +25,8 @@ #define Fem_FemPostPipeline_H #include "FemPostObject.h" +#include "FemPostFilter.h" +#include "FemPostFunction.h" #include #include @@ -40,25 +42,33 @@ public: /// Constructor FemPostPipeline(void); virtual ~FemPostPipeline(); - - /// returns the type name of the ViewProvider -// virtual const char* getViewProviderName(void) const { -// return "FemGui::ViewProviderPostPipeline"; -// } + + App::PropertyLinkList Filter; + App::PropertyLink Function; + App::PropertyEnumeration Mode; short mustExecute(void) const; virtual App::DocumentObjectExecReturn* execute(void); - PyObject* getPyObject(); - + //PyObject* getPyObject(); + + virtual const char* getViewProviderName(void) const { + return "FemGui::ViewProviderFemPostPipeline"; + } + //load data from files static bool canRead(Base::FileInfo file); void read(Base::FileInfo file); + //Pipeline handling + vtkSmartPointer getSource() {return source;}; + FemPostObject* getLastPostObject(); + protected: virtual void onChanged(const App::Property* prop); - //members +private: vtkSmartPointer source; + static const char* ModeEnums[]; }; } //namespace Fem diff --git a/src/Mod/Fem/Gui/AppFemGui.cpp b/src/Mod/Fem/Gui/AppFemGui.cpp index 470f16818..1b8340587 100644 --- a/src/Mod/Fem/Gui/AppFemGui.cpp +++ b/src/Mod/Fem/Gui/AppFemGui.cpp @@ -55,6 +55,12 @@ #include "ViewProviderResult.h" #include "Workbench.h" +#ifdef FC_USE_VTK +#include "ViewProviderFemPostObject.h" +#include "ViewProviderFemPostPipeline.h" +#include "ViewProviderFemPostFunction.h" +#endif + #ifdef FC_USE_VTK #include "ViewProviderFemPostObject.h" #endif @@ -116,6 +122,10 @@ PyMODINIT_FUNC initFemGui() #ifdef FC_USE_VTK FemGui::ViewProviderFemPostObject ::init(); + FemGui::ViewProviderFemPostPipeline ::init(); + FemGui::ViewProviderFemPostFunction ::init(); + FemGui::ViewProviderFemPostFunctionProvider::init(); + FemGui::ViewProviderFemPostPlaneFunction ::init(); #endif diff --git a/src/Mod/Fem/Gui/CMakeLists.txt b/src/Mod/Fem/Gui/CMakeLists.txt index 5ed169dfa..9d4d9b9f7 100755 --- a/src/Mod/Fem/Gui/CMakeLists.txt +++ b/src/Mod/Fem/Gui/CMakeLists.txt @@ -213,6 +213,10 @@ if(BUILD_FEM_VTK) SET(FemGui_SRCS_Post ViewProviderFemPostObject.h ViewProviderFemPostObject.cpp + ViewProviderFemPostPipeline.h + ViewProviderFemPostPipeline.cpp + ViewProviderFemPostFunction.h + ViewProviderFemPostFunction.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 7edc26988..e5fae8ca8 100644 --- a/src/Mod/Fem/Gui/Command.cpp +++ b/src/Mod/Fem/Gui/Command.cpp @@ -26,6 +26,7 @@ # include # include # include +#include #endif #include @@ -47,6 +48,7 @@ #include #include #include +#include #include #include @@ -58,9 +60,12 @@ #include #include #include - #include "ActiveAnalysisObserver.h" +#ifdef FC_USE_VTK +#include +#endif + using namespace std; @@ -757,6 +762,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 + //-------------------------------------------------------------------------------------- @@ -775,4 +989,10 @@ 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 } diff --git a/src/Mod/Fem/Gui/Command.cpp.orig b/src/Mod/Fem/Gui/Command.cpp.orig new file mode 100644 index 000000000..e891aab6d --- /dev/null +++ b/src/Mod/Fem/Gui/Command.cpp.orig @@ -0,0 +1,1779 @@ +<<<<<<< eec6f7aee8b6e5979a799358e2ae69bdc5a7af5b +/*************************************************************************** + * Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "ActiveAnalysisObserver.h" + +using namespace std; + + +bool getConstraintPrerequisits(Fem::FemAnalysis **Analysis) +{ + Fem::FemAnalysis* ActiveAnalysis = FemGui::ActiveAnalysisObserver::instance()->getActiveObject(); + if (!ActiveAnalysis || !ActiveAnalysis->getTypeId().isDerivedFrom(Fem::FemAnalysis::getClassTypeId())){ + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("No active Analysis"), + QObject::tr("You need to create or activate a Analysis")); + return true; + } + + *Analysis = static_cast(ActiveAnalysis); + + // return with no error + return false; + +} + +//OvG: Visibility automation show parts and hide meshes on activation of a constraint +std::string gethideMeshShowPartStr(std::string showConstr="") +{ + return "for amesh in App.activeDocument().Objects:\n\ + if \""+showConstr+"\" == amesh.Name:\n\ + amesh.ViewObject.Visibility = True\n\ + elif \"Mesh\" in amesh.TypeId:\n\ + aparttoshow = amesh.Name.replace(\"_Mesh\",\"\")\n\ + for apart in App.activeDocument().Objects:\n\ + if aparttoshow == apart.Name:\n\ + apart.ViewObject.Visibility = True\n\ + amesh.ViewObject.Visibility = False\n"; +} + +//===================================================================================== +DEF_STD_CMD_A(CmdFemCreateAnalysis); + +CmdFemCreateAnalysis::CmdFemCreateAnalysis() + : Command("Fem_CreateAnalysis") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Create a FEM analysis"); + sToolTipText = QT_TR_NOOP("Create a FEM analysis"); + sWhatsThis = "Fem_CreateAnalysis"; + sStatusTip = sToolTipText; + sPixmap = "fem-analysis"; +} + +void CmdFemCreateAnalysis::activated(int iMsg) +{ +#ifndef FCWithNetgen + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Your FreeCAD is build without NETGEN support. Meshing will not work....")); + return; +#endif + + std::vector selection = getSelection().getSelectionEx(); + + if (selection.size() != 1) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge, face or body. Only one body is allowed.")); + return; + } + + if (!selection[0].isObjectTypeOf(Part::Feature::getClassTypeId())){ + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong object type"), + QObject::tr("Fillet works only on parts")); + return; + } + + Part::Feature *base = static_cast(selection[0].getObject()); + + std::string AnalysisName = getUniqueObjectName("FemAnalysis"); + + std::string MeshName = getUniqueObjectName((std::string(base->getNameInDocument()) +"_Mesh").c_str()); + + + openCommand("Create FEM analysis"); + doCommand(Doc,"App.activeDocument().addObject('Fem::FemAnalysis','%s')",AnalysisName.c_str()); + doCommand(Doc,"App.activeDocument().addObject('Fem::FemMeshShapeNetgenObject','%s')",MeshName.c_str()); + doCommand(Doc,"App.activeDocument().ActiveObject.Shape = App.activeDocument().%s",base->getNameInDocument()); + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s",AnalysisName.c_str(),MeshName.c_str()); + addModule(Gui,"FemGui"); + doCommand(Gui,"FemGui.setActiveAnalysis(App.activeDocument().%s)",AnalysisName.c_str()); + commitCommand(); + + updateActive(); +} + +bool CmdFemCreateAnalysis::isActive(void) +{ + return !FemGui::ActiveAnalysisObserver::instance()->hasActiveObject(); +} + +//===================================================================================== + +DEF_STD_CMD_A(CmdFemAddPart); + +CmdFemAddPart::CmdFemAddPart() + : Command("Fem_FemAddPart") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Add a part to the Analysis"); + sToolTipText = QT_TR_NOOP("Add a part to the Analysis"); + sWhatsThis = "Fem_FemAddPart"; + sStatusTip = sToolTipText; + sPixmap = "fem-add-fem-mesh"; +} + +void CmdFemAddPart::activated(int iMsg) +{ +#ifndef FCWithNetgen + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Your FreeCAD is build without NETGEN support. Meshing will not work....")); + return; +#endif + + std::vector selection = getSelection().getSelectionEx(); + + if (selection.size() != 1) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge, face or body. Only one body is allowed.")); + return; + } + + if (!selection[0].isObjectTypeOf(Part::Feature::getClassTypeId())){ + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong object type"), + QObject::tr("Fillet works only on parts")); + return; + } + + Part::Feature *base = static_cast(selection[0].getObject()); + + std::string AnalysisName = getUniqueObjectName("FemAnalysis"); + std::string MeshName = getUniqueObjectName((std::string(base->getNameInDocument()) +"_Mesh").c_str()); + + openCommand("Create FEM analysis"); + doCommand(Doc,"App.activeDocument().addObject('Fem::FemAnalysis','%s')",AnalysisName.c_str()); + doCommand(Doc,"App.activeDocument().addObject('Fem::FemMeshShapeNetgenObject','%s')",MeshName.c_str()); + doCommand(Doc,"App.activeDocument().ActiveObject.Shape = App.activeDocument().%s",base->getNameInDocument()); + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s",AnalysisName.c_str(),MeshName.c_str()); + addModule(Gui,"FemGui"); + doCommand(Gui,"FemGui.setActiveAnalysis(App.activeDocument().%s)",AnalysisName.c_str()); + commitCommand(); + + updateActive(); +} + +bool CmdFemAddPart::isActive(void) +{ + if (Gui::Control().activeDialog()) + return false; + Base::Type type = Base::Type::fromName("Part::Feature"); + return Gui::Selection().countObjectsOfType(type) > 0; +} + +//===================================================================================== + +DEF_STD_CMD_A(CmdFemCreateSolver); + +CmdFemCreateSolver::CmdFemCreateSolver() + : Command("Fem_CreateSolver") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Add a solver to the Analysis"); + sToolTipText = QT_TR_NOOP("Add a solver to the Analysis"); + sWhatsThis = "Fem_CreateSolver"; + sStatusTip = sToolTipText; + sPixmap = "fem-solver"; +} + +void CmdFemCreateSolver::activated(int iMsg) +{ +#ifndef FCWithNetgen + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Your FreeCAD is build without NETGEN support. Meshing will not work....")); + return; +#endif + + Fem::FemAnalysis *Analysis; + + if(getConstraintPrerequisits(&Analysis)) + return; + + std::string FeatName = getUniqueObjectName("Solver"); + + openCommand("Create solver for FEM or CFD analysis"); + doCommand(Doc,"App.activeDocument().addObject(\"Fem::FemSolverObject\",\"%s\")",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s.Member + [App.activeDocument().%s]",Analysis->getNameInDocument(),Analysis->getNameInDocument(),FeatName.c_str()); + updateActive(); + + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); +} + +bool CmdFemCreateSolver::isActive(void) +{ + return hasActiveDocument(); +} + +//===================================================================================== + + +DEF_STD_CMD_A(CmdFemConstraintBearing); + +CmdFemConstraintBearing::CmdFemConstraintBearing() + : Command("Fem_ConstraintBearing") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Create FEM bearing constraint"); + sToolTipText = QT_TR_NOOP("Create FEM constraint for a bearing"); + sWhatsThis = "Fem_ConstraintBearing"; + sStatusTip = sToolTipText; + sPixmap = "fem-constraint-bearing"; +} + +void CmdFemConstraintBearing::activated(int iMsg) +{ + Fem::FemAnalysis *Analysis; + + if(getConstraintPrerequisits(&Analysis)) + return; + + std::string FeatName = getUniqueObjectName("FemConstraintBearing"); + + openCommand("Make FEM constraint for bearing"); + doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintBearing\",\"%s\")",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s.Member + [App.activeDocument().%s]",Analysis->getNameInDocument(),Analysis->getNameInDocument(),FeatName.c_str()); + + doCommand(Doc,"%s",gethideMeshShowPartStr(FeatName).c_str()); //OvG: Hide meshes and show parts + + updateActive(); + + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); +} + +bool CmdFemConstraintBearing::isActive(void) +{ + return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject(); +} + +//===================================================================================== + +DEF_STD_CMD_A(CmdFemConstraintFixed); + +CmdFemConstraintFixed::CmdFemConstraintFixed() + : Command("Fem_ConstraintFixed") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Create FEM fixed constraint"); + sToolTipText = QT_TR_NOOP("Create FEM constraint for a fixed geometric entity"); + sWhatsThis = "Fem_ConstraintFixed"; + sStatusTip = sToolTipText; + sPixmap = "fem-constraint-fixed"; +} + +void CmdFemConstraintFixed::activated(int iMsg) +{ + Fem::FemAnalysis *Analysis; + + if(getConstraintPrerequisits(&Analysis)) + return; + + std::string FeatName = getUniqueObjectName("FemConstraintFixed"); + + openCommand("Make FEM constraint fixed geometry"); + doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintFixed\",\"%s\")",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Scale = 1",FeatName.c_str()); //OvG: set initial scale to 1 + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s.Member + [App.activeDocument().%s]",Analysis->getNameInDocument(),Analysis->getNameInDocument(),FeatName.c_str()); + + doCommand(Doc,"%s",gethideMeshShowPartStr(FeatName).c_str()); //OvG: Hide meshes and show parts + + updateActive(); + + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); +} + +bool CmdFemConstraintFixed::isActive(void) +{ + return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject(); +} + +//===================================================================================== + +DEF_STD_CMD_A(CmdFemConstraintForce); + +CmdFemConstraintForce::CmdFemConstraintForce() + : Command("Fem_ConstraintForce") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Create FEM force constraint"); + sToolTipText = QT_TR_NOOP("Create FEM constraint for a force acting on a geometric entity"); + sWhatsThis = "Fem_ConstraintForce"; + sStatusTip = sToolTipText; + sPixmap = "fem-constraint-force"; +} + +void CmdFemConstraintForce::activated(int iMsg) +{ + Fem::FemAnalysis *Analysis; + + if(getConstraintPrerequisits(&Analysis)) + return; + + std::string FeatName = getUniqueObjectName("FemConstraintForce"); + + openCommand("Make FEM constraint force on geometry"); + doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintForce\",\"%s\")",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Force = 1.0",FeatName.c_str()); //OvG: set default not equal to 0 + doCommand(Doc,"App.activeDocument().%s.Reversed = False",FeatName.c_str()); //OvG: set default to False + doCommand(Doc,"App.activeDocument().%s.Scale = 1",FeatName.c_str()); //OvG: set initial scale to 1 + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s.Member + [App.activeDocument().%s]",Analysis->getNameInDocument(),Analysis->getNameInDocument(),FeatName.c_str()); + + doCommand(Doc,"%s",gethideMeshShowPartStr(FeatName).c_str()); //OvG: Hide meshes and show parts + + updateActive(); + + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); +} + +bool CmdFemConstraintForce::isActive(void) +{ + return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject(); +} + +//===================================================================================== + +DEF_STD_CMD_A(CmdFemConstraintPressure); + +CmdFemConstraintPressure::CmdFemConstraintPressure() + : Command("Fem_ConstraintPressure") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Create FEM pressure constraint"); + sToolTipText = QT_TR_NOOP("Create FEM constraint for a pressure acting on a face"); + sWhatsThis = "Fem_ConstraintPressure"; + sStatusTip = sToolTipText; + sPixmap = "fem-constraint-pressure"; +} + +void CmdFemConstraintPressure::activated(int iMsg) +{ + Fem::FemAnalysis *Analysis; + + if(getConstraintPrerequisits(&Analysis)) + return; + + std::string FeatName = getUniqueObjectName("FemConstraintPressure"); + + openCommand("Make FEM constraint pressure on face"); + doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintPressure\",\"%s\")",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Pressure = 1000.0",FeatName.c_str()); //OvG: set default not equal to 0 + doCommand(Doc,"App.activeDocument().%s.Reversed = False",FeatName.c_str()); //OvG: set default to False + doCommand(Doc,"App.activeDocument().%s.Scale = 1",FeatName.c_str()); //OvG: set initial scale to 1 + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s.Member + [App.activeDocument().%s]", + Analysis->getNameInDocument(),Analysis->getNameInDocument(),FeatName.c_str()); + + doCommand(Doc,"%s",gethideMeshShowPartStr(FeatName).c_str()); //OvG: Hide meshes and show parts + + updateActive(); + + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); +} + +bool CmdFemConstraintPressure::isActive(void) +{ + return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject(); +} + +//===================================================================================== + +DEF_STD_CMD_A(CmdFemConstraintGear); + +CmdFemConstraintGear::CmdFemConstraintGear() + : Command("Fem_ConstraintGear") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Create FEM gear constraint"); + sToolTipText = QT_TR_NOOP("Create FEM constraint for a gear"); + sWhatsThis = "Fem_ConstraintGear"; + sStatusTip = sToolTipText; + sPixmap = "fem-constraint-gear"; +} + +void CmdFemConstraintGear::activated(int iMsg) +{ + Fem::FemAnalysis *Analysis; + + if(getConstraintPrerequisits(&Analysis)) + return; + std::string FeatName = getUniqueObjectName("FemConstraintGear"); + + openCommand("Make FEM constraint for gear"); + doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintGear\",\"%s\")",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Diameter = 100.0",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s.Member + [App.activeDocument().%s]",Analysis->getNameInDocument(),Analysis->getNameInDocument(),FeatName.c_str()); + + doCommand(Doc,"%s",gethideMeshShowPartStr(FeatName).c_str()); //OvG: Hide meshes and show parts + + updateActive(); + + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); +} + +bool CmdFemConstraintGear::isActive(void) +{ + return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject(); +} + +//===================================================================================== + +DEF_STD_CMD_A(CmdFemConstraintPulley); + +CmdFemConstraintPulley::CmdFemConstraintPulley() + : Command("Fem_ConstraintPulley") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Create FEM pulley constraint"); + sToolTipText = QT_TR_NOOP("Create FEM constraint for a pulley"); + sWhatsThis = "Fem_ConstraintPulley"; + sStatusTip = sToolTipText; + sPixmap = "fem-constraint-pulley"; +} + +void CmdFemConstraintPulley::activated(int iMsg) +{ + Fem::FemAnalysis *Analysis; + + if(getConstraintPrerequisits(&Analysis)) + return; + + std::string FeatName = getUniqueObjectName("FemConstraintPulley"); + + openCommand("Make FEM constraint for pulley"); + doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintPulley\",\"%s\")",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Diameter = 300.0",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.OtherDiameter = 100.0",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.CenterDistance = 500.0",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Force = 100.0",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.TensionForce = 100.0",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s.Member + [App.activeDocument().%s]",Analysis->getNameInDocument(),Analysis->getNameInDocument(),FeatName.c_str()); + + doCommand(Doc,"%s",gethideMeshShowPartStr(FeatName).c_str()); //OvG: Hide meshes and show parts + + updateActive(); + + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); +} + +bool CmdFemConstraintPulley::isActive(void) +{ + return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject(); +} +//===================================================================================== + +DEF_STD_CMD_A(CmdFemConstraintDisplacement); + +CmdFemConstraintDisplacement::CmdFemConstraintDisplacement() + : Command("Fem_ConstraintDisplacement") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Create FEM displacement constraint"); + sToolTipText = QT_TR_NOOP("Create FEM constraint for a displacement acting on a face"); + sWhatsThis = "Fem_ConstraintDisplacement"; + sStatusTip = sToolTipText; + sPixmap = "fem-constraint-displacement"; +} + +void CmdFemConstraintDisplacement::activated(int iMsg) +{ + Fem::FemAnalysis *Analysis; + + if(getConstraintPrerequisits(&Analysis)) + return; + + std::string FeatName = getUniqueObjectName("FemConstraintDisplacement"); + + openCommand("Make FEM constraint displacement on face"); + doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintDisplacement\",\"%s\")",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Scale = 1",FeatName.c_str()); //OvG: set initial scale to 1 + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s.Member + [App.activeDocument().%s]", + Analysis->getNameInDocument(),Analysis->getNameInDocument(),FeatName.c_str()); + + doCommand(Doc,"%s",gethideMeshShowPartStr(FeatName).c_str()); //OvG: Hide meshes and show parts + + updateActive(); + + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); +} + +bool CmdFemConstraintDisplacement::isActive(void) +{ + return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject(); +} +// ##################################################################################################### + + + +DEF_STD_CMD_A(CmdFemDefineNodesSet); + + +void DefineNodesCallback(void * ud, SoEventCallback * n) +{ + Fem::FemAnalysis *Analysis; + + if(getConstraintPrerequisits(&Analysis)) + return; + + // show the wait cursor because this could take quite some time + Gui::WaitCursor wc; + + // When this callback function is invoked we must in either case leave the edit mode + Gui::View3DInventorViewer* view = reinterpret_cast(n->getUserData()); + view->setEditing(false); + view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), DefineNodesCallback,ud); + n->setHandled(); + + SbBool clip_inner; + std::vector clPoly = view->getGLPolygon(&clip_inner); + if (clPoly.size() < 3) + return; + if (clPoly.front() != clPoly.back()) + clPoly.push_back(clPoly.front()); + + SoCamera* cam = view->getSoRenderManager()->getCamera(); + SbViewVolume vv = cam->getViewVolume(); + Gui::ViewVolumeProjection proj(vv); + Base::Polygon2D polygon; + for (std::vector::const_iterator it = clPoly.begin(); it != clPoly.end(); ++it) + polygon.Add(Base::Vector2D((*it)[0],(*it)[1])); + + + std::vector docObj = Gui::Selection().getObjectsOfType(Fem::FemMeshObject::getClassTypeId()); + if(docObj.size() !=1) + return; + + const SMESHDS_Mesh* data = const_cast(dynamic_cast(docObj[0])->FemMesh.getValue().getSMesh())->GetMeshDS(); + + SMDS_NodeIteratorPtr aNodeIter = data->nodesIterator(); + Base::Vector3f pt2d; + std::set IntSet; + + while (aNodeIter->more()) { + const SMDS_MeshNode* aNode = aNodeIter->next(); + Base::Vector3f vec(aNode->X(),aNode->Y(),aNode->Z()); + pt2d = proj(vec); + if (polygon.Contains(Base::Vector2D(pt2d.x, pt2d.y)) == true) + IntSet.insert(aNode->GetID()); + } + + std::stringstream set; + + set << "["; + for(std::set::const_iterator it=IntSet.begin();it!=IntSet.end();++it) + if(it==IntSet.begin()) + set << *it ; + else + set << "," << *it ; + set << "]"; + + + Gui::Command::openCommand("Place robot"); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.addObject('Fem::FemSetNodesObject','NodeSet')"); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.ActiveObject.Nodes = %s",set.str().c_str()); + Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().%s.Member = App.activeDocument().%s.Member + [App.activeDocument().NodeSet]",Analysis->getNameInDocument(),Analysis->getNameInDocument()); + ////Gui::Command::updateActive(); + Gui::Command::commitCommand(); + + //std::vector views = view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId()); + //if (!views.empty()) { + // Gui::Application::Instance->activeDocument()->openCommand("Cut"); + // for (std::vector::iterator it = views.begin(); it != views.end(); ++it) { + // ViewProviderMesh* that = static_cast(*it); + // if (that->getEditingMode() > -1) { + // that->finishEditing(); + // that->cutMesh(clPoly, *view, clip_inner); + // } + // } + + // Gui::Application::Instance->activeDocument()->commitCommand(); + + // view->render(); + //} +} + + + +CmdFemDefineNodesSet::CmdFemDefineNodesSet() + : Command("Fem_DefineNodesSet") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Create node set by Poly"); + sToolTipText = QT_TR_NOOP("Create node set by Poly"); + sWhatsThis = "Create node set by Poly"; + sStatusTip = QT_TR_NOOP("Create node set by Poly"); + sPixmap = "fem-fem-mesh-create-node-by-poly"; +} + +void CmdFemDefineNodesSet::activated(int iMsg) +{ + std::vector docObj = Gui::Selection().getObjectsOfType(Fem::FemMeshObject::getClassTypeId()); + + for (std::vector::iterator it = docObj.begin(); it != docObj.end(); ++it) { + if (it == docObj.begin()) { + Gui::Document* doc = getActiveGuiDocument(); + Gui::MDIView* view = doc->getActiveView(); + if (view->getTypeId().isDerivedFrom(Gui::View3DInventor::getClassTypeId())) { + Gui::View3DInventorViewer* viewer = ((Gui::View3DInventor*)view)->getViewer(); + viewer->setEditing(true); + viewer->startSelection(Gui::View3DInventorViewer::Clip); + viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), DefineNodesCallback); + } + else { + return; + } + } + + //Gui::ViewProvider* pVP = getActiveGuiDocument()->getViewProvider(*it); + //if (pVP->isVisible()) + // pVP->startEditing(); + } +} + +bool CmdFemDefineNodesSet::isActive(void) +{ + // Check for the selected mesh feature (all Mesh types) + if (getSelection().countObjectsOfType(Fem::FemMeshObject::getClassTypeId()) != 1) + return false; + + Gui::MDIView* view = Gui::getMainWindow()->activeWindow(); + if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) { + Gui::View3DInventorViewer* viewer = static_cast(view)->getViewer(); + return !viewer->isEditing(); + } + + return false; +} + + +// ##################################################################################################### + +DEF_STD_CMD_A(CmdFemCreateNodesSet); + +CmdFemCreateNodesSet::CmdFemCreateNodesSet() + : Command("Fem_CreateNodesSet") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Define/create a nodes set..."); + sToolTipText = QT_TR_NOOP("Define/create a nodes set..."); + sWhatsThis = "Fem_CreateNodesSet"; + sStatusTip = sToolTipText; + sPixmap = "fem-fem-mesh-create-node-by-poly"; +} + +void CmdFemCreateNodesSet::activated(int iMsg) +{ + Gui::SelectionFilter ObjectFilter("SELECT Fem::FemSetNodesObject COUNT 1"); + Gui::SelectionFilter FemMeshFilter("SELECT Fem::FemMeshObject COUNT 1"); + + if (ObjectFilter.match()) { + Fem::FemSetNodesObject *NodesObj = static_cast(ObjectFilter.Result[0][0].getObject()); + openCommand("Edit nodes set"); + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",NodesObj->getNameInDocument()); + } + else if (FemMeshFilter.match()) { + Fem::FemMeshObject *MeshObj = static_cast(FemMeshFilter.Result[0][0].getObject()); + + std::string FeatName = getUniqueObjectName("NodesSet"); + + openCommand("Create nodes set"); + doCommand(Doc,"App.activeDocument().addObject('Fem::FemSetNodesObject','%s')",FeatName.c_str()); + doCommand(Gui,"App.activeDocument().%s.FemMesh = App.activeDocument().%s",FeatName.c_str(),MeshObj->getNameInDocument()); + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); + } + else { + QMessageBox::warning(Gui::getMainWindow(), + qApp->translate("CmdFemCreateNodesSet", "Wrong selection"), + qApp->translate("CmdFemCreateNodesSet", "Select a single FEM mesh or nodes set, please.")); + } +} + +bool CmdFemCreateNodesSet::isActive(void) +{ + return hasActiveDocument(); +} + +//-------------------------------------------------------------------------------------- + + +void CreateFemCommands(void) +{ + Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); + //rcCmdMgr.addCommand(new CmdFemCreateAnalysis()); + rcCmdMgr.addCommand(new CmdFemAddPart()); + //rcCmdMgr.addCommand(new CmdFemCreateSolver()); // Solver will be extended and created in python + rcCmdMgr.addCommand(new CmdFemCreateNodesSet()); + rcCmdMgr.addCommand(new CmdFemDefineNodesSet()); + rcCmdMgr.addCommand(new CmdFemConstraintBearing()); + rcCmdMgr.addCommand(new CmdFemConstraintFixed()); + rcCmdMgr.addCommand(new CmdFemConstraintForce()); + rcCmdMgr.addCommand(new CmdFemConstraintPressure()); + rcCmdMgr.addCommand(new CmdFemConstraintGear()); + rcCmdMgr.addCommand(new CmdFemConstraintPulley()); + rcCmdMgr.addCommand(new CmdFemConstraintDisplacement()); +} +======= +/*************************************************************************** + * Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" +#ifndef _PreComp_ +# include +# include +# include +#include +#endif + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include "ActiveAnalysisObserver.h" + +#ifdef FC_USE_VTK +#include +#endif + +using namespace std; + + +bool getConstraintPrerequisits(Fem::FemAnalysis **Analysis) +{ + Fem::FemAnalysis* ActiveAnalysis = FemGui::ActiveAnalysisObserver::instance()->getActiveObject(); + if (!ActiveAnalysis || !ActiveAnalysis->getTypeId().isDerivedFrom(Fem::FemAnalysis::getClassTypeId())){ + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("No active Analysis"), + QObject::tr("You need to create or activate a Analysis")); + return true; + } + + *Analysis = static_cast(ActiveAnalysis); + + // return with no error + return false; + +} + +//OvG: Visibility automation show parts and hide meshes on activation of a constraint +std::string gethideMeshShowPartStr(std::string showConstr="") +{ + return "for amesh in App.activeDocument().Objects:\n\ + if \""+showConstr+"\" == amesh.Name:\n\ + amesh.ViewObject.Visibility = True\n\ + elif \"Mesh\" in amesh.TypeId:\n\ + aparttoshow = amesh.Name.replace(\"_Mesh\",\"\")\n\ + for apart in App.activeDocument().Objects:\n\ + if aparttoshow == apart.Name:\n\ + apart.ViewObject.Visibility = True\n\ + amesh.ViewObject.Visibility = False\n"; +} + +//===================================================================================== +DEF_STD_CMD_A(CmdFemCreateAnalysis); + +CmdFemCreateAnalysis::CmdFemCreateAnalysis() + : Command("Fem_CreateAnalysis") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Create a FEM analysis"); + sToolTipText = QT_TR_NOOP("Create a FEM analysis"); + sWhatsThis = "Fem_CreateAnalysis"; + sStatusTip = sToolTipText; + sPixmap = "fem-analysis"; +} + +void CmdFemCreateAnalysis::activated(int iMsg) +{ +#ifndef FCWithNetgen + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Your FreeCAD is build without NETGEN support. Meshing will not work....")); + return; +#endif + + std::vector selection = getSelection().getSelectionEx(); + + if (selection.size() != 1) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge, face or body. Only one body is allowed.")); + return; + } + + if (!selection[0].isObjectTypeOf(Part::Feature::getClassTypeId())){ + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong object type"), + QObject::tr("Fillet works only on parts")); + return; + } + + Part::Feature *base = static_cast(selection[0].getObject()); + + std::string AnalysisName = getUniqueObjectName("FemAnalysis"); + + std::string MeshName = getUniqueObjectName((std::string(base->getNameInDocument()) +"_Mesh").c_str()); + + + openCommand("Create FEM analysis"); + doCommand(Doc,"App.activeDocument().addObject('Fem::FemAnalysis','%s')",AnalysisName.c_str()); + doCommand(Doc,"App.activeDocument().addObject('Fem::FemMeshShapeNetgenObject','%s')",MeshName.c_str()); + doCommand(Doc,"App.activeDocument().ActiveObject.Shape = App.activeDocument().%s",base->getNameInDocument()); + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s",AnalysisName.c_str(),MeshName.c_str()); + addModule(Gui,"FemGui"); + doCommand(Gui,"FemGui.setActiveAnalysis(App.activeDocument().%s)",AnalysisName.c_str()); + commitCommand(); + + updateActive(); +} + +bool CmdFemCreateAnalysis::isActive(void) +{ + return !FemGui::ActiveAnalysisObserver::instance()->hasActiveObject(); +} + +//===================================================================================== + +DEF_STD_CMD_A(CmdFemAddPart); + +CmdFemAddPart::CmdFemAddPart() + : Command("Fem_FemAddPart") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Add a part to the Analysis"); + sToolTipText = QT_TR_NOOP("Add a part to the Analysis"); + sWhatsThis = "Fem_FemAddPart"; + sStatusTip = sToolTipText; + sPixmap = "fem-add-fem-mesh"; +} + +void CmdFemAddPart::activated(int iMsg) +{ +#ifndef FCWithNetgen + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Your FreeCAD is build without NETGEN support. Meshing will not work....")); + return; +#endif + + std::vector selection = getSelection().getSelectionEx(); + + if (selection.size() != 1) { + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Select an edge, face or body. Only one body is allowed.")); + return; + } + + if (!selection[0].isObjectTypeOf(Part::Feature::getClassTypeId())){ + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong object type"), + QObject::tr("Fillet works only on parts")); + return; + } + + Part::Feature *base = static_cast(selection[0].getObject()); + + std::string AnalysisName = getUniqueObjectName("FemAnalysis"); + std::string MeshName = getUniqueObjectName((std::string(base->getNameInDocument()) +"_Mesh").c_str()); + + openCommand("Create FEM analysis"); + doCommand(Doc,"App.activeDocument().addObject('Fem::FemAnalysis','%s')",AnalysisName.c_str()); + doCommand(Doc,"App.activeDocument().addObject('Fem::FemMeshShapeNetgenObject','%s')",MeshName.c_str()); + doCommand(Doc,"App.activeDocument().ActiveObject.Shape = App.activeDocument().%s",base->getNameInDocument()); + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s",AnalysisName.c_str(),MeshName.c_str()); + addModule(Gui,"FemGui"); + doCommand(Gui,"FemGui.setActiveAnalysis(App.activeDocument().%s)",AnalysisName.c_str()); + commitCommand(); + + updateActive(); +} + +bool CmdFemAddPart::isActive(void) +{ + if (Gui::Control().activeDialog()) + return false; + Base::Type type = Base::Type::fromName("Part::Feature"); + return Gui::Selection().countObjectsOfType(type) > 0; +} + +//===================================================================================== + +DEF_STD_CMD_A(CmdFemCreateSolver); + +CmdFemCreateSolver::CmdFemCreateSolver() + : Command("Fem_CreateSolver") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Add a solver to the Analysis"); + sToolTipText = QT_TR_NOOP("Add a solver to the Analysis"); + sWhatsThis = "Fem_CreateSolver"; + sStatusTip = sToolTipText; + sPixmap = "fem-solver"; +} + +void CmdFemCreateSolver::activated(int iMsg) +{ +#ifndef FCWithNetgen + QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), + QObject::tr("Your FreeCAD is build without NETGEN support. Meshing will not work....")); + return; +#endif + + Fem::FemAnalysis *Analysis; + + if(getConstraintPrerequisits(&Analysis)) + return; + + std::string FeatName = getUniqueObjectName("Solver"); + + openCommand("Create solver for FEM or CFD analysis"); + doCommand(Doc,"App.activeDocument().addObject(\"Fem::FemSolverObject\",\"%s\")",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s.Member + [App.activeDocument().%s]",Analysis->getNameInDocument(),Analysis->getNameInDocument(),FeatName.c_str()); + updateActive(); + + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); +} + +bool CmdFemCreateSolver::isActive(void) +{ + return hasActiveDocument(); +} + +//===================================================================================== + + +DEF_STD_CMD_A(CmdFemConstraintBearing); + +CmdFemConstraintBearing::CmdFemConstraintBearing() + : Command("Fem_ConstraintBearing") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Create FEM bearing constraint"); + sToolTipText = QT_TR_NOOP("Create FEM constraint for a bearing"); + sWhatsThis = "Fem_ConstraintBearing"; + sStatusTip = sToolTipText; + sPixmap = "fem-constraint-bearing"; +} + +void CmdFemConstraintBearing::activated(int iMsg) +{ + Fem::FemAnalysis *Analysis; + + if(getConstraintPrerequisits(&Analysis)) + return; + + std::string FeatName = getUniqueObjectName("FemConstraintBearing"); + + openCommand("Make FEM constraint for bearing"); + doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintBearing\",\"%s\")",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s.Member + [App.activeDocument().%s]",Analysis->getNameInDocument(),Analysis->getNameInDocument(),FeatName.c_str()); + + doCommand(Doc,"%s",gethideMeshShowPartStr(FeatName).c_str()); //OvG: Hide meshes and show parts + + updateActive(); + + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); +} + +bool CmdFemConstraintBearing::isActive(void) +{ + return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject(); +} + +//===================================================================================== + +DEF_STD_CMD_A(CmdFemConstraintFixed); + +CmdFemConstraintFixed::CmdFemConstraintFixed() + : Command("Fem_ConstraintFixed") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Create FEM fixed constraint"); + sToolTipText = QT_TR_NOOP("Create FEM constraint for a fixed geometric entity"); + sWhatsThis = "Fem_ConstraintFixed"; + sStatusTip = sToolTipText; + sPixmap = "fem-constraint-fixed"; +} + +void CmdFemConstraintFixed::activated(int iMsg) +{ + Fem::FemAnalysis *Analysis; + + if(getConstraintPrerequisits(&Analysis)) + return; + + std::string FeatName = getUniqueObjectName("FemConstraintFixed"); + + openCommand("Make FEM constraint fixed geometry"); + doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintFixed\",\"%s\")",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Scale = 1",FeatName.c_str()); //OvG: set initial scale to 1 + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s.Member + [App.activeDocument().%s]",Analysis->getNameInDocument(),Analysis->getNameInDocument(),FeatName.c_str()); + + doCommand(Doc,"%s",gethideMeshShowPartStr(FeatName).c_str()); //OvG: Hide meshes and show parts + + updateActive(); + + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); +} + +bool CmdFemConstraintFixed::isActive(void) +{ + return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject(); +} + +//===================================================================================== + +DEF_STD_CMD_A(CmdFemConstraintForce); + +CmdFemConstraintForce::CmdFemConstraintForce() + : Command("Fem_ConstraintForce") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Create FEM force constraint"); + sToolTipText = QT_TR_NOOP("Create FEM constraint for a force acting on a geometric entity"); + sWhatsThis = "Fem_ConstraintForce"; + sStatusTip = sToolTipText; + sPixmap = "fem-constraint-force"; +} + +void CmdFemConstraintForce::activated(int iMsg) +{ + Fem::FemAnalysis *Analysis; + + if(getConstraintPrerequisits(&Analysis)) + return; + + std::string FeatName = getUniqueObjectName("FemConstraintForce"); + + openCommand("Make FEM constraint force on geometry"); + doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintForce\",\"%s\")",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Force = 1.0",FeatName.c_str()); //OvG: set default not equal to 0 + doCommand(Doc,"App.activeDocument().%s.Reversed = False",FeatName.c_str()); //OvG: set default to False + doCommand(Doc,"App.activeDocument().%s.Scale = 1",FeatName.c_str()); //OvG: set initial scale to 1 + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s.Member + [App.activeDocument().%s]",Analysis->getNameInDocument(),Analysis->getNameInDocument(),FeatName.c_str()); + + doCommand(Doc,"%s",gethideMeshShowPartStr(FeatName).c_str()); //OvG: Hide meshes and show parts + + updateActive(); + + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); +} + +bool CmdFemConstraintForce::isActive(void) +{ + return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject(); +} + +//===================================================================================== + +DEF_STD_CMD_A(CmdFemConstraintPressure); + +CmdFemConstraintPressure::CmdFemConstraintPressure() + : Command("Fem_ConstraintPressure") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Create FEM pressure constraint"); + sToolTipText = QT_TR_NOOP("Create FEM constraint for a pressure acting on a face"); + sWhatsThis = "Fem_ConstraintPressure"; + sStatusTip = sToolTipText; + sPixmap = "fem-constraint-pressure"; +} + +void CmdFemConstraintPressure::activated(int iMsg) +{ + Fem::FemAnalysis *Analysis; + + if(getConstraintPrerequisits(&Analysis)) + return; + + std::string FeatName = getUniqueObjectName("FemConstraintPressure"); + + openCommand("Make FEM constraint pressure on face"); + doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintPressure\",\"%s\")",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Pressure = 1000.0",FeatName.c_str()); //OvG: set default not equal to 0 + doCommand(Doc,"App.activeDocument().%s.Reversed = False",FeatName.c_str()); //OvG: set default to False + doCommand(Doc,"App.activeDocument().%s.Scale = 1",FeatName.c_str()); //OvG: set initial scale to 1 + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s.Member + [App.activeDocument().%s]", + Analysis->getNameInDocument(),Analysis->getNameInDocument(),FeatName.c_str()); + + doCommand(Doc,"%s",gethideMeshShowPartStr(FeatName).c_str()); //OvG: Hide meshes and show parts + + updateActive(); + + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); +} + +bool CmdFemConstraintPressure::isActive(void) +{ + return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject(); +} + +//===================================================================================== + +DEF_STD_CMD_A(CmdFemConstraintGear); + +CmdFemConstraintGear::CmdFemConstraintGear() + : Command("Fem_ConstraintGear") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Create FEM gear constraint"); + sToolTipText = QT_TR_NOOP("Create FEM constraint for a gear"); + sWhatsThis = "Fem_ConstraintGear"; + sStatusTip = sToolTipText; + sPixmap = "fem-constraint-gear"; +} + +void CmdFemConstraintGear::activated(int iMsg) +{ + Fem::FemAnalysis *Analysis; + + if(getConstraintPrerequisits(&Analysis)) + return; + std::string FeatName = getUniqueObjectName("FemConstraintGear"); + + openCommand("Make FEM constraint for gear"); + doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintGear\",\"%s\")",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Diameter = 100.0",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s.Member + [App.activeDocument().%s]",Analysis->getNameInDocument(),Analysis->getNameInDocument(),FeatName.c_str()); + + doCommand(Doc,"%s",gethideMeshShowPartStr(FeatName).c_str()); //OvG: Hide meshes and show parts + + updateActive(); + + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); +} + +bool CmdFemConstraintGear::isActive(void) +{ + return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject(); +} + +//===================================================================================== + +DEF_STD_CMD_A(CmdFemConstraintPulley); + +CmdFemConstraintPulley::CmdFemConstraintPulley() + : Command("Fem_ConstraintPulley") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Create FEM pulley constraint"); + sToolTipText = QT_TR_NOOP("Create FEM constraint for a pulley"); + sWhatsThis = "Fem_ConstraintPulley"; + sStatusTip = sToolTipText; + sPixmap = "fem-constraint-pulley"; +} + +void CmdFemConstraintPulley::activated(int iMsg) +{ + Fem::FemAnalysis *Analysis; + + if(getConstraintPrerequisits(&Analysis)) + return; + + std::string FeatName = getUniqueObjectName("FemConstraintPulley"); + + openCommand("Make FEM constraint for pulley"); + doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintPulley\",\"%s\")",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Diameter = 300.0",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.OtherDiameter = 100.0",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.CenterDistance = 500.0",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Force = 100.0",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.TensionForce = 100.0",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s.Member + [App.activeDocument().%s]",Analysis->getNameInDocument(),Analysis->getNameInDocument(),FeatName.c_str()); + + doCommand(Doc,"%s",gethideMeshShowPartStr(FeatName).c_str()); //OvG: Hide meshes and show parts + + updateActive(); + + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); +} + +bool CmdFemConstraintPulley::isActive(void) +{ + return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject(); +} +//===================================================================================== + +DEF_STD_CMD_A(CmdFemConstraintDisplacement); + +CmdFemConstraintDisplacement::CmdFemConstraintDisplacement() + : Command("Fem_ConstraintDisplacement") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Create FEM displacement constraint"); + sToolTipText = QT_TR_NOOP("Create FEM constraint for a displacement acting on a face"); + sWhatsThis = "Fem_ConstraintDisplacement"; + sStatusTip = sToolTipText; + sPixmap = "fem-constraint-displacement"; +} + +void CmdFemConstraintDisplacement::activated(int iMsg) +{ + Fem::FemAnalysis *Analysis; + + if(getConstraintPrerequisits(&Analysis)) + return; + + std::string FeatName = getUniqueObjectName("FemConstraintDisplacement"); + + openCommand("Make FEM constraint displacement on face"); + doCommand(Doc,"App.activeDocument().addObject(\"Fem::ConstraintDisplacement\",\"%s\")",FeatName.c_str()); + doCommand(Doc,"App.activeDocument().%s.Scale = 1",FeatName.c_str()); //OvG: set initial scale to 1 + doCommand(Doc,"App.activeDocument().%s.Member = App.activeDocument().%s.Member + [App.activeDocument().%s]", + Analysis->getNameInDocument(),Analysis->getNameInDocument(),FeatName.c_str()); + + doCommand(Doc,"%s",gethideMeshShowPartStr(FeatName).c_str()); //OvG: Hide meshes and show parts + + updateActive(); + + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); +} + +bool CmdFemConstraintDisplacement::isActive(void) +{ + return FemGui::ActiveAnalysisObserver::instance()->hasActiveObject(); +} +// ##################################################################################################### + + + +DEF_STD_CMD_A(CmdFemDefineNodesSet); + + +void DefineNodesCallback(void * ud, SoEventCallback * n) +{ + Fem::FemAnalysis *Analysis; + + if(getConstraintPrerequisits(&Analysis)) + return; + + // show the wait cursor because this could take quite some time + Gui::WaitCursor wc; + + // When this callback function is invoked we must in either case leave the edit mode + Gui::View3DInventorViewer* view = reinterpret_cast(n->getUserData()); + view->setEditing(false); + view->removeEventCallback(SoMouseButtonEvent::getClassTypeId(), DefineNodesCallback,ud); + n->setHandled(); + + SbBool clip_inner; + std::vector clPoly = view->getGLPolygon(&clip_inner); + if (clPoly.size() < 3) + return; + if (clPoly.front() != clPoly.back()) + clPoly.push_back(clPoly.front()); + + SoCamera* cam = view->getSoRenderManager()->getCamera(); + SbViewVolume vv = cam->getViewVolume(); + Gui::ViewVolumeProjection proj(vv); + Base::Polygon2D polygon; + for (std::vector::const_iterator it = clPoly.begin(); it != clPoly.end(); ++it) + polygon.Add(Base::Vector2D((*it)[0],(*it)[1])); + + + std::vector docObj = Gui::Selection().getObjectsOfType(Fem::FemMeshObject::getClassTypeId()); + if(docObj.size() !=1) + return; + + const SMESHDS_Mesh* data = const_cast(dynamic_cast(docObj[0])->FemMesh.getValue().getSMesh())->GetMeshDS(); + + SMDS_NodeIteratorPtr aNodeIter = data->nodesIterator(); + Base::Vector3f pt2d; + std::set IntSet; + + while (aNodeIter->more()) { + const SMDS_MeshNode* aNode = aNodeIter->next(); + Base::Vector3f vec(aNode->X(),aNode->Y(),aNode->Z()); + pt2d = proj(vec); + if (polygon.Contains(Base::Vector2D(pt2d.x, pt2d.y)) == true) + IntSet.insert(aNode->GetID()); + } + + std::stringstream set; + + set << "["; + for(std::set::const_iterator it=IntSet.begin();it!=IntSet.end();++it) + if(it==IntSet.begin()) + set << *it ; + else + set << "," << *it ; + set << "]"; + + + Gui::Command::openCommand("Place robot"); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.addObject('Fem::FemSetNodesObject','NodeSet')"); + Gui::Command::doCommand(Gui::Command::Doc,"App.ActiveDocument.ActiveObject.Nodes = %s",set.str().c_str()); + Gui::Command::doCommand(Gui::Command::Doc,"App.activeDocument().%s.Member = App.activeDocument().%s.Member + [App.activeDocument().NodeSet]",Analysis->getNameInDocument(),Analysis->getNameInDocument()); + ////Gui::Command::updateActive(); + Gui::Command::commitCommand(); + + //std::vector views = view->getViewProvidersOfType(ViewProviderMesh::getClassTypeId()); + //if (!views.empty()) { + // Gui::Application::Instance->activeDocument()->openCommand("Cut"); + // for (std::vector::iterator it = views.begin(); it != views.end(); ++it) { + // ViewProviderMesh* that = static_cast(*it); + // if (that->getEditingMode() > -1) { + // that->finishEditing(); + // that->cutMesh(clPoly, *view, clip_inner); + // } + // } + + // Gui::Application::Instance->activeDocument()->commitCommand(); + + // view->render(); + //} +} + + + +CmdFemDefineNodesSet::CmdFemDefineNodesSet() + : Command("Fem_DefineNodesSet") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Create node set by Poly"); + sToolTipText = QT_TR_NOOP("Create node set by Poly"); + sWhatsThis = "Create node set by Poly"; + sStatusTip = QT_TR_NOOP("Create node set by Poly"); + sPixmap = "fem-fem-mesh-create-node-by-poly"; +} + +void CmdFemDefineNodesSet::activated(int iMsg) +{ + std::vector docObj = Gui::Selection().getObjectsOfType(Fem::FemMeshObject::getClassTypeId()); + + for (std::vector::iterator it = docObj.begin(); it != docObj.end(); ++it) { + if (it == docObj.begin()) { + Gui::Document* doc = getActiveGuiDocument(); + Gui::MDIView* view = doc->getActiveView(); + if (view->getTypeId().isDerivedFrom(Gui::View3DInventor::getClassTypeId())) { + Gui::View3DInventorViewer* viewer = ((Gui::View3DInventor*)view)->getViewer(); + viewer->setEditing(true); + viewer->startSelection(Gui::View3DInventorViewer::Clip); + viewer->addEventCallback(SoMouseButtonEvent::getClassTypeId(), DefineNodesCallback); + } + else { + return; + } + } + + //Gui::ViewProvider* pVP = getActiveGuiDocument()->getViewProvider(*it); + //if (pVP->isVisible()) + // pVP->startEditing(); + } +} + +bool CmdFemDefineNodesSet::isActive(void) +{ + // Check for the selected mesh feature (all Mesh types) + if (getSelection().countObjectsOfType(Fem::FemMeshObject::getClassTypeId()) != 1) + return false; + + Gui::MDIView* view = Gui::getMainWindow()->activeWindow(); + if (view && view->isDerivedFrom(Gui::View3DInventor::getClassTypeId())) { + Gui::View3DInventorViewer* viewer = static_cast(view)->getViewer(); + return !viewer->isEditing(); + } + + return false; +} + + +// ##################################################################################################### + +DEF_STD_CMD_A(CmdFemCreateNodesSet); + +CmdFemCreateNodesSet::CmdFemCreateNodesSet() + : Command("Fem_CreateNodesSet") +{ + sAppModule = "Fem"; + sGroup = QT_TR_NOOP("Fem"); + sMenuText = QT_TR_NOOP("Define/create a nodes set..."); + sToolTipText = QT_TR_NOOP("Define/create a nodes set..."); + sWhatsThis = "Fem_CreateNodesSet"; + sStatusTip = sToolTipText; + sPixmap = "fem-fem-mesh-create-node-by-poly"; +} + +void CmdFemCreateNodesSet::activated(int iMsg) +{ + Gui::SelectionFilter ObjectFilter("SELECT Fem::FemSetNodesObject COUNT 1"); + Gui::SelectionFilter FemMeshFilter("SELECT Fem::FemMeshObject COUNT 1"); + + if (ObjectFilter.match()) { + Fem::FemSetNodesObject *NodesObj = static_cast(ObjectFilter.Result[0][0].getObject()); + openCommand("Edit nodes set"); + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",NodesObj->getNameInDocument()); + } + else if (FemMeshFilter.match()) { + Fem::FemMeshObject *MeshObj = static_cast(FemMeshFilter.Result[0][0].getObject()); + + std::string FeatName = getUniqueObjectName("NodesSet"); + + openCommand("Create nodes set"); + doCommand(Doc,"App.activeDocument().addObject('Fem::FemSetNodesObject','%s')",FeatName.c_str()); + doCommand(Gui,"App.activeDocument().%s.FemMesh = App.activeDocument().%s",FeatName.c_str(),MeshObj->getNameInDocument()); + doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); + } + else { + QMessageBox::warning(Gui::getMainWindow(), + qApp->translate("CmdFemCreateNodesSet", "Wrong selection"), + qApp->translate("CmdFemCreateNodesSet", "Select a single FEM mesh or nodes set, please.")); + } +} + +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 + +//-------------------------------------------------------------------------------------- + + +void CreateFemCommands(void) +{ + Gui::CommandManager &rcCmdMgr = Gui::Application::Instance->commandManager(); + //rcCmdMgr.addCommand(new CmdFemCreateAnalysis()); + rcCmdMgr.addCommand(new CmdFemAddPart()); + //rcCmdMgr.addCommand(new CmdFemCreateSolver()); // Solver will be extended and created in python + rcCmdMgr.addCommand(new CmdFemCreateNodesSet()); + rcCmdMgr.addCommand(new CmdFemDefineNodesSet()); + rcCmdMgr.addCommand(new CmdFemConstraintBearing()); + rcCmdMgr.addCommand(new CmdFemConstraintFixed()); + rcCmdMgr.addCommand(new CmdFemConstraintForce()); + rcCmdMgr.addCommand(new CmdFemConstraintPressure()); + 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 +} +>>>>>>> Basic implementation of filter framework diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp b/src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp new file mode 100644 index 000000000..1f0157b55 --- /dev/null +++ b/src/Mod/Fem/Gui/ViewProviderFemPostFunction.cpp @@ -0,0 +1,246 @@ +/*************************************************************************** + * 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_ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "ViewProviderFemPostFunction.h" +#include +#include +#include +#include +#include +#include +#include + +using namespace FemGui; + +PROPERTY_SOURCE(FemGui::ViewProviderFemPostFunctionProvider, Gui::ViewProviderDocumentObject) + +ViewProviderFemPostFunctionProvider::ViewProviderFemPostFunctionProvider() { + +} + +ViewProviderFemPostFunctionProvider::~ViewProviderFemPostFunctionProvider() { + +} + +std::vector< App::DocumentObject* > ViewProviderFemPostFunctionProvider::claimChildren(void) const { + + return static_cast(getObject())->Functions.getValues(); +} + +std::vector< App::DocumentObject* > ViewProviderFemPostFunctionProvider::claimChildren3D(void) const { + return claimChildren(); +} + + +PROPERTY_SOURCE(FemGui::ViewProviderFemPostFunction, Gui::ViewProviderDocumentObject) + +ViewProviderFemPostFunction::ViewProviderFemPostFunction() : m_autoscale(false), m_isDragging(false) +{ + + m_geometrySeperator = new SoSeparator(); + m_geometrySeperator->ref(); + + m_scale = new SoScale(); + m_scale->ref(); + m_scale->scaleFactor = SbVec3f(1,1,1); +} + +ViewProviderFemPostFunction::~ViewProviderFemPostFunction() +{ + m_geometrySeperator->unref(); + m_manip->unref(); + m_scale->unref(); +} + +void ViewProviderFemPostFunction::attach(App::DocumentObject *pcObj) +{ + ViewProviderDocumentObject::attach(pcObj); + Fem::FemPostPlaneFunction* func = static_cast(getObject()); + + // setup the graph for editing the function unit geometry + SoMaterial* color = new SoMaterial(); + color->diffuseColor.setValue(0,0,1); + color->transparency.setValue(0.5); + + SoTransform* trans = new SoTransform; + const Base::Vector3d& norm = func->Normal.getValue(); + const Base::Vector3d& base = func->Origin.getValue(); + SbRotation rot(SbVec3f(0,0,1), SbVec3f(norm.x,norm.y,norm.z)); + trans->rotation.setValue(rot); + trans->translation.setValue(base.x,base.y,base.z); + trans->center.setValue(0.0f,0.0f,0.0f); + + m_manip = setupManipulator(); + m_manip->ref(); + + SoSeparator* pcEditNode = new SoSeparator(); + + pcEditNode->addChild(color); + pcEditNode->addChild(trans); + pcEditNode->addChild(m_geometrySeperator); + + m_geometrySeperator->insertChild(m_scale, 0); + + // Now we replace the SoTransform node by a manipulator + // Note: Even SoCenterballManip inherits from SoTransform + // we cannot use it directly (in above code) because the + // translation and center fields are overridden. + SoSearchAction sa; + sa.setInterest(SoSearchAction::FIRST); + sa.setSearchingAll(FALSE); + sa.setNode(trans); + sa.apply(pcEditNode); + SoPath * path = sa.getPath(); + if (path) { + m_manip->replaceNode(path); + + SoDragger* dragger = m_manip->getDragger(); + dragger->addStartCallback(dragStartCallback, this); + dragger->addFinishCallback(dragFinishCallback, this); + dragger->addMotionCallback(dragMotionCallback, this); + } + + addDisplayMaskMode(pcEditNode, "Default"); + setDisplayMaskMode("Default"); +} + +SoTransformManip* ViewProviderFemPostFunction::setupManipulator() { + + return new SoCenterballManip; +} + + +std::vector ViewProviderFemPostFunction::getDisplayModes(void) const +{ + std::vector StrList; + StrList.push_back("Default"); + return StrList; +} + +void ViewProviderFemPostFunction::dragStartCallback(void *data, SoDragger *) +{ + // This is called when a manipulator is about to manipulating + Gui::Application::Instance->activeDocument()->openCommand("Edit Mirror"); + reinterpret_cast(data)->m_isDragging = true; + + ViewProviderFemPostFunction* that = reinterpret_cast(data); + ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/Mod/Fem"); + that->m_autoRecompute = hGrp->GetBool("PostAutoRecompute", false); +} + +void ViewProviderFemPostFunction::dragFinishCallback(void *data, SoDragger *) +{ + // This is called when a manipulator has done manipulating + Gui::Application::Instance->activeDocument()->commitCommand(); + + ViewProviderFemPostFunction* that = reinterpret_cast(data); + if(that->m_autoRecompute) + that->getObject()->getDocument()->recompute(); + + reinterpret_cast(data)->m_isDragging = false; +} + +void ViewProviderFemPostFunction::dragMotionCallback(void *data, SoDragger *drag) +{ + Base::Console().Message("dragger callback\n"); + ViewProviderFemPostFunction* that = reinterpret_cast(data); + that->draggerUpdate(drag); + + if(that->m_autoRecompute) + that->getObject()->getDocument()->recompute(); +} + +PROPERTY_SOURCE(FemGui::ViewProviderFemPostPlaneFunction, FemGui::ViewProviderFemPostFunction) + +ViewProviderFemPostPlaneFunction::ViewProviderFemPostPlaneFunction() { + + setAutoScale(true); + + //setup the visualisation geometry + SoCoordinate3* points = new SoCoordinate3(); + points->point.setNum(4); + points->point.set1Value(0, -0.5, -0.5, 0); + points->point.set1Value(1, -0.5, 0.5, 0); + points->point.set1Value(2, 0.5, 0.5, 0); + points->point.set1Value(3, 0.5, -0.5, 0); + points->point.set1Value(4, -0.5, -0.5, 0); + SoLineSet* line = new SoLineSet(); + getGeometryNode()->addChild(points); + getGeometryNode()->addChild(line); +} + +ViewProviderFemPostPlaneFunction::~ViewProviderFemPostPlaneFunction() { + +} + +void ViewProviderFemPostPlaneFunction::draggerUpdate(SoDragger* m) { + + Base::Console().Message("dragger udate\n"); + + Fem::FemPostPlaneFunction* func = static_cast(getObject()); + SoCenterballDragger* dragger = static_cast(m); + + // the new axis of the plane + SbRotation rot, scaleDir; + const SbVec3f& center = dragger->center.getValue(); + + SbVec3f norm(0,0,1); + dragger->rotation.getValue().multVec(norm,norm); + func->Origin.setValue(center[0], center[1], center[2]); + func->Normal.setValue(norm[0],norm[1],norm[2]); +} + +void ViewProviderFemPostPlaneFunction::updateData(const App::Property* p) { + + Fem::FemPostPlaneFunction* 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); +} diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostFunction.h b/src/Mod/Fem/Gui/ViewProviderFemPostFunction.h new file mode 100644 index 000000000..eb448930c --- /dev/null +++ b/src/Mod/Fem/Gui/ViewProviderFemPostFunction.h @@ -0,0 +1,102 @@ +/*************************************************************************** + * 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_VIEWPROVIDERFEMPOSTFUNCTION_H +#define FEM_VIEWPROVIDERFEMPOSTFUNCTION_H + +#include +#include + +class SoScale; +class SoSurroundScale; +class SoTransformManip; +class SoComposeMatrix; +class SoMatrixTransform; +class SoDragger; + +namespace FemGui +{ + +class FemGuiExport ViewProviderFemPostFunctionProvider : public Gui::ViewProviderDocumentObject +{ + PROPERTY_HEADER(FemGui::ViewProviderFemPostFunction); + +public: + ViewProviderFemPostFunctionProvider(); + virtual ~ViewProviderFemPostFunctionProvider(); + + virtual std::vector< App::DocumentObject* > claimChildren(void) const; + virtual std::vector< App::DocumentObject* > claimChildren3D(void) const; +}; + +class FemGuiExport ViewProviderFemPostFunction : public Gui::ViewProviderDocumentObject +{ + PROPERTY_HEADER(FemGui::ViewProviderFemPostFunction); + +public: + /// constructor. + ViewProviderFemPostFunction(); + ~ViewProviderFemPostFunction(); + + void attach(App::DocumentObject *pcObject); + std::vector getDisplayModes() const; + +protected: + void setAutoScale(bool value) {m_autoscale = value;}; + bool autoScale() {return m_autoscale;}; + + bool isDragging() {return m_isDragging;}; + + virtual SoTransformManip* setupManipulator(); + virtual void draggerUpdate(SoDragger* m) {}; + SoTransformManip* getManipulator() {return m_manip;}; + SoSeparator* getGeometryNode() {return m_geometrySeperator;}; + +private: + static void dragStartCallback(void * data, SoDragger * d); + static void dragFinishCallback(void * data, SoDragger * d); + static void dragMotionCallback(void * data, SoDragger * d); + + SoSeparator* m_geometrySeperator; + SoTransformManip* m_manip; + SoScale* m_scale; + bool m_autoscale, m_isDragging, m_autoRecompute; +}; + +class FemGuiExport ViewProviderFemPostPlaneFunction : public ViewProviderFemPostFunction { + + PROPERTY_HEADER(FemGui::ViewProviderFemPostPlaneFunction); + +public: + ViewProviderFemPostPlaneFunction(); + virtual ~ViewProviderFemPostPlaneFunction(); + +protected: + virtual void draggerUpdate(SoDragger* mat); + virtual void updateData(const App::Property*); +}; + +} //namespace FemGui + + +#endif // FEM_VIEWPROVIDERFEMPOSTFUNCTION_H \ No newline at end of file diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp b/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp index 505240b45..91404d391 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemPostObject.cpp @@ -369,7 +369,7 @@ void ViewProviderFemPostObject::WritePointData(vtkPoints* points, vtkDataArray* void ViewProviderFemPostObject::WriteColorData() { - if(!m_currentAlgorithm) + if(!setupPipeline()) return; if(Coloring.getEnumVector().empty() || Coloring.getValue() == 0) { @@ -429,7 +429,7 @@ void ViewProviderFemPostObject::updateData(const App::Property* p) { bool ViewProviderFemPostObject::setupPipeline() { - if(!static_cast(getObject())->getPolyAlgorithm()) + if(!static_cast(getObject())->providesPolyData()) return false; if(!m_currentAlgorithm) { diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.cpp b/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.cpp new file mode 100644 index 000000000..b60684c3b --- /dev/null +++ b/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.cpp @@ -0,0 +1,59 @@ +/*************************************************************************** + * 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 "ViewProviderFemPostPipeline.h" +#include +#include + +using namespace FemGui; + + +PROPERTY_SOURCE(FemGui::ViewProviderFemPostPipeline, FemGui::ViewProviderFemPostObject) + +ViewProviderFemPostPipeline::ViewProviderFemPostPipeline() +{ +} + +ViewProviderFemPostPipeline::~ViewProviderFemPostPipeline() +{ +} + +std::vector< App::DocumentObject* > ViewProviderFemPostPipeline::claimChildren(void) const { + + Fem::FemPostPipeline* pipeline = static_cast(getObject()); + std::vector children; + + if(pipeline->Function.getValue()) + children.push_back(pipeline->Function.getValue()); + + children.insert(children.end(), pipeline->Filter.getValues().begin(), pipeline->Filter.getValues().end()); + Base::Console().Message("claim children pipeline: %i\n", children.size()); + return children; +} + +std::vector< App::DocumentObject* > ViewProviderFemPostPipeline::claimChildren3D(void) const { + + return claimChildren(); +} + diff --git a/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h b/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h new file mode 100644 index 000000000..b96256ab3 --- /dev/null +++ b/src/Mod/Fem/Gui/ViewProviderFemPostPipeline.h @@ -0,0 +1,49 @@ +/*************************************************************************** + * 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_VIEWPROVIDERFEMPOSTPIPELINE_H +#define FEM_VIEWPROVIDERFEMPOSTPIPELINE_H + +#include "ViewProviderFemPostObject.h" + +namespace FemGui +{ + +class FemGuiExport ViewProviderFemPostPipeline : public ViewProviderFemPostObject { + + PROPERTY_HEADER(FemGui::ViewProviderFemPostPipeline); + +public: + /// constructor. + ViewProviderFemPostPipeline(); + ~ViewProviderFemPostPipeline(); + + virtual std::vector< App::DocumentObject* > claimChildren(void) const; + virtual std::vector< App::DocumentObject* > claimChildren3D(void) const; + +}; + +} //namespace FemGui + + +#endif // FEM_VIEWPROVIDERFEMPOSTPIPELINE_H \ No newline at end of file diff --git a/src/Mod/Fem/Gui/Workbench.cpp b/src/Mod/Fem/Gui/Workbench.cpp index 2756f3019..0505a9bc2 100755 --- a/src/Mod/Fem/Gui/Workbench.cpp +++ b/src/Mod/Fem/Gui/Workbench.cpp @@ -1,116 +1,125 @@ -/*************************************************************************** - * Copyright (c) 2008 Werner Mayer * - * * - * This file is part of the FreeCAD CAx development system. * - * * - * This library is free software; you can redistribute it and/or * - * modify it under the terms of the GNU Library General Public * - * License as published by the Free Software Foundation; either * - * version 2 of the License, or (at your option) any later version. * - * * - * This library is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU Library General Public License for more details. * - * * - * You should have received a copy of the GNU Library General Public * - * License along with this library; see the file COPYING.LIB. If not, * - * write to the Free Software Foundation, Inc., 59 Temple Place, * - * Suite 330, Boston, MA 02111-1307, USA * - * * - ***************************************************************************/ - - -#include "PreCompiled.h" - -#ifndef _PreComp_ -# include -#endif - -#include "Workbench.h" -#include -#include - - -using namespace FemGui; - -#if 0 // needed for Qt's lupdate utility - qApp->translate("Workbench", "FEM"); - qApp->translate("Workbench", "&FEM"); -#endif - -/// @namespace FemGui @class Workbench -TYPESYSTEM_SOURCE(FemGui::Workbench, Gui::StdWorkbench) - -Workbench::Workbench() -{ -} - -Workbench::~Workbench() -{ -} - -Gui::ToolBarItem* Workbench::setupToolBars() const -{ - Gui::ToolBarItem* root = StdWorkbench::setupToolBars(); - Gui::ToolBarItem* fem = new Gui::ToolBarItem(root); - fem->setCommand("FEM"); - *fem << "Fem_Analysis" - << "Fem_SolverCalculix" - // << "Fem_SolverZ88" - << "Fem_MeshFromShape" - << "Fem_MechanicalMaterial" - << "Fem_BeamSection" - << "Fem_ShellThickness" - << "Separator" - << "Fem_CreateNodesSet" - << "Separator" - << "Fem_ConstraintFixed" - << "Fem_ConstraintDisplacement" - << "Separator" - << "Fem_ConstraintForce" - << "Fem_ConstraintPressure" - << "Fem_ConstraintBearing" - << "Fem_ConstraintGear" - << "Fem_ConstraintPulley" - << "Separator" - << "Fem_ControlSolver" - << "Fem_RunSolver" - << "Fem_PurgeResults" - << "Fem_ShowResult"; - return root; -} - -Gui::MenuItem* Workbench::setupMenuBar() const -{ - Gui::MenuItem* root = StdWorkbench::setupMenuBar(); - Gui::MenuItem* item = root->findItem("&Windows"); - Gui::MenuItem* fem = new Gui::MenuItem; - root->insertItem(item, fem); - fem->setCommand("&FEM"); - *fem << "Fem_Analysis" - << "Fem_SolverCalculix" - << "Fem_SolverZ88" - << "Fem_MeshFromShape" - << "Fem_MechanicalMaterial" - << "Fem_BeamSection" - << "Fem_ShellThickness" - << "Separator" - << "Fem_CreateNodesSet" - << "Separator" - << "Fem_ConstraintFixed" - << "Fem_ConstraintDisplacement" - << "Separator" - << "Fem_ConstraintForce" - << "Fem_ConstraintPressure" - << "Fem_ConstraintBearing" - << "Fem_ConstraintGear" - << "Fem_ConstraintPulley" - << "Separator" - << "Fem_ControlSolver" - << "Fem_RunSolver" - << "Fem_PurgeResults" - << "Fem_ShowResult"; - - return root; -} +/*************************************************************************** + * Copyright (c) 2008 Werner Mayer * + * * + * This file is part of the FreeCAD CAx development system. * + * * + * This library is free software; you can redistribute it and/or * + * modify it under the terms of the GNU Library General Public * + * License as published by the Free Software Foundation; either * + * version 2 of the License, or (at your option) any later version. * + * * + * This library is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Library General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this library; see the file COPYING.LIB. If not, * + * write to the Free Software Foundation, Inc., 59 Temple Place, * + * Suite 330, Boston, MA 02111-1307, USA * + * * + ***************************************************************************/ + + +#include "PreCompiled.h" + +#ifndef _PreComp_ +# include +#endif + +#include "Workbench.h" +#include +#include + + +using namespace FemGui; + +#if 0 // needed for Qt's lupdate utility + qApp->translate("Workbench", "FEM"); + qApp->translate("Workbench", "&FEM"); +#endif + +/// @namespace FemGui @class Workbench +TYPESYSTEM_SOURCE(FemGui::Workbench, Gui::StdWorkbench) + +Workbench::Workbench() +{ +} + +Workbench::~Workbench() +{ +} + +Gui::ToolBarItem* Workbench::setupToolBars() const +{ + Gui::ToolBarItem* root = StdWorkbench::setupToolBars(); + Gui::ToolBarItem* fem = new Gui::ToolBarItem(root); + fem->setCommand("FEM"); + *fem << "Fem_Analysis" + << "Fem_SolverCalculix" + // << "Fem_SolverZ88" + << "Fem_MeshFromShape" + << "Fem_MechanicalMaterial" + << "Fem_BeamSection" + << "Fem_ShellThickness" + << "Separator" + << "Fem_CreateNodesSet" + << "Separator" + << "Fem_ConstraintFixed" + << "Fem_ConstraintDisplacement" + << "Separator" + << "Fem_ConstraintForce" + << "Fem_ConstraintPressure" + << "Fem_ConstraintBearing" + << "Fem_ConstraintGear" + << "Fem_ConstraintPulley" + << "Separator" + << "Fem_ControlSolver" + << "Fem_RunSolver" + << "Fem_PurgeResults" + << "Fem_ShowResult"; + +#ifdef FC_USE_VTK + Gui::ToolBarItem* post = new Gui::ToolBarItem(root); + post->setCommand("Post Processing"); + *post << "Fem_PostApplyChanges" + << "Fem_PostCreateClipFilter" + << "Fem_PostCreateFunctions"; +#endif + + return root; +} + +Gui::MenuItem* Workbench::setupMenuBar() const +{ + Gui::MenuItem* root = StdWorkbench::setupMenuBar(); + Gui::MenuItem* item = root->findItem("&Windows"); + Gui::MenuItem* fem = new Gui::MenuItem; + root->insertItem(item, fem); + fem->setCommand("&FEM"); + *fem << "Fem_Analysis" + << "Fem_SolverCalculix" + << "Fem_SolverZ88" + << "Fem_MeshFromShape" + << "Fem_MechanicalMaterial" + << "Fem_BeamSection" + << "Fem_ShellThickness" + << "Separator" + << "Fem_CreateNodesSet" + << "Separator" + << "Fem_ConstraintFixed" + << "Fem_ConstraintDisplacement" + << "Separator" + << "Fem_ConstraintForce" + << "Fem_ConstraintPressure" + << "Fem_ConstraintBearing" + << "Fem_ConstraintGear" + << "Fem_ConstraintPulley" + << "Separator" + << "Fem_ControlSolver" + << "Fem_RunSolver" + << "Fem_PurgeResults" + << "Fem_ShowResult"; + + return root; +} \ No newline at end of file