[FEM] add new filter to display iso contours
- very valuable to display for example electromagnetic field lines
This commit is contained in:
@@ -178,6 +178,7 @@ PyMOD_INIT_FUNC(Fem)
|
||||
Fem::FemPostPipeline ::init();
|
||||
Fem::FemPostFilter ::init();
|
||||
Fem::FemPostClipFilter ::init();
|
||||
Fem::FemPostContoursFilter ::init();
|
||||
Fem::FemPostCutFilter ::init();
|
||||
Fem::FemPostDataAlongLineFilter ::init();
|
||||
Fem::FemPostDataAtPointFilter ::init();
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#ifndef _PreComp_
|
||||
# include <Python.h>
|
||||
# include <vtkDoubleArray.h>
|
||||
# include <vtkPointData.h>
|
||||
#endif
|
||||
|
||||
@@ -68,23 +69,22 @@ DocumentObjectExecReturn* FemPostFilter::execute() {
|
||||
|
||||
if (!m_pipelines.empty() && !m_activePipeline.empty()) {
|
||||
FemPostFilter::FilterPipeline& pipe = m_pipelines[m_activePipeline];
|
||||
if (m_activePipeline.length() >= 11) {
|
||||
std::string LineClip = m_activePipeline.substr(0, 13);
|
||||
std::string PointClip = m_activePipeline.substr(0, 11);
|
||||
if ((LineClip == "DataAlongLine") || (PointClip == "DataAtPoint")) {
|
||||
vtkSmartPointer<vtkDataObject> data = getInputData();
|
||||
if (!data || !data->IsA("vtkDataSet"))
|
||||
return StdReturn;
|
||||
|
||||
if ((m_activePipeline == "DataAlongLine") || (m_activePipeline == "DataAtPoint")) {
|
||||
pipe.filterSource->SetSourceData(getInputData());
|
||||
pipe.filterTarget->Update();
|
||||
|
||||
Data.setValue(pipe.filterTarget->GetOutputDataObject(0));
|
||||
}
|
||||
}
|
||||
else {
|
||||
pipe.source->SetInputDataObject(getInputData());
|
||||
pipe.source->SetInputDataObject(data);
|
||||
pipe.target->Update();
|
||||
Data.setValue(pipe.target->GetOutputDataObject(0));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return StdReturn;
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ FemPostClipFilter::FemPostClipFilter() : FemPostFilter() {
|
||||
(false),
|
||||
"Clip",
|
||||
App::Prop_None,
|
||||
"Decides if cells are cuttet and interpolated or if the cells are kept as a whole");
|
||||
"Decides if cells are cut and interpolated or if the cells are kept as a whole");
|
||||
|
||||
FilterPipeline clip;
|
||||
m_clipper = vtkSmartPointer<vtkTableBasedClipDataSet>::New();
|
||||
@@ -187,7 +187,8 @@ short int FemPostClipFilter::mustExecute() const {
|
||||
|
||||
return 1;
|
||||
}
|
||||
else return App::DocumentObject::mustExecute();
|
||||
else
|
||||
return App::DocumentObject::mustExecute();
|
||||
}
|
||||
|
||||
DocumentObjectExecReturn* FemPostClipFilter::execute() {
|
||||
@@ -711,3 +712,260 @@ DocumentObjectExecReturn* FemPostCutFilter::execute()
|
||||
|
||||
return Fem::FemPostFilter::execute();
|
||||
}
|
||||
|
||||
// ***************************************************************************
|
||||
// contours filter
|
||||
PROPERTY_SOURCE(Fem::FemPostContoursFilter, Fem::FemPostFilter)
|
||||
|
||||
FemPostContoursFilter::FemPostContoursFilter()
|
||||
: FemPostFilter()
|
||||
{
|
||||
ADD_PROPERTY_TYPE(NumberOfContours, (10), "Contours",
|
||||
App::Prop_None, "The number of contours");
|
||||
ADD_PROPERTY_TYPE(Field, (long(0)), "Clip",
|
||||
App::Prop_None, "The field used to clip");
|
||||
ADD_PROPERTY_TYPE(VectorMode, ((long)0), "Contours",
|
||||
App::Prop_None, "Select what vector field");
|
||||
ADD_PROPERTY_TYPE(NoColor, (false), "Contours",
|
||||
App::Prop_None, "Don't color the contours");
|
||||
|
||||
m_contourConstraints.LowerBound = 1;
|
||||
m_contourConstraints.UpperBound = 1000;
|
||||
m_contourConstraints.StepSize = 1;
|
||||
NumberOfContours.setConstraints(&m_contourConstraints);
|
||||
|
||||
FilterPipeline contours;
|
||||
m_contours = vtkSmartPointer<vtkContourFilter>::New();
|
||||
m_contours->ComputeScalarsOn();
|
||||
contours.source = m_contours;
|
||||
contours.target = m_contours;
|
||||
addFilterPipeline(contours, "contours");
|
||||
setActiveFilterPipeline("contours");
|
||||
}
|
||||
|
||||
FemPostContoursFilter::~FemPostContoursFilter()
|
||||
{
|
||||
}
|
||||
|
||||
DocumentObjectExecReturn* FemPostContoursFilter::execute()
|
||||
{
|
||||
// update list of available fields and their vectors
|
||||
if (!m_blockPropertyChanges) {
|
||||
refreshFields();
|
||||
refreshVectors();
|
||||
}
|
||||
|
||||
// recalculate the filter
|
||||
auto returnObject = Fem::FemPostFilter::execute();
|
||||
|
||||
// delete contour field
|
||||
vtkSmartPointer<vtkDataObject> data = getInputData();
|
||||
vtkDataSet* dset = vtkDataSet::SafeDownCast(data);
|
||||
vtkPointData* pd = dset->GetPointData();
|
||||
dset->GetPointData()->RemoveArray(contourFieldName.c_str());
|
||||
// refresh fields to reflect the deletion
|
||||
if (!m_blockPropertyChanges)
|
||||
refreshFields();
|
||||
|
||||
return returnObject;
|
||||
}
|
||||
|
||||
void FemPostContoursFilter::onChanged(const Property* prop)
|
||||
{
|
||||
if (m_blockPropertyChanges)
|
||||
return;
|
||||
|
||||
if (prop == &Field && (Field.getValue() >= 0))
|
||||
refreshVectors();
|
||||
|
||||
// note that we need to calculate also in case of a Data change
|
||||
// otherwise the contours output would be empty and the ViewProviderFemPostObject
|
||||
// would not get any data
|
||||
if ((prop == &Field || prop == &VectorMode || prop == &NumberOfContours || prop == &Data)
|
||||
&& (Field.getValue() >= 0)) {
|
||||
double p[2];
|
||||
|
||||
// get the field and its data
|
||||
vtkSmartPointer<vtkDataObject> data = getInputData();
|
||||
if (!data || !data->IsA("vtkDataSet"))
|
||||
return;
|
||||
vtkDataSet* dset = vtkDataSet::SafeDownCast(data);
|
||||
vtkDataArray* pdata = dset->GetPointData()->GetArray(Field.getValueAsString());
|
||||
|
||||
if (!pdata)
|
||||
return;
|
||||
if (pdata->GetNumberOfComponents() == 1) {
|
||||
// if we have a scalar, we can directly use the array
|
||||
m_contours->SetInputArrayToProcess(
|
||||
0, 0, 0, vtkDataObject::FIELD_ASSOCIATION_POINTS, Field.getValueAsString());
|
||||
pdata->GetRange(p);
|
||||
recalculateContours(p[0], p[1]);
|
||||
}
|
||||
else {
|
||||
// The contour filter handles vectors by taking always its first component.
|
||||
// There is no other solution than to make the desired vectorn component a
|
||||
// scalar array and append this temporarily to the data. (vtkExtractVectorComponents
|
||||
// does not work because our data is an unstructured data set.)
|
||||
int component = -1;
|
||||
if (VectorMode.getValue() == 1)
|
||||
component = 0;
|
||||
else if (VectorMode.getValue() == 2)
|
||||
component = 1;
|
||||
else if (VectorMode.getValue() == 3)
|
||||
component = 2;
|
||||
// extract the component to a new array
|
||||
vtkSmartPointer<vtkDoubleArray> componentArray = vtkSmartPointer<vtkDoubleArray>::New();
|
||||
componentArray->SetNumberOfComponents(1);
|
||||
vtkIdType numTuples = pdata->GetNumberOfTuples();
|
||||
componentArray->SetNumberOfTuples(numTuples);
|
||||
|
||||
if (component >= 0) {
|
||||
for (vtkIdType tupleIdx = 0; tupleIdx < numTuples; ++tupleIdx) {
|
||||
componentArray->SetComponent(
|
||||
tupleIdx, 0, pdata->GetComponent(tupleIdx, component));
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (vtkIdType tupleIdx = 0; tupleIdx < numTuples; ++tupleIdx) {
|
||||
componentArray->SetComponent(tupleIdx, 0,
|
||||
std::sqrt(pdata->GetComponent(tupleIdx, 0) *
|
||||
pdata->GetComponent(tupleIdx, 0) +
|
||||
pdata->GetComponent(tupleIdx, 1) *
|
||||
pdata->GetComponent(tupleIdx, 1) +
|
||||
pdata->GetComponent(tupleIdx, 2) *
|
||||
pdata->GetComponent(tupleIdx, 2) ) );
|
||||
}
|
||||
}
|
||||
// name the array
|
||||
contourFieldName =
|
||||
std::string(Field.getValueAsString()) + "_contour";
|
||||
componentArray->SetName(contourFieldName.c_str());
|
||||
|
||||
// add the array as new field and use it for the contour filter
|
||||
dset->GetPointData()->AddArray(componentArray);
|
||||
m_contours->SetInputArrayToProcess(0, 0, 0,
|
||||
vtkDataObject::FIELD_ASSOCIATION_POINTS, contourFieldName.c_str());
|
||||
componentArray->GetRange(p);
|
||||
recalculateContours(p[0], p[1]);
|
||||
if (prop == &Data) {
|
||||
// we must recalculate to pass the new created contours field
|
||||
// to ViewProviderFemPostObject
|
||||
m_blockPropertyChanges = true;
|
||||
execute();
|
||||
m_blockPropertyChanges = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Fem::FemPostFilter::onChanged(prop);
|
||||
}
|
||||
|
||||
short int FemPostContoursFilter::mustExecute() const
|
||||
{
|
||||
if (Field.isTouched() || VectorMode.isTouched() || NumberOfContours.isTouched()
|
||||
|| Data.isTouched())
|
||||
return 1;
|
||||
else
|
||||
return App::DocumentObject::mustExecute();
|
||||
}
|
||||
|
||||
void FemPostContoursFilter::recalculateContours(double min, double max)
|
||||
{
|
||||
// As the min and max contours are not visible, an input of "3" leads
|
||||
// to 1 visible contour. To not confuse the user, take the visible contours
|
||||
// for NumberOfContours
|
||||
int visibleNum = NumberOfContours.getValue() + 2;
|
||||
m_contours->GenerateValues(visibleNum, min, max);
|
||||
}
|
||||
|
||||
void FemPostContoursFilter::refreshFields()
|
||||
{
|
||||
m_blockPropertyChanges = true;
|
||||
|
||||
std::string fieldName;
|
||||
if (Field.getValue() >= 0)
|
||||
fieldName = Field.getValueAsString();
|
||||
|
||||
std::vector<std::string> FieldsArray;
|
||||
|
||||
vtkSmartPointer<vtkDataObject> data = getInputData();
|
||||
if (!data || !data->IsA("vtkDataSet")) {
|
||||
m_blockPropertyChanges = false;
|
||||
return;
|
||||
}
|
||||
vtkDataSet* dset = vtkDataSet::SafeDownCast(data);
|
||||
vtkPointData* pd = dset->GetPointData();
|
||||
|
||||
// get all fields
|
||||
for (int i = 0; i < pd->GetNumberOfArrays(); ++i) {
|
||||
FieldsArray.emplace_back(pd->GetArrayName(i));
|
||||
}
|
||||
|
||||
App::Enumeration empty;
|
||||
Field.setValue(empty);
|
||||
m_fields.setEnums(FieldsArray);
|
||||
Field.setValue(m_fields);
|
||||
|
||||
// search if the current field is in the available ones and set it
|
||||
std::vector<std::string>::iterator it =
|
||||
std::find(FieldsArray.begin(), FieldsArray.end(), fieldName);
|
||||
if (!fieldName.empty() && it != FieldsArray.end()) {
|
||||
Field.setValue(fieldName.c_str());
|
||||
}
|
||||
else {
|
||||
m_blockPropertyChanges = false;
|
||||
// select the first field
|
||||
Field.setValue(long(0));
|
||||
fieldName = Field.getValueAsString();
|
||||
}
|
||||
|
||||
m_blockPropertyChanges = false;
|
||||
}
|
||||
|
||||
void FemPostContoursFilter::refreshVectors()
|
||||
{
|
||||
// refreshes the list of available vectors for the current Field
|
||||
m_blockPropertyChanges = true;
|
||||
|
||||
vtkSmartPointer<vtkDataObject> data = getInputData();
|
||||
if (!data || !data->IsA("vtkDataSet")) {
|
||||
m_blockPropertyChanges = false;
|
||||
return;
|
||||
}
|
||||
vtkDataSet* dset = vtkDataSet::SafeDownCast(data);
|
||||
vtkDataArray* fieldArray = dset->GetPointData()->GetArray(Field.getValueAsString());
|
||||
if (!fieldArray) {
|
||||
m_blockPropertyChanges = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// store name if already set
|
||||
std::string vectorName;
|
||||
if (VectorMode.hasEnums() && VectorMode.getValue() >= 0)
|
||||
vectorName = VectorMode.getValueAsString();
|
||||
|
||||
std::vector<std::string> vectorArray;
|
||||
if (fieldArray->GetNumberOfComponents() == 1)
|
||||
vectorArray.emplace_back("Not a vector");
|
||||
else {
|
||||
vectorArray.emplace_back("Magnitude");
|
||||
if (fieldArray->GetNumberOfComponents() >= 2) {
|
||||
vectorArray.emplace_back("X");
|
||||
vectorArray.emplace_back("Y");
|
||||
}
|
||||
if (fieldArray->GetNumberOfComponents() >= 3) {
|
||||
vectorArray.emplace_back("Z");
|
||||
}
|
||||
}
|
||||
App::Enumeration empty;
|
||||
VectorMode.setValue(empty);
|
||||
m_vectors.setEnums(vectorArray);
|
||||
VectorMode.setValue(m_vectors);
|
||||
|
||||
// apply stored name
|
||||
auto it = std::find(vectorArray.begin(), vectorArray.end(), vectorName);
|
||||
if (!vectorName.empty() && it != vectorArray.end())
|
||||
VectorMode.setValue(vectorName.c_str());
|
||||
|
||||
m_blockPropertyChanges = false;
|
||||
}
|
||||
|
||||
@@ -23,9 +23,12 @@
|
||||
#ifndef Fem_FemPostFilter_H
|
||||
#define Fem_FemPostFilter_H
|
||||
|
||||
#include <vtkContourFilter.h>
|
||||
#include <vtkCutter.h>
|
||||
#include <vtkExtractGeometry.h>
|
||||
#include <vtkExtractVectorComponents.h>
|
||||
#include <vtkLineSource.h>
|
||||
#include <vtkVectorNorm.h>
|
||||
#include <vtkPointSource.h>
|
||||
#include <vtkProbeFilter.h>
|
||||
#include <vtkSmartPointer.h>
|
||||
@@ -239,6 +242,44 @@ private:
|
||||
vtkSmartPointer<vtkCutter> m_cutter;
|
||||
};
|
||||
|
||||
class FemExport FemPostContoursFilter: public FemPostFilter
|
||||
{
|
||||
|
||||
PROPERTY_HEADER_WITH_OVERRIDE(Fem::FemPostContoursFilter);
|
||||
|
||||
public:
|
||||
FemPostContoursFilter();
|
||||
~FemPostContoursFilter() override;
|
||||
|
||||
App::PropertyEnumeration Field;
|
||||
App::PropertyIntegerConstraint NumberOfContours;
|
||||
App::PropertyEnumeration VectorMode;
|
||||
App::PropertyBool NoColor;
|
||||
|
||||
const char* getViewProviderName() const override
|
||||
{
|
||||
return "FemGui::ViewProviderFemPostContours";
|
||||
}
|
||||
short int mustExecute() const override;
|
||||
|
||||
protected:
|
||||
App::DocumentObjectExecReturn* execute() override;
|
||||
void onChanged(const App::Property* prop) override;
|
||||
void recalculateContours(double min, double max);
|
||||
void refreshFields();
|
||||
void refreshVectors();
|
||||
bool m_blockPropertyChanges = false;
|
||||
std::string contourFieldName;
|
||||
|
||||
private:
|
||||
vtkSmartPointer<vtkContourFilter> m_contours;
|
||||
vtkSmartPointer<vtkExtractVectorComponents> m_extractor;
|
||||
vtkSmartPointer<vtkVectorNorm> m_norm;
|
||||
App::Enumeration m_fields;
|
||||
App::Enumeration m_vectors;
|
||||
App::PropertyIntegerConstraint::Constraints m_contourConstraints;
|
||||
};
|
||||
|
||||
} //namespace Fem
|
||||
|
||||
|
||||
|
||||
@@ -152,6 +152,7 @@ PyMOD_INIT_FUNC(FemGui)
|
||||
FemGui::ViewProviderFemPostObject ::init();
|
||||
FemGui::ViewProviderFemPostPipeline ::init();
|
||||
FemGui::ViewProviderFemPostClip ::init();
|
||||
FemGui::ViewProviderFemPostContours ::init();
|
||||
FemGui::ViewProviderFemPostCut ::init();
|
||||
FemGui::ViewProviderFemPostDataAlongLine ::init();
|
||||
FemGui::ViewProviderFemPostDataAtPoint ::init();
|
||||
|
||||
@@ -93,6 +93,7 @@ if(BUILD_FEM_VTK)
|
||||
${FemGui_UIC_SRCS}
|
||||
TaskPostDisplay.ui
|
||||
TaskPostClip.ui
|
||||
TaskPostContours.ui
|
||||
TaskPostDataAlongLine.ui
|
||||
TaskPostDataAtPoint.ui
|
||||
TaskPostScalarClip.ui
|
||||
@@ -271,6 +272,7 @@ if(BUILD_FEM_VTK)
|
||||
PlaneWidget.ui
|
||||
SphereWidget.ui
|
||||
TaskPostClip.ui
|
||||
TaskPostContours.ui
|
||||
TaskPostDataAlongLine.ui
|
||||
TaskPostDataAtPoint.ui
|
||||
TaskPostScalarClip.ui
|
||||
|
||||
@@ -1534,13 +1534,14 @@ void setupFilter(Gui::Command* cmd, std::string Name) {
|
||||
|
||||
// issue error if no post object
|
||||
if (!((selObject->getTypeId() == Base::Type::fromName("Fem::FemPostPipeline"))
|
||||
|| (selObject->getTypeId() == Base::Type::fromName("Fem::FemPostWarpVectorFilter"))
|
||||
|| (selObject->getTypeId() == Base::Type::fromName("Fem::FemPostScalarClipFilter"))
|
||||
|| (selObject->getTypeId() == Base::Type::fromName("Fem::FemPostCutFilter"))
|
||||
|| (selObject->getTypeId() == Base::Type::fromName("Fem::FemPostClipFilter"))
|
||||
|| (selObject->getTypeId() == Base::Type::fromName("Fem::FemPostDataAlongLineFilter")) )
|
||||
) {
|
||||
QMessageBox::warning(Gui::getMainWindow(),
|
||||
|| (selObject->getTypeId() == Base::Type::fromName("Fem::FemPostClipFilter"))
|
||||
|| (selObject->getTypeId() == Base::Type::fromName("Fem::FemPostContoursFilter"))
|
||||
|| (selObject->getTypeId() == Base::Type::fromName("Fem::FemPostCutFilter"))
|
||||
|| (selObject->getTypeId() == Base::Type::fromName("Fem::FemPostDataAlongLineFilter"))
|
||||
|| (selObject->getTypeId() == Base::Type::fromName("Fem::FemPostScalarClipFilter"))
|
||||
|| (selObject->getTypeId() == Base::Type::fromName("Fem::FemPostWarpVectorFilter")))) {
|
||||
QMessageBox::warning(
|
||||
Gui::getMainWindow(),
|
||||
qApp->translate("setupFilter", "Error: no post processing object selected."),
|
||||
qApp->translate("setupFilter", "The filter could not be set up."));
|
||||
return;
|
||||
@@ -1721,20 +1722,21 @@ bool CmdFemPostClipFilter::isActive()
|
||||
// only allow one object
|
||||
if (getSelection().getSelection().size() > 1)
|
||||
return false;
|
||||
// only activate if a result is either a post pipeline, scalar, cut or warp filter,
|
||||
// itself or along line filter
|
||||
// only activate if a result is either a post pipeline or a possible filter
|
||||
if (getSelection().getObjectsOfType<Fem::FemPostPipeline>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostScalarClipFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostCutFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostWarpVectorFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostClipFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostDataAlongLineFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostScalarClipFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostContoursFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostCutFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostWarpVectorFilter>().size() == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
@@ -1765,20 +1767,21 @@ bool CmdFemPostCutFilter::isActive()
|
||||
// only allow one object
|
||||
if (getSelection().getSelection().size() > 1)
|
||||
return false;
|
||||
// only activate if a result is either a post pipeline, scalar, clip or warp filter,
|
||||
// itself, or along line filter
|
||||
// only activate if a result is either a post pipeline or a possible filter
|
||||
if (getSelection().getObjectsOfType<Fem::FemPostPipeline>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostScalarClipFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostClipFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostWarpVectorFilter>().size() == 1)
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostContoursFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostCutFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostScalarClipFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostDataAlongLineFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostWarpVectorFilter>().size() == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
@@ -1809,14 +1812,16 @@ bool CmdFemPostDataAlongLineFilter::isActive()
|
||||
// only allow one object
|
||||
if (getSelection().getSelection().size() > 1)
|
||||
return false;
|
||||
// only activate if a result is either a post pipeline, scalar, cut, clip or warp filter
|
||||
// only activate if a result is either a post pipeline or a possible filter
|
||||
if (getSelection().getObjectsOfType<Fem::FemPostPipeline>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostScalarClipFilter>().size() == 1)
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostClipFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostContoursFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostCutFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostClipFilter>().size() == 1)
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostScalarClipFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostWarpVectorFilter>().size() == 1)
|
||||
return true;
|
||||
@@ -1852,20 +1857,19 @@ bool CmdFemPostDataAtPointFilter::isActive()
|
||||
// only allow one object
|
||||
if (getSelection().getSelection().size() > 1)
|
||||
return false;
|
||||
// only activate if a result is either a post pipeline, scalar, cut, clip,
|
||||
// warp or along line filter
|
||||
// only activate if a result is either a post pipeline or a possible filter
|
||||
if (getSelection().getObjectsOfType<Fem::FemPostPipeline>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostScalarClipFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostCutFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostClipFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostWarpVectorFilter>().size() == 1)
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostCutFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostDataAlongLineFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostScalarClipFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostWarpVectorFilter>().size() == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
@@ -1970,17 +1974,19 @@ bool CmdFemPostScalarClipFilter::isActive()
|
||||
// only allow one object
|
||||
if (getSelection().getSelection().size() > 1)
|
||||
return false;
|
||||
// only activate if a result is either a post pipeline, clip, cut, warp or along line filter
|
||||
// only activate if a result is either a post pipeline or a possible other filter
|
||||
if (getSelection().getObjectsOfType<Fem::FemPostPipeline>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostClipFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostContoursFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostCutFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostWarpVectorFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostDataAlongLineFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostWarpVectorFilter>().size() == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
@@ -2011,17 +2017,63 @@ bool CmdFemPostWarpVectorFilter::isActive()
|
||||
// only allow one object
|
||||
if (getSelection().getSelection().size() > 1)
|
||||
return false;
|
||||
// only activate if a result is either a post pipeline, scalar, clip, cut or along line filter
|
||||
// only activate if a result is either a post pipeline or a possible other filter
|
||||
if (getSelection().getObjectsOfType<Fem::FemPostPipeline>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostScalarClipFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostClipFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostCutFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostClipFilter>().size() == 1)
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostContoursFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostDataAlongLineFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostScalarClipFilter>().size() == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
//================================================================================================
|
||||
DEF_STD_CMD_A(CmdFemPostContoursFilter)
|
||||
|
||||
CmdFemPostContoursFilter::CmdFemPostContoursFilter()
|
||||
: Command("FEM_PostFilterContours")
|
||||
{
|
||||
sAppModule = "Fem";
|
||||
sGroup = QT_TR_NOOP("Fem");
|
||||
sMenuText = QT_TR_NOOP("Contours filter");
|
||||
sToolTipText =
|
||||
QT_TR_NOOP("Define/create a contours filter which displays iso contours");
|
||||
sWhatsThis = "FEM_PostFilterContours";
|
||||
sStatusTip = sToolTipText;
|
||||
sPixmap = "FEM_PostFilterContours";
|
||||
}
|
||||
|
||||
void CmdFemPostContoursFilter::activated(int)
|
||||
{
|
||||
setupFilter(this, "Contours");
|
||||
}
|
||||
|
||||
bool CmdFemPostContoursFilter::isActive()
|
||||
{
|
||||
// only allow one object
|
||||
if (getSelection().getSelection().size() > 1)
|
||||
return false;
|
||||
// only activate if a result is either a post pipeline or a possible other filter
|
||||
if (getSelection().getObjectsOfType<Fem::FemPostPipeline>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostClipFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostCutFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostDataAlongLineFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostScalarClipFilter>().size() == 1)
|
||||
return true;
|
||||
else if (getSelection().getObjectsOfType<Fem::FemPostWarpVectorFilter>().size() == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
@@ -2370,15 +2422,16 @@ void CreateFemCommands()
|
||||
|
||||
// vtk post processing
|
||||
#ifdef FC_USE_VTK
|
||||
rcCmdMgr.addCommand(new CmdFemPostApllyChanges);
|
||||
rcCmdMgr.addCommand(new CmdFemPostClipFilter);
|
||||
rcCmdMgr.addCommand(new CmdFemPostContoursFilter);
|
||||
rcCmdMgr.addCommand(new CmdFemPostCutFilter);
|
||||
rcCmdMgr.addCommand(new CmdFemPostDataAlongLineFilter);
|
||||
rcCmdMgr.addCommand(new CmdFemPostDataAtPointFilter);
|
||||
rcCmdMgr.addCommand(new CmdFemPostLinearizedStressesFilter);
|
||||
rcCmdMgr.addCommand(new CmdFemPostScalarClipFilter);
|
||||
rcCmdMgr.addCommand(new CmdFemPostWarpVectorFilter);
|
||||
rcCmdMgr.addCommand(new CmdFemPostFunctions);
|
||||
rcCmdMgr.addCommand(new CmdFemPostApllyChanges);
|
||||
rcCmdMgr.addCommand(new CmdFemPostPipelineFromResult);
|
||||
rcCmdMgr.addCommand(new CmdFemPostScalarClipFilter);
|
||||
rcCmdMgr.addCommand(new CmdFemPostWarpVectorFilter);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
<!-- gui command icons: post processing -->
|
||||
<file>icons/FEM_PostFilterClipRegion.svg</file>
|
||||
<file>icons/FEM_PostFilterClipScalar.svg</file>
|
||||
<file>icons/FEM_PostFilterContours.svg</file>
|
||||
<file>icons/FEM_PostFilterCutFunction.svg</file>
|
||||
<file>icons/FEM_PostFilterDataAlongLine.svg</file>
|
||||
<file>icons/FEM_PostFilterDataAtPoint.svg</file>
|
||||
|
||||
70
src/Mod/Fem/Gui/Resources/icons/FEM_PostFilterContours.svg
Normal file
70
src/Mod/Fem/Gui/Resources/icons/FEM_PostFilterContours.svg
Normal file
@@ -0,0 +1,70 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg id="svg2" version="1.1" width="64" height="64" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
|
||||
<metadata id="metadata8">
|
||||
<rdf:RDF>
|
||||
<cc:Work rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:creator>
|
||||
<cc:Agent>
|
||||
<dc:title>[Alexander Gryson]</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:creator>
|
||||
<dc:date>2017-03-11</dc:date>
|
||||
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
|
||||
<dc:publisher>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:publisher>
|
||||
<dc:identifier>FreeCAD/src/Mod/</dc:identifier>
|
||||
<dc:rights>
|
||||
<cc:Agent>
|
||||
<dc:title>FreeCAD LGPL2+</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:rights>
|
||||
<cc:license>https://www.gnu.org/copyleft/lesser.html</cc:license>
|
||||
<dc:contributor>
|
||||
<cc:Agent>
|
||||
<dc:title>[agryson] Alexander Gryson</dc:title>
|
||||
</cc:Agent>
|
||||
</dc:contributor>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs id="defs6">
|
||||
<linearGradient id="linearGradient4937">
|
||||
<stop style="stop-color:#4e9a06;stop-opacity:1" offset="0" id="stop4933" />
|
||||
<stop style="stop-color:#73d216;stop-opacity:1" offset="1" id="stop4935" />
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient4929">
|
||||
<stop style="stop-color:#4e9a06;stop-opacity:1" offset="0" id="stop4925" />
|
||||
<stop style="stop-color:#73d216;stop-opacity:1" offset="1" id="stop4927" />
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient4921">
|
||||
<stop style="stop-color:#4e9a06;stop-opacity:1" offset="0" id="stop4917" />
|
||||
<stop style="stop-color:#73d216;stop-opacity:1" offset="1" id="stop4919" />
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient3826">
|
||||
<stop style="stop-color:#4e9a06;stop-opacity:1" offset="0" id="stop3828" />
|
||||
<stop style="stop-color:#73d216;stop-opacity:1" offset="1" id="stop3830" />
|
||||
</linearGradient>
|
||||
<linearGradient id="linearGradient3816">
|
||||
<stop style="stop-color:#73d216;stop-opacity:1" offset="0" id="stop3818" />
|
||||
<stop style="stop-color:#8ae234;stop-opacity:1" offset="1" id="stop3820" />
|
||||
</linearGradient>
|
||||
<linearGradient xlink:href="#linearGradient3816" id="linearGradient3841" gradientUnits="userSpaceOnUse" x1="95" y1="47" x2="91" y2="15" />
|
||||
<linearGradient xlink:href="#linearGradient3826" id="linearGradient3843" gradientUnits="userSpaceOnUse" x1="120" y1="46" x2="109" y2="15" />
|
||||
<linearGradient xlink:href="#linearGradient4929" id="linearGradient4931" x1="117.5" y1="50.5" x2="117.5" y2="50.5" gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient xlink:href="#linearGradient4937" id="linearGradient4939" x1="100.60143" y1="9.4661894" x2="117.5" y2="50.5" gradientUnits="userSpaceOnUse" />
|
||||
<linearGradient xlink:href="#linearGradient4921" id="linearGradient4949" gradientUnits="userSpaceOnUse" x1="100.60143" y1="9.4661894" x2="117.5" y2="50.5" />
|
||||
</defs>
|
||||
<g id="g3834" transform="matrix(1.5077443,0,0,1.2007124,-134.53727,-4.0213696)" style="stroke-width:0.743219">
|
||||
<path id="path3812" d="M 117,4 L 131,45 L 104,56 L 90,13 Z" style="fill:none;fill-opacity:1;stroke:#172a04;stroke-width:1.48643;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path style="fill:none;stroke:url(#linearGradient4939);stroke-width:1.11483;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" d="M 115.09277,8.1017279 C 115.09277,8.1017279 111.03315,16.682926 114.5164,25.024389 C 117.99965,33.365852 121.44094,39.334366 123.38943,40.657696 L 128,43.789004" id="path1048" />
|
||||
<path style="fill:none;stroke:url(#linearGradient4931);stroke-width:1.11483;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" d="M 107.86441,9.8386331 C 107.86441,9.8386331 102.54878,16.007596 105.02439,25.503784 C 107.5,34.999971 110.94492,40.843691 116.171,43.789004 L 121.3238,46.693017" id="path1050" />
|
||||
<path style="fill:none;stroke:url(#linearGradient4949);stroke-width:1.11483;stroke-linecap:butt;stroke-linejoin:miter;stroke-dasharray:none;stroke-opacity:1" d="M 99.999951,11.793103 C 99.999951,11.793103 95.928545,17.853922 99.053812,26.962416 C 102.17908,36.07091 106.80942,47.780649 110.5,50.196728" id="path1052" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.7 KiB |
@@ -56,6 +56,7 @@
|
||||
#include "ui_TaskPostDataAtPoint.h"
|
||||
#include "ui_TaskPostDisplay.h"
|
||||
#include "ui_TaskPostScalarClip.h"
|
||||
#include "ui_TaskPostContours.h"
|
||||
#include "ui_TaskPostWarpVector.h"
|
||||
|
||||
#include "TaskPostBoxes.h"
|
||||
@@ -1701,4 +1702,137 @@ void TaskPostCut::on_FunctionBox_currentIndexChanged(int idx) {
|
||||
recompute();
|
||||
}
|
||||
|
||||
|
||||
// ***************************************************************************
|
||||
// contours filter
|
||||
TaskPostContours::TaskPostContours(ViewProviderDocumentObject* view, QWidget* parent)
|
||||
: TaskPostBox(view, Gui::BitmapFactory().pixmap("FEM_PostFilterContours"),
|
||||
tr("Contours filter options"), parent),
|
||||
ui(new Ui_TaskPostContours)
|
||||
{
|
||||
assert(view->isDerivedFrom(ViewProviderFemPostContours::getClassTypeId()));
|
||||
|
||||
// load the views widget
|
||||
proxy = new QWidget(this);
|
||||
ui->setupUi(proxy);
|
||||
QMetaObject::connectSlotsByName(this);
|
||||
this->groupLayout()->addWidget(proxy);
|
||||
|
||||
// load filter settings
|
||||
updateEnumerationList(getTypedObject<Fem::FemPostContoursFilter>()->Field, ui->fieldsCB);
|
||||
updateEnumerationList(getTypedObject<Fem::FemPostContoursFilter>()->VectorMode, ui->vectorsCB);
|
||||
// for a new filter, initialize the coloring
|
||||
auto colorState = static_cast<Fem::FemPostContoursFilter*>(getObject())->NoColor.getValue();
|
||||
if (!colorState && getTypedView<ViewProviderFemPostObject>()->Field.getValue() == 0) {
|
||||
getTypedView<ViewProviderFemPostObject>()->Field.setValue(1);
|
||||
}
|
||||
|
||||
ui->numberContoursSB->setValue(
|
||||
static_cast<Fem::FemPostContoursFilter*>(getObject())->NumberOfContours.getValue());
|
||||
ui->noColorCB->setChecked(colorState);
|
||||
|
||||
// connect
|
||||
connect(ui->fieldsCB, qOverload<int>(&QComboBox::currentIndexChanged),
|
||||
this, &TaskPostContours::onFieldsChanged);
|
||||
connect(ui->vectorsCB, qOverload<int>(&QComboBox::currentIndexChanged),
|
||||
this, &TaskPostContours::onVectorModeChanged);
|
||||
connect(ui->numberContoursSB, qOverload<int>(&QSpinBox::valueChanged),
|
||||
this, &TaskPostContours::onNumberOfContoursChanged);
|
||||
connect(ui->noColorCB, &QCheckBox::toggled,
|
||||
this, &TaskPostContours::onNoColorChanged);
|
||||
}
|
||||
|
||||
TaskPostContours::~TaskPostContours()
|
||||
{}
|
||||
|
||||
void TaskPostContours::applyPythonCode()
|
||||
{}
|
||||
|
||||
void TaskPostContours::updateFields(int idx)
|
||||
{
|
||||
std::vector<std::string> fieldArray;
|
||||
std::vector<std::string> vec =
|
||||
getTypedObject<Fem::FemPostContoursFilter>()->Field.getEnumVector();
|
||||
for (std::vector<std::string>::iterator it = vec.begin(); it != vec.end(); ++it) {
|
||||
fieldArray.emplace_back(*it);
|
||||
}
|
||||
// update the ViewProvider Field enums
|
||||
App::Enumeration anEnum;
|
||||
getTypedView<ViewProviderFemPostObject>()->Field.setValue(anEnum);
|
||||
anEnum.setEnums(fieldArray);
|
||||
getTypedView<ViewProviderFemPostObject>()->Field.setValue(anEnum);
|
||||
// set new Field index to ViewProvider Field
|
||||
// the ViewProvider field starts with an additional entry "None",
|
||||
// therefore the desired new setting is idx + 1
|
||||
if (!static_cast<Fem::FemPostContoursFilter*>(getObject())->NoColor.getValue())
|
||||
getTypedView<ViewProviderFemPostObject>()->Field.setValue(idx + 1);
|
||||
else
|
||||
getTypedView<ViewProviderFemPostObject>()->Field.setValue(long(0));
|
||||
}
|
||||
|
||||
void TaskPostContours::onFieldsChanged(int idx)
|
||||
{
|
||||
static_cast<Fem::FemPostContoursFilter*>(getObject())->Field.setValue(idx);
|
||||
|
||||
blockVectorUpdate = true;
|
||||
updateEnumerationList(getTypedObject<Fem::FemPostContoursFilter>()->VectorMode, ui->vectorsCB);
|
||||
blockVectorUpdate = false;
|
||||
|
||||
// In > 99 % of the cases the coloring should be equal to the field,
|
||||
// thus change the coloring field too. Users can override this be resetting only the coloring
|
||||
// field afterwards in the properties if really necessary.
|
||||
updateFields(idx);
|
||||
|
||||
// since a new field can be e.g. no vector while the previous one was,
|
||||
// we must also update the VectorMode
|
||||
if (!static_cast<Fem::FemPostContoursFilter*>(getObject())->NoColor.getValue()) {
|
||||
auto newMode = getTypedObject<Fem::FemPostContoursFilter>()->VectorMode.getValue();
|
||||
getTypedView<ViewProviderFemPostObject>()->VectorMode.setValue(newMode);
|
||||
}
|
||||
}
|
||||
|
||||
void TaskPostContours::onVectorModeChanged(int idx)
|
||||
{
|
||||
static_cast<Fem::FemPostContoursFilter*>(getObject())->VectorMode.setValue(idx);
|
||||
recompute();
|
||||
if (!blockVectorUpdate) {
|
||||
// we can have the case that the previous field had VectorMode "Z" but
|
||||
// since it is a 2D field, Z is eompty thus no field is available to color
|
||||
// when the user noch goes back to e.g. "Y" we must set the Field
|
||||
// first to get the possible VectorModes of that field
|
||||
auto currentField = getTypedObject<Fem::FemPostContoursFilter>()->Field.getValue();
|
||||
updateFields(currentField);
|
||||
// now we can set the VectorMode
|
||||
if (!static_cast<Fem::FemPostContoursFilter*>(getObject())->NoColor.getValue())
|
||||
getTypedView<ViewProviderFemPostObject>()->VectorMode.setValue(idx);
|
||||
}
|
||||
}
|
||||
|
||||
void TaskPostContours::onNumberOfContoursChanged(int number)
|
||||
{
|
||||
static_cast<Fem::FemPostContoursFilter*>(getObject())->NumberOfContours.setValue(number);
|
||||
recompute();
|
||||
}
|
||||
|
||||
void TaskPostContours::onNoColorChanged(bool state)
|
||||
{
|
||||
static_cast<Fem::FemPostContoursFilter*>(getObject())->NoColor.setValue(state);
|
||||
if (state) {
|
||||
// no color
|
||||
getTypedView<ViewProviderFemPostObject>()->Field.setValue(long(0));
|
||||
}
|
||||
else {
|
||||
// set same field
|
||||
auto currentField = getTypedObject<Fem::FemPostContoursFilter>()->Field.getValue();
|
||||
// the ViewProvider field starts with an additional entry "None",
|
||||
// therefore the desired new setting is idx + 1
|
||||
getTypedView<ViewProviderFemPostObject>()->Field.setValue(currentField + 1);
|
||||
// set the VectorMode too
|
||||
auto currentMode = getTypedObject<Fem::FemPostContoursFilter>()->VectorMode.getValue();
|
||||
getTypedView<ViewProviderFemPostObject>()->VectorMode.setValue(currentMode);
|
||||
}
|
||||
recompute();
|
||||
}
|
||||
|
||||
|
||||
#include "moc_TaskPostBoxes.cpp"
|
||||
|
||||
@@ -34,6 +34,7 @@
|
||||
class QComboBox;
|
||||
class Ui_TaskPostDisplay;
|
||||
class Ui_TaskPostClip;
|
||||
class Ui_TaskPostContours;
|
||||
class Ui_TaskPostDataAlongLine;
|
||||
class Ui_TaskPostDataAtPoint;
|
||||
class Ui_TaskPostScalarClip;
|
||||
@@ -415,6 +416,30 @@ private:
|
||||
FunctionWidget* fwidget;
|
||||
};
|
||||
|
||||
|
||||
class TaskPostContours: public TaskPostBox
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit TaskPostContours(Gui::ViewProviderDocumentObject* view, QWidget* parent = nullptr);
|
||||
~TaskPostContours() override;
|
||||
|
||||
void applyPythonCode() override;
|
||||
|
||||
private Q_SLOTS:
|
||||
void onFieldsChanged(int idx);
|
||||
void onVectorModeChanged(int idx);
|
||||
void onNumberOfContoursChanged(int number);
|
||||
void onNoColorChanged(bool state);
|
||||
|
||||
private:
|
||||
QWidget* proxy;
|
||||
std::unique_ptr<Ui_TaskPostContours> ui;
|
||||
bool blockVectorUpdate = false;
|
||||
void updateFields(int idx);
|
||||
};
|
||||
|
||||
} //namespace FemGui
|
||||
|
||||
#endif // GUI_TASKVIEW_TaskPostDisplay_H
|
||||
|
||||
87
src/Mod/Fem/Gui/TaskPostContours.ui
Normal file
87
src/Mod/Fem/Gui/TaskPostContours.ui
Normal file
@@ -0,0 +1,87 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TaskPostContours</class>
|
||||
<widget class="QWidget" name="TaskPostContours">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>250</width>
|
||||
<height>115</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="1">
|
||||
<widget class="QComboBox" name="fieldsCB"/>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="vectorL">
|
||||
<property name="text">
|
||||
<string>Vector:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="vectorsCB"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="fieldL">
|
||||
<property name="text">
|
||||
<string>Field:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="numberContoursL">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true">Number of contours:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="numberContoursSB">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="noColorCB">
|
||||
<property name="toolTip">
|
||||
<string>Contour lines will not be colored</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>No color</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -99,7 +99,6 @@ void ViewProviderFemPostDataAtPoint::setupTaskDialog(TaskDlgPost* dlg) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
PROPERTY_SOURCE(FemGui::ViewProviderFemPostScalarClip, FemGui::ViewProviderFemPostObject)
|
||||
|
||||
ViewProviderFemPostScalarClip::ViewProviderFemPostScalarClip() {
|
||||
@@ -140,7 +139,6 @@ void ViewProviderFemPostWarpVector::setupTaskDialog(TaskDlgPost* dlg) {
|
||||
FemGui::ViewProviderFemPostObject::setupTaskDialog(dlg);
|
||||
}
|
||||
|
||||
|
||||
PROPERTY_SOURCE(FemGui::ViewProviderFemPostCut, FemGui::ViewProviderFemPostObject)
|
||||
|
||||
ViewProviderFemPostCut::ViewProviderFemPostCut() {
|
||||
@@ -161,3 +159,19 @@ void ViewProviderFemPostCut::setupTaskDialog(TaskDlgPost* dlg) {
|
||||
//add the display options
|
||||
FemGui::ViewProviderFemPostObject::setupTaskDialog(dlg);
|
||||
}
|
||||
|
||||
PROPERTY_SOURCE(FemGui::ViewProviderFemPostContours, FemGui::ViewProviderFemPostObject)
|
||||
|
||||
ViewProviderFemPostContours::ViewProviderFemPostContours()
|
||||
{
|
||||
sPixmap = "FEM_PostFilterContours";
|
||||
}
|
||||
|
||||
ViewProviderFemPostContours::~ViewProviderFemPostContours()
|
||||
{}
|
||||
|
||||
void ViewProviderFemPostContours::setupTaskDialog(TaskDlgPost* dlg)
|
||||
{
|
||||
// the filter-specific task panel
|
||||
dlg->appendBox(new TaskPostContours(dlg->getView()));
|
||||
}
|
||||
|
||||
@@ -108,6 +108,20 @@ protected:
|
||||
void setupTaskDialog(TaskDlgPost* dlg) override;
|
||||
};
|
||||
|
||||
class FemGuiExport ViewProviderFemPostContours: public ViewProviderFemPostObject
|
||||
{
|
||||
|
||||
PROPERTY_HEADER_WITH_OVERRIDE(FemGui::ViewProviderFemPostContours);
|
||||
|
||||
public:
|
||||
/// constructor.
|
||||
ViewProviderFemPostContours();
|
||||
~ViewProviderFemPostContours() override;
|
||||
|
||||
protected:
|
||||
void setupTaskDialog(TaskDlgPost* dlg) override;
|
||||
};
|
||||
|
||||
} //namespace FemGui
|
||||
|
||||
|
||||
|
||||
@@ -203,6 +203,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
|
||||
<< "FEM_PostFilterClipScalar"
|
||||
<< "FEM_PostFilterCutFunction"
|
||||
<< "FEM_PostFilterClipRegion"
|
||||
<< "FEM_PostFilterContours"
|
||||
<< "FEM_PostFilterDataAlongLine"
|
||||
<< "FEM_PostFilterLinearizedStresses"
|
||||
<< "FEM_PostFilterDataAtPoint"
|
||||
@@ -371,6 +372,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
|
||||
<< "FEM_PostFilterClipScalar"
|
||||
<< "FEM_PostFilterCutFunction"
|
||||
<< "FEM_PostFilterClipRegion"
|
||||
<< "FEM_PostFilterContours"
|
||||
<< "FEM_PostFilterDataAlongLine"
|
||||
<< "FEM_PostFilterLinearizedStresses"
|
||||
<< "FEM_PostFilterDataAtPoint"
|
||||
|
||||
@@ -720,6 +720,21 @@ def makePostVtkFilterWarp(
|
||||
return obj
|
||||
|
||||
|
||||
def makePostVtkFilterContours(
|
||||
doc,
|
||||
base_vtk_result,
|
||||
name="VtkFilterContours"
|
||||
):
|
||||
"""makePostVtkFilterContours(document, base_vtk_result, [name]):
|
||||
creates a FEM post processing contours filter object (vtk based)"""
|
||||
obj = doc.addObject("Fem::FemPostContoursFilter", name)
|
||||
tmp_filter_list = base_vtk_result.Filter
|
||||
tmp_filter_list.append(obj)
|
||||
base_vtk_result.Filter = tmp_filter_list
|
||||
del tmp_filter_list
|
||||
return obj
|
||||
|
||||
|
||||
def makePostVtkResult(
|
||||
doc,
|
||||
base_result,
|
||||
|
||||
@@ -154,6 +154,7 @@ class TestObjectExistance(unittest.TestCase):
|
||||
|
||||
expected_vtk_obj_types = [
|
||||
"Fem::FemPostClipFilter",
|
||||
"Fem::FemPostContoursFilter",
|
||||
"Fem::FemPostCutFilter",
|
||||
"Fem::FemPostDataAlongLineFilter",
|
||||
"Fem::FemPostDataAtPointFilter",
|
||||
|
||||
@@ -87,11 +87,11 @@ class TestObjectCreate(unittest.TestCase):
|
||||
# solver children: equations --> 8
|
||||
# gmsh mesh children: group, region, boundary layer --> 3
|
||||
# resule children: mesh result --> 1
|
||||
# post pipeline children: region, scalar, cut, wrap --> 4
|
||||
# post pipeline children: region, scalar, cut, wrap --> 5
|
||||
# analysis itself is not in analysis group --> 1
|
||||
# thus: -17
|
||||
# thus: -18
|
||||
|
||||
self.assertEqual(len(doc.Analysis.Group), count_defmake - 17)
|
||||
self.assertEqual(len(doc.Analysis.Group), count_defmake - 18)
|
||||
self.assertEqual(len(doc.Objects), count_defmake)
|
||||
|
||||
fcc_print("doc objects count: {}, method: {}".format(
|
||||
@@ -1858,6 +1858,7 @@ def create_all_fem_objects_doc(
|
||||
vres = analysis.addObject(ObjectsFem.makePostVtkResult(doc, res))[0]
|
||||
ObjectsFem.makePostVtkFilterClipRegion(doc, vres)
|
||||
ObjectsFem.makePostVtkFilterClipScalar(doc, vres)
|
||||
ObjectsFem.makePostVtkFilterContours(doc, vres)
|
||||
ObjectsFem.makePostVtkFilterCutFunction(doc, vres)
|
||||
ObjectsFem.makePostVtkFilterWarp(doc, vres)
|
||||
|
||||
|
||||
@@ -64,21 +64,21 @@ class VPMeshGmsh:
|
||||
|
||||
def setEdit(self, vobj, mode):
|
||||
# hide all FEM meshes and VTK FemPost* objects
|
||||
for o in vobj.Object.Document.Objects:
|
||||
for obj in vobj.Object.Document.Objects:
|
||||
if (
|
||||
o.isDerivedFrom("Fem::FemMeshObject")
|
||||
or o.isDerivedFrom("Fem::FemPostPipeline")
|
||||
or o.isDerivedFrom("Fem::FemPostClipFilter")
|
||||
or o.isDerivedFrom("Fem::FemPostScalarClipFilter")
|
||||
or o.isDerivedFrom("Fem::FemPostWarpVectorFilter")
|
||||
or o.isDerivedFrom("Fem::FemPostDataAlongLineFilter")
|
||||
or o.isDerivedFrom("Fem::FemPostDataAtPointFilter")
|
||||
or o.isDerivedFrom("Fem::FemPostCutFilter")
|
||||
or o.isDerivedFrom("Fem::FemPostDataAlongLineFilter")
|
||||
or o.isDerivedFrom("Fem::FemPostPlaneFunction")
|
||||
or o.isDerivedFrom("Fem::FemPostSphereFunction")
|
||||
obj.isDerivedFrom("Fem::FemMeshObject")
|
||||
or obj.isDerivedFrom("Fem::FemPostClipFilter")
|
||||
or obj.isDerivedFrom("Fem::FemPostContoursFilter")
|
||||
or obj.isDerivedFrom("Fem::FemPostCutFilter")
|
||||
or obj.isDerivedFrom("Fem::FemPostDataAlongLineFilter")
|
||||
or obj.isDerivedFrom("Fem::FemPostDataAtPointFilter")
|
||||
or obj.isDerivedFrom("Fem::FemPostPipeline")
|
||||
or obj.isDerivedFrom("Fem::FemPostPlaneFunction")
|
||||
or obj.isDerivedFrom("Fem::FemPostScalarClipFilter")
|
||||
or obj.isDerivedFrom("Fem::FemPostSphereFunction")
|
||||
or obj.isDerivedFrom("Fem::FemPostWarpVectorFilter")
|
||||
):
|
||||
o.ViewObject.hide()
|
||||
obj.ViewObject.hide()
|
||||
# show the mesh we like to edit
|
||||
self.ViewObject.show()
|
||||
# show task panel
|
||||
|
||||
Reference in New Issue
Block a user