Commit 488a4495 authored by Berk Geveci's avatar Berk Geveci
Browse files

ENH: Updated example to new amr

parent aa851697
......@@ -6,5 +6,5 @@ IF(NOT VTK_USE_RENDERING)
ENDIF(NOT VTK_USE_RENDERING)
INCLUDE(${VTK_USE_FILE})
ADD_EXECUTABLE(HierarchicalBoxPipeline HierarchicalBoxPipeline.cxx)
ADD_EXECUTABLE(HierarchicalBoxPipeline HierarchicalBoxPipeline.cxx vtkTestHierarchicalDataReader.cxx)
TARGET_LINK_LIBRARIES(HierarchicalBoxPipeline vtkRendering vtkIO)
......@@ -16,209 +16,123 @@
// AMR datasets can be processed using the new vtkHierarchicalBoxDataSet class.
//
// The command line arguments are:
// -D <path> => path to the data (VTKData); the data should be in <path>/Data/
// -I => run in interactive mode; unless this is used, the program will
// not allow interaction and exit
// -D <path> => path to the data; the data should be in <path>/Data/
#include "vtkActor.h"
#include "vtkAMRBox.h"
#include "vtkCamera.h"
#include "vtkCellDataToPointData.h"
#include "vtkCompositeDataPipeline.h"
#include "vtkContourFilter.h"
#include "vtkDebugLeaks.h"
#include "vtkHierarchicalBoxDataSet.h"
#include "vtkHierarchicalDataExtractLevel.h"
#include "vtkHierarchicalDataSetGeometryFilter.h"
#include "vtkImageData.h"
#include "vtkOutlineCornerFilter.h"
#include "vtkPolyDataMapper.h"
#include "vtkHierarchicalPolyDataMapper.h"
#include "vtkProperty.h"
#include "vtkTestUtilities.h"
#include "vtkRegressionTestImage.h"
#include "vtkRenderer.h"
#include "vtkRenderWindow.h"
#include "vtkRenderWindowInteractor.h"
#include "vtkUniformGrid.h"
#include "vtkXMLImageDataReader.h"
#include "vtkShrinkPolyData.h"
#include "vtkTestHierarchicalDataReader.h"
#include "vtkTestUtilities.h"
int main(int argc, char* argv[])
{
// Standard rendering classes
vtkRenderer *ren = vtkRenderer::New();
vtkCamera* cam = ren->GetActiveCamera();
cam->SetPosition(-5.1828, 5.89733, 8.97969);
cam->SetFocalPoint(14.6491, -2.08677, -8.92362);
cam->SetViewUp(0.210794, 0.95813, -0.193784);
vtkRenderWindow *renWin = vtkRenderWindow::New();
renWin->AddRenderer(ren);
vtkRenderWindowInteractor *iren = vtkRenderWindowInteractor::New();
iren->SetRenderWindow(renWin);
// Since there is no AMR reader avaible yet, we will load a
// collection of VTK files and create our own vtkHierarchicalBoxDataSet.
// To create the files, I loaded a Chombo file with an experimental
// Chombo reader and wrote the datasets separately.
int i;
vtkXMLImageDataReader* reader = vtkXMLImageDataReader::New();
// vtkHierarchicalBoxDataSet represents hierarchical box
// (uniform rectilinear) AMR datasets, See the class documentation
// for more information.
vtkHierarchicalBoxDataSet* hb = vtkHierarchicalBoxDataSet::New();
for (i=0; i<16; i++)
{
// Here we load the 16 separate files (each containing
// an image dataset -uniform rectilinear grid-)
ostrstream fname;
fname << "Data/chombo3d/chombo3d_" << i << ".vti" << ends;
char* fstr = fname.str();
char* cfname =
vtkTestUtilities::ExpandDataFileName(argc, argv, fstr);
reader->SetFileName(cfname);
// We have to update since we are working without a VTK pipeline.
// This will read the file and the output of the reader will be
// a valid image data.
reader->Update();
delete[] fstr;
delete[] cfname;
// We now create a vtkUniformGrid. This is essentially a simple
// vtkImageData (not a sub-class though) with blanking. Since
// VTK readers do not know vtkUniformGrid, we simply create our
// own by copying from the image data.
vtkUniformGrid* ug = vtkUniformGrid::New();
ug->ShallowCopy(reader->GetOutput());
// Each sub-dataset in a vtkHierarchicalBoxDataSet has an associated
// vtkAMRBox. This is similar to extent but is stored externally
// since it is possible to have sub-dataset nodes with NULL
// vtkUniformGrid pointers.
vtkAMRBox box;
// This is a hack (do not do this at home). Normally, the
// region (box) information should be available in the file.
// In this case, since there is no such information available,
// we obtain it by looking at each image data's extent.
// -- begin hack
int extent[6];
double spacing[3];
double origin[3];
ug->GetExtent(extent);
ug->GetSpacing(spacing);
ug->GetOrigin(origin);
for (int j=0; j<3; j++)
{
box.LoCorner[j] =
static_cast<int>(origin[j]/spacing[j] + extent[2*j]);
box.HiCorner[j] =
static_cast<int>(origin[j]/spacing[j] + extent[2*j+1] - 1);
}
// Similarly, the level of each sub-dataset is normally
// available in the file. Since this is not the case, I
// hard-coded this into the example program.
// Level 0 = { 0 }, Level 1 = { 1 },
// Level 2 = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }
int level;
int dsindex;
if (i == 0)
{
level = 0;
dsindex = 0;
}
else if (i == 1)
{
level = 1;
dsindex = 0;
}
else
{
level = 2;
dsindex = i-2;
}
// -- end hack
// Given the level, index and box, add the sub-dataset to
// hierarchical dataset.
hb->SetDataSet(level, dsindex, box, ug);
ug->Delete();
}
reader->Delete();
// I hard-coded the refinement ratios. These should normally
// be available in the file.
hb->SetRefinementRatio(0, 2);
hb->SetRefinementRatio(1, 2);
// This call generates visibility (blanking) arrays that mask
// regions of lower level datasets that overlap with regions
// of higher level datasets (it is assumed that, when available,
// higher level information should always be used instead of
// lower level information)
hb->GenerateVisibilityArrays();
// We now create a simple pipeline.
// AMR datasets can be processed with regular VTK filters in two ways:
// 1. Pass through a AMR aware consumer. Since a AMR
// aware mapper is not yet available, vtkHierarchicalDataSetGeometryFilter
// can be used
// 2. Assign the composite executive (vtkCompositeDataPipeline) to
// all "simple" (that work only on simple, non-composite datasets) filters
vtkCellDataToPointData* c2p = vtkCellDataToPointData::New();
c2p->SetInput(hb);
char* cfname =
vtkTestUtilities::ExpandDataFileName(argc, argv, "Data/chombo3d/chombo3d");
// contour
vtkContourFilter* contour = vtkContourFilter::New();
contour->SetInputConnection(0, c2p->GetOutputPort(0));
contour->SetValue(0, -0.013);
vtkTestHierarchicalDataReader* reader = vtkTestHierarchicalDataReader::New();
reader->SetFileName(cfname);
delete[] cfname;
// geometry filter
// This filter is AMR aware and will request blocks from the
// input. These blocks will be processed by simple processes as if they
// are the whole dataset
vtkHierarchicalDataSetGeometryFilter* geom1 =
vtkHierarchicalDataSetGeometryFilter* geom =
vtkHierarchicalDataSetGeometryFilter::New();
geom1->SetInputConnection(0, contour->GetOutputPort(0));
geom->SetInputConnection(0, reader->GetOutputPort(0));
// Rendering objects
vtkPolyDataMapper* ctMapper = vtkPolyDataMapper::New();
ctMapper->SetInputConnection(0, geom1->GetOutputPort(0));
vtkShrinkPolyData* shrink = vtkShrinkPolyData::New();
shrink->SetShrinkFactor(0.5);
shrink->SetInputConnection(0, geom->GetOutputPort(0));
vtkActor* ctActor = vtkActor::New();
ctActor->SetMapper(ctMapper);
ren->AddActor(ctActor);
// Rendering objects
vtkHierarchicalPolyDataMapper* shMapper = vtkHierarchicalPolyDataMapper::New();
shMapper->SetInputConnection(0, shrink->GetOutputPort(0));
vtkActor* shActor = vtkActor::New();
shActor->SetMapper(shMapper);
shActor->GetProperty()->SetColor(0, 0, 1);
ren->AddActor(shActor);
// outline
vtkOutlineCornerFilter* outline = vtkOutlineCornerFilter::New();
outline->SetInput(hb);
// corner outline
vtkOutlineCornerFilter* ocf = vtkOutlineCornerFilter::New();
ocf->SetInputConnection(0, reader->GetOutputPort(0));
vtkHierarchicalDataSetGeometryFilter* geom2 =
vtkHierarchicalDataSetGeometryFilter::New();
geom2->SetInputConnection(0, outline->GetOutputPort(0));
// Rendering objects
vtkPolyDataMapper* outMapper = vtkPolyDataMapper::New();
outMapper->SetInputConnection(0, geom2->GetOutputPort(0));
// This one is actually just a vtkPolyData so it doesn't need a hierarchical
// mapper, but we use this one to test hierarchical mapper with polydata input
vtkHierarchicalPolyDataMapper* ocMapper = vtkHierarchicalPolyDataMapper::New();
ocMapper->SetInputConnection(0, ocf->GetOutputPort(0));
vtkActor* ocActor = vtkActor::New();
ocActor->SetMapper(ocMapper);
ocActor->GetProperty()->SetColor(1, 0, 0);
ren->AddActor(ocActor);
// cell 2 point and contour
vtkHierarchicalDataExtractLevel* el = vtkHierarchicalDataExtractLevel::New();
el->SetInputConnection(0, reader->GetOutputPort(0));
el->SetLevelRange(2,2);
vtkActor* outActor = vtkActor::New();
outActor->SetMapper(outMapper);
outActor->GetProperty()->SetColor(0, 0, 0);
ren->AddActor(outActor);
vtkCellDataToPointData* c2p = vtkCellDataToPointData::New();
c2p->SetInputConnection(0, el->GetOutputPort(0));
vtkContourFilter* contour = vtkContourFilter::New();
contour->SetInputConnection(0, c2p->GetOutputPort(0));
contour->SetValue(0, -0.013);
contour->SetInputArrayToProcess(
0,0,0,vtkDataObject::FIELD_ASSOCIATION_POINTS,"phi");
// Rendering objects
vtkHierarchicalPolyDataMapper* contMapper =
vtkHierarchicalPolyDataMapper::New();
contMapper->SetInputConnection(0, contour->GetOutputPort(0));
vtkActor* contActor = vtkActor::New();
contActor->SetMapper(contMapper);
contActor->GetProperty()->SetColor(1, 0, 0);
ren->AddActor(contActor);
// In the future (once the pipeline changes are finished), it
// Standard testing code.
ren->SetBackground(1,1,1);
renWin->SetSize(300,300);
ren->ResetCamera();
iren->Start();
// Cleanup
geom1->Delete();
geom2->Delete();
ocf->Delete();
ocMapper->Delete();
ocActor->Delete();
c2p->Delete();
contour->Delete();
contMapper->Delete();
contActor->Delete();
el->Delete();
geom->Delete();
shMapper->Delete();
shActor->Delete();
ren->Delete();
renWin->Delete();
iren->Delete();
ctMapper->Delete();
ctActor->Delete();
outMapper->Delete();
outActor->Delete();
outline->Delete();
c2p->Delete();
contour->Delete();
hb->Delete();
reader->Delete();
shrink->Delete();
return 0;
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkTestHierarchicalDataReader.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 "vtkTestHierarchicalDataReader.h"
#include "vtkAMRBox.h"
#include "vtkCompositeDataPipeline.h"
#include "vtkExecutive.h"
#include "vtkHierarchicalBoxDataSet.h"
#include "vtkHierarchicalDataInformation.h"
#include "vtkImageData.h"
#include "vtkInformation.h"
#include "vtkInformationIntegerVectorKey.h"
#include "vtkInformationDoubleVectorKey.h"
#include "vtkInformationVector.h"
#include "vtkObjectFactory.h"
#include "vtkUniformGrid.h"
#include "vtkXMLImageDataReader.h"
vtkCxxRevisionMacro(vtkTestHierarchicalDataReader, "1.1");
vtkStandardNewMacro(vtkTestHierarchicalDataReader);
vtkTestHierarchicalDataReader::vtkTestHierarchicalDataReader()
{
this->FileName = 0;
this->SetNumberOfInputPorts(0);
}
vtkTestHierarchicalDataReader::~vtkTestHierarchicalDataReader()
{
this->SetFileName(0);
}
// Provide information about the dataset:
// * Number of levels
// * Number of boxes / level
// * AMRBox (extent) of each box
int vtkTestHierarchicalDataReader::RequestInformation(
vtkInformation* request,
vtkInformationVector** inputVector,
vtkInformationVector* outputVector)
{
if (!this->Superclass::RequestInformation(request, inputVector, outputVector))
{
return 0;
}
const int numLevels = 3;
int numBlocks[numLevels] = { 1, 1, 14 };
vtkHierarchicalDataInformation* compInfo =
vtkHierarchicalDataInformation::New();
compInfo->SetNumberOfLevels(numLevels);
int i;
for (i=0; i<numLevels; i++)
{
compInfo->SetNumberOfDataSets(i, numBlocks[i]);
}
vtkInformation* info = outputVector->GetInformationObject(0);
info->Set(
vtkCompositeDataPipeline::COMPOSITE_DATA_INFORMATION(), compInfo);
info->Set(
vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(), -1);
vtkXMLImageDataReader* reader = vtkXMLImageDataReader::New();
for (i=0; i<16; i++)
{
// Here we load the 16 separate files (each containing
// an image dataset -uniform rectilinear grid-)
char* fstr = this->GetBlockFileName(i);
reader->SetFileName(fstr);
reader->UpdateInformation();
delete[] fstr;
// Each sub-dataset in a vtkHierarchicalBoxDataSet has an associated
// vtkAMRBox. This is similar to extent but is stored externally
// since it is possible to have sub-dataset nodes with NULL
// vtkUniformGrid pointers.
vtkAMRBox box;
// This is a hack (do not do this at home). Normally, the
// region (box) information should be available in the file.
// In this case, since there is no such information available,
// we obtain it by looking at each image data's extent.
// -- begin hack
int extent[6];
double spacing[3];
double origin[3];
vtkInformation* outInfo = reader->GetExecutive()->GetOutputInformation(0);
outInfo->Get(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT(), extent);
outInfo->Get(vtkDataObject::SPACING(), spacing);
outInfo->Get(vtkDataObject::ORIGIN(), origin);
int j;
for (j=0; j<3; j++)
{
int num = static_cast<int>(floor(origin[j]/spacing[j] + 0.5));
box.LoCorner[j] = num + extent[2*j];
box.HiCorner[j] = num + extent[2*j+1] - 1;
}
int level;
int dsindex;
this->GetBlockIdx(i, level, dsindex);
vtkInformation* subInfo = compInfo->GetInformation(level, dsindex);
subInfo->Set(vtkHierarchicalBoxDataSet::BOX(),
box.LoCorner[0], box.LoCorner[1], box.LoCorner[2],
box.HiCorner[0], box.HiCorner[1], box.HiCorner[2]);
}
reader->Delete();
compInfo->Delete();
return 1;
}
int vtkTestHierarchicalDataReader::SetUpdateBlocks(
vtkInformation*,
vtkInformationVector**,
vtkInformationVector* outputVector)
{
vtkInformation* info = outputVector->GetInformationObject(0);
if (!info->Has(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()) ||
!info->Has(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()))
{
vtkErrorMacro("Expected information not found. "
"Cannot provide update extent.");
return 0;
}
vtkHierarchicalDataInformation* compInfo =
vtkHierarchicalDataInformation::SafeDownCast(
info->Get(vtkCompositeDataPipeline::COMPOSITE_DATA_INFORMATION()));
if (!compInfo)
{
vtkErrorMacro("Expected information not found. "
"Cannot provide update extent.");
return 0;
}
vtkHierarchicalDataInformation* updateInfo =
vtkHierarchicalDataInformation::New();
info->Set(
vtkCompositeDataPipeline::UPDATE_BLOCKS(), updateInfo);
updateInfo->SetNumberOfLevels(compInfo->GetNumberOfLevels());
unsigned int updatePiece = static_cast<unsigned int>(
info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER()));
unsigned int updateNumPieces = static_cast<unsigned int>(
info->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES()));
unsigned int numLevels = updateInfo->GetNumberOfLevels();
for (unsigned int j=0; j<numLevels; j++)
{
updateInfo->SetNumberOfDataSets(j, compInfo->GetNumberOfDataSets(j));
unsigned int numBlocks = updateInfo->GetNumberOfDataSets(j);
unsigned int numBlocksPerPiece = 1;
if (updateNumPieces < numBlocks)
{
numBlocksPerPiece = numBlocks / updateNumPieces;
}
unsigned int minBlock = numBlocksPerPiece*updatePiece;
unsigned int maxBlock = numBlocksPerPiece*(updatePiece+1);
if (updatePiece == updateNumPieces - 1)
{
maxBlock = numBlocks;
}
for (unsigned int i=minBlock; i<maxBlock; i++)
{
vtkInformation* blockInfo = updateInfo->GetInformation(j, i);
blockInfo->Set(vtkCompositeDataPipeline::MARKED_FOR_UPDATE(), 1);
}
}
updateInfo->Delete();
return 1;
}
int vtkTestHierarchicalDataReader::RequestData(
vtkInformation*, vtkInformationVector**, vtkInformationVector* outputVector)
{
int i;
if (!this->FileName)
{
return 0;
}
vtkInformation* info = outputVector->GetInformationObject(0);
vtkDataObject* doOutput =
info->Get(vtkCompositeDataSet::COMPOSITE_DATA_SET());
vtkHierarchicalBoxDataSet* hb =
vtkHierarchicalBoxDataSet::SafeDownCast(doOutput);
if (!hb)
{
return 0;
}
vtkHierarchicalDataInformation* compInfo =
vtkHierarchicalDataInformation::SafeDownCast(
info->Get(vtkCompositeDataPipeline::COMPOSITE_DATA_INFORMATION()));
hb->SetHierarchicalDataInformation(compInfo);
// Since there is no AMR reader avaible yet, we will load a
// collection of VTK files and create our own vtkHierarchicalBoxDataSet.
// To create the files, I loaded a Chombo file with an experimental
// Chombo reader and wrote the datasets separately.
vtkXMLImageDataReader* reader = vtkXMLImageDataReader::New();
for (i=0; i<16; i++)
{
// Here we load the 16 separate files (each containing
// an image dataset -uniform rectilinear grid-)
char* fstr = this->GetBlockFileName(i);
reader->SetFileName(fstr);
// We have to update since we are working without a VTK pipeline.
// This will read the file and the output of the reader will be
// a valid image data.
reader->Update();
delete[] fstr;
// We now create a vtkUniformGrid. This is essentially a simple
// vtkImageData (not a sub-class though) with blanking. Since
// VTK readers do not know vtkUniformGrid, we simply create our
// own by copying from the image data.
vtkUniformGrid* ug = vtkUniformGrid::New();
ug->ShallowCopy(reader->GetOutput());
int level;
int dsindex;
this->GetBlockIdx(i, level, dsindex);
// Given the level, index and box, add the sub-dataset to
// hierarchical dataset.
hb->SetDataSet(level, dsindex, ug);
ug->Delete();
}
reader->Delete();
// I hard-coded the refinement ratios. These should normally
// be available in the file.
hb->SetRefinementRatio(0, 2);
hb->SetRefinementRatio(1, 2);
// This call generates visibility (blanking) arrays that mask
// regions of lower level datasets that overlap with regions
// of higher level datasets (it is assumed that, when available,
// higher level information should always be used instead of
// lower level information)
hb->GenerateVisibilityArrays();
return 1;
}
void vtkTestHierarchicalDataReader::GetBlockIdx(
int blockId, int& level, int& dsindex)
{
// Similarly, the level of each sub-dataset is normally
// available in the file. Since this is not the case, I
// hard-coded this into the example program.
// Level 0 = { 0 }, Level 1 = { 1 },
// Level 2 = { 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }
if (blockId == 0)
{
level = 0;
dsindex = 0;
}
else if (blockId == 1)
{
level = 1;
dsindex = 0;
}
else
{
level = 2;
dsindex = blockId-2;