Commit 848fccf0 authored by Cory Quammen's avatar Cory Quammen

Change algorithm for computing selections

Previously, the vtkExtractSelection filter iterated over blocks in a
composite dataset and evaluated a vtkSelection block by
block. Unfortunately, this did not make it easy to write selection
operator subclasses that need to operate on an entire composite
dataset, and required some code contortions to enable block selection.

With this change, the selection algorithm is modified to iterate over
each vtkSelectionNode in the vtkSelection and create an insidedness
array associated with the attribute specified by the selection. Only
after each of these arrays is created do we iterate over blocks and
evaluate the selection expression, ultimately extracting the selected
elements.

This is accomplished by changing the query selector API's member
function ComputeSelectedElements() that takes two arguments, an input
vtkDataObject and an output vtkDataObject that will contain an
insidedness array after the function is executed. Two additional
protected pure virtual member functions have been added to the
protected API that separately handle composite data objects
(ComputeSelectedElementsForDataObject()) and non-composite data
objects (ComputeSelectedElementsForBlock()). The
ComputeSelectedElements() function invokes these functions to compute
the insidedness array for composite and non-composite data
sets, respectively. Subclasses are required to implement
ComputeSelectedElementsForBlock(). The default implementation for
ComputeSelectedElementsForDataObject() is to call
ComputeSelectedElementsForBlock().

vtkExtractSelection has been reorganized to implement the new
algorithm. The functionality in the internal evaluator classes has
been moved to the selectors themselves, and the evaluators have been
removed. These changes make it easier to extend the selection types
available. For example, block selection is now supported with a new
vtkBlockSelector object.
parent 96f882fd
set(Module_SRCS
vtkBlockSelector.cxx
vtkConvertSelection.cxx
vtkExtractBlock.cxx
vtkExtractCells.cxx
......
/*=========================================================================
Program: Visualization Toolkit
Module: vtkBlockSelector.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 "vtkBlockSelector.h"
#include "vtkArrayDispatch.h"
#include "vtkAssume.h"
#include "vtkCompositeDataIterator.h"
#include "vtkCompositeDataSet.h"
#include "vtkDataArray.h"
#include "vtkDataArrayAccessor.h"
#include "vtkDataSetAttributes.h"
#include "vtkObjectFactory.h"
#include "vtkSelectionNode.h"
#include "vtkSignedCharArray.h"
#include "vtkUniformGridAMRDataIterator.h"
#include <set>
class vtkBlockSelector::vtkInternals {
public:
// This functor is only needed for vtkArrayDispatch to correctly fill it up.
// Otherwise, it would simply be a set.
class CompositeIdsT : public std::set<unsigned int>
{
public:
template <typename ArrayType>
void operator()(ArrayType* array)
{
VTK_ASSUME(array->GetNumberOfComponents() == 1);
vtkDataArrayAccessor<ArrayType> accessor(array);
for (vtkIdType cc = 0, max = array->GetNumberOfTuples(); cc < max; ++cc)
{
this->insert(static_cast<unsigned int>(accessor.Get(cc, 0)));
}
}
};
// this functor are only needed for vtkArrayDispatch to correctly fill it up.
// otherwise, it'd simply be a set.
class AMRIdsT : public std::set<std::pair<unsigned int, unsigned int> >
{
public:
template <typename ArrayType>
void operator()(ArrayType* array)
{
VTK_ASSUME(array->GetNumberOfComponents() == 2);
vtkDataArrayAccessor<ArrayType> accessor(array);
for (vtkIdType cc = 0, max = array->GetNumberOfTuples(); cc < max; ++cc)
{
this->insert(
std::pair<unsigned int, unsigned int>(static_cast<unsigned int>(accessor.Get(cc, 0)),
static_cast<unsigned int>(accessor.Get(cc, 1))));
}
}
};
CompositeIdsT CompositeIds;
AMRIdsT AMRIds;
};
vtkStandardNewMacro(vtkBlockSelector);
//----------------------------------------------------------------------------
vtkBlockSelector::vtkBlockSelector()
{
this->Internals = new vtkInternals;
}
//----------------------------------------------------------------------------
vtkBlockSelector::~vtkBlockSelector()
{
delete this->Internals;
}
//----------------------------------------------------------------------------
void vtkBlockSelector::Initialize(vtkSelectionNode* node, const char* insidednessArrayName)
{
this->Superclass::Initialize(node, insidednessArrayName);
assert(this->Node->GetContentType() == vtkSelectionNode::BLOCKS);
vtkDataArray* selectionList = vtkDataArray::SafeDownCast(this->Node->GetSelectionList());
if (selectionList->GetNumberOfComponents() == 2)
{
if (!vtkArrayDispatch::DispatchByValueType<vtkArrayDispatch::Integrals>::Execute(
selectionList, this->Internals->AMRIds))
{
vtkGenericWarningMacro("SelectionList of unexpected type!");
}
}
else if (selectionList->GetNumberOfComponents() == 1)
{
if (!vtkArrayDispatch::DispatchByValueType<vtkArrayDispatch::Integrals>::Execute(
selectionList, this->Internals->CompositeIds))
{
vtkGenericWarningMacro("SelectionList of unexpected type!");
}
}
}
//----------------------------------------------------------------------------
bool vtkBlockSelector::ComputeSelectedElementsForBlock(vtkDataObject* vtkNotUsed(input),
vtkSignedCharArray* insidednessArray, unsigned int compositeIndex,
unsigned int amrLevel, unsigned int amrIndex)
{
bool is_selected =
(this->Internals->CompositeIds.find(compositeIndex) != this->Internals->CompositeIds.end()) ||
(this->Internals->AMRIds.find(std::pair<unsigned int, unsigned int>(amrLevel, amrIndex)) != this->Internals->AMRIds.end());
if (this->SkipBlock(compositeIndex, amrLevel, amrIndex) || !is_selected)
{
insidednessArray->FillValue(0);
}
else
{
insidednessArray->FillValue(1);
}
return true;
}
//----------------------------------------------------------------------------
void vtkBlockSelector::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkBlockSelector.h
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.
=========================================================================*/
/**
* @class vtkBlockSelector
* @brief Selects cells or points contained in a block as defined in the
* vtkSelectionNode used to initialize this operator.
*
*/
#ifndef vtkBlockSelector_h
#define vtkBlockSelector_h
#include "vtkSelectionOperator.h"
class VTKFILTERSEXTRACTION_EXPORT vtkBlockSelector : public vtkSelectionOperator
{
public:
static vtkBlockSelector* New();
vtkTypeMacro(vtkBlockSelector, vtkSelectionOperator);
void PrintSelf(ostream& os, vtkIndent indent) override;
void Initialize(vtkSelectionNode* node, const char* insidednessArrayName) override;
protected:
vtkBlockSelector();
~vtkBlockSelector();
bool ComputeSelectedElementsForBlock(vtkDataObject* input,
vtkSignedCharArray* insidednessArray, unsigned int compositeIndex,
unsigned int amrLevel, unsigned int amrIndex) override;
private:
vtkBlockSelector(const vtkBlockSelector&) = delete;
void operator=(const vtkBlockSelector&) = delete;
class vtkInternals;
vtkInternals* Internals;
};
#endif
This diff is collapsed.
......@@ -577,8 +577,10 @@ void vtkFrustumSelector::CreateFrustum(double verts[32])
}
//--------------------------------------------------------------------------
void vtkFrustumSelector::Initialize(vtkSelectionNode* node)
void vtkFrustumSelector::Initialize(vtkSelectionNode* node, const char* insidednessArrayName)
{
this->Superclass::Initialize(node, insidednessArrayName);
// sanity checks
if (node && node->GetContentType() == vtkSelectionNode::FRUSTUM)
{
......@@ -594,13 +596,9 @@ void vtkFrustumSelector::Initialize(vtkSelectionNode* node)
}
//--------------------------------------------------------------------------
void vtkFrustumSelector::Finalize()
{
this->Node = nullptr;
}
//--------------------------------------------------------------------------
bool vtkFrustumSelector::ComputeSelectedElements(vtkDataObject* input, vtkSignedCharArray* elementSelected)
bool vtkFrustumSelector::ComputeSelectedElementsForBlock(vtkDataObject* input,
vtkSignedCharArray* insidednessArray, unsigned int vtkNotUsed(compositeIndex),
unsigned int vtkNotUsed(amrLevel), unsigned int vtkNotUsed(amrIndex))
{
vtkDataSet* inputDS = vtkDataSet::SafeDownCast(input);
// frustum selection only supports datasets
......@@ -613,11 +611,11 @@ bool vtkFrustumSelector::ComputeSelectedElements(vtkDataObject* input, vtkSigned
auto fieldType = this->Node->GetProperties()->Get(vtkSelectionNode::FIELD_TYPE());
if (fieldType == vtkSelectionNode::POINT)
{
this->ComputeSelectedPoints(inputDS, elementSelected);
this->ComputeSelectedPoints(inputDS, insidednessArray);
}
else if (fieldType == vtkSelectionNode::CELL)
{
this->ComputeSelectedCells(inputDS, elementSelected);
this->ComputeSelectedCells(inputDS, insidednessArray);
}
else
{
......
......@@ -40,6 +40,8 @@ public:
vtkTypeMacro(vtkFrustumSelector, vtkSelectionOperator);
void PrintSelf(ostream& os, vtkIndent indent) override;
void Initialize(vtkSelectionNode* node, const char* insidednessArrayName) override;
/**
* Return the MTime taking into account changes to the Frustum
*/
......@@ -53,6 +55,17 @@ public:
vtkPlanes* GetFrustum();
//@}
protected:
vtkFrustumSelector(vtkPlanes *f=nullptr);
~vtkFrustumSelector() override;
vtkSmartPointer<vtkPlanes> Frustum;
vtkSmartPointer<vtkSelectionNode> Node;
bool ComputeSelectedElementsForBlock(vtkDataObject* input,
vtkSignedCharArray* insidednessArray, unsigned int compositeIndex,
unsigned int amrLevel, unsigned int amrIndex) override;
/**
* Given eight vertices, creates a frustum.
* each pt is x,y,z,1
......@@ -64,11 +77,6 @@ public:
*/
void CreateFrustum(double vertices[32]);
void Initialize(vtkSelectionNode* node) override;
void Finalize() override;
bool ComputeSelectedElements(vtkDataObject* input, vtkSignedCharArray* elementInside) override;
/**
* Computes which points in the dataset are inside the frustum and populates the pointsInside
* array with 1 for inside and 0 for outside.
......@@ -82,13 +90,6 @@ public:
int OverallBoundsTest(double bounds[6]);
protected:
vtkFrustumSelector(vtkPlanes *f=nullptr);
~vtkFrustumSelector() override;
vtkSmartPointer<vtkPlanes> Frustum;
vtkSmartPointer<vtkSelectionNode> Node;
private:
vtkFrustumSelector(const vtkFrustumSelector&) = delete;
void operator=(const vtkFrustumSelector&) = delete;
......
......@@ -32,7 +32,7 @@ class vtkLocationSelector::vtkInternals
{
public:
virtual ~vtkInternals() {}
virtual bool Execute(vtkDataSet* dataset, vtkSignedCharArray* insidenessArray) = 0;
virtual bool Execute(vtkDataSet* dataset, vtkSignedCharArray* insidednessArray) = 0;
};
/// When selecting points near the chosen locations, we use the following
......@@ -57,7 +57,7 @@ public:
this->PointLocator->Update();
}
bool Execute(vtkDataSet* dataset, vtkSignedCharArray* insidenessArray) override
bool Execute(vtkDataSet* dataset, vtkSignedCharArray* insidednessArray) override
{
const vtkIdType numpts = dataset->GetNumberOfPoints();
if (numpts <= 0)
......@@ -73,10 +73,10 @@ public:
double coords[3], d2;
dataset->GetPoint(cc, coords);
auto pid = locator->FindClosestPointWithinRadius(radius, coords, d2);
insidenessArray->SetValue(cc, pid >= 0 ? 1 : 0);
insidednessArray->SetValue(cc, pid >= 0 ? 1 : 0);
}
});
insidenessArray->Modified();
insidednessArray->Modified();
return true;
}
};
......@@ -91,15 +91,15 @@ public:
{
}
bool Execute(vtkDataSet* dataset, vtkSignedCharArray* insidenessArray) override
bool Execute(vtkDataSet* dataset, vtkSignedCharArray* insidednessArray) override
{
vtkNew<vtkStaticCellLocator> cellLocator;
cellLocator->SetDataSet(dataset);
cellLocator->Update();
const auto numLocations = this->SelectionList->GetNumberOfTuples();
const auto numCells = insidenessArray->GetNumberOfTuples();
std::fill_n(insidenessArray->GetPointer(0), numCells, static_cast<char>(0));
const auto numCells = insidednessArray->GetNumberOfTuples();
std::fill_n(insidednessArray->GetPointer(0), numCells, static_cast<char>(0));
for (vtkIdType cc = 0; cc < numLocations; ++cc)
{
double coords[3];
......@@ -107,10 +107,10 @@ public:
auto cid = cellLocator->FindCell(coords);
if (cid >= 0 && cid < numCells)
{
insidenessArray->SetValue(cid, 1);
insidednessArray->SetValue(cid, 1);
}
}
insidenessArray->Modified();
insidednessArray->Modified();
return true;
}
};
......@@ -128,8 +128,10 @@ vtkLocationSelector::~vtkLocationSelector()
}
//----------------------------------------------------------------------------
void vtkLocationSelector::Initialize(vtkSelectionNode* node)
void vtkLocationSelector::Initialize(vtkSelectionNode* node, const char* insidednessArrayName)
{
this->Superclass::Initialize(node, insidednessArrayName);
this->Internals.reset();
auto selectionList = vtkDataArray::SafeDownCast(node->GetSelectionList());
......@@ -182,12 +184,13 @@ void vtkLocationSelector::Finalize()
}
//----------------------------------------------------------------------------
bool vtkLocationSelector::ComputeSelectedElements(
vtkDataObject* input, vtkSignedCharArray* elementInside)
bool vtkLocationSelector::ComputeSelectedElementsForBlock(vtkDataObject* input,
vtkSignedCharArray* insidednessArray, unsigned int vtkNotUsed(compositeIndex),
unsigned int vtkNotUsed(amrLevel), unsigned int vtkNotUsed(amrIndex))
{
assert(input != nullptr && elementInside != nullptr);
assert(input != nullptr && insidednessArray != nullptr);
vtkDataSet* ds = vtkDataSet::SafeDownCast(input);
return (this->Internals != nullptr && ds != nullptr) ? this->Internals->Execute(ds, elementInside)
return (this->Internals != nullptr && ds != nullptr) ? this->Internals->Execute(ds, insidednessArray)
: false;
}
......
......@@ -34,14 +34,17 @@ public:
vtkTypeMacro(vtkLocationSelector, vtkSelectionOperator);
void PrintSelf(ostream& os, vtkIndent indent) override;
void Initialize(vtkSelectionNode* node) override;
void Initialize(vtkSelectionNode* node, const char* insidednessArrayName) override;
void Finalize() override;
bool ComputeSelectedElements(vtkDataObject* input, vtkSignedCharArray* elementInside) override;
protected:
vtkLocationSelector();
~vtkLocationSelector() override;
bool ComputeSelectedElementsForBlock(vtkDataObject* input,
vtkSignedCharArray* insidednessArray, unsigned int compositeIndex,
unsigned int amrLevel, unsigned int amrIndex) override;
private:
vtkLocationSelector(const vtkLocationSelector&) = delete;
void operator=(const vtkLocationSelector&) = delete;
......
......@@ -15,13 +15,203 @@
#include "vtkSelectionOperator.h"
#include "vtkCompositeDataIterator.h"
#include "vtkCompositeDataSet.h"
#include "vtkDataSet.h"
#include "vtkDataSetAttributes.h"
#include "vtkInformation.h"
#include "vtkSelectionNode.h"
#include "vtkSignedCharArray.h"
#include "vtkUniformGridAMRDataIterator.h"
//----------------------------------------------------------------------------
vtkSelectionOperator::vtkSelectionOperator()
{
}
//----------------------------------------------------------------------------
vtkSelectionOperator::~vtkSelectionOperator() = default;
vtkSelectionOperator::~vtkSelectionOperator()
{
this->Node = nullptr;
delete[] this->InsidednessArrayName;
}
//----------------------------------------------------------------------------
void vtkSelectionOperator::Initialize(vtkSelectionNode* node, const char* insidednessArrayName)
{
this->Node = node;
if (insidednessArrayName)
{
delete[] this->InsidednessArrayName;
size_t n = strlen(insidednessArrayName);
this->InsidednessArrayName = new char[n+1]; // +1 for '\0'
memcpy(this->InsidednessArrayName, insidednessArrayName, sizeof(char) * (n+1));
}
else
{
this->InsidednessArrayName = nullptr;
}
}
//--------------------------------------------------------------------------
bool vtkSelectionOperator::ComputeSelectedElements(vtkDataObject* input, vtkDataObject* output)
{
if (auto inputCD = vtkCompositeDataSet::SafeDownCast(input))
{
auto outputCD = vtkCompositeDataSet::SafeDownCast(output);
return this->ComputeSelectedElementsForCompositeDataSet(inputCD, outputCD);
}
else
{
int association =
vtkSelectionNode::ConvertSelectionFieldToAttributeType(
this->Node->GetFieldType());
vtkIdType numElements = input->GetNumberOfElements(association);
auto insidednessArray = this->CreateInsidednessArray(numElements);
insidednessArray->SetName(this->InsidednessArrayName);
bool computed = this->ComputeSelectedElementsForDataObject(input, insidednessArray);
// If selecting cells containing points, we need to map the selected points
// to selected cells.
auto selectionProperties = this->Node->GetProperties();
if (association == vtkDataObject::POINT &&
selectionProperties->Has(vtkSelectionNode::CONTAINING_CELLS()) &&
selectionProperties->Get(vtkSelectionNode::CONTAINING_CELLS()) == 1)
{
// insidednessArray going in is associated with points. Returned, it is
// associated with cells.
insidednessArray = this->ComputeCellsContainingSelectedPoints(input, insidednessArray);
insidednessArray->SetName(this->InsidednessArrayName);
association = vtkDataObject::CELL;
}
output->GetAttributes(association)->AddArray(insidednessArray);
return computed;
}
}
//----------------------------------------------------------------------------
bool vtkSelectionOperator::ComputeSelectedElementsForCompositeDataSet(
vtkCompositeDataSet* inputCD, vtkCompositeDataSet* outputCD)
{
assert(inputCD != nullptr);
assert(outputCD != nullptr);
vtkSmartPointer<vtkCompositeDataIterator> inIter;
inIter.TakeReference(inputCD->NewIterator());
auto inIterAMR = vtkUniformGridAMRDataIterator::SafeDownCast(inIter);
for (inIter->InitTraversal(); !inIter->IsDoneWithTraversal(); inIter->GoToNextItem())
{
vtkDataObject* inputBlock = inIter->GetCurrentDataObject();
vtkDataObject* outputBlock = outputCD->GetDataSet(inIter);
assert(inputBlock != nullptr);
assert(outputBlock != nullptr);
int association =
vtkSelectionNode::ConvertSelectionFieldToAttributeType(
this->Node->GetFieldType());
vtkIdType numElements = inputBlock->GetNumberOfElements(association);
auto insidednessArray = this->CreateInsidednessArray(numElements);
insidednessArray->SetName(this->InsidednessArrayName);
unsigned int compositeIndex = inIter->GetCurrentFlatIndex();
unsigned int amrLevel = inIterAMR ? inIterAMR->GetCurrentLevel() : VTK_UNSIGNED_INT_MAX;
unsigned int amrIndex = inIterAMR ? inIterAMR->GetCurrentIndex() : VTK_UNSIGNED_INT_MAX;
if (this->SkipBlock(compositeIndex, amrLevel, amrIndex))
{
insidednessArray->Fill(0);
}
else
{
this->ComputeSelectedElementsForBlock(inputBlock, insidednessArray, compositeIndex,
amrLevel, amrIndex);
// If selecting cells containing points, we need to map the selected points
// to selected cells.
auto selectionProperties = this->Node->GetProperties();
if (association == vtkDataObject::POINT &&
selectionProperties->Has(vtkSelectionNode::CONTAINING_CELLS()) &&
selectionProperties->Get(vtkSelectionNode::CONTAINING_CELLS()) == 1)
{
// insidednessArray going in is associated with points. Returned, it is
// associated with cells.
insidednessArray = this->ComputeCellsContainingSelectedPoints(inputBlock, insidednessArray);
insidednessArray->SetName(this->InsidednessArrayName);
association = vtkDataObject::CELL;
}
}
outputBlock->GetAttributes(association)->AddArray(insidednessArray);
}
return true;
}
//----------------------------------------------------------------------------
bool vtkSelectionOperator::SkipBlock(unsigned int compositeIndex, unsigned int amrLevel, unsigned int amrIndex)
{
auto properties = this->Node->GetProperties();
if (properties->Has(vtkSelectionNode::COMPOSITE_INDEX()) &&
static_cast<unsigned int>(properties->Get(vtkSelectionNode::COMPOSITE_INDEX())) != compositeIndex)
{
return true;
}
if (properties->Has(vtkSelectionNode::HIERARCHICAL_LEVEL()) &&
static_cast<unsigned int>(properties->Get(vtkSelectionNode::HIERARCHICAL_LEVEL())) != amrLevel)
{
return true;
}
if (properties->Has(vtkSelectionNode::HIERARCHICAL_INDEX()) &&
static_cast<unsigned int>(properties->Get(vtkSelectionNode::HIERARCHICAL_INDEX())) != amrIndex)
{
return true;
}
return false;
}
//----------------------------------------------------------------------------
// Creates a new insidedness array with the given number of elements.
vtkSmartPointer<vtkSignedCharArray> vtkSelectionOperator::CreateInsidednessArray(vtkIdType numElems)
{
auto darray = vtkSmartPointer<vtkSignedCharArray>::New();
darray->SetName("vtkInsidedness");
darray->SetNumberOfComponents(1);
darray->SetNumberOfTuples(numElems);
return darray;
}
//----------------------------------------------------------------------------
vtkSmartPointer<vtkSignedCharArray> vtkSelectionOperator::ComputeCellsContainingSelectedPoints(
vtkDataObject* data, vtkSignedCharArray* selectedPoints)
{
vtkDataSet* dataset = vtkDataSet::SafeDownCast(data);
if (!dataset)
{
return nullptr;
}
const vtkIdType numCells = dataset->GetNumberOfCells();
auto selectedCells = this->CreateInsidednessArray(numCells);
vtkNew<vtkIdList> cellPts;
// run through cells and accept those with any point inside
for (vtkIdType cellId = 0; cellId < numCells; ++cellId)
{
dataset->GetCellPoints(cellId, cellPts);
vtkIdType numCellPts = cellPts->GetNumberOfIds();
signed char selectedPointFound = 0;
for (vtkIdType i = 0; i < numCellPts; ++i)
{
vtkIdType ptId = cellPts->GetId(i);
if (selectedPoints->GetValue(ptId) != 0)
{
selectedPointFound = 1;
break;
}
}
selectedCells->SetValue(cellId, selectedPointFound);
}
return selectedCells;
}
//----------------------------------------------------------------------------
void vtkSelectionOperator::PrintSelf(ostream& os, vtkIndent indent)
......
......@@ -24,7 +24,9 @@
#include "vtkFiltersExtractionModule.h" // For export macro
#include "vtkObject.h"
#include "vtkSmartPointer.h" // For vtkSmartPointer
class vtkCompositeDataSet;
class vtkDataObject;
class vtkSelectionNode;
class vtkSignedCharArray;
......@@ -37,18 +39,52 @@ class VTKFILTERSEXTRACTION_EXPORT vtkSelectionOperator : public vtkObject
void PrintSelf(ostream& os, vtkIndent indent) override;
/**
* Sets the vtkSelectionNode used by this selection operator an initializes
* the datastructures in the selection operator based on the selection.
* Sets the vtkSelectionNode used by this selection operator and initializes
* the data structures in the selection operator based on the selection.
*
* (for example in the vtkFrustumSelector this creates the vtkPlanes
* implicit function to represent the frustum)
* implicit function to represent the frustum).
*
* @param node The selection node that determines the behavior of this operator.
* @param insidednessArrayName The name of the insidedness array to add to the output
* from this operator.
*/
virtual void Initialize(vtkSelectionNode* node) = 0;
virtual void Initialize(vtkSelectionNode* node, const char* insidednessArrayName);
/**
* Does any cleanup of objects created in Initialize
*/
virtual void Finalize() {}
//@{
/**
* Set/get the name to give the insidedness array.
*/
vtkGetStringMacro(InsidednessArrayName);
vtkSetStringMacro(InsidednessArrayName);
//@}
/**
* Given an input and the vtkSelectionNode passed into the Initialize() method, add to the
* output a vtkSignedChar attribute array indicating whether each element is inside (1)
* or outside (0) the selection. The attribute (point data or cell data) is determined
* by the vtkSelection that owns the vtkSelectionNode set in Initialize(). The insidedness
* array is named with the value of InsidednessArrayName. If input is a vtkCompositeDataSet,
* the insidedness array is added to each block.
*/
virtual bool ComputeSelectedElements(vtkDataObject* input, vtkDataObject* output);
protected:
vtkSelectionOperator();
virtual ~vtkSelectionOperator() override;
// Contains the selection criteria.
vtkSelectionNode* Node = nullptr;
// Name of the insidedness array added to the output when the selection criteria is
// evaluated by this operator.
char * InsidednessArrayName = nullptr;
/**
* This method computes whether or not each element in the dataset is inside the selection
* and populates the given array with 0 (outside the selection) or 1 (inside the selection).
......@@ -56,17 +92,60 @@ class VTKFILTERSEXTRACTION_EXPORT vtkSelectionOperator : public vtkObject
* The vtkDataObject passed in should be a non-composite data object.
*
* What type of elements are operated over is determined by the vtkSelectionNode's
* field association. The array passed in should have the correct number of elements
* field association. The insidednessArray passed in should have the correct number of elements
* for that field type or it will be resized.
*
* Returns true for successful completion. The operator should only return false
* Returns true for successful completion. The operator should only return false
* when it cannot operate on the inputs.
*/
virtual bool ComputeSelectedElements(vtkDataObject* input, vtkSignedCharArray* elementInside) = 0;
virtual bool ComputeSelectedElementsForDataObject(vtkDataObject* input,
vtkSignedCharArray* insidednessArray)
{
return this->ComputeSelectedElementsForBlock(input, insidednessArray,
VTK_UNSIGNED_INT_MAX, VTK_UNSIGNED_INT_MAX, VTK_UNSIGNED_INT_MAX);
}
/** A version of ComputeSelectedElementsForDataObject() that takes
* additional parameters giving the data object's composite index, AMR
* level or AMR index.
*/