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/XML/vtkXMLUniformGridAMRReader.cxx

483 lines
14 KiB
C++

/*=========================================================================
Program: ParaView
Module: vtkXMLUniformGridAMRReader.cxx
Copyright (c) Kitware, Inc.
All rights reserved.
See Copyright.txt or http://www.paraview.org/HTML/Copyright.html 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 "vtkXMLUniformGridAMRReader.h"
#include "vtkAMRBox.h"
#include "vtkAMRInformation.h"
#include "vtkAMRUtilities.h"
#include "vtkCompositeDataPipeline.h"
#include "vtkDataObjectTypes.h"
#include "vtkInformation.h"
#include "vtkInformationVector.h"
#include "vtkNonOverlappingAMR.h"
#include "vtkObjectFactory.h"
#include "vtkOverlappingAMR.h"
#include "vtkSmartPointer.h"
#include "vtkUniformGrid.h"
#include "vtkXMLDataElement.h"
#include <cassert>
#include <vector>
namespace
{
// Data type used to store a 3-tuple of doubles.
template <class T, int N> class vtkTuple
{
public:
T Data[N];
vtkTuple()
{
for (int cc=0; cc < N; cc++)
{
this->Data[cc] = 0;
}
}
operator T* ()
{
return this->Data;
}
};
typedef vtkTuple<double, 3> vtkSpacingType;
// Helper routine to parse the XML to collect information about the AMR.
bool vtkReadMetaData(
vtkXMLDataElement* ePrimary,
std::vector<unsigned int> &blocks_per_level,
std::vector<vtkSpacingType> &level_spacing,
std::vector<std::vector<vtkAMRBox> > &amr_boxes)
{
unsigned int numElems = ePrimary->GetNumberOfNestedElements();
for (unsigned int cc=0; cc < numElems; cc++)
{
vtkXMLDataElement* blockXML = ePrimary->GetNestedElement(cc);
if (!blockXML || !blockXML->GetName() ||
strcmp(blockXML->GetName(), "Block") != 0)
{
continue;
}
int level = 0;
if (!blockXML->GetScalarAttribute("level", level))
{
vtkGenericWarningMacro("Missing 'level' on 'Block' element in XML. Skipping");
continue;
}
if (level < 0)
{
// sanity check.
continue;
}
if (blocks_per_level.size() <= static_cast<size_t>(level))
{
blocks_per_level.resize(level+1, 0);
level_spacing.resize(level+1);
amr_boxes.resize(level+1);
}
double spacing[3];
if (blockXML->GetVectorAttribute("spacing", 3, spacing))
{
level_spacing[level][0] = spacing[0];
level_spacing[level][1] = spacing[1];
level_spacing[level][2] = spacing[2];
}
// now read the <DataSet/> elements for boxes and counting the number of
// nodes per level.
int numDatasets = blockXML->GetNumberOfNestedElements();
for (int kk=0; kk < numDatasets; kk++)
{
vtkXMLDataElement* datasetXML = blockXML->GetNestedElement(kk);
if (!datasetXML || !datasetXML->GetName() ||
strcmp(datasetXML->GetName(), "DataSet") != 0)
{
continue;
}
int index = 0;
if (!datasetXML->GetScalarAttribute("index", index))
{
vtkGenericWarningMacro("Missing 'index' on 'DataSet' element in XML. Skipping");
continue;
}
if (index >= static_cast<int>(blocks_per_level[level]))
{
blocks_per_level[level] = index+1;
}
if (static_cast<size_t>(index) >= amr_boxes[level].size())
{
amr_boxes[level].resize(index + 1);
}
int box[6];
// note: amr-box is not provided for non-overlapping AMR.
if (!datasetXML->GetVectorAttribute("amr_box", 6, box))
{
continue;
}
// box is xLo, xHi, yLo, yHi, zLo, zHi.
amr_boxes[level][index] = vtkAMRBox(box);
}
}
return true;
}
bool vtkReadMetaData(vtkXMLDataElement* ePrimary,
std::vector<unsigned int> &blocks_per_level)
{
std::vector<vtkSpacingType> spacings;
std::vector<std::vector<vtkAMRBox> > amr_boxes;
return vtkReadMetaData(ePrimary, blocks_per_level, spacings, amr_boxes);
}
}
vtkStandardNewMacro(vtkXMLUniformGridAMRReader);
//----------------------------------------------------------------------------
vtkXMLUniformGridAMRReader::vtkXMLUniformGridAMRReader()
{
this->OutputDataType = NULL;
this->MaximumLevelsToReadByDefault = 1;
}
//----------------------------------------------------------------------------
vtkXMLUniformGridAMRReader::~vtkXMLUniformGridAMRReader()
{
this->SetOutputDataType(NULL);
}
//----------------------------------------------------------------------------
void vtkXMLUniformGridAMRReader::PrintSelf(ostream& os, vtkIndent indent)
{
this->Superclass::PrintSelf(os, indent);
os << indent << "MaximumLevelsToReadByDefault: " <<
this->MaximumLevelsToReadByDefault << endl;
}
//----------------------------------------------------------------------------
const char* vtkXMLUniformGridAMRReader::GetDataSetName()
{
if (!this->OutputDataType)
{
vtkWarningMacro("We haven't determine a valid output type yet.");
return "vtkUniformGridAMR";
}
return this->OutputDataType;
}
//----------------------------------------------------------------------------
int vtkXMLUniformGridAMRReader::CanReadFileWithDataType(const char* dsname)
{
return (dsname && (
strcmp(dsname, "vtkOverlappingAMR") == 0 ||
strcmp(dsname, "vtkNonOverlappingAMR") == 0 ||
strcmp(dsname, "vtkHierarchicalBoxDataSet") == 0))? 1 : 0;
}
//----------------------------------------------------------------------------
int vtkXMLUniformGridAMRReader::ReadVTKFile(vtkXMLDataElement* eVTKFile)
{
// this->Superclass::ReadVTKFile(..) calls this->GetDataSetName().
// GetDataSetName() needs to know the data type we're reading and hence it's
// essential to read the "type" before calling the superclass' method.
// NOTE: eVTKFile maybe totally invalid, so proceed with caution.
const char* type = eVTKFile->GetAttribute("type");
if (type == NULL ||
(strcmp(type, "vtkHierarchicalBoxDataSet") != 0 &&
strcmp(type, "vtkOverlappingAMR") != 0 &&
strcmp(type, "vtkNonOverlappingAMR") != 0))
{
vtkErrorMacro(
"Invalid 'type' specified in the file: " << (type? type : "(none)"));
return 0;
}
this->SetOutputDataType(type);
return this->Superclass::ReadVTKFile(eVTKFile);
}
//----------------------------------------------------------------------------
int vtkXMLUniformGridAMRReader::ReadPrimaryElement(vtkXMLDataElement* ePrimary)
{
if (!this->Superclass::ReadPrimaryElement(ePrimary))
{
return 0;
}
if (this->GetFileMajorVersion() == -1 && this->GetFileMinorVersion() == -1)
{
// for old files, we don't support providing meta-data for
// RequestInformation() pass.
this->Metadata = NULL;
return 1;
}
if (strcmp(ePrimary->GetName(), "vtkNonOverlappingAMR") == 0)
{
// this is a non-overlapping AMR. We don't have meta-data for
// non-overlapping AMRs.
this->Metadata = NULL;
return 1;
}
// Read the xml to build the metadata.
this->Metadata = vtkSmartPointer<vtkOverlappingAMR>::New();
// iterate over the XML to fill up the AMRInformation with meta-data.
std::vector<unsigned int> blocks_per_level;
std::vector<vtkSpacingType> level_spacing;
std::vector<std::vector<vtkAMRBox> > amr_boxes;
vtkReadMetaData(ePrimary, blocks_per_level, level_spacing, amr_boxes);
if (blocks_per_level.size() > 0)
{
// initialize vtkAMRInformation.
this->Metadata->Initialize(
static_cast<int>(blocks_per_level.size()),
reinterpret_cast<int*>(&blocks_per_level[0]));
double origin[3] = {0, 0, 0};
if (!ePrimary->GetVectorAttribute("origin", 3, origin))
{
vtkWarningMacro("Missing 'origin'. Using (0, 0, 0).");
}
this->Metadata->SetOrigin(origin);
const char* grid_description = ePrimary->GetAttribute("grid_description");
int iGridDescription = VTK_XYZ_GRID;
if (grid_description && strcmp(grid_description, "XY") == 0)
{
iGridDescription = VTK_XY_PLANE;
}
else if (grid_description && strcmp(grid_description, "YZ") == 0)
{
iGridDescription = VTK_YZ_PLANE;
}
else if (grid_description && strcmp(grid_description, "XZ") == 0)
{
iGridDescription = VTK_XZ_PLANE;
}
this->Metadata->SetGridDescription(iGridDescription);
// pass refinement ratios.
for (size_t cc=0; cc < level_spacing.size(); cc++)
{
this->Metadata->GetAMRInfo()->SetSpacing(
static_cast<unsigned int>(cc), level_spacing[cc]);
}
// pass amr boxes.
for (size_t level=0; level < amr_boxes.size(); level++)
{
for (size_t index=0; index < amr_boxes[level].size(); index++)
{
const vtkAMRBox& box = amr_boxes[level][index];
if (!box.Empty())
{
this->Metadata->GetAMRInfo()->SetAMRBox(
static_cast<unsigned int>(level),
static_cast<unsigned int>(index), box);
}
}
}
}
this->Metadata->GenerateParentChildInformation();
return 1;
}
//----------------------------------------------------------------------------
int vtkXMLUniformGridAMRReader::RequestDataObject(
vtkInformation *vtkNotUsed(request),
vtkInformationVector **vtkNotUsed(inputVector),
vtkInformationVector *outputVector)
{
if (!this->ReadXMLInformation())
{
return 0;
}
vtkDataObject* output = vtkDataObject::GetData(outputVector, 0);
if (!output || !output->IsA(this->OutputDataType))
{
vtkDataObject* newDO = vtkDataObjectTypes::NewDataObject(this->OutputDataType);
if (newDO)
{
outputVector->GetInformationObject(0)->Set(
vtkDataObject::DATA_OBJECT(), newDO);
newDO->FastDelete();
return 1;
}
}
return 1;
}
//----------------------------------------------------------------------------
int vtkXMLUniformGridAMRReader::RequestInformation(vtkInformation *request,
vtkInformationVector **inputVector, vtkInformationVector *outputVector)
{
if (!this->Superclass::RequestInformation(request, inputVector, outputVector))
{
return 0;
}
if (this->Metadata)
{
outputVector->GetInformationObject(0)->Set(
vtkCompositeDataPipeline::COMPOSITE_DATA_META_DATA(),
this->Metadata);
}
else
{
outputVector->GetInformationObject(0)->Remove(
vtkCompositeDataPipeline::COMPOSITE_DATA_META_DATA());
}
return 1;
}
//----------------------------------------------------------------------------
void vtkXMLUniformGridAMRReader::ReadComposite(vtkXMLDataElement* element,
vtkCompositeDataSet* composite, const char* filePath,
unsigned int &dataSetIndex)
{
vtkUniformGridAMR* amr = vtkUniformGridAMR::SafeDownCast(composite);
if (!amr)
{
vtkErrorMacro("Dataset must be a vtkUniformGridAMR.");
return;
}
if (this->GetFileMajorVersion() == -1 && this->GetFileMinorVersion() == -1)
{
vtkErrorMacro(
"Version not supported. Use vtkXMLHierarchicalBoxDataReader instead.");
return;
}
vtkInformation* outinfo = this->GetCurrentOutputInformation();
bool has_block_requests =
outinfo->Has(vtkCompositeDataPipeline::LOAD_REQUESTED_BLOCKS()) != 0;
vtkOverlappingAMR* oamr = vtkOverlappingAMR::SafeDownCast(amr);
vtkNonOverlappingAMR* noamr = vtkNonOverlappingAMR::SafeDownCast(amr);
assert(oamr != NULL || noamr != NULL);
if (oamr)
{
// we don;t have the parse the structure. Just pass the inform from
// this->Metadata.
oamr->SetAMRInfo(this->Metadata->GetAMRInfo());
}
else if (noamr)
{
// We process the XML to collect information about the structure.
std::vector<unsigned int> blocks_per_level;
vtkReadMetaData(element, blocks_per_level);
noamr->Initialize(
static_cast<int>(blocks_per_level.size()),
reinterpret_cast<int*>(&blocks_per_level[0]));
}
// Now, simply scan the xml for dataset elements and read them as needed.
unsigned int numElems = element->GetNumberOfNestedElements();
for (unsigned int cc=0; cc < numElems; cc++)
{
vtkXMLDataElement* blockXML = element->GetNestedElement(cc);
if (!blockXML || !blockXML->GetName() ||
strcmp(blockXML->GetName(), "Block") != 0)
{
continue;
}
int level = 0;
if (!blockXML->GetScalarAttribute("level", level) || level < 0)
{
continue;
}
// now read the <DataSet/> elements for boxes and counting the number of
// nodes per level.
int numDatasets = blockXML->GetNumberOfNestedElements();
for (int kk=0; kk < numDatasets; kk++)
{
vtkXMLDataElement* datasetXML = blockXML->GetNestedElement(kk);
if (!datasetXML || !datasetXML->GetName() ||
strcmp(datasetXML->GetName(), "DataSet") != 0)
{
continue;
}
int index = 0;
if (!datasetXML->GetScalarAttribute("index", index) || index < 0)
{
continue;
}
if (this->ShouldReadDataSet(dataSetIndex))
{
// if has_block_requests==false, then we don't read any blocks greater
// than the MaximumLevelsToReadByDefault.
if (has_block_requests == false &&
this->MaximumLevelsToReadByDefault > 0 &&
static_cast<unsigned int>(level) >= this->MaximumLevelsToReadByDefault)
{
// don't actually read the data.
}
else
{
vtkSmartPointer<vtkDataSet> ds;
ds.TakeReference(this->ReadDataset(datasetXML, filePath));
if (ds && !ds->IsA("vtkUniformGrid"))
{
vtkErrorMacro("vtkUniformGridAMR can only contain vtkUniformGrids.");
}
else
{
amr->SetDataSet(
static_cast<unsigned int>(level), static_cast<unsigned int>(index),
vtkUniformGrid::SafeDownCast(ds.GetPointer()));
}
}
}
dataSetIndex++;
}
}
if( (oamr != NULL) && !has_block_requests )
{
vtkAMRUtilities::BlankCells(oamr);
}
}
//----------------------------------------------------------------------------
vtkDataSet* vtkXMLUniformGridAMRReader::ReadDataset(
vtkXMLDataElement* xmlElem, const char* filePath)
{
vtkDataSet* ds = this->Superclass::ReadDataset(xmlElem, filePath);
if (ds && ds->IsA("vtkImageData"))
{
// Convert vtkImageData to vtkUniformGrid as needed by
// vtkHierarchicalBoxDataSet.
vtkUniformGrid* ug = vtkUniformGrid::New();
ug->ShallowCopy(ds);
ds->Delete();
return ug;
}
return ds;
}