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.
793 lines
25 KiB
793 lines
25 KiB
/*=========================================================================
|
|
|
|
Program: Visualization Toolkit
|
|
Module: $RCSfile: vtkXMLUnstructuredDataWriter.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 "vtkXMLUnstructuredDataWriter.h"
|
|
|
|
#include "vtkCellArray.h"
|
|
#include "vtkCellData.h"
|
|
#include "vtkDataArray.h"
|
|
#include "vtkDataCompressor.h"
|
|
#include "vtkDataSetAttributes.h"
|
|
#include "vtkErrorCode.h"
|
|
#include "vtkIdTypeArray.h"
|
|
#include "vtkInformation.h"
|
|
#include "vtkInformationVector.h"
|
|
#include "vtkObjectFactory.h"
|
|
#include "vtkPointData.h"
|
|
#include "vtkPointSet.h"
|
|
#include "vtkPoints.h"
|
|
#include "vtkStreamingDemandDrivenPipeline.h"
|
|
#include "vtkUnsignedCharArray.h"
|
|
#define vtkOffsetsManager_DoNotInclude
|
|
#include "vtkOffsetsManagerArray.h"
|
|
#undef vtkOffsetsManager_DoNotInclude
|
|
|
|
#include <assert.h>
|
|
|
|
vtkCxxRevisionMacro(vtkXMLUnstructuredDataWriter, "$Revision: 1.19 $");
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkXMLUnstructuredDataWriter::vtkXMLUnstructuredDataWriter()
|
|
{
|
|
this->NumberOfPieces = 1;
|
|
this->WritePiece = -1;
|
|
this->GhostLevel = 0;
|
|
this->CellPoints = vtkIdTypeArray::New();
|
|
this->CellOffsets = vtkIdTypeArray::New();
|
|
this->CellPoints->SetName("connectivity");
|
|
this->CellOffsets->SetName("offsets");
|
|
|
|
this->CurrentPiece = 0;
|
|
this->FieldDataOM->Allocate(0);
|
|
this->PointsOM = new OffsetsManagerGroup;
|
|
this->PointDataOM = new OffsetsManagerArray;
|
|
this->CellDataOM = new OffsetsManagerArray;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkXMLUnstructuredDataWriter::~vtkXMLUnstructuredDataWriter()
|
|
{
|
|
this->CellPoints->Delete();
|
|
this->CellOffsets->Delete();
|
|
delete this->PointsOM;
|
|
delete this->PointDataOM;
|
|
delete this->CellDataOM;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLUnstructuredDataWriter::PrintSelf(ostream& os, vtkIndent indent)
|
|
{
|
|
this->Superclass::PrintSelf(os,indent);
|
|
os << indent << "NumberOfPieces: " << this->NumberOfPieces << "\n";
|
|
os << indent << "WritePiece: " << this->WritePiece << "\n";
|
|
os << indent << "GhostLevel: " << this->GhostLevel << "\n";
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkPointSet* vtkXMLUnstructuredDataWriter::GetInputAsPointSet()
|
|
{
|
|
return static_cast<vtkPointSet*>(this->Superclass::GetInput());
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkXMLUnstructuredDataWriter::ProcessRequest(vtkInformation* request,
|
|
vtkInformationVector** inputVector,
|
|
vtkInformationVector* outputVector)
|
|
{
|
|
|
|
if(request->Has(vtkStreamingDemandDrivenPipeline::REQUEST_UPDATE_EXTENT()))
|
|
{
|
|
if((this->WritePiece < 0) || (this->WritePiece >= this->NumberOfPieces))
|
|
{
|
|
this->SetInputUpdateExtent(
|
|
this->CurrentPiece, this->NumberOfPieces, this->GhostLevel);
|
|
}
|
|
else
|
|
{
|
|
this->SetInputUpdateExtent(
|
|
this->WritePiece, this->NumberOfPieces, this->GhostLevel);
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
// generate the data
|
|
else if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA()))
|
|
{
|
|
this->SetErrorCode(vtkErrorCode::NoError);
|
|
|
|
if(!this->Stream && !this->FileName)
|
|
{
|
|
this->SetErrorCode(vtkErrorCode::NoFileNameError);
|
|
vtkErrorMacro("The FileName or Stream must be set first.");
|
|
return 0;
|
|
}
|
|
|
|
// We don't want to write more pieces than the pipeline can produce,
|
|
// but we need to preserve the user's requested number of pieces in
|
|
// case the input changes later. If MaximumNumberOfPieces is lower
|
|
// than 1, any number of pieces can be produced by the pipeline.
|
|
vtkInformation* inInfo = inputVector[0]->GetInformationObject(0);
|
|
int numPieces = this->NumberOfPieces;
|
|
int maxPieces =
|
|
inInfo->Get(vtkStreamingDemandDrivenPipeline::MAXIMUM_NUMBER_OF_PIECES());
|
|
if((maxPieces > 0) && (this->NumberOfPieces > maxPieces))
|
|
{
|
|
this->NumberOfPieces = maxPieces;
|
|
}
|
|
|
|
if (this->WritePiece >= 0)
|
|
{
|
|
this->CurrentPiece = this->WritePiece;
|
|
}
|
|
else
|
|
{
|
|
float progressRange[2] = {0,0};
|
|
this->GetProgressRange(progressRange);
|
|
this->SetProgressRange(progressRange, this->CurrentPiece, this->NumberOfPieces);
|
|
}
|
|
|
|
int result = 1;
|
|
if (this->CurrentPiece == 0 && this->CurrentTimeIndex == 0 || this->WritePiece >= 0)
|
|
{
|
|
// We are just starting to write. Do not call
|
|
// UpdateProgressDiscrete because we want a 0 progress callback the
|
|
// first time.
|
|
this->UpdateProgress(0);
|
|
|
|
// Initialize progress range to entire 0..1 range.
|
|
float wholeProgressRange[2] = {0,1};
|
|
this->SetProgressRange(wholeProgressRange, 0, 1);
|
|
|
|
if (!this->OpenFile())
|
|
{
|
|
this->NumberOfPieces = numPieces;
|
|
return 0;
|
|
}
|
|
// Write the file.
|
|
if (!this->StartFile())
|
|
{
|
|
this->NumberOfPieces = numPieces;
|
|
return 0;
|
|
}
|
|
|
|
if (!this->WriteHeader())
|
|
{
|
|
this->NumberOfPieces = numPieces;
|
|
return 0;
|
|
}
|
|
|
|
this->CurrentTimeIndex = 0;
|
|
if( this->DataMode == vtkXMLWriter::Appended && this->FieldDataOM->GetNumberOfElements())
|
|
{
|
|
// Write the field data arrays.
|
|
this->WriteFieldDataAppendedData(this->GetInput()->GetFieldData(),
|
|
this->CurrentTimeIndex, this->FieldDataOM);
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
this->DeletePositionArrays();
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( !(this->UserContinueExecuting == 0)) //if user ask to stop do not try to write a piece
|
|
{
|
|
result = this->WriteAPiece();
|
|
}
|
|
|
|
if((this->WritePiece < 0) || (this->WritePiece >= this->NumberOfPieces))
|
|
{
|
|
// Tell the pipeline to start looping.
|
|
if (this->CurrentPiece == 0)
|
|
{
|
|
request->Set(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING(), 1);
|
|
}
|
|
this->CurrentPiece++;
|
|
}
|
|
|
|
if (this->CurrentPiece == this->NumberOfPieces || this->WritePiece >= 0)
|
|
{
|
|
request->Remove(vtkStreamingDemandDrivenPipeline::CONTINUE_EXECUTING());
|
|
this->CurrentPiece = 0;
|
|
// We are done writting all the pieces, lets loop over time now:
|
|
this->CurrentTimeIndex++;
|
|
|
|
if( this->UserContinueExecuting != 1 )
|
|
{
|
|
if (!this->WriteFooter())
|
|
{
|
|
this->NumberOfPieces = numPieces;
|
|
return 0;
|
|
}
|
|
|
|
if (!this->EndFile())
|
|
{
|
|
this->NumberOfPieces = numPieces;
|
|
return 0;
|
|
}
|
|
|
|
this->CloseFile();
|
|
this->CurrentTimeIndex = 0; // Reset
|
|
}
|
|
}
|
|
this->NumberOfPieces = numPieces;
|
|
|
|
// We have finished writing.
|
|
this->UpdateProgressDiscrete(1);
|
|
return result;
|
|
}
|
|
return this->Superclass::ProcessRequest(request, inputVector, outputVector);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLUnstructuredDataWriter::AllocatePositionArrays()
|
|
{
|
|
this->NumberOfPointsPositions = new unsigned long[this->NumberOfPieces];
|
|
|
|
this->PointsOM->Allocate(this->NumberOfPieces, this->NumberOfTimeSteps);
|
|
this->PointDataOM->Allocate(this->NumberOfPieces);
|
|
this->CellDataOM->Allocate(this->NumberOfPieces);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLUnstructuredDataWriter::DeletePositionArrays()
|
|
{
|
|
delete [] this->NumberOfPointsPositions;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkXMLUnstructuredDataWriter::WriteHeader()
|
|
{
|
|
vtkIndent indent = vtkIndent().GetNextIndent();
|
|
|
|
ostream& os = *(this->Stream);
|
|
|
|
if(!this->WritePrimaryElement(os, indent))
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
this->WriteFieldData(indent.GetNextIndent());
|
|
|
|
if(this->DataMode == vtkXMLWriter::Appended)
|
|
{
|
|
vtkIndent nextIndent = indent.GetNextIndent();
|
|
|
|
this->AllocatePositionArrays();
|
|
|
|
if((this->WritePiece < 0) || (this->WritePiece >= this->NumberOfPieces))
|
|
{
|
|
// Loop over each piece and write its structure.
|
|
int i;
|
|
for(i=0; i < this->NumberOfPieces; ++i)
|
|
{
|
|
// Open the piece's element.
|
|
os << nextIndent << "<Piece";
|
|
this->WriteAppendedPieceAttributes(i);
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
this->DeletePositionArrays();
|
|
return 0;
|
|
}
|
|
os << ">\n";
|
|
|
|
this->WriteAppendedPiece(i, nextIndent.GetNextIndent());
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
this->DeletePositionArrays();
|
|
return 0;
|
|
}
|
|
|
|
// Close the piece's element.
|
|
os << nextIndent << "</Piece>\n";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Write just the requested piece.
|
|
// Open the piece's element.
|
|
os << nextIndent << "<Piece";
|
|
this->WriteAppendedPieceAttributes(this->WritePiece);
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
this->DeletePositionArrays();
|
|
return 0;
|
|
}
|
|
os << ">\n";
|
|
|
|
this->WriteAppendedPiece(this->WritePiece, nextIndent.GetNextIndent());
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
this->DeletePositionArrays();
|
|
return 0;
|
|
}
|
|
|
|
// Close the piece's element.
|
|
os << nextIndent << "</Piece>\n";
|
|
}
|
|
|
|
// Close the primary element.
|
|
os << indent << "</" << this->GetDataSetName() << ">\n";
|
|
os.flush();
|
|
if (os.fail())
|
|
{
|
|
this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError);
|
|
this->DeletePositionArrays();
|
|
return 0;
|
|
}
|
|
|
|
this->StartAppendedData();
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
this->DeletePositionArrays();
|
|
return 0;
|
|
}
|
|
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkXMLUnstructuredDataWriter::WriteAPiece()
|
|
{
|
|
vtkIndent indent = vtkIndent().GetNextIndent();
|
|
|
|
int result=1;
|
|
|
|
if(this->DataMode == vtkXMLWriter::Appended)
|
|
{
|
|
this->WriteAppendedPieceData(this->CurrentPiece);
|
|
}
|
|
else
|
|
{
|
|
result = this->WriteInlineMode(indent);
|
|
}
|
|
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
this->DeletePositionArrays();
|
|
result = 0;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkXMLUnstructuredDataWriter::WriteFooter()
|
|
{
|
|
vtkIndent indent = vtkIndent().GetNextIndent();
|
|
|
|
ostream& os = *(this->Stream);
|
|
|
|
if(this->DataMode == vtkXMLWriter::Appended)
|
|
{
|
|
this->DeletePositionArrays();
|
|
this->EndAppendedData();
|
|
}
|
|
else
|
|
{
|
|
// Close the primary element.
|
|
os << indent << "</" << this->GetDataSetName() << ">\n";
|
|
os.flush();
|
|
if (os.fail())
|
|
{
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int vtkXMLUnstructuredDataWriter::WriteInlineMode(vtkIndent indent)
|
|
{
|
|
ostream& os = *(this->Stream);
|
|
vtkIndent nextIndent = indent.GetNextIndent();
|
|
|
|
// Open the piece's element.
|
|
os << nextIndent << "<Piece";
|
|
this->WriteInlinePieceAttributes();
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
return 0;
|
|
}
|
|
os << ">\n";
|
|
|
|
this->WriteInlinePiece(nextIndent.GetNextIndent());
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
// Close the piece's element.
|
|
os << nextIndent << "</Piece>\n";
|
|
|
|
return 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLUnstructuredDataWriter::WriteInlinePieceAttributes()
|
|
{
|
|
vtkPointSet* input = this->GetInputAsPointSet();
|
|
this->WriteScalarAttribute("NumberOfPoints",
|
|
input->GetNumberOfPoints());
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLUnstructuredDataWriter::WriteInlinePiece(vtkIndent indent)
|
|
{
|
|
vtkPointSet* input = this->GetInputAsPointSet();
|
|
|
|
// Split progress among point data, cell data, and point arrays.
|
|
float progressRange[2] = {0,0};
|
|
this->GetProgressRange(progressRange);
|
|
float fractions[4];
|
|
this->CalculateDataFractions(fractions);
|
|
|
|
// Set the range of progress for the point data arrays.
|
|
this->SetProgressRange(progressRange, 0, fractions);
|
|
|
|
// Write the point data arrays.
|
|
this->WritePointDataInline(input->GetPointData(), indent);
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Set the range of progress for the cell data arrays.
|
|
this->SetProgressRange(progressRange, 1, fractions);
|
|
|
|
// Write the cell data arrays.
|
|
this->WriteCellDataInline(input->GetCellData(), indent);
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Set the range of progress for the point specification array.
|
|
this->SetProgressRange(progressRange, 2, fractions);
|
|
|
|
// Write the point specification array.
|
|
this->WritePointsInline(input->GetPoints(), indent);
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLUnstructuredDataWriter::WriteAppendedPieceAttributes(int index)
|
|
{
|
|
this->NumberOfPointsPositions[index] =
|
|
this->ReserveAttributeSpace("NumberOfPoints");
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLUnstructuredDataWriter::WriteAppendedPiece(int index,
|
|
vtkIndent indent)
|
|
{
|
|
vtkPointSet* input = this->GetInputAsPointSet();
|
|
|
|
this->WritePointDataAppended(input->GetPointData(), indent,
|
|
&this->PointDataOM->GetPiece(index));
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
return;
|
|
}
|
|
|
|
this->WriteCellDataAppended(input->GetCellData(), indent,
|
|
&this->CellDataOM->GetPiece(index));
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
return;
|
|
}
|
|
|
|
this->WritePointsAppended(input->GetPoints(), indent,
|
|
&this->PointsOM->GetPiece(index));
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLUnstructuredDataWriter::WriteAppendedPieceData(int index)
|
|
{
|
|
ostream& os = *(this->Stream);
|
|
vtkPointSet* input = this->GetInputAsPointSet();
|
|
|
|
unsigned long returnPosition = os.tellp();
|
|
os.seekp(this->NumberOfPointsPositions[index]);
|
|
vtkPoints* points = input->GetPoints();
|
|
this->WriteScalarAttribute("NumberOfPoints",
|
|
(points?points->GetNumberOfPoints():0));
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
return;
|
|
}
|
|
os.seekp(returnPosition);
|
|
|
|
// Split progress among point data, cell data, and point arrays.
|
|
float progressRange[2] = {0,0};
|
|
this->GetProgressRange(progressRange);
|
|
float fractions[4];
|
|
this->CalculateDataFractions(fractions);
|
|
|
|
// Set the range of progress for the point data arrays.
|
|
this->SetProgressRange(progressRange, 0, fractions);
|
|
|
|
// Write the point data arrays.
|
|
this->WritePointDataAppendedData(input->GetPointData(), this->CurrentTimeIndex,
|
|
&this->PointDataOM->GetPiece(index));
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Set the range of progress for the cell data arrays.
|
|
this->SetProgressRange(progressRange, 1, fractions);
|
|
|
|
// Write the cell data arrays.
|
|
this->WriteCellDataAppendedData(input->GetCellData(), this->CurrentTimeIndex,
|
|
&this->CellDataOM->GetPiece(index));
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Set the range of progress for the point specification array.
|
|
this->SetProgressRange(progressRange, 2, fractions);
|
|
|
|
// Write the point specification array.
|
|
// Since we are writting the point let save the Modified Time of vtkPoints:
|
|
this->WritePointsAppendedData(input->GetPoints(), this->CurrentTimeIndex,
|
|
&this->PointsOM->GetPiece(index));
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLUnstructuredDataWriter::WriteCellsInline(const char* name,
|
|
vtkCellArray* cells,
|
|
vtkDataArray* types,
|
|
vtkIndent indent)
|
|
{
|
|
this->ConvertCells(cells);
|
|
|
|
ostream& os = *(this->Stream);
|
|
os << indent << "<" << name << ">\n";
|
|
|
|
// Split progress by cell connectivity, offset, and type arrays.
|
|
float progressRange[2] = {0,0};
|
|
this->GetProgressRange(progressRange);
|
|
float fractions[4];
|
|
this->CalculateCellFractions(fractions, types?types->GetNumberOfTuples():0);
|
|
|
|
// Set the range of progress for the connectivity array.
|
|
this->SetProgressRange(progressRange, 0, fractions);
|
|
|
|
// Write the connectivity array.
|
|
this->WriteDataArrayInline(this->CellPoints, indent.GetNextIndent());
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Set the range of progress for the offsets array.
|
|
this->SetProgressRange(progressRange, 1, fractions);
|
|
|
|
// Write the offsets array.
|
|
this->WriteDataArrayInline(this->CellOffsets, indent.GetNextIndent());
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if(types)
|
|
{
|
|
// Set the range of progress for the types array.
|
|
this->SetProgressRange(progressRange, 2, fractions);
|
|
|
|
// Write the types array.
|
|
this->WriteDataArrayInline(types, indent.GetNextIndent(), "types");
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
os << indent << "</" << name << ">\n";
|
|
os.flush();
|
|
if (os.fail())
|
|
{
|
|
this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLUnstructuredDataWriter::WriteCellsAppended(const char* name,
|
|
vtkDataArray* types,
|
|
vtkIndent indent,
|
|
OffsetsManagerGroup *cellsManager)
|
|
{
|
|
ostream& os = *(this->Stream);
|
|
os << indent << "<" << name << ">\n";
|
|
|
|
// Helper for the 'for' loop
|
|
vtkDataArray *allcells[3];
|
|
allcells[0] = this->CellPoints;
|
|
allcells[1] = this->CellOffsets;
|
|
allcells[2] = types;
|
|
const char *names[] = {NULL, NULL, "types"};
|
|
|
|
for(int t=0; t<this->NumberOfTimeSteps; t++)
|
|
{
|
|
for(int i=0; i<3; i++)
|
|
{
|
|
if(allcells[i])
|
|
{
|
|
cellsManager->GetElement(i).GetPosition(t) =
|
|
this->WriteDataArrayAppended(allcells[i], indent.GetNextIndent(),names[i],0,t);
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
os << indent << "</" << name << ">\n";
|
|
os.flush();
|
|
if (os.fail())
|
|
{
|
|
this->SetErrorCode(vtkErrorCode::OutOfDiskSpaceError);
|
|
return;
|
|
}
|
|
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void
|
|
vtkXMLUnstructuredDataWriter::WriteCellsAppendedData(vtkCellArray* cells,
|
|
vtkDataArray* types,
|
|
int timestep,
|
|
OffsetsManagerGroup *cellsManager)
|
|
{
|
|
this->ConvertCells(cells);
|
|
|
|
// Split progress by cell connectivity, offset, and type arrays.
|
|
float progressRange[2] = {0,0};
|
|
this->GetProgressRange(progressRange);
|
|
float fractions[4];
|
|
this->CalculateCellFractions(fractions, types?types->GetNumberOfTuples():0);
|
|
|
|
// Helper for the 'for' loop
|
|
vtkDataArray *allcells[3];
|
|
allcells[0] = this->CellPoints;
|
|
allcells[1] = this->CellOffsets;
|
|
allcells[2] = types;
|
|
|
|
for(int i=0; i<3; i++)
|
|
{
|
|
if(allcells[i])
|
|
{
|
|
// Set the range of progress for the connectivity array.
|
|
this->SetProgressRange(progressRange, i, fractions);
|
|
|
|
unsigned long mtime = allcells[i]->GetMTime();
|
|
unsigned long &cellsMTime = cellsManager->GetElement(i).GetLastMTime();
|
|
// Only write cells if MTime has changed
|
|
if( cellsMTime != mtime )
|
|
{
|
|
cellsMTime = mtime;
|
|
// Write the connectivity array.
|
|
this->WriteDataArrayAppendedData(allcells[i],
|
|
cellsManager->GetElement(i).GetPosition(timestep),
|
|
cellsManager->GetElement(i).GetOffsetValue(timestep));
|
|
if (this->ErrorCode == vtkErrorCode::OutOfDiskSpaceError)
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// One timestep must have already been written or the
|
|
// mtime would have changed and we would not be here.
|
|
assert( timestep > 0 );
|
|
cellsManager->GetElement(i).GetOffsetValue(timestep) =
|
|
cellsManager->GetElement(i).GetOffsetValue(timestep-1);
|
|
this->ForwardAppendedDataOffset(cellsManager->GetElement(i).GetPosition(timestep),
|
|
cellsManager->GetElement(i).GetOffsetValue(timestep),
|
|
"offset" );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLUnstructuredDataWriter::ConvertCells(vtkCellArray* cells)
|
|
{
|
|
vtkIdTypeArray* connectivity = cells->GetData();
|
|
vtkIdType numberOfCells = cells->GetNumberOfCells();
|
|
vtkIdType numberOfTuples = connectivity->GetNumberOfTuples();
|
|
|
|
this->CellPoints->SetNumberOfTuples(numberOfTuples - numberOfCells);
|
|
this->CellOffsets->SetNumberOfTuples(numberOfCells);
|
|
|
|
vtkIdType* inCell = connectivity->GetPointer(0);
|
|
vtkIdType* outCellPointsBase = this->CellPoints->GetPointer(0);
|
|
vtkIdType* outCellPoints = outCellPointsBase;
|
|
vtkIdType* outCellOffset = this->CellOffsets->GetPointer(0);
|
|
|
|
vtkIdType i;
|
|
for(i=0;i < numberOfCells; ++i)
|
|
{
|
|
vtkIdType numberOfPoints = *inCell++;
|
|
memcpy(outCellPoints, inCell, sizeof(vtkIdType)*numberOfPoints);
|
|
outCellPoints += numberOfPoints;
|
|
inCell += numberOfPoints;
|
|
*outCellOffset++ = outCellPoints - outCellPointsBase;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
vtkIdType vtkXMLUnstructuredDataWriter::GetNumberOfInputPoints()
|
|
{
|
|
vtkPointSet* input = this->GetInputAsPointSet();
|
|
vtkPoints* points = input->GetPoints();
|
|
return points?points->GetNumberOfPoints():0;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLUnstructuredDataWriter::CalculateDataFractions(float* fractions)
|
|
{
|
|
// Calculate the fraction of point/cell data and point
|
|
// specifications contributed by each component.
|
|
vtkPointSet* input = this->GetInputAsPointSet();
|
|
int pdArrays = input->GetPointData()->GetNumberOfArrays();
|
|
int cdArrays = input->GetCellData()->GetNumberOfArrays();
|
|
vtkIdType pdSize = pdArrays*this->GetNumberOfInputPoints();
|
|
vtkIdType cdSize = cdArrays*this->GetNumberOfInputCells();
|
|
int total = (pdSize+cdSize+this->GetNumberOfInputPoints());
|
|
if(total == 0)
|
|
{
|
|
total = 1;
|
|
}
|
|
fractions[0] = 0;
|
|
fractions[1] = float(pdSize)/total;
|
|
fractions[2] = float(pdSize+cdSize)/total;
|
|
fractions[3] = 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLUnstructuredDataWriter::CalculateCellFractions(float* fractions,
|
|
vtkIdType typesSize)
|
|
{
|
|
// Calculate the fraction of cell specification data contributed by
|
|
// each of the connectivity, offset, and type arrays.
|
|
vtkIdType connectSize = this->CellPoints->GetNumberOfTuples();
|
|
vtkIdType offsetSize = this->CellOffsets->GetNumberOfTuples();
|
|
vtkIdType total = connectSize+offsetSize+typesSize;
|
|
if(total == 0)
|
|
{
|
|
total = 1;
|
|
}
|
|
fractions[0] = 0;
|
|
fractions[1] = float(connectSize)/total;
|
|
fractions[2] = float(connectSize+offsetSize)/total;
|
|
fractions[3] = 1;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
void vtkXMLUnstructuredDataWriter::SetInputUpdateExtent(
|
|
int piece, int numPieces, int ghostLevel)
|
|
{
|
|
vtkInformation* inInfo =
|
|
this->GetExecutive()->GetInputInformation(0, 0);
|
|
inInfo->Set(
|
|
vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES(), numPieces);
|
|
inInfo->Set(
|
|
vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER(), piece);
|
|
inInfo->Set(
|
|
vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS(), ghostLevel);
|
|
}
|
|
|
|
|