You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
nmWTAI-Platform/3rd/VTK7.1/source/VTK-7.1.1/IO/Legacy/vtkCompositeDataReader.cxx

669 lines
18 KiB
C++

/*=========================================================================
Program: Visualization Toolkit
Module: vtkCompositeDataReader.cxx
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 "vtkCompositeDataReader.h"
#include "vtkAMRBox.h"
#include "vtkAMRInformation.h"
#include "vtkDataObjectTypes.h"
#include "vtkDoubleArray.h"
#include "vtkFieldData.h"
#include "vtkGenericDataObjectReader.h"
#include "vtkHierarchicalBoxDataSet.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkIntArray.h"
#include "vtkMultiBlockDataSet.h"
#include "vtkMultiPieceDataSet.h"
#include "vtkNonOverlappingAMR.h"
#include "vtkObjectFactory.h"
#include "vtkOverlappingAMR.h"
#include "vtkStreamingDemandDrivenPipeline.h"
#include "vtkUniformGrid.h"
#include <vtksys/RegularExpression.hxx>
#include <vtksys/SystemTools.hxx>
#include <sstream>
#include <vector>
vtkStandardNewMacro(vtkCompositeDataReader);
//----------------------------------------------------------------------------
vtkCompositeDataReader::vtkCompositeDataReader()
{
}
//----------------------------------------------------------------------------
vtkCompositeDataReader::~vtkCompositeDataReader()
{
}
//----------------------------------------------------------------------------
vtkCompositeDataSet* vtkCompositeDataReader::GetOutput()
{
return this->GetOutput(0);
}
//----------------------------------------------------------------------------
vtkCompositeDataSet* vtkCompositeDataReader::GetOutput(int idx)
{
return vtkCompositeDataSet::SafeDownCast(this->GetOutputDataObject(idx));
}
//----------------------------------------------------------------------------
void vtkCompositeDataReader::SetOutput(vtkCompositeDataSet *output)
{
this->GetExecutive()->SetOutputData(0, output);
}
//----------------------------------------------------------------------------
int vtkCompositeDataReader::RequestUpdateExtent(
vtkInformation *, vtkInformationVector **, vtkInformationVector *outputVector)
{
vtkInformation *outInfo = outputVector->GetInformationObject(0);
int piece, numPieces, ghostLevel;
piece = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_PIECE_NUMBER());
numPieces = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_PIECES());
ghostLevel = outInfo->Get(vtkStreamingDemandDrivenPipeline::UPDATE_NUMBER_OF_GHOST_LEVELS());
// make sure piece is valid
if (piece < 0 || piece >= numPieces)
{
return 1;
}
if (ghostLevel < 0)
{
return 1;
}
return 1;
}
//----------------------------------------------------------------------------
int vtkCompositeDataReader::FillOutputPortInformation(int, vtkInformation* info)
{
info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkCompositeDataSet");
return 1;
}
//----------------------------------------------------------------------------
int vtkCompositeDataReader::ProcessRequest(vtkInformation* request,
vtkInformationVector** inputVector, vtkInformationVector* outputVector)
{
// generate the data
if(request->Has(vtkDemandDrivenPipeline::REQUEST_DATA_OBJECT()))
{
return this->RequestDataObject(request, inputVector, outputVector);
}
return this->Superclass::ProcessRequest(request, inputVector, outputVector);
}
//----------------------------------------------------------------------------
int vtkCompositeDataReader::RequestDataObject(vtkInformation *,
vtkInformationVector **, vtkInformationVector *outputVector)
{
int output_type = this->ReadOutputType();
if (output_type < 0)
{
vtkErrorMacro("Failed to read data-type.");
return 0;
}
vtkDataObject* output = vtkDataObject::GetData(outputVector, 0);
if (!output ||
!output->IsA(vtkDataObjectTypes::GetClassNameFromTypeId(output_type)))
{
output = vtkDataObjectTypes::NewDataObject(output_type);
outputVector->GetInformationObject(0)->Set(
vtkDataObject::DATA_OBJECT(),
output);
output->FastDelete();
}
return 1;
}
//----------------------------------------------------------------------------
int vtkCompositeDataReader::ReadOutputType()
{
char line[256];
if (!this->OpenVTKFile() || !this->ReadHeader())
{
return -1;
}
// Determine dataset type
//
if (!this->ReadString(line))
{
vtkDebugMacro(<< "Premature EOF reading dataset keyword");
return -1;
}
if (strncmp(this->LowerCase(line),"dataset",static_cast<unsigned long>(7)) == 0)
{
// See iftype is recognized.
//
if (!this->ReadString(line))
{
vtkDebugMacro(<< "Premature EOF reading type");
this->CloseVTKFile ();
return -1;
}
this->CloseVTKFile();
if (strncmp(this->LowerCase(line), "multiblock", strlen("multiblock")) == 0)
{
return VTK_MULTIBLOCK_DATA_SET;
}
if (strncmp(this->LowerCase(line), "multipiece", strlen("multipiece")) == 0)
{
return VTK_MULTIPIECE_DATA_SET;
}
if (strncmp(this->LowerCase(line), "overlapping_amr", strlen("overlapping_amr")) == 0)
{
return VTK_OVERLAPPING_AMR;
}
if (strncmp(this->LowerCase(line), "non_overlapping_amr", strlen("non_overlapping_amr")) == 0)
{
return VTK_NON_OVERLAPPING_AMR;
}
if (strncmp(this->LowerCase(line), "hierarchical_box",
strlen("hierarchical_box")) == 0)
{
return VTK_HIERARCHICAL_BOX_DATA_SET;
}
}
return -1;
}
//----------------------------------------------------------------------------
int vtkCompositeDataReader::RequestData(vtkInformation *, vtkInformationVector **,
vtkInformationVector *outputVector)
{
if (!(this->OpenVTKFile()) || !this->ReadHeader())
{
return 0;
}
vtkMultiBlockDataSet* mb = vtkMultiBlockDataSet::GetData(outputVector, 0);
vtkMultiPieceDataSet* mp = vtkMultiPieceDataSet::GetData(outputVector, 0);
vtkHierarchicalBoxDataSet* hb = vtkHierarchicalBoxDataSet::GetData(outputVector, 0);
vtkOverlappingAMR* oamr = vtkOverlappingAMR::GetData(outputVector, 0);
vtkNonOverlappingAMR* noamr = vtkNonOverlappingAMR::GetData(outputVector, 0);
// Read the data-type description line which was already read in
// RequestDataObject() so we just skip it here without any additional
// validation.
char line[256];
if (!this->ReadString(line) || !this->ReadString(line))
{
vtkErrorMacro(<<"Data file ends prematurely!");
this->CloseVTKFile ();
return 0;
}
if (mb)
{
this->ReadCompositeData(mb);
}
else if (mp)
{
this->ReadCompositeData(mp);
}
else if (hb)
{
this->ReadCompositeData(hb);
}
else if (oamr)
{
this->ReadCompositeData(oamr);
}
else if (noamr)
{
this->ReadCompositeData(noamr);
}
return 1;
}
//----------------------------------------------------------------------------
bool vtkCompositeDataReader::ReadCompositeData(vtkMultiBlockDataSet* mb)
{
char line[256];
if (!this->ReadString(line))
{
vtkErrorMacro("Failed to read block-count");
return false;
}
if (strncmp(this->LowerCase(line), "children", strlen("children")) != 0)
{
vtkErrorMacro("Failed to read CHILDREN.");
return false;
}
unsigned int num_blocks = 0;
if (!this->Read(&num_blocks))
{
vtkErrorMacro("Failed to read number of blocks");
return false;
}
mb->SetNumberOfBlocks(num_blocks);
for (unsigned int cc=0; cc < num_blocks; cc++)
{
if (!this->ReadString(line))
{
vtkErrorMacro("Failed to read 'CHILD <type>' line");
return false;
}
int type;
if (!this->Read(&type))
{
vtkErrorMacro("Failed to read child type.");
return false;
}
// eat up the "\n" and other whitespace at the end of CHILD <type>.
this->ReadLine(line);
// if "line" has text enclosed in [] then that's the composite name.
vtksys::RegularExpression regEx("\\s*\\[(.*)\\]");
if (regEx.find(line))
{
std::string name = regEx.match(1);
mb->GetMetaData(cc)->Set(vtkCompositeDataSet::NAME(), name.c_str());
}
if (type != -1)
{
vtkDataObject* child = this->ReadChild();
if (!child)
{
vtkErrorMacro("Failed to read child.");
return false;
}
mb->SetBlock(cc, child);
child->FastDelete();
}
else
{
// eat up the ENDCHILD marker.
this->ReadString(line);
}
}
if (this->ReadString(line) && strncmp(this->LowerCase(line),"field",5) == 0)
{
vtkSmartPointer< vtkFieldData > fd = vtkSmartPointer< vtkFieldData >::Take(this->ReadFieldData());
mb->SetFieldData(fd);
}
return true;
}
//----------------------------------------------------------------------------
bool vtkCompositeDataReader::ReadCompositeData(vtkHierarchicalBoxDataSet* hb)
{
(void)hb;
vtkErrorMacro("This isn't supported yet.");
return false;
}
//----------------------------------------------------------------------------
bool vtkCompositeDataReader::ReadCompositeData(vtkOverlappingAMR* oamr)
{
char line[256];
// read GRID_DESCRIPTION.
int description;
if (!this->ReadString(line) ||
strncmp(this->LowerCase(line), "grid_description", strlen("grid_description")) != 0 ||
!this->Read(&description))
{
vtkErrorMacro("Failed to read GRID_DESCRIPTION (or its value).");
return false;
}
// read ORIGIN
double origin[3];
if (!this->ReadString(line) ||
strncmp(this->LowerCase(line), "origin", strlen("origin")) != 0 ||
!this->Read(&origin[0]) || !this->Read(&origin[1]) ||
!this->Read(&origin[2]))
{
vtkErrorMacro("Failed to read ORIGIN (or its value).");
return false;
}
// read LEVELS.
int num_levels;
if (!this->ReadString(line) ||
strncmp(this->LowerCase(line), "levels", strlen("levels")) != 0 ||
!this->Read(&num_levels))
{
vtkErrorMacro("Failed to read LEVELS (or its value).");
return false;
}
std::vector<int> blocksPerLevel;
blocksPerLevel.resize(num_levels);
std::vector<double> spacing;
spacing.resize(num_levels * 3);
int total_blocks = 0;
for (int cc=0; cc < num_levels; cc++)
{
if (!this->Read(&blocksPerLevel[cc]))
{
vtkErrorMacro("Failed to read number of datasets for level " << cc);
return false;
}
if (!this->Read(&spacing[3*cc +0]) || !this->Read(&spacing[3*cc +1]) ||
!this->Read(&spacing[3*cc+2]))
{
vtkErrorMacro("Failed to read spacing for level " << cc);
return false;
}
total_blocks += blocksPerLevel[cc];
}
// initialize the AMR.
oamr->Initialize(num_levels, &blocksPerLevel[0]);
oamr->SetGridDescription(description);
oamr->SetOrigin(origin);
for (int cc=0; cc < num_levels; cc++)
{
oamr->GetAMRInfo()->SetSpacing(cc, &spacing[3*cc]);
}
//read in the amr boxes0
if (!this->ReadString(line))
{
vtkErrorMacro("Failed to read AMRBOXES' line");
}
else
{
if (strncmp(this->LowerCase(line), "amrboxes", strlen("amrboxes")) != 0)
{
vtkErrorMacro("Failed to read AMRBOXES' line");
}
else
{
// now read the amrbox information.
int num_tuples, num_components;
if (!this->Read(&num_tuples) || !this->Read(&num_components))
{
vtkErrorMacro("Failed to read values for AMRBOXES.");
return false;
}
vtkSmartPointer<vtkIntArray> idata;
idata.TakeReference(vtkArrayDownCast<vtkIntArray>(
this->ReadArray("int", num_tuples, num_components)));
if (!idata || idata->GetNumberOfComponents() != 6 ||
idata->GetNumberOfTuples() != static_cast<vtkIdType>(oamr->GetTotalNumberOfBlocks()))
{
vtkErrorMacro("Failed to read meta-data");
return false;
}
unsigned int metadata_index = 0;
for (int level=0; level < num_levels; level++)
{
unsigned int num_datasets = oamr->GetNumberOfDataSets(level);
for (unsigned int index=0; index < num_datasets; index++, metadata_index++)
{
int tuple[6];
idata->GetTypedTuple(metadata_index, tuple);
vtkAMRBox box;
box.SetDimensions(&tuple[0], &tuple[3], description);
oamr->SetAMRBox(level, index, box);
}
}
}
}
//read in the actual data
for (int cc=0; cc < total_blocks; cc++)
{
if (!this->ReadString(line))
{
// we may reach end of file sooner than total_blocks since not all blocks
// may be present in the data.
break;
}
if (strncmp(this->LowerCase(line), "child", strlen("child")) == 0)
{
unsigned int level=0, index=0;
if (!this->Read(&level) || !this->Read(&index))
{
vtkErrorMacro("Failed to read level and index information");
return false;
}
this->ReadLine(line);
vtkDataObject* child = this->ReadChild();
if (!child)
{
vtkErrorMacro("Failed to read dataset at " << level << ", " << index);
return false;
}
if (child->IsA("vtkImageData"))
{
vtkUniformGrid* grid = vtkUniformGrid::New();
grid->ShallowCopy(child);
oamr->SetDataSet(level, index, grid);
grid->FastDelete();
child->Delete();
}
else
{
vtkErrorMacro("vtkImageData expected at " << level << ", " << index);
child->Delete();
return false;
}
}
else
{
vtkErrorMacro("Failed to read 'CHILD' line");
return false;
}
}
return true;
}
//----------------------------------------------------------------------------
bool vtkCompositeDataReader::ReadCompositeData(vtkNonOverlappingAMR* hb)
{
(void)hb;
vtkErrorMacro("This isn't supported yet.");
return false;
}
//----------------------------------------------------------------------------
bool vtkCompositeDataReader::ReadCompositeData(vtkMultiPieceDataSet* mp)
{
char line[256];
if (!this->ReadString(line))
{
vtkErrorMacro("Failed to read block-count");
return false;
}
if (strncmp(this->LowerCase(line), "children", strlen("children")) != 0)
{
vtkErrorMacro("Failed to read CHILDREN.");
return false;
}
unsigned int num_pieces = 0;
if (!this->Read(&num_pieces))
{
vtkErrorMacro("Failed to read number of pieces.");
return false;
}
mp->SetNumberOfPieces(num_pieces);
for (unsigned int cc=0; cc < num_pieces; cc++)
{
if (!this->ReadString(line))
{
vtkErrorMacro("Failed to read 'CHILD <type>' line");
return false;
}
int type;
if (!this->Read(&type))
{
vtkErrorMacro("Failed to read child type.");
return false;
}
// eat up the "\n" and other whitespace at the end of CHILD <type>.
this->ReadLine(line);
// if "line" has text enclosed in [] then that's the composite name.
vtksys::RegularExpression regEx("\\s*\\[(.*)\\]");
if (regEx.find(line))
{
std::string name = regEx.match(1);
mp->GetMetaData(cc)->Set(vtkCompositeDataSet::NAME(), name.c_str());
}
if (type != -1)
{
vtkDataObject* child = this->ReadChild();
if (!child)
{
vtkErrorMacro("Failed to read child.");
return false;
}
mp->SetPiece(cc, child);
child->FastDelete();
}
else
{
// eat up the ENDCHILD marker.
this->ReadString(line);
}
}
return true;
}
//----------------------------------------------------------------------------
vtkDataObject* vtkCompositeDataReader::ReadChild()
{
// This is tricky. Simplistically speaking, we need to read the string for the
// child and then pass it to a vtkGenericDataObjectReader and get it read.
// Identifying where the child ends can be tricky since the child itself may
// be a composite-dataset. Also, we need to avoid copy memory if we are
// already reading from a string.
// We can optimize this further when reading in from a string buffer to avoid
// copying. But we'll do that later.
unsigned int child_stack_depth = 1;
std::ostringstream child_data;
char line[512];
while (child_stack_depth > 0)
// read until ENDCHILD (passing over any nested CHILD-ENDCHILD correctly).
{
bool new_line = true;
while (true)
// read a full line until "\n". This maybe longer than 512 and hence this
// extra loop.
{
this->IS->get(line, 512);
if (this->IS->fail())
{
if (this->IS->eof())
{
vtkErrorMacro("Premature EOF.");
return NULL;
}
else
{
// else it's possible that we read in an empty line. istream still marks
// that as fail().
this->IS->clear();
}
}
if (new_line)
{
// these comparisons need to happen only when a new line is
// started, hence this "if".
if (strncmp(line, "ENDCHILD", strlen("ENDCHILD")) == 0)
{
child_stack_depth--;
}
else if (strncmp(line, "CHILD", strlen("CHILD")) == 0)
{
// should not match CHILDREN :(
if (strncmp(line, "CHILDREN", strlen("CHILDREN")) != 0)
{
child_stack_depth++;
}
}
}
if (child_stack_depth > 0)
{
// except the last ENDCHILD, all the read content is to passed to the
// child-reader.
child_data.write(line, this->IS->gcount());
}
new_line = false;
if (this->IS->peek() == '\n')
{
this->IS->ignore(VTK_INT_MAX, '\n');
// end of line reached.
child_data << '\n';
break;
}
} // while (true);
} // while (child_stack_depth > 0);
vtkGenericDataObjectReader* reader = vtkGenericDataObjectReader::New();
reader->SetBinaryInputString(child_data.str().c_str(),
static_cast<int>(child_data.str().size()));
reader->ReadFromInputStringOn();
reader->Update();
vtkDataObject* child = reader->GetOutput(0);
if (child)
{
child->Register(this);
}
reader->Delete();
return child;
}
//----------------------------------------------------------------------------
void vtkCompositeDataReader::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
}