//============================================================================ // 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. //============================================================================ #ifndef vtk_m_io_VTKDataSetReaderBase_h #define vtk_m_io_VTKDataSetReaderBase_h #include #include #include #include #include #include #include #include #include namespace vtkm { namespace io { namespace internal { struct VTKDataSetFile { std::string FileName; vtkm::Id2 Version; std::string Title; bool IsBinary; vtkm::io::internal::DataSetStructure Structure; std::ifstream Stream; }; inline void parseAssert(bool condition) { if (!condition) { throw vtkm::io::ErrorIO("Parse Error"); } } template struct StreamIOType { using Type = T; }; template <> struct StreamIOType { using Type = vtkm::Int16; }; template <> struct StreamIOType { using Type = vtkm::UInt16; }; inline vtkm::cont::UnknownCellSet CreateCellSetStructured(const vtkm::Id3& dim) { if (dim[0] > 1 && dim[1] > 1 && dim[2] > 1) { vtkm::cont::CellSetStructured<3> cs; cs.SetPointDimensions(vtkm::make_Vec(dim[0], dim[1], dim[2])); return cs; } else if (dim[0] > 1 && dim[1] > 1 && dim[2] <= 1) { vtkm::cont::CellSetStructured<2> cs; cs.SetPointDimensions(vtkm::make_Vec(dim[0], dim[1])); return cs; } else if (dim[0] > 1 && dim[1] <= 1 && dim[2] <= 1) { vtkm::cont::CellSetStructured<1> cs; cs.SetPointDimensions(dim[0]); return cs; } std::stringstream ss; ss << "Unsupported dimensions: (" << dim[0] << ", " << dim[1] << ", " << dim[2] << "), 2D structured datasets should be on X-Y plane and " << "1D structured datasets should be along X axis"; throw vtkm::io::ErrorIO(ss.str()); } } // namespace internal class VTKM_IO_EXPORT VTKDataSetReaderBase { protected: std::unique_ptr DataFile; vtkm::cont::DataSet DataSet; private: bool Loaded; vtkm::cont::ArrayHandle CellsPermutation; friend class VTKDataSetReader; public: explicit VTKM_CONT VTKDataSetReaderBase(const char* fileName); explicit VTKM_CONT VTKDataSetReaderBase(const std::string& fileName); virtual VTKM_CONT ~VTKDataSetReaderBase(); VTKDataSetReaderBase(const VTKDataSetReaderBase&) = delete; void operator=(const VTKDataSetReaderBase&) = delete; /// @brief Load data from the file and return it in a `DataSet` object. VTKM_CONT const vtkm::cont::DataSet& ReadDataSet(); const vtkm::cont::DataSet& GetDataSet() const { return this->DataSet; } virtual VTKM_CONT void PrintSummary(std::ostream& out) const; protected: VTKM_CONT void ReadPoints(); VTKM_CONT void ReadCells(vtkm::cont::ArrayHandle& connectivity, vtkm::cont::ArrayHandle& numIndices); VTKM_CONT void ReadShapes(vtkm::cont::ArrayHandle& shapes); VTKM_CONT void ReadAttributes(); void SetCellsPermutation(const vtkm::cont::ArrayHandle& permutation) { this->CellsPermutation = permutation; } VTKM_CONT vtkm::cont::ArrayHandle GetCellsPermutation() const { return this->CellsPermutation; } VTKM_CONT void TransferDataFile(VTKDataSetReaderBase& reader) { reader.DataFile.swap(this->DataFile); this->DataFile.reset(nullptr); } VTKM_CONT virtual void CloseFile(); VTKM_CONT virtual void Read() = 0; private: VTKM_CONT void OpenFile(); VTKM_CONT void ReadHeader(); VTKM_CONT void AddField(const std::string& name, vtkm::cont::Field::Association association, vtkm::cont::UnknownArrayHandle& data); VTKM_CONT void ReadScalars(vtkm::cont::Field::Association association, std::size_t numElements); VTKM_CONT void ReadColorScalars(vtkm::cont::Field::Association association, std::size_t numElements); VTKM_CONT void ReadLookupTable(); VTKM_CONT void ReadTextureCoordinates(vtkm::cont::Field::Association association, std::size_t numElements); VTKM_CONT void ReadVectors(vtkm::cont::Field::Association association, std::size_t numElements); VTKM_CONT void ReadTensors(vtkm::cont::Field::Association association, std::size_t numElements); VTKM_CONT void ReadFields(vtkm::cont::Field::Association association, std::size_t expectedNumElements); VTKM_CONT void ReadGlobalOrPedigreeIds(vtkm::cont::Field::Association association, std::size_t numElements); protected: VTKM_CONT void ReadGlobalFields(std::vector* visitBounds = nullptr); private: class SkipArrayVariant; class ReadArrayVariant; //Make the Array parsing methods protected so that derived classes //can call the methods. protected: VTKM_CONT void DoSkipArrayVariant(std::string dataType, std::size_t numElements, vtkm::IdComponent numComponents); VTKM_CONT vtkm::cont::UnknownArrayHandle DoReadArrayVariant( vtkm::cont::Field::Association association, std::string dataType, std::size_t numElements, vtkm::IdComponent numComponents); template VTKM_CONT void ReadArray(std::vector& buffer) { using ComponentType = typename vtkm::VecTraits::ComponentType; constexpr vtkm::IdComponent numComponents = vtkm::VecTraits::NUM_COMPONENTS; std::size_t numElements = buffer.size(); if (this->DataFile->IsBinary) { this->DataFile->Stream.read(reinterpret_cast(&buffer[0]), static_cast(numElements * sizeof(T))); if (vtkm::io::internal::IsLittleEndian()) { vtkm::io::internal::FlipEndianness(buffer); } } else { for (std::size_t i = 0; i < numElements; ++i) { for (vtkm::IdComponent j = 0; j < numComponents; ++j) { typename internal::StreamIOType::Type val; this->DataFile->Stream >> val; vtkm::VecTraits::SetComponent(buffer[i], j, static_cast(val)); } } } this->DataFile->Stream >> std::ws; this->SkipArrayMetaData(numComponents); } template VTKM_CONT void ReadArray( std::vector>& buffer) { VTKM_LOG_S(vtkm::cont::LogLevel::Warn, "Support for data type 'bit' is not implemented. Skipping."); this->SkipArray(buffer.size(), vtkm::Vec()); buffer.clear(); } VTKM_CONT void ReadArray(std::vector& buffer); template void SkipArray(std::size_t numElements, T) { using ComponentType = typename vtkm::VecTraits::ComponentType; constexpr vtkm::IdComponent numComponents = vtkm::VecTraits::NUM_COMPONENTS; if (this->DataFile->IsBinary) { this->DataFile->Stream.seekg(static_cast(numElements * sizeof(T)), std::ios_base::cur); } else { for (std::size_t i = 0; i < numElements; ++i) { for (vtkm::IdComponent j = 0; j < numComponents; ++j) { typename internal::StreamIOType::Type val; this->DataFile->Stream >> val; } } } this->DataFile->Stream >> std::ws; this->SkipArrayMetaData(numComponents); } template void SkipArray(std::size_t numElements, vtkm::Vec) { this->SkipArray(numElements * static_cast(NumComponents), vtkm::io::internal::DummyBitType(), NumComponents); } VTKM_CONT void SkipArray(std::size_t numElements, vtkm::io::internal::DummyBitType, vtkm::IdComponent numComponents = 1); VTKM_CONT void SkipStringArray(std::size_t numStrings); VTKM_CONT void SkipArrayMetaData(vtkm::IdComponent numComponents); }; } } // vtkm::io #endif // vtk_m_io_VTKDataSetReaderBase_h