A patch update will be applied today - June 21st between 1pm - 1:45pm EDT (UTC-0400). GitLab will go down a few minutes within that time.

Commit 6b16e1f1 authored by Utkarsh Ayachit's avatar Utkarsh Ayachit
Browse files

ENH: Fixed BUG #4133. Added support to select blocks of a multiblock dataset.

Use the shortcut "B" to enter the block-selection mode and then draw the rubber
band or simply click to select the block at the cursor.

Added a new ContentType (BLOCKS) to vtkSelection. In this mode, the
vtkSelectionList is a vtkUnsignedIntArray with the composite index for the
selected blocks.
parent a79822f4
......@@ -31,7 +31,7 @@
#include <vtkstd/map>
#include <vtkstd/vector>
vtkCxxRevisionMacro(vtkSelection, "1.24");
vtkCxxRevisionMacro(vtkSelection, "1.25");
vtkStandardNewMacro(vtkSelection);
vtkInformationKeyMacro(vtkSelection,CONTENT_TYPE,Integer);
......@@ -428,6 +428,7 @@ void vtkSelection::UnionSelectionList(vtkSelection* other)
case INDICES:
case LOCATIONS:
case THRESHOLDS:
case BLOCKS:
{
vtkFieldData* fd1 = this->GetFieldData();
vtkFieldData* fd2 = other->GetFieldData();
......
......@@ -187,7 +187,8 @@ public:
INDICES,
FRUSTUM,
LOCATIONS,
THRESHOLDS
THRESHOLDS,
BLOCKS // used to select blocks within a composite dataset.
};
//ETX
......
......@@ -79,6 +79,7 @@ vtkExtractLevel.cxx
vtkExtractPolyDataGeometry.cxx
vtkExtractRectilinearGrid.cxx
vtkExtractSelectionBase.cxx
vtkExtractSelectedBlock.cxx
vtkExtractSelectedFrustum.cxx
vtkExtractSelectedIds.cxx
vtkExtractSelectedLocations.cxx
......
......@@ -39,6 +39,7 @@
#include "vtkSmartPointer.h"
#include "vtkStringArray.h"
#include "vtkTable.h"
#include "vtkUnsignedIntArray.h"
#include "vtkVariantArray.h"
#include <vtkstd/algorithm>
......@@ -50,7 +51,7 @@
vtkCxxSetObjectMacro(vtkConvertSelection, ArrayNames, vtkStringArray);
vtkCxxRevisionMacro(vtkConvertSelection, "1.12");
vtkCxxRevisionMacro(vtkConvertSelection, "1.13");
vtkStandardNewMacro(vtkConvertSelection);
//----------------------------------------------------------------------------
vtkConvertSelection::vtkConvertSelection()
......@@ -216,12 +217,83 @@ void vtkConvertSelectionLookup(
}
}
//----------------------------------------------------------------------------
int vtkConvertSelection::ConvertToBlockSelection(
vtkSelection* input, vtkCompositeDataSet* data, vtkSelection* output)
{
output->SetContentType(vtkSelection::BLOCKS);
vtkstd::vector<vtkSelection*> inputSelections;
// If input selection is a composite selection consisting of other selections,
// then iterate over each of the constituent selection instances.
if (input->GetContentType() == vtkSelection::SELECTIONS)
{
for (unsigned int i = 0; i < input->GetNumberOfChildren(); ++i)
{
vtkSelection* inputChild = input->GetChild(i);
if (inputChild && inputChild->GetContentType() != vtkSelection::SELECTIONS)
{
inputSelections.push_back(inputChild);
}
}
}
else
{
inputSelections.push_back(input);
}
vtkstd::set<unsigned int> indices;
vtkstd::vector<vtkSelection*>::iterator iter;
for (iter = inputSelections.begin(); iter != inputSelections.end(); ++iter)
{
vtkSmartPointer<vtkSelection> curSel = (*iter);
if (curSel->GetContentType() == vtkSelection::GLOBALIDS)
{
// global id selection does not have COMPOSITE_INDEX() key, so we convert
// it to an index base selection, so that we can determine the composite
// indices.
vtkSelection* newSel = vtkConvertSelection::ToIndexSelection(curSel, data);
curSel.TakeReference(newSel);
}
vtkInformation* properties = curSel->GetProperties();
if (properties->Has(vtkSelection::CONTENT_TYPE()) &&
properties->Has(vtkSelection::COMPOSITE_INDEX()))
{
indices.insert(static_cast<unsigned int>(
properties->Get(vtkSelection::COMPOSITE_INDEX())));
}
// TODO: is has HIERARCHICAL_INDEX() & HIERARCHICAL_LEVEL.
}
VTK_CREATE(vtkUnsignedIntArray, selectionList);
selectionList->SetNumberOfTuples(indices.size());
vtkstd::set<unsigned int>::iterator siter;
vtkIdType index=0;
for (siter = indices.begin(); siter != indices.end(); ++siter, ++index)
{
selectionList->SetValue(index, *siter);
}
output->SetSelectionList(selectionList);
return 1;
}
//----------------------------------------------------------------------------
int vtkConvertSelection::ConvertCompositeDataSet(
vtkSelection* input,
vtkCompositeDataSet* data,
vtkSelection* output)
{
// If this->OutputType == vtkSelection::BLOCKS we just want to create a new
// selection with the chosen block indices.
if (this->OutputType == vtkSelection::BLOCKS)
{
return this->ConvertToBlockSelection(input, data, output);
}
// If input selection is a composite selection consisting of other selections,
// then iterate over each of the constituent selection instances.
if (input->GetContentType() == vtkSelection::SELECTIONS)
......@@ -800,6 +872,7 @@ int vtkConvertSelection::FillInputPortInformation(
{
// Can convert from a vtkDataSet, vtkGraph, or vtkTable
info->Remove(vtkConvertSelection::INPUT_REQUIRED_DATA_TYPE());
info->Append(vtkConvertSelection::INPUT_REQUIRED_DATA_TYPE(), "vtkCompositeDataSet");
info->Append(vtkConvertSelection::INPUT_REQUIRED_DATA_TYPE(), "vtkDataSet");
info->Append(vtkConvertSelection::INPUT_REQUIRED_DATA_TYPE(), "vtkGraph");
info->Append(vtkConvertSelection::INPUT_REQUIRED_DATA_TYPE(), "vtkTable");
......
......@@ -121,6 +121,9 @@ protected:
vtkTable* dataTable,
vtkIdTypeArray* indices);
int ConvertToBlockSelection(
vtkSelection* input, vtkCompositeDataSet* data, vtkSelection* output);
virtual int FillInputPortInformation(
int port, vtkInformation* info);
......
/*=========================================================================
Program: Visualization Toolkit
Module: vtkExtractSelectedBlock.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 "vtkExtractSelectedBlock.h"
#include "vtkCompositeDataIterator.h"
#include "vtkUnsignedIntArray.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkObjectFactory.h"
#include "vtkSelection.h"
#include <vtkstd/set>
vtkStandardNewMacro(vtkExtractSelectedBlock);
vtkCxxRevisionMacro(vtkExtractSelectedBlock, "1.1");
//----------------------------------------------------------------------------
vtkExtractSelectedBlock::vtkExtractSelectedBlock()
{
}
//----------------------------------------------------------------------------
vtkExtractSelectedBlock::~vtkExtractSelectedBlock()
{
}
//----------------------------------------------------------------------------
int vtkExtractSelectedBlock::FillInputPortInformation(
int port, vtkInformation* info)
{
this->Superclass::FillInputPortInformation(port, info);
// now add our info
if (port == 0)
{
// Can work with composite datasets.
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataObject");
}
return 1;
}
//----------------------------------------------------------------------------
// Needed because parent class sets output type to input type
// and we sometimes want to change it to make an UnstructuredGrid regardless of
// input type
int vtkExtractSelectedBlock::RequestDataObject(
vtkInformation* req,
vtkInformationVector** inputVector ,
vtkInformationVector* outputVector)
{
vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
if (!inInfo)
{
return 0;
}
vtkCompositeDataSet *input = vtkCompositeDataSet::GetData(inInfo);
vtkInformation* outInfo = outputVector->GetInformationObject(0);
if (input)
{
vtkMultiBlockDataSet* output = vtkMultiBlockDataSet::GetData(outInfo);
if (!output)
{
output = vtkMultiBlockDataSet::New();
output->SetPipelineInformation(outInfo);
output->Delete();
this->GetOutputPortInformation(0)->Set(
vtkDataObject::DATA_EXTENT_TYPE(), output->GetExtentType());
}
return 1;
}
return this->Superclass::RequestDataObject(req, inputVector, outputVector);
}
//----------------------------------------------------------------------------
int vtkExtractSelectedBlock::RequestData(
vtkInformation *vtkNotUsed(request),
vtkInformationVector **inputVector,
vtkInformationVector *outputVector)
{
// get the info objects
vtkInformation *selInfo = inputVector[1]->GetInformationObject(0);
vtkInformation *inInfo = inputVector[0]->GetInformationObject(0);
vtkInformation *outInfo = outputVector->GetInformationObject(0);
vtkCompositeDataSet* cd = vtkCompositeDataSet::GetData(inInfo);
if (!cd)
{
vtkDataObject* outputDO = vtkDataObject::GetData(outInfo);
outputDO->ShallowCopy(vtkDataObject::GetData(inInfo));
return 1;
}
if (!selInfo)
{
//When not given a selection, quietly select nothing.
return 1;
}
vtkSelection* sel = vtkSelection::GetData(selInfo);
vtkMultiBlockDataSet* output = vtkMultiBlockDataSet::GetData(outInfo);
if (sel->GetContentType() != vtkSelection::BLOCKS)
{
vtkErrorMacro("Missing or incompatible CONTENT_TYPE.");
return 0;
}
output->CopyStructure(cd);
vtkUnsignedIntArray* selectionList = vtkUnsignedIntArray::SafeDownCast(
sel->GetSelectionList());
if (selectionList)
{
vtkstd::set<unsigned int> blocks;
vtkIdType numValues = selectionList->GetNumberOfTuples();
for (vtkIdType cc=0; cc < numValues; cc++)
{
blocks.insert(selectionList->GetValue(cc));
}
if (numValues > 0)
{
vtkCompositeDataIterator* citer = cd->NewIterator();
for (citer->InitTraversal(); !citer->IsDoneWithTraversal(); citer->GoToNextItem())
{
if (blocks.find(citer->GetCurrentFlatIndex()) != blocks.end())
{
output->SetDataSet(citer, citer->GetCurrentDataObject());
}
}
citer->Delete();
}
}
return 1;
}
//----------------------------------------------------------------------------
void vtkExtractSelectedBlock::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkExtractSelectedBlock.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.
=========================================================================*/
// .NAME vtkExtractSelectedBlock
// .SECTION Description
#ifndef __vtkExtractSelectedBlock_h
#define __vtkExtractSelectedBlock_h
#include "vtkExtractSelectionBase.h"
class VTK_GRAPHICS_EXPORT vtkExtractSelectedBlock : public vtkExtractSelectionBase
{
public:
static vtkExtractSelectedBlock* New();
vtkTypeRevisionMacro(vtkExtractSelectedBlock, vtkExtractSelectionBase);
void PrintSelf(ostream& os, vtkIndent indent);
//BTX
protected:
vtkExtractSelectedBlock();
~vtkExtractSelectedBlock();
// Generate the output.
virtual int RequestData(vtkInformation *,
vtkInformationVector **, vtkInformationVector *);
// Description:
// Sets up empty output dataset
virtual int RequestDataObject(vtkInformation* request,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector);
virtual int FillInputPortInformation(int port, vtkInformation* info);
private:
vtkExtractSelectedBlock(const vtkExtractSelectedBlock&); // Not implemented.
void operator=(const vtkExtractSelectedBlock&); // Not implemented.
//ETX
};
#endif
......@@ -15,6 +15,7 @@
#include "vtkExtractSelection.h"
#include "vtkDataSet.h"
#include "vtkExtractSelectedBlock.h"
#include "vtkExtractSelectedFrustum.h"
#include "vtkExtractSelectedIds.h"
#include "vtkExtractSelectedLocations.h"
......@@ -28,12 +29,13 @@
#include "vtkSelection.h"
#include "vtkStreamingDemandDrivenPipeline.h"
vtkCxxRevisionMacro(vtkExtractSelection, "1.22");
vtkCxxRevisionMacro(vtkExtractSelection, "1.23");
vtkStandardNewMacro(vtkExtractSelection);
//----------------------------------------------------------------------------
vtkExtractSelection::vtkExtractSelection()
{
this->BlockFilter = vtkExtractSelectedBlock::New();
this->IdsFilter = vtkExtractSelectedIds::New();
this->FrustumFilter = vtkExtractSelectedFrustum::New();
this->LocationsFilter = vtkExtractSelectedLocations::New();
......@@ -46,6 +48,7 @@ vtkExtractSelection::vtkExtractSelection()
//----------------------------------------------------------------------------
vtkExtractSelection::~vtkExtractSelection()
{
this->BlockFilter->Delete();
this->IdsFilter->Delete();
this->FrustumFilter->Delete();
this->LocationsFilter->Delete();
......@@ -60,7 +63,7 @@ int vtkExtractSelection::FillInputPortInformation(
if (port==0)
{
// Can work with composite datasets.
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataObject");
info->Set(vtkAlgorithm::INPUT_REQUIRED_DATA_TYPE(), "vtkDataObject");
}
else
{
......@@ -103,20 +106,23 @@ int vtkExtractSelection::RequestData(
vtkErrorMacro("Selection missing CONTENT_TYPE.");
return 0;
}
vtkDataObject *output = vtkDataObject::SafeDownCast(
outInfo->Get(vtkDataObject::DATA_OBJECT()));
if (input->IsA("vtkCompositeDataSet"))
int selType = sel->GetContentType();
// if selType == vtkSelection::BLOCKS, we don;t need to iterate over nodes in
// the composite dataset, the extract block filter can handle composite datasets.
if (input->IsA("vtkCompositeDataSet") && selType != vtkSelection::BLOCKS)
{
vtkCompositeDataSet* cdInput = vtkCompositeDataSet::SafeDownCast(input);
vtkCompositeDataSet* cdOutput = vtkCompositeDataSet::SafeDownCast(output);
cdOutput->CopyStructure(cdInput);
vtkCompositeDataIterator* iter = cdInput->NewIterator();
vtkHierarchicalBoxDataIterator* hbIter =
vtkHierarchicalBoxDataIterator* hbIter =
vtkHierarchicalBoxDataIterator::SafeDownCast(iter);
for (iter->InitTraversal(); !iter->IsDoneWithTraversal();
for (iter->InitTraversal(); !iter->IsDoneWithTraversal();
iter->GoToNextItem())
{
vtkDataObject* subOutput = 0;
......@@ -126,7 +132,7 @@ int vtkExtractSelection::RequestData(
iter->GetCurrentFlatIndex(),
hbIter->GetCurrentLevel(),
hbIter->GetCurrentIndex(),
vtkDataSet::SafeDownCast(iter->GetCurrentDataObject()),
vtkDataSet::SafeDownCast(iter->GetCurrentDataObject()),
sel, outInfo);
}
else
......@@ -145,8 +151,8 @@ int vtkExtractSelection::RequestData(
}
else
{
vtkDataObject* ecOutput =
this->RequestDataFromBlock(vtkDataSet::SafeDownCast(input), sel, outInfo);
vtkDataObject* ecOutput =
this->RequestDataFromBlock(input, sel, outInfo);
if (ecOutput)
{
output->ShallowCopy(ecOutput);
......@@ -190,7 +196,7 @@ int vtkExtractSelection::RequestDataObject(
}
//-----------------------------------------------------------------------------
vtkDataSet* vtkExtractSelection::RequestDataInternal(
vtkDataObject* vtkExtractSelection::RequestDataInternal(
unsigned int composite_index,
vtkDataSet* input, vtkSelection* sel,
vtkInformation* outInfo)
......@@ -222,7 +228,7 @@ vtkDataSet* vtkExtractSelection::RequestDataInternal(
}
}
}
else if (!selProperties->Has(vtkSelection::COMPOSITE_INDEX()) ||
else if (!selProperties->Has(vtkSelection::COMPOSITE_INDEX()) ||
(static_cast<unsigned int>(selProperties->Get(vtkSelection::COMPOSITE_INDEX()))
== composite_index))
{
......@@ -233,14 +239,14 @@ vtkDataSet* vtkExtractSelection::RequestDataInternal(
}
//-----------------------------------------------------------------------------
vtkDataSet* vtkExtractSelection::RequestDataInternal(
vtkDataObject* vtkExtractSelection::RequestDataInternal(
unsigned int composite_index,
unsigned int level,
unsigned int index,
vtkDataSet* input, vtkSelection* sel,
vtkInformation* outInfo)
{
// Here either COMPOSITE_INDEX() is present or
// Here either COMPOSITE_INDEX() is present or
// (HIERARCHICAL_LEVEL(), HIERARCHICAL_INDEX()) is present.
if (!input || !sel)
......@@ -297,8 +303,8 @@ vtkDataSet* vtkExtractSelection::RequestDataInternal(
{
return this->RequestDataFromBlock(input, sel, outInfo);
}
else if (!selProperties->Has(vtkSelection::COMPOSITE_INDEX()) &&
!selProperties->Has(vtkSelection::HIERARCHICAL_LEVEL()) &&
else if (!selProperties->Has(vtkSelection::COMPOSITE_INDEX()) &&
!selProperties->Has(vtkSelection::HIERARCHICAL_LEVEL()) &&
!selProperties->Has(vtkSelection::HIERARCHICAL_INDEX()))
{
return this->RequestDataFromBlock(input, sel, outInfo);
......@@ -308,8 +314,8 @@ vtkDataSet* vtkExtractSelection::RequestDataInternal(
}
//-----------------------------------------------------------------------------
vtkDataSet* vtkExtractSelection::RequestDataFromBlock(
vtkDataSet* input, vtkSelection* sel, vtkInformation* outInfo)
vtkDataObject* vtkExtractSelection::RequestDataFromBlock(
vtkDataObject* input, vtkSelection* sel, vtkInformation* outInfo)
{
if (sel->GetContentType() == vtkSelection::SELECTIONS)
{
......@@ -326,33 +332,33 @@ vtkDataSet* vtkExtractSelection::RequestDataFromBlock(
int seltype = sel->GetContentType();
switch (seltype)
{
case vtkSelection::GLOBALIDS:
case vtkSelection::PEDIGREEIDS:
case vtkSelection::VALUES:
case vtkSelection::INDICES:
{
case vtkSelection::GLOBALIDS:
case vtkSelection::PEDIGREEIDS:
case vtkSelection::VALUES:
case vtkSelection::INDICES:
subFilter = this->IdsFilter;
break;
}
case vtkSelection::FRUSTUM:
{
case vtkSelection::FRUSTUM:
subFilter = this->FrustumFilter;
this->FrustumFilter->SetShowBounds(this->ShowBounds);
break;
}
case vtkSelection::LOCATIONS:
{
case vtkSelection::LOCATIONS:
subFilter = this->UseProbeForLocations?
static_cast<vtkExtractSelectionBase*>(this->ProbeFilter) :
static_cast<vtkExtractSelectionBase*>(this->LocationsFilter);
break;
}
case vtkSelection::THRESHOLDS:
{
case vtkSelection::THRESHOLDS:
subFilter = this->ThresholdsFilter;
break;
}
default:
case vtkSelection::BLOCKS:
subFilter = this->BlockFilter;
break;
default:
vtkErrorMacro("Unrecognized CONTENT_TYPE: " << seltype);
return NULL;
}
......@@ -392,23 +398,22 @@ vtkDataSet* vtkExtractSelection::RequestDataFromBlock(
sddp->SetUpdateExtent(0, uExtent);
}
}
vtkDataObject* inputCopy = input->NewInstance();
inputCopy->ShallowCopy(input);
subFilter->SetInput(0, inputCopy);
subFilter->Update();
vtkDataSet* ecOutput = vtkDataSet::SafeDownCast(
subFilter->GetOutputDataObject(0));
vtkDataSet* output = ecOutput->NewInstance();
vtkDataObject* ecOutput = subFilter->GetOutputDataObject(0);
vtkDataObject* output = ecOutput->NewInstance();
output->ShallowCopy(ecOutput);
//make sure everything is deallocated
inputCopy->Delete();
ecOutput->Initialize();
subFilter->SetInput(0,static_cast<vtkDataSet *>(NULL));
subFilter->SetInput(0,static_cast<vtkDataObject*>(NULL));
subFilter->SetInput(1,static_cast<vtkSelection *>(NULL));
return output;
}
......
......@@ -30,8 +30,9 @@
#include "vtkExtractSelectionBase.h"
class vtkExtractSelectedIds;
class vtkExtractSelectedBlock;
class vtkExtractSelectedFrustum;
class vtkExtractSelectedIds;
class vtkExtractSelectedLocations;
class vtkExtractSelectedThresholds;
class vtkProbeSelectedLocations;
......@@ -76,13 +77,13 @@ protected:
vtkInformationVector *);
// used for composite, non-hierarhical input.
vtkDataSet* RequestDataInternal(
vtkDataObject* RequestDataInternal(
unsigned int composite_index,
vtkDataSet* input, vtkSelection* sel,
vtkInformation* outInfo);
// Used for hierarchical input.
vtkDataSet* RequestDataInternal(
vtkDataObject* RequestDataInternal(
unsigned int composite_index,
unsigned int level,
unsigned int index,
......@@ -91,9 +92,10 @@ protected:
// called for non-composite input or for a block in a composite dataset.
vtkDataSet* RequestDataFromBlock(vtkDataSet* input,