/*========================================================================= 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(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(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; } }