mirror of
https://gitlab.kitware.com/vtk/vtk-m
synced 2024-09-16 17:22:55 +00:00
Merge branch 'master' into osc_refactor
This commit is contained in:
commit
08ad08b138
@ -312,7 +312,15 @@ endfunction()
|
||||
#
|
||||
# DEVICE_SOURCES: The collection of source files that are used by `target(s)` that
|
||||
# need to be marked as going to a special compiler for certain device adapters
|
||||
# such as CUDA.
|
||||
# such as CUDA. A source file generally needs to be in DEVICE_SOURCES if (and
|
||||
# usually only if) it includes vtkm/cont/DeviceAdapterAlgorithm.h (either directly
|
||||
# or indirectly). The most common code to include DeviceAdapterAlgorithm.h are
|
||||
# those that use vtkm::cont::Algorithm or those that define worklets. Templated
|
||||
# code that does computation often links to device adapter algorithms. Some
|
||||
# device adapters that require a special compiler for device code will check in
|
||||
# their headers that a device compiler is being used when it is needed. Such
|
||||
# errors can be corrected by adding the source code to `DEVICE_SOURCES` (or
|
||||
# removing the dependence on device algorithm when possible).
|
||||
#
|
||||
# EXTENDS_VTKM: Some programming models have restrictions on how types can be used,
|
||||
# passed across library boundaries, and derived from.
|
||||
|
7
docs/changelog/write-binary.md
Normal file
7
docs/changelog/write-binary.md
Normal file
@ -0,0 +1,7 @@
|
||||
# Support writing binary files to legacy VTK files
|
||||
|
||||
The legacy VTK file writer writes out in ASCII. This is helpful when a
|
||||
human is trying to read the file. However, if you have more than a
|
||||
trivial amount of data, the file can get impractically large. To get
|
||||
around this, `VTKDataSetWriter` now has a flag that allows you to write
|
||||
the data in binary format.
|
@ -33,8 +33,27 @@ namespace cont
|
||||
namespace detail
|
||||
{
|
||||
|
||||
#ifdef VTKM_GCC
|
||||
// On rare occasion, we have seen errors like this:
|
||||
// `_ZN4vtkm4cont6detailL27UnknownAHNumberOfComponentsIxEEiv' referenced in section
|
||||
// `.data.rel.ro.local' of CMakeFiles/UnitTests_vtkm_cont_testing.dir/UnitTestCellSet.cxx.o:
|
||||
// defined in discarded section
|
||||
// `.text._ZN4vtkm4cont6detailL27UnknownAHNumberOfComponentsIxEEiv[_ZN4vtkm4cont14ArrayGetValuesINS0_15StorageTagBasicExNS0_18StorageTagCountingES2_EEvRKNS0_11ArrayHandleIxT_EERKNS4_IT0_T1_EERNS4_IS9_T2_EE]'
|
||||
// of CMakeFiles/UnitTests_vtkm_cont_testing.dir/UnitTestCellSet.cxx.o
|
||||
// I don't know what circumstances exactly lead up to this, but it appears that the compiler is
|
||||
// being overly aggressive with removing unused symbols. In this instance, it seems to have removed
|
||||
// a function actually being used. This might be a bug in the compiler (I happen to have seen it in
|
||||
// gcc 8.3, 9.4, and 11.0), or it could be caused by a link-time optimizer. The problem should be
|
||||
// able to be solved by explictly saying that this templated method is being used. (I can't think
|
||||
// of any circumstances where this template would be instantiated but not used.) If the compiler
|
||||
// knows this is being used, it should know all the templated methods internal are also used.
|
||||
#define VTKM_FORCE_USED __attribute__((used))
|
||||
#else
|
||||
#define VTKM_FORCE_USED
|
||||
#endif
|
||||
|
||||
template <typename T, typename S>
|
||||
static void UnknownAHDelete(void* mem)
|
||||
VTKM_FORCE_USED static void UnknownAHDelete(void* mem)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
@ -42,13 +61,13 @@ static void UnknownAHDelete(void* mem)
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
static void* UnknownAHNewInstance()
|
||||
VTKM_FORCE_USED static void* UnknownAHNewInstance()
|
||||
{
|
||||
return new vtkm::cont::ArrayHandle<T, S>;
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
static vtkm::Id UnknownAHNumberOfValues(void* mem)
|
||||
VTKM_FORCE_USED static vtkm::Id UnknownAHNumberOfValues(void* mem)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
@ -69,7 +88,7 @@ struct UnknownAHNumberOfComponentsImpl<T, vtkm::VecTraitsTagSizeVariable>
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
static vtkm::IdComponent UnknownAHNumberOfComponents()
|
||||
VTKM_FORCE_USED static vtkm::IdComponent UnknownAHNumberOfComponents()
|
||||
{
|
||||
return UnknownAHNumberOfComponentsImpl<T>::Value;
|
||||
}
|
||||
@ -88,16 +107,16 @@ struct UnknownAHNumberOfComponentsFlatImpl<T, vtkm::VecTraitsTagSizeVariable>
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
static vtkm::IdComponent UnknownAHNumberOfComponentsFlat()
|
||||
VTKM_FORCE_USED static vtkm::IdComponent UnknownAHNumberOfComponentsFlat()
|
||||
{
|
||||
return UnknownAHNumberOfComponentsFlatImpl<T>::Value;
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
static void UnknownAHAllocate(void* mem,
|
||||
vtkm::Id numValues,
|
||||
vtkm::CopyFlag preserve,
|
||||
vtkm::cont::Token& token)
|
||||
VTKM_FORCE_USED static void UnknownAHAllocate(void* mem,
|
||||
vtkm::Id numValues,
|
||||
vtkm::CopyFlag preserve,
|
||||
vtkm::cont::Token& token)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
@ -105,7 +124,7 @@ static void UnknownAHAllocate(void* mem,
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
static void UnknownAHShallowCopy(const void* sourceMem, void* destinationMem)
|
||||
VTKM_FORCE_USED static void UnknownAHShallowCopy(const void* sourceMem, void* destinationMem)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
const AH* source = reinterpret_cast<const AH*>(sourceMem);
|
||||
@ -114,7 +133,7 @@ static void UnknownAHShallowCopy(const void* sourceMem, void* destinationMem)
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
static std::vector<vtkm::cont::internal::Buffer>
|
||||
VTKM_FORCE_USED static std::vector<vtkm::cont::internal::Buffer>
|
||||
UnknownAHExtractComponent(void* mem, vtkm::IdComponent componentIndex, vtkm::CopyFlag allowCopy)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
@ -125,7 +144,7 @@ UnknownAHExtractComponent(void* mem, vtkm::IdComponent componentIndex, vtkm::Cop
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
static void UnknownAHReleaseResources(void* mem)
|
||||
VTKM_FORCE_USED static void UnknownAHReleaseResources(void* mem)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
@ -133,7 +152,7 @@ static void UnknownAHReleaseResources(void* mem)
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
static void UnknownAHReleaseResourcesExecution(void* mem)
|
||||
VTKM_FORCE_USED static void UnknownAHReleaseResourcesExecution(void* mem)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
@ -141,7 +160,7 @@ static void UnknownAHReleaseResourcesExecution(void* mem)
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
static void UnknownAHPrintSummary(void* mem, std::ostream& out, bool full)
|
||||
VTKM_FORCE_USED static void UnknownAHPrintSummary(void* mem, std::ostream& out, bool full)
|
||||
{
|
||||
using AH = vtkm::cont::ArrayHandle<T, S>;
|
||||
AH* arrayHandle = reinterpret_cast<AH*>(mem);
|
||||
@ -281,60 +300,47 @@ private:
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
static std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic(vtkm::VecTraitsTagSizeStatic)
|
||||
VTKM_FORCE_USED static std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic(
|
||||
vtkm::VecTraitsTagSizeStatic)
|
||||
{
|
||||
return UnknownAHContainer::Make(vtkm::cont::ArrayHandleBasic<T>{});
|
||||
}
|
||||
template <typename T>
|
||||
static std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic(vtkm::VecTraitsTagSizeVariable)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadType("Cannot create a basic array container from with ValueType of " +
|
||||
vtkm::cont::TypeToString<T>());
|
||||
}
|
||||
template <typename T>
|
||||
static std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic()
|
||||
{
|
||||
return UnknownAHNewInstanceBasic<T>(typename vtkm::VecTraits<T>::IsSizeStatic{});
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic(
|
||||
vtkm::VecTraitsTagSizeStatic)
|
||||
{
|
||||
using FloatT = typename vtkm::VecTraits<T>::template ReplaceBaseComponentType<vtkm::FloatDefault>;
|
||||
return UnknownAHContainer::Make(vtkm::cont::ArrayHandleBasic<FloatT>{});
|
||||
}
|
||||
template <typename T>
|
||||
static std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic(
|
||||
VTKM_FORCE_USED static std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic(
|
||||
vtkm::VecTraitsTagSizeVariable)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadType("Cannot create a basic array container from with ValueType of " +
|
||||
vtkm::cont::TypeToString<T>());
|
||||
}
|
||||
template <typename T>
|
||||
static std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic()
|
||||
VTKM_FORCE_USED static std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceBasic()
|
||||
{
|
||||
return UnknownAHNewInstanceBasic<T>(typename vtkm::VecTraits<T>::IsSizeStatic{});
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
VTKM_FORCE_USED static std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic(
|
||||
vtkm::VecTraitsTagSizeStatic)
|
||||
{
|
||||
using FloatT = typename vtkm::VecTraits<T>::template ReplaceBaseComponentType<vtkm::FloatDefault>;
|
||||
return UnknownAHContainer::Make(vtkm::cont::ArrayHandleBasic<FloatT>{});
|
||||
}
|
||||
template <typename T>
|
||||
VTKM_FORCE_USED static std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic(
|
||||
vtkm::VecTraitsTagSizeVariable)
|
||||
{
|
||||
throw vtkm::cont::ErrorBadType("Cannot create a basic array container from with ValueType of " +
|
||||
vtkm::cont::TypeToString<T>());
|
||||
}
|
||||
template <typename T>
|
||||
VTKM_FORCE_USED static std::shared_ptr<UnknownAHContainer> UnknownAHNewInstanceFloatBasic()
|
||||
{
|
||||
return UnknownAHNewInstanceFloatBasic<T>(typename vtkm::VecTraits<T>::IsSizeStatic{});
|
||||
}
|
||||
|
||||
template <typename T, typename S>
|
||||
#ifdef VTKM_GCC
|
||||
// On rare occasion, we have seen errors like this:
|
||||
// `_ZN4vtkm4cont6detailL27UnknownAHNumberOfComponentsIxEEiv' referenced in section
|
||||
// `.data.rel.ro.local' of CMakeFiles/UnitTests_vtkm_cont_testing.dir/UnitTestCellSet.cxx.o:
|
||||
// defined in discarded section
|
||||
// `.text._ZN4vtkm4cont6detailL27UnknownAHNumberOfComponentsIxEEiv[_ZN4vtkm4cont14ArrayGetValuesINS0_15StorageTagBasicExNS0_18StorageTagCountingES2_EEvRKNS0_11ArrayHandleIxT_EERKNS4_IT0_T1_EERNS4_IS9_T2_EE]'
|
||||
// of CMakeFiles/UnitTests_vtkm_cont_testing.dir/UnitTestCellSet.cxx.o
|
||||
// I don't know what circumstances exactly lead up to this, but it appears that the compiler
|
||||
// is being overly aggressive with removing unused symbols. In this instance, it seems to have
|
||||
// removed a function actually being used. This might be a bug in the compiler (I happen to have
|
||||
// seen it in gcc 8.3), or it could be caused by a link-time optimizer. The problem should be
|
||||
// able to be solved by explictly saying that this templated method is being used. (I can't think
|
||||
// of any circumstances where this template would be instantiated but not used.) If the compiler
|
||||
// knows this is being used, it should know all the templated methods internal are also used.
|
||||
__attribute__((used))
|
||||
#endif
|
||||
inline UnknownAHContainer::UnknownAHContainer(const vtkm::cont::ArrayHandle<T, S>& array)
|
||||
VTKM_FORCE_USED inline UnknownAHContainer::UnknownAHContainer(
|
||||
const vtkm::cont::ArrayHandle<T, S>& array)
|
||||
: ArrayHandlePointer(new vtkm::cont::ArrayHandle<T, S>(array))
|
||||
, ValueType(typeid(T))
|
||||
, StorageType(typeid(S))
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include <vtkm/io/ErrorIO.h>
|
||||
|
||||
#include <vtkm/io/internal/Endian.h>
|
||||
#include <vtkm/io/internal/VTKDataSetTypes.h>
|
||||
|
||||
#include <algorithm>
|
||||
@ -85,10 +86,28 @@ using ArrayHandleRectilinearCoordinates =
|
||||
struct OutputArrayDataFunctor
|
||||
{
|
||||
template <typename T>
|
||||
VTKM_CONT void operator()(T, const vtkm::cont::UnknownArrayHandle& array, std::ostream& out) const
|
||||
VTKM_CONT void operator()(T,
|
||||
const vtkm::cont::UnknownArrayHandle& array,
|
||||
std::ostream& out,
|
||||
vtkm::io::FileType fileType) const
|
||||
{
|
||||
auto componentArray = array.ExtractArrayFromComponents<T>();
|
||||
auto portal = componentArray.ReadPortal();
|
||||
switch (fileType)
|
||||
{
|
||||
case vtkm::io::FileType::ASCII:
|
||||
this->OutputAsciiArray(portal, out);
|
||||
break;
|
||||
case vtkm::io::FileType::BINARY:
|
||||
this->OutputBinaryArray(portal, out);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename PortalType>
|
||||
void OutputAsciiArray(const PortalType& portal, std::ostream& out) const
|
||||
{
|
||||
using T = typename PortalType::ValueType::ComponentType;
|
||||
|
||||
vtkm::Id numValues = portal.GetNumberOfValues();
|
||||
for (vtkm::Id valueIndex = 0; valueIndex < numValues; ++valueIndex)
|
||||
@ -109,11 +128,37 @@ struct OutputArrayDataFunctor
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
template <typename PortalType>
|
||||
void OutputBinaryArray(const PortalType& portal, std::ostream& out) const
|
||||
{
|
||||
using T = typename PortalType::ValueType::ComponentType;
|
||||
|
||||
vtkm::Id numValues = portal.GetNumberOfValues();
|
||||
std::vector<T> tuple;
|
||||
for (vtkm::Id valueIndex = 0; valueIndex < numValues; ++valueIndex)
|
||||
{
|
||||
auto value = portal.Get(valueIndex);
|
||||
tuple.resize(static_cast<std::size_t>(value.GetNumberOfComponents()));
|
||||
for (vtkm::IdComponent cIndex = 0; cIndex < value.GetNumberOfComponents(); ++cIndex)
|
||||
{
|
||||
tuple[static_cast<std::size_t>(cIndex)] = value[cIndex];
|
||||
}
|
||||
if (vtkm::io::internal::IsLittleEndian())
|
||||
{
|
||||
vtkm::io::internal::FlipEndianness(tuple);
|
||||
}
|
||||
out.write(reinterpret_cast<const char*>(tuple.data()),
|
||||
static_cast<std::streamsize>(tuple.size() * sizeof(T)));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
void OutputArrayData(const vtkm::cont::UnknownArrayHandle& array, std::ostream& out)
|
||||
void OutputArrayData(const vtkm::cont::UnknownArrayHandle& array,
|
||||
std::ostream& out,
|
||||
vtkm::io::FileType fileType)
|
||||
{
|
||||
CallForBaseType(OutputArrayDataFunctor{}, array, out);
|
||||
CallForBaseType(OutputArrayDataFunctor{}, array, out, fileType);
|
||||
}
|
||||
|
||||
struct GetFieldTypeNameFunctor
|
||||
@ -147,7 +192,7 @@ void WriteDimensions(std::ostream& out, const vtkm::cont::CellSetStructured<DIM>
|
||||
out << (DIM > 2 ? VTraits::GetComponent(pointDimensions, 2) : 1) << "\n";
|
||||
}
|
||||
|
||||
void WritePoints(std::ostream& out, const vtkm::cont::DataSet& dataSet)
|
||||
void WritePoints(std::ostream& out, const vtkm::cont::DataSet& dataSet, vtkm::io::FileType fileType)
|
||||
{
|
||||
///\todo: support other coordinate systems
|
||||
int cindex = 0;
|
||||
@ -158,11 +203,11 @@ void WritePoints(std::ostream& out, const vtkm::cont::DataSet& dataSet)
|
||||
vtkm::Id npoints = cdata.GetNumberOfValues();
|
||||
out << "POINTS " << npoints << " " << typeName << " " << '\n';
|
||||
|
||||
OutputArrayData(cdata, out);
|
||||
OutputArrayData(cdata, out, fileType);
|
||||
}
|
||||
|
||||
template <class CellSetType>
|
||||
void WriteExplicitCells(std::ostream& out, const CellSetType& cellSet)
|
||||
void WriteExplicitCellsAscii(std::ostream& out, const CellSetType& cellSet)
|
||||
{
|
||||
vtkm::Id nCells = cellSet.GetNumberOfCells();
|
||||
|
||||
@ -182,7 +227,9 @@ void WriteExplicitCells(std::ostream& out, const CellSetType& cellSet)
|
||||
out << nids;
|
||||
auto IdPortal = ids.ReadPortal();
|
||||
for (int j = 0; j < nids; ++j)
|
||||
{
|
||||
out << " " << IdPortal.Get(j);
|
||||
}
|
||||
out << '\n';
|
||||
}
|
||||
|
||||
@ -194,7 +241,74 @@ void WriteExplicitCells(std::ostream& out, const CellSetType& cellSet)
|
||||
}
|
||||
}
|
||||
|
||||
void WritePointFields(std::ostream& out, const vtkm::cont::DataSet& dataSet)
|
||||
template <class CellSetType>
|
||||
void WriteExplicitCellsBinary(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';
|
||||
|
||||
std::vector<vtkm::Int32> buffer;
|
||||
buffer.reserve(static_cast<std::size_t>(conn_length));
|
||||
for (vtkm::Id i = 0; i < nCells; ++i)
|
||||
{
|
||||
vtkm::cont::ArrayHandle<vtkm::Id> ids;
|
||||
vtkm::Id nids = cellSet.GetNumberOfPointsInCell(i);
|
||||
cellSet.GetIndices(i, ids);
|
||||
buffer.push_back(static_cast<vtkm::Int32>(nids));
|
||||
auto IdPortal = ids.ReadPortal();
|
||||
for (int j = 0; j < nids; ++j)
|
||||
{
|
||||
buffer.push_back(static_cast<vtkm::Int32>(IdPortal.Get(j)));
|
||||
}
|
||||
}
|
||||
if (vtkm::io::internal::IsLittleEndian())
|
||||
{
|
||||
vtkm::io::internal::FlipEndianness(buffer);
|
||||
}
|
||||
VTKM_ASSERT(static_cast<vtkm::Id>(buffer.size()) == conn_length);
|
||||
out.write(reinterpret_cast<const char*>(buffer.data()),
|
||||
static_cast<std::streamsize>(buffer.size() * sizeof(vtkm::Int32)));
|
||||
|
||||
out << "CELL_TYPES " << nCells << '\n';
|
||||
buffer.resize(0);
|
||||
buffer.reserve(static_cast<std::size_t>(nCells));
|
||||
for (vtkm::Id i = 0; i < nCells; ++i)
|
||||
{
|
||||
buffer.push_back(static_cast<vtkm::Int32>(cellSet.GetCellShape(i)));
|
||||
}
|
||||
if (vtkm::io::internal::IsLittleEndian())
|
||||
{
|
||||
vtkm::io::internal::FlipEndianness(buffer);
|
||||
}
|
||||
VTKM_ASSERT(static_cast<vtkm::Id>(buffer.size()) == nCells);
|
||||
out.write(reinterpret_cast<const char*>(buffer.data()),
|
||||
static_cast<std::streamsize>(buffer.size() * sizeof(vtkm::Int32)));
|
||||
}
|
||||
|
||||
template <class CellSetType>
|
||||
void WriteExplicitCells(std::ostream& out, const CellSetType& cellSet, vtkm::io::FileType fileType)
|
||||
{
|
||||
switch (fileType)
|
||||
{
|
||||
case vtkm::io::FileType::ASCII:
|
||||
WriteExplicitCellsAscii(out, cellSet);
|
||||
break;
|
||||
case vtkm::io::FileType::BINARY:
|
||||
WriteExplicitCellsBinary(out, cellSet);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void WritePointFields(std::ostream& out,
|
||||
const vtkm::cont::DataSet& dataSet,
|
||||
vtkm::io::FileType fileType)
|
||||
{
|
||||
bool wrote_header = false;
|
||||
for (vtkm::Id f = 0; f < dataSet.GetNumberOfFields(); f++)
|
||||
@ -227,11 +341,13 @@ void WritePointFields(std::ostream& out, const vtkm::cont::DataSet& dataSet)
|
||||
out << "SCALARS " << name << " " << typeName << " " << ncomps << '\n';
|
||||
out << "LOOKUP_TABLE default" << '\n';
|
||||
|
||||
OutputArrayData(field.GetData(), out);
|
||||
OutputArrayData(field.GetData(), out, fileType);
|
||||
}
|
||||
}
|
||||
|
||||
void WriteCellFields(std::ostream& out, const vtkm::cont::DataSet& dataSet)
|
||||
void WriteCellFields(std::ostream& out,
|
||||
const vtkm::cont::DataSet& dataSet,
|
||||
vtkm::io::FileType fileType)
|
||||
{
|
||||
bool wrote_header = false;
|
||||
for (vtkm::Id f = 0; f < dataSet.GetNumberOfFields(); f++)
|
||||
@ -266,18 +382,19 @@ void WriteCellFields(std::ostream& out, const vtkm::cont::DataSet& dataSet)
|
||||
out << "SCALARS " << name << " " << typeName << " " << ncomps << '\n';
|
||||
out << "LOOKUP_TABLE default" << '\n';
|
||||
|
||||
OutputArrayData(field.GetData(), out);
|
||||
OutputArrayData(field.GetData(), out, fileType);
|
||||
}
|
||||
}
|
||||
|
||||
template <class CellSetType>
|
||||
void WriteDataSetAsUnstructured(std::ostream& out,
|
||||
const vtkm::cont::DataSet& dataSet,
|
||||
const CellSetType& cellSet)
|
||||
const CellSetType& cellSet,
|
||||
vtkm::io::FileType fileType)
|
||||
{
|
||||
out << "DATASET UNSTRUCTURED_GRID" << '\n';
|
||||
WritePoints(out, dataSet);
|
||||
WriteExplicitCells(out, cellSet);
|
||||
WritePoints(out, dataSet, fileType);
|
||||
WriteExplicitCells(out, cellSet, fileType);
|
||||
}
|
||||
|
||||
template <vtkm::IdComponent DIM>
|
||||
@ -299,7 +416,8 @@ void WriteDataSetAsStructuredPoints(std::ostream& out,
|
||||
template <typename T, vtkm::IdComponent DIM>
|
||||
void WriteDataSetAsRectilinearGrid(std::ostream& out,
|
||||
const ArrayHandleRectilinearCoordinates<T>& points,
|
||||
const vtkm::cont::CellSetStructured<DIM>& cellSet)
|
||||
const vtkm::cont::CellSetStructured<DIM>& cellSet,
|
||||
vtkm::io::FileType fileType)
|
||||
{
|
||||
out << "DATASET RECTILINEAR_GRID\n";
|
||||
|
||||
@ -310,33 +428,35 @@ void WriteDataSetAsRectilinearGrid(std::ostream& out,
|
||||
|
||||
dimArray = points.GetFirstArray();
|
||||
out << "X_COORDINATES " << dimArray.GetNumberOfValues() << " " << typeName << "\n";
|
||||
OutputArrayData(dimArray, out);
|
||||
OutputArrayData(dimArray, out, fileType);
|
||||
|
||||
dimArray = points.GetSecondArray();
|
||||
out << "Y_COORDINATES " << dimArray.GetNumberOfValues() << " " << typeName << "\n";
|
||||
OutputArrayData(dimArray, out);
|
||||
OutputArrayData(dimArray, out, fileType);
|
||||
|
||||
dimArray = points.GetThirdArray();
|
||||
out << "Z_COORDINATES " << dimArray.GetNumberOfValues() << " " << typeName << "\n";
|
||||
OutputArrayData(dimArray, out);
|
||||
OutputArrayData(dimArray, out, fileType);
|
||||
}
|
||||
|
||||
template <vtkm::IdComponent DIM>
|
||||
void WriteDataSetAsStructuredGrid(std::ostream& out,
|
||||
const vtkm::cont::DataSet& dataSet,
|
||||
const vtkm::cont::CellSetStructured<DIM>& cellSet)
|
||||
const vtkm::cont::CellSetStructured<DIM>& cellSet,
|
||||
vtkm::io::FileType fileType)
|
||||
{
|
||||
out << "DATASET STRUCTURED_GRID" << '\n';
|
||||
|
||||
WriteDimensions(out, cellSet);
|
||||
|
||||
WritePoints(out, dataSet);
|
||||
WritePoints(out, dataSet, fileType);
|
||||
}
|
||||
|
||||
template <vtkm::IdComponent DIM>
|
||||
void WriteDataSetAsStructured(std::ostream& out,
|
||||
const vtkm::cont::DataSet& dataSet,
|
||||
const vtkm::cont::CellSetStructured<DIM>& cellSet)
|
||||
const vtkm::cont::CellSetStructured<DIM>& cellSet,
|
||||
vtkm::io::FileType fileType)
|
||||
{
|
||||
///\todo: support rectilinear
|
||||
|
||||
@ -351,21 +471,27 @@ void WriteDataSetAsStructured(std::ostream& out,
|
||||
else if (coordSystem.IsType<ArrayHandleRectilinearCoordinates<vtkm::Float32>>())
|
||||
{
|
||||
WriteDataSetAsRectilinearGrid(
|
||||
out, coordSystem.AsArrayHandle<ArrayHandleRectilinearCoordinates<vtkm::Float32>>(), cellSet);
|
||||
out,
|
||||
coordSystem.AsArrayHandle<ArrayHandleRectilinearCoordinates<vtkm::Float32>>(),
|
||||
cellSet,
|
||||
fileType);
|
||||
}
|
||||
else if (coordSystem.IsType<ArrayHandleRectilinearCoordinates<vtkm::Float64>>())
|
||||
{
|
||||
WriteDataSetAsRectilinearGrid(
|
||||
out, coordSystem.AsArrayHandle<ArrayHandleRectilinearCoordinates<vtkm::Float64>>(), cellSet);
|
||||
out,
|
||||
coordSystem.AsArrayHandle<ArrayHandleRectilinearCoordinates<vtkm::Float64>>(),
|
||||
cellSet,
|
||||
fileType);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Curvilinear is written as "structured grid"
|
||||
WriteDataSetAsStructuredGrid(out, dataSet, cellSet);
|
||||
WriteDataSetAsStructuredGrid(out, dataSet, cellSet, fileType);
|
||||
}
|
||||
}
|
||||
|
||||
void Write(std::ostream& out, const vtkm::cont::DataSet& dataSet)
|
||||
void Write(std::ostream& out, const vtkm::cont::DataSet& dataSet, vtkm::io::FileType fileType)
|
||||
{
|
||||
// The Paraview parser cannot handle scientific notation:
|
||||
out << std::fixed;
|
||||
@ -380,41 +506,54 @@ void Write(std::ostream& out, const vtkm::cont::DataSet& dataSet)
|
||||
#endif
|
||||
out << "# vtk DataFile Version 3.0" << '\n';
|
||||
out << "vtk output" << '\n';
|
||||
out << "ASCII" << '\n';
|
||||
switch (fileType)
|
||||
{
|
||||
case vtkm::io::FileType::ASCII:
|
||||
out << "ASCII" << '\n';
|
||||
break;
|
||||
case vtkm::io::FileType::BINARY:
|
||||
out << "BINARY" << '\n';
|
||||
break;
|
||||
}
|
||||
|
||||
vtkm::cont::DynamicCellSet cellSet = dataSet.GetCellSet();
|
||||
if (cellSet.IsType<vtkm::cont::CellSetExplicit<>>())
|
||||
{
|
||||
WriteDataSetAsUnstructured(out, dataSet, cellSet.Cast<vtkm::cont::CellSetExplicit<>>());
|
||||
WriteDataSetAsUnstructured(
|
||||
out, dataSet, cellSet.Cast<vtkm::cont::CellSetExplicit<>>(), fileType);
|
||||
}
|
||||
else if (cellSet.IsType<vtkm::cont::CellSetStructured<1>>())
|
||||
{
|
||||
WriteDataSetAsStructured(out, dataSet, cellSet.Cast<vtkm::cont::CellSetStructured<1>>());
|
||||
WriteDataSetAsStructured(
|
||||
out, dataSet, cellSet.Cast<vtkm::cont::CellSetStructured<1>>(), fileType);
|
||||
}
|
||||
else if (cellSet.IsType<vtkm::cont::CellSetStructured<2>>())
|
||||
{
|
||||
WriteDataSetAsStructured(out, dataSet, cellSet.Cast<vtkm::cont::CellSetStructured<2>>());
|
||||
WriteDataSetAsStructured(
|
||||
out, dataSet, cellSet.Cast<vtkm::cont::CellSetStructured<2>>(), fileType);
|
||||
}
|
||||
else if (cellSet.IsType<vtkm::cont::CellSetStructured<3>>())
|
||||
{
|
||||
WriteDataSetAsStructured(out, dataSet, cellSet.Cast<vtkm::cont::CellSetStructured<3>>());
|
||||
WriteDataSetAsStructured(
|
||||
out, dataSet, cellSet.Cast<vtkm::cont::CellSetStructured<3>>(), fileType);
|
||||
}
|
||||
else if (cellSet.IsType<vtkm::cont::CellSetSingleType<>>())
|
||||
{
|
||||
// these function just like explicit cell sets
|
||||
WriteDataSetAsUnstructured(out, dataSet, cellSet.Cast<vtkm::cont::CellSetSingleType<>>());
|
||||
WriteDataSetAsUnstructured(
|
||||
out, dataSet, cellSet.Cast<vtkm::cont::CellSetSingleType<>>(), fileType);
|
||||
}
|
||||
else if (cellSet.IsType<vtkm::cont::CellSetExtrude>())
|
||||
{
|
||||
WriteDataSetAsUnstructured(out, dataSet, cellSet.Cast<vtkm::cont::CellSetExtrude>());
|
||||
WriteDataSetAsUnstructured(out, dataSet, cellSet.Cast<vtkm::cont::CellSetExtrude>(), fileType);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw vtkm::cont::ErrorBadType("Could not determine type to write out.");
|
||||
}
|
||||
|
||||
WritePointFields(out, dataSet);
|
||||
WriteCellFields(out, dataSet);
|
||||
WritePointFields(out, dataSet, fileType);
|
||||
WriteCellFields(out, dataSet, fileType);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
@ -443,8 +582,8 @@ void VTKDataSetWriter::WriteDataSet(const vtkm::cont::DataSet& dataSet) const
|
||||
}
|
||||
try
|
||||
{
|
||||
std::ofstream fileStream(this->FileName.c_str(), std::fstream::trunc);
|
||||
Write(fileStream, dataSet);
|
||||
std::ofstream fileStream(this->FileName.c_str(), std::fstream::trunc | std::fstream::binary);
|
||||
Write(fileStream, dataSet, this->GetFileType());
|
||||
fileStream.close();
|
||||
}
|
||||
catch (std::ofstream::failure& error)
|
||||
@ -452,5 +591,16 @@ void VTKDataSetWriter::WriteDataSet(const vtkm::cont::DataSet& dataSet) const
|
||||
throw vtkm::io::ErrorIO(error.what());
|
||||
}
|
||||
}
|
||||
|
||||
vtkm::io::FileType VTKDataSetWriter::GetFileType() const
|
||||
{
|
||||
return this->FileType;
|
||||
}
|
||||
|
||||
void VTKDataSetWriter::SetFileType(vtkm::io::FileType type)
|
||||
{
|
||||
this->FileType = type;
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace vtkm::io
|
||||
|
@ -19,6 +19,13 @@ namespace vtkm
|
||||
namespace io
|
||||
{
|
||||
|
||||
// Might want to place this somewhere else.
|
||||
enum struct FileType
|
||||
{
|
||||
ASCII,
|
||||
BINARY
|
||||
};
|
||||
|
||||
struct VTKM_IO_EXPORT VTKDataSetWriter
|
||||
{
|
||||
public:
|
||||
@ -27,8 +34,20 @@ public:
|
||||
|
||||
VTKM_CONT void WriteDataSet(const vtkm::cont::DataSet& dataSet) const;
|
||||
|
||||
/// \brief Get whether the file will be written in ASCII or binary format.
|
||||
///
|
||||
VTKM_CONT vtkm::io::FileType GetFileType() const;
|
||||
|
||||
/// \{
|
||||
/// \brief Set whether the file will be written in ASCII or binary format.
|
||||
VTKM_CONT void SetFileType(vtkm::io::FileType type);
|
||||
VTKM_CONT void SetFileTypeToAscii() { this->SetFileType(vtkm::io::FileType::ASCII); }
|
||||
VTKM_CONT void SetFileTypeToBinary() { this->SetFileType(vtkm::io::FileType::BINARY); }
|
||||
/// \}
|
||||
|
||||
private:
|
||||
std::string FileName;
|
||||
vtkm::io::FileType FileType = vtkm::io::FileType::ASCII;
|
||||
|
||||
}; //struct VTKDataSetWriter
|
||||
}
|
||||
|
@ -143,6 +143,24 @@ void TestVTKWriteTestData(const std::string& methodName, const vtkm::cont::DataS
|
||||
// Read back and check.
|
||||
vtkm::io::VTKDataSetReader reader(methodName + ".vtk");
|
||||
CheckWrittenReadData(data, reader.ReadDataSet());
|
||||
|
||||
std::cout << "Writing " << methodName << " ascii" << std::endl;
|
||||
vtkm::io::VTKDataSetWriter writerAscii(methodName + "-ascii.vtk");
|
||||
writerAscii.SetFileTypeToAscii();
|
||||
writerAscii.WriteDataSet(data);
|
||||
|
||||
// Read back and check.
|
||||
vtkm::io::VTKDataSetReader readerAscii(methodName + "-ascii.vtk");
|
||||
CheckWrittenReadData(data, readerAscii.ReadDataSet());
|
||||
|
||||
std::cout << "Writing " << methodName << " binary" << std::endl;
|
||||
vtkm::io::VTKDataSetWriter writerBinary(methodName + "-binary.vtk");
|
||||
writerBinary.SetFileTypeToBinary();
|
||||
writerBinary.WriteDataSet(data);
|
||||
|
||||
// Read back and check.
|
||||
vtkm::io::VTKDataSetReader readerBinary(methodName + "-binary.vtk");
|
||||
CheckWrittenReadData(data, readerBinary.ReadDataSet());
|
||||
}
|
||||
|
||||
void TestVTKExplicitWrite()
|
||||
|
Loading…
Reference in New Issue
Block a user