# for(vtkDataObject \*ds : vtk::Range(multiblock\_ds)) { .. }

**URL:** https://discourse.vtk.org/t/for-vtkdataobject-ds-vtk-range-multiblock-ds/262
**Category:** Development
**Created:** [February 12, 2019, 5:53pm UTC](https://discourse.vtk.org/t/for-vtkdataobject-ds-vtk-range-multiblock-ds/262 "2019-02-12T17:53:46Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![allison.vacanti](https://discourse.vtk.org/user_avatar/discourse.vtk.org/allison.vacanti/32/679_2.png) [@allison.vacanti](https://discourse.vtk.org/u/allison.vacanti)
#### Post date: [February 12, 2019, 5:53pm UTC](https://discourse.vtk.org/t/for-vtkdataobject-ds-vtk-range-multiblock-ds/262/1 "2019-02-12T17:53:46Z")

</div>

Similar to the `vtk::DataArrayTupleRange`, `vtk::DataArrayValueRange`, and `vtk::Range(vtkCollection*)` helpers [added recently](https://blog.kitware.com/c11-for-range-support-in-vtk/), it’s the `vtkCompositeDataSet` hierarchy’s turn to get C++11 for-range support:

[https://gitlab.kitware.com/vtk/vtk/merge\_requests/5158](https://gitlab.kitware.com/vtk/vtk/merge_requests/5158)

Compared with the usual way of traversing a multiblock dataset (`vtkCompositeDataSetIterator` / `vtkDataObjectTreeIterator`), the new syntax is much easier to use. For example, computing the bounds of a `vtkMultiBlockDataSet` used to look something like this:

```cpp
#include <vtkDataObjectTreeIterator.h>

auto *iter = mbds->NewTreeIterator(); // Get iterator
iter->SkipEmptyNodesOn(); // Configure
iter->TraverseSubTreeOn();
iter->VisitOnlyLeavesOn();
for (iter->InitTraversal(); // Traverse
     !iter->IsDoneWithTraversal();
     iter->GoToNextItem())
{
  vtkDataObject *dObj = iter->GetCurrentDataObject(); // Dereference
  /* Accumulate dObj's bounds */ // Work
}
iter->Delete(); // Clean-up

```

Compare this with the new for-range equivalent:

```cpp
#include <vtkDataObjectTreeRange.h>

using Opts = vtk::DataObjectTreeOptions;
for (vtkDataObject *dObj : vtk::Range(mbds, Opts::SkipEmptyNodes |
                                            Opts::TraverseSubTree |
                                            Opts::VisitOnlyLeaves))
{
  /* Accumulate dObj's bounds */
}

```

- The code is safer – less complexity means less to mess up:
  - There’s no need to manage the lifetime of the iterators. They are scoped to the for-loop and clean themselves up when destroyed. The only objects that exist in the new code are the input multiblock and the current leaf data object.
  - The old-style VTK iterator API is error prone for me – I tend to forget to negate the result of `IsDoneWithTraversal()` and things like that when using it. It’s too verbose for a very simple, common operation.

- The traversal options offered by the older iterators (SkipEmptyNodes, TraverseSubTree, VisitOnlyLeaves) are provided as enum flags that are passed into the `vtk::Range` function.
- The loop syntax is much, much easier to write.
- The intent of the loop is also easier to read – less clutter, more code that matters.

~~It is worthwhile to note that these do not replace the old iterators completely. They cannot be used with the `vtkCompositeDataSet` API to modify the structure of the dataset, nor do they provide the CurrentFlatIndex information. They are simply a convenient view into the component datasets.~~  
_Edit: This functionality was added in a followup patch. See the comments below._

---

<div class="post-metadata">

### Author: ![Haocheng\_Liu](https://discourse.vtk.org/user_avatar/discourse.vtk.org/haocheng_liu/32/258_2.png) [@Haocheng\_Liu](https://discourse.vtk.org/u/Haocheng_Liu)
#### Post date: [February 12, 2019, 11:07pm UTC](https://discourse.vtk.org/t/for-vtkdataobject-ds-vtk-range-multiblock-ds/262/2 "2019-02-12T23:07:10Z")

</div>

Nice! It can really alleviate the headache when traversing the vtk compsite dataset. I can help to convert the vtk examples once it’s merged.

---

<div class="post-metadata">

### Author: ![Haocheng\_Liu](https://discourse.vtk.org/user_avatar/discourse.vtk.org/haocheng_liu/32/258_2.png) [@Haocheng\_Liu](https://discourse.vtk.org/u/Haocheng_Liu)
#### Post date: [February 12, 2019, 11:13pm UTC](https://discourse.vtk.org/t/for-vtkdataobject-ds-vtk-range-multiblock-ds/262/3 "2019-02-12T23:13:39Z")

</div>

> [@allison.vacanti](#):
>
> It is worthwhile to note that these do not replace the old iterators completely. They cannot be used with the `vtkCompositeDataSet` API to modify the structure of the dataset, nor do they provide the CurrentFlatIndex information. They are simply a convenient view into the component datasets.

What’s the road block for using it to modify the structure of the dataset? For now in VTK, what’s the canonical way to modify a dataset(I assume through some existing filter)?

---

<div class="post-metadata">

### Author: ![allison.vacanti](https://discourse.vtk.org/user_avatar/discourse.vtk.org/allison.vacanti/32/679_2.png) [@allison.vacanti](https://discourse.vtk.org/u/allison.vacanti)
#### Post date: [February 13, 2019, 2:13pm UTC](https://discourse.vtk.org/t/for-vtkdataobject-ds-vtk-range-multiblock-ds/262/4 "2019-02-13T14:13:49Z")

</div>

Right now, if all you have is a `vtkCompositeDataSet` or `vtkDataObjectTree` pointer, the dataset’s structure can only be modified using these iterators, since there is no other API for setting the internal datasets:

[https://vtk.org/doc/nightly/html/classvtkCompositeDataSet.html](https://vtk.org/doc/nightly/html/classvtkCompositeDataSet.html)  
[https://vtk.org/doc/nightly/html/classvtkDataObjectTree.html](https://vtk.org/doc/nightly/html/classvtkDataObjectTree.html)

I have an idea that might actually allow this to work. I’ll see if I can get a patch together in the next few hours.

---

<div class="post-metadata">

### Author: ![allison.vacanti](https://discourse.vtk.org/user_avatar/discourse.vtk.org/allison.vacanti/32/679_2.png) [@allison.vacanti](https://discourse.vtk.org/u/allison.vacanti)
#### Post date: [February 13, 2019, 9:51pm UTC](https://discourse.vtk.org/t/for-vtkdataobject-ds-vtk-range-multiblock-ds/262/5 "2019-02-13T21:51:50Z")

</div>

I have a new MR that extends the existing functionality to do everything the older vtkCompositeDataIterators did, except iterate in reverse:

[https://gitlab.kitware.com/vtk/vtk/merge\_requests/5201](https://gitlab.kitware.com/vtk/vtk/merge_requests/5201)

The iterators now return a reference proxy object, instead of `vtkDataObject*`. This proxy may be used like a pointer, in which case it will forward the current `vtkDataObject*`. This means that the following code is still legal:

```cpp
for (auto node : vtk::Range(cds))                                            
{ // decltype(node) == CompositeDataSetNodeReference                         
  if (node) // same as: if (node.GetDataObject() != nullptr)
  {                                                                          
    assert(node->IsA("vtkDataObject")); // node.GetDataObject()->IsA(...)
    node = nullptr; // node.SetDataObject(nullptr)   
  }                                                                          
}                                                                            
                                                                             
for (vtkDataObject *dObj : vtk::Range(cds))                                  
{                                                                            
  // Work with dObj                                                          
}                                                                            

```

This allows for simple access to the objects in the composite dataset. If more advanced operations are required, the CompositeDataSetNodeReference can:

- Access the current vtkDataObject\*:
  - `vtkDataObject* NodeReference::GetDataObject() const`
  - `NodeReference::operator vtkDataObject* () const` (implicit conversion)
  - `vtkDataObject* NodeReference::operator->() const` (arrow operator)

- Replace the current vtkDataObject\* in the composite dataset:
  - `void NodeReference::SetDataObject(vtkDataObject*)`
  - `NodeReference& NodeReference::operator=(vtkDataObject*)` (assignment)

- SetGet the vtkDataObject at the same position in another composite dataset
  - `void NodeReference::SetDataObject(vtkCompositeDataSet*, vtkDataObject*)`
  - `vtkDataObject* NodeReference::GetDataObject(vtkCompositeDataSet*) const`

- Check and access node metadata (if any):
  - `bool NodeReference::HasMetaData() const`
  - `vtkInformation* NodeReference::GetMetaData() const`

- Get the current flat index within the parent range:
  - `unsigned int NodeReference::GetFlatIndex() const`

The NodeReference shares state with the OwnerType iterator that generates it. Incrementing or destroying the parent iterator will invalidate the reference. In debugging builds, these misuses will be caught via runtime assertions.

Several usages of `vtkCompositeDataIterator` have been ported to use the new range iteration syntax to improve testing and provide some examples. The unit tests for these ranges also show example usages of the new functionality.

---

<div class="post-metadata">

### Author: ![mwestphal](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mwestphal/32/19_2.png) [@mwestphal](https://discourse.vtk.org/u/mwestphal)
#### Post date: [February 14, 2019, 8:35am UTC](https://discourse.vtk.org/t/for-vtkdataobject-ds-vtk-range-multiblock-ds/262/6 "2019-02-14T08:35:45Z")

</div>

Will there be a blog at some point ?

Nice work !

---

<div class="post-metadata">

### Author: ![allison.vacanti](https://discourse.vtk.org/user_avatar/discourse.vtk.org/allison.vacanti/32/679_2.png) [@allison.vacanti](https://discourse.vtk.org/u/allison.vacanti)
#### Post date: [February 14, 2019, 1:06pm UTC](https://discourse.vtk.org/t/for-vtkdataobject-ds-vtk-range-multiblock-ds/262/7 "2019-02-14T13:06:19Z")

</div>

Thanks! No plans for a blog right now, but maybe after the implementation settles a bit I will.

---

<div class="post-metadata">

### Author: ![Haocheng\_Liu](https://discourse.vtk.org/user_avatar/discourse.vtk.org/haocheng_liu/32/258_2.png) [@Haocheng\_Liu](https://discourse.vtk.org/u/Haocheng_Liu)
#### Post date: [April 18, 2019, 3:51pm UTC](https://discourse.vtk.org/t/for-vtkdataobject-ds-vtk-range-multiblock-ds/262/8 "2019-04-18T15:51:18Z")

</div>

The pull request to update VTK examples is [here](https://github.com/lorensen/VTKExamples/pull/547). One thing I found is that you can not mix vtkCompositeDataSet/vtkDataObjectTree with vtkDataObjectTreeIterator/vtkCompositeDataSetIterator. And I think it makes sense which can catch run time error at compile time.
