You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
491 lines
18 KiB
491 lines
18 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkXMLStructuredDataReader.cxx,v $
|
|
|
|
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 "vtkXMLStructuredDataReader.h"
|
|
|
|
#include "vtkDataArray.h"
|
|
#include "vtkDataSet.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkStreamingDemandDrivenPipeline.h"
|
|
#include "vtkXMLDataElement.h"
|
|
#include "vtkXMLDataParser.h"
|
|
|
|
vtkCxxRevisionMacro(vtkXMLStructuredDataReader, "$Revision: 1.20 $");
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkXMLStructuredDataReader::vtkXMLStructuredDataReader()
|
|
{
|
|
this->PieceExtents = 0;
|
|
this->PiecePointDimensions = 0;
|
|
this->PiecePointIncrements = 0;
|
|
this->PieceCellDimensions = 0;
|
|
this->PieceCellIncrements = 0;
|
|
this->WholeSlices = 1;
|
|
|
|
// Initialize these in case someone calls GetNumberOfPoints or
|
|
// GetNumberOfCells before UpdateInformation is called.
|
|
this->PointDimensions[0] = 0;
|
|
this->PointDimensions[1] = 0;
|
|
this->PointDimensions[2] = 0;
|
|
this->CellDimensions[0] = 0;
|
|
this->CellDimensions[1] = 0;
|
|
this->CellDimensions[2] = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkXMLStructuredDataReader::~vtkXMLStructuredDataReader()
|
|
{
|
|
if(this->NumberOfPieces)
|
|
{
|
|
this->DestroyPieces();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLStructuredDataReader::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os, indent);
|
|
os << indent << "WholeSlices: " << this->WholeSlices << "\n";
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkXMLStructuredDataReader::ReadPrimaryElement(vtkXMLDataElement* ePrimary)
|
|
{
|
|
// Get the whole extent attribute.
|
|
int extent[6];
|
|
if(ePrimary->GetVectorAttribute("WholeExtent", 6, extent) == 6)
|
|
{
|
|
// Set the output's whole extent.
|
|
this->GetOutputAsDataSet(0)->SetWholeExtent(extent);
|
|
|
|
// Check each axis to see if it has cells.
|
|
for(int a=0; a < 3; ++a)
|
|
{
|
|
this->AxesEmpty[a] = (extent[2*a+1] > extent[2*a])? 0 : 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
vtkErrorMacro(<< this->GetDataSetName() << " element has no WholeExtent.");
|
|
return 0;
|
|
}
|
|
|
|
return this->Superclass::ReadPrimaryElement(ePrimary);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
vtkXMLStructuredDataReader::CopyOutputInformation(vtkInformation* outInfo,
|
|
int port)
|
|
{
|
|
// Let the superclass copy information first.
|
|
this->Superclass::CopyOutputInformation(outInfo, port);
|
|
|
|
// All structured data has a whole extent.
|
|
vtkInformation* localInfo = this->GetExecutive()->GetOutputInformation(port);
|
|
if(localInfo->Has(vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT()))
|
|
{
|
|
outInfo->CopyEntry(localInfo,
|
|
vtkStreamingDemandDrivenPipeline::WHOLE_EXTENT());
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLStructuredDataReader::SetupEmptyOutput()
|
|
{
|
|
// Special extent to indicate no input.
|
|
this->GetOutputAsDataSet(0)->SetWholeExtent(0, -1, 0, -1, 0, -1);
|
|
this->GetOutputAsDataSet(0)->SetUpdateExtent(0, -1, 0, -1, 0, -1);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLStructuredDataReader::SetupPieces(int numPieces)
|
|
{
|
|
this->Superclass::SetupPieces(numPieces);
|
|
this->PieceExtents = new int[numPieces*6];
|
|
this->PiecePointDimensions = new int[numPieces*3];
|
|
this->PiecePointIncrements = new vtkIdType[numPieces*3];
|
|
this->PieceCellDimensions = new int[numPieces*3];
|
|
this->PieceCellIncrements = new vtkIdType[numPieces*3];
|
|
int i;
|
|
for(i=0; i < numPieces; ++i)
|
|
{
|
|
int* extent = this->PieceExtents + i*6;
|
|
extent[0]=0; extent[1]=-1;
|
|
extent[2]=0; extent[3]=-1;
|
|
extent[4]=0; extent[5]=-1;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLStructuredDataReader::DestroyPieces()
|
|
{
|
|
delete [] this->PieceExtents;
|
|
delete [] this->PiecePointDimensions;
|
|
delete [] this->PiecePointIncrements;
|
|
delete [] this->PieceCellDimensions;
|
|
delete [] this->PieceCellIncrements;
|
|
this->PieceExtents = 0;
|
|
this->PiecePointDimensions = 0;
|
|
this->PiecePointIncrements = 0;
|
|
this->PieceCellDimensions = 0;
|
|
this->PieceCellIncrements = 0;
|
|
this->Superclass::DestroyPieces();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkIdType vtkXMLStructuredDataReader::GetNumberOfPoints()
|
|
{
|
|
return (this->PointDimensions[0]*
|
|
this->PointDimensions[1]*
|
|
this->PointDimensions[2]);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkIdType vtkXMLStructuredDataReader::GetNumberOfCells()
|
|
{
|
|
return (this->CellDimensions[0]*
|
|
this->CellDimensions[1]*
|
|
this->CellDimensions[2]);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkXMLStructuredDataReader::ReadPiece(vtkXMLDataElement* ePiece)
|
|
{
|
|
if(!this->Superclass::ReadPiece(ePiece))
|
|
{
|
|
return 0;
|
|
}
|
|
int* pieceExtent = this->PieceExtents + this->Piece*6;
|
|
|
|
// Read the extent of the piece.
|
|
if(strcmp(ePiece->GetName(), "Piece") == 0)
|
|
{
|
|
if(!ePiece->GetAttribute("Extent"))
|
|
{
|
|
vtkErrorMacro("Piece has no extent.");
|
|
}
|
|
if(ePiece->GetVectorAttribute("Extent", 6, pieceExtent) < 6)
|
|
{
|
|
vtkErrorMacro("Extent attribute is not 6 integers.");
|
|
return 0;
|
|
}
|
|
}
|
|
else if(ePiece->GetVectorAttribute("WholeExtent", 6, pieceExtent) < 6)
|
|
{
|
|
vtkErrorMacro("WholeExtent attribute is not 6 integers.");
|
|
return 0;
|
|
}
|
|
|
|
// Compute the dimensions and increments for this piece's extent.
|
|
int* piecePointDimensions = this->PiecePointDimensions + this->Piece*3;
|
|
vtkIdType* piecePointIncrements = this->PiecePointIncrements + this->Piece*3;
|
|
int* pieceCellDimensions = this->PieceCellDimensions + this->Piece*3;
|
|
vtkIdType* pieceCellIncrements = this->PieceCellIncrements + this->Piece*3;
|
|
this->ComputePointDimensions(pieceExtent, piecePointDimensions);
|
|
this->ComputePointIncrements(pieceExtent, piecePointIncrements);
|
|
this->ComputeCellDimensions(pieceExtent, pieceCellDimensions);
|
|
this->ComputeCellIncrements(pieceExtent, pieceCellIncrements);
|
|
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLStructuredDataReader::ReadXMLData()
|
|
{
|
|
// Get the requested Update Extent.
|
|
this->GetOutputAsDataSet(0)->GetUpdateExtent(this->UpdateExtent);
|
|
|
|
vtkDebugMacro("Updating extent "
|
|
<< this->UpdateExtent[0] << " " << this->UpdateExtent[1] << " "
|
|
<< this->UpdateExtent[2] << " " << this->UpdateExtent[3] << " "
|
|
<< this->UpdateExtent[4] << " " << this->UpdateExtent[5]
|
|
<< "\n");
|
|
|
|
// Prepare increments for the update extent.
|
|
this->ComputePointDimensions(this->UpdateExtent, this->PointDimensions);
|
|
this->ComputePointIncrements(this->UpdateExtent, this->PointIncrements);
|
|
this->ComputeCellDimensions(this->UpdateExtent, this->CellDimensions);
|
|
this->ComputeCellIncrements(this->UpdateExtent, this->CellIncrements);
|
|
|
|
// Let superclasses read data. This also allocates output data.
|
|
this->Superclass::ReadXMLData();
|
|
|
|
// Split current progress range based on fraction contributed by
|
|
// each piece.
|
|
float progressRange[2] = {0,0};
|
|
this->GetProgressRange(progressRange);
|
|
|
|
// Calculate the cumulative fraction of data contributed by each
|
|
// piece (for progress).
|
|
float* fractions = new float[this->NumberOfPieces+1];
|
|
int i;
|
|
fractions[0] = 0;
|
|
for(i=0;i < this->NumberOfPieces;++i)
|
|
{
|
|
int* pieceExtent = this->PieceExtents + i*6;
|
|
int pieceDims[3] = {0,0,0};
|
|
// Intersect the extents to get the part we need to read.
|
|
if(this->IntersectExtents(pieceExtent, this->UpdateExtent,
|
|
this->SubExtent))
|
|
{
|
|
this->ComputePointDimensions(this->SubExtent, pieceDims);
|
|
fractions[i+1] = fractions[i] + pieceDims[0]*pieceDims[1]*pieceDims[2];
|
|
}
|
|
else
|
|
{
|
|
fractions[i+1] = 0;
|
|
}
|
|
}
|
|
if(fractions[this->NumberOfPieces] == 0)
|
|
{
|
|
fractions[this->NumberOfPieces] = 1;
|
|
}
|
|
for(i=1;i <= this->NumberOfPieces;++i)
|
|
{
|
|
fractions[i] = fractions[i] / fractions[this->NumberOfPieces];
|
|
}
|
|
|
|
// Read the data needed from each piece.
|
|
for(i=0;(i < this->NumberOfPieces && !this->AbortExecute &&
|
|
!this->DataError);++i)
|
|
{
|
|
// Set the range of progress for this piece.
|
|
this->SetProgressRange(progressRange, i, fractions);
|
|
|
|
// Intersect the extents to get the part we need to read.
|
|
int* pieceExtent = this->PieceExtents + i*6;
|
|
if(this->IntersectExtents(pieceExtent, this->UpdateExtent,
|
|
this->SubExtent))
|
|
{
|
|
vtkDebugMacro("Reading extent "
|
|
<< this->SubExtent[0] << " " << this->SubExtent[1] << " "
|
|
<< this->SubExtent[2] << " " << this->SubExtent[3] << " "
|
|
<< this->SubExtent[4] << " " << this->SubExtent[5]
|
|
<< " from piece " << i);
|
|
|
|
this->ComputePointDimensions(this->SubExtent, this->SubPointDimensions);
|
|
this->ComputeCellDimensions(this->SubExtent, this->SubCellDimensions);
|
|
|
|
// Read the data from this piece.
|
|
if(!this->ReadPieceData(i))
|
|
{
|
|
// An error occurred while reading the piece.
|
|
this->DataError = 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
delete [] fractions;
|
|
|
|
// We filled the exact update extent in the output.
|
|
this->SetOutputExtent(this->UpdateExtent);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkXMLStructuredDataReader::ReadArrayForPoints(vtkXMLDataElement* da,
|
|
vtkDataArray* outArray)
|
|
{
|
|
int* pieceExtent = this->PieceExtents + this->Piece*6;
|
|
int* piecePointDimensions = this->PiecePointDimensions + this->Piece*3;
|
|
vtkIdType* piecePointIncrements = this->PiecePointIncrements + this->Piece*3;
|
|
if(!this->ReadSubExtent(pieceExtent, piecePointDimensions,
|
|
piecePointIncrements, this->UpdateExtent,
|
|
this->PointDimensions, this->PointIncrements,
|
|
this->SubExtent, this->SubPointDimensions,
|
|
da, outArray))
|
|
{
|
|
vtkErrorMacro("Error reading extent "
|
|
<< this->SubExtent[0] << " " << this->SubExtent[1] << " "
|
|
<< this->SubExtent[2] << " " << this->SubExtent[3] << " "
|
|
<< this->SubExtent[4] << " " << this->SubExtent[5]
|
|
<< " from piece " << this->Piece);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkXMLStructuredDataReader::ReadArrayForCells(vtkXMLDataElement* da,
|
|
vtkDataArray* outArray)
|
|
{
|
|
int* pieceExtent = this->PieceExtents + this->Piece*6;
|
|
int* pieceCellDimensions = this->PieceCellDimensions + this->Piece*3;
|
|
vtkIdType* pieceCellIncrements = this->PieceCellIncrements + this->Piece*3;
|
|
if(!this->ReadSubExtent(pieceExtent, pieceCellDimensions,
|
|
pieceCellIncrements, this->UpdateExtent,
|
|
this->CellDimensions, this->CellIncrements,
|
|
this->SubExtent, this->SubCellDimensions,
|
|
da, outArray))
|
|
{
|
|
vtkErrorMacro("Error reading extent "
|
|
<< this->SubExtent[0] << " " << this->SubExtent[1] << " "
|
|
<< this->SubExtent[2] << " " << this->SubExtent[3] << " "
|
|
<< this->SubExtent[4] << " " << this->SubExtent[5]
|
|
<< " from piece " << this->Piece);
|
|
return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
vtkXMLStructuredDataReader
|
|
::ReadSubExtent(int* inExtent, int* inDimensions, vtkIdType* inIncrements,
|
|
int* outExtent, int* outDimensions, vtkIdType* outIncrements,
|
|
int* subExtent, int* subDimensions, vtkXMLDataElement* da,
|
|
vtkDataArray* array)
|
|
{
|
|
int components = array->GetNumberOfComponents();
|
|
|
|
if((inDimensions[0] == outDimensions[0]) &&
|
|
(inDimensions[1] == outDimensions[1]))
|
|
{
|
|
if(inDimensions[2] == outDimensions[2])
|
|
{
|
|
// Read the whole volume at once. This fills the array's entire
|
|
// progress range.
|
|
vtkIdType volumeTuples =
|
|
(inDimensions[0]*inDimensions[1]*inDimensions[2]);
|
|
if(!this->ReadData(da, array->GetVoidPointer(0), array->GetDataType(),
|
|
0, volumeTuples*components))
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Read an entire slice at a time. Split progress range by
|
|
// slice.
|
|
float progressRange[2] = {0,0};
|
|
this->GetProgressRange(progressRange);
|
|
vtkIdType sliceTuples = inDimensions[0]*inDimensions[1];
|
|
int k;
|
|
for(k=0;k < subDimensions[2] && !this->AbortExecute;++k)
|
|
{
|
|
// Calculate the starting tuples for source and destination.
|
|
vtkIdType sourceTuple =
|
|
this->GetStartTuple(inExtent, inIncrements,
|
|
subExtent[0], subExtent[2], subExtent[4]+k);
|
|
vtkIdType destTuple =
|
|
this->GetStartTuple(outExtent, outIncrements,
|
|
subExtent[0], subExtent[2], subExtent[4]+k);
|
|
|
|
// Set the range of progress for this slice.
|
|
this->SetProgressRange(progressRange, k, subDimensions[2]);
|
|
|
|
// Read the slice.
|
|
if(!this->ReadData(da, array->GetVoidPointer(destTuple*components),
|
|
array->GetDataType(), sourceTuple*components,
|
|
sliceTuples*components))
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(!this->WholeSlices)
|
|
{
|
|
// Read a row at a time. Split progress range by row.
|
|
float progressRange[2] = {0,0};
|
|
this->GetProgressRange(progressRange);
|
|
vtkIdType rowTuples = subDimensions[0];
|
|
int j,k;
|
|
for(k=0;k < subDimensions[2] && !this->AbortExecute;++k)
|
|
{
|
|
for(j=0;j < subDimensions[1] && !this->AbortExecute;++j)
|
|
{
|
|
// Calculate the starting tuples for source and destination.
|
|
vtkIdType sourceTuple =
|
|
this->GetStartTuple(inExtent, inIncrements,
|
|
subExtent[0], subExtent[2]+j, subExtent[4]+k);
|
|
vtkIdType destTuple =
|
|
this->GetStartTuple(outExtent, outIncrements,
|
|
subExtent[0], subExtent[2]+j, subExtent[4]+k);
|
|
|
|
// Set the range of progress for this row.
|
|
this->SetProgressRange(progressRange, subDimensions[1]*k+j,
|
|
subDimensions[2]*subDimensions[1]);
|
|
|
|
// Read the row.
|
|
if(!this->ReadData(da, array->GetVoidPointer(destTuple*components),
|
|
array->GetDataType(), sourceTuple*components,
|
|
rowTuples*components))
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Read in each slice and copy the needed rows from it. Split
|
|
// progress range by slice.
|
|
float progressRange[2] = {0,0};
|
|
this->GetProgressRange(progressRange);
|
|
vtkIdType rowTuples = subDimensions[0];
|
|
vtkIdType partialSliceTuples = inDimensions[0]*subDimensions[1];
|
|
int tupleSize = components*array->GetDataTypeSize();
|
|
vtkDataArray* temp = array->NewInstance();
|
|
temp->SetNumberOfComponents(array->GetNumberOfComponents());
|
|
temp->SetNumberOfTuples(partialSliceTuples);
|
|
int k;
|
|
for(k=0;k < subDimensions[2] && !this->AbortExecute;++k)
|
|
{
|
|
// Calculate the starting tuple from the input.
|
|
vtkIdType inTuple =
|
|
this->GetStartTuple(inExtent, inIncrements,
|
|
inExtent[0], subExtent[2], subExtent[4]+k);
|
|
int memExtent[6];
|
|
memExtent[0] = inExtent[0];
|
|
memExtent[1] = inExtent[1];
|
|
memExtent[2] = subExtent[2];
|
|
memExtent[3] = subExtent[3];
|
|
memExtent[4] = subExtent[4]+k;
|
|
memExtent[5] = subExtent[4]+k;
|
|
|
|
// Set the range of progress for this slice.
|
|
this->SetProgressRange(progressRange, k, subDimensions[2]);
|
|
|
|
// Read the slice.
|
|
if(!this->ReadData(da, temp->GetVoidPointer(0), temp->GetDataType(),
|
|
inTuple*components,
|
|
partialSliceTuples*components))
|
|
{
|
|
temp->Delete();
|
|
return 0;
|
|
}
|
|
|
|
// Copy the portion of the slice we need.
|
|
int j;
|
|
for(j=0;j < subDimensions[1];++j)
|
|
{
|
|
vtkIdType sourceTuple =
|
|
this->GetStartTuple(memExtent, inIncrements,
|
|
subExtent[0], subExtent[2]+j, subExtent[4]+k);
|
|
vtkIdType destTuple =
|
|
this->GetStartTuple(outExtent, outIncrements,
|
|
subExtent[0], subExtent[2]+j, subExtent[4]+k);
|
|
memcpy(array->GetVoidPointer(destTuple*components),
|
|
temp->GetVoidPointer(sourceTuple*components),
|
|
tupleSize*rowTuples);
|
|
}
|
|
}
|
|
temp->Delete();
|
|
}
|
|
}
|
|
return 1;
|
|
}
|
|
|