Commit 7014b417 authored by Max Zeyen's avatar Max Zeyen

New feature for vtkPointDataToCellData and vtkCellDataToPointData

New feature gives an option allowing the selective processing of data arrays.
The default is still standard behavior.

Filter vtkPointDataToCellData modified

Added an option to activate a new feature in the filter.
It allows users to select which point data arrays the filter should be applied to.

Selective vtkPointDataToCellData and vtkCellDataToPointData

The two VTK filters mentioned above got a new feature allowing them
to perform their operations only on data arrays selected by the user.

Documentation and code cleanup

Documented the newly added functionality to vtkPointDataToCellData and vtkCellDataToPointData.
Cleaned and modernized the code a little (C++11).

Adding Tests for new Filter feature

Modified the test of CellDataToPointData to test the new feature.
Created a new test for PointDataToCellData to test the new feature.
parent 92e2c1dc
......@@ -29,6 +29,7 @@ vtk_add_test_cxx(vtkFiltersCoreCxxTests tests
TestImplicitPolyDataDistance.cxx
TestMaskPoints.cxx,NO_VALID
TestNamedComponents.cxx,NO_VALID
TestPointDataToCellData.cxx,NO_VALID
TestPolyDataConnectivityFilter.cxx,NO_VALID
TestProbeFilter.cxx,NO_VALID
TestProbeFilterImageInput.cxx
......
......@@ -18,6 +18,8 @@
#include <vtkCellData.h>
#include <vtkDataSet.h>
#include <vtkDataSetTriangleFilter.h>
#include <vtkDoubleArray.h>
#include <vtkImageData.h>
#include <vtkPointData.h>
#include <vtkPointDataToCellData.h>
#include <vtkRTAnalyticSource.h>
......@@ -26,13 +28,10 @@
#include <vtkThreshold.h>
#include <vtkTestUtilities.h>
#define vsp(type, name) \
vtkSmartPointer<vtk##type> name = vtkSmartPointer<vtk##type>::New()
int TestCellDataToPointData (int, char*[])
{
char const name [] = "RTData";
vsp(RTAnalyticSource, wavelet);
vtkNew<vtkRTAnalyticSource> wavelet;
wavelet->SetWholeExtent(-2, 2, -2, 2, -2, 2);
wavelet->SetCenter(0, 0, 0);
wavelet->SetMaximum(255);
......@@ -44,24 +43,67 @@ int TestCellDataToPointData (int, char*[])
wavelet->SetYMag(18);
wavelet->SetZMag(5);
wavelet->SetSubsampleRate(1);
wavelet->Update();
vtkNew<vtkDoubleArray> dist;
dist->SetNumberOfComponents(1);
dist->SetName("Dist");
vtkImageData *original = wavelet->GetOutput();
for (vtkIdType i = 0; i < original->GetNumberOfPoints(); ++i)
{
double p[3];
original->GetPoint(i, p);
dist->InsertNextValue(p[0]*p[0] + p[1]*p[1] + p[2]*p[2]);
}
original->GetPointData()->AddArray(dist);
vsp(PointDataToCellData, p2c);
p2c->SetInputConnection(wavelet->GetOutputPort());
vtkNew<vtkPointDataToCellData> p2c;
p2c->SetInputData(original);
p2c->PassPointDataOff();
vsp(CellDataToPointData, sc2p);
vtkNew<vtkCellDataToPointData> selectiveC2P;
selectiveC2P->SetInputConnection(p2c->GetOutputPort());
selectiveC2P->SetProcessAllArrays(false);
selectiveC2P->AddCellDataArray(name);
selectiveC2P->Update();
vtkNew<vtkCellDataToPointData> sc2p;
sc2p->SetInputConnection(p2c->GetOutputPort());
sc2p->PassCellDataOff();
sc2p->Update();
vsp(DataSetTriangleFilter, c2g);
vtkNew<vtkDataSetTriangleFilter> c2g;
c2g->SetInputConnection(p2c->GetOutputPort());
vsp(CellDataToPointData, uc2p);
vtkNew<vtkCellDataToPointData> uc2p;
uc2p->SetInputConnection(c2g->GetOutputPort());
vtkDataArray* const x = sc2p->GetOutput()->GetPointData()->GetArray(name);
// test if selective CellDataToPointData operates on the correct
int outNumPArrays = selectiveC2P->GetOutput()->GetPointData()->GetNumberOfArrays(); // should be 1
int outNumCArrays = selectiveC2P->GetOutput()->GetCellData()->GetNumberOfArrays(); // should be 0
std::string pArrayName = selectiveC2P->GetOutput()->GetPointData()->GetArrayName(0); // should be RTData
if (outNumPArrays != 1)
{
std::cerr << "Wrong number of PointData arrays." << std::endl;
return EXIT_FAILURE;
}
if (outNumCArrays != 0)
{
std::cerr << "Wrong number of CellData arrays." << std::endl;
return EXIT_FAILURE;
}
if (pArrayName != name)
{
std::cerr << "Array name not matching original name." << std::endl;
return EXIT_FAILURE;
}
// iterate through the options for which cells contribute to the result
// for the cell data to point data filter. since all cells are 3D the
// result should be the same.
......
/*=========================================================================
Program: Visualization Toolkit
Module: TestCellDataToPointData.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include <vtkDataArray.h>
#include <vtkCellData.h>
#include <vtkDataSet.h>
#include <vtkDataSetTriangleFilter.h>
#include <vtkDoubleArray.h>
#include <vtkImageData.h>
#include <vtkPointData.h>
#include <vtkPointDataToCellData.h>
#include <vtkRTAnalyticSource.h>
#include <vtkUnstructuredGrid.h>
#include <vtkThreshold.h>
#include <vtkTestUtilities.h>
int TestPointDataToCellData (int, char*[])
{
char const name [] = "RTData";
vtkNew<vtkRTAnalyticSource> wavelet;
wavelet->SetWholeExtent(-2, 2, -2, 2, -2, 2);
wavelet->SetCenter(0, 0, 0);
wavelet->SetMaximum(255);
wavelet->SetStandardDeviation(.5);
wavelet->SetXFreq(60);
wavelet->SetYFreq(30);
wavelet->SetZFreq(40);
wavelet->SetXMag(10);
wavelet->SetYMag(18);
wavelet->SetZMag(5);
wavelet->SetSubsampleRate(1);
wavelet->Update();
vtkNew<vtkDoubleArray> dist;
dist->SetNumberOfComponents(1);
dist->SetName("Dist");
vtkImageData *original = wavelet->GetOutput();
for (vtkIdType i = 0; i < original->GetNumberOfPoints(); ++i)
{
double p[3];
original->GetPoint(i, p);
dist->InsertNextValue(p[0]*p[0] + p[1]*p[1] + p[2]*p[2]);
}
original->GetPointData()->AddArray(dist);
vtkNew<vtkPointDataToCellData> p2c;
p2c->SetInputData(original);
p2c->SetProcessAllArrays(false);
p2c->AddPointDataArray(name);
p2c->PassPointDataOff();
p2c->Update();
// test if selective CellDataToPointData operates on the correct
int outNumPArrays = p2c->GetOutput()->GetPointData()->GetNumberOfArrays(); // should be 0
int outNumCArrays = p2c->GetOutput()->GetCellData()->GetNumberOfArrays(); // should be 1
std::string cArrayName = p2c->GetOutput()->GetCellData()->GetArrayName(0); // should be RTData
if (outNumPArrays != 0)
{
std::cerr << "Wrong number of PointData arrays." << std::endl;
return EXIT_FAILURE;
}
if (outNumCArrays != 1)
{
std::cerr << "Wrong number of CellData arrays." << std::endl;
return EXIT_FAILURE;
}
if (cArrayName != name)
{
std::cerr << "Array name not matching original name." << std::endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
This diff is collapsed.
......@@ -19,8 +19,10 @@
* vtkCellDataToPointData is a filter that transforms cell data (i.e., data
* specified per cell) into point data (i.e., data specified at cell
* points). The method of transformation is based on averaging the data
* values of all cells using a particular point. Optionally, the input cell
* data can be passed through to the output as well.
* values of all cells using a particular point. For large datasets with
* several cell data arrays, the filter optionally supports selective
* processing to speed up processing. Optionally, the input cell data can
* be passed through to the output as well.
* Unstructured grids and polydata can have cells of different dimensions.
* To handle different use cases in this situation, the user can specify
* which cells contribute to the computation. The options for this are
......@@ -66,9 +68,9 @@ public:
* on, then the input cell data is passed through to the output; otherwise,
* only generated point data is placed into the output.
*/
vtkSetMacro(PassCellData,vtkTypeBool);
vtkGetMacro(PassCellData,vtkTypeBool);
vtkBooleanMacro(PassCellData,vtkTypeBool);
vtkSetMacro(PassCellData,bool);
vtkGetMacro(PassCellData,bool);
vtkBooleanMacro(PassCellData,bool);
//@}
//@{
......@@ -80,9 +82,39 @@ public:
vtkGetMacro(ContributingCellOption, int);
//@}
//@{
/**
* Activate selective processing of arrays. If inactive, only arrays selected
* by the user will be considered by this filter. The default is true.
*/
vtkSetMacro(ProcessAllArrays, bool);
vtkGetMacro(ProcessAllArrays, bool);
vtkBooleanMacro(ProcessAllArrays, bool);
//@}
/**
* Adds an array to be processed. This only has an effect if the
* ProcessAllArrays option is turned off. If a name is already present,
* nothing happens.
*/
virtual void AddCellDataArray(const char *name);
/**
* Removes an array to be processed. This only has an effect if the
* ProcessAllArrays option is turned off. If the specified name is not
* present, nothing happens.
*/
virtual void RemoveCellDataArray(const char *name);
/**
* Removes all arrays to be processed from the list. This only has an effect
* if the ProcessAllArrays option is turned off.
*/
virtual void ClearCellDataArrays();
protected:
vtkCellDataToPointData();
~vtkCellDataToPointData() override {}
~vtkCellDataToPointData() override;
int RequestData(vtkInformation* request,
vtkInformationVector** inputVector,
......@@ -97,13 +129,13 @@ protected:
(vtkInformation*, vtkInformationVector**, vtkInformationVector*);
//@}
void InterpolatePointData(vtkDataSet *input, vtkDataSet *output);
int InterpolatePointData(vtkDataSet *input, vtkDataSet *output);
//@{
/**
* Option to pass cell data arrays through to the output. Default is 0/off.
*/
vtkTypeBool PassCellData;
bool PassCellData;
//@}
//@{
......@@ -114,6 +146,14 @@ protected:
int ContributingCellOption;
//@}
/**
* Option to activate selective processing of arrays.
*/
bool ProcessAllArrays;
class Internals;
Internals *Implementation;
private:
vtkCellDataToPointData(const vtkCellDataToPointData&) = delete;
void operator=(const vtkCellDataToPointData&) = delete;
......
......@@ -17,6 +17,7 @@
#include <algorithm>
#include <cassert>
#include <limits>
#include <set>
#include <vector>
#include "vtkCellData.h"
......@@ -150,6 +151,12 @@ vtkIdType Histogram::IndexOfLargestBin()
}
class vtkPointDataToCellData::Internals
{
public:
std::set<std::string> PointDataArrays;
};
vtkStandardNewMacro(vtkPointDataToCellData);
......@@ -159,6 +166,50 @@ vtkPointDataToCellData::vtkPointDataToCellData()
{
this->PassPointData = 0;
this->CategoricalData = 0;
this->ProcessAllArrays = true;
this->Implementation = new Internals();
}
//----------------------------------------------------------------------------
vtkPointDataToCellData::~vtkPointDataToCellData()
{
delete this->Implementation;
}
//----------------------------------------------------------------------------
void vtkPointDataToCellData::AddPointDataArray(const char *name)
{
if (!name)
{
vtkErrorMacro("name cannot be null.");
return;
}
this->Implementation->PointDataArrays.insert(std::string(name));
this->Modified();
}
//----------------------------------------------------------------------------
void vtkPointDataToCellData::RemovePointDataArray(const char *name)
{
if (!name)
{
vtkErrorMacro("name cannot be null.");
return;
}
this->Implementation->PointDataArrays.erase(name);
this->Modified();
}
//----------------------------------------------------------------------------
void vtkPointDataToCellData::ClearPointDataArrays()
{
if (!this->Implementation->PointDataArrays.empty())
{
this->Modified();
}
this->Implementation->PointDataArrays.clear();
}
//----------------------------------------------------------------------------
......@@ -177,13 +228,34 @@ int vtkPointDataToCellData::RequestData(
vtkIdType cellId, ptId, pointId;
vtkIdType numCells, numPts;
vtkPointData *inPD=input->GetPointData();
vtkPointData *inputInPD = input->GetPointData();
vtkPointData *inPD;
vtkCellData *outCD=output->GetCellData();
int maxCellSize=input->GetMaxCellSize();
vtkIdList *cellPts;
double weight;
double *weights;
if (!this->ProcessAllArrays)
{
inPD = vtkPointData::New();
for (const auto &name : this->Implementation->PointDataArrays)
{
vtkAbstractArray *arr = inputInPD->GetAbstractArray(name.c_str());
if (arr == nullptr)
{
vtkWarningMacro("point data array name not found.");
continue;
}
inPD->AddArray(arr);
}
}
else
{
inPD = inputInPD;
}
vtkDebugMacro(<<"Mapping point data to cell data");
// First, copy the input to the output as a starting point
......@@ -292,6 +364,11 @@ int vtkPointDataToCellData::RequestData(
cellPts->Delete();
delete [] weights;
if (!this->ProcessAllArrays)
{
inPD->Delete();
}
return 1;
}
......
......@@ -19,7 +19,9 @@
* vtkPointDataToCellData is a filter that transforms point data (i.e., data
* specified per point) into cell data (i.e., data specified per cell).
* The method of transformation is based on averaging the data
* values of all points defining a particular cell. Optionally, the input point
* values of all points defining a particular cell. For large datasets with
* several cell data arrays, the filter optionally supports selective
* processing to speed up processing. Optionally, the input point
* data can be passed through to the output as well.
*
* @warning
......@@ -51,9 +53,9 @@ public:
* on, then the input point data is passed through to the output; otherwise,
* only generated point data is placed into the output.
*/
vtkSetMacro(PassPointData,vtkTypeBool);
vtkGetMacro(PassPointData,vtkTypeBool);
vtkBooleanMacro(PassPointData,vtkTypeBool);
vtkSetMacro(PassPointData,bool);
vtkGetMacro(PassPointData,bool);
vtkBooleanMacro(PassPointData,bool);
//@}
//@{
......@@ -62,21 +64,56 @@ public:
* the data is categorical, then the resultant cell data will be determined by
* a "majority rules" vote, with ties going to the smaller value.
*/
vtkSetMacro(CategoricalData,vtkTypeBool);
vtkGetMacro(CategoricalData,vtkTypeBool);
vtkBooleanMacro(CategoricalData,vtkTypeBool);
vtkSetMacro(CategoricalData,bool);
vtkGetMacro(CategoricalData,bool);
vtkBooleanMacro(CategoricalData,bool);
//@}
//@{
/**
* Activate selective processing of arrays. If inactive, only arrays selected
* by the user will be considered by this filter. The default is true.
*/
vtkSetMacro(ProcessAllArrays, bool);
vtkGetMacro(ProcessAllArrays, bool);
vtkBooleanMacro(ProcessAllArrays, bool);
//@}
/**
* Adds an array to be processed. This only has an effect if the
* ProcessAllArrays option is turned off. If a name is already present,
* nothing happens.
*/
virtual void AddPointDataArray(const char *name);
/**
* Removes an array to be processed. This only has an effect if the
* ProcessAllArrays option is turned off. If the specified name is not
* present, nothing happens.
*/
virtual void RemovePointDataArray(const char *name);
/**
* Removes all arrays to be processed from the list. This only has an effect
* if the ProcessAllArrays option is turned off.
*/
virtual void ClearPointDataArrays();
protected:
vtkPointDataToCellData();
~vtkPointDataToCellData() override {}
~vtkPointDataToCellData() override;
int RequestData(vtkInformation* request,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector) override;
vtkTypeBool PassPointData;
vtkTypeBool CategoricalData;
bool PassPointData;
bool CategoricalData;
bool ProcessAllArrays;
class Internals;
Internals *Implementation;
private:
vtkPointDataToCellData(const vtkPointDataToCellData&) = delete;
void operator=(const vtkPointDataToCellData&) = delete;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment