mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-07-30 02:34:02 +00:00
Move VTKDataSetReaderBase code to vtkm_io
Most of this code is not templated methods. Rather, it implements over several types to call templated functions, which creates quite a bit of code. Rather than have all code using a reader recompile the code, just compile it once and put it in a library.
This commit is contained in:
parent
11a341ced5
commit
0612be9c5b
@ -52,7 +52,7 @@ set(VTKm_BENCHS_RANGE_UPPER_BOUNDARY 134217728 CACHE STRING "Biggest sample for
|
||||
mark_as_advanced(VTKm_BENCHS_RANGE_LOWER_BOUNDARY VTKm_BENCHS_RANGE_UPPER_BOUNDARY)
|
||||
|
||||
foreach (benchmark ${benchmarks})
|
||||
add_benchmark(NAME ${benchmark} FILE ${benchmark}.cxx LIBS vtkm_source vtkm_filter)
|
||||
add_benchmark(NAME ${benchmark} FILE ${benchmark}.cxx LIBS vtkm_source vtkm_filter vtkm_io)
|
||||
endforeach ()
|
||||
|
||||
target_compile_definitions(BenchmarkDeviceAdapter PUBLIC VTKm_BENCHS_RANGE_LOWER_BOUNDARY=${VTKm_BENCHS_RANGE_LOWER_BOUNDARY})
|
||||
|
@ -26,7 +26,7 @@ project(MeshQuality CXX)
|
||||
find_package(VTKm REQUIRED QUIET)
|
||||
|
||||
add_executable(MeshQuality MeshQuality.cxx)
|
||||
target_link_libraries(MeshQuality PRIVATE vtkm_filter)
|
||||
target_link_libraries(MeshQuality PRIVATE vtkm_filter vtkm_io)
|
||||
|
||||
if(TARGET vtkm::tbb)
|
||||
target_compile_definitions(MeshQuality PRIVATE BUILDING_TBB_VERSION)
|
||||
|
@ -14,7 +14,7 @@ project(ParticleAdvection CXX)
|
||||
find_package(VTKm REQUIRED QUIET)
|
||||
|
||||
add_executable(Particle_Advection ParticleAdvection.cxx)
|
||||
target_link_libraries(Particle_Advection PRIVATE vtkm_filter)
|
||||
target_link_libraries(Particle_Advection PRIVATE vtkm_filter vtkm_io)
|
||||
vtkm_add_target_information(Particle_Advection
|
||||
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
|
||||
DEVICE_SOURCES ParticleAdvection.cxx)
|
||||
|
@ -13,7 +13,7 @@ project(RedistributePoints CXX)
|
||||
#Find the VTK-m package
|
||||
find_package(VTKm REQUIRED QUIET)
|
||||
add_executable(RedistributePoints RedistributePoints.cxx RedistributePoints.h)
|
||||
target_link_libraries(RedistributePoints PRIVATE vtkm_filter)
|
||||
target_link_libraries(RedistributePoints PRIVATE vtkm_filter vtkm_io)
|
||||
vtkm_add_target_information(RedistributePoints
|
||||
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
|
||||
DEVICE_SOURCES RedistributePoints.cxx)
|
||||
|
@ -19,4 +19,4 @@ add_executable(Temporal_Advection TemporalAdvection.cxx)
|
||||
vtkm_add_target_information(Temporal_Advection
|
||||
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
|
||||
DEVICE_SOURCES TemporalAdvection.cxx)
|
||||
target_link_libraries(Temporal_Advection PRIVATE vtkm_filter)
|
||||
target_link_libraries(Temporal_Advection PRIVATE vtkm_filter vtkm_io)
|
||||
|
@ -69,7 +69,7 @@ set(unit_tests
|
||||
|
||||
vtkm_unit_tests(
|
||||
SOURCES ${unit_tests}
|
||||
LIBRARIES vtkm_filter vtkm_source
|
||||
LIBRARIES vtkm_filter vtkm_source vtkm_io
|
||||
ALL_BACKENDS
|
||||
USE_VTKM_JOB_POOL
|
||||
)
|
||||
|
@ -35,6 +35,7 @@ set(template_sources
|
||||
set(sources
|
||||
DecodePNG.cxx
|
||||
EncodePNG.cxx
|
||||
VTKDataSetReaderBase.cxx
|
||||
)
|
||||
|
||||
vtkm_declare_headers(
|
||||
|
826
vtkm/io/VTKDataSetReaderBase.cxx
Normal file
826
vtkm/io/VTKDataSetReaderBase.cxx
Normal file
@ -0,0 +1,826 @@
|
||||
//============================================================================
|
||||
// Copyright (c) Kitware, Inc.
|
||||
// All rights reserved.
|
||||
// See LICENSE.txt 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 <vtkm/io/VTKDataSetReaderBase.h>
|
||||
|
||||
#include <vtkm/VecTraits.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayPortalToIterators.h>
|
||||
#include <vtkm/cont/Logging.h>
|
||||
#include <vtkm/cont/VariantArrayHandle.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
inline void PrintVTKDataFileSummary(const vtkm::io::internal::VTKDataSetFile& df, std::ostream& out)
|
||||
{
|
||||
out << "\tFile: " << df.FileName << std::endl;
|
||||
out << "\tVersion: " << df.Version[0] << "." << df.Version[0] << std::endl;
|
||||
out << "\tTitle: " << df.Title << std::endl;
|
||||
out << "\tFormat: " << (df.IsBinary ? "BINARY" : "ASCII") << std::endl;
|
||||
out << "\tDataSet type: " << vtkm::io::internal::DataSetStructureString(df.Structure)
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
// Since Fields and DataSets store data in the default VariantArrayHandle, convert
|
||||
// the data to the closest type supported by default. The following will
|
||||
// need to be updated if VariantArrayHandle or TypeListCommon changes.
|
||||
template <typename T>
|
||||
struct ClosestCommonType
|
||||
{
|
||||
using Type = T;
|
||||
};
|
||||
template <>
|
||||
struct ClosestCommonType<vtkm::Int8>
|
||||
{
|
||||
using Type = vtkm::Int32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestCommonType<vtkm::UInt8>
|
||||
{
|
||||
using Type = vtkm::Int32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestCommonType<vtkm::Int16>
|
||||
{
|
||||
using Type = vtkm::Int32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestCommonType<vtkm::UInt16>
|
||||
{
|
||||
using Type = vtkm::Int32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestCommonType<vtkm::UInt32>
|
||||
{
|
||||
using Type = vtkm::Int64;
|
||||
};
|
||||
template <>
|
||||
struct ClosestCommonType<vtkm::UInt64>
|
||||
{
|
||||
using Type = vtkm::Int64;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ClosestFloat
|
||||
{
|
||||
using Type = T;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::Int8>
|
||||
{
|
||||
using Type = vtkm::Float32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::UInt8>
|
||||
{
|
||||
using Type = vtkm::Float32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::Int16>
|
||||
{
|
||||
using Type = vtkm::Float32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::UInt16>
|
||||
{
|
||||
using Type = vtkm::Float32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::Int32>
|
||||
{
|
||||
using Type = vtkm::Float64;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::UInt32>
|
||||
{
|
||||
using Type = vtkm::Float64;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::Int64>
|
||||
{
|
||||
using Type = vtkm::Float64;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::UInt64>
|
||||
{
|
||||
using Type = vtkm::Float64;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
vtkm::cont::VariantArrayHandle CreateVariantArrayHandle(const std::vector<T>& vec)
|
||||
{
|
||||
switch (vtkm::VecTraits<T>::NUM_COMPONENTS)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
using CommonType = typename ClosestCommonType<T>::Type;
|
||||
constexpr bool not_same = !std::is_same<T, CommonType>::value;
|
||||
if (not_same)
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
"Type " << vtkm::io::internal::DataTypeName<T>::Name()
|
||||
<< " is currently unsupported. Converting to "
|
||||
<< vtkm::io::internal::DataTypeName<CommonType>::Name()
|
||||
<< ".");
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<CommonType> output;
|
||||
output.Allocate(static_cast<vtkm::Id>(vec.size()));
|
||||
auto portal = output.WritePortal();
|
||||
for (vtkm::Id i = 0; i < output.GetNumberOfValues(); ++i)
|
||||
{
|
||||
portal.Set(i, static_cast<CommonType>(vec[static_cast<std::size_t>(i)]));
|
||||
}
|
||||
|
||||
return vtkm::cont::VariantArrayHandle(output);
|
||||
}
|
||||
case 2:
|
||||
case 3:
|
||||
case 9:
|
||||
{
|
||||
constexpr auto numComps = vtkm::VecTraits<T>::NUM_COMPONENTS;
|
||||
|
||||
using InComponentType = typename vtkm::VecTraits<T>::ComponentType;
|
||||
using OutComponentType = typename ClosestFloat<InComponentType>::Type;
|
||||
using CommonType = vtkm::Vec<OutComponentType, numComps>;
|
||||
constexpr bool not_same = !std::is_same<T, CommonType>::value;
|
||||
if (not_same)
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
"Type " << vtkm::io::internal::DataTypeName<InComponentType>::Name() << "["
|
||||
<< vtkm::VecTraits<T>::GetNumberOfComponents(T())
|
||||
<< "] "
|
||||
<< "is currently unsupported. Converting to "
|
||||
<< vtkm::io::internal::DataTypeName<OutComponentType>::Name()
|
||||
<< "["
|
||||
<< numComps
|
||||
<< "].");
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<CommonType> output;
|
||||
output.Allocate(static_cast<vtkm::Id>(vec.size()));
|
||||
auto portal = output.WritePortal();
|
||||
for (vtkm::Id i = 0; i < output.GetNumberOfValues(); ++i)
|
||||
{
|
||||
CommonType outval = CommonType();
|
||||
for (vtkm::IdComponent j = 0; j < numComps; ++j)
|
||||
{
|
||||
outval[j] = static_cast<OutComponentType>(
|
||||
vtkm::VecTraits<T>::GetComponent(vec[static_cast<std::size_t>(i)], j));
|
||||
}
|
||||
portal.Set(i, outval);
|
||||
}
|
||||
|
||||
return vtkm::cont::VariantArrayHandle(output);
|
||||
}
|
||||
default:
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn, "Only 1, 2, 3, or 9 components supported. Skipping.");
|
||||
return vtkm::cont::VariantArrayHandle(vtkm::cont::ArrayHandle<vtkm::Float32>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
namespace io
|
||||
{
|
||||
|
||||
VTKDataSetReaderBase::VTKDataSetReaderBase(const char* fileName)
|
||||
: DataFile(new internal::VTKDataSetFile)
|
||||
, DataSet()
|
||||
, Loaded(false)
|
||||
{
|
||||
this->DataFile->FileName = fileName;
|
||||
}
|
||||
|
||||
VTKDataSetReaderBase::VTKDataSetReaderBase(const std::string& fileName)
|
||||
: DataFile(new internal::VTKDataSetFile)
|
||||
, DataSet()
|
||||
, Loaded(false)
|
||||
{
|
||||
this->DataFile->FileName = fileName;
|
||||
}
|
||||
|
||||
VTKDataSetReaderBase::~VTKDataSetReaderBase()
|
||||
{
|
||||
}
|
||||
|
||||
const vtkm::cont::DataSet& VTKDataSetReaderBase::ReadDataSet()
|
||||
{
|
||||
if (!this->Loaded)
|
||||
{
|
||||
try
|
||||
{
|
||||
this->OpenFile();
|
||||
this->ReadHeader();
|
||||
this->Read();
|
||||
this->CloseFile();
|
||||
this->Loaded = true;
|
||||
}
|
||||
catch (std::ifstream::failure& e)
|
||||
{
|
||||
std::string message("IO Error: ");
|
||||
throw vtkm::io::ErrorIO(message + e.what());
|
||||
}
|
||||
}
|
||||
|
||||
return this->DataSet;
|
||||
}
|
||||
|
||||
void VTKDataSetReaderBase::PrintSummary(std::ostream& out) const
|
||||
{
|
||||
out << "VTKDataSetReader" << std::endl;
|
||||
PrintVTKDataFileSummary(*this->DataFile.get(), out);
|
||||
this->DataSet.PrintSummary(out);
|
||||
}
|
||||
|
||||
void VTKDataSetReaderBase::ReadPoints()
|
||||
{
|
||||
std::string dataType;
|
||||
std::size_t numPoints;
|
||||
this->DataFile->Stream >> numPoints >> dataType >> std::ws;
|
||||
|
||||
vtkm::cont::VariantArrayHandle points =
|
||||
this->DoReadArrayVariant(vtkm::cont::Field::Association::POINTS, dataType, numPoints, 3);
|
||||
|
||||
this->DataSet.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", points));
|
||||
}
|
||||
|
||||
void VTKDataSetReaderBase::ReadCells(vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
|
||||
vtkm::cont::ArrayHandle<vtkm::IdComponent>& numIndices)
|
||||
{
|
||||
vtkm::Id numCells, numInts;
|
||||
this->DataFile->Stream >> numCells >> numInts >> std::ws;
|
||||
|
||||
connectivity.Allocate(numInts - numCells);
|
||||
numIndices.Allocate(numCells);
|
||||
|
||||
std::vector<vtkm::Int32> buffer(static_cast<std::size_t>(numInts));
|
||||
this->ReadArray(buffer);
|
||||
|
||||
vtkm::Int32* buffp = &buffer[0];
|
||||
auto connectivityPortal = connectivity.WritePortal();
|
||||
auto numIndicesPortal = numIndices.WritePortal();
|
||||
for (vtkm::Id i = 0, connInd = 0; i < numCells; ++i)
|
||||
{
|
||||
vtkm::IdComponent numInds = static_cast<vtkm::IdComponent>(*buffp++);
|
||||
numIndicesPortal.Set(i, numInds);
|
||||
for (vtkm::IdComponent j = 0; j < numInds; ++j, ++connInd)
|
||||
{
|
||||
connectivityPortal.Set(connInd, static_cast<vtkm::Id>(*buffp++));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VTKDataSetReaderBase::ReadShapes(vtkm::cont::ArrayHandle<vtkm::UInt8>& shapes)
|
||||
{
|
||||
std::string tag;
|
||||
vtkm::Id numCells;
|
||||
this->DataFile->Stream >> tag >> numCells >> std::ws;
|
||||
internal::parseAssert(tag == "CELL_TYPES");
|
||||
|
||||
shapes.Allocate(numCells);
|
||||
std::vector<vtkm::Int32> buffer(static_cast<std::size_t>(numCells));
|
||||
this->ReadArray(buffer);
|
||||
|
||||
vtkm::Int32* buffp = &buffer[0];
|
||||
auto shapesPortal = shapes.WritePortal();
|
||||
for (vtkm::Id i = 0; i < numCells; ++i)
|
||||
{
|
||||
shapesPortal.Set(i, static_cast<vtkm::UInt8>(*buffp++));
|
||||
}
|
||||
}
|
||||
|
||||
void VTKDataSetReaderBase::ReadAttributes()
|
||||
{
|
||||
if (this->DataFile->Stream.eof())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vtkm::cont::Field::Association association = vtkm::cont::Field::Association::ANY;
|
||||
std::size_t size;
|
||||
|
||||
std::string tag;
|
||||
this->DataFile->Stream >> tag;
|
||||
while (!this->DataFile->Stream.eof())
|
||||
{
|
||||
if (tag == "POINT_DATA")
|
||||
{
|
||||
association = vtkm::cont::Field::Association::POINTS;
|
||||
}
|
||||
else if (tag == "CELL_DATA")
|
||||
{
|
||||
association = vtkm::cont::Field::Association::CELL_SET;
|
||||
}
|
||||
else
|
||||
{
|
||||
internal::parseAssert(false);
|
||||
}
|
||||
|
||||
this->DataFile->Stream >> size;
|
||||
while (!this->DataFile->Stream.eof())
|
||||
{
|
||||
this->DataFile->Stream >> tag;
|
||||
if (tag == "SCALARS")
|
||||
{
|
||||
this->ReadScalars(association, size);
|
||||
}
|
||||
else if (tag == "COLOR_SCALARS")
|
||||
{
|
||||
this->ReadColorScalars(association, size);
|
||||
}
|
||||
else if (tag == "LOOKUP_TABLE")
|
||||
{
|
||||
this->ReadLookupTable();
|
||||
}
|
||||
else if (tag == "VECTORS" || tag == "NORMALS")
|
||||
{
|
||||
this->ReadVectors(association, size);
|
||||
}
|
||||
else if (tag == "TEXTURE_COORDINATES")
|
||||
{
|
||||
this->ReadTextureCoordinates(association, size);
|
||||
}
|
||||
else if (tag == "TENSORS")
|
||||
{
|
||||
this->ReadTensors(association, size);
|
||||
}
|
||||
else if (tag == "FIELD")
|
||||
{
|
||||
this->ReadFields(association, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VTKDataSetReaderBase::CloseFile()
|
||||
{
|
||||
this->DataFile->Stream.close();
|
||||
}
|
||||
|
||||
void VTKDataSetReaderBase::OpenFile()
|
||||
{
|
||||
this->DataFile->Stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
try
|
||||
{
|
||||
this->DataFile->Stream.open(this->DataFile->FileName.c_str(),
|
||||
std::ios_base::in | std::ios_base::binary);
|
||||
}
|
||||
catch (std::ifstream::failure&)
|
||||
{
|
||||
std::string message("could not open file \"" + this->DataFile->FileName + "\"");
|
||||
throw vtkm::io::ErrorIO(message);
|
||||
}
|
||||
}
|
||||
|
||||
void VTKDataSetReaderBase::ReadHeader()
|
||||
{
|
||||
char vstring[] = "# vtk DataFile Version";
|
||||
const std::size_t vlen = sizeof(vstring);
|
||||
|
||||
// Read version line
|
||||
char vbuf[vlen];
|
||||
this->DataFile->Stream.read(vbuf, vlen - 1);
|
||||
vbuf[vlen - 1] = '\0';
|
||||
if (std::string(vbuf) != std::string(vstring))
|
||||
{
|
||||
throw vtkm::io::ErrorIO("Incorrect file format.");
|
||||
}
|
||||
|
||||
char dot;
|
||||
this->DataFile->Stream >> this->DataFile->Version[0] >> dot >> this->DataFile->Version[1];
|
||||
// skip rest of the line
|
||||
std::string skip;
|
||||
std::getline(this->DataFile->Stream, skip);
|
||||
|
||||
if ((this->DataFile->Version[0] > 4) ||
|
||||
(this->DataFile->Version[0] == 4 && this->DataFile->Version[1] > 2))
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||
"Reader may not correctly read >v4.2 files. Reading version "
|
||||
<< this->DataFile->Version[0]
|
||||
<< "."
|
||||
<< this->DataFile->Version[1]
|
||||
<< ".\n");
|
||||
}
|
||||
|
||||
// Read title line
|
||||
std::getline(this->DataFile->Stream, this->DataFile->Title);
|
||||
|
||||
// Read format line
|
||||
this->DataFile->IsBinary = false;
|
||||
std::string format;
|
||||
this->DataFile->Stream >> format >> std::ws;
|
||||
if (format == "BINARY")
|
||||
{
|
||||
this->DataFile->IsBinary = true;
|
||||
}
|
||||
else if (format != "ASCII")
|
||||
{
|
||||
throw vtkm::io::ErrorIO("Unsupported Format.");
|
||||
}
|
||||
|
||||
// Read structure line
|
||||
std::string tag, structStr;
|
||||
this->DataFile->Stream >> tag >> structStr >> std::ws;
|
||||
internal::parseAssert(tag == "DATASET");
|
||||
|
||||
this->DataFile->Structure = vtkm::io::internal::DataSetStructureId(structStr);
|
||||
if (this->DataFile->Structure == vtkm::io::internal::DATASET_UNKNOWN)
|
||||
{
|
||||
throw vtkm::io::ErrorIO("Unsupported DataSet type.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void VTKDataSetReaderBase::AddField(const std::string& name,
|
||||
vtkm::cont::Field::Association association,
|
||||
vtkm::cont::VariantArrayHandle& data)
|
||||
{
|
||||
if (data.GetNumberOfValues() > 0)
|
||||
{
|
||||
switch (association)
|
||||
{
|
||||
case vtkm::cont::Field::Association::POINTS:
|
||||
case vtkm::cont::Field::Association::WHOLE_MESH:
|
||||
this->DataSet.AddField(vtkm::cont::Field(name, association, data));
|
||||
break;
|
||||
case vtkm::cont::Field::Association::CELL_SET:
|
||||
this->DataSet.AddField(vtkm::cont::Field(name, association, data));
|
||||
break;
|
||||
default:
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||
"Not recording field '" << name << "' because it has an unknown association");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VTKDataSetReaderBase::ReadScalars(vtkm::cont::Field::Association association,
|
||||
std::size_t numElements)
|
||||
{
|
||||
std::string dataName, dataType, lookupTableName;
|
||||
vtkm::IdComponent numComponents = 1;
|
||||
this->DataFile->Stream >> dataName >> dataType;
|
||||
std::string tag;
|
||||
this->DataFile->Stream >> tag;
|
||||
if (tag != "LOOKUP_TABLE")
|
||||
{
|
||||
try
|
||||
{
|
||||
numComponents = std::stoi(tag);
|
||||
}
|
||||
catch (std::invalid_argument&)
|
||||
{
|
||||
internal::parseAssert(false);
|
||||
}
|
||||
this->DataFile->Stream >> tag;
|
||||
}
|
||||
|
||||
internal::parseAssert(tag == "LOOKUP_TABLE");
|
||||
this->DataFile->Stream >> lookupTableName >> std::ws;
|
||||
|
||||
vtkm::cont::VariantArrayHandle data =
|
||||
this->DoReadArrayVariant(association, dataType, numElements, numComponents);
|
||||
this->AddField(dataName, association, data);
|
||||
}
|
||||
|
||||
void VTKDataSetReaderBase::ReadColorScalars(vtkm::cont::Field::Association association,
|
||||
std::size_t numElements)
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn, "Support for COLOR_SCALARS is not implemented. Skipping.");
|
||||
|
||||
std::string dataName;
|
||||
vtkm::IdComponent numComponents;
|
||||
this->DataFile->Stream >> dataName >> numComponents >> std::ws;
|
||||
std::string dataType = this->DataFile->IsBinary ? "unsigned_char" : "float";
|
||||
vtkm::cont::VariantArrayHandle data =
|
||||
this->DoReadArrayVariant(association, dataType, numElements, numComponents);
|
||||
this->AddField(dataName, association, data);
|
||||
}
|
||||
|
||||
void VTKDataSetReaderBase::ReadLookupTable()
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn, "Support for LOOKUP_TABLE is not implemented. Skipping.");
|
||||
|
||||
std::string dataName;
|
||||
std::size_t numEntries;
|
||||
this->DataFile->Stream >> dataName >> numEntries >> std::ws;
|
||||
this->SkipArray(numEntries, vtkm::Vec<vtkm::io::internal::ColorChannel8, 4>());
|
||||
}
|
||||
|
||||
void VTKDataSetReaderBase::ReadTextureCoordinates(vtkm::cont::Field::Association association,
|
||||
std::size_t numElements)
|
||||
{
|
||||
std::string dataName;
|
||||
vtkm::IdComponent numComponents;
|
||||
std::string dataType;
|
||||
this->DataFile->Stream >> dataName >> numComponents >> dataType >> std::ws;
|
||||
|
||||
vtkm::cont::VariantArrayHandle data =
|
||||
this->DoReadArrayVariant(association, dataType, numElements, numComponents);
|
||||
this->AddField(dataName, association, data);
|
||||
}
|
||||
|
||||
void VTKDataSetReaderBase::ReadVectors(vtkm::cont::Field::Association association,
|
||||
std::size_t numElements)
|
||||
{
|
||||
std::string dataName;
|
||||
std::string dataType;
|
||||
this->DataFile->Stream >> dataName >> dataType >> std::ws;
|
||||
|
||||
vtkm::cont::VariantArrayHandle data =
|
||||
this->DoReadArrayVariant(association, dataType, numElements, 3);
|
||||
this->AddField(dataName, association, data);
|
||||
}
|
||||
|
||||
void VTKDataSetReaderBase::ReadTensors(vtkm::cont::Field::Association association,
|
||||
std::size_t numElements)
|
||||
{
|
||||
std::string dataName;
|
||||
std::string dataType;
|
||||
this->DataFile->Stream >> dataName >> dataType >> std::ws;
|
||||
|
||||
vtkm::cont::VariantArrayHandle data =
|
||||
this->DoReadArrayVariant(association, dataType, numElements, 9);
|
||||
this->AddField(dataName, association, data);
|
||||
}
|
||||
|
||||
void VTKDataSetReaderBase::ReadFields(vtkm::cont::Field::Association association,
|
||||
std::size_t expectedNumElements)
|
||||
{
|
||||
std::string dataName;
|
||||
vtkm::Id numArrays;
|
||||
this->DataFile->Stream >> dataName >> numArrays >> std::ws;
|
||||
for (vtkm::Id i = 0; i < numArrays; ++i)
|
||||
{
|
||||
std::size_t numTuples;
|
||||
vtkm::IdComponent numComponents;
|
||||
std::string arrayName, dataType;
|
||||
this->DataFile->Stream >> arrayName >> numComponents >> numTuples >> dataType >> std::ws;
|
||||
if (numTuples == expectedNumElements)
|
||||
{
|
||||
vtkm::cont::VariantArrayHandle data =
|
||||
this->DoReadArrayVariant(association, dataType, numTuples, numComponents);
|
||||
this->AddField(arrayName, association, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||
"Field " << arrayName
|
||||
<< "'s size does not match expected number of elements. Skipping");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VTKDataSetReaderBase::ReadGlobalFields(std::vector<vtkm::Float32>* visitBounds)
|
||||
{
|
||||
std::string dataName;
|
||||
vtkm::Id numArrays;
|
||||
this->DataFile->Stream >> dataName >> numArrays >> std::ws;
|
||||
for (vtkm::Id i = 0; i < numArrays; ++i)
|
||||
{
|
||||
std::size_t numTuples;
|
||||
vtkm::IdComponent numComponents;
|
||||
std::string arrayName, dataType;
|
||||
this->DataFile->Stream >> arrayName >> numComponents >> numTuples >> dataType >> std::ws;
|
||||
if (arrayName == "avtOriginalBounds" && visitBounds)
|
||||
{
|
||||
visitBounds->resize(6);
|
||||
internal::parseAssert(numComponents == 1 && numTuples == 6);
|
||||
// parse the bounds and fill the bounds vector
|
||||
this->ReadArray(*visitBounds);
|
||||
}
|
||||
else
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
"Support for global field " << arrayName << " not implemented. Skipping.");
|
||||
this->DoSkipArrayVariant(dataType, numTuples, numComponents);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class VTKDataSetReaderBase::SkipArrayVariant
|
||||
{
|
||||
public:
|
||||
SkipArrayVariant(VTKDataSetReaderBase* reader, std::size_t numElements)
|
||||
: Reader(reader)
|
||||
, NumElements(numElements)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void operator()(T) const
|
||||
{
|
||||
this->Reader->SkipArray(this->NumElements, T());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void operator()(vtkm::IdComponent numComponents, T) const
|
||||
{
|
||||
this->Reader->SkipArray(this->NumElements * static_cast<std::size_t>(numComponents), T());
|
||||
}
|
||||
|
||||
protected:
|
||||
VTKDataSetReaderBase* Reader;
|
||||
std::size_t NumElements;
|
||||
};
|
||||
|
||||
class VTKDataSetReaderBase::ReadArrayVariant : public SkipArrayVariant
|
||||
{
|
||||
public:
|
||||
ReadArrayVariant(VTKDataSetReaderBase* reader,
|
||||
vtkm::cont::Field::Association association,
|
||||
std::size_t numElements,
|
||||
vtkm::cont::VariantArrayHandle& data)
|
||||
: SkipArrayVariant(reader, numElements)
|
||||
, Association(association)
|
||||
, Data(&data)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void operator()(T) const
|
||||
{
|
||||
std::vector<T> buffer(this->NumElements);
|
||||
this->Reader->ReadArray(buffer);
|
||||
if ((this->Association != vtkm::cont::Field::Association::CELL_SET) ||
|
||||
(this->Reader->GetCellsPermutation().GetNumberOfValues() < 1))
|
||||
{
|
||||
*this->Data = CreateVariantArrayHandle(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are reading data associated with a cell set, we need to (sometimes) permute the
|
||||
// data due to differences between VTK and VTK-m cell shapes.
|
||||
auto permutation = this->Reader->GetCellsPermutation().ReadPortal();
|
||||
vtkm::Id outSize = permutation.GetNumberOfValues();
|
||||
std::vector<T> permutedBuffer(static_cast<std::size_t>(outSize));
|
||||
for (vtkm::Id outIndex = 0; outIndex < outSize; outIndex++)
|
||||
{
|
||||
std::size_t inIndex = static_cast<std::size_t>(permutation.Get(outIndex));
|
||||
permutedBuffer[static_cast<std::size_t>(outIndex)] = buffer[inIndex];
|
||||
}
|
||||
*this->Data = CreateVariantArrayHandle(permutedBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void operator()(vtkm::IdComponent numComponents, T) const
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||
"Support for " << numComponents << " components not implemented. Skipping.");
|
||||
SkipArrayVariant::operator()(numComponents, T());
|
||||
}
|
||||
|
||||
private:
|
||||
vtkm::cont::Field::Association Association;
|
||||
vtkm::cont::VariantArrayHandle* Data;
|
||||
};
|
||||
|
||||
void VTKDataSetReaderBase::DoSkipArrayVariant(std::string dataType,
|
||||
std::size_t numElements,
|
||||
vtkm::IdComponent numComponents)
|
||||
{
|
||||
// string is unsupported for SkipArrayVariant, so it requires some
|
||||
// special handling
|
||||
if (dataType == "string")
|
||||
{
|
||||
const vtkm::Id stringCount = numComponents * static_cast<vtkm::Id>(numElements);
|
||||
for (vtkm::Id i = 0; i < stringCount; ++i)
|
||||
{
|
||||
std::string trash;
|
||||
this->DataFile->Stream >> trash;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vtkm::io::internal::DataType typeId = vtkm::io::internal::DataTypeId(dataType);
|
||||
vtkm::io::internal::SelectTypeAndCall(
|
||||
typeId, numComponents, SkipArrayVariant(this, numElements));
|
||||
}
|
||||
}
|
||||
|
||||
vtkm::cont::VariantArrayHandle VTKDataSetReaderBase::DoReadArrayVariant(
|
||||
vtkm::cont::Field::Association association,
|
||||
std::string dataType,
|
||||
std::size_t numElements,
|
||||
vtkm::IdComponent numComponents)
|
||||
{
|
||||
// Create empty data to start so that the return can check if data were actually read
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> empty;
|
||||
vtkm::cont::VariantArrayHandle data(empty);
|
||||
|
||||
vtkm::io::internal::DataType typeId = vtkm::io::internal::DataTypeId(dataType);
|
||||
vtkm::io::internal::SelectTypeAndCall(
|
||||
typeId, numComponents, ReadArrayVariant(this, association, numElements, data));
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void VTKDataSetReaderBase::ReadArray(std::vector<vtkm::io::internal::DummyBitType>& buffer)
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||
"Support for data type 'bit' is not implemented. Skipping.");
|
||||
this->SkipArray(buffer.size(), vtkm::io::internal::DummyBitType());
|
||||
buffer.clear();
|
||||
}
|
||||
|
||||
void VTKDataSetReaderBase::SkipArray(std::size_t numElements,
|
||||
vtkm::io::internal::DummyBitType,
|
||||
vtkm::IdComponent numComponents)
|
||||
{
|
||||
if (this->DataFile->IsBinary)
|
||||
{
|
||||
numElements = (numElements + 7) / 8;
|
||||
this->DataFile->Stream.seekg(static_cast<std::streamoff>(numElements), std::ios_base::cur);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (std::size_t i = 0; i < numElements; ++i)
|
||||
{
|
||||
vtkm::UInt16 val;
|
||||
this->DataFile->Stream >> val;
|
||||
}
|
||||
}
|
||||
this->DataFile->Stream >> std::ws;
|
||||
this->SkipArrayMetaData(numComponents);
|
||||
}
|
||||
|
||||
void VTKDataSetReaderBase::SkipArrayMetaData(vtkm::IdComponent numComponents)
|
||||
{
|
||||
if (!this->DataFile->Stream.good())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto begining = this->DataFile->Stream.tellg();
|
||||
|
||||
std::string tag;
|
||||
this->DataFile->Stream >> tag;
|
||||
if (tag != "METADATA")
|
||||
{
|
||||
this->DataFile->Stream.seekg(begining);
|
||||
return;
|
||||
}
|
||||
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn, "METADATA is not supported. Attempting to Skip.");
|
||||
|
||||
this->DataFile->Stream >> tag >> std::ws;
|
||||
if (tag == "COMPONENT_NAMES")
|
||||
{
|
||||
std::string name;
|
||||
for (vtkm::IdComponent i = 0; i < numComponents; ++i)
|
||||
{
|
||||
this->DataFile->Stream >> name >> std::ws;
|
||||
}
|
||||
}
|
||||
else if (tag == "INFORMATION")
|
||||
{
|
||||
int numKeys = 0;
|
||||
this->DataFile->Stream >> numKeys >> std::ws;
|
||||
|
||||
// Skipping INFORMATION is tricky. The reader needs to be aware of the types of the
|
||||
// information, which is not provided in the file.
|
||||
// Here we will just skip until an empty line is found.
|
||||
// However, if there are no keys, then there is nothing to read (and the stream tends
|
||||
// to skip over empty lines.
|
||||
if (numKeys > 0)
|
||||
{
|
||||
std::string line;
|
||||
do
|
||||
{
|
||||
std::getline(this->DataFile->Stream, line);
|
||||
} while (this->DataFile->Stream.good() && !line.empty());
|
||||
|
||||
// Eat any remaining whitespace after the INFORMATION to be ready to read the next token
|
||||
this->DataFile->Stream >> std::ws;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
internal::parseAssert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace vtkm::io
|
@ -10,25 +10,16 @@
|
||||
#ifndef vtk_m_io_VTKDataSetReaderBase_h
|
||||
#define vtk_m_io_VTKDataSetReaderBase_h
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
#include <vtkm/io/ErrorIO.h>
|
||||
#include <vtkm/io/vtkm_io_export.h>
|
||||
|
||||
#include <vtkm/io/internal/Endian.h>
|
||||
#include <vtkm/io/internal/VTKDataSetCells.h>
|
||||
#include <vtkm/io/internal/VTKDataSetStructures.h>
|
||||
#include <vtkm/io/internal/VTKDataSetTypes.h>
|
||||
|
||||
#include <vtkm/Types.h>
|
||||
#include <vtkm/VecTraits.h>
|
||||
#include <vtkm/cont/ArrayHandle.h>
|
||||
#include <vtkm/cont/ArrayPortalToIterators.h>
|
||||
#include <vtkm/cont/DataSet.h>
|
||||
#include <vtkm/cont/Logging.h>
|
||||
#include <vtkm/cont/VariantArrayHandle.h>
|
||||
#include <vtkm/internal/ExportMacros.h>
|
||||
#include <vtkm/io/ErrorIO.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace vtkm
|
||||
{
|
||||
@ -48,16 +39,6 @@ struct VTKDataSetFile
|
||||
std::ifstream Stream;
|
||||
};
|
||||
|
||||
inline void PrintVTKDataFileSummary(const VTKDataSetFile& df, std::ostream& out)
|
||||
{
|
||||
out << "\tFile: " << df.FileName << std::endl;
|
||||
out << "\tVersion: " << df.Version[0] << "." << df.Version[0] << std::endl;
|
||||
out << "\tTitle: " << df.Title << std::endl;
|
||||
out << "\tFormat: " << (df.IsBinary ? "BINARY" : "ASCII") << std::endl;
|
||||
out << "\tDataSet type: " << vtkm::io::internal::DataSetStructureString(df.Structure)
|
||||
<< std::endl;
|
||||
}
|
||||
|
||||
inline void parseAssert(bool condition)
|
||||
{
|
||||
if (!condition)
|
||||
@ -82,166 +63,6 @@ struct StreamIOType<vtkm::UInt8>
|
||||
using Type = vtkm::UInt16;
|
||||
};
|
||||
|
||||
// Since Fields and DataSets store data in the default VariantArrayHandle, convert
|
||||
// the data to the closest type supported by default. The following will
|
||||
// need to be updated if VariantArrayHandle or TypeListCommon changes.
|
||||
template <typename T>
|
||||
struct ClosestCommonType
|
||||
{
|
||||
using Type = T;
|
||||
};
|
||||
template <>
|
||||
struct ClosestCommonType<vtkm::Int8>
|
||||
{
|
||||
using Type = vtkm::Int32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestCommonType<vtkm::UInt8>
|
||||
{
|
||||
using Type = vtkm::Int32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestCommonType<vtkm::Int16>
|
||||
{
|
||||
using Type = vtkm::Int32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestCommonType<vtkm::UInt16>
|
||||
{
|
||||
using Type = vtkm::Int32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestCommonType<vtkm::UInt32>
|
||||
{
|
||||
using Type = vtkm::Int64;
|
||||
};
|
||||
template <>
|
||||
struct ClosestCommonType<vtkm::UInt64>
|
||||
{
|
||||
using Type = vtkm::Int64;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct ClosestFloat
|
||||
{
|
||||
using Type = T;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::Int8>
|
||||
{
|
||||
using Type = vtkm::Float32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::UInt8>
|
||||
{
|
||||
using Type = vtkm::Float32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::Int16>
|
||||
{
|
||||
using Type = vtkm::Float32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::UInt16>
|
||||
{
|
||||
using Type = vtkm::Float32;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::Int32>
|
||||
{
|
||||
using Type = vtkm::Float64;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::UInt32>
|
||||
{
|
||||
using Type = vtkm::Float64;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::Int64>
|
||||
{
|
||||
using Type = vtkm::Float64;
|
||||
};
|
||||
template <>
|
||||
struct ClosestFloat<vtkm::UInt64>
|
||||
{
|
||||
using Type = vtkm::Float64;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
vtkm::cont::VariantArrayHandle CreateVariantArrayHandle(const std::vector<T>& vec)
|
||||
{
|
||||
switch (vtkm::VecTraits<T>::NUM_COMPONENTS)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
using CommonType = typename ClosestCommonType<T>::Type;
|
||||
constexpr bool not_same = !std::is_same<T, CommonType>::value;
|
||||
if (not_same)
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
"Type " << vtkm::io::internal::DataTypeName<T>::Name()
|
||||
<< " is currently unsupported. Converting to "
|
||||
<< vtkm::io::internal::DataTypeName<CommonType>::Name()
|
||||
<< ".");
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<CommonType> output;
|
||||
output.Allocate(static_cast<vtkm::Id>(vec.size()));
|
||||
auto portal = output.WritePortal();
|
||||
for (vtkm::Id i = 0; i < output.GetNumberOfValues(); ++i)
|
||||
{
|
||||
portal.Set(i, static_cast<CommonType>(vec[static_cast<std::size_t>(i)]));
|
||||
}
|
||||
|
||||
return vtkm::cont::VariantArrayHandle(output);
|
||||
}
|
||||
case 2:
|
||||
case 3:
|
||||
case 9:
|
||||
{
|
||||
constexpr auto numComps = vtkm::VecTraits<T>::NUM_COMPONENTS;
|
||||
|
||||
using InComponentType = typename vtkm::VecTraits<T>::ComponentType;
|
||||
using OutComponentType = typename ClosestFloat<InComponentType>::Type;
|
||||
using CommonType = vtkm::Vec<OutComponentType, numComps>;
|
||||
constexpr bool not_same = !std::is_same<T, CommonType>::value;
|
||||
if (not_same)
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
"Type " << vtkm::io::internal::DataTypeName<InComponentType>::Name() << "["
|
||||
<< vtkm::VecTraits<T>::GetNumberOfComponents(T())
|
||||
<< "] "
|
||||
<< "is currently unsupported. Converting to "
|
||||
<< vtkm::io::internal::DataTypeName<OutComponentType>::Name()
|
||||
<< "["
|
||||
<< numComps
|
||||
<< "].");
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<CommonType> output;
|
||||
output.Allocate(static_cast<vtkm::Id>(vec.size()));
|
||||
auto portal = output.WritePortal();
|
||||
for (vtkm::Id i = 0; i < output.GetNumberOfValues(); ++i)
|
||||
{
|
||||
CommonType outval = CommonType();
|
||||
for (vtkm::IdComponent j = 0; j < numComps; ++j)
|
||||
{
|
||||
outval[j] = static_cast<OutComponentType>(
|
||||
vtkm::VecTraits<T>::GetComponent(vec[static_cast<std::size_t>(i)], j));
|
||||
}
|
||||
portal.Set(i, outval);
|
||||
}
|
||||
|
||||
return vtkm::cont::VariantArrayHandle(output);
|
||||
}
|
||||
default:
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn, "Only 1, 2, 3, or 9 components supported. Skipping.");
|
||||
return vtkm::cont::VariantArrayHandle(vtkm::cont::ArrayHandle<vtkm::Float32>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline vtkm::cont::DynamicCellSet CreateCellSetStructured(const vtkm::Id3& dim)
|
||||
{
|
||||
if (dim[0] > 1 && dim[1] > 1 && dim[2] > 1)
|
||||
@ -272,564 +93,102 @@ inline vtkm::cont::DynamicCellSet CreateCellSetStructured(const vtkm::Id3& dim)
|
||||
|
||||
} // namespace internal
|
||||
|
||||
VTKM_SILENCE_WEAK_VTABLE_WARNING_START
|
||||
|
||||
class VTKDataSetReaderBase
|
||||
class VTKM_IO_EXPORT VTKDataSetReaderBase
|
||||
{
|
||||
protected:
|
||||
std::unique_ptr<internal::VTKDataSetFile> DataFile;
|
||||
vtkm::cont::DataSet DataSet;
|
||||
|
||||
private:
|
||||
bool Loaded;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> CellsPermutation;
|
||||
|
||||
friend class VTKDataSetReader;
|
||||
|
||||
public:
|
||||
explicit VTKDataSetReaderBase(const char* fileName)
|
||||
: DataFile(new internal::VTKDataSetFile)
|
||||
, DataSet()
|
||||
, Loaded(false)
|
||||
{
|
||||
this->DataFile->FileName = fileName;
|
||||
}
|
||||
explicit VTKM_CONT VTKDataSetReaderBase(const char* fileName);
|
||||
|
||||
explicit VTKDataSetReaderBase(const std::string& fileName)
|
||||
: DataFile(new internal::VTKDataSetFile)
|
||||
, DataSet()
|
||||
, Loaded(false)
|
||||
{
|
||||
this->DataFile->FileName = fileName;
|
||||
}
|
||||
explicit VTKM_CONT VTKDataSetReaderBase(const std::string& fileName);
|
||||
|
||||
virtual ~VTKDataSetReaderBase() {}
|
||||
virtual VTKM_CONT ~VTKDataSetReaderBase();
|
||||
|
||||
const vtkm::cont::DataSet& ReadDataSet()
|
||||
{
|
||||
if (!this->Loaded)
|
||||
{
|
||||
try
|
||||
{
|
||||
this->OpenFile();
|
||||
this->ReadHeader();
|
||||
this->Read();
|
||||
this->CloseFile();
|
||||
this->Loaded = true;
|
||||
}
|
||||
catch (std::ifstream::failure& e)
|
||||
{
|
||||
std::string message("IO Error: ");
|
||||
throw vtkm::io::ErrorIO(message + e.what());
|
||||
}
|
||||
}
|
||||
VTKDataSetReaderBase(const VTKDataSetReaderBase&) = delete;
|
||||
void operator=(const VTKDataSetReaderBase&) = delete;
|
||||
|
||||
return this->DataSet;
|
||||
}
|
||||
const VTKM_CONT vtkm::cont::DataSet& ReadDataSet();
|
||||
|
||||
const vtkm::cont::DataSet& GetDataSet() const { return this->DataSet; }
|
||||
|
||||
virtual void PrintSummary(std::ostream& out) const
|
||||
{
|
||||
out << "VTKDataSetReader" << std::endl;
|
||||
PrintVTKDataFileSummary(*this->DataFile.get(), out);
|
||||
this->DataSet.PrintSummary(out);
|
||||
}
|
||||
virtual VTKM_CONT void PrintSummary(std::ostream& out) const;
|
||||
|
||||
protected:
|
||||
void ReadPoints()
|
||||
{
|
||||
std::string dataType;
|
||||
std::size_t numPoints;
|
||||
this->DataFile->Stream >> numPoints >> dataType >> std::ws;
|
||||
VTKM_CONT void ReadPoints();
|
||||
|
||||
vtkm::cont::VariantArrayHandle points =
|
||||
this->DoReadArrayVariant(vtkm::cont::Field::Association::POINTS, dataType, numPoints, 3);
|
||||
VTKM_CONT void ReadCells(vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
|
||||
vtkm::cont::ArrayHandle<vtkm::IdComponent>& numIndices);
|
||||
|
||||
this->DataSet.AddCoordinateSystem(vtkm::cont::CoordinateSystem("coordinates", points));
|
||||
}
|
||||
VTKM_CONT void ReadShapes(vtkm::cont::ArrayHandle<vtkm::UInt8>& shapes);
|
||||
|
||||
void ReadCells(vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
|
||||
vtkm::cont::ArrayHandle<vtkm::IdComponent>& numIndices)
|
||||
{
|
||||
vtkm::Id numCells, numInts;
|
||||
this->DataFile->Stream >> numCells >> numInts >> std::ws;
|
||||
|
||||
connectivity.Allocate(numInts - numCells);
|
||||
numIndices.Allocate(numCells);
|
||||
|
||||
std::vector<vtkm::Int32> buffer(static_cast<std::size_t>(numInts));
|
||||
this->ReadArray(buffer);
|
||||
|
||||
vtkm::Int32* buffp = &buffer[0];
|
||||
auto connectivityPortal = connectivity.WritePortal();
|
||||
auto numIndicesPortal = numIndices.WritePortal();
|
||||
for (vtkm::Id i = 0, connInd = 0; i < numCells; ++i)
|
||||
{
|
||||
vtkm::IdComponent numInds = static_cast<vtkm::IdComponent>(*buffp++);
|
||||
numIndicesPortal.Set(i, numInds);
|
||||
for (vtkm::IdComponent j = 0; j < numInds; ++j, ++connInd)
|
||||
{
|
||||
connectivityPortal.Set(connInd, static_cast<vtkm::Id>(*buffp++));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ReadShapes(vtkm::cont::ArrayHandle<vtkm::UInt8>& shapes)
|
||||
{
|
||||
std::string tag;
|
||||
vtkm::Id numCells;
|
||||
this->DataFile->Stream >> tag >> numCells >> std::ws;
|
||||
internal::parseAssert(tag == "CELL_TYPES");
|
||||
|
||||
shapes.Allocate(numCells);
|
||||
std::vector<vtkm::Int32> buffer(static_cast<std::size_t>(numCells));
|
||||
this->ReadArray(buffer);
|
||||
|
||||
vtkm::Int32* buffp = &buffer[0];
|
||||
auto shapesPortal = shapes.WritePortal();
|
||||
for (vtkm::Id i = 0; i < numCells; ++i)
|
||||
{
|
||||
shapesPortal.Set(i, static_cast<vtkm::UInt8>(*buffp++));
|
||||
}
|
||||
}
|
||||
|
||||
void ReadAttributes()
|
||||
{
|
||||
if (this->DataFile->Stream.eof())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
vtkm::cont::Field::Association association = vtkm::cont::Field::Association::ANY;
|
||||
std::size_t size;
|
||||
|
||||
std::string tag;
|
||||
this->DataFile->Stream >> tag;
|
||||
while (!this->DataFile->Stream.eof())
|
||||
{
|
||||
if (tag == "POINT_DATA")
|
||||
{
|
||||
association = vtkm::cont::Field::Association::POINTS;
|
||||
}
|
||||
else if (tag == "CELL_DATA")
|
||||
{
|
||||
association = vtkm::cont::Field::Association::CELL_SET;
|
||||
}
|
||||
else
|
||||
{
|
||||
internal::parseAssert(false);
|
||||
}
|
||||
|
||||
this->DataFile->Stream >> size;
|
||||
while (!this->DataFile->Stream.eof())
|
||||
{
|
||||
this->DataFile->Stream >> tag;
|
||||
if (tag == "SCALARS")
|
||||
{
|
||||
this->ReadScalars(association, size);
|
||||
}
|
||||
else if (tag == "COLOR_SCALARS")
|
||||
{
|
||||
this->ReadColorScalars(association, size);
|
||||
}
|
||||
else if (tag == "LOOKUP_TABLE")
|
||||
{
|
||||
this->ReadLookupTable();
|
||||
}
|
||||
else if (tag == "VECTORS" || tag == "NORMALS")
|
||||
{
|
||||
this->ReadVectors(association, size);
|
||||
}
|
||||
else if (tag == "TEXTURE_COORDINATES")
|
||||
{
|
||||
this->ReadTextureCoordinates(association, size);
|
||||
}
|
||||
else if (tag == "TENSORS")
|
||||
{
|
||||
this->ReadTensors(association, size);
|
||||
}
|
||||
else if (tag == "FIELD")
|
||||
{
|
||||
this->ReadFields(association, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
VTKM_CONT void ReadAttributes();
|
||||
|
||||
void SetCellsPermutation(const vtkm::cont::ArrayHandle<vtkm::Id>& permutation)
|
||||
{
|
||||
this->CellsPermutation = permutation;
|
||||
}
|
||||
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> GetCellsPermutation() const { return this->CellsPermutation; }
|
||||
VTKM_CONT vtkm::cont::ArrayHandle<vtkm::Id> GetCellsPermutation() const
|
||||
{
|
||||
return this->CellsPermutation;
|
||||
}
|
||||
|
||||
void TransferDataFile(VTKDataSetReaderBase& reader)
|
||||
VTKM_CONT void TransferDataFile(VTKDataSetReaderBase& reader)
|
||||
{
|
||||
reader.DataFile.swap(this->DataFile);
|
||||
this->DataFile.reset(nullptr);
|
||||
}
|
||||
|
||||
virtual void CloseFile() { this->DataFile->Stream.close(); }
|
||||
VTKM_CONT virtual void CloseFile();
|
||||
|
||||
VTKM_CONT virtual void Read() = 0;
|
||||
|
||||
private:
|
||||
void OpenFile()
|
||||
{
|
||||
this->DataFile->Stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
||||
try
|
||||
{
|
||||
this->DataFile->Stream.open(this->DataFile->FileName.c_str(),
|
||||
std::ios_base::in | std::ios_base::binary);
|
||||
}
|
||||
catch (std::ifstream::failure&)
|
||||
{
|
||||
std::string message("could not open file \"" + this->DataFile->FileName + "\"");
|
||||
throw vtkm::io::ErrorIO(message);
|
||||
}
|
||||
}
|
||||
|
||||
void ReadHeader()
|
||||
{
|
||||
char vstring[] = "# vtk DataFile Version";
|
||||
const std::size_t vlen = sizeof(vstring);
|
||||
|
||||
// Read version line
|
||||
char vbuf[vlen];
|
||||
this->DataFile->Stream.read(vbuf, vlen - 1);
|
||||
vbuf[vlen - 1] = '\0';
|
||||
if (std::string(vbuf) != std::string(vstring))
|
||||
{
|
||||
throw vtkm::io::ErrorIO("Incorrect file format.");
|
||||
}
|
||||
|
||||
char dot;
|
||||
this->DataFile->Stream >> this->DataFile->Version[0] >> dot >> this->DataFile->Version[1];
|
||||
// skip rest of the line
|
||||
std::string skip;
|
||||
std::getline(this->DataFile->Stream, skip);
|
||||
|
||||
if ((this->DataFile->Version[0] > 4) ||
|
||||
(this->DataFile->Version[0] == 4 && this->DataFile->Version[1] > 2))
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||
"Reader may not correctly read >v4.2 files. Reading version "
|
||||
<< this->DataFile->Version[0]
|
||||
<< "."
|
||||
<< this->DataFile->Version[1]
|
||||
<< ".\n");
|
||||
}
|
||||
|
||||
// Read title line
|
||||
std::getline(this->DataFile->Stream, this->DataFile->Title);
|
||||
|
||||
// Read format line
|
||||
this->DataFile->IsBinary = false;
|
||||
std::string format;
|
||||
this->DataFile->Stream >> format >> std::ws;
|
||||
if (format == "BINARY")
|
||||
{
|
||||
this->DataFile->IsBinary = true;
|
||||
}
|
||||
else if (format != "ASCII")
|
||||
{
|
||||
throw vtkm::io::ErrorIO("Unsupported Format.");
|
||||
}
|
||||
|
||||
// Read structure line
|
||||
std::string tag, structStr;
|
||||
this->DataFile->Stream >> tag >> structStr >> std::ws;
|
||||
internal::parseAssert(tag == "DATASET");
|
||||
|
||||
this->DataFile->Structure = vtkm::io::internal::DataSetStructureId(structStr);
|
||||
if (this->DataFile->Structure == vtkm::io::internal::DATASET_UNKNOWN)
|
||||
{
|
||||
throw vtkm::io::ErrorIO("Unsupported DataSet type.");
|
||||
}
|
||||
}
|
||||
|
||||
virtual void Read() = 0;
|
||||
|
||||
void AddField(const std::string& name,
|
||||
vtkm::cont::Field::Association association,
|
||||
vtkm::cont::VariantArrayHandle& data)
|
||||
{
|
||||
if (data.GetNumberOfValues() > 0)
|
||||
{
|
||||
switch (association)
|
||||
{
|
||||
case vtkm::cont::Field::Association::POINTS:
|
||||
case vtkm::cont::Field::Association::WHOLE_MESH:
|
||||
this->DataSet.AddField(vtkm::cont::Field(name, association, data));
|
||||
break;
|
||||
case vtkm::cont::Field::Association::CELL_SET:
|
||||
this->DataSet.AddField(vtkm::cont::Field(name, association, data));
|
||||
break;
|
||||
default:
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||
"Not recording field '" << name << "' because it has an unknown association");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ReadScalars(vtkm::cont::Field::Association association, std::size_t numElements)
|
||||
{
|
||||
std::string dataName, dataType, lookupTableName;
|
||||
vtkm::IdComponent numComponents = 1;
|
||||
this->DataFile->Stream >> dataName >> dataType;
|
||||
std::string tag;
|
||||
this->DataFile->Stream >> tag;
|
||||
if (tag != "LOOKUP_TABLE")
|
||||
{
|
||||
try
|
||||
{
|
||||
numComponents = std::stoi(tag);
|
||||
}
|
||||
catch (std::invalid_argument&)
|
||||
{
|
||||
internal::parseAssert(false);
|
||||
}
|
||||
this->DataFile->Stream >> tag;
|
||||
}
|
||||
|
||||
internal::parseAssert(tag == "LOOKUP_TABLE");
|
||||
this->DataFile->Stream >> lookupTableName >> std::ws;
|
||||
|
||||
vtkm::cont::VariantArrayHandle data =
|
||||
this->DoReadArrayVariant(association, dataType, numElements, numComponents);
|
||||
this->AddField(dataName, association, data);
|
||||
}
|
||||
|
||||
void ReadColorScalars(vtkm::cont::Field::Association association, std::size_t numElements)
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||
"Support for COLOR_SCALARS is not implemented. Skipping.");
|
||||
|
||||
std::string dataName;
|
||||
vtkm::IdComponent numComponents;
|
||||
this->DataFile->Stream >> dataName >> numComponents >> std::ws;
|
||||
std::string dataType = this->DataFile->IsBinary ? "unsigned_char" : "float";
|
||||
vtkm::cont::VariantArrayHandle data =
|
||||
this->DoReadArrayVariant(association, dataType, numElements, numComponents);
|
||||
this->AddField(dataName, association, data);
|
||||
}
|
||||
|
||||
void ReadLookupTable()
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||
"Support for LOOKUP_TABLE is not implemented. Skipping.");
|
||||
|
||||
std::string dataName;
|
||||
std::size_t numEntries;
|
||||
this->DataFile->Stream >> dataName >> numEntries >> std::ws;
|
||||
this->SkipArray(numEntries, vtkm::Vec<vtkm::io::internal::ColorChannel8, 4>());
|
||||
}
|
||||
|
||||
void ReadTextureCoordinates(vtkm::cont::Field::Association association, std::size_t numElements)
|
||||
{
|
||||
std::string dataName;
|
||||
vtkm::IdComponent numComponents;
|
||||
std::string dataType;
|
||||
this->DataFile->Stream >> dataName >> numComponents >> dataType >> std::ws;
|
||||
|
||||
vtkm::cont::VariantArrayHandle data =
|
||||
this->DoReadArrayVariant(association, dataType, numElements, numComponents);
|
||||
this->AddField(dataName, association, data);
|
||||
}
|
||||
|
||||
void ReadVectors(vtkm::cont::Field::Association association, std::size_t numElements)
|
||||
{
|
||||
std::string dataName;
|
||||
std::string dataType;
|
||||
this->DataFile->Stream >> dataName >> dataType >> std::ws;
|
||||
|
||||
vtkm::cont::VariantArrayHandle data =
|
||||
this->DoReadArrayVariant(association, dataType, numElements, 3);
|
||||
this->AddField(dataName, association, data);
|
||||
}
|
||||
|
||||
void ReadTensors(vtkm::cont::Field::Association association, std::size_t numElements)
|
||||
{
|
||||
std::string dataName;
|
||||
std::string dataType;
|
||||
this->DataFile->Stream >> dataName >> dataType >> std::ws;
|
||||
|
||||
vtkm::cont::VariantArrayHandle data =
|
||||
this->DoReadArrayVariant(association, dataType, numElements, 9);
|
||||
this->AddField(dataName, association, data);
|
||||
}
|
||||
|
||||
void ReadFields(vtkm::cont::Field::Association association, std::size_t expectedNumElements)
|
||||
{
|
||||
std::string dataName;
|
||||
vtkm::Id numArrays;
|
||||
this->DataFile->Stream >> dataName >> numArrays >> std::ws;
|
||||
for (vtkm::Id i = 0; i < numArrays; ++i)
|
||||
{
|
||||
std::size_t numTuples;
|
||||
vtkm::IdComponent numComponents;
|
||||
std::string arrayName, dataType;
|
||||
this->DataFile->Stream >> arrayName >> numComponents >> numTuples >> dataType >> std::ws;
|
||||
if (numTuples == expectedNumElements)
|
||||
{
|
||||
vtkm::cont::VariantArrayHandle data =
|
||||
this->DoReadArrayVariant(association, dataType, numTuples, numComponents);
|
||||
this->AddField(arrayName, association, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||
"Field " << arrayName
|
||||
<< "'s size does not match expected number of elements. Skipping");
|
||||
}
|
||||
}
|
||||
}
|
||||
VTKM_CONT void OpenFile();
|
||||
VTKM_CONT void ReadHeader();
|
||||
VTKM_CONT void AddField(const std::string& name,
|
||||
vtkm::cont::Field::Association association,
|
||||
vtkm::cont::VariantArrayHandle& data);
|
||||
VTKM_CONT void ReadScalars(vtkm::cont::Field::Association association, std::size_t numElements);
|
||||
VTKM_CONT void ReadColorScalars(vtkm::cont::Field::Association association,
|
||||
std::size_t numElements);
|
||||
VTKM_CONT void ReadLookupTable();
|
||||
VTKM_CONT void ReadTextureCoordinates(vtkm::cont::Field::Association association,
|
||||
std::size_t numElements);
|
||||
VTKM_CONT void ReadVectors(vtkm::cont::Field::Association association, std::size_t numElements);
|
||||
VTKM_CONT void ReadTensors(vtkm::cont::Field::Association association, std::size_t numElements);
|
||||
VTKM_CONT void ReadFields(vtkm::cont::Field::Association association,
|
||||
std::size_t expectedNumElements);
|
||||
|
||||
protected:
|
||||
void ReadGlobalFields(std::vector<vtkm::Float32>* visitBounds = nullptr)
|
||||
{
|
||||
std::string dataName;
|
||||
vtkm::Id numArrays;
|
||||
this->DataFile->Stream >> dataName >> numArrays >> std::ws;
|
||||
for (vtkm::Id i = 0; i < numArrays; ++i)
|
||||
{
|
||||
std::size_t numTuples;
|
||||
vtkm::IdComponent numComponents;
|
||||
std::string arrayName, dataType;
|
||||
this->DataFile->Stream >> arrayName >> numComponents >> numTuples >> dataType >> std::ws;
|
||||
if (arrayName == "avtOriginalBounds" && visitBounds)
|
||||
{
|
||||
visitBounds->resize(6);
|
||||
internal::parseAssert(numComponents == 1 && numTuples == 6);
|
||||
// parse the bounds and fill the bounds vector
|
||||
this->ReadArray(*visitBounds);
|
||||
}
|
||||
else
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Info,
|
||||
"Support for global field " << arrayName << " not implemented. Skipping.");
|
||||
this->DoSkipArrayVariant(dataType, numTuples, numComponents);
|
||||
}
|
||||
}
|
||||
}
|
||||
VTKM_CONT void ReadGlobalFields(std::vector<vtkm::Float32>* visitBounds = nullptr);
|
||||
|
||||
private:
|
||||
class SkipArrayVariant
|
||||
{
|
||||
public:
|
||||
SkipArrayVariant(VTKDataSetReaderBase* reader, std::size_t numElements)
|
||||
: Reader(reader)
|
||||
, NumElements(numElements)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void operator()(T) const
|
||||
{
|
||||
this->Reader->SkipArray(this->NumElements, T());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void operator()(vtkm::IdComponent numComponents, T) const
|
||||
{
|
||||
this->Reader->SkipArray(this->NumElements * static_cast<std::size_t>(numComponents), T());
|
||||
}
|
||||
|
||||
protected:
|
||||
VTKDataSetReaderBase* Reader;
|
||||
std::size_t NumElements;
|
||||
};
|
||||
|
||||
class ReadArrayVariant : public SkipArrayVariant
|
||||
{
|
||||
public:
|
||||
ReadArrayVariant(VTKDataSetReaderBase* reader,
|
||||
vtkm::cont::Field::Association association,
|
||||
std::size_t numElements,
|
||||
vtkm::cont::VariantArrayHandle& data)
|
||||
: SkipArrayVariant(reader, numElements)
|
||||
, Association(association)
|
||||
, Data(&data)
|
||||
{
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void operator()(T) const
|
||||
{
|
||||
std::vector<T> buffer(this->NumElements);
|
||||
this->Reader->ReadArray(buffer);
|
||||
if ((this->Association != vtkm::cont::Field::Association::CELL_SET) ||
|
||||
(this->Reader->GetCellsPermutation().GetNumberOfValues() < 1))
|
||||
{
|
||||
*this->Data = internal::CreateVariantArrayHandle(buffer);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If we are reading data associated with a cell set, we need to (sometimes) permute the
|
||||
// data due to differences between VTK and VTK-m cell shapes.
|
||||
auto permutation = this->Reader->GetCellsPermutation().ReadPortal();
|
||||
vtkm::Id outSize = permutation.GetNumberOfValues();
|
||||
std::vector<T> permutedBuffer(static_cast<std::size_t>(outSize));
|
||||
for (vtkm::Id outIndex = 0; outIndex < outSize; outIndex++)
|
||||
{
|
||||
std::size_t inIndex = static_cast<std::size_t>(permutation.Get(outIndex));
|
||||
permutedBuffer[static_cast<std::size_t>(outIndex)] = buffer[inIndex];
|
||||
}
|
||||
*this->Data = internal::CreateVariantArrayHandle(permutedBuffer);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void operator()(vtkm::IdComponent numComponents, T) const
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||
"Support for " << numComponents << " components not implemented. Skipping.");
|
||||
SkipArrayVariant::operator()(numComponents, T());
|
||||
}
|
||||
|
||||
private:
|
||||
vtkm::cont::Field::Association Association;
|
||||
vtkm::cont::VariantArrayHandle* Data;
|
||||
};
|
||||
class SkipArrayVariant;
|
||||
class ReadArrayVariant;
|
||||
|
||||
//Make the Array parsing methods protected so that derived classes
|
||||
//can call the methods.
|
||||
protected:
|
||||
void DoSkipArrayVariant(std::string dataType,
|
||||
std::size_t numElements,
|
||||
vtkm::IdComponent numComponents)
|
||||
{
|
||||
// string is unsupported for SkipArrayVariant, so it requires some
|
||||
// special handling
|
||||
if (dataType == "string")
|
||||
{
|
||||
const vtkm::Id stringCount = numComponents * static_cast<vtkm::Id>(numElements);
|
||||
for (vtkm::Id i = 0; i < stringCount; ++i)
|
||||
{
|
||||
std::string trash;
|
||||
this->DataFile->Stream >> trash;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
vtkm::io::internal::DataType typeId = vtkm::io::internal::DataTypeId(dataType);
|
||||
vtkm::io::internal::SelectTypeAndCall(
|
||||
typeId, numComponents, SkipArrayVariant(this, numElements));
|
||||
}
|
||||
}
|
||||
|
||||
vtkm::cont::VariantArrayHandle DoReadArrayVariant(vtkm::cont::Field::Association association,
|
||||
std::string dataType,
|
||||
std::size_t numElements,
|
||||
vtkm::IdComponent numComponents)
|
||||
{
|
||||
// Create empty data to start so that the return can check if data were actually read
|
||||
vtkm::cont::ArrayHandle<vtkm::Float32> empty;
|
||||
vtkm::cont::VariantArrayHandle data(empty);
|
||||
|
||||
vtkm::io::internal::DataType typeId = vtkm::io::internal::DataTypeId(dataType);
|
||||
vtkm::io::internal::SelectTypeAndCall(
|
||||
typeId, numComponents, ReadArrayVariant(this, association, numElements, data));
|
||||
|
||||
return data;
|
||||
}
|
||||
VTKM_CONT void DoSkipArrayVariant(std::string dataType,
|
||||
std::size_t numElements,
|
||||
vtkm::IdComponent numComponents);
|
||||
VTKM_CONT vtkm::cont::VariantArrayHandle DoReadArrayVariant(
|
||||
vtkm::cont::Field::Association association,
|
||||
std::string dataType,
|
||||
std::size_t numElements,
|
||||
vtkm::IdComponent numComponents);
|
||||
|
||||
template <typename T>
|
||||
void ReadArray(std::vector<T>& buffer)
|
||||
VTKM_CONT void ReadArray(std::vector<T>& buffer)
|
||||
{
|
||||
using ComponentType = typename vtkm::VecTraits<T>::ComponentType;
|
||||
constexpr vtkm::IdComponent numComponents = vtkm::VecTraits<T>::NUM_COMPONENTS;
|
||||
@ -861,7 +220,8 @@ protected:
|
||||
}
|
||||
|
||||
template <vtkm::IdComponent NumComponents>
|
||||
void ReadArray(std::vector<vtkm::Vec<vtkm::io::internal::DummyBitType, NumComponents>>& buffer)
|
||||
VTKM_CONT void ReadArray(
|
||||
std::vector<vtkm::Vec<vtkm::io::internal::DummyBitType, NumComponents>>& buffer)
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||
"Support for data type 'bit' is not implemented. Skipping.");
|
||||
@ -869,13 +229,7 @@ protected:
|
||||
buffer.clear();
|
||||
}
|
||||
|
||||
void ReadArray(std::vector<vtkm::io::internal::DummyBitType>& buffer)
|
||||
{
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||
"Support for data type 'bit' is not implemented. Skipping.");
|
||||
this->SkipArray(buffer.size(), vtkm::io::internal::DummyBitType());
|
||||
buffer.clear();
|
||||
}
|
||||
VTKM_CONT void ReadArray(std::vector<vtkm::io::internal::DummyBitType>& buffer);
|
||||
|
||||
template <typename T>
|
||||
void SkipArray(std::size_t numElements, T)
|
||||
@ -912,95 +266,12 @@ protected:
|
||||
NumComponents);
|
||||
}
|
||||
|
||||
void SkipArray(std::size_t numElements,
|
||||
vtkm::io::internal::DummyBitType,
|
||||
vtkm::IdComponent numComponents = 1)
|
||||
{
|
||||
if (this->DataFile->IsBinary)
|
||||
{
|
||||
numElements = (numElements + 7) / 8;
|
||||
this->DataFile->Stream.seekg(static_cast<std::streamoff>(numElements), std::ios_base::cur);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (std::size_t i = 0; i < numElements; ++i)
|
||||
{
|
||||
vtkm::UInt16 val;
|
||||
this->DataFile->Stream >> val;
|
||||
}
|
||||
}
|
||||
this->DataFile->Stream >> std::ws;
|
||||
this->SkipArrayMetaData(numComponents);
|
||||
}
|
||||
VTKM_CONT void SkipArray(std::size_t numElements,
|
||||
vtkm::io::internal::DummyBitType,
|
||||
vtkm::IdComponent numComponents = 1);
|
||||
|
||||
void SkipArrayMetaData(vtkm::IdComponent numComponents)
|
||||
{
|
||||
if (!this->DataFile->Stream.good())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto begining = this->DataFile->Stream.tellg();
|
||||
|
||||
std::string tag;
|
||||
this->DataFile->Stream >> tag;
|
||||
if (tag != "METADATA")
|
||||
{
|
||||
this->DataFile->Stream.seekg(begining);
|
||||
return;
|
||||
}
|
||||
|
||||
VTKM_LOG_S(vtkm::cont::LogLevel::Warn, "METADATA is not supported. Attempting to Skip.");
|
||||
|
||||
this->DataFile->Stream >> tag >> std::ws;
|
||||
if (tag == "COMPONENT_NAMES")
|
||||
{
|
||||
std::string name;
|
||||
for (vtkm::IdComponent i = 0; i < numComponents; ++i)
|
||||
{
|
||||
this->DataFile->Stream >> name >> std::ws;
|
||||
}
|
||||
}
|
||||
else if (tag == "INFORMATION")
|
||||
{
|
||||
int numKeys = 0;
|
||||
this->DataFile->Stream >> numKeys >> std::ws;
|
||||
|
||||
// Skipping INFORMATION is tricky. The reader needs to be aware of the types of the
|
||||
// information, which is not provided in the file.
|
||||
// Here we will just skip until an empty line is found.
|
||||
// However, if there are no keys, then there is nothing to read (and the stream tends
|
||||
// to skip over empty lines.
|
||||
if (numKeys > 0)
|
||||
{
|
||||
std::string line;
|
||||
do
|
||||
{
|
||||
std::getline(this->DataFile->Stream, line);
|
||||
} while (this->DataFile->Stream.good() && !line.empty());
|
||||
|
||||
// Eat any remaining whitespace after the INFORMATION to be ready to read the next token
|
||||
this->DataFile->Stream >> std::ws;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
internal::parseAssert(false);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
std::unique_ptr<internal::VTKDataSetFile> DataFile;
|
||||
vtkm::cont::DataSet DataSet;
|
||||
|
||||
private:
|
||||
bool Loaded;
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> CellsPermutation;
|
||||
|
||||
friend class VTKDataSetReader;
|
||||
VTKM_CONT void SkipArrayMetaData(vtkm::IdComponent numComponents);
|
||||
};
|
||||
|
||||
VTKM_SILENCE_WEAK_VTABLE_WARNING_END
|
||||
}
|
||||
} // vtkm::io
|
||||
|
||||
|
@ -11,6 +11,7 @@
|
||||
#define vtk_m_io_VTKPolyDataReader_h
|
||||
|
||||
#include <vtkm/io/VTKDataSetReaderBase.h>
|
||||
#include <vtkm/io/internal/VTKDataSetCells.h>
|
||||
|
||||
#include <vtkm/cont/ArrayPortalToIterators.h>
|
||||
|
||||
|
@ -15,14 +15,14 @@ set(unit_tests
|
||||
UnitTestVTKDataSetWriter.cxx
|
||||
)
|
||||
|
||||
vtkm_unit_tests(SOURCES ${unit_tests} ALL_BACKENDS LIBRARIES vtkm_lodepng)
|
||||
set(unit_test_libraries vtkm_lodepng vtkm_io)
|
||||
|
||||
if(NOT VTKm_ENABLE_RENDERING)
|
||||
return()
|
||||
if(VTKm_ENABLE_RENDERING)
|
||||
set(unit_tests ${unit_tests}
|
||||
UnitTestImageWriter.cxx
|
||||
)
|
||||
|
||||
set(unit_test_libraries ${unit_test_libraries} vtkm_rendering)
|
||||
endif()
|
||||
|
||||
set(image_unit_tests
|
||||
UnitTestImageWriter.cxx
|
||||
)
|
||||
|
||||
vtkm_unit_tests(NAME UnitTests_vtkm_io_image_testing SOURCES ${image_unit_tests} ALL_BACKENDS LIBRARIES vtkm_rendering vtkm_lodepng)
|
||||
vtkm_unit_tests(SOURCES ${unit_tests} ALL_BACKENDS LIBRARIES ${unit_test_libraries})
|
||||
|
Loading…
Reference in New Issue
Block a user