Skip to content
Snippets Groups Projects
Commit 96f882fd authored by Utkarsh Ayachit's avatar Utkarsh Ayachit Committed by Kitware Robot
Browse files

Merge topic 'partial-arrays-xml-io'


02f949cb Handle mismatch is chosen and available arrays.
1fffa689 add tests to read/write multiblock with partial arrays

Acked-by: default avatarKitware Robot <kwrobot@kitware.com>
Merge-request: !4337
parents ccd60e52 02f949cb
No related branches found
No related tags found
No related merge requests found
......@@ -2,6 +2,7 @@ set(TestXML_ARGS "DATA{${VTK_TEST_INPUT_DIR}/sample.xml}")
set(all_tests
TestAMRXMLIO.cxx,NO_VALID
TestDataObjectXMLIO.cxx,NO_VALID
TestMultiBlockXMLIOWithPartialArrays.cxx,NO_VALID
TestReadDuplicateDataArrayNames.cxx,NO_DATA,NO_VALID
TestXML.cxx,NO_DATA,NO_VALID,NO_OUTPUT
TestXMLGhostCellsImport.cxx
......
#include <vtkDataArray.h>
#include <vtkMultiBlockDataSet.h>
#include <vtkNew.h>
#include <vtkPointData.h>
#include <vtkPolyData.h>
#include <vtkSphereSource.h>
#include <vtkTesting.h>
#include <vtkXMLMultiBlockDataReader.h>
#include <vtkXMLMultiBlockDataWriter.h>
int TestMultiBlockXMLIOWithPartialArrays(int argc, char* argv[])
{
vtkNew<vtkSphereSource> sp;
sp->Update();
vtkNew<vtkPolyData> pd0;
pd0->DeepCopy(sp->GetOutput());
vtkNew<vtkPolyData> pd1;
pd1->DeepCopy(sp->GetOutput());
pd1->GetPointData()->GetArray("Normals")->SetName("NewNormals");
vtkNew<vtkMultiBlockDataSet> outMB;
outMB->SetBlock(0, pd0);
outMB->SetBlock(1, pd1);
vtkNew<vtkTesting> testing;
testing->AddArguments(argc, argv);
std::ostringstream filename_stream;
filename_stream << testing->GetTempDirectory() << "/TestMultiBlockXMLIOWithPartialArrays.vtm";
vtkNew<vtkXMLMultiBlockDataWriter> writer;
writer->SetFileName(filename_stream.str().c_str());
writer->SetInputDataObject(outMB);
writer->Write();
vtkNew<vtkXMLMultiBlockDataReader> reader;
reader->SetFileName(filename_stream.str().c_str());
reader->Update();
auto inMB = vtkMultiBlockDataSet::SafeDownCast(reader->GetOutputDataObject(0));
if (inMB->GetNumberOfBlocks() != 2 ||
vtkPolyData::SafeDownCast(inMB->GetBlock(0)) == nullptr ||
vtkPolyData::SafeDownCast(inMB->GetBlock(0))->GetPointData()->GetArray("Normals") == nullptr ||
vtkPolyData::SafeDownCast(inMB->GetBlock(0))->GetPointData()->GetArray("NewNormals") != nullptr ||
vtkPolyData::SafeDownCast(inMB->GetBlock(1)) == nullptr ||
vtkPolyData::SafeDownCast(inMB->GetBlock(1))->GetPointData()->GetArray("Normals") != nullptr ||
vtkPolyData::SafeDownCast(inMB->GetBlock(1))->GetPointData()->GetArray("NewNormals") == nullptr)
{
cerr << "ERROR: In/out data mismatched!" << endl;
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
......@@ -30,10 +30,21 @@
#include <cassert>
#include <map> // needed for std::map
class vtkXMLDataReader::MapStringToInt : public std::map<std::string, int>
{
};
class vtkXMLDataReader::MapStringToInt64 : public std::map<std::string, vtkTypeInt64>
{
};
//----------------------------------------------------------------------------
vtkXMLDataReader::vtkXMLDataReader()
: PointDataTimeStep(new vtkXMLDataReader::MapStringToInt())
, PointDataOffset(new vtkXMLDataReader::MapStringToInt64())
, CellDataTimeStep(new vtkXMLDataReader::MapStringToInt())
, CellDataOffset(new vtkXMLDataReader::MapStringToInt64())
{
this->NumberOfPieces = 0;
this->PointDataElements = nullptr;
......@@ -47,11 +58,6 @@ vtkXMLDataReader::vtkXMLDataReader()
this->DataProgressObserver = vtkCallbackCommand::New();
this->DataProgressObserver->SetCallback(&vtkXMLDataReader::DataProgressCallbackFunction);
this->DataProgressObserver->SetClientData(this);
this->PointDataTimeStep = nullptr;
this->PointDataOffset = nullptr;
this->CellDataTimeStep = nullptr;
this->CellDataOffset = nullptr;
}
//----------------------------------------------------------------------------
......@@ -66,16 +72,6 @@ vtkXMLDataReader::~vtkXMLDataReader()
this->DestroyPieces();
}
this->DataProgressObserver->Delete();
if (this->NumberOfPointArrays)
{
delete[] this->PointDataTimeStep;
delete[] this->PointDataOffset;
}
if (this->NumberOfCellArrays)
{
delete[] this->CellDataTimeStep;
delete[] this->CellDataOffset;
}
}
//----------------------------------------------------------------------------
......@@ -270,16 +266,21 @@ void vtkXMLDataReader::SetupOutputData()
// from one piece because all pieces have the same set of arrays.
vtkXMLDataElement* ePointData = this->PointDataElements[0];
vtkXMLDataElement* eCellData = this->CellDataElements[0];
this->NumberOfPointArrays = 0;
this->PointDataTimeStep->clear();
this->PointDataOffset->clear();
if (ePointData)
{
for (int i = 0; i < ePointData->GetNumberOfNestedElements(); i++)
{
vtkXMLDataElement* eNested = ePointData->GetNestedElement(i);
if (this->PointDataArrayIsEnabled(eNested) &&
!pointData->HasArray(eNested->GetAttribute("Name")))
const char* ename = eNested->GetAttribute("Name");
if (this->PointDataArrayIsEnabled(eNested) && !pointData->HasArray(ename))
{
this->NumberOfPointArrays++;
(*this->PointDataTimeStep)[ename] = -1;
(*this->PointDataOffset)[ename] = -1;
vtkAbstractArray* array = this->CreateArray(eNested);
if (array)
{
......@@ -294,18 +295,20 @@ void vtkXMLDataReader::SetupOutputData()
}
}
}
assert(this->NumberOfPointArrays == this->PointDataArraySelection->GetNumberOfArraysEnabled());
this->NumberOfCellArrays = 0;
this->CellDataTimeStep->clear();
this->CellDataOffset->clear();
if (eCellData)
{
for (int i = 0; i < eCellData->GetNumberOfNestedElements(); i++)
{
vtkXMLDataElement* eNested = eCellData->GetNestedElement(i);
if (this->CellDataArrayIsEnabled(eNested) &&
!cellData->HasArray(eNested->GetAttribute("Name")))
const char* ename = eNested->GetAttribute("Name");
if (this->CellDataArrayIsEnabled(eNested) && !cellData->HasArray(ename))
{
this->NumberOfCellArrays++;
(*this->CellDataTimeStep)[ename] = -1;
(*this->CellDataOffset)[ename] = -1;
vtkAbstractArray* array = this->CreateArray(eNested);
if (array)
{
......@@ -320,41 +323,10 @@ void vtkXMLDataReader::SetupOutputData()
}
}
}
assert(this->NumberOfCellArrays == this->CellDataArraySelection->GetNumberOfArraysEnabled());
// Setup attribute indices for the point data and cell data.
this->ReadAttributeIndices(ePointData, pointData);
this->ReadAttributeIndices(eCellData, cellData);
// Since NumberOfCellArrays and NumberOfPointArrays are valid
// lets allocate PointDataTimeStep, CellDataTimeStep, PointDataOffset
// CellDataOffset
if (this->NumberOfPointArrays)
{
delete [] this->PointDataTimeStep;
delete [] this->PointDataOffset;
this->PointDataTimeStep = new int[this->NumberOfPointArrays];
this->PointDataOffset = new vtkTypeInt64[this->NumberOfPointArrays];
for (int i = 0; i < this->NumberOfPointArrays; i++)
{
this->PointDataTimeStep[i] = -1;
this->PointDataOffset[i] = -1;
}
}
if (this->NumberOfCellArrays)
{
delete [] this->CellDataTimeStep;
delete [] this->CellDataOffset;
this->CellDataTimeStep = new int[this->NumberOfCellArrays];
this->CellDataOffset = new vtkTypeInt64[this->NumberOfCellArrays];
for (int i = 0; i < this->NumberOfCellArrays; i++)
{
this->CellDataTimeStep[i] = -1;
this->CellDataOffset[i] = -1;
}
}
}
//----------------------------------------------------------------------------
......@@ -579,7 +551,6 @@ int vtkXMLDataReader::PointDataNeedToReadTimeStep(vtkXMLDataElement *eNested)
{
// First thing need to find the id of this dataarray from its name:
const char* name = eNested->GetAttribute("Name");
int idx = this->PointDataArraySelection->GetEnabledArrayIndex(name);
// Easy case no timestep:
int numTimeSteps = eNested->GetVectorAttribute("TimeStep",
......@@ -592,7 +563,7 @@ int vtkXMLDataReader::PointDataNeedToReadTimeStep(vtkXMLDataElement *eNested)
}
if (!numTimeSteps && !this->NumberOfTimeSteps)
{
assert(this->PointDataTimeStep[idx] == -1); //No timestep in this file
assert(this->PointDataTimeStep->at(name) == -1); // No timestep in this file
return 1;
}
// else TimeStep was specified but no TimeValues associated were found
......@@ -611,11 +582,11 @@ int vtkXMLDataReader::PointDataNeedToReadTimeStep(vtkXMLDataElement *eNested)
vtkTypeInt64 offset;
if (eNested->GetScalarAttribute("offset", offset))
{
if (this->PointDataOffset[idx] != offset)
if (this->PointDataOffset->at(name) != offset)
{
// save the pointsOffset
assert(this->PointDataTimeStep[idx] == -1); //cannot have mixture of binary and appended
this->PointDataOffset[idx] = offset;
assert(this->PointDataTimeStep->at(name) == -1); // cannot have mixture of binary and appended
this->PointDataOffset->at(name) = offset;
return 1;
}
}
......@@ -623,20 +594,20 @@ int vtkXMLDataReader::PointDataNeedToReadTimeStep(vtkXMLDataElement *eNested)
{
// No offset is specified this is a binary file
// First thing to check if numTimeSteps == 0:
if (!numTimeSteps && this->NumberOfTimeSteps && this->PointDataTimeStep[idx] == -1)
if (!numTimeSteps && this->NumberOfTimeSteps && this->PointDataTimeStep->at(name) == -1)
{
// Update last PointsTimeStep read
this->PointDataTimeStep[idx] = this->CurrentTimeStep;
(*this->PointDataTimeStep)[name] = this->CurrentTimeStep;
return 1;
}
int isLastTimeInArray = vtkXMLReader::IsTimeStepInArray(
this->PointDataTimeStep[idx], this->TimeSteps, numTimeSteps);
// If no time is specified or if time is specified and match then read
this->PointDataTimeStep->at(name), this->TimeSteps, numTimeSteps);
// If no time is specified or if time is specified and match then read
if (isCurrentTimeInArray && !isLastTimeInArray)
{
// CurrentTimeStep is in TimeSteps but Last is not := need to read
// Update last PointsTimeStep read
this->PointDataTimeStep[idx] = this->CurrentTimeStep;
this->PointDataTimeStep->at(name) = this->CurrentTimeStep;
return 1;
}
}
......@@ -649,7 +620,6 @@ int vtkXMLDataReader::CellDataNeedToReadTimeStep(vtkXMLDataElement *eNested)
{
// First thing need to find the id of this dataarray from its name:
const char* name = eNested->GetAttribute("Name");
int idx = this->CellDataArraySelection->GetEnabledArrayIndex(name);
// Easy case no timestep:
int numTimeSteps = eNested->GetVectorAttribute("TimeStep",
......@@ -662,7 +632,7 @@ int vtkXMLDataReader::CellDataNeedToReadTimeStep(vtkXMLDataElement *eNested)
}
if (!numTimeSteps && !this->NumberOfTimeSteps)
{
assert(this->CellDataTimeStep[idx] == -1); //No timestep in this file
assert(this->CellDataTimeStep->at(name) == -1); // No timestep in this file
return 1;
}
// else TimeStep was specified but no TimeValues associated were found
......@@ -681,11 +651,11 @@ int vtkXMLDataReader::CellDataNeedToReadTimeStep(vtkXMLDataElement *eNested)
vtkTypeInt64 offset;
if (eNested->GetScalarAttribute("offset", offset))
{
if (this->CellDataOffset[idx] != offset)
if (this->CellDataOffset->at(name) != offset)
{
// save the pointsOffset
assert(this->CellDataTimeStep[idx] == -1); //cannot have mixture of binary and appended
this->CellDataOffset[idx] = offset;
assert(this->CellDataTimeStep->at(name) == -1); // cannot have mixture of binary and appended
this->CellDataOffset->at(name) = offset;
return 1;
}
}
......@@ -693,20 +663,20 @@ int vtkXMLDataReader::CellDataNeedToReadTimeStep(vtkXMLDataElement *eNested)
{
// No offset is specified this is a binary file
// First thing to check if numTimeSteps == 0:
if (!numTimeSteps && this->NumberOfTimeSteps && this->CellDataTimeStep[idx] == -1)
if (!numTimeSteps && this->NumberOfTimeSteps && this->CellDataTimeStep->at(name) == -1)
{
// Update last CellDataTimeStep read
this->CellDataTimeStep[idx] = this->CurrentTimeStep;
this->CellDataTimeStep->at(name) = this->CurrentTimeStep;
return 1;
}
int isLastTimeInArray = vtkXMLReader::IsTimeStepInArray(
this->CellDataTimeStep[idx], this->TimeSteps, numTimeSteps);
// If no time is specified or if time is specified and match then read
this->CellDataTimeStep->at(name), this->TimeSteps, numTimeSteps);
// If no time is specified or if time is specified and match then read
if (isCurrentTimeInArray && !isLastTimeInArray)
{
// CurrentTimeStep is in TimeSteps but Last is not := need to read
// Update last CellsTimeStep read
this->CellDataTimeStep[idx] = this->CurrentTimeStep;
this->CellDataTimeStep->at(name) = this->CurrentTimeStep;
return 1;
}
}
......
......@@ -30,6 +30,8 @@
#include "vtkIOXMLModule.h" // For export macro
#include "vtkXMLReader.h"
#include <memory> // for std::unique_ptr
class VTKIOXML_EXPORT vtkXMLDataReader : public vtkXMLReader
{
public:
......@@ -108,25 +110,27 @@ protected:
// The observer to report progress from reading data from XMLParser.
vtkCallbackCommand* DataProgressObserver;
private:
class MapStringToInt;
class MapStringToInt64;
// Specify the last time step read, useful to know if we need to rearead data
// //PointData
int *PointDataTimeStep;
vtkTypeInt64 *PointDataOffset;
std::unique_ptr<MapStringToInt> PointDataTimeStep;
std::unique_ptr<MapStringToInt64> PointDataOffset;
int PointDataNeedToReadTimeStep(vtkXMLDataElement *eNested);
//CellData
int *CellDataTimeStep;
vtkTypeInt64 *CellDataOffset;
std::unique_ptr<MapStringToInt> CellDataTimeStep;
std::unique_ptr<MapStringToInt64> CellDataOffset;
int CellDataNeedToReadTimeStep(vtkXMLDataElement *eNested);
private:
vtkXMLDataReader(const vtkXMLDataReader&) = delete;
void operator=(const vtkXMLDataReader&) = delete;
void ConvertGhostLevelsToGhostType(
FieldType type, vtkAbstractArray* data, vtkIdType startIndex,
vtkIdType numValues) override;
};
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment