FEM Post: FreeCADify the vtk post processing
- Data property for saving/loading vtk data - Use FreeCAD recompute system instead of vtk pipeline
This commit is contained in:
@@ -59,6 +59,7 @@
|
||||
#include "FemPostPipeline.h"
|
||||
#include "FemPostFilter.h"
|
||||
#include "FemPostFunction.h"
|
||||
#include "PropertyPostDataObject.h"
|
||||
#endif
|
||||
|
||||
namespace Fem {
|
||||
@@ -163,5 +164,6 @@ PyMODINIT_FUNC initFem()
|
||||
Fem::FemPostFunctionProvider ::init();
|
||||
Fem::FemPostPlaneFunction ::init();
|
||||
Fem::FemPostSphereFunction ::init();
|
||||
Fem::PropertyPostDataObject ::init();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<<<<<<< 559b38429c3ec5bcad9eced553e5d7ca544cb55e
|
||||
<<<<<<< 43b51b168bc838480fd6a0a4b9f67e0bf864a560
|
||||
/***************************************************************************
|
||||
* Copyright (c) 2008 Jürgen Riegel (juergen.riegel@web.de) *
|
||||
* *
|
||||
@@ -159,6 +159,7 @@ PyMODINIT_FUNC initFem()
|
||||
Fem::FemPostClipFilter ::init();
|
||||
Fem::FemPostScalarClipFilter ::init();
|
||||
Fem::FemPostWarpVectorFilter ::init();
|
||||
Fem::FemPostCutFilter ::init();
|
||||
Fem::FemPostFunction ::init();
|
||||
Fem::FemPostFunctionProvider ::init();
|
||||
Fem::FemPostPlaneFunction ::init();
|
||||
@@ -227,6 +228,7 @@ PyMODINIT_FUNC initFem()
|
||||
#include "FemPostPipeline.h"
|
||||
#include "FemPostFilter.h"
|
||||
#include "FemPostFunction.h"
|
||||
#include "PropertyPostDataObject.h"
|
||||
#endif
|
||||
|
||||
namespace Fem {
|
||||
@@ -331,6 +333,7 @@ PyMODINIT_FUNC initFem()
|
||||
Fem::FemPostFunctionProvider ::init();
|
||||
Fem::FemPostPlaneFunction ::init();
|
||||
Fem::FemPostSphereFunction ::init();
|
||||
Fem::PropertyPostDataObject ::init();
|
||||
#endif
|
||||
}
|
||||
>>>>>>> Add cut filter
|
||||
>>>>>>> FreeCADify the vtk post processing
|
||||
|
||||
@@ -202,6 +202,8 @@ SOURCE_GROUP("Constraints" FILES ${FemConstraints_SRCS})
|
||||
|
||||
if(BUILD_FEM_VTK)
|
||||
SET(FemPost_SRCS
|
||||
PropertyPostDataObject.h
|
||||
PropertyPostDataObject.cpp
|
||||
FemPostObject.h
|
||||
FemPostObject.cpp
|
||||
FemPostPipeline.h
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "FemPostFilter.h"
|
||||
#include "FemPostPipeline.h"
|
||||
#include <Base/Console.h>
|
||||
#include <App/Document.h>
|
||||
#include <App/DocumentObjectPy.h>
|
||||
#include <vtkFieldData.h>
|
||||
#include <vtkPointData.h>
|
||||
@@ -41,115 +42,14 @@ PROPERTY_SOURCE(Fem::FemPostFilter, Fem::FemPostObject)
|
||||
|
||||
FemPostFilter::FemPostFilter()
|
||||
{
|
||||
m_pass = vtkPassThrough::New();
|
||||
ADD_PROPERTY(Input,(0));
|
||||
}
|
||||
|
||||
FemPostFilter::~FemPostFilter()
|
||||
{
|
||||
//we need to make sure that all vtk filters are disconnected
|
||||
//as the would stay alive and connected otherwise
|
||||
clearInput();
|
||||
|
||||
}
|
||||
|
||||
bool FemPostFilter::valid() {
|
||||
return polyDataSource && !m_pipelines.empty() && !m_activePipeline.empty();
|
||||
}
|
||||
|
||||
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 StdReturn;
|
||||
}
|
||||
|
||||
|
||||
void FemPostFilter::clearInput() {
|
||||
|
||||
if(isConnected()) {
|
||||
for(std::map<std::string, FilterPipeline>::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<std::string, FilterPipeline>::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<std::string, FilterPipeline>::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;
|
||||
}
|
||||
@@ -162,13 +62,43 @@ 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());
|
||||
}
|
||||
}
|
||||
|
||||
DocumentObjectExecReturn* FemPostFilter::execute(void) {
|
||||
|
||||
Base::Console().Message("Recalculate filter\n");
|
||||
if(!m_pipelines.empty() && !m_activePipeline.empty()) {
|
||||
|
||||
FemPostFilter::FilterPipeline& pipe = m_pipelines[m_activePipeline];
|
||||
pipe.source->SetInputDataObject(getInputData());
|
||||
pipe.target->Update();
|
||||
|
||||
Data.setValue(pipe.target->GetOutputDataObject(0));
|
||||
}
|
||||
Base::Console().Message("Done Recalculate filter\n");
|
||||
return StdReturn;
|
||||
}
|
||||
|
||||
vtkDataObject* FemPostFilter::getInputData() {
|
||||
|
||||
if(Input.getValue()) {
|
||||
return Input.getValue<FemPostObject*>()->Data.getValue();
|
||||
}
|
||||
else {
|
||||
//get the pipeline and use the pipelinedata
|
||||
std::vector<App::DocumentObject*> objs = getDocument()->getObjectsOfType(FemPostPipeline::getClassTypeId());
|
||||
for(std::vector<App::DocumentObject*>::iterator it = objs.begin(); it != objs.end(); ++it) {
|
||||
|
||||
if(static_cast<FemPostPipeline*>(*it)->holdsPostObject(this)) {
|
||||
|
||||
return static_cast<FemPostObject*>(*it)->Data.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
PROPERTY_SOURCE(Fem::FemPostClipFilter, Fem::FemPostFilter)
|
||||
@@ -178,21 +108,17 @@ 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 = vtkTableBasedClipDataSet::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);
|
||||
@@ -228,6 +154,17 @@ void FemPostClipFilter::onChanged(const Property* prop) {
|
||||
Fem::FemPostFilter::onChanged(prop);
|
||||
}
|
||||
|
||||
short int FemPostClipFilter::mustExecute(void) const {
|
||||
|
||||
if(Function.isTouched() ||
|
||||
InsideOut.isTouched() ||
|
||||
CutCells.isTouched()) {
|
||||
|
||||
return 1;
|
||||
}
|
||||
else return App::DocumentObject::mustExecute();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -240,14 +177,11 @@ FemPostScalarClipFilter::FemPostScalarClipFilter(void) : FemPostFilter() {
|
||||
ADD_PROPERTY_TYPE(InsideOut, (false), "Clip", App::Prop_None, "Invert the clip direction");
|
||||
|
||||
Value.setConstraints(&m_constraints);
|
||||
|
||||
polyDataSource = vtkGeometryFilter::New();
|
||||
|
||||
|
||||
FilterPipeline clip;
|
||||
m_clipper = vtkTableBasedClipDataSet::New();
|
||||
clip.source = m_clipper;
|
||||
clip.target = m_clipper;
|
||||
clip.visualisation = m_clipper;
|
||||
addFilterPipeline(clip, "clip");
|
||||
setActiveFilterPipeline("clip");
|
||||
}
|
||||
@@ -257,10 +191,6 @@ FemPostScalarClipFilter::~FemPostScalarClipFilter() {
|
||||
}
|
||||
|
||||
DocumentObjectExecReturn* FemPostScalarClipFilter::execute(void) {
|
||||
|
||||
//update the available fields and set the correct input field data for clipping
|
||||
if(!isConnected())
|
||||
return StdReturn;
|
||||
|
||||
std::string val;
|
||||
if(m_scalarFields.getEnums() && Scalars.getValue() >= 0)
|
||||
@@ -268,18 +198,11 @@ DocumentObjectExecReturn* FemPostScalarClipFilter::execute(void) {
|
||||
|
||||
std::vector<std::string> array;
|
||||
|
||||
vtkDataObject* data;
|
||||
if(hasInputAlgorithmConnected()) {
|
||||
getConnectedInputAlgorithm()->Update();
|
||||
data = getConnectedInputAlgorithm()->GetOutputDataObject(0);
|
||||
}
|
||||
else
|
||||
data = getConnectedInputData();
|
||||
|
||||
vtkDataSet* dset = dynamic_cast<vtkDataSet*>(data);
|
||||
if(!dset)
|
||||
vtkSmartPointer<vtkDataObject> data = getInputData();
|
||||
if(!data || !data->IsA("vtkDataSet"))
|
||||
return StdReturn;
|
||||
|
||||
vtkDataSet* dset = vtkDataSet::SafeDownCast(data);
|
||||
vtkPointData* pd = dset->GetPointData();
|
||||
|
||||
for(int i=0; i<pd->GetNumberOfArrays(); ++i) {
|
||||
@@ -318,20 +241,25 @@ void FemPostScalarClipFilter::onChanged(const Property* prop) {
|
||||
Fem::FemPostFilter::onChanged(prop);
|
||||
}
|
||||
|
||||
short int FemPostScalarClipFilter::mustExecute(void) const {
|
||||
|
||||
if(Value.isTouched() ||
|
||||
InsideOut.isTouched() ||
|
||||
Scalars.isTouched()) {
|
||||
|
||||
return 1;
|
||||
}
|
||||
else return App::DocumentObject::mustExecute();
|
||||
}
|
||||
|
||||
void FemPostScalarClipFilter::setConstraintForField() {
|
||||
|
||||
vtkDataObject* data;
|
||||
if(hasInputAlgorithmConnected()) {
|
||||
getConnectedInputAlgorithm()->Update();
|
||||
data = getConnectedInputAlgorithm()->GetOutputDataObject(0);
|
||||
}
|
||||
else
|
||||
data = getConnectedInputData();
|
||||
|
||||
vtkDataSet* dset = dynamic_cast<vtkDataSet*>(data);
|
||||
if(!dset)
|
||||
vtkSmartPointer<vtkDataObject> data = getInputData();
|
||||
if(!data || !data->IsA("vtkDataSet"))
|
||||
return;
|
||||
|
||||
vtkDataSet* dset = vtkDataSet::SafeDownCast(data);
|
||||
|
||||
vtkDataArray* pdata = dset->GetPointData()->GetArray(Scalars.getValueAsString());
|
||||
double p[2];
|
||||
pdata->GetRange(p);
|
||||
@@ -347,14 +275,11 @@ FemPostWarpVectorFilter::FemPostWarpVectorFilter(void): FemPostFilter() {
|
||||
|
||||
ADD_PROPERTY_TYPE(Factor, (0), "Warp", App::Prop_None, "The factor by which the vector is added to the node positions");
|
||||
ADD_PROPERTY_TYPE(Vector, (long(0)), "Warp", App::Prop_None, "The field added to the node position");
|
||||
|
||||
polyDataSource = vtkGeometryFilter::New();
|
||||
|
||||
|
||||
FilterPipeline warp;
|
||||
m_warp = vtkWarpVector::New();
|
||||
warp.source = m_warp;
|
||||
warp.target = m_warp;
|
||||
warp.visualisation = m_warp;
|
||||
addFilterPipeline(warp, "warp");
|
||||
setActiveFilterPipeline("warp");
|
||||
}
|
||||
@@ -365,10 +290,6 @@ FemPostWarpVectorFilter::~FemPostWarpVectorFilter() {
|
||||
|
||||
|
||||
DocumentObjectExecReturn* FemPostWarpVectorFilter::execute(void) {
|
||||
|
||||
//update the available fields and set the correct input field data for clipping
|
||||
if(!isConnected())
|
||||
return StdReturn;
|
||||
|
||||
std::string val;
|
||||
if(m_vectorFields.getEnums() && Vector.getValue() >= 0)
|
||||
@@ -376,18 +297,11 @@ DocumentObjectExecReturn* FemPostWarpVectorFilter::execute(void) {
|
||||
|
||||
std::vector<std::string> array;
|
||||
|
||||
vtkDataObject* data;
|
||||
if(hasInputAlgorithmConnected()) {
|
||||
getConnectedInputAlgorithm()->Update();
|
||||
data = getConnectedInputAlgorithm()->GetOutputDataObject(0);
|
||||
}
|
||||
else
|
||||
data = getConnectedInputData();
|
||||
|
||||
vtkDataSet* dset = dynamic_cast<vtkDataSet*>(data);
|
||||
if(!dset)
|
||||
vtkSmartPointer<vtkDataObject> data = getInputData();
|
||||
if(!data || !data->IsA("vtkDataSet"))
|
||||
return StdReturn;
|
||||
|
||||
vtkDataSet* dset = vtkDataSet::SafeDownCast(data);
|
||||
vtkPointData* pd = dset->GetPointData();
|
||||
|
||||
for(int i=0; i<pd->GetNumberOfArrays(); ++i) {
|
||||
@@ -422,20 +336,27 @@ void FemPostWarpVectorFilter::onChanged(const Property* prop) {
|
||||
Fem::FemPostFilter::onChanged(prop);
|
||||
}
|
||||
|
||||
short int FemPostWarpVectorFilter::mustExecute(void) const {
|
||||
|
||||
if(Factor.isTouched() ||
|
||||
Vector.isTouched()) {
|
||||
|
||||
return 1;
|
||||
}
|
||||
else return App::DocumentObject::mustExecute();
|
||||
}
|
||||
|
||||
|
||||
PROPERTY_SOURCE(Fem::FemPostCutFilter, Fem::FemPostFilter)
|
||||
|
||||
FemPostCutFilter::FemPostCutFilter(void) : FemPostFilter() {
|
||||
|
||||
ADD_PROPERTY_TYPE(Function, (0), "Cut", App::Prop_None, "The function object which defines the clip cut function");
|
||||
|
||||
polyDataSource = vtkGeometryFilter::New();
|
||||
|
||||
FilterPipeline clip;
|
||||
m_cutter = vtkCutter::New();
|
||||
clip.source = m_cutter;
|
||||
clip.target = m_cutter;
|
||||
clip.visualisation = m_cutter;
|
||||
addFilterPipeline(clip, "cut");
|
||||
setActiveFilterPipeline("cut");
|
||||
}
|
||||
@@ -455,3 +376,13 @@ void FemPostCutFilter::onChanged(const Property* prop) {
|
||||
|
||||
Fem::FemPostFilter::onChanged(prop);
|
||||
}
|
||||
|
||||
short int FemPostCutFilter::mustExecute(void) const {
|
||||
|
||||
if(Function.isTouched()) {
|
||||
|
||||
return 1;
|
||||
}
|
||||
else return App::DocumentObject::mustExecute();
|
||||
}
|
||||
|
||||
|
||||
@@ -47,44 +47,27 @@ public:
|
||||
/// Constructor
|
||||
FemPostFilter(void);
|
||||
virtual ~FemPostFilter();
|
||||
|
||||
|
||||
App::PropertyLink Input;
|
||||
|
||||
virtual App::DocumentObjectExecReturn* execute(void);
|
||||
|
||||
vtkSmartPointer<vtkAlgorithm> getOutputAlgorithm();
|
||||
|
||||
bool hasInputAlgorithmConnected();
|
||||
void connectInputAlgorithm(vtkSmartPointer<vtkAlgorithm> algo);
|
||||
vtkSmartPointer<vtkAlgorithm> getConnectedInputAlgorithm();
|
||||
|
||||
bool hasInputDataConnected();
|
||||
void connectInputData(vtkSmartPointer<vtkDataSet> data);
|
||||
vtkSmartPointer<vtkDataObject> 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();
|
||||
|
||||
protected:
|
||||
vtkDataObject* getInputData();
|
||||
|
||||
//pipeline handling for derived filter
|
||||
struct FilterPipeline {
|
||||
vtkSmartPointer<vtkAlgorithm> source, target, visualisation;
|
||||
vtkSmartPointer<vtkAlgorithm> source, target;
|
||||
std::vector<vtkSmartPointer<vtkAlgorithm> > algorithmStorage;
|
||||
};
|
||||
|
||||
void addFilterPipeline(const FilterPipeline& p, std::string name);
|
||||
void setActiveFilterPipeline(std::string name);
|
||||
FilterPipeline& getFilterPipeline(std::string name);
|
||||
|
||||
FilterPipeline& getFilterPipeline(std::string name);
|
||||
private:
|
||||
//handling of multiple pipelines which can be the filter
|
||||
std::map<std::string, FilterPipeline> m_pipelines;
|
||||
std::string m_activePipeline;
|
||||
vtkSmartPointer<vtkPassThrough> m_pass;
|
||||
};
|
||||
|
||||
class AppFemExport FemPostClipFilter : public FemPostFilter {
|
||||
@@ -102,13 +85,14 @@ public:
|
||||
virtual const char* getViewProviderName(void) const {
|
||||
return "FemGui::ViewProviderFemPostClip";
|
||||
}
|
||||
virtual short int mustExecute(void) const;
|
||||
|
||||
protected:
|
||||
virtual void onChanged(const App::Property* prop);
|
||||
|
||||
private:
|
||||
vtkSmartPointer<vtkTableBasedClipDataSet> m_clipper;
|
||||
vtkSmartPointer<vtkExtractGeometry> m_extractor;
|
||||
vtkSmartPointer<vtkTableBasedClipDataSet> m_clipper;
|
||||
vtkSmartPointer<vtkExtractGeometry> m_extractor;
|
||||
};
|
||||
|
||||
|
||||
@@ -127,6 +111,7 @@ public:
|
||||
virtual const char* getViewProviderName(void) const {
|
||||
return "FemGui::ViewProviderFemPostScalarClip";
|
||||
}
|
||||
virtual short int mustExecute(void) const;
|
||||
|
||||
protected:
|
||||
virtual App::DocumentObjectExecReturn* execute(void);
|
||||
@@ -153,6 +138,7 @@ public:
|
||||
virtual const char* getViewProviderName(void) const {
|
||||
return "FemGui::ViewProviderFemPostWarpVector";
|
||||
}
|
||||
virtual short int mustExecute(void) const;
|
||||
|
||||
protected:
|
||||
virtual App::DocumentObjectExecReturn* execute(void);
|
||||
@@ -176,6 +162,7 @@ public:
|
||||
virtual const char* getViewProviderName(void) const {
|
||||
return "FemGui::ViewProviderFemPostCut";
|
||||
}
|
||||
virtual short int mustExecute(void) const;
|
||||
|
||||
protected:
|
||||
virtual void onChanged(const App::Property* prop);
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <vtkImplicitFunction.h>
|
||||
#include <vtkPlane.h>
|
||||
#include <vtkSphere.h>
|
||||
#include <vtkBoundingBox.h>
|
||||
|
||||
namespace Fem
|
||||
{
|
||||
|
||||
@@ -42,38 +42,21 @@ PROPERTY_SOURCE(Fem::FemPostObject, App::GeoFeature)
|
||||
|
||||
FemPostObject::FemPostObject()
|
||||
{
|
||||
ADD_PROPERTY(ModificationTime,(0));
|
||||
ADD_PROPERTY(Data,(0));
|
||||
}
|
||||
|
||||
FemPostObject::~FemPostObject()
|
||||
{
|
||||
}
|
||||
|
||||
short FemPostObject::mustExecute(void) const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
vtkBoundingBox FemPostObject::getBoundingBox() {
|
||||
|
||||
DocumentObjectExecReturn* FemPostObject::execute(void) {
|
||||
|
||||
if(providesPolyData()) {
|
||||
polyDataSource->Update();
|
||||
vtkSmartPointer<vtkPolyData> poly = polyDataSource->GetOutput();
|
||||
|
||||
if(static_cast<unsigned long>(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<long>(poly->GetMTime()));
|
||||
}
|
||||
}
|
||||
vtkBoundingBox box;
|
||||
|
||||
return DocumentObject::StdReturn;
|
||||
}
|
||||
|
||||
void FemPostObject::onChanged(const Property* prop)
|
||||
{
|
||||
App::GeoFeature::onChanged(prop);
|
||||
if(Data.getValue() && Data.getValue()->IsA("vtkDataSet"))
|
||||
box.AddBounds(vtkDataSet::SafeDownCast(Data.getValue())->GetBounds());
|
||||
|
||||
//TODO: add calculation of multiblock and Multipiece datasets
|
||||
|
||||
return box;
|
||||
}
|
||||
|
||||
@@ -25,11 +25,10 @@
|
||||
#define Fem_FemPostObject_H
|
||||
|
||||
#include <App/GeoFeature.h>
|
||||
|
||||
#include <vtkSmartPointer.h>
|
||||
#include <vtkPolyDataAlgorithm.h>
|
||||
#include "PropertyPostDataObject.h"
|
||||
#include <vtkBoundingBox.h>
|
||||
|
||||
|
||||
namespace Fem
|
||||
{
|
||||
|
||||
@@ -43,33 +42,9 @@ public:
|
||||
FemPostObject(void);
|
||||
virtual ~FemPostObject();
|
||||
|
||||
App::PropertyInteger ModificationTime;
|
||||
|
||||
/// returns the type name of the ViewProvider
|
||||
virtual const char* getViewProviderName(void) const {
|
||||
return "FemGui::ViewProviderFemPostObject";
|
||||
}
|
||||
Fem::PropertyPostDataObject Data;
|
||||
|
||||
short mustExecute(void) const;
|
||||
virtual App::DocumentObjectExecReturn* execute(void);
|
||||
|
||||
//bounding box handling. By default the bounding box is calcualted from the poly data output
|
||||
//which is visualized
|
||||
virtual vtkBoundingBox getBoundingBox() {return m_boundingBox;};
|
||||
|
||||
//poly data algorithm handling
|
||||
virtual bool providesPolyData() {return getPolyAlgorithm()!=NULL;};
|
||||
vtkSmartPointer<vtkPolyDataAlgorithm> getPolyAlgorithm() {return polyDataSource;};
|
||||
|
||||
|
||||
protected:
|
||||
virtual void onChanged(const App::Property* prop);
|
||||
|
||||
//members
|
||||
vtkSmartPointer<vtkPolyDataAlgorithm> polyDataSource;
|
||||
|
||||
private:
|
||||
vtkBoundingBox m_boundingBox;
|
||||
vtkBoundingBox getBoundingBox();
|
||||
};
|
||||
|
||||
} //namespace Fem
|
||||
|
||||
@@ -56,13 +56,11 @@ 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(Functions, (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()
|
||||
@@ -76,21 +74,11 @@ short FemPostPipeline::mustExecute(void) const
|
||||
|
||||
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<vtkStructuredGrid*>(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());
|
||||
// }
|
||||
|
||||
//if we are in serial mode we just copy over the data of the last filter,
|
||||
//but if we are in parallel we need to combine all filter results
|
||||
|
||||
|
||||
|
||||
return Fem::FemPostObject::execute();
|
||||
}
|
||||
@@ -98,9 +86,14 @@ DocumentObjectExecReturn* FemPostPipeline::execute(void) {
|
||||
|
||||
bool FemPostPipeline::canRead(Base::FileInfo File) {
|
||||
|
||||
if (File.hasExtension("vtk") )
|
||||
if (File.hasExtension("vtk") ||
|
||||
File.hasExtension("vtp") ||
|
||||
File.hasExtension("vts") ||
|
||||
File.hasExtension("vtr") ||
|
||||
File.hasExtension("vtu") ||
|
||||
File.hasExtension("vti"))
|
||||
return true;
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -111,21 +104,16 @@ void FemPostPipeline::read(Base::FileInfo File) {
|
||||
if (!File.isReadable())
|
||||
throw Base::Exception("File to load not existing or not readable");
|
||||
|
||||
if (File.hasExtension("vtk") ) {
|
||||
if (canRead(File)) {
|
||||
|
||||
vtkSmartPointer<vtkDataSetReader> reader = vtkSmartPointer<vtkDataSetReader>::New();
|
||||
reader->SetFileName(File.filePath().c_str());
|
||||
reader->Update();
|
||||
source = reader->GetOutput();
|
||||
|
||||
Data.setValue(reader->GetOutput());
|
||||
}
|
||||
else{
|
||||
throw Base::Exception("Unknown extension");
|
||||
}
|
||||
|
||||
polyDataSource = vtkGeometryFilter::New();
|
||||
polyDataSource->SetInputData(source);
|
||||
polyDataSource->Update();
|
||||
}
|
||||
|
||||
|
||||
@@ -151,26 +139,53 @@ void FemPostPipeline::onChanged(const Property* prop)
|
||||
std::vector<App::DocumentObject*>::iterator it = objs.begin();
|
||||
FemPostFilter* filter = static_cast<FemPostFilter*>(*it);
|
||||
|
||||
//the first one is always connected to the pipeline
|
||||
if(!filter->hasInputDataConnected() || filter->getConnectedInputData() != getSource())
|
||||
filter->connectInputData(getSource());
|
||||
//If we have a Input we need to ensure our filters are connected correctly
|
||||
if(Input.getValue()) {
|
||||
|
||||
//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<FemPostFilter*>(*it);
|
||||
//the first filter is always connected to the input
|
||||
if(filter->Input.getValue() != Input.getValue())
|
||||
filter->Input.setValue(Input.getValue());
|
||||
|
||||
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());
|
||||
}
|
||||
//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<FemPostFilter*>(*it);
|
||||
|
||||
if(Mode.getValue() == 0) { //serial mode
|
||||
if( nextFilter->Input.getValue() != filter)
|
||||
nextFilter->Input.setValue(filter);
|
||||
}
|
||||
else { //Parallel mode
|
||||
if( nextFilter->Input.getValue() != Input.getValue())
|
||||
nextFilter->Input.setValue(Input.getValue());
|
||||
}
|
||||
|
||||
filter = nextFilter;
|
||||
};
|
||||
}
|
||||
//if we have no input the filters are responsible of grabbing the pipeline data themself
|
||||
else {
|
||||
//the first filter must always grab the data
|
||||
if(filter->Input.getValue() != NULL)
|
||||
filter->Input.setValue(NULL);
|
||||
|
||||
filter = nextFilter;
|
||||
};
|
||||
//all the others need to be connected to the previous filter or grab the data, dependend on mode
|
||||
++it;
|
||||
for(; it != objs.end(); ++it) {
|
||||
FemPostFilter* nextFilter = static_cast<FemPostFilter*>(*it);
|
||||
|
||||
if(Mode.getValue() == 0) { //serial mode
|
||||
if( nextFilter->Input.getValue() != filter)
|
||||
nextFilter->Input.setValue(filter);
|
||||
}
|
||||
else { //Parallel mode
|
||||
if( nextFilter->Input.getValue() != NULL)
|
||||
nextFilter->Input.setValue(NULL);
|
||||
}
|
||||
|
||||
filter = nextFilter;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
App::GeoFeature::onChanged(prop);
|
||||
@@ -185,11 +200,21 @@ FemPostObject* FemPostPipeline::getLastPostObject() {
|
||||
return static_cast<FemPostObject*>(Filter.getValues().back());
|
||||
}
|
||||
|
||||
bool FemPostPipeline::holdsPostObject(FemPostObject* obj) {
|
||||
|
||||
std::vector<App::DocumentObject*>::const_iterator it = Filter.getValues().begin();
|
||||
for(; it != Filter.getValues().end(); ++it) {
|
||||
|
||||
if(*it == obj)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void FemPostPipeline::load(FemResultObject* res) {
|
||||
|
||||
vtkSmartPointer<vtkUnstructuredGrid> grid = vtkUnstructuredGrid::New();
|
||||
source = grid;
|
||||
|
||||
//first copy the mesh over
|
||||
//########################
|
||||
@@ -329,15 +354,11 @@ void FemPostPipeline::load(FemResultObject* res) {
|
||||
|
||||
for(std::vector<Base::Vector3d>::const_iterator it=vec.begin(); it!=vec.end(); ++it) {
|
||||
double tuple[] = {it->x, it->y, it->z};
|
||||
Base::Console().Message("disp mag; %f\n", it->Length());
|
||||
data->InsertNextTuple(tuple);
|
||||
}
|
||||
|
||||
grid->GetPointData()->AddArray(data);
|
||||
}
|
||||
|
||||
|
||||
polyDataSource = vtkGeometryFilter::New();
|
||||
polyDataSource->SetInputData(source);
|
||||
polyDataSource->Update();
|
||||
Data.setValue(grid);
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
namespace Fem
|
||||
{
|
||||
|
||||
class AppFemExport FemPostPipeline : public Fem::FemPostObject
|
||||
class AppFemExport FemPostPipeline : public Fem::FemPostFilter
|
||||
{
|
||||
PROPERTY_HEADER(Fem::FemPostPipeline);
|
||||
|
||||
@@ -45,7 +45,7 @@ public:
|
||||
virtual ~FemPostPipeline();
|
||||
|
||||
App::PropertyLinkList Filter;
|
||||
App::PropertyLink Function;
|
||||
App::PropertyLink Functions;
|
||||
App::PropertyEnumeration Mode;
|
||||
|
||||
short mustExecute(void) const;
|
||||
@@ -64,14 +64,13 @@ public:
|
||||
void load(FemResultObject* res);
|
||||
|
||||
//Pipeline handling
|
||||
vtkSmartPointer<vtkDataSet> getSource() {return source;};
|
||||
FemPostObject* getLastPostObject();
|
||||
bool holdsPostObject(FemPostObject* obj);
|
||||
|
||||
protected:
|
||||
virtual void onChanged(const App::Property* prop);
|
||||
|
||||
private:
|
||||
vtkSmartPointer<vtkDataSet> source;
|
||||
static const char* ModeEnums[];
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user