Commit 13c02378 authored by Cory Quammen's avatar Cory Quammen Committed by Kitware Robot

Merge topic '18708-merge-blocks-polydata'

e781ba52 doc: add release note for changes to Append Data and Merge Blocks
a9656475 Append Datasets and Merge Blocks: add tests for output type
633ef5c2 Use vtkAppendDataSets for Append Datasets filter
871cf7da Add vtkPointSet as dataset type requiring output being same as input
10b1c2ef Add vtkDataObjectTreeToPointSet filter
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Acked-by: Utkarsh Ayachit's avatarUtkarsh Ayachit <utkarsh.ayachit@kitware.com>
Merge-request: !2980
parents 3e52b6b5 e781ba52
Pipeline #134734 pending with stage
#### Verify that Append Datasets produces polydata output when inputs are polydata
from paraview.simple import *
from vtkmodules.util import vtkConstants
# create a new 'Sphere'
sphere1 = Sphere()
sphere2 = Sphere()
sphere2.Center = [1.0, 0.0, 0.0]
# create a new 'Append Datasets'
appendDatasets = AppendDatasets(Input=[sphere1, sphere2])
appendDatasets.UpdatePipeline()
# By default the output data type of appendDatasets is vtkUnstructuredGrid
assert(appendDatasets.GetDataInformation().GetDataSetTypeAsString() == 'vtkUnstructuredGrid')
# Ensure that the output data type of appendDatasets is vtkPolyData
appendDatasets.OutputDataSetType = vtkConstants.VTK_POLY_DATA
appendDatasets.UpdatePipeline()
assert(appendDatasets.GetDataInformation().GetDataSetTypeAsString() == 'vtkPolyData')
# Now add in a non-polydata source. It will be skipped in the append
unstructured = UnstructuredCellTypes()
appendDatasets.Input = [sphere1, sphere2, unstructured]
appendDatasets.UpdatePipeline()
# Ensure that the output data type of appendDatasets is still vtkPolyData
assert(appendDatasets.GetDataInformation().GetDataSetTypeAsString() == 'vtkPolyData')
# Ensure output number of cells is the sum of the number of cells in the vtkPolyData input.
# The unstructured grid will be skipped when appending blocks.
sphere1NumCells = sphere1.GetDataInformation().GetNumberOfCells()
sphere2NumCells = sphere2.GetDataInformation().GetNumberOfCells()
outputNumCells = appendDatasets.GetDataInformation().GetNumberOfCells()
assert(sphere1NumCells + sphere2NumCells == outputNumCells)
......@@ -70,8 +70,10 @@ paraview_add_test_python(
paraview_add_test_python(
NO_DATA NO_VALID NO_OUTPUT NO_RT
TestResetProperty.py
AppendDatasetsPolyData.py
MergeBlocksPolyData.py
PointPicking.py
TestResetProperty.py
)
paraview_add_test_python(
......
#### Verify that Merge Blocks produces polydata output when inputs are polydata
from paraview.simple import *
from vtkmodules.util import vtkConstants
# create a new 'Sphere'
sphere1 = Sphere()
sphere2 = Sphere()
sphere2.Center = [1.0, 0.0, 0.0]
# create a new 'Group Datasets'
groupDatasets = GroupDatasets(Input=[sphere1, sphere2])
# create a new 'Merge Blocks'
mergeBlocks = MergeBlocks(Input=groupDatasets)
mergeBlocks.UpdatePipeline()
# By default the output data type of appendDatasets is vtkUnstructuredGrid
assert(mergeBlocks.GetDataInformation().GetDataSetTypeAsString() == 'vtkUnstructuredGrid')
# Ensure that the output data type of mergeBlocks is vtkPolyData
mergeBlocks.OutputDataSetType = vtkConstants.VTK_POLY_DATA
mergeBlocks.UpdatePipeline()
assert(mergeBlocks.GetDataInformation().GetDataSetTypeAsString() == 'vtkPolyData')
# Now add in a non-polydata source
unstructured = UnstructuredCellTypes()
groupDatasets.Input = [sphere1, sphere2, unstructured]
groupDatasets.UpdatePipeline()
mergeBlocks.UpdatePipeline()
# Ensure that the output data type of appendDatasets is still vtkPolyData
assert(mergeBlocks.GetDataInformation().GetDataSetTypeAsString() == 'vtkPolyData')
# Ensure output number of cells is the sum of the number of cells in the vtkPolyData input.
# The unstructured grid will be skipped when merging blocks.
sphere1NumCells = sphere1.GetDataInformation().GetNumberOfCells()
sphere2NumCells = sphere2.GetDataInformation().GetNumberOfCells()
outputNumCells = mergeBlocks.GetDataInformation().GetNumberOfCells()
assert(sphere1NumCells + sphere2NumCells == outputNumCells)
# Append Datasets and Merge Blocks allow selection of output type
The **Append Datasets** and **Merge Blocks** filters each have a new advanced property enabling the selection of the output type. If the output type is specified as a "Polygonal Mesh", then only polygonal meshes from the inputs/input blocks are merged into an output of type "Polygonal Mesh". If the output type is "Unstructured Grid", then all inputs/blocks will be merged into an output of type "Unstructured Grid".
......@@ -1117,20 +1117,17 @@
<!-- End AppendPolyData -->
</SourceProxy>
<!-- ==================================================================== -->
<SourceProxy class="vtkAppendFilter"
<SourceProxy class="vtkAppendDataSets"
label="Append Datasets"
name="Append">
<Documentation long_help="Takes an input of multiple datasets and output has only one unstructured grid."
<Documentation long_help="Takes an input of multiple datasets and output has only one unstructured grid or polydata."
short_help="Append multiple datasets into one.">The Append
Datasets filter operates on multiple data sets of any type
(polygonal, structured, etc.). It merges their geometry
into a single data set. Only the point and cell attributes
that all of the input data sets have in common will appear
in the output. The input data sets must already be
collected together, either as a result of a reader that
loads multiple parts (e.g., EnSight reader) or because the
Group Parts filter has been run to form a collection of
data sets.</Documentation>
(polygonal, structured, etc.). It merges their meshes
into a single dataset. If all inputs are polydata, the output
is a polydata, otherwise it is an unstructured grid.
Only the point and cell attributes that all of the input
datasets have in common will appear in the output.</Documentation>
<InputProperty clean_command="RemoveAllInputs"
command="AddInputConnection"
multiple_input="1"
......@@ -1146,6 +1143,24 @@
<Documentation>This property specifies the datasets to be merged into a
single dataset by the Append Datasets filter.</Documentation>
</InputProperty>
<IntVectorProperty command="SetOutputDataSetType"
default_values="4"
number_of_elements="1"
name="OutputDataSetType"
panel_visibility="advanced">
<EnumerationDomain name="enum">
<Entry text="Polygonal Mesh"
value="0" />
<Entry text="Unstructured Grid"
value="4" />
</EnumerationDomain>
<Documentation>Determines the output type produced by this filter. Only input datasets compatible
with the output type will be merged in the output. For example, if the output type is
"Polygonal Mesh", then inputs of type "Image Data", "StructuredGrid", etc. will not be merged.
On the other hand, if the output type is "Unstructured Grid", then inputs of almost any type
will be merged in the output. Defaults to "Unstructured Grid".
</Documentation>
</IntVectorProperty>
<!-- End AppendDataSet -->
</SourceProxy>
<!-- ==================================================================== -->
......@@ -13163,22 +13178,39 @@ Every Nth Point.
<!-- End of ConvertSelection -->
</SourceProxy>
<!-- ==================================================================== -->
<SourceProxy class="vtkCompositeDataToUnstructuredGridFilter"
<SourceProxy class="vtkDataObjectTreeToPointSetFilter"
label="Merge Blocks"
name="MergeBlocks">
<Documentation short_help="Appends vtkCompositeDataSet leaves into a single vtkUnstructuredGrid">
vtkCompositeDataToUnstructuredGridFilter appends all vtkDataSet leaves of
the input composite dataset to a single unstructured grid. The subtree to
be combined can be chosen using the SubTreeCompositeIndex. If the
SubTreeCompositeIndex is a leaf node, then no appending is
required.</Documentation>
<Documentation short_help="Appends vtkCompositeDataSet leaves into a single vtkUnstructuredGrid or vtkPolyData">
Merge Blocks appends all vtkDataSet leaves of the input composite dataset to a single
unstructured grid (or polydata if all leaves are polydata). The subtree to
be combined can be chosen using the SubTreeCompositeIndex. If the SubTreeCompositeIndex
is a leaf node, then no appending is required nor performed.</Documentation>
<InputProperty command="SetInputConnection"
name="Input">
<DataTypeDomain name="input_type">
<DataType value="vtkCompositeDataSet" />
<DataType value="vtkDataObjectTree" />
</DataTypeDomain>
<Documentation>Set the input composite dataset.</Documentation>
</InputProperty>
<IntVectorProperty command="SetOutputDataSetType"
default_values="4"
number_of_elements="1"
name="OutputDataSetType"
panel_visibility="advanced">
<EnumerationDomain name="enum">
<Entry text="Polygonal Mesh"
value="0" />
<Entry text="Unstructured Grid"
value="4" />
</EnumerationDomain>
<Documentation>Determines the output type produced by this filter. Only blocks compatible
with the output type will be merged in the output. For example, if the output type is
"Polygonal Mesh", then blocks of type "Image Data", "Structured Grid", etc. will not be merged.
If the output type is "UnstructuredGrid", then blocks of any type will be merged in the output.
Defaults to "Unstructured Grid".
</Documentation>
</IntVectorProperty>
<IntVectorProperty command="SetSubTreeCompositeIndex"
default_values="0"
is_internal="1"
......@@ -13200,14 +13232,34 @@ Every Nth Point.
name="MergePoints"
number_of_elements="1">
<BooleanDomain name="bool" />
<Documentation>Merge points within a distance specified by the **Tolerance**
property.</Documentation>
</IntVectorProperty>
<DoubleVectorProperty command="SetTolerance"
default_values="0"
label="Tolerance"
name="Tolerance"
number_of_elements="1"
panel_visibility="advanced">
<Documentation>Set the tolerance for merging points if **Merge Points** is enabled.</Documentation>
<Hints>
<PropertyWidgetDecorator type="GenericDecorator"
mode="visibility"
property="MergePoints"
value="1" />
<!-- show this widget when MergePoints==1 and showing advanced options -->
</Hints>
</DoubleVectorProperty>
<IntVectorProperty command="SetToleranceIsAbsolute"
default_values="0"
label="Tolerance"
name="Tolerance"
name="ToleranceIsAbsolute"
number_of_elements="1"
panel_visibility="advanced">
<Documentation>Set the tolerance for merging points if **Merge Points** is enabled.</Documentation>
<BooleanDomain name="bool" />
<Documentation>This property determines whether to treat the **Tolerance**
property as absolute (points closer than Tolerance are merged) or relative
(points closer than a fraction of the input data's bounding box diagonal length)
when performing point merging.</Documentation>
<Hints>
<PropertyWidgetDecorator type="GenericDecorator"
mode="visibility"
......@@ -13215,7 +13267,7 @@ Every Nth Point.
value="1" />
<!-- show this widget when MergePoints==1 and showing advanced options -->
</Hints>
</DoubleVectorProperty>
</IntVectorProperty>
<!-- End of MergeBlocks -->
</SourceProxy>
<!-- ==================================================================== -->
......
......@@ -103,7 +103,8 @@ int vtkReductionFilter::RequestDataObject(
const char* hOT = helpersInfo->Get(vtkDataObject::DATA_TYPE_NAME());
const char* helpersOutType = hOT;
if ((!strcmp(hOT, "vtkDataSet") || !strcmp(hOT, "vtkDataObject")))
if ((!strcmp(hOT, "vtkPointSet") || !strcmp(hOT, "vtkDataSet") ||
!strcmp(hOT, "vtkDataObject")))
{
// Output type must be same as input.
vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
......
......@@ -39,6 +39,7 @@ set(classes
vtkCleanArrays
vtkCompositeDataToUnstructuredGridFilter
vtkContext2DScalarBarActor
vtkDataObjectTreeToPointSetFilter
vtkImageCompressor
vtkImageTransparencyFilter
vtkKdTreeGenerator
......
/*=========================================================================
Program: ParaView
Module: vtkDataObjectTreeToPointSetFilter.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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 "vtkDataObjectTreeToPointSetFilter.h"
#include "vtkAppendDataSets.h"
#include "vtkAppendFilter.h" // For unstructured grid output
#include "vtkAppendPolyData.h" // For polydata output
#include "vtkCleanArrays.h"
#include "vtkDataObjectTree.h"
#include "vtkDataObjectTreeIterator.h"
#include "vtkDataObjectTypes.h"
#include "vtkDataSet.h"
#include "vtkFieldData.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkPolyData.h"
#include "vtkType.h"
#include "vtkUnstructuredGrid.h"
vtkStandardNewMacro(vtkDataObjectTreeToPointSetFilter);
//----------------------------------------------------------------------------
vtkDataObjectTreeToPointSetFilter::vtkDataObjectTreeToPointSetFilter()
: SubTreeCompositeIndex(0)
, MergePoints(true)
, Tolerance(0.0)
, ToleranceIsAbsolute(false)
, OutputDataSetType(VTK_UNSTRUCTURED_GRID)
{
}
//----------------------------------------------------------------------------
vtkDataObjectTreeToPointSetFilter::~vtkDataObjectTreeToPointSetFilter()
{
}
//----------------------------------------------------------------------------
int vtkDataObjectTreeToPointSetFilter::RequestDataObject(vtkInformation* vtkNotUsed(request),
vtkInformationVector** inputVector, vtkInformationVector* outputVector)
{
vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
if (!inInfo)
{
return 0;
}
if (this->OutputDataSetType != VTK_POLY_DATA && this->OutputDataSetType != VTK_UNSTRUCTURED_GRID)
{
vtkErrorMacro(
"Output type '" << vtkDataObjectTypes::GetClassNameFromTypeId(this->OutputDataSetType)
<< "' is not supported.");
return 0;
}
auto input = vtkDataObjectTree::SafeDownCast(inInfo->Get(vtkDataObject::DATA_OBJECT()));
if (input)
{
vtkInformation* info = outputVector->GetInformationObject(0);
vtkDataObject* output = info->Get(vtkDataObject::DATA_OBJECT());
if (!output || (vtkDataObjectTypes::GetTypeIdFromClassName(output->GetClassName()) !=
this->OutputDataSetType))
{
vtkSmartPointer<vtkDataObject> newOutput;
newOutput.TakeReference(vtkDataObjectTypes::NewDataObject(this->OutputDataSetType));
info->Set(vtkDataObject::DATA_OBJECT(), newOutput);
this->GetOutputPortInformation(0)->Set(
vtkDataObject::DATA_EXTENT_TYPE(), newOutput->GetExtentType());
}
return 1;
}
return 0;
}
//----------------------------------------------------------------------------
int vtkDataObjectTreeToPointSetFilter::RequestData(vtkInformation* vtkNotUsed(request),
vtkInformationVector** inputVector, vtkInformationVector* outputVector)
{
// input
vtkDataSet* ds = vtkDataSet::GetData(inputVector[0], 0);
vtkDataObjectTree* dot = vtkDataObjectTree::GetData(inputVector[0], 0);
// output
vtkDataSet* output = vtkDataSet::GetData(outputVector, 0);
vtkNew<vtkAppendDataSets> appender;
appender->SetOutputDataSetType(this->OutputDataSetType);
appender->SetMergePoints(this->MergePoints ? 1 : 0);
if (this->MergePoints)
{
appender->SetTolerance(this->Tolerance);
appender->SetToleranceIsAbsolute(this->ToleranceIsAbsolute);
}
if (ds)
{
appender->AddInputData(ds);
}
else if (dot)
{
if (this->SubTreeCompositeIndex == 0)
{
this->ExecuteSubTree(dot, appender);
}
vtkDataObjectTreeIterator* iter =
vtkDataObjectTreeIterator::SafeDownCast(dot->NewTreeIterator());
iter->VisitOnlyLeavesOff();
for (iter->InitTraversal();
!iter->IsDoneWithTraversal() && iter->GetCurrentFlatIndex() <= this->SubTreeCompositeIndex;
iter->GoToNextItem())
{
if (iter->GetCurrentFlatIndex() == this->SubTreeCompositeIndex)
{
vtkDataObject* curDO = iter->GetCurrentDataObject();
vtkDataObjectTree* curDOT = vtkDataObjectTree::SafeDownCast(curDO);
vtkDataSet* curDS = vtkUnstructuredGrid::SafeDownCast(curDO);
if (curDS && curDS->GetNumberOfPoints() > 0)
{
appender->AddInputData(curDS);
}
else if (curDOT)
{
this->ExecuteSubTree(curDOT, appender);
}
break;
}
}
iter->Delete();
}
if (appender->GetNumberOfInputConnections(0) > 0)
{
appender->Update();
output->ShallowCopy(appender->GetOutput());
// this will override field data the vtkAppendFilter passed from the first
// block. It seems like a reasonable approach, if global field data is
// present.
output->GetFieldData()->PassData(dot->GetFieldData());
}
this->RemovePartialArrays(output);
return 1;
}
//----------------------------------------------------------------------------
int vtkDataObjectTreeToPointSetFilter::FillInputPortInformation(
int vtkNotUsed(port), vtkInformation* info)
{
info->Remove(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE());
info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataObjectTree");
info->Append(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
return 1;
}
//----------------------------------------------------------------------------
void vtkDataObjectTreeToPointSetFilter::RemovePartialArrays(vtkDataSet* data)
{
vtkNew<vtkCleanArrays> cleaner;
cleaner->SetInputData(data);
cleaner->Update();
data->ShallowCopy(cleaner->GetOutput());
}
//----------------------------------------------------------------------------
void vtkDataObjectTreeToPointSetFilter::ExecuteSubTree(
vtkDataObjectTree* dot, vtkAppendDataSets* appender)
{
vtkDataObjectTreeIterator* iter = dot->NewTreeIterator();
for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem())
{
vtkDataSet* curDS = vtkDataSet::SafeDownCast(iter->GetCurrentDataObject());
if (curDS)
{
appender->AddInputData(curDS);
}
}
iter->Delete();
}
//----------------------------------------------------------------------------
void vtkDataObjectTreeToPointSetFilter::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
os << indent << "SubTreeCompositeIndex: " << this->SubTreeCompositeIndex << "\n";
os << indent << "MergePoints: " << (this->MergePoints ? "On" : "Off") << "\n";
os << indent << "Tolerance: " << this->Tolerance << "\n";
os << indent << "ToleranceIsAbsolute: " << this->ToleranceIsAbsolute << "\n";
os << indent
<< "OutputDataSetType: " << vtkDataObjectTypes::GetClassNameFromTypeId(this->OutputDataSetType)
<< "\n";
}
/*=========================================================================
Program: ParaView
Module: vtkDataObjectTreeToPointSetFilter.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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.
=========================================================================*/
/**
* @class vtkDataObjectTreeToPointSetFilter
* @brief Filter that merges blocks from a data object tree to a vtkPolyData of vtkUnstructuredGrid
*
* This filter takes a vtkDataObjectTree as input and merges the blocks in the tree into a single
* output vtkUnstructuredGrid if the ExtractSurfaces option is off. If the ExtractSurfaces option
* is on, surfaces of non-vtkPolyData datasets in the input tree will be extracted and merged to
* the output with vtkPolyData datasets.
*/
#ifndef vtkDataObjectTreeToPointSetFilter_h
#define vtkDataObjectTreeToPointSetFilter_h
#include "vtkPVVTKExtensionsRenderingModule.h" // For export macro
#include "vtkPointSetAlgorithm.h"
class vtkAppendDataSets;
class vtkDataObjectTree;
class vtkDataSet;
class VTKPVVTKEXTENSIONSRENDERING_EXPORT vtkDataObjectTreeToPointSetFilter
: public vtkPointSetAlgorithm
{
public:
static vtkDataObjectTreeToPointSetFilter* New();
vtkTypeMacro(vtkDataObjectTreeToPointSetFilter, vtkPointSetAlgorithm);
void PrintSelf(ostream& os, vtkIndent indent) override;
//@{
/**
* Get/Set the composite index of the subtree to be merged. By default set to
* 0 i.e. root, hence entire input composite dataset is merged.
*/
vtkSetMacro(SubTreeCompositeIndex, unsigned int);
vtkGetMacro(SubTreeCompositeIndex, unsigned int);
//@}
//@{
/**
* Turn on/off merging of coincidental points. Frontend to
* vtkAppendFilter::MergePoints. Default is on.
*/
vtkSetMacro(MergePoints, bool);
vtkGetMacro(MergePoints, bool);
vtkBooleanMacro(MergePoints, bool);
//@}
//@{
/**
* Get/Set the tolerance to use to find coincident points when `MergePoints`
* is `true`. Default is 0.0.
*
* This is simply passed on to the internal vtkAppendFilter::vtkLocator used to merge points.
* @sa `vtkLocator::SetTolerance`.
*/
vtkSetClampMacro(Tolerance, double, 0.0, VTK_DOUBLE_MAX);
vtkGetMacro(Tolerance, double);
//@}
//@{
/**
* Get/Set whether Tolerance is treated as an absolute or relative tolerance.
* The default is to treat it as an absolute tolerance.
*/
vtkSetMacro(ToleranceIsAbsolute, bool);
vtkGetMacro(ToleranceIsAbsolute, bool);
vtkBooleanMacro(ToleranceIsAbsolute, bool);
//@}
//@{
/**
* Get/Set the output type produced by this filter. Only blocks compatible with the output type
* will be merged in the output. For example, if the output type is vtkPolyData, then
* blocks of type vtkImageData, vtkStructuredGrid, etc. will not be merged - only vtkPolyData
* can be merged into a vtkPolyData. On the other hand, if the output type is
* vtkUnstructuredGrid, then blocks of almost any type will be merged in the output.
* Valid values are VTK_POLY_DATA and VTK_UNSTRUCTURED_GRID defined in vtkType.h.
* Defaults to VTK_UNSTRUCTURED_GRID.
*/
//@}
vtkSetMacro(OutputDataSetType, int);
vtkGetMacro(OutputDataSetType, int);
protected:
vtkDataObjectTreeToPointSetFilter();
~vtkDataObjectTreeToPointSetFilter() override;
int RequestDataObject(vtkInformation* request, vtkInformationVector** inputVector,
vtkInformationVector* outputVector) override;
int RequestData(vtkInformation* request, vtkInformationVector** inputVector,
vtkInformationVector* outputVector) override;
int FillInputPortInformation(int port, vtkInformation* info) override;
/**
* Remove point/cell arrays not present on all processes.
*/
void RemovePartialArrays(vtkDataSet* data);
void ExecuteSubTree(vtkDataObjectTree* dot, vtkAppendDataSets* appender);
unsigned int SubTreeCompositeIndex;
bool MergePoints;
double Tolerance;
bool ToleranceIsAbsolute;
int OutputDataSetType;
private:
vtkDataObjectTreeToPointSetFilter(const vtkDataObjectTreeToPointSetFilter&) = delete;
void operator=(const vtkDataObjectTreeToPointSetFilter&) = delete;
};
#endif
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