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.
402 lines
13 KiB
402 lines
13 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkXMLPUnstructuredDataReader.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 "vtkXMLPUnstructuredDataReader.h"
|
|
#include "vtkXMLDataElement.h"
|
|
#include "vtkXMLUnstructuredDataReader.h"
|
|
#include "vtkPointSet.h"
|
|
#include "vtkCellArray.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkStreamingDemandDrivenPipeline.h"
|
|
|
|
vtkCxxRevisionMacro(vtkXMLPUnstructuredDataReader, "$Revision: 1.18 $");
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkXMLPUnstructuredDataReader::vtkXMLPUnstructuredDataReader()
|
|
{
|
|
this->TotalNumberOfPoints = 0;
|
|
this->TotalNumberOfCells = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkXMLPUnstructuredDataReader::~vtkXMLPUnstructuredDataReader()
|
|
{
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLPUnstructuredDataReader::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os, indent);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkPointSet* vtkXMLPUnstructuredDataReader::GetOutputAsPointSet()
|
|
{
|
|
return vtkPointSet::SafeDownCast( this->GetOutputDataObject(0) );
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkPointSet* vtkXMLPUnstructuredDataReader::GetPieceInputAsPointSet(int piece)
|
|
{
|
|
vtkXMLDataReader* reader = this->PieceReaders[piece];
|
|
if(!reader) { return 0; }
|
|
if(reader->GetNumberOfOutputPorts() < 1) { return 0; }
|
|
return static_cast<vtkPointSet*>(reader->GetExecutive()->GetOutputData(0));
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLPUnstructuredDataReader::SetupOutputTotals()
|
|
{
|
|
int i;
|
|
this->TotalNumberOfPoints = 0;
|
|
for(i=this->StartPiece; i < this->EndPiece; ++i)
|
|
{
|
|
if(this->PieceReaders[i])
|
|
{
|
|
this->TotalNumberOfPoints += this->PieceReaders[i]->GetNumberOfPoints();
|
|
}
|
|
}
|
|
this->StartPoint = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLPUnstructuredDataReader::SetupNextPiece()
|
|
{
|
|
if(this->PieceReaders[this->Piece])
|
|
{
|
|
this->StartPoint += this->PieceReaders[this->Piece]->GetNumberOfPoints();
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkIdType vtkXMLPUnstructuredDataReader::GetNumberOfPoints()
|
|
{
|
|
return this->TotalNumberOfPoints;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkIdType vtkXMLPUnstructuredDataReader::GetNumberOfCells()
|
|
{
|
|
return this->TotalNumberOfCells;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkIdType vtkXMLPUnstructuredDataReader::GetNumberOfPointsInPiece(int piece)
|
|
{
|
|
if(this->PieceReaders[piece])
|
|
{
|
|
return this->PieceReaders[piece]->GetNumberOfPoints();
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkIdType vtkXMLPUnstructuredDataReader::GetNumberOfCellsInPiece(int piece)
|
|
{
|
|
if(this->PieceReaders[piece])
|
|
{
|
|
return this->PieceReaders[piece]->GetNumberOfCells();
|
|
}
|
|
else
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLPUnstructuredDataReader::SetupEmptyOutput()
|
|
{
|
|
// No pieces means no input.
|
|
this->GetOutputAsDataSet(0)->SetUpdateExtent(0, 0);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Note that any changes (add or removing information) made to this method
|
|
// should be replicated in CopyOutputInformation
|
|
void vtkXMLPUnstructuredDataReader::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 vtkXMLPUnstructuredDataReader::CopyOutputInformation(vtkInformation *outInfo, int port)
|
|
{
|
|
this->Superclass::CopyOutputInformation(outInfo, port);
|
|
outInfo->CopyEntry( this->GetExecutive()->GetOutputInformation( port ),
|
|
vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES() );
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLPUnstructuredDataReader::SetupOutputData()
|
|
{
|
|
this->Superclass::SetupOutputData();
|
|
|
|
// Create the points array.
|
|
vtkPoints* points = vtkPoints::New();
|
|
if(this->PPointsElement)
|
|
{
|
|
vtkDataArray* a = this->CreateDataArray(this->PPointsElement->GetNestedElement(0));
|
|
if(a)
|
|
{
|
|
a->SetNumberOfTuples(this->GetNumberOfPoints());
|
|
points->SetData(a);
|
|
a->Delete();
|
|
}
|
|
else
|
|
{
|
|
this->DataError = 1;
|
|
}
|
|
}
|
|
this->GetOutputAsPointSet()->SetPoints(points);
|
|
points->Delete();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLPUnstructuredDataReader::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;
|
|
}
|
|
|
|
// Update the information of the pieces we need.
|
|
int i;
|
|
for(i=this->StartPiece; i < this->EndPiece; ++i)
|
|
{
|
|
if(this->CanReadPiece(i))
|
|
{
|
|
this->PieceReaders[i]->UpdateInformation();
|
|
vtkXMLUnstructuredDataReader* pReader =
|
|
static_cast<vtkXMLUnstructuredDataReader*>(this->PieceReaders[i]);
|
|
pReader->SetupUpdateExtent(0, 1, this->UpdateGhostLevel);
|
|
}
|
|
}
|
|
|
|
// Find the total size of the output.
|
|
this->SetupOutputTotals();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
vtkXMLPUnstructuredDataReader::ReadPrimaryElement(vtkXMLDataElement* ePrimary)
|
|
{
|
|
if(!this->Superclass::ReadPrimaryElement(ePrimary)) { return 0; }
|
|
|
|
// Find the PPoints element.
|
|
this->PPointsElement = 0;
|
|
int i;
|
|
int numNested = ePrimary->GetNumberOfNestedElements();
|
|
for(i=0;i < numNested; ++i)
|
|
{
|
|
vtkXMLDataElement* eNested = ePrimary->GetNestedElement(i);
|
|
if((strcmp(eNested->GetName(), "PPoints") == 0) &&
|
|
(eNested->GetNumberOfNestedElements() == 1))
|
|
{
|
|
this->PPointsElement = eNested;
|
|
}
|
|
}
|
|
|
|
// If PPoints element was not found, we must assume there are 0
|
|
// points. If there are found to be points later, the error will be
|
|
// reported by ReadPieceData.
|
|
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLPUnstructuredDataReader::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;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkXMLPUnstructuredDataReader::ReadPieceData()
|
|
{
|
|
// Use the internal reader to read the piece.
|
|
vtkPointSet* input = this->GetPieceInputAsPointSet(this->Piece);
|
|
input->SetUpdateExtent(0, 1, this->UpdateGhostLevel);
|
|
input->Update();
|
|
|
|
vtkPointSet* output = this->GetOutputAsPointSet();
|
|
|
|
// If there are some points, but no PPoints element, report the
|
|
// error.
|
|
if(!this->PPointsElement && (this->GetNumberOfPoints() > 0))
|
|
{
|
|
vtkErrorMacro("Could not find PPoints element with 1 array.");
|
|
return 0;
|
|
}
|
|
|
|
if (!input->GetPoints())
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// Copy the points array.
|
|
this->CopyArrayForPoints(input->GetPoints()->GetData(),
|
|
output->GetPoints()->GetData());
|
|
|
|
// Let the superclass read the data it wants.
|
|
return this->Superclass::ReadPieceData();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLPUnstructuredDataReader::CopyArrayForPoints(vtkDataArray* inArray,
|
|
vtkDataArray* outArray)
|
|
{
|
|
if(!this->PieceReaders[this->Piece])
|
|
{
|
|
return;
|
|
}
|
|
if (inArray == NULL || outArray == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
vtkIdType numPoints = this->PieceReaders[this->Piece]->GetNumberOfPoints();
|
|
vtkIdType components = outArray->GetNumberOfComponents();
|
|
vtkIdType tupleSize = inArray->GetDataTypeSize()*components;
|
|
memcpy(outArray->GetVoidPointer(this->StartPoint*components),
|
|
inArray->GetVoidPointer(0), numPoints*tupleSize);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLPUnstructuredDataReader::CopyCellArray(vtkIdType totalNumberOfCells,
|
|
vtkCellArray* inCells,
|
|
vtkCellArray* outCells)
|
|
{
|
|
// Allocate memory in the output connectivity array.
|
|
vtkIdType curSize = 0;
|
|
if(outCells->GetData())
|
|
{
|
|
curSize = outCells->GetData()->GetNumberOfTuples();
|
|
}
|
|
vtkIdTypeArray* inData = inCells->GetData();
|
|
vtkIdType newSize = curSize+inData->GetNumberOfTuples();
|
|
vtkIdType* in = inData->GetPointer(0);
|
|
vtkIdType* end = inData->GetPointer(inData->GetNumberOfTuples());
|
|
vtkIdType* out = outCells->WritePointer(totalNumberOfCells, newSize);
|
|
out += curSize;
|
|
|
|
// Copy the connectivity data.
|
|
while(in < end)
|
|
{
|
|
vtkIdType length = *in++;
|
|
*out++ = length;
|
|
// Copy the point indices, but increment them for the appended
|
|
// version's index.
|
|
vtkIdType j;
|
|
for(j=0;j < length; ++j)
|
|
{
|
|
out[j] = in[j]+this->StartPoint;
|
|
}
|
|
in += length;
|
|
out += length;
|
|
}
|
|
}
|
|
|