Skip to content
Permalink
Browse files

FEM: added PostGlyphFilter

  • Loading branch information...
AMstuff committed Oct 9, 2017
1 parent 3b479e0 commit 41781f87ea0fd91540d84924f9966664172ce48d
@@ -177,6 +177,7 @@ PyMOD_INIT_FUNC(Fem)
Fem::FemPostDataAlongLineFilter ::init();
Fem::FemPostScalarClipFilter ::init();
Fem::FemPostWarpVectorFilter ::init();
Fem::FemPostGlyphFilter ::init();
Fem::FemPostCutFilter ::init();
Fem::FemPostFunction ::init();
Fem::FemPostFunctionProvider ::init();
@@ -50,6 +50,8 @@ SET(Python_SRCS
HypothesisPy.h
)
if(BUILD_FEM_VTK)
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
SET(Python_SRCS
${Python_SRCS}
FemPostPipelinePy.xml
@@ -428,7 +428,7 @@ DocumentObjectExecReturn* FemPostWarpVectorFilter::execute(void) {
val = Vector.getValueAsString();

std::vector<std::string> array;

vtkSmartPointer<vtkDataObject> data = getInputData();
if(!data || !data->IsA("vtkDataSet"))
return StdReturn;
@@ -526,4 +526,242 @@ DocumentObjectExecReturn* FemPostCutFilter::execute(void) {
return Fem::FemPostFilter::execute();
}

PROPERTY_SOURCE(Fem::FemPostGlyphFilter, Fem::FemPostFilter)

FemPostGlyphFilter::FemPostGlyphFilter(void): FemPostFilter() {

ADD_PROPERTY_TYPE(Factor, (0), "Glyph", App::Prop_None, "The factor by which the Glyph is scaled and colored");
ADD_PROPERTY_TYPE(Vector, (long(0)), "Glyph", App::Prop_None, "The field of vectors");
ADD_PROPERTY_TYPE(GlyphType, (long(0)), "Glyph", App::Prop_None, "The selected glyph");

arrowSource = vtkSmartPointer<vtkArrowSource>::New();

programmableGlyph = vtkSmartPointer<vtkProgrammableGlyphFilter>::New();
programmableGlyph->SetSourceConnection(arrowSource->GetOutputPort());
programmableGlyph->SetGlyphMethod(FemPostGlyphFilter::calcGlyphArrow, programmableGlyph);

//set up glyph methods here
glyphMethod method1 = {};
method1.Name = "doubleheaded Arrow";
method1.method = FemPostGlyphFilter::calcGlyphArrow;
glyphMethods.push_back(method1);

glyphMethod method2 = {};
method2.Name = "Arrow";
method2.method = FemPostGlyphFilter::calcGlyphArrow;
glyphMethods.push_back(method2);

FilterPipeline glyph;

glyph.source = programmableGlyph;
glyph.target = programmableGlyph;
addFilterPipeline(glyph, "glyph");
setActiveFilterPipeline("glyph");
}

FemPostGlyphFilter::~FemPostGlyphFilter() {

}


DocumentObjectExecReturn* FemPostGlyphFilter::execute(void) {

std::string val;
if(m_vectorFields.getEnums() && Vector.getValue() >= 0)
val = Vector.getValueAsString();

std::vector<std::string> array;

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) {
if(pd->GetArray(i)->GetNumberOfComponents()==3)
array.push_back(pd->GetArrayName(i));
}

App::Enumeration empty;
Vector.setValue(empty);
m_vectorFields.setEnums(array);
Vector.setValue(m_vectorFields);

std::vector<std::string>::iterator it = std::find(array.begin(), array.end(), val);
if(!val.empty() && it != array.end())
Vector.setValue(val.c_str());

//do the same with the glyphs
std::string glyphVal;
if(m_glyphMethods.getEnums() && GlyphType.getValue() >= 0)
glyphVal = GlyphType.getValueAsString();

std::vector<std::string> namesGlyphMethods;
for (auto it = glyphMethods.begin(); it != glyphMethods.end(); it++){
namesGlyphMethods.push_back(it->Name);
}

GlyphType.setValue(empty);
m_glyphMethods.setEnums(namesGlyphMethods);
GlyphType.setValue(m_glyphMethods);

std::vector<std::string>::iterator it2 = std::find(namesGlyphMethods.begin(), namesGlyphMethods.end(), glyphVal);
if(!glyphVal.empty() && it != namesGlyphMethods.end())
GlyphType.setValue(glyphVal.c_str());

return Fem::FemPostFilter::execute();
}


void FemPostGlyphFilter::calcGlyphArrow(void *arg){
vtkProgrammableGlyphFilter *glyphFilter = (vtkProgrammableGlyphFilter*) arg;

if (!glyphFilter)
{
return;
}

//aquire Data
vtkPointData* pd = glyphFilter->GetPointData();
int pid = glyphFilter->GetPointId();

//translation
double position[3];
glyphFilter->GetPoint(position);

//orientation
double orientvector[3];
pd->GetArray(0)->GetTuple(pid, orientvector);

//magnitude
double magnitude = vtkMath::Norm(orientvector);

//setup transformation
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
transform->Identity();
transform->Translate(position[0], position[1], position[2]);
double vNew[3];

// if statement from paraviews vtkArrowGlyphFilter.cxx
if (magnitude > 0.0)
{
// if there is no y or z component
if (orientvector[1] == 0.0 && orientvector[2] == 0.0)
{
if (orientvector[0] < 0)
{ // just flip x if we need to
transform->RotateWXYZ(180.0,0,1,0);
}
}
else
{
vNew[0] = (orientvector[0] + magnitude ) / 2.0 ;
vNew[1] = orientvector[1] / 2.0;
vNew[2] = orientvector[2] / 2.0;
transform->RotateWXYZ(180.0, vNew[0], vNew[1], vNew[2]);
}
}
//end -- thanks paraview
transform->Update();


vtkSmartPointer<vtkArrowSource> arrowSource = vtkSmartPointer<vtkArrowSource>::New();
//if arrowSource wasn't provided outside of this function, use defaults
if (!arrowSource){
arrowSource = vtkSmartPointer<vtkArrowSource>::New();
}

vtkSmartPointer<vtkArrowSource> localArrow = vtkSmartPointer<vtkArrowSource>::New();


vtkSmartPointer<vtkAlgorithm> glyph;

bool doubleheaded = true;
if (doubleheaded) {
//take settings from arrowSource and scale them, so that the length is 1 again
localArrow->SetTipLength(arrowSource->GetTipLength()*2.0);
localArrow->SetTipRadius(arrowSource->GetTipRadius()*2.0);
localArrow->SetTipResolution(arrowSource->GetTipResolution());
localArrow->SetShaftRadius(arrowSource->GetShaftRadius()*2.0);
localArrow->SetShaftResolution(arrowSource->GetShaftResolution());

//inversion attributes are only necessary if we're using double-headed arrows, since otherwise the orientation will do the inversion for us
if (magnitude < 0)
localArrow->InvertOn();

localArrow->Update();

//make the double-headed arrow
vtkSmartPointer<vtkPolyData> arrow1 = vtkSmartPointer<vtkPolyData>::New();
arrow1->ShallowCopy(localArrow->GetOutput());
vtkSmartPointer<vtkTransform> transformArrow = vtkSmartPointer<vtkTransform>::New();
transformArrow->Identity();
transformArrow->RotateZ(180);
transformArrow->Update();
vtkSmartPointer<vtkTransformPolyDataFilter> transformArrowFilter = vtkSmartPointer<vtkTransformPolyDataFilter>::New();
transformArrowFilter->SetTransform(transformArrow);
transformArrowFilter->SetInputConnection(localArrow->GetOutputPort());
transformArrowFilter->Update();
vtkSmartPointer<vtkPolyData> arrow2 = vtkSmartPointer<vtkPolyData>::New();
arrow2->ShallowCopy(transformArrowFilter->GetOutput());
vtkSmartPointer<vtkAppendPolyData> doubleHeadedArrow = vtkSmartPointer<vtkAppendPolyData>::New();
doubleHeadedArrow->AddInputData(arrow1);
doubleHeadedArrow->AddInputData(arrow2);
doubleHeadedArrow->Update();
glyph = doubleHeadedArrow;
transform->Scale(.5,.5,.5);
transform->Update();
}
else {
//just one arrow --> don't mess with scaling
localArrow->SetTipLength(arrowSource->GetTipLength());
localArrow->SetTipRadius(arrowSource->GetTipRadius());
localArrow->SetTipResolution(arrowSource->GetTipResolution());
localArrow->SetShaftRadius(arrowSource->GetShaftRadius());
localArrow->SetShaftResolution(arrowSource->GetShaftResolution());
localArrow->Update();
glyph = localArrow;
}

//apply the transformation to the glyph
vtkSmartPointer<vtkTransformFilter> transformFilter = vtkSmartPointer<vtkTransformFilter>::New();
transformFilter->SetTransform(transform);
transformFilter->SetInputConnection(glyph->GetOutputPort());
transformFilter->Update();

glyphFilter->SetSourceConnection(transformFilter->GetOutputPort());
}

void FemPostGlyphFilter::onChanged(const Property* prop)
{
if (prop == &Factor) {
//programmableGlyph->SetScaleFactor(Factor.getValue());
}
else if (prop == &Vector && (Vector.getValue() >= 0)) {
//programmableGlyph->SetInputArrayToProcess(0, 0, 0,vtkDataObject::FIELD_ASSOCIATION_POINTS, Vector.getValueAsString() );
}
else if (prop == &GlyphType && (GlyphType.getValue() >= 0)) {
std::string glyph = GlyphType.getValueAsString();
for (auto it = glyphMethods.begin(); it != glyphMethods.end(); it++){
if (it->Name.compare(glyph)){
void (*method)(void *) = it->method;
programmableGlyph->SetGlyphMethod(method, programmableGlyph);
}
}
}

Fem::FemPostFilter::onChanged(prop);
}

short int FemPostGlyphFilter::mustExecute(void) const {

if(Factor.isTouched() ||
Vector.isTouched() ||
GlyphType.isTouched()) {

return 1;
}
else return App::DocumentObject::mustExecute();
}
@@ -39,6 +39,16 @@
#include <vtkProbeFilter.h>
#include <vtkThreshold.h>


#include <vtkSmartPointer.h>
#include <vtkTransform.h>
#include <vtkTransformFilter.h>
#include <vtkTransformPolyDataFilter.h>
#include <vtkAppendPolyData.h>
#include <vtkPolyData.h>
#include <vtkArrowSource.h>
#include <vtkProgrammableGlyphFilter.h>

namespace Fem
{

@@ -208,6 +218,44 @@ class AppFemExport FemPostCutFilter : public FemPostFilter {
vtkSmartPointer<vtkCutter> m_cutter;
};


class AppFemExport FemPostGlyphFilter : public FemPostFilter {

PROPERTY_HEADER(Fem::FemPostGlyphFilter);

public:
FemPostGlyphFilter(void);
virtual ~FemPostGlyphFilter();

App::PropertyEnumeration GlyphType;
App::PropertyEnumeration Vector;
App::PropertyFloat Factor;

virtual const char* getViewProviderName(void) const {
return "FemGui::ViewProviderFemPostGlyph";
}
virtual short int mustExecute(void) const;

protected:
virtual App::DocumentObjectExecReturn* execute(void);
virtual void onChanged(const App::Property* prop);

private:
struct glyphMethod {
std::string Name;
void (*method)(void *) ;
};

std::vector<FemPostGlyphFilter::glyphMethod> glyphMethods;
vtkSmartPointer<vtkArrowSource> arrowSource;
vtkSmartPointer<vtkProgrammableGlyphFilter> programmableGlyph;
App::Enumeration m_vectorFields;
App::Enumeration m_glyphMethods;
static void calcGlyphArrow(void *arg);
};



} //namespace Fem


@@ -150,6 +150,7 @@ PyMOD_INIT_FUNC(FemGui)
FemGui::ViewProviderFemPostDataAlongLine ::init();
FemGui::ViewProviderFemPostScalarClip ::init();
FemGui::ViewProviderFemPostWarpVector ::init();
FemGui::ViewProviderFemPostGlyph ::init();
FemGui::ViewProviderFemPostCut ::init();
#endif

@@ -112,6 +112,7 @@ if(BUILD_FEM_VTK)
TaskPostDataAlongLine.ui
TaskPostScalarClip.ui
TaskPostWarpVector.ui
TaskPostGlyph.ui
TaskPostCut.ui
PlaneWidget.ui
SphereWidget.ui
@@ -275,6 +276,7 @@ if(BUILD_FEM_VTK)
TaskPostScalarClip.ui
TaskPostDisplay.ui
TaskPostWarpVector.ui
TaskPostGlyph.ui
TaskPostCut.ui
TaskPostBoxes.h
TaskPostBoxes.cpp
@@ -1299,6 +1299,31 @@ bool CmdFemPostWarpVectorFilter::isActive(void)
return hasActiveDocument();
}

DEF_STD_CMD_A(CmdFemPostGlyphFilter);

CmdFemPostGlyphFilter::CmdFemPostGlyphFilter()
: Command("FEM_PostCreateGlyph")
{
sAppModule = "Fem";
sGroup = QT_TR_NOOP("Fem");
sMenuText = QT_TR_NOOP("Glyph Filter");
sToolTipText = QT_TR_NOOP("Displays a Glyph to show a vectorfield");
sWhatsThis = "FEM_PostCreateGlyph";
sStatusTip = sToolTipText;
sPixmap = "fem-warp";
}

void CmdFemPostGlyphFilter::activated(int)
{
setupFilter(this, "Glyph");
}

bool CmdFemPostGlyphFilter::isActive(void)
{
return hasActiveDocument();
}


DEF_STD_CMD_A(CmdFemPostCutFilter);

CmdFemPostCutFilter::CmdFemPostCutFilter()
@@ -1591,6 +1616,7 @@ void CreateFemCommands(void)
rcCmdMgr.addCommand(new CmdFemPostCreateLinearizedStressesFilter);
rcCmdMgr.addCommand(new CmdFemPostCreateScalarClipFilter);
rcCmdMgr.addCommand(new CmdFemPostWarpVectorFilter);
rcCmdMgr.addCommand(new CmdFemPostGlyphFilter);
rcCmdMgr.addCommand(new CmdFemPostFunctions);
rcCmdMgr.addCommand(new CmdFemPostApllyChanges);
rcCmdMgr.addCommand(new CmdFemPostPipelineFromResult);

0 comments on commit 41781f8

Please sign in to comment.
You can’t perform that action at this time.