mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
Merge topic 'io-library'
05fcda6c7 Compile IO library with device compilers dce576bd1 Add BOVDataSetReader implementation to vtkm_io 8657a9b3c Update VTKDataSetWriter to compile into vtkm_io 086439e71 Update variants of VTKDataSetReaders to compile into vtkm_io 0612be9c5 Move VTKDataSetReaderBase code to vtkm_io Acked-by: Kitware Robot <kwrobot@kitware.com> Acked-by: Sujin Philip <sujin.philip@kitware.com> Merge-request: !2100
This commit is contained in:
commit
bc5ecf262c
@ -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)
|
mark_as_advanced(VTKm_BENCHS_RANGE_LOWER_BOUNDARY VTKm_BENCHS_RANGE_UPPER_BOUNDARY)
|
||||||
|
|
||||||
foreach (benchmark ${benchmarks})
|
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 ()
|
endforeach ()
|
||||||
|
|
||||||
target_compile_definitions(BenchmarkDeviceAdapter PUBLIC VTKm_BENCHS_RANGE_LOWER_BOUNDARY=${VTKm_BENCHS_RANGE_LOWER_BOUNDARY})
|
target_compile_definitions(BenchmarkDeviceAdapter PUBLIC VTKm_BENCHS_RANGE_LOWER_BOUNDARY=${VTKm_BENCHS_RANGE_LOWER_BOUNDARY})
|
||||||
|
13
docs/changelog/vtk-io-in-library.md
Normal file
13
docs/changelog/vtk-io-in-library.md
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Move VTK file readers and writers into vtkm_io
|
||||||
|
|
||||||
|
The legacy VTK file reader and writer were created back when VTK-m was a
|
||||||
|
header-only library. Things have changed and we now compile quite a bit of
|
||||||
|
code into libraries. At this point, there is no reason why the VTK file
|
||||||
|
reader/writer should be any different.
|
||||||
|
|
||||||
|
Thus, `VTKDataSetReader`, `VTKDataSetWriter`, and several supporting
|
||||||
|
classes are now compiled into the `vtkm_io` library. Also similarly updated
|
||||||
|
`BOVDataSetReader` for good measure.
|
||||||
|
|
||||||
|
As a side effect, code using VTK-m will need to link to `vtkm_io` if they
|
||||||
|
are using any readers or writers.
|
@ -14,7 +14,7 @@ project(Clipping CXX)
|
|||||||
find_package(VTKm REQUIRED QUIET)
|
find_package(VTKm REQUIRED QUIET)
|
||||||
|
|
||||||
add_executable(Clipping Clipping.cxx)
|
add_executable(Clipping Clipping.cxx)
|
||||||
target_link_libraries(Clipping PRIVATE vtkm_filter)
|
target_link_libraries(Clipping PRIVATE vtkm_filter vtkm_io)
|
||||||
|
|
||||||
vtkm_add_target_information(Clipping
|
vtkm_add_target_information(Clipping
|
||||||
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
|
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
|
||||||
|
@ -14,7 +14,7 @@ project(HelloWorklet CXX)
|
|||||||
find_package(VTKm REQUIRED QUIET)
|
find_package(VTKm REQUIRED QUIET)
|
||||||
|
|
||||||
add_executable(HelloWorklet HelloWorklet.cxx)
|
add_executable(HelloWorklet HelloWorklet.cxx)
|
||||||
target_link_libraries(HelloWorklet PRIVATE vtkm_filter)
|
target_link_libraries(HelloWorklet PRIVATE vtkm_filter vtkm_io)
|
||||||
|
|
||||||
vtkm_add_target_information(HelloWorklet
|
vtkm_add_target_information(HelloWorklet
|
||||||
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
|
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
|
||||||
|
@ -26,7 +26,7 @@ project(MeshQuality CXX)
|
|||||||
find_package(VTKm REQUIRED QUIET)
|
find_package(VTKm REQUIRED QUIET)
|
||||||
|
|
||||||
add_executable(MeshQuality MeshQuality.cxx)
|
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)
|
if(TARGET vtkm::tbb)
|
||||||
target_compile_definitions(MeshQuality PRIVATE BUILDING_TBB_VERSION)
|
target_compile_definitions(MeshQuality PRIVATE BUILDING_TBB_VERSION)
|
||||||
|
@ -14,7 +14,7 @@ project(ParticleAdvection CXX)
|
|||||||
find_package(VTKm REQUIRED QUIET)
|
find_package(VTKm REQUIRED QUIET)
|
||||||
|
|
||||||
add_executable(Particle_Advection ParticleAdvection.cxx)
|
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
|
vtkm_add_target_information(Particle_Advection
|
||||||
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
|
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
|
||||||
DEVICE_SOURCES ParticleAdvection.cxx)
|
DEVICE_SOURCES ParticleAdvection.cxx)
|
||||||
|
@ -13,7 +13,7 @@ project(RedistributePoints CXX)
|
|||||||
#Find the VTK-m package
|
#Find the VTK-m package
|
||||||
find_package(VTKm REQUIRED QUIET)
|
find_package(VTKm REQUIRED QUIET)
|
||||||
add_executable(RedistributePoints RedistributePoints.cxx RedistributePoints.h)
|
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
|
vtkm_add_target_information(RedistributePoints
|
||||||
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
|
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
|
||||||
DEVICE_SOURCES RedistributePoints.cxx)
|
DEVICE_SOURCES RedistributePoints.cxx)
|
||||||
|
@ -19,4 +19,4 @@ add_executable(Temporal_Advection TemporalAdvection.cxx)
|
|||||||
vtkm_add_target_information(Temporal_Advection
|
vtkm_add_target_information(Temporal_Advection
|
||||||
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
|
DROP_UNUSED_SYMBOLS MODIFY_CUDA_FLAGS
|
||||||
DEVICE_SOURCES TemporalAdvection.cxx)
|
DEVICE_SOURCES TemporalAdvection.cxx)
|
||||||
target_link_libraries(Temporal_Advection PRIVATE vtkm_filter)
|
target_link_libraries(Temporal_Advection PRIVATE vtkm_filter vtkm_io)
|
||||||
|
@ -14,10 +14,10 @@ project(Tetrahedra CXX)
|
|||||||
find_package(VTKm REQUIRED QUIET)
|
find_package(VTKm REQUIRED QUIET)
|
||||||
|
|
||||||
add_executable(Tetrahedralize Tetrahedralize.cxx)
|
add_executable(Tetrahedralize Tetrahedralize.cxx)
|
||||||
target_link_libraries(Tetrahedralize PRIVATE vtkm_filter)
|
target_link_libraries(Tetrahedralize PRIVATE vtkm_filter vtkm_io)
|
||||||
|
|
||||||
add_executable(Triangulate Triangulate.cxx)
|
add_executable(Triangulate Triangulate.cxx)
|
||||||
target_link_libraries(Triangulate PRIVATE vtkm_filter)
|
target_link_libraries(Triangulate PRIVATE vtkm_filter vtkm_io)
|
||||||
|
|
||||||
vtkm_add_target_information(Tetrahedralize Triangulate
|
vtkm_add_target_information(Tetrahedralize Triangulate
|
||||||
DROP_UNUSED_SYMBOLS
|
DROP_UNUSED_SYMBOLS
|
||||||
|
@ -69,7 +69,7 @@ set(unit_tests
|
|||||||
|
|
||||||
vtkm_unit_tests(
|
vtkm_unit_tests(
|
||||||
SOURCES ${unit_tests}
|
SOURCES ${unit_tests}
|
||||||
LIBRARIES vtkm_filter vtkm_source
|
LIBRARIES vtkm_filter vtkm_source vtkm_io
|
||||||
ALL_BACKENDS
|
ALL_BACKENDS
|
||||||
USE_VTKM_JOB_POOL
|
USE_VTKM_JOB_POOL
|
||||||
)
|
)
|
||||||
|
254
vtkm/io/BOVDataSetReader.cxx
Normal file
254
vtkm/io/BOVDataSetReader.cxx
Normal file
@ -0,0 +1,254 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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/BOVDataSetReader.h>
|
||||||
|
|
||||||
|
#include <vtkm/cont/DataSetBuilderUniform.h>
|
||||||
|
#include <vtkm/cont/DataSetFieldAdd.h>
|
||||||
|
#include <vtkm/io/ErrorIO.h>
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
enum class DataFormat
|
||||||
|
{
|
||||||
|
ByteData,
|
||||||
|
ShortData,
|
||||||
|
IntegerData,
|
||||||
|
FloatData,
|
||||||
|
DoubleData
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void ReadBuffer(const std::string& fName, const vtkm::Id& sz, std::vector<T>& buff)
|
||||||
|
{
|
||||||
|
FILE* fp = fopen(fName.c_str(), "rb");
|
||||||
|
size_t readSize = static_cast<size_t>(sz);
|
||||||
|
if (fp == nullptr)
|
||||||
|
{
|
||||||
|
throw vtkm::io::ErrorIO("Unable to open data file: " + fName);
|
||||||
|
}
|
||||||
|
buff.resize(readSize);
|
||||||
|
size_t nread = fread(&buff[0], sizeof(T), readSize, fp);
|
||||||
|
if (nread != readSize)
|
||||||
|
{
|
||||||
|
throw vtkm::io::ErrorIO("Data file read failed: " + fName);
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void ReadScalar(const std::string& fName, const vtkm::Id& nTuples, vtkm::cont::ArrayHandle<T>& var)
|
||||||
|
{
|
||||||
|
std::vector<T> buff;
|
||||||
|
ReadBuffer(fName, nTuples, buff);
|
||||||
|
var.Allocate(nTuples);
|
||||||
|
auto writePortal = var.WritePortal();
|
||||||
|
for (vtkm::Id i = 0; i < nTuples; i++)
|
||||||
|
{
|
||||||
|
writePortal.Set(i, buff[static_cast<size_t>(i)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void ReadVector(const std::string& fName,
|
||||||
|
const vtkm::Id& nTuples,
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>>& var)
|
||||||
|
{
|
||||||
|
std::vector<T> buff;
|
||||||
|
ReadBuffer(fName, nTuples * 3, buff);
|
||||||
|
|
||||||
|
var.Allocate(nTuples);
|
||||||
|
vtkm::Vec<T, 3> v;
|
||||||
|
auto writePortal = var.WritePortal();
|
||||||
|
for (vtkm::Id i = 0; i < nTuples; i++)
|
||||||
|
{
|
||||||
|
v[0] = buff[static_cast<size_t>(i * 3 + 0)];
|
||||||
|
v[1] = buff[static_cast<size_t>(i * 3 + 1)];
|
||||||
|
v[2] = buff[static_cast<size_t>(i * 3 + 2)];
|
||||||
|
writePortal.Set(i, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace io
|
||||||
|
{
|
||||||
|
|
||||||
|
BOVDataSetReader::BOVDataSetReader(const char* fileName)
|
||||||
|
: FileName(fileName)
|
||||||
|
, Loaded(false)
|
||||||
|
, DataSet()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BOVDataSetReader::BOVDataSetReader(const std::string& fileName)
|
||||||
|
: FileName(fileName)
|
||||||
|
, Loaded(false)
|
||||||
|
, DataSet()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const vtkm::cont::DataSet& BOVDataSetReader::ReadDataSet()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this->LoadFile();
|
||||||
|
}
|
||||||
|
catch (std::ifstream::failure& e)
|
||||||
|
{
|
||||||
|
std::string message("IO Error: ");
|
||||||
|
throw vtkm::io::ErrorIO(message + e.what());
|
||||||
|
}
|
||||||
|
return this->DataSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
void BOVDataSetReader::LoadFile()
|
||||||
|
{
|
||||||
|
if (this->Loaded)
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::ifstream stream(this->FileName);
|
||||||
|
if (stream.fail())
|
||||||
|
throw vtkm::io::ErrorIO("Failed to open file: " + this->FileName);
|
||||||
|
|
||||||
|
DataFormat dataFormat = DataFormat::ByteData;
|
||||||
|
std::string bovFile, line, token, options, variableName;
|
||||||
|
vtkm::Id numComponents = 1;
|
||||||
|
vtkm::Id3 dim;
|
||||||
|
vtkm::Vec3f origin(0, 0, 0);
|
||||||
|
vtkm::Vec3f spacing(1, 1, 1);
|
||||||
|
bool spacingSet = false;
|
||||||
|
|
||||||
|
while (stream.good())
|
||||||
|
{
|
||||||
|
std::getline(stream, line);
|
||||||
|
if (line.size() == 0 || line[0] == '#')
|
||||||
|
continue;
|
||||||
|
//std::cout<<"::"<<line<<"::"<<std::endl;
|
||||||
|
std::size_t pos = line.find(":");
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
throw vtkm::io::ErrorIO("Unsupported option: " + line);
|
||||||
|
token = line.substr(0, pos);
|
||||||
|
options = line.substr(pos + 1, line.size() - 1);
|
||||||
|
//std::cout<<token<<"::"<<options<<std::endl;
|
||||||
|
|
||||||
|
std::stringstream strStream(options);
|
||||||
|
|
||||||
|
//Format supports both space and "_" separated tokens...
|
||||||
|
if (token.find("DATA") != std::string::npos && token.find("FILE") != std::string::npos)
|
||||||
|
{
|
||||||
|
strStream >> bovFile >> std::ws;
|
||||||
|
}
|
||||||
|
else if (token.find("DATA") != std::string::npos && token.find("SIZE") != std::string::npos)
|
||||||
|
{
|
||||||
|
strStream >> dim[0] >> dim[1] >> dim[2] >> std::ws;
|
||||||
|
}
|
||||||
|
else if (token.find("BRICK") != std::string::npos && token.find("ORIGIN") != std::string::npos)
|
||||||
|
{
|
||||||
|
strStream >> origin[0] >> origin[1] >> origin[2] >> std::ws;
|
||||||
|
}
|
||||||
|
|
||||||
|
//DRP
|
||||||
|
else if (token.find("BRICK") != std::string::npos && token.find("SIZE") != std::string::npos)
|
||||||
|
{
|
||||||
|
strStream >> spacing[0] >> spacing[1] >> spacing[2] >> std::ws;
|
||||||
|
spacingSet = true;
|
||||||
|
}
|
||||||
|
else if (token.find("DATA") != std::string::npos && token.find("FORMAT") != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string opt;
|
||||||
|
strStream >> opt >> std::ws;
|
||||||
|
if (opt.find("FLOAT") != std::string::npos || opt.find("REAL") != std::string::npos)
|
||||||
|
dataFormat = DataFormat::FloatData;
|
||||||
|
else if (opt.find("DOUBLE") != std::string::npos)
|
||||||
|
dataFormat = DataFormat::DoubleData;
|
||||||
|
else
|
||||||
|
throw vtkm::io::ErrorIO("Unsupported data type: " + token);
|
||||||
|
}
|
||||||
|
else if (token.find("DATA") != std::string::npos &&
|
||||||
|
token.find("COMPONENTS") != std::string::npos)
|
||||||
|
{
|
||||||
|
strStream >> numComponents >> std::ws;
|
||||||
|
if (numComponents != 1 && numComponents != 3)
|
||||||
|
throw vtkm::io::ErrorIO("Unsupported number of components");
|
||||||
|
}
|
||||||
|
else if (token.find("VARIABLE") != std::string::npos &&
|
||||||
|
token.find("PALETTE") == std::string::npos)
|
||||||
|
{
|
||||||
|
strStream >> variableName >> std::ws;
|
||||||
|
if (variableName[0] == '"')
|
||||||
|
variableName = variableName.substr(1, variableName.size() - 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spacingSet)
|
||||||
|
{
|
||||||
|
spacing[0] = (spacing[0]) / static_cast<vtkm::FloatDefault>(dim[0] - 1);
|
||||||
|
spacing[1] = (spacing[1]) / static_cast<vtkm::FloatDefault>(dim[1] - 1);
|
||||||
|
spacing[2] = (spacing[2]) / static_cast<vtkm::FloatDefault>(dim[2] - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string fullPathDataFile;
|
||||||
|
std::size_t pos = FileName.rfind("/");
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
std::string baseDir;
|
||||||
|
baseDir = this->FileName.substr(0, pos);
|
||||||
|
fullPathDataFile = baseDir + "/" + bovFile;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
fullPathDataFile = bovFile;
|
||||||
|
|
||||||
|
|
||||||
|
vtkm::cont::DataSetBuilderUniform dataSetBuilder;
|
||||||
|
vtkm::cont::DataSetFieldAdd dsf;
|
||||||
|
this->DataSet = dataSetBuilder.Create(dim, origin, spacing);
|
||||||
|
|
||||||
|
vtkm::Id numTuples = dim[0] * dim[1] * dim[2];
|
||||||
|
if (numComponents == 1)
|
||||||
|
{
|
||||||
|
if (dataFormat == DataFormat::FloatData)
|
||||||
|
{
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::Float32> var;
|
||||||
|
ReadScalar(fullPathDataFile, numTuples, var);
|
||||||
|
dsf.AddPointField(this->DataSet, variableName, var);
|
||||||
|
}
|
||||||
|
else if (dataFormat == DataFormat::DoubleData)
|
||||||
|
{
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::Float64> var;
|
||||||
|
ReadScalar(fullPathDataFile, numTuples, var);
|
||||||
|
dsf.AddPointField(this->DataSet, variableName, var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (numComponents == 3)
|
||||||
|
{
|
||||||
|
if (dataFormat == DataFormat::FloatData)
|
||||||
|
{
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::Vec3f_32> var;
|
||||||
|
ReadVector(fullPathDataFile, numTuples, var);
|
||||||
|
dsf.AddPointField(this->DataSet, variableName, var);
|
||||||
|
}
|
||||||
|
else if (dataFormat == DataFormat::DoubleData)
|
||||||
|
{
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::Vec3f_64> var;
|
||||||
|
ReadVector(fullPathDataFile, numTuples, var);
|
||||||
|
dsf.AddPointField(this->DataSet, variableName, var);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this->Loaded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace vtkm::io
|
@ -10,234 +10,25 @@
|
|||||||
#ifndef vtk_m_io_BOVDataSetReader_h
|
#ifndef vtk_m_io_BOVDataSetReader_h
|
||||||
#define vtk_m_io_BOVDataSetReader_h
|
#define vtk_m_io_BOVDataSetReader_h
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <vtkm/cont/DataSet.h>
|
#include <vtkm/cont/DataSet.h>
|
||||||
#include <vtkm/cont/DataSetBuilderUniform.h>
|
|
||||||
#include <vtkm/cont/DataSetFieldAdd.h>
|
#include <vtkm/io/vtkm_io_export.h>
|
||||||
#include <vtkm/io/ErrorIO.h>
|
|
||||||
|
|
||||||
namespace vtkm
|
namespace vtkm
|
||||||
{
|
{
|
||||||
namespace io
|
namespace io
|
||||||
{
|
{
|
||||||
|
|
||||||
class BOVDataSetReader
|
class VTKM_IO_EXPORT BOVDataSetReader
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
BOVDataSetReader(const char* fileName)
|
VTKM_CONT BOVDataSetReader(const char* fileName);
|
||||||
: FileName(fileName)
|
VTKM_CONT BOVDataSetReader(const std::string& fileName);
|
||||||
, Loaded(false)
|
|
||||||
, DataSet()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
BOVDataSetReader(const std::string& fileName)
|
|
||||||
: FileName(fileName)
|
|
||||||
, Loaded(false)
|
|
||||||
, DataSet()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
const vtkm::cont::DataSet& ReadDataSet()
|
VTKM_CONT const vtkm::cont::DataSet& ReadDataSet();
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
LoadFile();
|
|
||||||
}
|
|
||||||
catch (std::ifstream::failure& e)
|
|
||||||
{
|
|
||||||
std::string message("IO Error: ");
|
|
||||||
throw vtkm::io::ErrorIO(message + e.what());
|
|
||||||
}
|
|
||||||
return this->DataSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
using DataFormat = enum { ByteData, ShortData, IntegerData, FloatData, DoubleData };
|
VTKM_CONT void LoadFile();
|
||||||
|
|
||||||
void LoadFile()
|
|
||||||
{
|
|
||||||
if (this->Loaded)
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::ifstream stream(this->FileName);
|
|
||||||
if (stream.fail())
|
|
||||||
throw vtkm::io::ErrorIO("Failed to open file: " + this->FileName);
|
|
||||||
|
|
||||||
DataFormat dataFormat = ByteData;
|
|
||||||
std::string bovFile, line, token, options, variableName;
|
|
||||||
vtkm::Id numComponents = 1;
|
|
||||||
vtkm::Id3 dim;
|
|
||||||
vtkm::Vec3f origin(0, 0, 0);
|
|
||||||
vtkm::Vec3f spacing(1, 1, 1);
|
|
||||||
bool spacingSet = false;
|
|
||||||
|
|
||||||
while (stream.good())
|
|
||||||
{
|
|
||||||
std::getline(stream, line);
|
|
||||||
if (line.size() == 0 || line[0] == '#')
|
|
||||||
continue;
|
|
||||||
//std::cout<<"::"<<line<<"::"<<std::endl;
|
|
||||||
std::size_t pos = line.find(":");
|
|
||||||
if (pos == std::string::npos)
|
|
||||||
throw vtkm::io::ErrorIO("Unsupported option: " + line);
|
|
||||||
token = line.substr(0, pos);
|
|
||||||
options = line.substr(pos + 1, line.size() - 1);
|
|
||||||
//std::cout<<token<<"::"<<options<<std::endl;
|
|
||||||
|
|
||||||
std::stringstream strStream(options);
|
|
||||||
|
|
||||||
//Format supports both space and "_" separated tokens...
|
|
||||||
if (token.find("DATA") != std::string::npos && token.find("FILE") != std::string::npos)
|
|
||||||
{
|
|
||||||
strStream >> bovFile >> std::ws;
|
|
||||||
}
|
|
||||||
else if (token.find("DATA") != std::string::npos && token.find("SIZE") != std::string::npos)
|
|
||||||
{
|
|
||||||
strStream >> dim[0] >> dim[1] >> dim[2] >> std::ws;
|
|
||||||
}
|
|
||||||
else if (token.find("BRICK") != std::string::npos &&
|
|
||||||
token.find("ORIGIN") != std::string::npos)
|
|
||||||
{
|
|
||||||
strStream >> origin[0] >> origin[1] >> origin[2] >> std::ws;
|
|
||||||
}
|
|
||||||
|
|
||||||
//DRP
|
|
||||||
else if (token.find("BRICK") != std::string::npos && token.find("SIZE") != std::string::npos)
|
|
||||||
{
|
|
||||||
strStream >> spacing[0] >> spacing[1] >> spacing[2] >> std::ws;
|
|
||||||
spacingSet = true;
|
|
||||||
}
|
|
||||||
else if (token.find("DATA") != std::string::npos && token.find("FORMAT") != std::string::npos)
|
|
||||||
{
|
|
||||||
std::string opt;
|
|
||||||
strStream >> opt >> std::ws;
|
|
||||||
if (opt.find("FLOAT") != std::string::npos || opt.find("REAL") != std::string::npos)
|
|
||||||
dataFormat = FloatData;
|
|
||||||
else if (opt.find("DOUBLE") != std::string::npos)
|
|
||||||
dataFormat = DoubleData;
|
|
||||||
else
|
|
||||||
throw vtkm::io::ErrorIO("Unsupported data type: " + token);
|
|
||||||
}
|
|
||||||
else if (token.find("DATA") != std::string::npos &&
|
|
||||||
token.find("COMPONENTS") != std::string::npos)
|
|
||||||
{
|
|
||||||
strStream >> numComponents >> std::ws;
|
|
||||||
if (numComponents != 1 && numComponents != 3)
|
|
||||||
throw vtkm::io::ErrorIO("Unsupported number of components");
|
|
||||||
}
|
|
||||||
else if (token.find("VARIABLE") != std::string::npos &&
|
|
||||||
token.find("PALETTE") == std::string::npos)
|
|
||||||
{
|
|
||||||
strStream >> variableName >> std::ws;
|
|
||||||
if (variableName[0] == '"')
|
|
||||||
variableName = variableName.substr(1, variableName.size() - 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (spacingSet)
|
|
||||||
{
|
|
||||||
spacing[0] = (spacing[0]) / static_cast<vtkm::FloatDefault>(dim[0] - 1);
|
|
||||||
spacing[1] = (spacing[1]) / static_cast<vtkm::FloatDefault>(dim[1] - 1);
|
|
||||||
spacing[2] = (spacing[2]) / static_cast<vtkm::FloatDefault>(dim[2] - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string fullPathDataFile;
|
|
||||||
std::size_t pos = FileName.rfind("/");
|
|
||||||
if (pos != std::string::npos)
|
|
||||||
{
|
|
||||||
std::string baseDir;
|
|
||||||
baseDir = this->FileName.substr(0, pos);
|
|
||||||
fullPathDataFile = baseDir + "/" + bovFile;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
fullPathDataFile = bovFile;
|
|
||||||
|
|
||||||
|
|
||||||
vtkm::cont::DataSetBuilderUniform dataSetBuilder;
|
|
||||||
vtkm::cont::DataSetFieldAdd dsf;
|
|
||||||
this->DataSet = dataSetBuilder.Create(dim, origin, spacing);
|
|
||||||
|
|
||||||
vtkm::Id numTuples = dim[0] * dim[1] * dim[2];
|
|
||||||
if (numComponents == 1)
|
|
||||||
{
|
|
||||||
if (dataFormat == FloatData)
|
|
||||||
{
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Float32> var;
|
|
||||||
ReadScalar(fullPathDataFile, numTuples, var);
|
|
||||||
dsf.AddPointField(this->DataSet, variableName, var);
|
|
||||||
}
|
|
||||||
else if (dataFormat == DoubleData)
|
|
||||||
{
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Float64> var;
|
|
||||||
ReadScalar(fullPathDataFile, numTuples, var);
|
|
||||||
dsf.AddPointField(this->DataSet, variableName, var);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (numComponents == 3)
|
|
||||||
{
|
|
||||||
if (dataFormat == FloatData)
|
|
||||||
{
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Vec3f_32> var;
|
|
||||||
ReadVector(fullPathDataFile, numTuples, var);
|
|
||||||
dsf.AddPointField(this->DataSet, variableName, var);
|
|
||||||
}
|
|
||||||
else if (dataFormat == DoubleData)
|
|
||||||
{
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Vec3f_64> var;
|
|
||||||
ReadVector(fullPathDataFile, numTuples, var);
|
|
||||||
dsf.AddPointField(this->DataSet, variableName, var);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this->Loaded = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void ReadBuffer(const std::string& fName, const vtkm::Id& sz, std::vector<T>& buff)
|
|
||||||
{
|
|
||||||
FILE* fp = fopen(fName.c_str(), "rb");
|
|
||||||
size_t readSize = static_cast<size_t>(sz);
|
|
||||||
if (fp == nullptr)
|
|
||||||
throw vtkm::io::ErrorIO("Unable to open data file: " + fName);
|
|
||||||
buff.resize(readSize);
|
|
||||||
size_t nread = fread(&buff[0], sizeof(T), readSize, fp);
|
|
||||||
if (nread != readSize)
|
|
||||||
throw vtkm::io::ErrorIO("Data file read failed: " + fName);
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void ReadScalar(const std::string& fName,
|
|
||||||
const vtkm::Id& nTuples,
|
|
||||||
vtkm::cont::ArrayHandle<T>& var)
|
|
||||||
{
|
|
||||||
std::vector<T> buff;
|
|
||||||
ReadBuffer(fName, nTuples, buff);
|
|
||||||
var.Allocate(nTuples);
|
|
||||||
auto writePortal = var.WritePortal();
|
|
||||||
for (vtkm::Id i = 0; i < nTuples; i++)
|
|
||||||
writePortal.Set(i, buff[(size_t)i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
void ReadVector(const std::string& fName,
|
|
||||||
const vtkm::Id& nTuples,
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Vec<T, 3>>& var)
|
|
||||||
{
|
|
||||||
std::vector<T> buff;
|
|
||||||
ReadBuffer(fName, nTuples * 3, buff);
|
|
||||||
|
|
||||||
var.Allocate(nTuples);
|
|
||||||
vtkm::Vec<T, 3> v;
|
|
||||||
auto writePortal = var.WritePortal();
|
|
||||||
for (vtkm::Id i = 0; i < nTuples; i++)
|
|
||||||
{
|
|
||||||
v[0] = buff[static_cast<size_t>(i * 3 + 0)];
|
|
||||||
v[1] = buff[static_cast<size_t>(i * 3 + 1)];
|
|
||||||
v[2] = buff[static_cast<size_t>(i * 3 + 2)];
|
|
||||||
writePortal.Set(i, v);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string FileName;
|
std::string FileName;
|
||||||
bool Loaded;
|
bool Loaded;
|
||||||
|
@ -18,12 +18,12 @@ set(headers
|
|||||||
PixelTypes.h
|
PixelTypes.h
|
||||||
VTKDataSetReader.h
|
VTKDataSetReader.h
|
||||||
VTKDataSetReaderBase.h
|
VTKDataSetReaderBase.h
|
||||||
|
VTKDataSetWriter.h
|
||||||
VTKPolyDataReader.h
|
VTKPolyDataReader.h
|
||||||
VTKRectilinearGridReader.h
|
VTKRectilinearGridReader.h
|
||||||
VTKStructuredGridReader.h
|
VTKStructuredGridReader.h
|
||||||
VTKStructuredPointsReader.h
|
VTKStructuredPointsReader.h
|
||||||
VTKUnstructuredGridReader.h
|
VTKUnstructuredGridReader.h
|
||||||
VTKDataSetWriter.h
|
|
||||||
)
|
)
|
||||||
|
|
||||||
set(template_sources
|
set(template_sources
|
||||||
@ -37,6 +37,22 @@ set(sources
|
|||||||
EncodePNG.cxx
|
EncodePNG.cxx
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# TODO: None of these codes actually use a device. Rather, they access ArrayHandle, and we
|
||||||
|
# currently need to ensure that ArrayHandle is correctly compiled for all devices. This is
|
||||||
|
# kind of silly, so hopefully sometime in the future you will no longer need to compile for
|
||||||
|
# devices for ArrayHandle, and this requirement will go away.
|
||||||
|
set(device_sources
|
||||||
|
BOVDataSetReader.cxx
|
||||||
|
VTKDataSetReader.cxx
|
||||||
|
VTKDataSetReaderBase.cxx
|
||||||
|
VTKDataSetWriter.cxx
|
||||||
|
VTKPolyDataReader.cxx
|
||||||
|
VTKRectilinearGridReader.cxx
|
||||||
|
VTKStructuredGridReader.cxx
|
||||||
|
VTKStructuredPointsReader.cxx
|
||||||
|
VTKUnstructuredGridReader.cxx
|
||||||
|
)
|
||||||
|
|
||||||
vtkm_declare_headers(
|
vtkm_declare_headers(
|
||||||
${headers}
|
${headers}
|
||||||
${template_sources}
|
${template_sources}
|
||||||
@ -45,6 +61,7 @@ vtkm_declare_headers(
|
|||||||
vtkm_library(
|
vtkm_library(
|
||||||
NAME vtkm_io
|
NAME vtkm_io
|
||||||
SOURCES ${sources}
|
SOURCES ${sources}
|
||||||
|
DEVICE_SOURCES ${device_sources}
|
||||||
HEADERS ${headers}
|
HEADERS ${headers}
|
||||||
TEMPLATE_SOURCES ${template_sources}
|
TEMPLATE_SOURCES ${template_sources}
|
||||||
)
|
)
|
||||||
|
92
vtkm/io/VTKDataSetReader.cxx
Normal file
92
vtkm/io/VTKDataSetReader.cxx
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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/VTKDataSetReader.h>
|
||||||
|
|
||||||
|
#include <vtkm/io/VTKPolyDataReader.h>
|
||||||
|
#include <vtkm/io/VTKRectilinearGridReader.h>
|
||||||
|
#include <vtkm/io/VTKStructuredGridReader.h>
|
||||||
|
#include <vtkm/io/VTKStructuredPointsReader.h>
|
||||||
|
#include <vtkm/io/VTKUnstructuredGridReader.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace io
|
||||||
|
{
|
||||||
|
|
||||||
|
VTKDataSetReader::VTKDataSetReader(const char* fileName)
|
||||||
|
: VTKDataSetReaderBase(fileName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKDataSetReader::VTKDataSetReader(const std::string& fileName)
|
||||||
|
: VTKDataSetReaderBase(fileName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKDataSetReader::~VTKDataSetReader()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void VTKDataSetReader::PrintSummary(std::ostream& out) const
|
||||||
|
{
|
||||||
|
if (this->Reader)
|
||||||
|
{
|
||||||
|
this->Reader->PrintSummary(out);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VTKDataSetReaderBase::PrintSummary(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VTKDataSetReader::CloseFile()
|
||||||
|
{
|
||||||
|
if (this->Reader)
|
||||||
|
{
|
||||||
|
this->Reader->CloseFile();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
VTKDataSetReaderBase::CloseFile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VTKDataSetReader::Read()
|
||||||
|
{
|
||||||
|
switch (this->DataFile->Structure)
|
||||||
|
{
|
||||||
|
case vtkm::io::internal::DATASET_STRUCTURED_POINTS:
|
||||||
|
this->Reader.reset(new VTKStructuredPointsReader(""));
|
||||||
|
break;
|
||||||
|
case vtkm::io::internal::DATASET_STRUCTURED_GRID:
|
||||||
|
this->Reader.reset(new VTKStructuredGridReader(""));
|
||||||
|
break;
|
||||||
|
case vtkm::io::internal::DATASET_RECTILINEAR_GRID:
|
||||||
|
this->Reader.reset(new VTKRectilinearGridReader(""));
|
||||||
|
break;
|
||||||
|
case vtkm::io::internal::DATASET_POLYDATA:
|
||||||
|
this->Reader.reset(new VTKPolyDataReader(""));
|
||||||
|
break;
|
||||||
|
case vtkm::io::internal::DATASET_UNSTRUCTURED_GRID:
|
||||||
|
this->Reader.reset(new VTKUnstructuredGridReader(""));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw vtkm::io::ErrorIO("Unsupported DataSet type.");
|
||||||
|
}
|
||||||
|
|
||||||
|
this->TransferDataFile(*this->Reader.get());
|
||||||
|
this->Reader->Read();
|
||||||
|
this->DataSet = this->Reader->GetDataSet();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace vtkm::io
|
@ -11,86 +11,27 @@
|
|||||||
#define vtk_m_io_VTKDataSetReader_h
|
#define vtk_m_io_VTKDataSetReader_h
|
||||||
|
|
||||||
#include <vtkm/io/VTKDataSetReaderBase.h>
|
#include <vtkm/io/VTKDataSetReaderBase.h>
|
||||||
#include <vtkm/io/VTKPolyDataReader.h>
|
|
||||||
#include <vtkm/io/VTKRectilinearGridReader.h>
|
|
||||||
#include <vtkm/io/VTKStructuredGridReader.h>
|
|
||||||
#include <vtkm/io/VTKStructuredPointsReader.h>
|
|
||||||
#include <vtkm/io/VTKUnstructuredGridReader.h>
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
namespace vtkm
|
namespace vtkm
|
||||||
{
|
{
|
||||||
namespace io
|
namespace io
|
||||||
{
|
{
|
||||||
|
|
||||||
VTKM_SILENCE_WEAK_VTABLE_WARNING_START
|
class VTKM_IO_EXPORT VTKDataSetReader : public VTKDataSetReaderBase
|
||||||
|
|
||||||
class VTKDataSetReader : public VTKDataSetReaderBase
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit VTKDataSetReader(const char* fileName)
|
VTKM_CONT VTKDataSetReader(const char* fileName);
|
||||||
: VTKDataSetReaderBase(fileName)
|
VTKM_CONT VTKDataSetReader(const std::string& fileName);
|
||||||
{
|
VTKM_CONT ~VTKDataSetReader() override;
|
||||||
}
|
|
||||||
|
|
||||||
explicit VTKDataSetReader(const std::string& fileName)
|
VTKDataSetReader(const VTKDataSetReader&) = delete;
|
||||||
: VTKDataSetReaderBase(fileName)
|
void operator=(const VTKDataSetReader&) = delete;
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void PrintSummary(std::ostream& out) const
|
VTKM_CONT void PrintSummary(std::ostream& out) const override;
|
||||||
{
|
|
||||||
if (this->Reader)
|
|
||||||
{
|
|
||||||
this->Reader->PrintSummary(out);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
VTKDataSetReaderBase::PrintSummary(out);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void CloseFile()
|
VTKM_CONT void CloseFile() override;
|
||||||
{
|
VTKM_CONT void Read() override;
|
||||||
if (this->Reader)
|
|
||||||
{
|
|
||||||
this->Reader->CloseFile();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
VTKDataSetReaderBase::CloseFile();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual void Read()
|
|
||||||
{
|
|
||||||
switch (this->DataFile->Structure)
|
|
||||||
{
|
|
||||||
case vtkm::io::internal::DATASET_STRUCTURED_POINTS:
|
|
||||||
this->Reader.reset(new VTKStructuredPointsReader(""));
|
|
||||||
break;
|
|
||||||
case vtkm::io::internal::DATASET_STRUCTURED_GRID:
|
|
||||||
this->Reader.reset(new VTKStructuredGridReader(""));
|
|
||||||
break;
|
|
||||||
case vtkm::io::internal::DATASET_RECTILINEAR_GRID:
|
|
||||||
this->Reader.reset(new VTKRectilinearGridReader(""));
|
|
||||||
break;
|
|
||||||
case vtkm::io::internal::DATASET_POLYDATA:
|
|
||||||
this->Reader.reset(new VTKPolyDataReader(""));
|
|
||||||
break;
|
|
||||||
case vtkm::io::internal::DATASET_UNSTRUCTURED_GRID:
|
|
||||||
this->Reader.reset(new VTKUnstructuredGridReader(""));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw vtkm::io::ErrorIO("Unsupported DataSet type.");
|
|
||||||
}
|
|
||||||
|
|
||||||
this->TransferDataFile(*this->Reader.get());
|
|
||||||
this->Reader->Read();
|
|
||||||
this->DataSet = this->Reader->GetDataSet();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::unique_ptr<VTKDataSetReaderBase> Reader;
|
std::unique_ptr<VTKDataSetReaderBase> Reader;
|
||||||
};
|
};
|
||||||
|
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
|
#ifndef vtk_m_io_VTKDataSetReaderBase_h
|
||||||
#define 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/Endian.h>
|
||||||
#include <vtkm/io/internal/VTKDataSetCells.h>
|
|
||||||
#include <vtkm/io/internal/VTKDataSetStructures.h>
|
#include <vtkm/io/internal/VTKDataSetStructures.h>
|
||||||
#include <vtkm/io/internal/VTKDataSetTypes.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 <fstream>
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace vtkm
|
namespace vtkm
|
||||||
{
|
{
|
||||||
@ -48,16 +39,6 @@ struct VTKDataSetFile
|
|||||||
std::ifstream Stream;
|
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)
|
inline void parseAssert(bool condition)
|
||||||
{
|
{
|
||||||
if (!condition)
|
if (!condition)
|
||||||
@ -82,166 +63,6 @@ struct StreamIOType<vtkm::UInt8>
|
|||||||
using Type = vtkm::UInt16;
|
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)
|
inline vtkm::cont::DynamicCellSet CreateCellSetStructured(const vtkm::Id3& dim)
|
||||||
{
|
{
|
||||||
if (dim[0] > 1 && dim[1] > 1 && dim[2] > 1)
|
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
|
} // namespace internal
|
||||||
|
|
||||||
VTKM_SILENCE_WEAK_VTABLE_WARNING_START
|
class VTKM_IO_EXPORT VTKDataSetReaderBase
|
||||||
|
|
||||||
class 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:
|
public:
|
||||||
explicit VTKDataSetReaderBase(const char* fileName)
|
explicit VTKM_CONT VTKDataSetReaderBase(const char* fileName);
|
||||||
: DataFile(new internal::VTKDataSetFile)
|
|
||||||
, DataSet()
|
|
||||||
, Loaded(false)
|
|
||||||
{
|
|
||||||
this->DataFile->FileName = fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit VTKDataSetReaderBase(const std::string& fileName)
|
explicit VTKM_CONT VTKDataSetReaderBase(const std::string& fileName);
|
||||||
: DataFile(new internal::VTKDataSetFile)
|
|
||||||
, DataSet()
|
|
||||||
, Loaded(false)
|
|
||||||
{
|
|
||||||
this->DataFile->FileName = fileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual ~VTKDataSetReaderBase() {}
|
virtual VTKM_CONT ~VTKDataSetReaderBase();
|
||||||
|
|
||||||
const vtkm::cont::DataSet& ReadDataSet()
|
VTKDataSetReaderBase(const VTKDataSetReaderBase&) = delete;
|
||||||
{
|
void operator=(const VTKDataSetReaderBase&) = delete;
|
||||||
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;
|
const VTKM_CONT vtkm::cont::DataSet& ReadDataSet();
|
||||||
}
|
|
||||||
|
|
||||||
const vtkm::cont::DataSet& GetDataSet() const { return this->DataSet; }
|
const vtkm::cont::DataSet& GetDataSet() const { return this->DataSet; }
|
||||||
|
|
||||||
virtual void PrintSummary(std::ostream& out) const
|
virtual VTKM_CONT void PrintSummary(std::ostream& out) const;
|
||||||
{
|
|
||||||
out << "VTKDataSetReader" << std::endl;
|
|
||||||
PrintVTKDataFileSummary(*this->DataFile.get(), out);
|
|
||||||
this->DataSet.PrintSummary(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void ReadPoints()
|
VTKM_CONT void ReadPoints();
|
||||||
{
|
|
||||||
std::string dataType;
|
|
||||||
std::size_t numPoints;
|
|
||||||
this->DataFile->Stream >> numPoints >> dataType >> std::ws;
|
|
||||||
|
|
||||||
vtkm::cont::VariantArrayHandle points =
|
VTKM_CONT void ReadCells(vtkm::cont::ArrayHandle<vtkm::Id>& connectivity,
|
||||||
this->DoReadArrayVariant(vtkm::cont::Field::Association::POINTS, dataType, numPoints, 3);
|
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 void ReadAttributes();
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetCellsPermutation(const vtkm::cont::ArrayHandle<vtkm::Id>& permutation)
|
void SetCellsPermutation(const vtkm::cont::ArrayHandle<vtkm::Id>& permutation)
|
||||||
{
|
{
|
||||||
this->CellsPermutation = 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);
|
reader.DataFile.swap(this->DataFile);
|
||||||
this->DataFile.reset(nullptr);
|
this->DataFile.reset(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void CloseFile() { this->DataFile->Stream.close(); }
|
VTKM_CONT virtual void CloseFile();
|
||||||
|
|
||||||
|
VTKM_CONT virtual void Read() = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void OpenFile()
|
VTKM_CONT void OpenFile();
|
||||||
{
|
VTKM_CONT void ReadHeader();
|
||||||
this->DataFile->Stream.exceptions(std::ifstream::failbit | std::ifstream::badbit);
|
VTKM_CONT void AddField(const std::string& name,
|
||||||
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::Field::Association association,
|
||||||
vtkm::cont::VariantArrayHandle& data)
|
vtkm::cont::VariantArrayHandle& data);
|
||||||
{
|
VTKM_CONT void ReadScalars(vtkm::cont::Field::Association association, std::size_t numElements);
|
||||||
if (data.GetNumberOfValues() > 0)
|
VTKM_CONT void ReadColorScalars(vtkm::cont::Field::Association association,
|
||||||
{
|
std::size_t numElements);
|
||||||
switch (association)
|
VTKM_CONT void ReadLookupTable();
|
||||||
{
|
VTKM_CONT void ReadTextureCoordinates(vtkm::cont::Field::Association association,
|
||||||
case vtkm::cont::Field::Association::POINTS:
|
std::size_t numElements);
|
||||||
case vtkm::cont::Field::Association::WHOLE_MESH:
|
VTKM_CONT void ReadVectors(vtkm::cont::Field::Association association, std::size_t numElements);
|
||||||
this->DataSet.AddField(vtkm::cont::Field(name, association, data));
|
VTKM_CONT void ReadTensors(vtkm::cont::Field::Association association, std::size_t numElements);
|
||||||
break;
|
VTKM_CONT void ReadFields(vtkm::cont::Field::Association association,
|
||||||
case vtkm::cont::Field::Association::CELL_SET:
|
std::size_t expectedNumElements);
|
||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void ReadGlobalFields(std::vector<vtkm::Float32>* visitBounds = nullptr)
|
VTKM_CONT 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class SkipArrayVariant
|
class SkipArrayVariant;
|
||||||
{
|
class ReadArrayVariant;
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
//Make the Array parsing methods protected so that derived classes
|
//Make the Array parsing methods protected so that derived classes
|
||||||
//can call the methods.
|
//can call the methods.
|
||||||
protected:
|
protected:
|
||||||
void DoSkipArrayVariant(std::string dataType,
|
VTKM_CONT void DoSkipArrayVariant(std::string dataType,
|
||||||
std::size_t numElements,
|
std::size_t numElements,
|
||||||
vtkm::IdComponent numComponents)
|
vtkm::IdComponent numComponents);
|
||||||
{
|
VTKM_CONT vtkm::cont::VariantArrayHandle DoReadArrayVariant(
|
||||||
// string is unsupported for SkipArrayVariant, so it requires some
|
vtkm::cont::Field::Association association,
|
||||||
// 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::string dataType,
|
||||||
std::size_t numElements,
|
std::size_t numElements,
|
||||||
vtkm::IdComponent numComponents)
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void ReadArray(std::vector<T>& buffer)
|
VTKM_CONT void ReadArray(std::vector<T>& buffer)
|
||||||
{
|
{
|
||||||
using ComponentType = typename vtkm::VecTraits<T>::ComponentType;
|
using ComponentType = typename vtkm::VecTraits<T>::ComponentType;
|
||||||
constexpr vtkm::IdComponent numComponents = vtkm::VecTraits<T>::NUM_COMPONENTS;
|
constexpr vtkm::IdComponent numComponents = vtkm::VecTraits<T>::NUM_COMPONENTS;
|
||||||
@ -861,7 +220,8 @@ protected:
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <vtkm::IdComponent NumComponents>
|
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,
|
VTKM_LOG_S(vtkm::cont::LogLevel::Warn,
|
||||||
"Support for data type 'bit' is not implemented. Skipping.");
|
"Support for data type 'bit' is not implemented. Skipping.");
|
||||||
@ -869,13 +229,7 @@ protected:
|
|||||||
buffer.clear();
|
buffer.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadArray(std::vector<vtkm::io::internal::DummyBitType>& buffer)
|
VTKM_CONT 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void SkipArray(std::size_t numElements, T)
|
void SkipArray(std::size_t numElements, T)
|
||||||
@ -912,99 +266,13 @@ protected:
|
|||||||
NumComponents);
|
NumComponents);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SkipArray(std::size_t numElements,
|
VTKM_CONT void SkipArray(std::size_t numElements,
|
||||||
vtkm::io::internal::DummyBitType,
|
vtkm::io::internal::DummyBitType,
|
||||||
vtkm::IdComponent numComponents = 1)
|
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SkipArrayMetaData(vtkm::IdComponent numComponents)
|
VTKM_CONT 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_SILENCE_WEAK_VTABLE_WARNING_END
|
|
||||||
}
|
}
|
||||||
} // vtkm::io
|
} // vtkm::io
|
||||||
|
|
||||||
VTKM_BASIC_TYPE_VECTOR(vtkm::io::internal::ColorChannel8)
|
|
||||||
VTKM_BASIC_TYPE_VECTOR(vtkm::io::internal::DummyBitType)
|
|
||||||
|
|
||||||
#endif // vtk_m_io_VTKDataSetReaderBase_h
|
#endif // vtk_m_io_VTKDataSetReaderBase_h
|
||||||
|
407
vtkm/io/VTKDataSetWriter.cxx
Normal file
407
vtkm/io/VTKDataSetWriter.cxx
Normal file
@ -0,0 +1,407 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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/VTKDataSetWriter.h>
|
||||||
|
|
||||||
|
#include <vtkm/CellShape.h>
|
||||||
|
|
||||||
|
#include <vtkm/cont/CellSetExplicit.h>
|
||||||
|
#include <vtkm/cont/CellSetSingleType.h>
|
||||||
|
#include <vtkm/cont/CellSetStructured.h>
|
||||||
|
#include <vtkm/cont/ErrorBadType.h>
|
||||||
|
#include <vtkm/cont/ErrorBadValue.h>
|
||||||
|
#include <vtkm/cont/Field.h>
|
||||||
|
|
||||||
|
#include <vtkm/io/ErrorIO.h>
|
||||||
|
|
||||||
|
#include <vtkm/io/internal/VTKDataSetTypes.h>
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cctype>
|
||||||
|
#include <cstring>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
struct OutputPointsFunctor
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::ostream& out;
|
||||||
|
|
||||||
|
template <typename PortalType>
|
||||||
|
VTKM_CONT void Output(const PortalType& portal) const
|
||||||
|
{
|
||||||
|
for (vtkm::Id index = 0; index < portal.GetNumberOfValues(); index++)
|
||||||
|
{
|
||||||
|
const int VTKDims = 3; // VTK files always require 3 dims for points
|
||||||
|
|
||||||
|
using ValueType = typename PortalType::ValueType;
|
||||||
|
using VecType = typename vtkm::VecTraits<ValueType>;
|
||||||
|
|
||||||
|
const ValueType& value = portal.Get(index);
|
||||||
|
|
||||||
|
vtkm::IdComponent numComponents = VecType::GetNumberOfComponents(value);
|
||||||
|
for (vtkm::IdComponent c = 0; c < numComponents && c < VTKDims; c++)
|
||||||
|
{
|
||||||
|
out << (c == 0 ? "" : " ") << VecType::GetComponent(value, c);
|
||||||
|
}
|
||||||
|
for (vtkm::IdComponent c = numComponents; c < VTKDims; c++)
|
||||||
|
{
|
||||||
|
out << " 0";
|
||||||
|
}
|
||||||
|
out << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
VTKM_CONT
|
||||||
|
OutputPointsFunctor(std::ostream& o)
|
||||||
|
: out(o)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Storage>
|
||||||
|
VTKM_CONT void operator()(const vtkm::cont::ArrayHandle<T, Storage>& array) const
|
||||||
|
{
|
||||||
|
this->Output(array.ReadPortal());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct OutputFieldFunctor
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::ostream& out;
|
||||||
|
|
||||||
|
template <typename PortalType>
|
||||||
|
VTKM_CONT void Output(const PortalType& portal) const
|
||||||
|
{
|
||||||
|
for (vtkm::Id index = 0; index < portal.GetNumberOfValues(); index++)
|
||||||
|
{
|
||||||
|
using ValueType = typename PortalType::ValueType;
|
||||||
|
using VecType = typename vtkm::VecTraits<ValueType>;
|
||||||
|
|
||||||
|
const ValueType& value = portal.Get(index);
|
||||||
|
|
||||||
|
vtkm::IdComponent numComponents = VecType::GetNumberOfComponents(value);
|
||||||
|
for (vtkm::IdComponent c = 0; c < numComponents; c++)
|
||||||
|
{
|
||||||
|
out << (c == 0 ? "" : " ") << VecType::GetComponent(value, c);
|
||||||
|
}
|
||||||
|
out << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
VTKM_CONT
|
||||||
|
OutputFieldFunctor(std::ostream& o)
|
||||||
|
: out(o)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename Storage>
|
||||||
|
VTKM_CONT void operator()(const vtkm::cont::ArrayHandle<T, Storage>& array) const
|
||||||
|
{
|
||||||
|
this->Output(array.ReadPortal());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class GetDataTypeName
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GetDataTypeName(std::string& name)
|
||||||
|
: Name(&name)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename ArrayHandleType>
|
||||||
|
void operator()(const ArrayHandleType&) const
|
||||||
|
{
|
||||||
|
using DataType = typename vtkm::VecTraits<typename ArrayHandleType::ValueType>::ComponentType;
|
||||||
|
*this->Name = vtkm::io::internal::DataTypeName<DataType>::Name();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string* Name;
|
||||||
|
};
|
||||||
|
|
||||||
|
void WritePoints(std::ostream& out, const vtkm::cont::DataSet& dataSet)
|
||||||
|
{
|
||||||
|
///\todo: support other coordinate systems
|
||||||
|
int cindex = 0;
|
||||||
|
auto cdata = dataSet.GetCoordinateSystem(cindex).GetData();
|
||||||
|
|
||||||
|
vtkm::Id npoints = cdata.GetNumberOfValues();
|
||||||
|
out << "POINTS " << npoints << " " << vtkm::io::internal::DataTypeName<vtkm::FloatDefault>::Name()
|
||||||
|
<< " " << '\n';
|
||||||
|
|
||||||
|
OutputPointsFunctor{ out }(cdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CellSetType>
|
||||||
|
void WriteExplicitCells(std::ostream& out, const CellSetType& cellSet)
|
||||||
|
{
|
||||||
|
vtkm::Id nCells = cellSet.GetNumberOfCells();
|
||||||
|
|
||||||
|
vtkm::Id conn_length = 0;
|
||||||
|
for (vtkm::Id i = 0; i < nCells; ++i)
|
||||||
|
{
|
||||||
|
conn_length += 1 + cellSet.GetNumberOfPointsInCell(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "CELLS " << nCells << " " << conn_length << '\n';
|
||||||
|
|
||||||
|
for (vtkm::Id i = 0; i < nCells; ++i)
|
||||||
|
{
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::Id> ids;
|
||||||
|
vtkm::Id nids = cellSet.GetNumberOfPointsInCell(i);
|
||||||
|
cellSet.GetIndices(i, ids);
|
||||||
|
out << nids;
|
||||||
|
auto IdPortal = ids.ReadPortal();
|
||||||
|
for (int j = 0; j < nids; ++j)
|
||||||
|
out << " " << IdPortal.Get(j);
|
||||||
|
out << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "CELL_TYPES " << nCells << '\n';
|
||||||
|
for (vtkm::Id i = 0; i < nCells; ++i)
|
||||||
|
{
|
||||||
|
vtkm::Id shape = cellSet.GetCellShape(i);
|
||||||
|
out << shape << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteVertexCells(std::ostream& out, const vtkm::cont::DataSet& dataSet)
|
||||||
|
{
|
||||||
|
vtkm::Id nCells = dataSet.GetCoordinateSystem(0).GetNumberOfPoints();
|
||||||
|
|
||||||
|
out << "CELLS " << nCells << " " << nCells * 2 << '\n';
|
||||||
|
for (int i = 0; i < nCells; i++)
|
||||||
|
{
|
||||||
|
out << "1 " << i << '\n';
|
||||||
|
}
|
||||||
|
out << "CELL_TYPES " << nCells << '\n';
|
||||||
|
for (int i = 0; i < nCells; i++)
|
||||||
|
{
|
||||||
|
out << vtkm::CELL_SHAPE_VERTEX << '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WritePointFields(std::ostream& out, const vtkm::cont::DataSet& dataSet)
|
||||||
|
{
|
||||||
|
bool wrote_header = false;
|
||||||
|
for (vtkm::Id f = 0; f < dataSet.GetNumberOfFields(); f++)
|
||||||
|
{
|
||||||
|
const vtkm::cont::Field field = dataSet.GetField(f);
|
||||||
|
|
||||||
|
if (field.GetAssociation() != vtkm::cont::Field::Association::POINTS)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
vtkm::Id npoints = field.GetNumberOfValues();
|
||||||
|
int ncomps = field.GetData().GetNumberOfComponents();
|
||||||
|
if (ncomps > 4)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!wrote_header)
|
||||||
|
{
|
||||||
|
out << "POINT_DATA " << npoints << '\n';
|
||||||
|
wrote_header = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string typeName;
|
||||||
|
vtkm::cont::CastAndCall(field.GetData().ResetTypes(vtkm::TypeListAll{}),
|
||||||
|
GetDataTypeName(typeName));
|
||||||
|
std::string name = field.GetName();
|
||||||
|
for (auto& c : name)
|
||||||
|
{
|
||||||
|
if (std::isspace(c))
|
||||||
|
{
|
||||||
|
c = '_';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << "SCALARS " << name << " " << typeName << " " << ncomps << '\n';
|
||||||
|
out << "LOOKUP_TABLE default" << '\n';
|
||||||
|
|
||||||
|
vtkm::cont::CastAndCall(field.GetData().ResetTypes(vtkm::TypeListAll{}),
|
||||||
|
OutputFieldFunctor(out));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteCellFields(std::ostream& out, const vtkm::cont::DataSet& dataSet)
|
||||||
|
{
|
||||||
|
bool wrote_header = false;
|
||||||
|
for (vtkm::Id f = 0; f < dataSet.GetNumberOfFields(); f++)
|
||||||
|
{
|
||||||
|
const vtkm::cont::Field field = dataSet.GetField(f);
|
||||||
|
if (!field.IsFieldCell())
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
vtkm::Id ncells = field.GetNumberOfValues();
|
||||||
|
int ncomps = field.GetData().GetNumberOfComponents();
|
||||||
|
if (ncomps > 4)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!wrote_header)
|
||||||
|
{
|
||||||
|
out << "CELL_DATA " << ncells << '\n';
|
||||||
|
wrote_header = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string typeName;
|
||||||
|
vtkm::cont::CastAndCall(field.GetData().ResetTypes(vtkm::TypeListAll{}),
|
||||||
|
GetDataTypeName(typeName));
|
||||||
|
|
||||||
|
std::string name = field.GetName();
|
||||||
|
for (auto& c : name)
|
||||||
|
{
|
||||||
|
if (std::isspace(c))
|
||||||
|
{
|
||||||
|
c = '_';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out << "SCALARS " << name << " " << typeName << " " << ncomps << '\n';
|
||||||
|
out << "LOOKUP_TABLE default" << '\n';
|
||||||
|
|
||||||
|
vtkm::cont::CastAndCall(field.GetData().ResetTypes(vtkm::TypeListAll{}),
|
||||||
|
OutputFieldFunctor(out));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void WriteDataSetAsPoints(std::ostream& out, const vtkm::cont::DataSet& dataSet)
|
||||||
|
{
|
||||||
|
out << "DATASET UNSTRUCTURED_GRID" << '\n';
|
||||||
|
WritePoints(out, dataSet);
|
||||||
|
WriteVertexCells(out, dataSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class CellSetType>
|
||||||
|
void WriteDataSetAsUnstructured(std::ostream& out,
|
||||||
|
const vtkm::cont::DataSet& dataSet,
|
||||||
|
const CellSetType& cellSet)
|
||||||
|
{
|
||||||
|
out << "DATASET UNSTRUCTURED_GRID" << '\n';
|
||||||
|
WritePoints(out, dataSet);
|
||||||
|
WriteExplicitCells(out, cellSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <vtkm::IdComponent DIM>
|
||||||
|
void WriteDataSetAsStructured(std::ostream& out,
|
||||||
|
const vtkm::cont::DataSet& dataSet,
|
||||||
|
const vtkm::cont::CellSetStructured<DIM>& cellSet)
|
||||||
|
{
|
||||||
|
///\todo: support uniform/rectilinear
|
||||||
|
out << "DATASET STRUCTURED_GRID" << '\n';
|
||||||
|
|
||||||
|
auto pointDimensions = cellSet.GetPointDimensions();
|
||||||
|
using VTraits = vtkm::VecTraits<decltype(pointDimensions)>;
|
||||||
|
|
||||||
|
out << "DIMENSIONS ";
|
||||||
|
out << VTraits::GetComponent(pointDimensions, 0) << " ";
|
||||||
|
out << (DIM > 1 ? VTraits::GetComponent(pointDimensions, 1) : 1) << " ";
|
||||||
|
out << (DIM > 2 ? VTraits::GetComponent(pointDimensions, 2) : 1) << " ";
|
||||||
|
|
||||||
|
WritePoints(out, dataSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Write(std::ostream& out, const vtkm::cont::DataSet& dataSet, bool just_points = false)
|
||||||
|
{
|
||||||
|
// The Paraview parser cannot handle scientific notation:
|
||||||
|
out << std::fixed;
|
||||||
|
out << "# vtk DataFile Version 3.0" << '\n';
|
||||||
|
out << "vtk output" << '\n';
|
||||||
|
out << "ASCII" << '\n';
|
||||||
|
|
||||||
|
if (just_points)
|
||||||
|
{
|
||||||
|
WriteDataSetAsPoints(out, dataSet);
|
||||||
|
WritePointFields(out, dataSet);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vtkm::cont::DynamicCellSet cellSet = dataSet.GetCellSet();
|
||||||
|
if (cellSet.IsType<vtkm::cont::CellSetExplicit<>>())
|
||||||
|
{
|
||||||
|
WriteDataSetAsUnstructured(out, dataSet, cellSet.Cast<vtkm::cont::CellSetExplicit<>>());
|
||||||
|
}
|
||||||
|
else if (cellSet.IsType<vtkm::cont::CellSetStructured<1>>())
|
||||||
|
{
|
||||||
|
WriteDataSetAsStructured(out, dataSet, cellSet.Cast<vtkm::cont::CellSetStructured<1>>());
|
||||||
|
}
|
||||||
|
else if (cellSet.IsType<vtkm::cont::CellSetStructured<2>>())
|
||||||
|
{
|
||||||
|
WriteDataSetAsStructured(out, dataSet, cellSet.Cast<vtkm::cont::CellSetStructured<2>>());
|
||||||
|
}
|
||||||
|
else if (cellSet.IsType<vtkm::cont::CellSetStructured<3>>())
|
||||||
|
{
|
||||||
|
WriteDataSetAsStructured(out, dataSet, cellSet.Cast<vtkm::cont::CellSetStructured<3>>());
|
||||||
|
}
|
||||||
|
else if (cellSet.IsType<vtkm::cont::CellSetSingleType<>>())
|
||||||
|
{
|
||||||
|
// these function just like explicit cell sets
|
||||||
|
WriteDataSetAsUnstructured(out, dataSet, cellSet.Cast<vtkm::cont::CellSetSingleType<>>());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw vtkm::cont::ErrorBadType("Could not determine type to write out.");
|
||||||
|
}
|
||||||
|
|
||||||
|
WritePointFields(out, dataSet);
|
||||||
|
WriteCellFields(out, dataSet);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // anonymous namespace
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace io
|
||||||
|
{
|
||||||
|
|
||||||
|
VTKDataSetWriter::VTKDataSetWriter(const char* fileName)
|
||||||
|
: FileName(fileName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKDataSetWriter::VTKDataSetWriter(const std::string& fileName)
|
||||||
|
: FileName(fileName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void VTKDataSetWriter::WriteDataSet(const vtkm::cont::DataSet& dataSet, bool just_points) const
|
||||||
|
{
|
||||||
|
if (dataSet.GetNumberOfCoordinateSystems() < 1)
|
||||||
|
{
|
||||||
|
throw vtkm::cont::ErrorBadValue(
|
||||||
|
"DataSet has no coordinate system, which is not supported by VTK file format.");
|
||||||
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
std::ofstream fileStream(this->FileName.c_str(), std::fstream::trunc);
|
||||||
|
Write(fileStream, dataSet, just_points);
|
||||||
|
fileStream.close();
|
||||||
|
}
|
||||||
|
catch (std::ofstream::failure& error)
|
||||||
|
{
|
||||||
|
throw vtkm::io::ErrorIO(error.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace vtkm::io
|
@ -10,400 +10,22 @@
|
|||||||
#ifndef vtk_m_io_DataSetWriter_h
|
#ifndef vtk_m_io_DataSetWriter_h
|
||||||
#define vtk_m_io_DataSetWriter_h
|
#define vtk_m_io_DataSetWriter_h
|
||||||
|
|
||||||
#include <cctype>
|
|
||||||
#include <vtkm/CellShape.h>
|
|
||||||
|
|
||||||
#include <vtkm/cont/CellSetExplicit.h>
|
|
||||||
#include <vtkm/cont/CellSetSingleType.h>
|
|
||||||
#include <vtkm/cont/CellSetStructured.h>
|
|
||||||
#include <vtkm/cont/DataSet.h>
|
#include <vtkm/cont/DataSet.h>
|
||||||
#include <vtkm/cont/ErrorBadType.h>
|
|
||||||
#include <vtkm/cont/ErrorBadValue.h>
|
|
||||||
#include <vtkm/cont/Field.h>
|
|
||||||
|
|
||||||
#include <vtkm/io/ErrorIO.h>
|
#include <vtkm/io/vtkm_io_export.h>
|
||||||
|
|
||||||
#include <vtkm/io/internal/VTKDataSetTypes.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <cstring>
|
|
||||||
#include <fstream>
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
namespace vtkm
|
namespace vtkm
|
||||||
{
|
{
|
||||||
namespace io
|
namespace io
|
||||||
{
|
{
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
|
|
||||||
struct OutputPointsFunctor
|
struct VTKM_IO_EXPORT VTKDataSetWriter
|
||||||
{
|
|
||||||
private:
|
|
||||||
std::ostream& out;
|
|
||||||
|
|
||||||
template <typename PortalType>
|
|
||||||
VTKM_CONT void Output(const PortalType& portal) const
|
|
||||||
{
|
|
||||||
for (vtkm::Id index = 0; index < portal.GetNumberOfValues(); index++)
|
|
||||||
{
|
|
||||||
const int VTKDims = 3; // VTK files always require 3 dims for points
|
|
||||||
|
|
||||||
using ValueType = typename PortalType::ValueType;
|
|
||||||
using VecType = typename vtkm::VecTraits<ValueType>;
|
|
||||||
|
|
||||||
const ValueType& value = portal.Get(index);
|
|
||||||
|
|
||||||
vtkm::IdComponent numComponents = VecType::GetNumberOfComponents(value);
|
|
||||||
for (vtkm::IdComponent c = 0; c < numComponents && c < VTKDims; c++)
|
|
||||||
{
|
|
||||||
out << (c == 0 ? "" : " ") << VecType::GetComponent(value, c);
|
|
||||||
}
|
|
||||||
for (vtkm::IdComponent c = numComponents; c < VTKDims; c++)
|
|
||||||
{
|
|
||||||
out << " 0";
|
|
||||||
}
|
|
||||||
out << '\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
VTKM_CONT
|
|
||||||
OutputPointsFunctor(std::ostream& o)
|
|
||||||
: out(o)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename Storage>
|
|
||||||
VTKM_CONT void operator()(const vtkm::cont::ArrayHandle<T, Storage>& array) const
|
|
||||||
{
|
|
||||||
this->Output(array.ReadPortal());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct OutputFieldFunctor
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
std::ostream& out;
|
|
||||||
|
|
||||||
template <typename PortalType>
|
|
||||||
VTKM_CONT void Output(const PortalType& portal) const
|
|
||||||
{
|
|
||||||
for (vtkm::Id index = 0; index < portal.GetNumberOfValues(); index++)
|
|
||||||
{
|
|
||||||
using ValueType = typename PortalType::ValueType;
|
|
||||||
using VecType = typename vtkm::VecTraits<ValueType>;
|
|
||||||
|
|
||||||
const ValueType& value = portal.Get(index);
|
|
||||||
|
|
||||||
vtkm::IdComponent numComponents = VecType::GetNumberOfComponents(value);
|
|
||||||
for (vtkm::IdComponent c = 0; c < numComponents; c++)
|
|
||||||
{
|
|
||||||
out << (c == 0 ? "" : " ") << VecType::GetComponent(value, c);
|
|
||||||
}
|
|
||||||
out << '\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
VTKM_CONT
|
|
||||||
OutputFieldFunctor(std::ostream& o)
|
|
||||||
: out(o)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename T, typename Storage>
|
|
||||||
VTKM_CONT void operator()(const vtkm::cont::ArrayHandle<T, Storage>& array) const
|
|
||||||
{
|
|
||||||
this->Output(array.ReadPortal());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
class GetDataTypeName
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
GetDataTypeName(std::string& name)
|
VTKM_CONT VTKDataSetWriter(const char* fileName);
|
||||||
: Name(&name)
|
VTKM_CONT VTKDataSetWriter(const std::string& fileName);
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ArrayHandleType>
|
VTKM_CONT void WriteDataSet(const vtkm::cont::DataSet& dataSet, bool just_points = false) const;
|
||||||
void operator()(const ArrayHandleType&) const
|
|
||||||
{
|
|
||||||
using DataType = typename vtkm::VecTraits<typename ArrayHandleType::ValueType>::ComponentType;
|
|
||||||
*this->Name = vtkm::io::internal::DataTypeName<DataType>::Name();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::string* Name;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
struct VTKDataSetWriter
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
static void WritePoints(std::ostream& out, const vtkm::cont::DataSet& dataSet)
|
|
||||||
{
|
|
||||||
///\todo: support other coordinate systems
|
|
||||||
int cindex = 0;
|
|
||||||
auto cdata = dataSet.GetCoordinateSystem(cindex).GetData();
|
|
||||||
|
|
||||||
vtkm::Id npoints = cdata.GetNumberOfValues();
|
|
||||||
out << "POINTS " << npoints << " "
|
|
||||||
<< vtkm::io::internal::DataTypeName<vtkm::FloatDefault>::Name() << " " << '\n';
|
|
||||||
|
|
||||||
detail::OutputPointsFunctor{ out }(cdata);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class CellSetType>
|
|
||||||
static void WriteExplicitCells(std::ostream& out, const CellSetType& cellSet)
|
|
||||||
{
|
|
||||||
vtkm::Id nCells = cellSet.GetNumberOfCells();
|
|
||||||
|
|
||||||
vtkm::Id conn_length = 0;
|
|
||||||
for (vtkm::Id i = 0; i < nCells; ++i)
|
|
||||||
{
|
|
||||||
conn_length += 1 + cellSet.GetNumberOfPointsInCell(i);
|
|
||||||
}
|
|
||||||
|
|
||||||
out << "CELLS " << nCells << " " << conn_length << '\n';
|
|
||||||
|
|
||||||
for (vtkm::Id i = 0; i < nCells; ++i)
|
|
||||||
{
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Id> ids;
|
|
||||||
vtkm::Id nids = cellSet.GetNumberOfPointsInCell(i);
|
|
||||||
cellSet.GetIndices(i, ids);
|
|
||||||
out << nids;
|
|
||||||
auto IdPortal = ids.ReadPortal();
|
|
||||||
for (int j = 0; j < nids; ++j)
|
|
||||||
out << " " << IdPortal.Get(j);
|
|
||||||
out << '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
out << "CELL_TYPES " << nCells << '\n';
|
|
||||||
for (vtkm::Id i = 0; i < nCells; ++i)
|
|
||||||
{
|
|
||||||
vtkm::Id shape = cellSet.GetCellShape(i);
|
|
||||||
out << shape << '\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void WriteVertexCells(std::ostream& out, const vtkm::cont::DataSet& dataSet)
|
|
||||||
{
|
|
||||||
vtkm::Id nCells = dataSet.GetCoordinateSystem(0).GetNumberOfPoints();
|
|
||||||
|
|
||||||
out << "CELLS " << nCells << " " << nCells * 2 << '\n';
|
|
||||||
for (int i = 0; i < nCells; i++)
|
|
||||||
{
|
|
||||||
out << "1 " << i << '\n';
|
|
||||||
}
|
|
||||||
out << "CELL_TYPES " << nCells << '\n';
|
|
||||||
for (int i = 0; i < nCells; i++)
|
|
||||||
{
|
|
||||||
out << vtkm::CELL_SHAPE_VERTEX << '\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void WritePointFields(std::ostream& out, const vtkm::cont::DataSet& dataSet)
|
|
||||||
{
|
|
||||||
bool wrote_header = false;
|
|
||||||
for (vtkm::Id f = 0; f < dataSet.GetNumberOfFields(); f++)
|
|
||||||
{
|
|
||||||
const vtkm::cont::Field field = dataSet.GetField(f);
|
|
||||||
|
|
||||||
if (field.GetAssociation() != vtkm::cont::Field::Association::POINTS)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
vtkm::Id npoints = field.GetNumberOfValues();
|
|
||||||
int ncomps = field.GetData().GetNumberOfComponents();
|
|
||||||
if (ncomps > 4)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!wrote_header)
|
|
||||||
{
|
|
||||||
out << "POINT_DATA " << npoints << '\n';
|
|
||||||
wrote_header = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string typeName;
|
|
||||||
vtkm::cont::CastAndCall(field.GetData().ResetTypes(TypeListAll{}),
|
|
||||||
detail::GetDataTypeName(typeName));
|
|
||||||
std::string name = field.GetName();
|
|
||||||
for (auto& c : name)
|
|
||||||
{
|
|
||||||
if (std::isspace(c))
|
|
||||||
{
|
|
||||||
c = '_';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out << "SCALARS " << name << " " << typeName << " " << ncomps << '\n';
|
|
||||||
out << "LOOKUP_TABLE default" << '\n';
|
|
||||||
|
|
||||||
vtkm::cont::CastAndCall(field.GetData().ResetTypes(TypeListAll{}),
|
|
||||||
detail::OutputFieldFunctor(out));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void WriteCellFields(std::ostream& out, const vtkm::cont::DataSet& dataSet)
|
|
||||||
{
|
|
||||||
bool wrote_header = false;
|
|
||||||
for (vtkm::Id f = 0; f < dataSet.GetNumberOfFields(); f++)
|
|
||||||
{
|
|
||||||
const vtkm::cont::Field field = dataSet.GetField(f);
|
|
||||||
if (!field.IsFieldCell())
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
vtkm::Id ncells = field.GetNumberOfValues();
|
|
||||||
int ncomps = field.GetData().GetNumberOfComponents();
|
|
||||||
if (ncomps > 4)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!wrote_header)
|
|
||||||
{
|
|
||||||
out << "CELL_DATA " << ncells << '\n';
|
|
||||||
wrote_header = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string typeName;
|
|
||||||
vtkm::cont::CastAndCall(field.GetData().ResetTypes(TypeListAll{}),
|
|
||||||
detail::GetDataTypeName(typeName));
|
|
||||||
|
|
||||||
std::string name = field.GetName();
|
|
||||||
for (auto& c : name)
|
|
||||||
{
|
|
||||||
if (std::isspace(c))
|
|
||||||
{
|
|
||||||
c = '_';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out << "SCALARS " << name << " " << typeName << " " << ncomps << '\n';
|
|
||||||
out << "LOOKUP_TABLE default" << '\n';
|
|
||||||
|
|
||||||
vtkm::cont::CastAndCall(field.GetData().ResetTypes(TypeListAll{}),
|
|
||||||
detail::OutputFieldFunctor(out));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void WriteDataSetAsPoints(std::ostream& out, const vtkm::cont::DataSet& dataSet)
|
|
||||||
{
|
|
||||||
out << "DATASET UNSTRUCTURED_GRID" << '\n';
|
|
||||||
WritePoints(out, dataSet);
|
|
||||||
WriteVertexCells(out, dataSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <class CellSetType>
|
|
||||||
static void WriteDataSetAsUnstructured(std::ostream& out,
|
|
||||||
const vtkm::cont::DataSet& dataSet,
|
|
||||||
const CellSetType& cellSet)
|
|
||||||
{
|
|
||||||
out << "DATASET UNSTRUCTURED_GRID" << '\n';
|
|
||||||
WritePoints(out, dataSet);
|
|
||||||
WriteExplicitCells(out, cellSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <vtkm::IdComponent DIM>
|
|
||||||
static void WriteDataSetAsStructured(std::ostream& out,
|
|
||||||
const vtkm::cont::DataSet& dataSet,
|
|
||||||
const vtkm::cont::CellSetStructured<DIM>& cellSet)
|
|
||||||
{
|
|
||||||
///\todo: support uniform/rectilinear
|
|
||||||
out << "DATASET STRUCTURED_GRID" << '\n';
|
|
||||||
|
|
||||||
auto pointDimensions = cellSet.GetPointDimensions();
|
|
||||||
using VTraits = vtkm::VecTraits<decltype(pointDimensions)>;
|
|
||||||
|
|
||||||
out << "DIMENSIONS ";
|
|
||||||
out << VTraits::GetComponent(pointDimensions, 0) << " ";
|
|
||||||
out << (DIM > 1 ? VTraits::GetComponent(pointDimensions, 1) : 1) << " ";
|
|
||||||
out << (DIM > 2 ? VTraits::GetComponent(pointDimensions, 2) : 1) << " ";
|
|
||||||
|
|
||||||
WritePoints(out, dataSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void Write(std::ostream& out, const vtkm::cont::DataSet& dataSet, bool just_points = false)
|
|
||||||
{
|
|
||||||
// The Paraview parser cannot handle scientific notation:
|
|
||||||
out << std::fixed;
|
|
||||||
out << "# vtk DataFile Version 3.0" << '\n';
|
|
||||||
out << "vtk output" << '\n';
|
|
||||||
out << "ASCII" << '\n';
|
|
||||||
|
|
||||||
if (just_points)
|
|
||||||
{
|
|
||||||
WriteDataSetAsPoints(out, dataSet);
|
|
||||||
WritePointFields(out, dataSet);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
vtkm::cont::DynamicCellSet cellSet = dataSet.GetCellSet();
|
|
||||||
if (cellSet.IsType<vtkm::cont::CellSetExplicit<>>())
|
|
||||||
{
|
|
||||||
WriteDataSetAsUnstructured(out, dataSet, cellSet.Cast<vtkm::cont::CellSetExplicit<>>());
|
|
||||||
}
|
|
||||||
else if (cellSet.IsType<vtkm::cont::CellSetStructured<1>>())
|
|
||||||
{
|
|
||||||
WriteDataSetAsStructured(out, dataSet, cellSet.Cast<vtkm::cont::CellSetStructured<1>>());
|
|
||||||
}
|
|
||||||
else if (cellSet.IsType<vtkm::cont::CellSetStructured<2>>())
|
|
||||||
{
|
|
||||||
WriteDataSetAsStructured(out, dataSet, cellSet.Cast<vtkm::cont::CellSetStructured<2>>());
|
|
||||||
}
|
|
||||||
else if (cellSet.IsType<vtkm::cont::CellSetStructured<3>>())
|
|
||||||
{
|
|
||||||
WriteDataSetAsStructured(out, dataSet, cellSet.Cast<vtkm::cont::CellSetStructured<3>>());
|
|
||||||
}
|
|
||||||
else if (cellSet.IsType<vtkm::cont::CellSetSingleType<>>())
|
|
||||||
{
|
|
||||||
// these function just like explicit cell sets
|
|
||||||
WriteDataSetAsUnstructured(out, dataSet, cellSet.Cast<vtkm::cont::CellSetSingleType<>>());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
throw vtkm::cont::ErrorBadType("Could not determine type to write out.");
|
|
||||||
}
|
|
||||||
|
|
||||||
WritePointFields(out, dataSet);
|
|
||||||
WriteCellFields(out, dataSet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
VTKM_CONT
|
|
||||||
explicit VTKDataSetWriter(const std::string& filename)
|
|
||||||
: FileName(filename)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
VTKM_CONT
|
|
||||||
void WriteDataSet(const vtkm::cont::DataSet& dataSet, bool just_points = false) const
|
|
||||||
{
|
|
||||||
if (dataSet.GetNumberOfCoordinateSystems() < 1)
|
|
||||||
{
|
|
||||||
throw vtkm::cont::ErrorBadValue(
|
|
||||||
"DataSet has no coordinate system, which is not supported by VTK file format.");
|
|
||||||
}
|
|
||||||
try
|
|
||||||
{
|
|
||||||
std::ofstream fileStream(this->FileName.c_str(), std::fstream::trunc);
|
|
||||||
this->Write(fileStream, dataSet, just_points);
|
|
||||||
fileStream.close();
|
|
||||||
}
|
|
||||||
catch (std::ofstream::failure& error)
|
|
||||||
{
|
|
||||||
throw vtkm::io::ErrorIO(error.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string FileName;
|
std::string FileName;
|
||||||
|
152
vtkm/io/VTKPolyDataReader.cxx
Normal file
152
vtkm/io/VTKPolyDataReader.cxx
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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/VTKPolyDataReader.h>
|
||||||
|
|
||||||
|
namespace
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline vtkm::cont::ArrayHandle<T> ConcatinateArrayHandles(
|
||||||
|
const std::vector<vtkm::cont::ArrayHandle<T>>& arrays)
|
||||||
|
{
|
||||||
|
vtkm::Id size = 0;
|
||||||
|
for (std::size_t i = 0; i < arrays.size(); ++i)
|
||||||
|
{
|
||||||
|
size += arrays[i].GetNumberOfValues();
|
||||||
|
}
|
||||||
|
|
||||||
|
vtkm::cont::ArrayHandle<T> out;
|
||||||
|
out.Allocate(size);
|
||||||
|
|
||||||
|
auto outp = vtkm::cont::ArrayPortalToIteratorBegin(out.WritePortal());
|
||||||
|
for (std::size_t i = 0; i < arrays.size(); ++i)
|
||||||
|
{
|
||||||
|
std::copy(vtkm::cont::ArrayPortalToIteratorBegin(arrays[i].ReadPortal()),
|
||||||
|
vtkm::cont::ArrayPortalToIteratorEnd(arrays[i].ReadPortal()),
|
||||||
|
outp);
|
||||||
|
using DifferenceType = typename std::iterator_traits<decltype(outp)>::difference_type;
|
||||||
|
std::advance(outp, static_cast<DifferenceType>(arrays[i].GetNumberOfValues()));
|
||||||
|
}
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace io
|
||||||
|
{
|
||||||
|
|
||||||
|
VTKPolyDataReader::VTKPolyDataReader(const char* fileName)
|
||||||
|
: VTKDataSetReaderBase(fileName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKPolyDataReader::VTKPolyDataReader(const std::string& fileName)
|
||||||
|
: VTKDataSetReaderBase(fileName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void VTKPolyDataReader::Read()
|
||||||
|
{
|
||||||
|
if (this->DataFile->Structure != vtkm::io::internal::DATASET_POLYDATA)
|
||||||
|
{
|
||||||
|
throw vtkm::io::ErrorIO("Incorrect DataSet type");
|
||||||
|
}
|
||||||
|
|
||||||
|
//We need to be able to handle VisIt files which dump Field data
|
||||||
|
//at the top of a VTK file
|
||||||
|
std::string tag;
|
||||||
|
this->DataFile->Stream >> tag;
|
||||||
|
if (tag == "FIELD")
|
||||||
|
{
|
||||||
|
this->ReadGlobalFields();
|
||||||
|
this->DataFile->Stream >> tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the points
|
||||||
|
internal::parseAssert(tag == "POINTS");
|
||||||
|
this->ReadPoints();
|
||||||
|
|
||||||
|
vtkm::Id numPoints = this->DataSet.GetNumberOfPoints();
|
||||||
|
|
||||||
|
// Read the cellset
|
||||||
|
std::vector<vtkm::cont::ArrayHandle<vtkm::Id>> connectivityArrays;
|
||||||
|
std::vector<vtkm::cont::ArrayHandle<vtkm::IdComponent>> numIndicesArrays;
|
||||||
|
std::vector<vtkm::UInt8> shapesBuffer;
|
||||||
|
while (!this->DataFile->Stream.eof())
|
||||||
|
{
|
||||||
|
vtkm::UInt8 shape = vtkm::CELL_SHAPE_EMPTY;
|
||||||
|
this->DataFile->Stream >> tag;
|
||||||
|
if (tag == "VERTICES")
|
||||||
|
{
|
||||||
|
shape = vtkm::io::internal::CELL_SHAPE_POLY_VERTEX;
|
||||||
|
}
|
||||||
|
else if (tag == "LINES")
|
||||||
|
{
|
||||||
|
shape = vtkm::io::internal::CELL_SHAPE_POLY_LINE;
|
||||||
|
}
|
||||||
|
else if (tag == "POLYGONS")
|
||||||
|
{
|
||||||
|
shape = vtkm::CELL_SHAPE_POLYGON;
|
||||||
|
}
|
||||||
|
else if (tag == "TRIANGLE_STRIPS")
|
||||||
|
{
|
||||||
|
shape = vtkm::io::internal::CELL_SHAPE_TRIANGLE_STRIP;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this->DataFile->Stream.seekg(-static_cast<std::streamoff>(tag.length()), std::ios_base::cur);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::Id> cellConnectivity;
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::IdComponent> cellNumIndices;
|
||||||
|
this->ReadCells(cellConnectivity, cellNumIndices);
|
||||||
|
|
||||||
|
connectivityArrays.push_back(cellConnectivity);
|
||||||
|
numIndicesArrays.push_back(cellNumIndices);
|
||||||
|
shapesBuffer.insert(
|
||||||
|
shapesBuffer.end(), static_cast<std::size_t>(cellNumIndices.GetNumberOfValues()), shape);
|
||||||
|
}
|
||||||
|
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::Id> connectivity = ConcatinateArrayHandles(connectivityArrays);
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::IdComponent> numIndices = ConcatinateArrayHandles(numIndicesArrays);
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::UInt8> shapes;
|
||||||
|
shapes.Allocate(static_cast<vtkm::Id>(shapesBuffer.size()));
|
||||||
|
std::copy(shapesBuffer.begin(),
|
||||||
|
shapesBuffer.end(),
|
||||||
|
vtkm::cont::ArrayPortalToIteratorBegin(shapes.WritePortal()));
|
||||||
|
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::Id> permutation;
|
||||||
|
vtkm::io::internal::FixupCellSet(connectivity, numIndices, shapes, permutation);
|
||||||
|
this->SetCellsPermutation(permutation);
|
||||||
|
|
||||||
|
if (vtkm::io::internal::IsSingleShape(shapes))
|
||||||
|
{
|
||||||
|
vtkm::cont::CellSetSingleType<> cellSet;
|
||||||
|
cellSet.Fill(
|
||||||
|
numPoints, shapes.ReadPortal().Get(0), numIndices.ReadPortal().Get(0), connectivity);
|
||||||
|
this->DataSet.SetCellSet(cellSet);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto offsets = vtkm::cont::ConvertNumIndicesToOffsets(numIndices);
|
||||||
|
vtkm::cont::CellSetExplicit<> cellSet;
|
||||||
|
cellSet.Fill(numPoints, shapes, connectivity, offsets);
|
||||||
|
this->DataSet.SetCellSet(cellSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read points and cell attributes
|
||||||
|
this->ReadAttributes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace vtkm::io
|
@ -11,6 +11,7 @@
|
|||||||
#define vtk_m_io_VTKPolyDataReader_h
|
#define vtk_m_io_VTKPolyDataReader_h
|
||||||
|
|
||||||
#include <vtkm/io/VTKDataSetReaderBase.h>
|
#include <vtkm/io/VTKDataSetReaderBase.h>
|
||||||
|
#include <vtkm/io/internal/VTKDataSetCells.h>
|
||||||
|
|
||||||
#include <vtkm/cont/ArrayPortalToIterators.h>
|
#include <vtkm/cont/ArrayPortalToIterators.h>
|
||||||
|
|
||||||
@ -21,147 +22,15 @@ namespace vtkm
|
|||||||
namespace io
|
namespace io
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace internal
|
class VTKM_IO_EXPORT VTKPolyDataReader : public VTKDataSetReaderBase
|
||||||
{
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
inline vtkm::cont::ArrayHandle<T> ConcatinateArrayHandles(
|
|
||||||
const std::vector<vtkm::cont::ArrayHandle<T>>& arrays)
|
|
||||||
{
|
|
||||||
vtkm::Id size = 0;
|
|
||||||
for (std::size_t i = 0; i < arrays.size(); ++i)
|
|
||||||
{
|
|
||||||
size += arrays[i].GetNumberOfValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<T> out;
|
|
||||||
out.Allocate(size);
|
|
||||||
|
|
||||||
auto outp = vtkm::cont::ArrayPortalToIteratorBegin(out.WritePortal());
|
|
||||||
for (std::size_t i = 0; i < arrays.size(); ++i)
|
|
||||||
{
|
|
||||||
std::copy(vtkm::cont::ArrayPortalToIteratorBegin(arrays[i].ReadPortal()),
|
|
||||||
vtkm::cont::ArrayPortalToIteratorEnd(arrays[i].ReadPortal()),
|
|
||||||
outp);
|
|
||||||
using DifferenceType = typename std::iterator_traits<decltype(outp)>::difference_type;
|
|
||||||
std::advance(outp, static_cast<DifferenceType>(arrays[i].GetNumberOfValues()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace internal
|
|
||||||
|
|
||||||
VTKM_SILENCE_WEAK_VTABLE_WARNING_START
|
|
||||||
|
|
||||||
class VTKPolyDataReader : public VTKDataSetReaderBase
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit VTKPolyDataReader(const char* fileName)
|
explicit VTKM_CONT VTKPolyDataReader(const char* fileName);
|
||||||
: VTKDataSetReaderBase(fileName)
|
explicit VTKM_CONT VTKPolyDataReader(const std::string& fileName);
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void Read()
|
void Read() override;
|
||||||
{
|
|
||||||
if (this->DataFile->Structure != vtkm::io::internal::DATASET_POLYDATA)
|
|
||||||
{
|
|
||||||
throw vtkm::io::ErrorIO("Incorrect DataSet type");
|
|
||||||
}
|
|
||||||
|
|
||||||
//We need to be able to handle VisIt files which dump Field data
|
|
||||||
//at the top of a VTK file
|
|
||||||
std::string tag;
|
|
||||||
this->DataFile->Stream >> tag;
|
|
||||||
if (tag == "FIELD")
|
|
||||||
{
|
|
||||||
this->ReadGlobalFields();
|
|
||||||
this->DataFile->Stream >> tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the points
|
|
||||||
internal::parseAssert(tag == "POINTS");
|
|
||||||
this->ReadPoints();
|
|
||||||
|
|
||||||
vtkm::Id numPoints = this->DataSet.GetNumberOfPoints();
|
|
||||||
|
|
||||||
// Read the cellset
|
|
||||||
std::vector<vtkm::cont::ArrayHandle<vtkm::Id>> connectivityArrays;
|
|
||||||
std::vector<vtkm::cont::ArrayHandle<vtkm::IdComponent>> numIndicesArrays;
|
|
||||||
std::vector<vtkm::UInt8> shapesBuffer;
|
|
||||||
while (!this->DataFile->Stream.eof())
|
|
||||||
{
|
|
||||||
vtkm::UInt8 shape = vtkm::CELL_SHAPE_EMPTY;
|
|
||||||
this->DataFile->Stream >> tag;
|
|
||||||
if (tag == "VERTICES")
|
|
||||||
{
|
|
||||||
shape = vtkm::io::internal::CELL_SHAPE_POLY_VERTEX;
|
|
||||||
}
|
|
||||||
else if (tag == "LINES")
|
|
||||||
{
|
|
||||||
shape = vtkm::io::internal::CELL_SHAPE_POLY_LINE;
|
|
||||||
}
|
|
||||||
else if (tag == "POLYGONS")
|
|
||||||
{
|
|
||||||
shape = vtkm::CELL_SHAPE_POLYGON;
|
|
||||||
}
|
|
||||||
else if (tag == "TRIANGLE_STRIPS")
|
|
||||||
{
|
|
||||||
shape = vtkm::io::internal::CELL_SHAPE_TRIANGLE_STRIP;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
this->DataFile->Stream.seekg(-static_cast<std::streamoff>(tag.length()),
|
|
||||||
std::ios_base::cur);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Id> cellConnectivity;
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::IdComponent> cellNumIndices;
|
|
||||||
this->ReadCells(cellConnectivity, cellNumIndices);
|
|
||||||
|
|
||||||
connectivityArrays.push_back(cellConnectivity);
|
|
||||||
numIndicesArrays.push_back(cellNumIndices);
|
|
||||||
shapesBuffer.insert(
|
|
||||||
shapesBuffer.end(), static_cast<std::size_t>(cellNumIndices.GetNumberOfValues()), shape);
|
|
||||||
}
|
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Id> connectivity =
|
|
||||||
internal::ConcatinateArrayHandles(connectivityArrays);
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::IdComponent> numIndices =
|
|
||||||
internal::ConcatinateArrayHandles(numIndicesArrays);
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::UInt8> shapes;
|
|
||||||
shapes.Allocate(static_cast<vtkm::Id>(shapesBuffer.size()));
|
|
||||||
std::copy(shapesBuffer.begin(),
|
|
||||||
shapesBuffer.end(),
|
|
||||||
vtkm::cont::ArrayPortalToIteratorBegin(shapes.WritePortal()));
|
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Id> permutation;
|
|
||||||
vtkm::io::internal::FixupCellSet(connectivity, numIndices, shapes, permutation);
|
|
||||||
this->SetCellsPermutation(permutation);
|
|
||||||
|
|
||||||
if (vtkm::io::internal::IsSingleShape(shapes))
|
|
||||||
{
|
|
||||||
vtkm::cont::CellSetSingleType<> cellSet;
|
|
||||||
cellSet.Fill(
|
|
||||||
numPoints, shapes.ReadPortal().Get(0), numIndices.ReadPortal().Get(0), connectivity);
|
|
||||||
this->DataSet.SetCellSet(cellSet);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto offsets = vtkm::cont::ConvertNumIndicesToOffsets(numIndices);
|
|
||||||
vtkm::cont::CellSetExplicit<> cellSet;
|
|
||||||
cellSet.Fill(numPoints, shapes, connectivity, offsets);
|
|
||||||
this->DataSet.SetCellSet(cellSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read points and cell attributes
|
|
||||||
this->ReadAttributes();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
VTKM_SILENCE_WEAK_VTABLE_WARNING_END
|
|
||||||
}
|
}
|
||||||
} // namespace vtkm::io
|
} // namespace vtkm::io
|
||||||
|
|
||||||
|
95
vtkm/io/VTKRectilinearGridReader.cxx
Normal file
95
vtkm/io/VTKRectilinearGridReader.cxx
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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/VTKRectilinearGridReader.h>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace io
|
||||||
|
{
|
||||||
|
|
||||||
|
VTKRectilinearGridReader::VTKRectilinearGridReader(const char* fileName)
|
||||||
|
: VTKDataSetReaderBase(fileName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKRectilinearGridReader::VTKRectilinearGridReader(const std::string& fileName)
|
||||||
|
: VTKDataSetReaderBase(fileName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void VTKRectilinearGridReader::Read()
|
||||||
|
{
|
||||||
|
if (this->DataFile->Structure != vtkm::io::internal::DATASET_RECTILINEAR_GRID)
|
||||||
|
throw vtkm::io::ErrorIO("Incorrect DataSet type");
|
||||||
|
|
||||||
|
//We need to be able to handle VisIt files which dump Field data
|
||||||
|
//at the top of a VTK file
|
||||||
|
std::string tag;
|
||||||
|
this->DataFile->Stream >> tag;
|
||||||
|
if (tag == "FIELD")
|
||||||
|
{
|
||||||
|
this->ReadGlobalFields();
|
||||||
|
this->DataFile->Stream >> tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read structured grid specific meta-data
|
||||||
|
internal::parseAssert(tag == "DIMENSIONS");
|
||||||
|
vtkm::Id3 dim;
|
||||||
|
this->DataFile->Stream >> dim[0] >> dim[1] >> dim[2] >> std::ws;
|
||||||
|
|
||||||
|
//Read the points.
|
||||||
|
std::string dataType;
|
||||||
|
std::size_t numPoints[3];
|
||||||
|
vtkm::cont::VariantArrayHandle X, Y, Z;
|
||||||
|
|
||||||
|
// Always read coordinates as vtkm::FloatDefault
|
||||||
|
std::string readDataType = vtkm::io::internal::DataTypeName<vtkm::FloatDefault>::Name();
|
||||||
|
|
||||||
|
this->DataFile->Stream >> tag >> numPoints[0] >> dataType >> std::ws;
|
||||||
|
if (tag != "X_COORDINATES")
|
||||||
|
throw vtkm::io::ErrorIO("X_COORDINATES tag not found");
|
||||||
|
X = this->DoReadArrayVariant(vtkm::cont::Field::Association::ANY, readDataType, numPoints[0], 1);
|
||||||
|
|
||||||
|
this->DataFile->Stream >> tag >> numPoints[1] >> dataType >> std::ws;
|
||||||
|
if (tag != "Y_COORDINATES")
|
||||||
|
throw vtkm::io::ErrorIO("Y_COORDINATES tag not found");
|
||||||
|
Y = this->DoReadArrayVariant(vtkm::cont::Field::Association::ANY, readDataType, numPoints[1], 1);
|
||||||
|
|
||||||
|
this->DataFile->Stream >> tag >> numPoints[2] >> dataType >> std::ws;
|
||||||
|
if (tag != "Z_COORDINATES")
|
||||||
|
throw vtkm::io::ErrorIO("Z_COORDINATES tag not found");
|
||||||
|
Z = this->DoReadArrayVariant(vtkm::cont::Field::Association::ANY, readDataType, numPoints[2], 1);
|
||||||
|
|
||||||
|
if (dim != vtkm::Id3(static_cast<vtkm::Id>(numPoints[0]),
|
||||||
|
static_cast<vtkm::Id>(numPoints[1]),
|
||||||
|
static_cast<vtkm::Id>(numPoints[2])))
|
||||||
|
throw vtkm::io::ErrorIO("DIMENSIONS not equal to number of points");
|
||||||
|
|
||||||
|
vtkm::cont::ArrayHandleCartesianProduct<vtkm::cont::ArrayHandle<vtkm::FloatDefault>,
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::FloatDefault>,
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::FloatDefault>>
|
||||||
|
coords;
|
||||||
|
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::FloatDefault> Xc, Yc, Zc;
|
||||||
|
X.CopyTo(Xc);
|
||||||
|
Y.CopyTo(Yc);
|
||||||
|
Z.CopyTo(Zc);
|
||||||
|
coords = vtkm::cont::make_ArrayHandleCartesianProduct(Xc, Yc, Zc);
|
||||||
|
vtkm::cont::CoordinateSystem coordSys("coordinates", coords);
|
||||||
|
this->DataSet.AddCoordinateSystem(coordSys);
|
||||||
|
|
||||||
|
this->DataSet.SetCellSet(internal::CreateCellSetStructured(dim));
|
||||||
|
|
||||||
|
// Read points and cell attributes
|
||||||
|
this->ReadAttributes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace vtkm::io
|
@ -17,89 +17,15 @@ namespace vtkm
|
|||||||
namespace io
|
namespace io
|
||||||
{
|
{
|
||||||
|
|
||||||
VTKM_SILENCE_WEAK_VTABLE_WARNING_START
|
class VTKM_IO_EXPORT VTKRectilinearGridReader : public VTKDataSetReaderBase
|
||||||
|
|
||||||
class VTKRectilinearGridReader : public VTKDataSetReaderBase
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit VTKRectilinearGridReader(const char* fileName)
|
explicit VTKM_CONT VTKRectilinearGridReader(const char* fileName);
|
||||||
: VTKDataSetReaderBase(fileName)
|
explicit VTKM_CONT VTKRectilinearGridReader(const std::string& fileName);
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void Read()
|
VTKM_CONT void Read() override;
|
||||||
{
|
|
||||||
if (this->DataFile->Structure != vtkm::io::internal::DATASET_RECTILINEAR_GRID)
|
|
||||||
throw vtkm::io::ErrorIO("Incorrect DataSet type");
|
|
||||||
|
|
||||||
//We need to be able to handle VisIt files which dump Field data
|
|
||||||
//at the top of a VTK file
|
|
||||||
std::string tag;
|
|
||||||
this->DataFile->Stream >> tag;
|
|
||||||
if (tag == "FIELD")
|
|
||||||
{
|
|
||||||
this->ReadGlobalFields();
|
|
||||||
this->DataFile->Stream >> tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read structured grid specific meta-data
|
|
||||||
internal::parseAssert(tag == "DIMENSIONS");
|
|
||||||
vtkm::Id3 dim;
|
|
||||||
this->DataFile->Stream >> dim[0] >> dim[1] >> dim[2] >> std::ws;
|
|
||||||
|
|
||||||
//Read the points.
|
|
||||||
std::string dataType;
|
|
||||||
std::size_t numPoints[3];
|
|
||||||
vtkm::cont::VariantArrayHandle X, Y, Z;
|
|
||||||
|
|
||||||
// Always read coordinates as vtkm::FloatDefault
|
|
||||||
std::string readDataType = vtkm::io::internal::DataTypeName<vtkm::FloatDefault>::Name();
|
|
||||||
|
|
||||||
this->DataFile->Stream >> tag >> numPoints[0] >> dataType >> std::ws;
|
|
||||||
if (tag != "X_COORDINATES")
|
|
||||||
throw vtkm::io::ErrorIO("X_COORDINATES tag not found");
|
|
||||||
X =
|
|
||||||
this->DoReadArrayVariant(vtkm::cont::Field::Association::ANY, readDataType, numPoints[0], 1);
|
|
||||||
|
|
||||||
this->DataFile->Stream >> tag >> numPoints[1] >> dataType >> std::ws;
|
|
||||||
if (tag != "Y_COORDINATES")
|
|
||||||
throw vtkm::io::ErrorIO("Y_COORDINATES tag not found");
|
|
||||||
Y =
|
|
||||||
this->DoReadArrayVariant(vtkm::cont::Field::Association::ANY, readDataType, numPoints[1], 1);
|
|
||||||
|
|
||||||
this->DataFile->Stream >> tag >> numPoints[2] >> dataType >> std::ws;
|
|
||||||
if (tag != "Z_COORDINATES")
|
|
||||||
throw vtkm::io::ErrorIO("Z_COORDINATES tag not found");
|
|
||||||
Z =
|
|
||||||
this->DoReadArrayVariant(vtkm::cont::Field::Association::ANY, readDataType, numPoints[2], 1);
|
|
||||||
|
|
||||||
if (dim != vtkm::Id3(static_cast<vtkm::Id>(numPoints[0]),
|
|
||||||
static_cast<vtkm::Id>(numPoints[1]),
|
|
||||||
static_cast<vtkm::Id>(numPoints[2])))
|
|
||||||
throw vtkm::io::ErrorIO("DIMENSIONS not equal to number of points");
|
|
||||||
|
|
||||||
vtkm::cont::ArrayHandleCartesianProduct<vtkm::cont::ArrayHandle<vtkm::FloatDefault>,
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault>,
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault>>
|
|
||||||
coords;
|
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::FloatDefault> Xc, Yc, Zc;
|
|
||||||
X.CopyTo(Xc);
|
|
||||||
Y.CopyTo(Yc);
|
|
||||||
Z.CopyTo(Zc);
|
|
||||||
coords = vtkm::cont::make_ArrayHandleCartesianProduct(Xc, Yc, Zc);
|
|
||||||
vtkm::cont::CoordinateSystem coordSys("coordinates", coords);
|
|
||||||
this->DataSet.AddCoordinateSystem(coordSys);
|
|
||||||
|
|
||||||
this->DataSet.SetCellSet(internal::CreateCellSetStructured(dim));
|
|
||||||
|
|
||||||
// Read points and cell attributes
|
|
||||||
this->ReadAttributes();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
VTKM_SILENCE_WEAK_VTABLE_WARNING_END
|
|
||||||
}
|
}
|
||||||
} // namespace vtkm::io
|
} // namespace vtkm::io
|
||||||
|
|
||||||
|
62
vtkm/io/VTKStructuredGridReader.cxx
Normal file
62
vtkm/io/VTKStructuredGridReader.cxx
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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/VTKStructuredGridReader.h>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace io
|
||||||
|
{
|
||||||
|
|
||||||
|
VTKStructuredGridReader::VTKStructuredGridReader(const char* fileName)
|
||||||
|
: VTKDataSetReaderBase(fileName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKStructuredGridReader::VTKStructuredGridReader(const std::string& fileName)
|
||||||
|
: VTKDataSetReaderBase(fileName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void VTKStructuredGridReader::Read()
|
||||||
|
{
|
||||||
|
if (this->DataFile->Structure != vtkm::io::internal::DATASET_STRUCTURED_GRID)
|
||||||
|
{
|
||||||
|
throw vtkm::io::ErrorIO("Incorrect DataSet type");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string tag;
|
||||||
|
|
||||||
|
//We need to be able to handle VisIt files which dump Field data
|
||||||
|
//at the top of a VTK file
|
||||||
|
this->DataFile->Stream >> tag;
|
||||||
|
if (tag == "FIELD")
|
||||||
|
{
|
||||||
|
this->ReadGlobalFields();
|
||||||
|
this->DataFile->Stream >> tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read structured grid specific meta-data
|
||||||
|
internal::parseAssert(tag == "DIMENSIONS");
|
||||||
|
vtkm::Id3 dim;
|
||||||
|
this->DataFile->Stream >> dim[0] >> dim[1] >> dim[2] >> std::ws;
|
||||||
|
|
||||||
|
this->DataSet.SetCellSet(internal::CreateCellSetStructured(dim));
|
||||||
|
|
||||||
|
// Read the points
|
||||||
|
this->DataFile->Stream >> tag;
|
||||||
|
internal::parseAssert(tag == "POINTS");
|
||||||
|
this->ReadPoints();
|
||||||
|
|
||||||
|
// Read points and cell attributes
|
||||||
|
this->ReadAttributes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace vtkm::io
|
@ -17,53 +17,15 @@ namespace vtkm
|
|||||||
namespace io
|
namespace io
|
||||||
{
|
{
|
||||||
|
|
||||||
VTKM_SILENCE_WEAK_VTABLE_WARNING_START
|
class VTKM_IO_EXPORT VTKStructuredGridReader : public VTKDataSetReaderBase
|
||||||
|
|
||||||
class VTKStructuredGridReader : public VTKDataSetReaderBase
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit VTKStructuredGridReader(const char* fileName)
|
explicit VTKM_CONT VTKStructuredGridReader(const char* fileName);
|
||||||
: VTKDataSetReaderBase(fileName)
|
explicit VTKM_CONT VTKStructuredGridReader(const std::string& fileName);
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void Read()
|
VTKM_CONT void Read() override;
|
||||||
{
|
|
||||||
if (this->DataFile->Structure != vtkm::io::internal::DATASET_STRUCTURED_GRID)
|
|
||||||
{
|
|
||||||
throw vtkm::io::ErrorIO("Incorrect DataSet type");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string tag;
|
|
||||||
|
|
||||||
//We need to be able to handle VisIt files which dump Field data
|
|
||||||
//at the top of a VTK file
|
|
||||||
this->DataFile->Stream >> tag;
|
|
||||||
if (tag == "FIELD")
|
|
||||||
{
|
|
||||||
this->ReadGlobalFields();
|
|
||||||
this->DataFile->Stream >> tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read structured grid specific meta-data
|
|
||||||
internal::parseAssert(tag == "DIMENSIONS");
|
|
||||||
vtkm::Id3 dim;
|
|
||||||
this->DataFile->Stream >> dim[0] >> dim[1] >> dim[2] >> std::ws;
|
|
||||||
|
|
||||||
this->DataSet.SetCellSet(internal::CreateCellSetStructured(dim));
|
|
||||||
|
|
||||||
// Read the points
|
|
||||||
this->DataFile->Stream >> tag;
|
|
||||||
internal::parseAssert(tag == "POINTS");
|
|
||||||
this->ReadPoints();
|
|
||||||
|
|
||||||
// Read points and cell attributes
|
|
||||||
this->ReadAttributes();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
VTKM_SILENCE_WEAK_VTABLE_WARNING_END
|
|
||||||
}
|
}
|
||||||
} // namespace vtkm::io
|
} // namespace vtkm::io
|
||||||
|
|
||||||
|
79
vtkm/io/VTKStructuredPointsReader.cxx
Normal file
79
vtkm/io/VTKStructuredPointsReader.cxx
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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/VTKStructuredPointsReader.h>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace io
|
||||||
|
{
|
||||||
|
|
||||||
|
VTKStructuredPointsReader::VTKStructuredPointsReader(const char* fileName)
|
||||||
|
: VTKDataSetReaderBase(fileName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKStructuredPointsReader::VTKStructuredPointsReader(const std::string& fileName)
|
||||||
|
: VTKDataSetReaderBase(fileName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void VTKStructuredPointsReader::Read()
|
||||||
|
{
|
||||||
|
if (this->DataFile->Structure != vtkm::io::internal::DATASET_STRUCTURED_POINTS)
|
||||||
|
{
|
||||||
|
throw vtkm::io::ErrorIO("Incorrect DataSet type");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string tag;
|
||||||
|
|
||||||
|
// Read structured points specific meta-data
|
||||||
|
vtkm::Id3 dim;
|
||||||
|
vtkm::Vec3f_32 origin, spacing;
|
||||||
|
|
||||||
|
//Two ways the file can describe the dimensions. The proper way is by
|
||||||
|
//using the DIMENSIONS keyword, but VisIt written VTK files spicify data
|
||||||
|
//bounds instead, as a FIELD
|
||||||
|
std::vector<vtkm::Float32> visitBounds;
|
||||||
|
this->DataFile->Stream >> tag;
|
||||||
|
if (tag == "FIELD")
|
||||||
|
{
|
||||||
|
this->ReadGlobalFields(&visitBounds);
|
||||||
|
this->DataFile->Stream >> tag;
|
||||||
|
}
|
||||||
|
if (visitBounds.empty())
|
||||||
|
{
|
||||||
|
internal::parseAssert(tag == "DIMENSIONS");
|
||||||
|
this->DataFile->Stream >> dim[0] >> dim[1] >> dim[2] >> std::ws;
|
||||||
|
this->DataFile->Stream >> tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal::parseAssert(tag == "SPACING");
|
||||||
|
this->DataFile->Stream >> spacing[0] >> spacing[1] >> spacing[2] >> std::ws;
|
||||||
|
if (!visitBounds.empty())
|
||||||
|
{
|
||||||
|
//now with spacing and physical bounds we can back compute the dimensions
|
||||||
|
dim[0] = static_cast<vtkm::Id>((visitBounds[1] - visitBounds[0]) / spacing[0]);
|
||||||
|
dim[1] = static_cast<vtkm::Id>((visitBounds[3] - visitBounds[2]) / spacing[1]);
|
||||||
|
dim[2] = static_cast<vtkm::Id>((visitBounds[5] - visitBounds[4]) / spacing[2]);
|
||||||
|
}
|
||||||
|
|
||||||
|
this->DataFile->Stream >> tag >> origin[0] >> origin[1] >> origin[2] >> std::ws;
|
||||||
|
internal::parseAssert(tag == "ORIGIN");
|
||||||
|
|
||||||
|
this->DataSet.SetCellSet(internal::CreateCellSetStructured(dim));
|
||||||
|
this->DataSet.AddCoordinateSystem(
|
||||||
|
vtkm::cont::CoordinateSystem("coordinates", dim, origin, spacing));
|
||||||
|
|
||||||
|
// Read points and cell attributes
|
||||||
|
this->ReadAttributes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace vtkm::io
|
@ -17,70 +17,15 @@ namespace vtkm
|
|||||||
namespace io
|
namespace io
|
||||||
{
|
{
|
||||||
|
|
||||||
VTKM_SILENCE_WEAK_VTABLE_WARNING_START
|
class VTKM_IO_EXPORT VTKStructuredPointsReader : public VTKDataSetReaderBase
|
||||||
|
|
||||||
class VTKStructuredPointsReader : public VTKDataSetReaderBase
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit VTKStructuredPointsReader(const char* fileName)
|
explicit VTKM_CONT VTKStructuredPointsReader(const char* fileName);
|
||||||
: VTKDataSetReaderBase(fileName)
|
explicit VTKM_CONT VTKStructuredPointsReader(const std::string& fileName);
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void Read()
|
VTKM_CONT void Read() override;
|
||||||
{
|
|
||||||
if (this->DataFile->Structure != vtkm::io::internal::DATASET_STRUCTURED_POINTS)
|
|
||||||
{
|
|
||||||
throw vtkm::io::ErrorIO("Incorrect DataSet type");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string tag;
|
|
||||||
|
|
||||||
// Read structured points specific meta-data
|
|
||||||
vtkm::Id3 dim;
|
|
||||||
vtkm::Vec3f_32 origin, spacing;
|
|
||||||
|
|
||||||
//Two ways the file can describe the dimensions. The proper way is by
|
|
||||||
//using the DIMENSIONS keyword, but VisIt written VTK files spicify data
|
|
||||||
//bounds instead, as a FIELD
|
|
||||||
std::vector<vtkm::Float32> visitBounds;
|
|
||||||
this->DataFile->Stream >> tag;
|
|
||||||
if (tag == "FIELD")
|
|
||||||
{
|
|
||||||
this->ReadGlobalFields(&visitBounds);
|
|
||||||
this->DataFile->Stream >> tag;
|
|
||||||
}
|
|
||||||
if (visitBounds.empty())
|
|
||||||
{
|
|
||||||
internal::parseAssert(tag == "DIMENSIONS");
|
|
||||||
this->DataFile->Stream >> dim[0] >> dim[1] >> dim[2] >> std::ws;
|
|
||||||
this->DataFile->Stream >> tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal::parseAssert(tag == "SPACING");
|
|
||||||
this->DataFile->Stream >> spacing[0] >> spacing[1] >> spacing[2] >> std::ws;
|
|
||||||
if (!visitBounds.empty())
|
|
||||||
{
|
|
||||||
//now with spacing and physical bounds we can back compute the dimensions
|
|
||||||
dim[0] = static_cast<vtkm::Id>((visitBounds[1] - visitBounds[0]) / spacing[0]);
|
|
||||||
dim[1] = static_cast<vtkm::Id>((visitBounds[3] - visitBounds[2]) / spacing[1]);
|
|
||||||
dim[2] = static_cast<vtkm::Id>((visitBounds[5] - visitBounds[4]) / spacing[2]);
|
|
||||||
}
|
|
||||||
|
|
||||||
this->DataFile->Stream >> tag >> origin[0] >> origin[1] >> origin[2] >> std::ws;
|
|
||||||
internal::parseAssert(tag == "ORIGIN");
|
|
||||||
|
|
||||||
this->DataSet.SetCellSet(internal::CreateCellSetStructured(dim));
|
|
||||||
this->DataSet.AddCoordinateSystem(
|
|
||||||
vtkm::cont::CoordinateSystem("coordinates", dim, origin, spacing));
|
|
||||||
|
|
||||||
// Read points and cell attributes
|
|
||||||
this->ReadAttributes();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
VTKM_SILENCE_WEAK_VTABLE_WARNING_END
|
|
||||||
}
|
}
|
||||||
} // namespace vtkm::io
|
} // namespace vtkm::io
|
||||||
|
|
||||||
|
88
vtkm/io/VTKUnstructuredGridReader.cxx
Normal file
88
vtkm/io/VTKUnstructuredGridReader.cxx
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
//============================================================================
|
||||||
|
// 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/VTKUnstructuredGridReader.h>
|
||||||
|
|
||||||
|
#include <vtkm/io/internal/VTKDataSetCells.h>
|
||||||
|
|
||||||
|
namespace vtkm
|
||||||
|
{
|
||||||
|
namespace io
|
||||||
|
{
|
||||||
|
|
||||||
|
VTKUnstructuredGridReader::VTKUnstructuredGridReader(const char* fileName)
|
||||||
|
: VTKDataSetReaderBase(fileName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
VTKUnstructuredGridReader::VTKUnstructuredGridReader(const std::string& fileName)
|
||||||
|
: VTKDataSetReaderBase(fileName)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void VTKUnstructuredGridReader::Read()
|
||||||
|
{
|
||||||
|
if (this->DataFile->Structure != vtkm::io::internal::DATASET_UNSTRUCTURED_GRID)
|
||||||
|
{
|
||||||
|
throw vtkm::io::ErrorIO("Incorrect DataSet type");
|
||||||
|
}
|
||||||
|
|
||||||
|
//We need to be able to handle VisIt files which dump Field data
|
||||||
|
//at the top of a VTK file
|
||||||
|
std::string tag;
|
||||||
|
this->DataFile->Stream >> tag;
|
||||||
|
if (tag == "FIELD")
|
||||||
|
{
|
||||||
|
this->ReadGlobalFields();
|
||||||
|
this->DataFile->Stream >> tag;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read the points
|
||||||
|
internal::parseAssert(tag == "POINTS");
|
||||||
|
this->ReadPoints();
|
||||||
|
|
||||||
|
vtkm::Id numPoints = this->DataSet.GetNumberOfPoints();
|
||||||
|
|
||||||
|
// Read the cellset
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::IdComponent> numIndices;
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::UInt8> shapes;
|
||||||
|
|
||||||
|
this->DataFile->Stream >> tag;
|
||||||
|
internal::parseAssert(tag == "CELLS");
|
||||||
|
|
||||||
|
this->ReadCells(connectivity, numIndices);
|
||||||
|
this->ReadShapes(shapes);
|
||||||
|
|
||||||
|
vtkm::cont::ArrayHandle<vtkm::Id> permutation;
|
||||||
|
vtkm::io::internal::FixupCellSet(connectivity, numIndices, shapes, permutation);
|
||||||
|
this->SetCellsPermutation(permutation);
|
||||||
|
|
||||||
|
//DRP
|
||||||
|
if (false) //vtkm::io::internal::IsSingleShape(shapes))
|
||||||
|
{
|
||||||
|
vtkm::cont::CellSetSingleType<> cellSet;
|
||||||
|
cellSet.Fill(
|
||||||
|
numPoints, shapes.ReadPortal().Get(0), numIndices.ReadPortal().Get(0), connectivity);
|
||||||
|
this->DataSet.SetCellSet(cellSet);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
auto offsets = vtkm::cont::ConvertNumIndicesToOffsets(numIndices);
|
||||||
|
vtkm::cont::CellSetExplicit<> cellSet;
|
||||||
|
cellSet.Fill(numPoints, shapes, connectivity, offsets);
|
||||||
|
this->DataSet.SetCellSet(cellSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read points and cell attributes
|
||||||
|
this->ReadAttributes();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -17,77 +17,15 @@ namespace vtkm
|
|||||||
namespace io
|
namespace io
|
||||||
{
|
{
|
||||||
|
|
||||||
VTKM_SILENCE_WEAK_VTABLE_WARNING_START
|
class VTKM_IO_EXPORT VTKUnstructuredGridReader : public VTKDataSetReaderBase
|
||||||
|
|
||||||
class VTKUnstructuredGridReader : public VTKDataSetReaderBase
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit VTKUnstructuredGridReader(const char* fileName)
|
explicit VTKM_CONT VTKUnstructuredGridReader(const char* fileName);
|
||||||
: VTKDataSetReaderBase(fileName)
|
explicit VTKM_CONT VTKUnstructuredGridReader(const std::string& fileName);
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void Read()
|
VTKM_CONT void Read() override;
|
||||||
{
|
|
||||||
if (this->DataFile->Structure != vtkm::io::internal::DATASET_UNSTRUCTURED_GRID)
|
|
||||||
{
|
|
||||||
throw vtkm::io::ErrorIO("Incorrect DataSet type");
|
|
||||||
}
|
|
||||||
|
|
||||||
//We need to be able to handle VisIt files which dump Field data
|
|
||||||
//at the top of a VTK file
|
|
||||||
std::string tag;
|
|
||||||
this->DataFile->Stream >> tag;
|
|
||||||
if (tag == "FIELD")
|
|
||||||
{
|
|
||||||
this->ReadGlobalFields();
|
|
||||||
this->DataFile->Stream >> tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read the points
|
|
||||||
internal::parseAssert(tag == "POINTS");
|
|
||||||
this->ReadPoints();
|
|
||||||
|
|
||||||
vtkm::Id numPoints = this->DataSet.GetNumberOfPoints();
|
|
||||||
|
|
||||||
// Read the cellset
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Id> connectivity;
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::IdComponent> numIndices;
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::UInt8> shapes;
|
|
||||||
|
|
||||||
this->DataFile->Stream >> tag;
|
|
||||||
internal::parseAssert(tag == "CELLS");
|
|
||||||
|
|
||||||
this->ReadCells(connectivity, numIndices);
|
|
||||||
this->ReadShapes(shapes);
|
|
||||||
|
|
||||||
vtkm::cont::ArrayHandle<vtkm::Id> permutation;
|
|
||||||
vtkm::io::internal::FixupCellSet(connectivity, numIndices, shapes, permutation);
|
|
||||||
this->SetCellsPermutation(permutation);
|
|
||||||
|
|
||||||
//DRP
|
|
||||||
if (false) //vtkm::io::internal::IsSingleShape(shapes))
|
|
||||||
{
|
|
||||||
vtkm::cont::CellSetSingleType<> cellSet;
|
|
||||||
cellSet.Fill(
|
|
||||||
numPoints, shapes.ReadPortal().Get(0), numIndices.ReadPortal().Get(0), connectivity);
|
|
||||||
this->DataSet.SetCellSet(cellSet);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto offsets = vtkm::cont::ConvertNumIndicesToOffsets(numIndices);
|
|
||||||
vtkm::cont::CellSetExplicit<> cellSet;
|
|
||||||
cellSet.Fill(numPoints, shapes, connectivity, offsets);
|
|
||||||
this->DataSet.SetCellSet(cellSet);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Read points and cell attributes
|
|
||||||
this->ReadAttributes();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
VTKM_SILENCE_WEAK_VTABLE_WARNING_END
|
|
||||||
}
|
}
|
||||||
} // namespace vtkm::io
|
} // namespace vtkm::io
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#define vtk_m_io_internal_VTKDataSetTypes_h
|
#define vtk_m_io_internal_VTKDataSetTypes_h
|
||||||
|
|
||||||
#include <vtkm/Types.h>
|
#include <vtkm/Types.h>
|
||||||
|
#include <vtkm/VecTraits.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
@ -238,4 +239,7 @@ inline void SelectTypeAndCall(DataType dtype,
|
|||||||
}
|
}
|
||||||
} // namespace vtkm::io::internal
|
} // namespace vtkm::io::internal
|
||||||
|
|
||||||
|
VTKM_BASIC_TYPE_VECTOR(vtkm::io::internal::ColorChannel8)
|
||||||
|
VTKM_BASIC_TYPE_VECTOR(vtkm::io::internal::DummyBitType)
|
||||||
|
|
||||||
#endif // vtk_m_io_internal_VTKDataSetTypes_h
|
#endif // vtk_m_io_internal_VTKDataSetTypes_h
|
||||||
|
@ -15,14 +15,14 @@ set(unit_tests
|
|||||||
UnitTestVTKDataSetWriter.cxx
|
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)
|
if(VTKm_ENABLE_RENDERING)
|
||||||
return()
|
set(unit_tests ${unit_tests}
|
||||||
endif()
|
|
||||||
|
|
||||||
set(image_unit_tests
|
|
||||||
UnitTestImageWriter.cxx
|
UnitTestImageWriter.cxx
|
||||||
)
|
)
|
||||||
|
|
||||||
vtkm_unit_tests(NAME UnitTests_vtkm_io_image_testing SOURCES ${image_unit_tests} ALL_BACKENDS LIBRARIES vtkm_rendering vtkm_lodepng)
|
set(unit_test_libraries ${unit_test_libraries} vtkm_rendering)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
vtkm_unit_tests(SOURCES ${unit_tests} ALL_BACKENDS LIBRARIES ${unit_test_libraries})
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vtkm/cont/testing/Testing.h>
|
#include <vtkm/cont/testing/Testing.h>
|
||||||
#include <vtkm/io/BOVDataSetReader.h>
|
#include <vtkm/io/BOVDataSetReader.h>
|
||||||
|
#include <vtkm/io/ErrorIO.h>
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user