diff --git a/data/data/uniform/simple_structured_points_strings_ascii.vtk b/data/data/uniform/simple_structured_points_strings_ascii.vtk new file mode 100644 index 000000000..6091acfac --- /dev/null +++ b/data/data/uniform/simple_structured_points_strings_ascii.vtk @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c20b10be38f4dd931bebbea201fb1d4b3b033c048f2e2c77be369bd58d9d0b0a +size 603 diff --git a/data/data/uniform/simple_structured_points_strings_bin.vtk b/data/data/uniform/simple_structured_points_strings_bin.vtk new file mode 100644 index 000000000..800bcd33c --- /dev/null +++ b/data/data/uniform/simple_structured_points_strings_bin.vtk @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:efa0d42dc02757126f2186f8c479e370f462c3cd7a16417240d967294725cdab +size 367 diff --git a/vtkm/io/VTKDataSetReaderBase.cxx b/vtkm/io/VTKDataSetReaderBase.cxx index e622001fa..4e6a30197 100644 --- a/vtkm/io/VTKDataSetReaderBase.cxx +++ b/vtkm/io/VTKDataSetReaderBase.cxx @@ -322,6 +322,12 @@ void VTKDataSetReaderBase::ReadAttributes() { association = vtkm::cont::Field::Association::CELL_SET; } + else if (tag == "FIELD") // can see field in this position also + { + this->ReadGlobalFields(nullptr); + this->DataFile->Stream >> tag; + continue; + } else { internal::parseAssert(false); @@ -693,16 +699,11 @@ 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") + // string requires some special handling + if (dataType == "string" || dataType == "utf8_string") { const vtkm::Id stringCount = numComponents * static_cast(numElements); - for (vtkm::Id i = 0; i < stringCount; ++i) - { - std::string trash; - this->DataFile->Stream >> trash; - } + this->SkipStringArray(stringCount); } else { @@ -722,9 +723,20 @@ vtkm::cont::UnknownArrayHandle VTKDataSetReaderBase::DoReadArrayVariant( vtkm::cont::ArrayHandle empty; vtkm::cont::UnknownArrayHandle data(empty); - vtkm::io::internal::DataType typeId = vtkm::io::internal::DataTypeId(dataType); - vtkm::io::internal::SelectTypeAndCall( - typeId, numComponents, ReadArrayVariant(this, association, numElements, data)); + // string requires some special handling + if (dataType == "string" || dataType == "utf8_string") + { + VTKM_LOG_S(vtkm::cont::LogLevel::Warn, + "Support for data type 'string' and 'utf8_string' is not implemented. Skipping."); + const vtkm::Id stringCount = numComponents * static_cast(numElements); + this->SkipStringArray(stringCount); + } + else + { + vtkm::io::internal::DataType typeId = vtkm::io::internal::DataTypeId(dataType); + vtkm::io::internal::SelectTypeAndCall( + typeId, numComponents, ReadArrayVariant(this, association, numElements, data)); + } return data; } @@ -758,6 +770,65 @@ void VTKDataSetReaderBase::SkipArray(std::size_t numElements, this->SkipArrayMetaData(numComponents); } +void VTKDataSetReaderBase::SkipStringArray(std::size_t numStrings) +{ + if (this->DataFile->IsBinary) + { + for (std::size_t i = 0; i < numStrings; ++i) + { + auto firstByte = this->DataFile->Stream.peek(); + auto type = firstByte >> 6; + switch (type) + { + case 3: // length stored in 1 byte + { + auto length = this->DataFile->Stream.get(); + length &= 0x3F; + this->DataFile->Stream.seekg(static_cast(length), std::ios_base::cur); + break; + } + case 2: // length stored in 2 bytes + { + vtkm::UInt16 length = 0; + auto bytes = reinterpret_cast(&length); + this->DataFile->Stream.read(bytes, 2); + std::swap(bytes[0], bytes[1]); + length &= 0x3FFF; + this->DataFile->Stream.seekg(static_cast(length), std::ios_base::cur); + break; + } + case 1: // length stored in 4 bytes + { + vtkm::UInt32 length = 0; + auto bytes = reinterpret_cast(&length); + this->DataFile->Stream.read(bytes, 4); + std::reverse(bytes, bytes + 4); + length &= 0x3FFFFFFF; + this->DataFile->Stream.seekg(static_cast(length), std::ios_base::cur); + break; + } + default: // length stored in 8 bytes + { + vtkm::UInt64 length = 0; + auto bytes = reinterpret_cast(&length); + this->DataFile->Stream.read(bytes, 8); + std::reverse(bytes, bytes + 8); + this->DataFile->Stream.seekg(static_cast(length), std::ios_base::cur); + break; + } + } + } + } + else + { + for (std::size_t i = 0; i < numStrings; ++i) + { + // ASCII mode stores one string per line + this->DataFile->Stream.ignore(std::numeric_limits::max(), '\n'); + } + } +} + void VTKDataSetReaderBase::SkipArrayMetaData(vtkm::IdComponent numComponents) { if (!this->DataFile->Stream.good()) diff --git a/vtkm/io/VTKDataSetReaderBase.h b/vtkm/io/VTKDataSetReaderBase.h index cc2957a9c..d8b86cfad 100644 --- a/vtkm/io/VTKDataSetReaderBase.h +++ b/vtkm/io/VTKDataSetReaderBase.h @@ -271,6 +271,8 @@ protected: vtkm::io::internal::DummyBitType, vtkm::IdComponent numComponents = 1); + VTKM_CONT void SkipStringArray(std::size_t numStrings); + VTKM_CONT void SkipArrayMetaData(vtkm::IdComponent numComponents); }; } diff --git a/vtkm/io/testing/UnitTestVTKDataSetReader.cxx b/vtkm/io/testing/UnitTestVTKDataSetReader.cxx index 3d0bed1d4..89186143e 100644 --- a/vtkm/io/testing/UnitTestVTKDataSetReader.cxx +++ b/vtkm/io/testing/UnitTestVTKDataSetReader.cxx @@ -468,6 +468,23 @@ void TestReadingFusion() VTKM_TEST_ASSERT(test_equal(zVecRange.Max, 0.480726)); } +void TestSkppingStringFields(Format format) +{ + std::string testFileName = (format == FORMAT_ASCII) + ? vtkm::cont::testing::Testing::DataPath("uniform/simple_structured_points_strings_ascii.vtk") + : vtkm::cont::testing::Testing::DataPath("uniform/simple_structured_points_strings_bin.vtk"); + + vtkm::cont::DataSet ds = readVTKDataSet(testFileName); + + VTKM_TEST_ASSERT(ds.GetNumberOfFields() == 1, "Incorrect number of fields"); + VTKM_TEST_ASSERT(ds.GetNumberOfPoints() == 72, "Incorrect number of points"); + VTKM_TEST_ASSERT(ds.GetCellSet().GetNumberOfPoints() == 72, + "Incorrect number of points (from cell set)"); + VTKM_TEST_ASSERT(ds.GetNumberOfCells() == 30, "Incorrect number of cells"); + VTKM_TEST_ASSERT(ds.GetCellSet().IsType>(), + "Incorrect cellset type"); +} + void TestReadingVTKDataSet() { std::cout << "Test reading VTK Polydata file in ASCII" << std::endl; @@ -509,6 +526,11 @@ void TestReadingVTKDataSet() TestReadingASCIIFishTank(); std::cout << "Test reading fusion" << std::endl; TestReadingFusion(); + + std::cout << "Test skipping string fields in ASCII files" << std::endl; + TestSkppingStringFields(FORMAT_ASCII); + std::cout << "Test skipping string fields in BINARY files" << std::endl; + TestSkppingStringFields(FORMAT_BINARY); } int UnitTestVTKDataSetReader(int argc, char* argv[])