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.
511 lines
15 KiB
511 lines
15 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkXMLPDataReader.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 "vtkXMLPDataReader.h"
|
|
|
|
#include "vtkCallbackCommand.h"
|
|
#include "vtkCellData.h"
|
|
#include "vtkDataArray.h"
|
|
#include "vtkDataArraySelection.h"
|
|
#include "vtkDataSet.h"
|
|
#include "vtkPointData.h"
|
|
#include "vtkXMLDataElement.h"
|
|
#include "vtkXMLDataReader.h"
|
|
#include "vtkInformationVector.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkStreamingDemandDrivenPipeline.h"
|
|
|
|
vtkCxxRevisionMacro(vtkXMLPDataReader, "$Revision: 1.17 $");
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkXMLPDataReader::vtkXMLPDataReader()
|
|
{
|
|
this->GhostLevel = 0;
|
|
|
|
this->NumberOfPieces = 0;
|
|
|
|
this->PieceElements = 0;
|
|
this->PieceReaders = 0;
|
|
this->CanReadPieceFlag = 0;
|
|
|
|
this->PathName = 0;
|
|
|
|
// Setup a callback for the internal serial readers to report
|
|
// progress.
|
|
this->PieceProgressObserver = vtkCallbackCommand::New();
|
|
this->PieceProgressObserver->SetCallback(&vtkXMLPDataReader::PieceProgressCallbackFunction);
|
|
this->PieceProgressObserver->SetClientData(this);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkXMLPDataReader::~vtkXMLPDataReader()
|
|
{
|
|
if(this->NumberOfPieces)
|
|
{
|
|
this->DestroyPieces();
|
|
}
|
|
if(this->PathName)
|
|
{
|
|
delete [] this->PathName;
|
|
}
|
|
this->PieceProgressObserver->Delete();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLPDataReader::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os, indent);
|
|
os << indent << "NumberOfPieces: " << this->NumberOfPieces << "\n";
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkDataSet* vtkXMLPDataReader::GetPieceInputAsDataSet(int piece)
|
|
{
|
|
vtkXMLDataReader* reader = this->PieceReaders[piece];
|
|
if(!reader)
|
|
{
|
|
return 0;
|
|
}
|
|
if(reader->GetNumberOfOutputPorts() < 1)
|
|
{
|
|
return 0;
|
|
}
|
|
return static_cast<vtkDataSet*>(reader->GetExecutive()->GetOutputData(0));
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLPDataReader::SetupOutputData()
|
|
{
|
|
this->Superclass::SetupOutputData();
|
|
|
|
// Setup the output arrays.
|
|
vtkXMLDataElement* ePointData = this->PPointDataElement;
|
|
vtkXMLDataElement* eCellData = this->PCellDataElement;
|
|
vtkPointData* pointData = this->GetOutputAsDataSet(0)->GetPointData();
|
|
vtkCellData* cellData = this->GetOutputAsDataSet(0)->GetCellData();
|
|
|
|
// Get the size of the output arrays.
|
|
unsigned long pointTuples = this->GetNumberOfPoints();
|
|
unsigned long cellTuples = this->GetNumberOfCells();
|
|
|
|
// Allocate data in the arrays.
|
|
int i;
|
|
if(ePointData)
|
|
{
|
|
for(i=0;i < ePointData->GetNumberOfNestedElements();++i)
|
|
{
|
|
vtkXMLDataElement* eNested = ePointData->GetNestedElement(i);
|
|
if(this->PointDataArrayIsEnabled(eNested))
|
|
{
|
|
vtkDataArray* array = this->CreateDataArray(eNested);
|
|
if(array)
|
|
{
|
|
array->SetNumberOfTuples(pointTuples);
|
|
pointData->AddArray(array);
|
|
array->Delete();
|
|
}
|
|
else
|
|
{
|
|
this->DataError = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(eCellData)
|
|
{
|
|
for(i = 0; i < eCellData->GetNumberOfNestedElements(); i++)
|
|
{
|
|
vtkXMLDataElement* eNested = eCellData->GetNestedElement(i);
|
|
if(this->CellDataArrayIsEnabled(eNested))
|
|
{
|
|
vtkDataArray* array = this->CreateDataArray(eNested);
|
|
if(array)
|
|
{
|
|
array->SetNumberOfTuples(cellTuples);
|
|
cellData->AddArray(array);
|
|
array->Delete();
|
|
}
|
|
else
|
|
{
|
|
this->DataError = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Setup attribute indices for the point data and cell data.
|
|
this->ReadAttributeIndices(ePointData, pointData);
|
|
this->ReadAttributeIndices(eCellData, cellData);
|
|
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkXMLPDataReader::ReadXMLInformation()
|
|
{
|
|
// First setup the filename components.
|
|
this->SplitFileName();
|
|
|
|
// Now proceed with reading the information.
|
|
return this->Superclass::ReadXMLInformation();
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Note that any changes (add or removing information) made to this method
|
|
// should be replicated in CopyOutputInformation
|
|
void vtkXMLPDataReader::SetupOutputInformation(vtkInformation *outInfo)
|
|
{
|
|
if (this->InformationError)
|
|
{
|
|
vtkErrorMacro("Should not still be processing output information if have set InformationError");
|
|
return;
|
|
}
|
|
|
|
// Initialize DataArraySelections to anable all that are present
|
|
this->SetDataArraySelections(this->PPointDataElement, this->PointDataArraySelection);
|
|
this->SetDataArraySelections(this->PCellDataElement, this->CellDataArraySelection);
|
|
|
|
// Setup the Field Information for PointData. We only need the
|
|
// information from one piece because all pieces have the same set of arrays.
|
|
vtkInformationVector *infoVector = NULL;
|
|
if (!this->SetFieldDataInfo(this->PPointDataElement,
|
|
vtkDataObject::FIELD_ASSOCIATION_POINTS, this->GetNumberOfPoints(), infoVector))
|
|
{
|
|
return;
|
|
}
|
|
if (infoVector)
|
|
{
|
|
outInfo->Set(vtkDataObject::POINT_DATA_VECTOR(), infoVector);
|
|
infoVector->Delete();
|
|
}
|
|
|
|
// now the Cell data
|
|
infoVector = NULL;
|
|
if (!this->SetFieldDataInfo(this->PCellDataElement,
|
|
vtkDataObject::FIELD_ASSOCIATION_CELLS, this->GetNumberOfCells(), infoVector))
|
|
{
|
|
return;
|
|
}
|
|
if (infoVector)
|
|
{
|
|
outInfo->Set(vtkDataObject::CELL_DATA_VECTOR(), infoVector);
|
|
infoVector->Delete();
|
|
}
|
|
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLPDataReader::CopyOutputInformation(vtkInformation *outInfo, int port)
|
|
{
|
|
vtkInformation *localInfo = this->GetExecutive()->GetOutputInformation( port );
|
|
if ( localInfo->Has(vtkDataObject::POINT_DATA_VECTOR()) )
|
|
{
|
|
outInfo->CopyEntry( localInfo, vtkDataObject::POINT_DATA_VECTOR() );
|
|
}
|
|
if ( localInfo->Has(vtkDataObject::CELL_DATA_VECTOR()) )
|
|
{
|
|
outInfo->CopyEntry( localInfo, vtkDataObject::CELL_DATA_VECTOR() );
|
|
}
|
|
}
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkXMLPDataReader::ReadPrimaryElement(vtkXMLDataElement* ePrimary)
|
|
{
|
|
if(!this->Superclass::ReadPrimaryElement(ePrimary))
|
|
{
|
|
return 0;
|
|
}
|
|
// Read information about the data.
|
|
if(!ePrimary->GetScalarAttribute("GhostLevel", this->GhostLevel))
|
|
{
|
|
this->GhostLevel = 0;
|
|
}
|
|
|
|
// Read information about the pieces.
|
|
this->PPointDataElement = 0;
|
|
this->PCellDataElement = 0;
|
|
int i;
|
|
int numNested = ePrimary->GetNumberOfNestedElements();
|
|
int numPieces = 0;
|
|
for(i=0;i < numNested; ++i)
|
|
{
|
|
vtkXMLDataElement* eNested = ePrimary->GetNestedElement(i);
|
|
if(strcmp(eNested->GetName(), "Piece") == 0)
|
|
{
|
|
++numPieces;
|
|
}
|
|
else if(strcmp(eNested->GetName(), "PPointData") == 0)
|
|
{
|
|
this->PPointDataElement = eNested;
|
|
}
|
|
else if(strcmp(eNested->GetName(), "PCellData") == 0)
|
|
{
|
|
this->PCellDataElement = eNested;
|
|
}
|
|
}
|
|
this->SetupPieces(numPieces);
|
|
int piece = 0;
|
|
for(i=0;i < numNested; ++i)
|
|
{
|
|
vtkXMLDataElement* eNested = ePrimary->GetNestedElement(i);
|
|
if(strcmp(eNested->GetName(), "Piece") == 0)
|
|
{
|
|
if(!this->ReadPiece(eNested, piece++))
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLPDataReader::SetupPieces(int numPieces)
|
|
{
|
|
if(this->NumberOfPieces)
|
|
{
|
|
this->DestroyPieces();
|
|
}
|
|
this->NumberOfPieces = numPieces;
|
|
this->PieceElements = new vtkXMLDataElement*[this->NumberOfPieces];
|
|
this->PieceReaders = new vtkXMLDataReader*[this->NumberOfPieces];
|
|
this->CanReadPieceFlag = new int[this->NumberOfPieces];
|
|
int i;
|
|
for(i=0;i < this->NumberOfPieces;++i)
|
|
{
|
|
this->PieceElements[i] = 0;
|
|
this->PieceReaders[i] = 0;
|
|
this->CanReadPieceFlag[i] = 0;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLPDataReader::DestroyPieces()
|
|
{
|
|
int i;
|
|
for(i=0;i < this->NumberOfPieces;++i)
|
|
{
|
|
if(this->PieceReaders[i])
|
|
{
|
|
this->PieceReaders[i]->RemoveObserver(this->PieceProgressObserver);
|
|
this->PieceReaders[i]->Delete();
|
|
}
|
|
}
|
|
delete [] this->PieceElements;
|
|
delete [] this->CanReadPieceFlag;
|
|
delete [] this->PieceReaders;
|
|
this->PieceElements = 0;
|
|
this->PieceReaders = 0;
|
|
this->NumberOfPieces = 0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkXMLPDataReader::ReadPiece(vtkXMLDataElement* ePiece, int index)
|
|
{
|
|
this->Piece = index;
|
|
return this->ReadPiece(ePiece);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkXMLPDataReader::ReadPiece(vtkXMLDataElement* ePiece)
|
|
{
|
|
this->PieceElements[this->Piece] = ePiece;
|
|
|
|
const char* fileName = ePiece->GetAttribute("Source");
|
|
if(!fileName)
|
|
{
|
|
vtkErrorMacro("Piece " << this->Piece << " has no Source attribute.");
|
|
return 0;
|
|
}
|
|
|
|
// The file name is relative to the summary file. Convert it to
|
|
// something we can use.
|
|
char *pieceFileName = this->CreatePieceFileName(fileName);
|
|
|
|
vtkXMLDataReader* reader = this->CreatePieceReader();
|
|
this->PieceReaders[this->Piece] = reader;
|
|
this->PieceReaders[this->Piece]->AddObserver(vtkCommand::ProgressEvent,
|
|
this->PieceProgressObserver);
|
|
reader->SetFileName(pieceFileName);
|
|
|
|
delete [] pieceFileName;
|
|
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkXMLPDataReader::ReadPieceData(int index)
|
|
{
|
|
this->Piece = index;
|
|
|
|
// We need data, make sure the piece can be read.
|
|
if(!this->CanReadPiece(this->Piece))
|
|
{
|
|
vtkErrorMacro("File for piece " << this->Piece << " cannot be read.");
|
|
return 0;
|
|
}
|
|
|
|
// Actually read the data.
|
|
this->PieceReaders[this->Piece]->SetAbortExecute(0);
|
|
vtkDataArraySelection* pds =
|
|
this->PieceReaders[this->Piece]->GetPointDataArraySelection();
|
|
vtkDataArraySelection* cds =
|
|
this->PieceReaders[this->Piece]->GetCellDataArraySelection();
|
|
pds->CopySelections(this->PointDataArraySelection);
|
|
cds->CopySelections(this->CellDataArraySelection);
|
|
return this->ReadPieceData();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkXMLPDataReader::ReadPieceData()
|
|
{
|
|
vtkDataSet* input = this->GetPieceInputAsDataSet(this->Piece);
|
|
vtkDataSet* output = this->GetOutputAsDataSet(0);
|
|
|
|
// copy any field data
|
|
if (input->GetFieldData())
|
|
{
|
|
int i;
|
|
for (i = 0; i < input->GetFieldData()->GetNumberOfArrays(); i++)
|
|
{
|
|
output->GetFieldData()->AddArray( input->GetFieldData()->GetArray(i) );
|
|
}
|
|
}
|
|
|
|
// Copy point data and cell data for this piece.
|
|
int i;
|
|
for(i=0;i < output->GetPointData()->GetNumberOfArrays();++i)
|
|
{
|
|
this->CopyArrayForPoints(input->GetPointData()->GetArray(i),
|
|
output->GetPointData()->GetArray(i));
|
|
}
|
|
for(i=0;i < output->GetCellData()->GetNumberOfArrays();++i)
|
|
{
|
|
this->CopyArrayForCells(input->GetCellData()->GetArray(i),
|
|
output->GetCellData()->GetArray(i));
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkXMLPDataReader::CanReadPiece(int index)
|
|
{
|
|
// If necessary, test whether the piece can be read.
|
|
vtkXMLDataReader* reader = this->PieceReaders[index];
|
|
if(reader && !this->CanReadPieceFlag[index])
|
|
{
|
|
if(reader->CanReadFile(reader->GetFileName()))
|
|
{
|
|
// We can read the piece. Save result to avoid later repeat of
|
|
// test.
|
|
this->CanReadPieceFlag[index] = 1;
|
|
}
|
|
else
|
|
{
|
|
// We cannot read the piece. Destroy the reader to avoid later
|
|
// repeat of test.
|
|
this->PieceReaders[index] = 0;
|
|
reader->Delete();
|
|
}
|
|
}
|
|
|
|
return (this->PieceReaders[index]? 1:0);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
char* vtkXMLPDataReader::CreatePieceFileName(const char* fileName)
|
|
{
|
|
ostrstream fn_with_warning_C4701;
|
|
if(this->PathName)
|
|
{
|
|
fn_with_warning_C4701 << this->PathName;
|
|
}
|
|
fn_with_warning_C4701 << fileName << ends;
|
|
return fn_with_warning_C4701.str();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLPDataReader::SplitFileName()
|
|
{
|
|
if(!this->FileName)
|
|
{
|
|
vtkErrorMacro( << "Need to specify a filename" );
|
|
return;
|
|
}
|
|
|
|
// Pull the PathName component out of the FileName.
|
|
size_t length = strlen(this->FileName);
|
|
char* fileName = new char[length+1];
|
|
strcpy(fileName, this->FileName);
|
|
char* begin = fileName;
|
|
char* end = fileName + length;
|
|
char* s;
|
|
|
|
#if defined(_WIN32)
|
|
// Convert to UNIX-style slashes.
|
|
for(s=begin;s != end;++s) { if(*s == '\\') { *s = '/'; } }
|
|
#endif
|
|
|
|
// Extract the path name up to the last '/'.
|
|
if(this->PathName)
|
|
{
|
|
delete [] this->PathName;
|
|
this->PathName = 0;
|
|
}
|
|
char* rbegin = end-1;
|
|
char* rend = begin-1;
|
|
for(s=rbegin;s != rend;--s)
|
|
{
|
|
if(*s == '/')
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
if(s >= begin)
|
|
{
|
|
length = (s-begin)+1;
|
|
this->PathName = new char[length+1];
|
|
strncpy(this->PathName, this->FileName, length);
|
|
this->PathName[length] = '\0';
|
|
}
|
|
|
|
// Cleanup temporary name.
|
|
delete [] fileName;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLPDataReader::PieceProgressCallbackFunction(vtkObject*, unsigned long,
|
|
void* clientdata, void*)
|
|
{
|
|
reinterpret_cast<vtkXMLPDataReader*>(clientdata)->PieceProgressCallback();
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLPDataReader::PieceProgressCallback()
|
|
{
|
|
float width = this->ProgressRange[1]-this->ProgressRange[0];
|
|
float pieceProgress = this->PieceReaders[this->Piece]->GetProgress();
|
|
float progress = this->ProgressRange[0] + pieceProgress*width;
|
|
this->UpdateProgressDiscrete(progress);
|
|
if(this->AbortExecute)
|
|
{
|
|
this->PieceReaders[this->Piece]->SetAbortExecute(1);
|
|
}
|
|
}
|
|
|