From 1dcdba8a4f986ddaad698ed33e52acd7b448c099 Mon Sep 17 00:00:00 2001 From: Allison Vacanti Date: Tue, 5 Feb 2019 13:32:20 -0500 Subject: [PATCH 1/3] Add move support to vtkSmartPointer. --- Common/Core/vtkSmartPointer.h | 9 +++++++++ Common/Core/vtkSmartPointerBase.cxx | 9 +++++++++ Common/Core/vtkSmartPointerBase.h | 12 ++++++++++++ 3 files changed, 30 insertions(+) diff --git a/Common/Core/vtkSmartPointer.h b/Common/Core/vtkSmartPointer.h index 921eca7daa4..1582788b3bd 100644 --- a/Common/Core/vtkSmartPointer.h +++ b/Common/Core/vtkSmartPointer.h @@ -25,6 +25,7 @@ #include "vtkSmartPointerBase.h" #include "vtkNew.h" // For converting New pointers to Smart pointers +#include // for enable_if template class vtkSmartPointer: public vtkSmartPointerBase @@ -54,6 +55,14 @@ public: vtkSmartPointer(const vtkSmartPointer& r): vtkSmartPointerBase(CheckType(r.GetPointer())) {} + /** + * Move the contents of @a r into @a this. + */ + template ::value>::type> + vtkSmartPointer(vtkSmartPointer&& r) noexcept + : vtkSmartPointerBase(std::move(r)) {} + //@{ /** * Assign object to reference. This removes any reference to an old diff --git a/Common/Core/vtkSmartPointerBase.cxx b/Common/Core/vtkSmartPointerBase.cxx index 1f83553c0fe..47f1709c1ff 100644 --- a/Common/Core/vtkSmartPointerBase.cxx +++ b/Common/Core/vtkSmartPointerBase.cxx @@ -89,6 +89,15 @@ vtkSmartPointerBase::operator=(const vtkSmartPointerBase& r) return *this; } +//---------------------------------------------------------------------------- +vtkSmartPointerBase &vtkSmartPointerBase::operator=(vtkSmartPointerBase &&r) noexcept +{ + using std::swap; + swap(this->Object, r.Object); + r = nullptr; // Unregister our old object. + return *this; +} + //---------------------------------------------------------------------------- void vtkSmartPointerBase::Report(vtkGarbageCollector* collector, const char* desc) diff --git a/Common/Core/vtkSmartPointerBase.h b/Common/Core/vtkSmartPointerBase.h index 42b8dfb4353..24d44f42dcc 100644 --- a/Common/Core/vtkSmartPointerBase.h +++ b/Common/Core/vtkSmartPointerBase.h @@ -48,6 +48,15 @@ public: */ vtkSmartPointerBase(const vtkSmartPointerBase& r); + /** + * Move the pointee from @a r into @a this and reset @ r. + */ + vtkSmartPointerBase(vtkSmartPointerBase&& r) noexcept + : Object(r.Object) + { + r.Object = nullptr; + } + /** * Destroy smart pointer and remove the reference to its object. */ @@ -60,6 +69,9 @@ public: */ vtkSmartPointerBase& operator=(vtkObjectBase* r); vtkSmartPointerBase& operator=(const vtkSmartPointerBase& r); +#ifndef __VTK_WRAP__ + vtkSmartPointerBase& operator=(vtkSmartPointerBase&& r) noexcept; +#endif // __VTK_WRAP__ //@} /** -- GitLab From 4bf0437b6d5301dee83b9a5923ff9f4c8ebed46c Mon Sep 17 00:00:00 2001 From: Allison Vacanti Date: Fri, 1 Feb 2019 14:08:31 -0500 Subject: [PATCH 2/3] Use more compiler-friendly strategy for vtk::Range includes. Rather than include a single header that pulls in every known range implementation, specific implementations should be pulled in (e.g. ). This will reduce the amount of work needed to compile TUs containing these headers, and allow modules other than CommonCore to hook into the vtk::Range() subsystem. --- Common/Core/Testing/Cxx/TestCollection.cxx | 2 +- Common/Core/vtkCollectionRange.h | 1 + Common/Core/vtkRange.h | 3 +-- IO/Export/vtkGLTFExporter.cxx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Common/Core/Testing/Cxx/TestCollection.cxx b/Common/Core/Testing/Cxx/TestCollection.cxx index b99ef690a8b..8b637d89208 100644 --- a/Common/Core/Testing/Cxx/TestCollection.cxx +++ b/Common/Core/Testing/Cxx/TestCollection.cxx @@ -14,9 +14,9 @@ =========================================================================*/ #include "vtkCollection.h" +#include "vtkCollectionRange.h" #include "vtkIntArray.h" #include "vtkNew.h" -#include "vtkRange.h" #include "vtkSmartPointer.h" #include diff --git a/Common/Core/vtkCollectionRange.h b/Common/Core/vtkCollectionRange.h index e18b4da18f6..9ae52911dd2 100644 --- a/Common/Core/vtkCollectionRange.h +++ b/Common/Core/vtkCollectionRange.h @@ -19,6 +19,7 @@ #include "vtkCollection.h" #include "vtkMeta.h" #include "vtkSmartPointer.h" +#include "vtkRange.h" namespace vtk { diff --git a/Common/Core/vtkRange.h b/Common/Core/vtkRange.h index 358b30a421e..caf6b263b09 100644 --- a/Common/Core/vtkRange.h +++ b/Common/Core/vtkRange.h @@ -16,7 +16,6 @@ #ifndef vtkRange_h #define vtkRange_h -#include "vtkCollectionRange.h" #include "vtkMeta.h" #include @@ -31,7 +30,7 @@ namespace vtk * * Currently supports: * - * - vtkCollection: + * - vtkCollection (`#include `): * - ItemType is the (non-pointer) result type of GetNextItem() if this method * exists on the collection type, otherwise vtkObject is used. * - Iterators fulfill the STL InputIterator concept with some exceptions: diff --git a/IO/Export/vtkGLTFExporter.cxx b/IO/Export/vtkGLTFExporter.cxx index 0d4d939e325..0aab83edbcc 100644 --- a/IO/Export/vtkGLTFExporter.cxx +++ b/IO/Export/vtkGLTFExporter.cxx @@ -22,13 +22,13 @@ #include "vtkAssemblyPath.h" #include "vtkBase64OutputStream.h" #include "vtkCamera.h" +#include "vtkCollectionRange.h" #include "vtkCompositeDataIterator.h" #include "vtkCompositeDataSet.h" #include "vtkMapper.h" #include "vtkMatrix4x4.h" #include "vtkObjectFactory.h" #include "vtkPolyData.h" -#include "vtkRange.h" #include "vtkRendererCollection.h" #include "vtkRenderWindow.h" #include "vtkTriangleFilter.h" -- GitLab From 49ef51243bd39a0dc435d28315e1c252c16c0442 Mon Sep 17 00:00:00 2001 From: Allison Vacanti Date: Tue, 5 Feb 2019 13:32:47 -0500 Subject: [PATCH 3/3] Add for-range iterator for vtkCompositeDataSet. --- Common/Core/CMakeLists.txt | 1 + Common/Core/vtkCollectionRange.h | 20 +- Common/Core/vtkMeta.h | 7 - Common/Core/vtkRange.h | 23 +- Common/Core/vtkRangeIterableTraits.h | 72 ++++ Common/Core/vtkSetGet.h | 41 +++ Common/Core/vtkSmartPointer.h | 2 + Common/Core/vtkSmartPointerBase.h | 2 + Common/DataModel/CMakeLists.txt | 2 + Common/DataModel/Testing/Cxx/CMakeLists.txt | 2 + .../Testing/Cxx/TestCompositeDataSetRange.cxx | 164 +++++++++ .../Testing/Cxx/TestDataObjectTreeRange.cxx | 174 ++++++++++ Common/DataModel/vtkCompositeDataSetRange.h | 318 +++++++++++++++++ Common/DataModel/vtkDataObjectTreeRange.h | 326 ++++++++++++++++++ ...kXMLPartitionedDataSetCollectionWriter.cxx | 27 +- .../vtkCompositeDataDisplayAttributes.cxx | 27 +- Rendering/Core/vtkGlyph3DMapper.cxx | 21 +- .../OpenGL2/vtkCompositePolyDataMapper2.cxx | 22 +- 18 files changed, 1159 insertions(+), 92 deletions(-) create mode 100644 Common/Core/vtkRangeIterableTraits.h create mode 100644 Common/DataModel/Testing/Cxx/TestCompositeDataSetRange.cxx create mode 100644 Common/DataModel/Testing/Cxx/TestDataObjectTreeRange.cxx create mode 100644 Common/DataModel/vtkCompositeDataSetRange.h create mode 100644 Common/DataModel/vtkDataObjectTreeRange.h diff --git a/Common/Core/CMakeLists.txt b/Common/Core/CMakeLists.txt index bd3fc6912ca..c510ca37c3a 100644 --- a/Common/Core/CMakeLists.txt +++ b/Common/Core/CMakeLists.txt @@ -252,6 +252,7 @@ set(headers vtkAtomicTypes.h vtkAutoInit.h vtkBuffer.h + vtkCollectionRange.h vtkDataArrayAccessor.h vtkDataArrayIteratorMacro.h vtkDataArrayMeta.h diff --git a/Common/Core/vtkCollectionRange.h b/Common/Core/vtkCollectionRange.h index 9ae52911dd2..f32746d41f6 100644 --- a/Common/Core/vtkCollectionRange.h +++ b/Common/Core/vtkCollectionRange.h @@ -21,6 +21,8 @@ #include "vtkSmartPointer.h" #include "vtkRange.h" +#ifndef __VTK_WRAP__ + namespace vtk { namespace detail @@ -34,7 +36,7 @@ template struct CollectionIterator; template struct IsCollection : std::is_base_of {}; -template +template using EnableIfIsCollection = typename std::enable_if::value, T>::type; @@ -253,23 +255,11 @@ private: vtkSmartPointer Collection; }; -// IterableTraits specialization to hook into vtk::Range. -template > -struct IterableTraits -{ - static_assert(IsCollection::value, - "Invalid vtkCollection subclass."); - - using ItemType = typename GetCollectionItemType::Type; - using RangeType = CollectionRange; -}; - - - } } // end namespace vtk::detail +#endif // __VTK_WRAP__ + #endif // vtkCollectionRange_h // VTK-HeaderTest-Exclude: vtkCollectionRange.h diff --git a/Common/Core/vtkMeta.h b/Common/Core/vtkMeta.h index dacb86a9dc8..8c8eeea5b01 100644 --- a/Common/Core/vtkMeta.h +++ b/Common/Core/vtkMeta.h @@ -76,13 +76,6 @@ public: using value = decltype(impl(std::declval())); }; -// Traits class that should define RangeType, which would point to the range -// proxy for Iterable. This is only used by vtk::Range calls. -// It is included here to ensure that the stub is defined before any -// specializations. -template -struct IterableTraits; - } } // end namespace vtk::detail diff --git a/Common/Core/vtkRange.h b/Common/Core/vtkRange.h index caf6b263b09..830c834e2fe 100644 --- a/Common/Core/vtkRange.h +++ b/Common/Core/vtkRange.h @@ -17,6 +17,7 @@ #define vtkRange_h #include "vtkMeta.h" +#include "vtkRangeIterableTraits.h" #include #include @@ -30,7 +31,7 @@ namespace vtk * * Currently supports: * - * - vtkCollection (`#include `): + * - vtkCollection and subclasses (`#include `): * - ItemType is the (non-pointer) result type of GetNextItem() if this method * exists on the collection type, otherwise vtkObject is used. * - Iterators fulfill the STL InputIterator concept with some exceptions: @@ -42,6 +43,16 @@ namespace vtk * - ItemType*& references aren't generally desired. * - ItemType& references are unconventional for vtkObjects. * - ItemType** pointers are unruly. + * - vtkCompositeDataSet (`#include `) + * - vtk::CompositeDataSetOptions: None, SkipEmptyNodes. + * - Ex. vtk::Range(compDS, vtk::CompositeDataSetOptions::SkipEmptyNodes); + * - Read-only -- reference types not supported. + * - vtkDataObjectTree (`#include `) + * - vtk::DataObjectTreeOptions: + * None, SkipEmptyNodes, VisitOnlyLeaves, TraverseSubTree. + * - Ex. vtk::Range(dObjTree, vtk::DataObjectTreeOptions::TraverseSubTree | + * vtk::DataObjectTreeOptions::SkipEmptyNodes); + * - Read-only -- reference types not supported. * * Usage: * @@ -53,20 +64,22 @@ namespace vtk * * // or: * - * auto range = vtk::Range(myCollection); + * using Opts = vtk::vtkDataObjectTreeOptions; + * auto range = vtk::Range(dataObjTree, + * Opts::TraverseSubTree | Opts::VisitOnlyLeaves); * some_algo(range.begin(), range.end()); * * ``` */ -template -auto Range(IterablePtr iterable) +template +auto Range(IterablePtr iterable, Options&&... opts) -> typename detail::IterableTraits< typename detail::StripPointers::type >::RangeType { using Iterable = typename detail::StripPointers::type; using RangeType = typename detail::IterableTraits::RangeType; - return RangeType{iterable}; + return RangeType{iterable, std::forward(opts)...}; } } // end namespace vtk diff --git a/Common/Core/vtkRangeIterableTraits.h b/Common/Core/vtkRangeIterableTraits.h new file mode 100644 index 00000000000..af3a91e8f69 --- /dev/null +++ b/Common/Core/vtkRangeIterableTraits.h @@ -0,0 +1,72 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: vtkRangeIterableTraits.h + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm 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 vtkRangeIterableTraits_h +#define vtkRangeIterableTraits_h + +class vtkCollection; +class vtkCompositeDataSet; +class vtkDataObjectTree; + +namespace vtk +{ +namespace detail +{ + +template struct CollectionRange; + +struct CompositeDataSetRange; +struct DataObjectTreeRange; + +//------------------------------------------------------------------------------ +// DeduceRangeType: +// These function signatures define a mapping from an Iterable (e.g. vtkObject) +// to a RangeType (e.g. the for-range iterable object). +// They are not implemented, as only the signatures are important. Classes used +// should only be forward declared in this header. +// Since classes are only forward declared, the argument type should be const& +// qualified, and the return type should be a reference. + +// vtkCollection subclasses --> CollectionRange +template ::value + >::type> +CollectionRange& DeduceRangeType(const CollectionType&); + +// vtkCompositeDataSet --> CompositeDataSetRange +CompositeDataSetRange& DeduceRangeType(const vtkCompositeDataSet&); + +// vtkDataObjectTree --> DataObjectTreeRange +DataObjectTreeRange& DeduceRangeType(const vtkDataObjectTree&); + +// Traits class that defines a RangeType corresponding to the iterable range +// type most appropriate for Iterable. +template +struct IterableTraits +{ +private: + using RangeTypeInternal = + decltype(vtk::detail::DeduceRangeType(std::declval())); +public: + using RangeType = typename std::decay::type; +}; + +} +} + +#endif // vtkRangeIterableTraits_h + +// VTK-HeaderTest-Exclude: vtkRangeIterableTraits.h diff --git a/Common/Core/vtkSetGet.h b/Common/Core/vtkSetGet.h index dc810c5a227..54ba53b2b31 100644 --- a/Common/Core/vtkSetGet.h +++ b/Common/Core/vtkSetGet.h @@ -31,6 +31,7 @@ #include "vtkSystemIncludes.h" #include #include +#include // for std::underlying type. //---------------------------------------------------------------------------- // Check for unsupported old compilers. @@ -1020,5 +1021,45 @@ virtual double *Get##name() VTK_SIZEHINT(2)\ # define VTK_FALLTHROUGH ((void)0) #endif +//---------------------------------------------------------------------------- +// Macro to generate bitflag operators for C++11 scoped enums. + +#define VTK_GENERATE_BITFLAG_OPS(EnumType) \ + inline EnumType operator|(EnumType f1, EnumType f2) \ + { \ + using T = typename std::underlying_type::type; \ + return static_cast(static_cast(f1) | static_cast(f2)); \ + } \ + inline EnumType operator&(EnumType f1, EnumType f2) \ + { \ + using T = typename std::underlying_type::type; \ + return static_cast(static_cast(f1) & static_cast(f2)); \ + } \ + inline EnumType operator^(EnumType f1, EnumType f2) \ + { \ + using T = typename std::underlying_type::type; \ + return static_cast(static_cast(f1) ^ static_cast(f2)); \ + } \ + inline EnumType operator~(EnumType f1) \ + { \ + using T = typename std::underlying_type::type; \ + return static_cast(~static_cast(f1)); \ + } \ + inline EnumType& operator|=(EnumType &f1, EnumType f2) \ + { \ + using T = typename std::underlying_type::type; \ + return f1 = static_cast(static_cast(f1) | static_cast(f2)); \ + } \ + inline EnumType& operator&=(EnumType &f1, EnumType f2) \ + { \ + using T = typename std::underlying_type::type; \ + return f1 = static_cast(static_cast(f1) & static_cast(f2)); \ + } \ + inline EnumType& operator^=(EnumType &f1, EnumType f2) \ + { \ + using T = typename std::underlying_type::type; \ + return f1 = static_cast(static_cast(f1) ^ static_cast(f2)); \ + } + #endif // VTK-HeaderTest-Exclude: vtkSetGet.h diff --git a/Common/Core/vtkSmartPointer.h b/Common/Core/vtkSmartPointer.h index 1582788b3bd..9c8f8891726 100644 --- a/Common/Core/vtkSmartPointer.h +++ b/Common/Core/vtkSmartPointer.h @@ -55,6 +55,7 @@ public: vtkSmartPointer(const vtkSmartPointer& r): vtkSmartPointerBase(CheckType(r.GetPointer())) {} +#ifndef __VTK_WRAP__ /** * Move the contents of @a r into @a this. */ @@ -62,6 +63,7 @@ public: typename = typename std::enable_if::value>::type> vtkSmartPointer(vtkSmartPointer&& r) noexcept : vtkSmartPointerBase(std::move(r)) {} +#endif //@{ /** diff --git a/Common/Core/vtkSmartPointerBase.h b/Common/Core/vtkSmartPointerBase.h index 24d44f42dcc..a06a552b2f0 100644 --- a/Common/Core/vtkSmartPointerBase.h +++ b/Common/Core/vtkSmartPointerBase.h @@ -48,6 +48,7 @@ public: */ vtkSmartPointerBase(const vtkSmartPointerBase& r); +#ifndef __VTK_WRAP__ /** * Move the pointee from @a r into @a this and reset @ r. */ @@ -56,6 +57,7 @@ public: { r.Object = nullptr; } +#endif // __VTK_WRAP__ /** * Destroy smart pointer and remove the reference to its object. diff --git a/Common/DataModel/CMakeLists.txt b/Common/DataModel/CMakeLists.txt index 469870cf137..9ed1e569fc6 100644 --- a/Common/DataModel/CMakeLists.txt +++ b/Common/DataModel/CMakeLists.txt @@ -232,7 +232,9 @@ set(template_classes set(headers vtkCellType.h vtkColor.h + vtkCompositeDataSetRange.h vtkDataArrayDispatcher.h + vtkDataObjectTreeRange.h vtkDispatcher.h vtkDispatcher_Private.h vtkDoubleDispatcher.h diff --git a/Common/DataModel/Testing/Cxx/CMakeLists.txt b/Common/DataModel/Testing/Cxx/CMakeLists.txt index 7cd91efb343..b0a87c53411 100644 --- a/Common/DataModel/Testing/Cxx/CMakeLists.txt +++ b/Common/DataModel/Testing/Cxx/CMakeLists.txt @@ -8,9 +8,11 @@ vtk_add_test_cxx(vtkCommonDataModelCxxTests tests TestAMRBox.cxx TestBiQuadraticQuad.cxx TestCompositeDataSets.cxx + TestCompositeDataSetRange.cxx TestComputeBoundingSphere.cxx TestDataArrayDispatcher.cxx TestDataObject.cxx + TestDataObjectTreeRange.cxx TestDispatchers.cxx TestFieldList.cxx TestGenericCell.cxx diff --git a/Common/DataModel/Testing/Cxx/TestCompositeDataSetRange.cxx b/Common/DataModel/Testing/Cxx/TestCompositeDataSetRange.cxx new file mode 100644 index 00000000000..7df5c3125fa --- /dev/null +++ b/Common/DataModel/Testing/Cxx/TestCompositeDataSetRange.cxx @@ -0,0 +1,164 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: TestCompositeDataSetRange.cxx + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm 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 +#include +#include +#include +#include +#include + +#define TEST_FAIL(msg) \ + std::cerr << "Test failed! " msg << "\n"; \ + return false + +namespace { + +// Test that the for-range iterators behave the same as the regular iterators. +bool TestConfig(vtkCompositeDataSet *cds, + vtk::CompositeDataSetOptions opts) +{ + using SmartIterator = vtkSmartPointer; + using Opts = vtk::CompositeDataSetOptions; + + auto refIter = SmartIterator::Take(cds->NewIterator()); + refIter->SetSkipEmptyNodes((opts & Opts::SkipEmptyNodes) != Opts::None); + refIter->InitTraversal(); + + for (auto dObj : vtk::Range(cds, opts)) + { + if (refIter->IsDoneWithTraversal()) + { + TEST_FAIL("vtkCompositeIterator finished before Range iterator."); + } + if (dObj != refIter->GetCurrentDataObject()) + { + TEST_FAIL("Range iterator does not match vtkCompositeDataIterator."); + } + + refIter->GoToNextItem(); + } + + if (!refIter->IsDoneWithTraversal()) + { + TEST_FAIL("Range iterator did not completely traverse composite dataset."); + } + + return true; +} + +bool TestOptions(vtkCompositeDataSet *cds) +{ + using Opts = vtk::CompositeDataSetOptions; + + if (!TestConfig(cds, Opts::None)) + { + TEST_FAIL("Error while testing options 'None'."); + } + if (!TestConfig(cds, Opts::SkipEmptyNodes)) + { + TEST_FAIL("Error while testing options 'SkipEmptyNodes'."); + } + + return true; +} + +// Construct the following hierarchy for testing: +// M = MBDS; P = PolyData; 0 = null dataset +// +// ------------------------M------------------------ // depth 0 +// | | | | +// P 0 -------------------M-- M // depth 1 +// | | | | | +// -----M----- 0 P ------M ------------M // depth 2 +// | | | | | | | +// 0 0 0 P 0 ------M----- 0 // depth 3 +// | | | +// M 0 P // depth 4 +// | +// P // depth 5 +// +vtkSmartPointer CreateDataSet() +{ + auto addPolyData = [](unsigned int blockNum, vtkMultiBlockDataSet *mbds) + -> vtkSmartPointer + { + vtkNew pd; + mbds->SetBlock(blockNum, pd); + return pd; + }; + + auto addMultiBlock = [](unsigned int blockNum, vtkMultiBlockDataSet *mbds) + -> vtkSmartPointer + { + auto newMbds = vtkSmartPointer::New(); + mbds->SetBlock(blockNum, newMbds); + return newMbds; + }; + + auto addNullDataSet = [](unsigned int blockNum, + vtkMultiBlockDataSet *mbds) -> void + { + mbds->SetBlock(blockNum, nullptr); + }; + + auto cds00 = vtkSmartPointer::New(); + cds00->SetNumberOfBlocks(4); + addPolyData(0, cds00); + addNullDataSet(1, cds00); + auto cds10 = addMultiBlock(2, cds00); + auto cds11 = addMultiBlock(3, cds00); + + cds10->SetNumberOfBlocks(4); + auto cds20 = addMultiBlock(0, cds10); + addNullDataSet(1, cds10); + addPolyData(2, cds10); + auto cds21 = addMultiBlock(3, cds10); + + cds11->SetNumberOfBlocks(1); + auto cds22 = addMultiBlock(0, cds11); + + cds20->SetNumberOfBlocks(3); + addNullDataSet(0, cds20); + addNullDataSet(1, cds20); + addNullDataSet(2, cds20); + + cds21->SetNumberOfBlocks(2); + addPolyData(0, cds21); + addNullDataSet(1, cds21); + + cds22->SetNumberOfBlocks(2); + auto cds30 = addMultiBlock(0, cds22); + addNullDataSet(1, cds22); + + cds30->SetNumberOfBlocks(3); + auto cds40 = addMultiBlock(0, cds30); + addNullDataSet(1, cds30); + addPolyData(2, cds30); + + cds40->SetNumberOfBlocks(1); + addPolyData(0, cds40); + + // move needed to silence warnings while calling the New->SmartPointer ctor. + return std::move(cds00); +} + +} // end anon namespace + +int TestCompositeDataSetRange(int, char*[]) +{ + auto cds = CreateDataSet(); + return TestOptions(cds) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/Common/DataModel/Testing/Cxx/TestDataObjectTreeRange.cxx b/Common/DataModel/Testing/Cxx/TestDataObjectTreeRange.cxx new file mode 100644 index 00000000000..f2c7dc1ab41 --- /dev/null +++ b/Common/DataModel/Testing/Cxx/TestDataObjectTreeRange.cxx @@ -0,0 +1,174 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: TestDataObjectTreeRange.cxx + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm 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 +#include +#include +#include +#include +#include + +#define TEST_FAIL(msg) \ + std::cerr << "Test failed! " msg << "\n"; \ + return false + +namespace { + +// Test that the for-range iterators behave the same as the regular iterators. +bool TestConfig(vtkDataObjectTree *cds, + vtk::DataObjectTreeOptions opts) +{ + using SmartIterator = vtkSmartPointer; + using Opts = vtk::DataObjectTreeOptions; + + auto refIter = SmartIterator::Take(cds->NewTreeIterator()); + refIter->SetSkipEmptyNodes((opts & Opts::SkipEmptyNodes) != Opts::None); + refIter->SetVisitOnlyLeaves((opts & Opts::VisitOnlyLeaves) != Opts::None); + refIter->SetTraverseSubTree((opts & Opts::TraverseSubTree) != Opts::None); + refIter->InitTraversal(); + + for (auto dObj : vtk::Range(cds, opts)) + { + if (refIter->IsDoneWithTraversal()) + { + TEST_FAIL("vtkDataObjectTreeIterator finished before Range iterator."); + } + if (dObj != refIter->GetCurrentDataObject()) + { + TEST_FAIL("Range iterator does not match vtkDataObjectTreeIterator."); + } + + refIter->GoToNextItem(); + } + + if (!refIter->IsDoneWithTraversal()) + { + TEST_FAIL("Range iterator did not completely traverse data object tree."); + } + + return true; +} + +bool TestOptions(vtkDataObjectTree *cds) +{ + using Opts = vtk::DataObjectTreeOptions; + + if (!TestConfig(cds, Opts::None)) + { + TEST_FAIL("Error while testing options 'None'."); + } + if (!TestConfig(cds, Opts::SkipEmptyNodes)) + { + TEST_FAIL("Error while testing options 'SkipEmptyNodes'."); + } + if (!TestConfig(cds, Opts::VisitOnlyLeaves)) + { + TEST_FAIL("Error while testing options 'VisitOnlyLeaves'."); + } + if (!TestConfig(cds, Opts::TraverseSubTree)) + { + TEST_FAIL("Error while testing options 'TraverseSubTree'."); + } + + return true; +} + +// Construct the following hierarchy for testing: +// M = MBDS; P = PolyData; 0 = null dataset +// +// ------------------------M------------------------ // depth 0 +// | | | | +// P 0 -------------------M-- M // depth 1 +// | | | | | +// -----M----- 0 P ------M ------------M // depth 2 +// | | | | | | | +// 0 0 0 P 0 ------M----- 0 // depth 3 +// | | | +// M 0 P // depth 4 +// | +// P // depth 5 +// +vtkSmartPointer CreateDataSet() +{ + auto addPolyData = [](unsigned int blockNum, vtkMultiBlockDataSet *mbds) + -> vtkSmartPointer + { + vtkNew pd; + mbds->SetBlock(blockNum, pd); + return pd; + }; + + auto addMultiBlock = [](unsigned int blockNum, vtkMultiBlockDataSet *mbds) + -> vtkSmartPointer + { + auto newMbds = vtkSmartPointer::New(); + mbds->SetBlock(blockNum, newMbds); + return newMbds; + }; + + auto addNullDataSet = [](unsigned int blockNum, + vtkMultiBlockDataSet *mbds) -> void + { + mbds->SetBlock(blockNum, nullptr); + }; + + auto cds00 = vtkSmartPointer::New(); + cds00->SetNumberOfBlocks(4); + addPolyData(0, cds00); + addNullDataSet(1, cds00); + auto cds10 = addMultiBlock(2, cds00); + auto cds11 = addMultiBlock(3, cds00); + + cds10->SetNumberOfBlocks(4); + auto cds20 = addMultiBlock(0, cds10); + addNullDataSet(1, cds10); + addPolyData(2, cds10); + auto cds21 = addMultiBlock(3, cds10); + + cds11->SetNumberOfBlocks(1); + auto cds22 = addMultiBlock(0, cds11); + + cds20->SetNumberOfBlocks(3); + addNullDataSet(0, cds20); + addNullDataSet(1, cds20); + addNullDataSet(2, cds20); + + cds21->SetNumberOfBlocks(2); + addPolyData(0, cds21); + addNullDataSet(1, cds21); + + cds22->SetNumberOfBlocks(2); + auto cds30 = addMultiBlock(0, cds22); + addNullDataSet(1, cds22); + + cds30->SetNumberOfBlocks(3); + auto cds40 = addMultiBlock(0, cds30); + addNullDataSet(1, cds30); + addPolyData(2, cds30); + + cds40->SetNumberOfBlocks(1); + addPolyData(0, cds40); + + // move needed to silence warnings while calling the New->SmartPointer ctor. + return std::move(cds00); +} + +} // end anon namespace + +int TestDataObjectTreeRange(int, char*[]) +{ + auto cds = CreateDataSet(); + return TestOptions(cds) ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/Common/DataModel/vtkCompositeDataSetRange.h b/Common/DataModel/vtkCompositeDataSetRange.h new file mode 100644 index 00000000000..51ed699faa8 --- /dev/null +++ b/Common/DataModel/vtkCompositeDataSetRange.h @@ -0,0 +1,318 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: vtkCompositeDataSetRange.h + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm 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 vtkCompositeDataSetRange_h +#define vtkCompositeDataSetRange_h + +#include "vtkCompositeDataIterator.h" +#include "vtkCompositeDataSet.h" +#include "vtkMeta.h" +#include "vtkRange.h" +#include "vtkSmartPointer.h" + +#ifndef __VTK_WRAP__ + +namespace vtk +{ + +// Pass these to vtk::Range(cds, options): +enum class CompositeDataSetOptions : unsigned int +{ + None = 0, + SkipEmptyNodes = 1 << 1 // Skip null datasets. +}; + +} // end namespace vtk (for bitflag op definition) + +VTK_GENERATE_BITFLAG_OPS(vtk::CompositeDataSetOptions) + +namespace vtk +{ + +namespace detail +{ + +struct CompositeDataSetRange; +struct CompositeDataSetIterator; + +//------------------------------------------------------------------------------ +// vtkCompositeDataSet iterator. Reference, value, and pointer types are all +// `vtkDataObject*` since: +// a) values: vtkDataObject* instead of vtkDataObject because vtkObjects can't +// be copied/assigned. +// b) references: TODO These could be implemented if needed, but it's a lot of +// work and greatly complicates usage/implementation -- See the constraints on +// the DataArrayTupleRange for example. Unless this is implemented, these +// containers are read only. +// c) pointers: Returning ItemType** from operator-> would be useless. +// +// There are no const_reference, etc, since VTK is not const correct and marking +// vtkObjects consts makes them unusable. +struct CompositeDataSetIterator : + public std::iterator +{ +private: + using Superclass = std::iterator; + using InternalIterator = vtkCompositeDataIterator; + using SmartIterator = vtkSmartPointer; + +public: + using iterator_category = typename Superclass::iterator_category; + using value_type = typename Superclass::value_type; + using difference_type = typename Superclass::difference_type; + using pointer = typename Superclass::pointer; + using reference = typename Superclass::reference; + + CompositeDataSetIterator(const CompositeDataSetIterator& o) noexcept + : Iterator(o.Iterator ? SmartIterator::Take(o.Iterator->NewInstance()) + : nullptr) + { + this->CopyState(o.Iterator); + } + + CompositeDataSetIterator(CompositeDataSetIterator&&) noexcept = default; + + CompositeDataSetIterator& operator=(const CompositeDataSetIterator& o) noexcept + { + this->Iterator = o.Iterator ? SmartIterator::Take(o.Iterator->NewInstance()) + : nullptr; + this->CopyState(o.Iterator); + return *this; + } + + CompositeDataSetIterator& operator=(CompositeDataSetIterator&& o) noexcept + { + this->Iterator = std::move(o.Iterator); + return *this; + } + + CompositeDataSetIterator& operator++() noexcept // prefix + { + this->Increment(); + return *this; + } + + CompositeDataSetIterator operator++(int) noexcept // postfix + { + CompositeDataSetIterator other(*this); + this->Increment(); + return other; + } + + reference operator*() const noexcept + { + return this->GetData(); + } + + pointer operator->() const noexcept + { + return this->GetData(); + } + + friend bool operator==(const CompositeDataSetIterator& lhs, + const CompositeDataSetIterator& rhs) noexcept + { + // A null internal iterator means it is an 'end' sentinal. + InternalIterator *l = lhs.Iterator; + InternalIterator *r = rhs.Iterator; + + if (!r && !l) + { // end == end + return true; + } + else if (!r) + { // right is end + return l->IsDoneWithTraversal() != 0; + } + else if (!l) + { // left is end + return r->IsDoneWithTraversal() != 0; + } + else + { // Both iterators are valid, check unique idx: + return r->GetCurrentFlatIndex() == l->GetCurrentFlatIndex(); + } + } + + friend bool operator!=(const CompositeDataSetIterator& lhs, + const CompositeDataSetIterator& rhs) noexcept + { + return !(lhs == rhs); // let the compiler handle this one =) + } + + friend void swap(CompositeDataSetIterator& lhs, + CompositeDataSetIterator& rhs) noexcept + { + using std::swap; + swap(lhs.Iterator, rhs.Iterator); + } + + friend struct CompositeDataSetRange; + +protected: + // Note: This takes ownership of iter and manages its lifetime. + // Iter should not be used past this point by the caller. + CompositeDataSetIterator(SmartIterator &&iter) noexcept + : Iterator(std::move(iter)) + { + } + + // Note: Iterators constructed using this ctor will be considered + // 'end' iterators via a sentinal pattern. + CompositeDataSetIterator() noexcept : Iterator(nullptr) {} + +private: + void CopyState(InternalIterator *source) + { + if (source) + { + assert(this->Iterator != nullptr); + this->Iterator->SetDataSet(source->GetDataSet()); + this->Iterator->SetSkipEmptyNodes(source->GetSkipEmptyNodes()); + this->Iterator->InitTraversal(); + this->AdvanceTo(source->GetCurrentFlatIndex()); + } + } + + void AdvanceTo(const unsigned int flatIdx) + { + assert(this->Iterator != nullptr); + assert(this->Iterator->GetCurrentFlatIndex() <= flatIdx); + while (this->Iterator->GetCurrentFlatIndex() < flatIdx) + { + this->Increment(); + } + } + + void Increment() + { + assert(this->Iterator != nullptr); + assert(!this->Iterator->IsDoneWithTraversal()); + this->Iterator->GoToNextItem(); + } + + vtkDataObject* GetData() const + { + assert(this->Iterator != nullptr); + assert(!this->Iterator->IsDoneWithTraversal()); + return this->Iterator->GetCurrentDataObject(); + } + + mutable SmartIterator Iterator; +}; + +//------------------------------------------------------------------------------ +// CompositeDataSet range proxy. +// The const_iterators/references are the same as the non-const versions, since +// vtkObjects marked const are unusable. +struct CompositeDataSetRange +{ +private: + using InternalIterator = vtkCompositeDataIterator; + using SmartIterator = vtkSmartPointer; + +public: + using size_type = int; + using iterator = CompositeDataSetIterator; + using const_iterator = CompositeDataSetIterator; + using reference = vtkDataObject*; + using const_reference = vtkDataObject*; + using value_type = vtkDataObject*; + + CompositeDataSetRange(vtkCompositeDataSet *cds, + CompositeDataSetOptions opts = CompositeDataSetOptions::None) noexcept + : CompositeDataSet(cds) + , Options(opts) + { + assert(this->CompositeDataSet); + } + + vtkCompositeDataSet* GetCompositeDataSet() const noexcept + { + return this->CompositeDataSet; + } + + CompositeDataSetOptions GetOptions() const noexcept + { + return this->Options; + } + + // This is O(N), since the size requires traversal due to various options. + size_type size() const noexcept + { + size_type result = 0; + auto iter = this->NewIterator(); + iter->InitTraversal(); + while (!iter->IsDoneWithTraversal()) + { + ++result; + iter->GoToNextItem(); + } + return result; + } + + iterator begin() const + { + return CompositeDataSetIterator{this->NewIterator()}; + } + + iterator end() const + { + return CompositeDataSetIterator{}; + } + + // Note: These return mutable objects because const vtkObject are unusable. + const_iterator cbegin() const + { + return CompositeDataSetIterator{this->NewIterator()}; + } + + // Note: These return mutable objects because const vtkObjects are unusable. + const_iterator cend() const + { + return CompositeDataSetIterator{}; + } + +private: + SmartIterator NewIterator() const + { + using Opts = vtk::CompositeDataSetOptions; + + auto result = SmartIterator::Take(this->CompositeDataSet->NewIterator()); + result->SetSkipEmptyNodes((this->Options & Opts::SkipEmptyNodes) != Opts::None); + result->InitTraversal(); + return result; + } + + mutable vtkSmartPointer CompositeDataSet; + CompositeDataSetOptions Options; +}; + +} +} // end namespace vtk::detail + +#endif // __VTK_WRAP__ + +#endif // vtkCompositeDataSetRange_h + +// VTK-HeaderTest-Exclude: vtkCompositeDataSetRange.h diff --git a/Common/DataModel/vtkDataObjectTreeRange.h b/Common/DataModel/vtkDataObjectTreeRange.h new file mode 100644 index 00000000000..95fc450245f --- /dev/null +++ b/Common/DataModel/vtkDataObjectTreeRange.h @@ -0,0 +1,326 @@ +/*========================================================================= + + Program: Visualization Toolkit + Module: vtkDataObjectTreeRange.h + + Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen + All rights reserved. + See Copyright.txt or http://www.kitware.com/Copyright.htm 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 vtkDataObjectTreeRange_h +#define vtkDataObjectTreeRange_h + +#include "vtkDataObjectTreeIterator.h" +#include "vtkDataObjectTree.h" +#include "vtkMeta.h" +#include "vtkRange.h" +#include "vtkSmartPointer.h" + +#include + +#ifndef __VTK_WRAP__ + +namespace vtk +{ + +// Pass these to vtk::Range(cds, options): +enum class DataObjectTreeOptions : unsigned int +{ + None = 0, + SkipEmptyNodes = 1 << 1, // Skip null datasets. + VisitOnlyLeaves = 1 << 2, // Skip child composite datasets. + TraverseSubTree = 1 << 3, // Descend into child composite datasets. +}; + +} // end namespace vtk (for bitflag op definition) + +VTK_GENERATE_BITFLAG_OPS(vtk::DataObjectTreeOptions) + +namespace vtk +{ + +namespace detail +{ + +struct DataObjectTreeRange; +struct DataObjectTreeIterator; + +//------------------------------------------------------------------------------ +// vtkDataObjectTree iterator. Reference, value, and pointer types are all +// `vtkDataObject*` since: +// a) values: vtkDataObject* instead of vtkDataObject because vtkObjects can't +// be copied/assigned. +// b) references: TODO These could be implemented if needed, but it's a lot of +// work and greatly complicates usage/implementation -- See the constraints on +// the DataArrayTupleRange for example. Unless this is implemented, these +// containers are read only. +// c) pointers: Returning ItemType** from operator-> would be useless. +// +// There are no const_reference, etc, since VTK is not const correct and marking +// vtkObjects consts makes them unusable. +struct DataObjectTreeIterator : + public std::iterator +{ +private: + using Superclass = std::iterator; + using InternalIterator = vtkDataObjectTreeIterator; + using SmartIterator = vtkSmartPointer; + +public: + using iterator_category = typename Superclass::iterator_category; + using value_type = typename Superclass::value_type; + using difference_type = typename Superclass::difference_type; + using pointer = typename Superclass::pointer; + using reference = typename Superclass::reference; + + DataObjectTreeIterator(const DataObjectTreeIterator& o) noexcept + : Iterator(o.Iterator ? SmartIterator::Take(o.Iterator->NewInstance()) + : nullptr) + { + this->CopyState(o.Iterator); + } + + DataObjectTreeIterator(DataObjectTreeIterator&&) noexcept = default; + + DataObjectTreeIterator& operator=(const DataObjectTreeIterator& o) noexcept + { + this->Iterator = o.Iterator ? SmartIterator::Take(o.Iterator->NewInstance()) + : nullptr; + this->CopyState(o.Iterator); + return *this; + } + + DataObjectTreeIterator& operator=(DataObjectTreeIterator&& o) noexcept + { + this->Iterator = std::move(o.Iterator); + return *this; + } + + DataObjectTreeIterator& operator++() noexcept // prefix + { + this->Increment(); + return *this; + } + + DataObjectTreeIterator operator++(int) noexcept // postfix + { + DataObjectTreeIterator other(*this); + this->Increment(); + return other; + } + + reference operator*() const noexcept + { + return this->GetData(); + } + + pointer operator->() const noexcept + { + return this->GetData(); + } + + friend bool operator==(const DataObjectTreeIterator& lhs, + const DataObjectTreeIterator& rhs) noexcept + { + // A null internal iterator means it is an 'end' sentinal. + InternalIterator *l = lhs.Iterator; + InternalIterator *r = rhs.Iterator; + + if (!r && !l) + { // end == end + return true; + } + else if (!r) + { // right is end + return l->IsDoneWithTraversal() != 0; + } + else if (!l) + { // left is end + return r->IsDoneWithTraversal() != 0; + } + else + { // Both iterators are valid, check unique idx: + return r->GetCurrentFlatIndex() == l->GetCurrentFlatIndex(); + } + } + + friend bool operator!=(const DataObjectTreeIterator& lhs, + const DataObjectTreeIterator& rhs) noexcept + { + return !(lhs == rhs); // let the compiler handle this one =) + } + + friend void swap(DataObjectTreeIterator& lhs, + DataObjectTreeIterator& rhs) noexcept + { + using std::swap; + swap(lhs.Iterator, rhs.Iterator); + } + + friend struct DataObjectTreeRange; + +protected: + // Note: This takes ownership of iter and manages its lifetime. + // Iter should not be used past this point by the caller. + DataObjectTreeIterator(SmartIterator &&iter) noexcept + : Iterator(std::move(iter)) + { + } + + // Note: Iterators constructed using this ctor will be considered + // 'end' iterators via a sentinal pattern. + DataObjectTreeIterator() noexcept : Iterator{nullptr} {} + +private: + void CopyState(InternalIterator *source) + { + if (source) + { + assert(this->Iterator != nullptr); + this->Iterator->SetDataSet(source->GetDataSet()); + this->Iterator->SetSkipEmptyNodes(source->GetSkipEmptyNodes()); + this->Iterator->SetVisitOnlyLeaves(source->GetVisitOnlyLeaves()); + this->Iterator->SetTraverseSubTree(source->GetTraverseSubTree()); + this->Iterator->InitTraversal(); + this->AdvanceTo(source->GetCurrentFlatIndex()); + } + } + + void AdvanceTo(const unsigned int flatIdx) + { + assert(this->Iterator != nullptr); + assert(this->Iterator->GetCurrentFlatIndex() <= flatIdx); + while (this->Iterator->GetCurrentFlatIndex() < flatIdx) + { + this->Increment(); + } + } + + void Increment() + { + assert(this->Iterator != nullptr); + assert(!this->Iterator->IsDoneWithTraversal()); + this->Iterator->GoToNextItem(); + } + + vtkDataObject* GetData() const + { + assert(this->Iterator != nullptr); + assert(!this->Iterator->IsDoneWithTraversal()); + return this->Iterator->GetCurrentDataObject(); + } + + mutable SmartIterator Iterator; +}; + +//------------------------------------------------------------------------------ +// DataObjectTree range proxy. +// The const_iterators/references are the same as the non-const versions, since +// vtkObjects marked const are unusable. +struct DataObjectTreeRange +{ +private: + using InternalIterator = vtkDataObjectTreeIterator; + using SmartIterator = vtkSmartPointer; + +public: + using size_type = int; + using iterator = DataObjectTreeIterator; + using const_iterator = DataObjectTreeIterator; + using reference = vtkDataObject*; + using const_reference = vtkDataObject*; + using value_type = vtkDataObject*; + + DataObjectTreeRange(vtkDataObjectTree *cds, + DataObjectTreeOptions opts = DataObjectTreeOptions::None) noexcept + : DataObjectTree(cds) + , Options(opts) + { + assert(this->DataObjectTree); + } + + vtkDataObjectTree* GetDataObjectTree() const noexcept + { + return this->DataObjectTree; + } + + DataObjectTreeOptions GetOptions() const noexcept + { + return this->Options; + } + + // This is O(N), since the size requires traversal due to various options. + size_type size() const noexcept + { + size_type result = 0; + auto iter = this->NewIterator(); + iter->InitTraversal(); + while (!iter->IsDoneWithTraversal()) + { + ++result; + iter->GoToNextItem(); + } + return result; + } + + iterator begin() const + { + return DataObjectTreeIterator{this->NewIterator()}; + } + + iterator end() const + { + return DataObjectTreeIterator{}; + } + + // Note: These return mutable objects because const vtkObject are unusable. + const_iterator cbegin() const + { + return DataObjectTreeIterator{this->NewIterator()}; + } + + // Note: These return mutable objects because const vtkObjects are unusable. + const_iterator cend() const + { + return DataObjectTreeIterator{}; + } + +private: + SmartIterator NewIterator() const + { + using Opts = vtk::DataObjectTreeOptions; + + auto result = SmartIterator::Take(this->DataObjectTree->NewTreeIterator()); + result->SetSkipEmptyNodes((this->Options & Opts::SkipEmptyNodes) != Opts::None); + result->SetVisitOnlyLeaves((this->Options & Opts::VisitOnlyLeaves) != Opts::None); + result->SetTraverseSubTree((this->Options & Opts::TraverseSubTree) != Opts::None); + result->InitTraversal(); + return result; + } + + mutable vtkSmartPointer DataObjectTree; + DataObjectTreeOptions Options; +}; + +} +} // end namespace vtk::detail + +#endif // __VTK_WRAP__ + +#endif // vtkDataObjectTreeRange_h + +// VTK-HeaderTest-Exclude: vtkDataObjectTreeRange.h diff --git a/IO/XML/vtkXMLPartitionedDataSetCollectionWriter.cxx b/IO/XML/vtkXMLPartitionedDataSetCollectionWriter.cxx index da5282c82a2..59e6de3c566 100644 --- a/IO/XML/vtkXMLPartitionedDataSetCollectionWriter.cxx +++ b/IO/XML/vtkXMLPartitionedDataSetCollectionWriter.cxx @@ -14,7 +14,7 @@ =========================================================================*/ #include "vtkXMLPartitionedDataSetCollectionWriter.h" -#include "vtkDataObjectTreeIterator.h" +#include "vtkDataObjectTreeRange.h" #include "vtkInformation.h" #include "vtkMultiBlockDataSet.h" #include "vtkObjectFactory.h" @@ -54,30 +54,20 @@ int vtkXMLPartitionedDataSetCollectionWriter::WriteComposite(vtkCompositeDataSet return 0; } + auto *dObjTree = static_cast(compositeData); + // Write each input. - vtkSmartPointer iter; - iter.TakeReference( - vtkDataObjectTree::SafeDownCast(compositeData)->NewTreeIterator()); - iter->VisitOnlyLeavesOff(); - iter->TraverseSubTreeOff(); - iter->SkipEmptyNodesOff(); - int toBeWritten = 0; - for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); - iter->GoToNextItem()) - { - toBeWritten++; - } + using Opts = vtk::DataObjectTreeOptions; + const auto dObjRange = vtk::Range(dObjTree, Opts::None); + int toBeWritten = static_cast(dObjRange.size()); float progressRange[2] = { 0.f, 0.f }; this->GetProgressRange(progressRange); int index = 0; int RetVal = 0; - for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); - iter->GoToNextItem(), index++) + for (vtkDataObject *curDO : dObjRange) { - vtkDataObject* curDO = iter->GetCurrentDataObject(); - if (curDO && curDO->IsA("vtkCompositeDataSet")) // if node is a supported composite dataset // note in structure file and recurse. @@ -113,7 +103,10 @@ int vtkXMLPartitionedDataSetCollectionWriter::WriteComposite(vtkCompositeDataSet } datasetXML->Delete(); } + + index++; } + return RetVal; } diff --git a/Rendering/Core/vtkCompositeDataDisplayAttributes.cxx b/Rendering/Core/vtkCompositeDataDisplayAttributes.cxx index c0496b49e48..4fb3283a3f5 100644 --- a/Rendering/Core/vtkCompositeDataDisplayAttributes.cxx +++ b/Rendering/Core/vtkCompositeDataDisplayAttributes.cxx @@ -15,9 +15,8 @@ #include "vtkBoundingBox.h" #include "vtkCompositeDataDisplayAttributes.h" -#include "vtkCompositeDataIterator.h" #include "vtkDataObjectTree.h" -#include "vtkDataObjectTreeIterator.h" +#include "vtkDataObjectTreeRange.h" #include "vtkDataSet.h" #include "vtkMath.h" #include "vtkMultiBlockDataSet.h" @@ -279,18 +278,11 @@ void vtkCompositeDataDisplayAttributes::ComputeVisibleBoundsInternal( vtkDataObjectTree *dObjTree = vtkDataObjectTree::SafeDownCast(dobj); if (dObjTree) { - auto iter = vtkSmartPointer::Take(dObjTree->NewTreeIterator()); - iter->TraverseSubTreeOff(); - iter->SkipEmptyNodesOn(); - iter->VisitOnlyLeavesOff(); // Visit nodes to maintain parent visibility. - for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem()) + using Opts = vtk::DataObjectTreeOptions; + for (vtkDataObject *child : vtk::Range(dObjTree, Opts::SkipEmptyNodes)) { - vtkDataObject *child = iter->GetCurrentDataObject(); - if (child) - { - vtkCompositeDataDisplayAttributes::ComputeVisibleBoundsInternal( - cda, child, bbox, blockVisible); - } + vtkCompositeDataDisplayAttributes::ComputeVisibleBoundsInternal( + cda, child, bbox, blockVisible); } } else if (dobj && blockVisible == true) @@ -326,14 +318,9 @@ vtkDataObject* vtkCompositeDataDisplayAttributes::DataObjectFromIndex( vtkDataObjectTree *dObjTree = vtkDataObjectTree::SafeDownCast(parent_obj); if (dObjTree) { - auto iter = vtkSmartPointer::Take(dObjTree->NewTreeIterator()); - iter->TraverseSubTreeOff(); - iter->VisitOnlyLeavesOff(); - iter->SkipEmptyNodesOff(); - - for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem()) + using Opts = vtk::DataObjectTreeOptions; + for (vtkDataObject *child : vtk::Range(dObjTree, Opts::None)) { - vtkDataObject *child = iter->GetCurrentDataObject(); if (child) { const auto data = vtkCompositeDataDisplayAttributes::DataObjectFromIndex( diff --git a/Rendering/Core/vtkGlyph3DMapper.cxx b/Rendering/Core/vtkGlyph3DMapper.cxx index c28804040a4..1b9556c2e57 100644 --- a/Rendering/Core/vtkGlyph3DMapper.cxx +++ b/Rendering/Core/vtkGlyph3DMapper.cxx @@ -20,9 +20,11 @@ #include "vtkCompositeDataDisplayAttributes.h" #include "vtkCompositeDataIterator.h" #include "vtkCompositeDataSet.h" +#include "vtkCompositeDataSetRange.h" #include "vtkDataArray.h" #include "vtkDataObjectTree.h" #include "vtkDataObjectTreeIterator.h" +#include "vtkDataObjectTreeRange.h" #include "vtkDataSetAttributes.h" #include "vtkInformation.h" #include "vtkInformationVector.h" @@ -619,23 +621,17 @@ bool vtkGlyph3DMapper::GetBoundsInternal(vtkDataSet* ds, double ds_bounds[6]) { if (sourceTableTree) { - vtkDataObjectTreeIterator *sTTIter = sourceTableTree->NewTreeIterator(); - sTTIter->SetTraverseSubTree(false); - sTTIter->SetVisitOnlyLeaves(false); - sTTIter->SetSkipEmptyNodes(false); + auto sTTRange = vtk::Range(sourceTableTree); + auto sTTIter = sTTRange.begin(); // Advance to first indexed dataset: - sTTIter->InitTraversal(); - int idx = 0; - for (; idx < indexRange[0]; ++idx) - { - sTTIter->GoToNextItem(); - } + int idx = indexRange[0]; + std::advance(sTTIter, idx); // Add the bounds from the appropriate datasets: while (idx <= indexRange[1]) { - vtkDataObject *sourceDObj = sTTIter->GetCurrentDataObject(); + vtkDataObject *sourceDObj = *sTTIter; // The source table tree may have composite nodes: vtkCompositeDataSet *sourceCDS = @@ -692,10 +688,9 @@ bool vtkGlyph3DMapper::GetBoundsInternal(vtkDataSet* ds, double ds_bounds[6]) } // Move to the next node in the source table tree. - sTTIter->GoToNextItem(); + ++sTTIter; ++idx; } - sTTIter->Delete(); } } else // non-source-table-tree table diff --git a/Rendering/OpenGL2/vtkCompositePolyDataMapper2.cxx b/Rendering/OpenGL2/vtkCompositePolyDataMapper2.cxx index c8fc51ebf4f..024efaf8a5a 100644 --- a/Rendering/OpenGL2/vtkCompositePolyDataMapper2.cxx +++ b/Rendering/OpenGL2/vtkCompositePolyDataMapper2.cxx @@ -21,11 +21,11 @@ #include "vtkColorTransferFunction.h" #include "vtkCommand.h" #include "vtkCompositeDataDisplayAttributes.h" -#include "vtkCompositeDataIterator.h" #include "vtkCompositeDataPipeline.h" #include "vtkCompositeDataSet.h" +#include "vtkCompositeDataSetRange.h" #include "vtkDataObjectTree.h" -#include "vtkDataObjectTreeIterator.h" +#include "vtkDataObjectTreeRange.h" #include "vtkFloatArray.h" #include "vtkHardwareSelector.h" #include "vtkImageData.h" @@ -1280,11 +1280,10 @@ bool vtkCompositePolyDataMapper2::GetIsOpaque() (this->ColorMode == VTK_COLOR_MODE_DEFAULT || this->ColorMode == VTK_COLOR_MODE_DIRECT_SCALARS)) { - vtkSmartPointer iter; - iter.TakeReference(input->NewIterator()); - for (iter->InitTraversal(); !iter->IsDoneWithTraversal(); iter->GoToNextItem()) + using Opts = vtk::CompositeDataSetOptions; + for (vtkDataObject *dObj : vtk::Range(input, Opts::SkipEmptyNodes)) { - vtkPolyData *pd = vtkPolyData::SafeDownCast(iter->GetCurrentDataObject()); + vtkPolyData *pd = vtkPolyData::SafeDownCast(dObj); if (pd) { int cellFlag; @@ -1841,16 +1840,9 @@ void vtkCompositePolyDataMapper2::BuildRenderValues( auto dObjTree = vtkDataObjectTree::SafeDownCast(dobj); if (dObjTree) { - using SmartDOTIter = vtkSmartPointer; - auto iter = SmartDOTIter::Take(dObjTree->NewTreeIterator()); - iter->TraverseSubTreeOff(); - iter->VisitOnlyLeavesOff(); - iter->SkipEmptyNodesOff(); - for (iter->InitTraversal(); - !iter->IsDoneWithTraversal(); - iter->GoToNextItem()) + using Opts = vtk::DataObjectTreeOptions; + for (vtkDataObject *child : vtk::Range(dObjTree, Opts::None)) { - auto child = iter->GetCurrentDataObject(); if (!child) { ++flat_index; -- GitLab