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.
813 lines
27 KiB
813 lines
27 KiB
2 years ago
|
/*=========================================================================
|
||
|
|
||
|
Program: Visualization Toolkit
|
||
|
Module: $RCSfile: vtkXMLUnstructuredDataReader.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 "vtkXMLUnstructuredDataReader.h"
|
||
|
#include "vtkObjectFactory.h"
|
||
|
#include "vtkXMLDataElement.h"
|
||
|
#include "vtkPoints.h"
|
||
|
#include "vtkIdTypeArray.h"
|
||
|
#include "vtkUnsignedCharArray.h"
|
||
|
#include "vtkCellArray.h"
|
||
|
#include "vtkPointSet.h"
|
||
|
#include "vtkInformation.h"
|
||
|
#include "vtkStreamingDemandDrivenPipeline.h"
|
||
|
|
||
|
#include <assert.h>
|
||
|
|
||
|
vtkCxxRevisionMacro(vtkXMLUnstructuredDataReader, "$Revision: 1.27 $");
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
vtkXMLUnstructuredDataReader::vtkXMLUnstructuredDataReader()
|
||
|
{
|
||
|
this->PointElements = 0;
|
||
|
this->NumberOfPoints = 0;
|
||
|
this->TotalNumberOfPoints = 0;
|
||
|
this->TotalNumberOfCells = 0;
|
||
|
|
||
|
this->PointsTimeStep = -1; //invalid state
|
||
|
this->PointsOffset = (unsigned long)-1;
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
vtkXMLUnstructuredDataReader::~vtkXMLUnstructuredDataReader()
|
||
|
{
|
||
|
if(this->NumberOfPieces)
|
||
|
{
|
||
|
this->DestroyPieces();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
void vtkXMLUnstructuredDataReader::PrintSelf(ostream& os, vtkIndent indent)
|
||
|
{
|
||
|
this->Superclass::PrintSelf(os, indent);
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
vtkPointSet* vtkXMLUnstructuredDataReader::GetOutputAsPointSet()
|
||
|
{
|
||
|
return vtkPointSet::SafeDownCast( this->GetOutputDataObject(0) );
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
vtkXMLDataElement*
|
||
|
vtkXMLUnstructuredDataReader
|
||
|
::FindDataArrayWithName(vtkXMLDataElement* eParent, const char* name)
|
||
|
{
|
||
|
// Find a nested element that represents a data array with the given name.
|
||
|
// and proper TimeStep
|
||
|
int i;
|
||
|
for(i=0;i < eParent->GetNumberOfNestedElements(); ++i)
|
||
|
{
|
||
|
vtkXMLDataElement* eNested = eParent->GetNestedElement(i);
|
||
|
if(strcmp(eNested->GetName(), "DataArray") == 0)
|
||
|
{
|
||
|
const char* aName = eNested->GetAttribute("Name");
|
||
|
if(aName && (strcmp(aName, name) == 0))
|
||
|
{
|
||
|
int numTimeSteps = eNested->GetVectorAttribute("TimeStep",
|
||
|
this->NumberOfTimeSteps, this->TimeSteps);
|
||
|
assert( numTimeSteps <= this->NumberOfTimeSteps );
|
||
|
// Check if CurrentTimeStep is in the array and particular field is also:
|
||
|
int isCurrentTimeInArray =
|
||
|
vtkXMLReader::IsTimeStepInArray(this->CurrentTimeStep, this->TimeSteps, numTimeSteps);
|
||
|
// If no time is specified or if time is specified and match then read
|
||
|
if( !numTimeSteps || isCurrentTimeInArray )
|
||
|
{
|
||
|
return eNested;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
template <class TIn, class TOut>
|
||
|
void vtkXMLUnstructuredDataReaderCopyArray(TIn* in, TOut* out,
|
||
|
vtkIdType length)
|
||
|
{
|
||
|
for(vtkIdType i = 0; i < length; ++i)
|
||
|
{
|
||
|
out[i] = static_cast<TOut>(in[i]);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
vtkIdTypeArray*
|
||
|
vtkXMLUnstructuredDataReader::ConvertToIdTypeArray(vtkDataArray* a)
|
||
|
{
|
||
|
// If it is already a vtkIdTypeArray, just return it.
|
||
|
vtkIdTypeArray* ida = vtkIdTypeArray::SafeDownCast(a);
|
||
|
if(ida)
|
||
|
{
|
||
|
return ida;
|
||
|
}
|
||
|
|
||
|
// Need to convert the data.
|
||
|
ida = vtkIdTypeArray::New();
|
||
|
ida->SetNumberOfComponents(a->GetNumberOfComponents());
|
||
|
ida->SetNumberOfTuples(a->GetNumberOfTuples());
|
||
|
vtkIdType length = a->GetNumberOfComponents() * a->GetNumberOfTuples();
|
||
|
vtkIdType* idBuffer = ida->GetPointer(0);
|
||
|
switch (a->GetDataType())
|
||
|
{
|
||
|
vtkTemplateMacro(
|
||
|
vtkXMLUnstructuredDataReaderCopyArray(
|
||
|
static_cast<VTK_TT*>(a->GetVoidPointer(0)),
|
||
|
idBuffer, length));
|
||
|
default:
|
||
|
vtkErrorMacro("Cannot convert vtkDataArray of type " << a->GetDataType()
|
||
|
<< " to vtkIdTypeArray.");
|
||
|
ida->Delete();
|
||
|
ida = 0;
|
||
|
}
|
||
|
a->Delete();
|
||
|
return ida;
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
vtkUnsignedCharArray*
|
||
|
vtkXMLUnstructuredDataReader::ConvertToUnsignedCharArray(vtkDataArray* a)
|
||
|
{
|
||
|
// If it is already a vtkUnsignedCharArray, just return it.
|
||
|
vtkUnsignedCharArray* uca = vtkUnsignedCharArray::SafeDownCast(a);
|
||
|
if(uca)
|
||
|
{
|
||
|
return uca;
|
||
|
}
|
||
|
|
||
|
// Need to convert the data.
|
||
|
uca = vtkUnsignedCharArray::New();
|
||
|
uca->SetNumberOfComponents(a->GetNumberOfComponents());
|
||
|
uca->SetNumberOfTuples(a->GetNumberOfTuples());
|
||
|
vtkIdType length = a->GetNumberOfComponents() * a->GetNumberOfTuples();
|
||
|
unsigned char* ucBuffer = uca->GetPointer(0);
|
||
|
switch (a->GetDataType())
|
||
|
{
|
||
|
vtkTemplateMacro(
|
||
|
vtkXMLUnstructuredDataReaderCopyArray(
|
||
|
static_cast<VTK_TT*>(a->GetVoidPointer(0)),
|
||
|
ucBuffer, length));
|
||
|
default:
|
||
|
vtkErrorMacro("Cannot convert vtkDataArray of type " << a->GetDataType()
|
||
|
<< " to vtkUnsignedCharArray.");
|
||
|
uca->Delete();
|
||
|
uca = 0;
|
||
|
}
|
||
|
a->Delete();
|
||
|
return uca;
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
void vtkXMLUnstructuredDataReader::SetupEmptyOutput()
|
||
|
{
|
||
|
// No pieces means no input.
|
||
|
this->GetOutputAsDataSet(0)->SetUpdateExtent(0, 0);
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
void vtkXMLUnstructuredDataReader::SetupOutputTotals()
|
||
|
{
|
||
|
this->TotalNumberOfPoints = 0;
|
||
|
for(int i=this->StartPiece; i < this->EndPiece; ++i)
|
||
|
{
|
||
|
this->TotalNumberOfPoints += this->NumberOfPoints[i];
|
||
|
}
|
||
|
this->StartPoint = 0;
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
void vtkXMLUnstructuredDataReader::SetupNextPiece()
|
||
|
{
|
||
|
this->StartPoint += this->NumberOfPoints[this->Piece];
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
void vtkXMLUnstructuredDataReader::SetupUpdateExtent(int piece,
|
||
|
int numberOfPieces,
|
||
|
int ghostLevel)
|
||
|
{
|
||
|
this->UpdatePiece = piece;
|
||
|
this->UpdateNumberOfPieces = numberOfPieces;
|
||
|
this->UpdateGhostLevel = ghostLevel;
|
||
|
|
||
|
// If more pieces are requested than available, just return empty
|
||
|
// pieces for the extra ones.
|
||
|
if(this->UpdateNumberOfPieces > this->NumberOfPieces)
|
||
|
{
|
||
|
this->UpdateNumberOfPieces = this->NumberOfPieces;
|
||
|
}
|
||
|
|
||
|
// Find the range of pieces to read.
|
||
|
if(this->UpdatePiece < this->UpdateNumberOfPieces)
|
||
|
{
|
||
|
this->StartPiece = ((this->UpdatePiece*this->NumberOfPieces) /
|
||
|
this->UpdateNumberOfPieces);
|
||
|
this->EndPiece = (((this->UpdatePiece+1)*this->NumberOfPieces) /
|
||
|
this->UpdateNumberOfPieces);
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
this->StartPiece = 0;
|
||
|
this->EndPiece = 0;
|
||
|
}
|
||
|
|
||
|
// Find the total size of the output.
|
||
|
this->SetupOutputTotals();
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
void vtkXMLUnstructuredDataReader::ReadXMLData()
|
||
|
{
|
||
|
// Get the update request.
|
||
|
int piece;
|
||
|
int numberOfPieces;
|
||
|
int ghostLevel;
|
||
|
this->GetOutputUpdateExtent(piece, numberOfPieces, ghostLevel);
|
||
|
|
||
|
vtkDebugMacro("Updating piece " << piece << " of " << numberOfPieces
|
||
|
<< " with ghost level " << ghostLevel);
|
||
|
|
||
|
// Setup the range of pieces that will be read.
|
||
|
this->SetupUpdateExtent(piece, numberOfPieces, ghostLevel);
|
||
|
|
||
|
// If there are no data to read, stop now.
|
||
|
if(this->StartPiece == this->EndPiece)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
vtkDebugMacro("Reading piece range [" << this->StartPiece
|
||
|
<< ", " << this->EndPiece << ") from file.");
|
||
|
|
||
|
// 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->EndPiece-this->StartPiece+1];
|
||
|
int i;
|
||
|
fractions[0] = 0;
|
||
|
for(i=this->StartPiece; i < this->EndPiece; ++i)
|
||
|
{
|
||
|
int index = i-this->StartPiece;
|
||
|
fractions[index+1] = (fractions[index] +
|
||
|
this->GetNumberOfPointsInPiece(i) +
|
||
|
this->GetNumberOfCellsInPiece(i));
|
||
|
}
|
||
|
if(fractions[this->EndPiece-this->StartPiece] == 0)
|
||
|
{
|
||
|
fractions[this->EndPiece-this->StartPiece] = 1;
|
||
|
}
|
||
|
for(i=this->StartPiece; i < this->EndPiece; ++i)
|
||
|
{
|
||
|
int index = i-this->StartPiece;
|
||
|
fractions[index+1] = fractions[index+1] / fractions[this->EndPiece-this->StartPiece];
|
||
|
}
|
||
|
|
||
|
// Read the data needed from each piece.
|
||
|
for(i=this->StartPiece; (i < this->EndPiece && !this->AbortExecute &&
|
||
|
!this->DataError); ++i)
|
||
|
{
|
||
|
// Set the range of progress for this piece.
|
||
|
this->SetProgressRange(progressRange, i-this->StartPiece, fractions);
|
||
|
|
||
|
if(!this->Superclass::ReadPieceData(i))
|
||
|
{
|
||
|
// An error occurred while reading the piece.
|
||
|
this->DataError = 1;
|
||
|
}
|
||
|
this->SetupNextPiece();
|
||
|
}
|
||
|
|
||
|
delete [] fractions;
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
void vtkXMLUnstructuredDataReader::SetupPieces(int numPieces)
|
||
|
{
|
||
|
this->Superclass::SetupPieces(numPieces);
|
||
|
this->NumberOfPoints = new vtkIdType[numPieces];
|
||
|
this->PointElements = new vtkXMLDataElement*[numPieces];
|
||
|
for(int i=0;i < numPieces; ++i)
|
||
|
{
|
||
|
this->PointElements[i] = 0;
|
||
|
this->NumberOfPoints[i] = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
void vtkXMLUnstructuredDataReader::DestroyPieces()
|
||
|
{
|
||
|
delete [] this->PointElements;
|
||
|
delete [] this->NumberOfPoints;
|
||
|
this->PointElements = 0;
|
||
|
this->NumberOfPoints = 0;
|
||
|
this->Superclass::DestroyPieces();
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
vtkIdType vtkXMLUnstructuredDataReader::GetNumberOfPoints()
|
||
|
{
|
||
|
return this->TotalNumberOfPoints;
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
vtkIdType vtkXMLUnstructuredDataReader::GetNumberOfCells()
|
||
|
{
|
||
|
return this->TotalNumberOfCells;
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
vtkIdType vtkXMLUnstructuredDataReader::GetNumberOfPointsInPiece(int piece)
|
||
|
{
|
||
|
return this->NumberOfPoints[piece];
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Note that any changes (add or removing information) made to this method
|
||
|
// should be replicated in CopyOutputInformation
|
||
|
void vtkXMLUnstructuredDataReader::SetupOutputInformation(vtkInformation *outInfo)
|
||
|
{
|
||
|
this->Superclass::SetupOutputInformation(outInfo);
|
||
|
|
||
|
// Set the maximum number of pieces that can be provided by this
|
||
|
// reader.
|
||
|
outInfo->Set(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES(),
|
||
|
this->NumberOfPieces);
|
||
|
}
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
void vtkXMLUnstructuredDataReader::CopyOutputInformation(vtkInformation *outInfo, int port)
|
||
|
{
|
||
|
this->Superclass::CopyOutputInformation(outInfo, port);
|
||
|
outInfo->CopyEntry( this->GetExecutive()->GetOutputInformation( port ),
|
||
|
vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES() );
|
||
|
}
|
||
|
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
void vtkXMLUnstructuredDataReader::SetupOutputData()
|
||
|
{
|
||
|
this->Superclass::SetupOutputData();
|
||
|
|
||
|
// Create the points array.
|
||
|
vtkPoints* points = vtkPoints::New();
|
||
|
|
||
|
// Use the configuration of the first piece since all are the same.
|
||
|
vtkXMLDataElement* ePoints = this->PointElements[0];
|
||
|
if (ePoints)
|
||
|
{
|
||
|
// Non-zero volume.
|
||
|
vtkDataArray* a = this->CreateDataArray(ePoints->GetNestedElement(0));
|
||
|
if (a)
|
||
|
{
|
||
|
// Allocate the points array.
|
||
|
a->SetNumberOfTuples( this->GetNumberOfPoints() );
|
||
|
points->SetData(a);
|
||
|
a->Delete();
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
this->DataError = 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
this->GetOutputAsPointSet()->SetPoints(points);
|
||
|
points->Delete();
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
int vtkXMLUnstructuredDataReader::ReadPiece(vtkXMLDataElement* ePiece)
|
||
|
{
|
||
|
if(!this->Superclass::ReadPiece(ePiece))
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
if(!ePiece->GetScalarAttribute("NumberOfPoints",
|
||
|
this->NumberOfPoints[this->Piece]))
|
||
|
{
|
||
|
vtkErrorMacro("Piece " << this->Piece
|
||
|
<< " is missing its NumberOfPoints attribute.");
|
||
|
this->NumberOfPoints[this->Piece] = 0;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// Find the Points element in the piece.
|
||
|
int i;
|
||
|
this->PointElements[this->Piece] = 0;
|
||
|
for(i=0; i < ePiece->GetNumberOfNestedElements(); ++i)
|
||
|
{
|
||
|
vtkXMLDataElement* eNested = ePiece->GetNestedElement(i);
|
||
|
if(strcmp(eNested->GetName(), "Points") == 0)
|
||
|
{
|
||
|
// make sure the XML file is somehow valid:
|
||
|
if( (this->NumberOfTimeSteps > 0 && eNested->GetNumberOfNestedElements() >= 1) ||
|
||
|
(this->NumberOfTimeSteps == 0 && eNested->GetNumberOfNestedElements() == 1))
|
||
|
{
|
||
|
this->PointElements[this->Piece] = eNested;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// If there are some points, we require a Points element.
|
||
|
if(!this->PointElements[this->Piece] &&
|
||
|
(this->NumberOfPoints[this->Piece] > 0))
|
||
|
{
|
||
|
vtkErrorMacro("A piece is missing its Points element "
|
||
|
"or element does not have exactly 1 array.");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
int vtkXMLUnstructuredDataReader::ReadPieceData()
|
||
|
{
|
||
|
// The amount of data read by the superclass's ReadPieceData comes
|
||
|
// from point/cell data (we read point specifications here).
|
||
|
vtkIdType superclassPieceSize =
|
||
|
(this->NumberOfPointArrays*this->GetNumberOfPointsInPiece(this->Piece)+
|
||
|
this->NumberOfCellArrays*this->GetNumberOfCellsInPiece(this->Piece));
|
||
|
|
||
|
// Total amount of data in this piece comes from point/cell data
|
||
|
// arrays and the point specifications themselves.
|
||
|
vtkIdType totalPieceSize =
|
||
|
superclassPieceSize + 1*this->GetNumberOfPointsInPiece(this->Piece);
|
||
|
if(totalPieceSize == 0)
|
||
|
{
|
||
|
totalPieceSize = 1;
|
||
|
}
|
||
|
|
||
|
// Split the progress range based on the approximate fraction of
|
||
|
// data that will be read by each step in this method.
|
||
|
float progressRange[2] = {0,0};
|
||
|
this->GetProgressRange(progressRange);
|
||
|
float fractions[3] =
|
||
|
{
|
||
|
0,
|
||
|
float(superclassPieceSize)/totalPieceSize,
|
||
|
1
|
||
|
};
|
||
|
|
||
|
// Set the range of progress for the superclass.
|
||
|
this->SetProgressRange(progressRange, 0, fractions);
|
||
|
|
||
|
// Let the superclass read its data.
|
||
|
if(!this->Superclass::ReadPieceData())
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
vtkPointSet* output = this->GetOutputAsPointSet();
|
||
|
|
||
|
// Set the range of progress for the Points.
|
||
|
this->SetProgressRange(progressRange, 1, fractions);
|
||
|
|
||
|
// Read the points array.
|
||
|
vtkXMLDataElement* ePoints = this->PointElements[this->Piece];
|
||
|
if(ePoints)
|
||
|
{
|
||
|
for(int i=0;(i < ePoints->GetNumberOfNestedElements() &&
|
||
|
!this->AbortExecute);++i)
|
||
|
{
|
||
|
vtkXMLDataElement* eNested = ePoints->GetNestedElement(i);
|
||
|
assert( strcmp(eNested->GetName(), "DataArray") == 0 );
|
||
|
int needToRead = this->PointsNeedToReadTimeStep(eNested);
|
||
|
if( needToRead )
|
||
|
{
|
||
|
// Read the array.
|
||
|
if(!this->ReadArrayForPoints(eNested, output->GetPoints()->GetData()))
|
||
|
{
|
||
|
vtkErrorMacro("Cannot read points array from " << ePoints->GetName()
|
||
|
<< " in piece " << this->Piece
|
||
|
<< ". The data array in the element may be too short.");
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
int vtkXMLUnstructuredDataReader::ReadCellArray(vtkIdType numberOfCells,
|
||
|
vtkIdType totalNumberOfCells,
|
||
|
vtkXMLDataElement* eCells,
|
||
|
vtkCellArray* outCells)
|
||
|
{
|
||
|
if(numberOfCells <= 0)
|
||
|
{
|
||
|
return 1;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
if(!eCells)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Split progress range into 1/5 for offsets array and 4/5 for
|
||
|
// connectivity array. This assumes an average of 4 points per
|
||
|
// cell. Unfortunately, we cannot know the length of the
|
||
|
// connectivity array ahead of time to calculate the real fraction.
|
||
|
float progressRange[2] = {0,0};
|
||
|
this->GetProgressRange(progressRange);
|
||
|
float fractions[3] = {0, 0.2, 1};
|
||
|
|
||
|
// Set range of progress for offsets array.
|
||
|
this->SetProgressRange(progressRange, 0, fractions);
|
||
|
|
||
|
// Read the cell offsets.
|
||
|
vtkXMLDataElement* eOffsets = this->FindDataArrayWithName(eCells, "offsets");
|
||
|
if(!eOffsets)
|
||
|
{
|
||
|
vtkErrorMacro("Cannot read cell offsets from " << eCells->GetName()
|
||
|
<< " in piece " << this->Piece
|
||
|
<< " because the \"offsets\" array could not be found.");
|
||
|
return 0;
|
||
|
}
|
||
|
vtkDataArray* c1 = this->CreateDataArray(eOffsets);
|
||
|
if(!c1 || (c1->GetNumberOfComponents() != 1))
|
||
|
{
|
||
|
vtkErrorMacro("Cannot read cell offsets from " << eCells->GetName()
|
||
|
<< " in piece " << this->Piece
|
||
|
<< " because the \"offsets\" array could not be created"
|
||
|
<< " with one component.");
|
||
|
return 0;
|
||
|
}
|
||
|
c1->SetNumberOfTuples(numberOfCells);
|
||
|
if(!this->ReadData(eOffsets, c1->GetVoidPointer(0), c1->GetDataType(),
|
||
|
0, numberOfCells))
|
||
|
{
|
||
|
vtkErrorMacro("Cannot read cell offsets from " << eCells->GetName()
|
||
|
<< " in piece " << this->Piece
|
||
|
<< " because the \"offsets\" array is not long enough.");
|
||
|
return 0;
|
||
|
}
|
||
|
vtkIdTypeArray* cellOffsets = this->ConvertToIdTypeArray(c1);
|
||
|
if(!cellOffsets)
|
||
|
{
|
||
|
vtkErrorMacro("Cannot read cell offsets from " << eCells->GetName()
|
||
|
<< " in piece " << this->Piece
|
||
|
<< " because the \"offsets\" array could not be"
|
||
|
<< " converted to a vtkIdTypeArray.");
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// Check the contents of the cell offsets array.
|
||
|
vtkIdType* coffset = cellOffsets->GetPointer(0);
|
||
|
vtkIdType lastOffset = 0;
|
||
|
vtkIdType i;
|
||
|
for(i=0; i < numberOfCells; ++i)
|
||
|
{
|
||
|
if(coffset[i] <= lastOffset)
|
||
|
{
|
||
|
vtkErrorMacro("Cannot read cell connectivity from " << eCells->GetName()
|
||
|
<< " in piece " << this->Piece
|
||
|
<< " because the \"offsets\" array is"
|
||
|
<< " not monotonically increasing or starts with a"
|
||
|
<< " value less than 1.");
|
||
|
cellOffsets->Delete();
|
||
|
return 0;
|
||
|
}
|
||
|
lastOffset = coffset[i];
|
||
|
}
|
||
|
|
||
|
// Set range of progress for connectivity array.
|
||
|
this->SetProgressRange(progressRange, 1, fractions);
|
||
|
|
||
|
// Read the cell point connectivity array.
|
||
|
vtkIdType cpLength = cellOffsets->GetValue(numberOfCells-1);
|
||
|
vtkXMLDataElement* eConn = this->FindDataArrayWithName(eCells, "connectivity");
|
||
|
if(!eConn)
|
||
|
{
|
||
|
vtkErrorMacro("Cannot read cell connectivity from " << eCells->GetName()
|
||
|
<< " in piece " << this->Piece
|
||
|
<< " because the \"connectivity\" array could not be found.");
|
||
|
cellOffsets->Delete();
|
||
|
return 0;
|
||
|
}
|
||
|
vtkDataArray* c0 = this->CreateDataArray(eConn);
|
||
|
if(!c0 || (c0->GetNumberOfComponents() != 1))
|
||
|
{
|
||
|
vtkErrorMacro("Cannot read cell connectivity from " << eCells->GetName()
|
||
|
<< " in piece " << this->Piece
|
||
|
<< " because the \"connectivity\" array could not be created"
|
||
|
<< " with one component.");
|
||
|
cellOffsets->Delete();
|
||
|
return 0;
|
||
|
}
|
||
|
c0->SetNumberOfTuples(cpLength);
|
||
|
if(!this->ReadData(eConn, c0->GetVoidPointer(0), c0->GetDataType(),
|
||
|
0, cpLength))
|
||
|
{
|
||
|
vtkErrorMacro("Cannot read cell connectivity from " << eCells->GetName()
|
||
|
<< " in piece " << this->Piece
|
||
|
<< " because the \"connectivity\" array is not long enough.");
|
||
|
cellOffsets->Delete();
|
||
|
return 0;
|
||
|
}
|
||
|
vtkIdTypeArray* cellPoints = this->ConvertToIdTypeArray(c0);
|
||
|
if(!cellPoints)
|
||
|
{
|
||
|
vtkErrorMacro("Cannot read cell connectivity from " << eCells->GetName()
|
||
|
<< " in piece " << this->Piece
|
||
|
<< " because the \"connectivity\" array could not be"
|
||
|
<< " converted to a vtkIdTypeArray.");
|
||
|
cellOffsets->Delete();
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
// Allocate memory in the output connectivity array.
|
||
|
vtkIdType curSize = 0;
|
||
|
if(outCells->GetData())
|
||
|
{
|
||
|
curSize = outCells->GetData()->GetNumberOfTuples();
|
||
|
}
|
||
|
vtkIdType newSize = curSize+numberOfCells+cellPoints->GetNumberOfTuples();
|
||
|
vtkIdType* cptr = outCells->WritePointer(totalNumberOfCells, newSize);
|
||
|
cptr += curSize;
|
||
|
|
||
|
// Copy the connectivity data.
|
||
|
vtkIdType previousOffset = 0;
|
||
|
for(i=0; i < numberOfCells; ++i)
|
||
|
{
|
||
|
vtkIdType length = cellOffsets->GetValue(i)-previousOffset;
|
||
|
*cptr++ = length;
|
||
|
vtkIdType* sptr = cellPoints->GetPointer(previousOffset);
|
||
|
// Copy the point indices, but increment them for the appended
|
||
|
// version's index.
|
||
|
vtkIdType j;
|
||
|
for(j=0;j < length; ++j)
|
||
|
{
|
||
|
cptr[j] = sptr[j]+this->StartPoint;
|
||
|
}
|
||
|
cptr += length;
|
||
|
previousOffset += length;
|
||
|
}
|
||
|
|
||
|
cellPoints->Delete();
|
||
|
cellOffsets->Delete();
|
||
|
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
int vtkXMLUnstructuredDataReader::ReadArrayForPoints(vtkXMLDataElement* da,
|
||
|
vtkDataArray* outArray)
|
||
|
{
|
||
|
vtkIdType startPoint = this->StartPoint;
|
||
|
vtkIdType numPoints = this->NumberOfPoints[this->Piece];
|
||
|
vtkIdType components = outArray->GetNumberOfComponents();
|
||
|
return this->ReadData(da, outArray->GetVoidPointer(startPoint*components),
|
||
|
outArray->GetDataType(), 0, numPoints*components);
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
int vtkXMLUnstructuredDataReader::PointsNeedToReadTimeStep(vtkXMLDataElement *eNested)
|
||
|
{
|
||
|
// Easy case no timestep:
|
||
|
int numTimeSteps = eNested->GetVectorAttribute("TimeStep",
|
||
|
this->NumberOfTimeSteps, this->TimeSteps);
|
||
|
assert( numTimeSteps <= this->NumberOfTimeSteps );
|
||
|
if (!numTimeSteps && !this->NumberOfTimeSteps)
|
||
|
{
|
||
|
assert( this->PointsTimeStep == -1 ); //No timestep in this file
|
||
|
return 1;
|
||
|
}
|
||
|
// else TimeStep was specified but no TimeValues associated were found
|
||
|
assert( this->NumberOfTimeSteps );
|
||
|
|
||
|
// case numTimeSteps > 1
|
||
|
int isCurrentTimeInArray =
|
||
|
vtkXMLReader::IsTimeStepInArray(this->CurrentTimeStep, this->TimeSteps, numTimeSteps);
|
||
|
if( !isCurrentTimeInArray && numTimeSteps)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
// we know that time steps are specified and that CurrentTimeStep is in the array
|
||
|
// we need to figure out if we need to read the array or if it was forwarded
|
||
|
// Need to check the current 'offset'
|
||
|
unsigned long offset;
|
||
|
if( eNested->GetScalarAttribute("offset", offset) )
|
||
|
{
|
||
|
if( this->PointsOffset != offset )
|
||
|
{
|
||
|
// save the pointsOffset we are about to read
|
||
|
assert( this->PointsTimeStep == -1 ); //cannot have mixture of binary and appended
|
||
|
this->PointsOffset = offset;
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// No offset is specified this is a binary file
|
||
|
// First thing to check if numTimeSteps == 0:
|
||
|
if( !numTimeSteps && this->NumberOfTimeSteps && this->PointsTimeStep == -1)
|
||
|
{
|
||
|
// Update last PointsTimeStep read
|
||
|
this->PointsTimeStep = this->CurrentTimeStep;
|
||
|
return 1;
|
||
|
}
|
||
|
int isLastTimeInArray =
|
||
|
vtkXMLReader::IsTimeStepInArray(this->PointsTimeStep, this->TimeSteps, numTimeSteps);
|
||
|
// If no time is specified or if time is specified and match then read
|
||
|
if (isCurrentTimeInArray && !isLastTimeInArray)
|
||
|
{
|
||
|
// CurrentTimeStep is in TimeSteps but Last is not := need to read
|
||
|
// Update last PointsTimeStep read
|
||
|
this->PointsTimeStep = this->CurrentTimeStep;
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
// all other cases we don't need to read:
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
//----------------------------------------------------------------------------
|
||
|
// Returns true if we need to read the data for the current time step
|
||
|
int vtkXMLUnstructuredDataReader::CellsNeedToReadTimeStep(vtkXMLDataElement *eNested,
|
||
|
int &cellstimestep, unsigned long &cellsoffset)
|
||
|
{
|
||
|
// Easy case no timestep:
|
||
|
int numTimeSteps = eNested->GetVectorAttribute("TimeStep",
|
||
|
this->NumberOfTimeSteps, this->TimeSteps);
|
||
|
assert( numTimeSteps <= this->NumberOfTimeSteps );
|
||
|
if (!numTimeSteps && !this->NumberOfTimeSteps)
|
||
|
{
|
||
|
assert( cellstimestep == -1 ); //No timestep in this file
|
||
|
return 1;
|
||
|
}
|
||
|
// else TimeStep was specified but no TimeValues associated were found
|
||
|
assert( !this->NumberOfTimeSteps );
|
||
|
|
||
|
// case numTimeSteps > 1
|
||
|
int isCurrentTimeInArray =
|
||
|
vtkXMLReader::IsTimeStepInArray(this->CurrentTimeStep, this->TimeSteps, numTimeSteps);
|
||
|
if( !isCurrentTimeInArray && numTimeSteps)
|
||
|
{
|
||
|
return 0;
|
||
|
}
|
||
|
// we know that time steps are specified and that CurrentTimeStep is in the array
|
||
|
// we need to figure out if we need to read the array or if it was forwarded
|
||
|
// Need to check the current 'offset'
|
||
|
unsigned long offset;
|
||
|
if( eNested->GetScalarAttribute("offset", offset) )
|
||
|
{
|
||
|
if( cellsoffset != offset )
|
||
|
{
|
||
|
// save the cellsOffset we are about to read
|
||
|
assert( cellstimestep == -1 ); //cannot have mixture of binary and appended
|
||
|
cellsoffset = offset;
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// No offset is specified this is a binary file
|
||
|
// First thing to check if numTimeSteps == 0:
|
||
|
if( !numTimeSteps && this->NumberOfTimeSteps && cellstimestep == -1)
|
||
|
{
|
||
|
// Update last PointsTimeStep read
|
||
|
cellstimestep = this->CurrentTimeStep;
|
||
|
return 1;
|
||
|
}
|
||
|
int isLastTimeInArray =
|
||
|
vtkXMLReader::IsTimeStepInArray(cellstimestep, this->TimeSteps, numTimeSteps);
|
||
|
// If no time is specified or if time is specified and match then read
|
||
|
if (isCurrentTimeInArray && !isLastTimeInArray)
|
||
|
{
|
||
|
// CurrentTimeStep is in TimeSteps but Last is not := need to read
|
||
|
// Update last cellstimestep read
|
||
|
cellstimestep = this->CurrentTimeStep;
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
// all other cases we don't need to read:
|
||
|
return 0;
|
||
|
}
|
||
|
|