# Upcoming changes to vtkCellArray

**URL:** https://discourse.vtk.org/t/upcoming-changes-to-vtkcellarray/2066
**Category:** Development
**Created:** [November 7, 2019, 10:08pm UTC](https://discourse.vtk.org/t/upcoming-changes-to-vtkcellarray/2066 "2019-11-07T22:08:28Z")
**Posts on this page:** 17
**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: [November 7, 2019, 10:08pm UTC](https://discourse.vtk.org/t/upcoming-changes-to-vtkcellarray/2066/1 "2019-11-07T22:08:28Z")

</div>

Over the next few days/weeks, we’ll be merging in some major changes to `vtkCellArray` to support new functionality. This involves some significant changes to the vtkCellArray’s internal data structures, but we’ve retained as much of the older API as possible.

The change is motivated by two goals:

1. Split the current connectivity array into Offsets and Connectivity. This will allow random-access directly into the cell array, and ease integration with other toolkits and rendering systems.

2. Allow the arrays to be stored as either 32-bit or 64-bit integers, regardless of VTK\_USE\_64BIT\_IDS. This will (a) allow smaller datasets to use less memory by switching to 32-bit arrays, and (b) allow better zero-copy integration with datasets that might be using a different sized integer than what VTK was built with. The API will still use vtkIdType.

We’ve provided legacy implementations for as much of the older API as possible, but in particular, GetPointer and WritePointer had to be completely removed, since they simply cannot be supported with the new internals. New methods (`ExportLegacyFormat`, `ImportLegacyFormat`, and `AppendLegacyFormat`) can be used to simplify porting to the new API.

A new preprocessor definition, `VTK_CELL_ARRAY_V2`, is defined when the new vtkCellArray API is active to make it easier to support both the old and new APIs in external projects. It can be used to switch between legacy and modern usages of the class.

Patches are ready for VTK proper, the WikiExamples repo, VTK’s remote modules, ParaView, ParaView’s VisitBridge.

The merge request tha updates VTK is here: [https://gitlab.kitware.com/vtk/vtk/merge\_requests/5682](https://gitlab.kitware.com/vtk/vtk/merge_requests/5682)

The new class documentation covers the changes, so I’ll just include that to give a summary of the changes:

# `vtkCellArray` class documentation

vtkCellArray stores dataset topologies as an explicit connectivity table  
listing the point ids that make up each cell.

Internally, the connectivity table is represented as two arrays: Offsets and  
Connectivity.

Offsets is an array of [numCells+1] values indicating the index in the  
Connectivity array where each cell’s points start. The last value is always  
the length of the Connectivity array.

The Connectivity array stores the lists of point ids for each cell.

Thus, for a dataset consisting of 2 triangles, a quad, and a line, the  
internal arrays will appear as follows:

```auto
Topology:
---------
Cell 0: Triangle | point ids: {0, 1, 2}
Cell 1: Triangle | point ids: {5, 7, 2}
Cell 2: Quad | point ids: {3, 4, 6, 7}
Cell 4: Line | point ids: {5, 8}

vtkCellArray (current):
-----------------------
Offsets: {0, 3, 6, 10, 12}
Connectivity: {0, 1, 2, 5, 7, 2, 3, 4, 6, 7, 5, 8}

```

While this class provides traversal methods (InitTraversal, GetNextCell),  
these are not thread-safe and are a bit difficult to use correctly as they  
do not use the typical VTK iterator API. Prefer to use a local  
vtkCellArrayIterator object, which can be obtained via:

```auto
auto iter = vtk::TakeSmartPointer(cellArray->NewIterator());
for (iter->GoToFirstCell(); !iter->IsDoneWithTraversal(); iter->GoToNextCell())
{
  // do work with iter
}

```

The internal arrays may store either 32- or 64-bit values, though most of the API  
will prefer to use vtkIdType to refer to items in these arrays. This enables  
significant memory savings when vtkIdType is 64-bit, but 32 bits are  
sufficient to store all of the values in the connectivity table. Using  
64-bit storage with a 32-bit vtkIdType is permitted, but values too large to  
fit in a 32-bit signed integer will be truncated when accessed through the  
API.

Methods for managing the storage type are:

- `bool IsStorage64Bit()`
- `void Use32BitStorage()`
- `void Use64BitStorage()`
- `void UseDefaultStorage() // Depends on vtkIdType`
- `bool CanConvertTo32BitStorage()`
- `bool CanConvertTo64BitStorage()`
- `bool CanConvertToDefaultStorage() // Depends on vtkIdType`
- `bool ConvertTo32BitStorage()`
- `bool ConvertTo64BitStorage()`
- `bool ConvertToDefaultStorage() // Depends on vtkIdType`
- `bool ConvertToSmallestStorage() // Depends on current values in arrays`

Note that some methods are still available that reflect the previous  
storage format of this data, which embedded the cell sizes into the  
Connectivity array:

```auto
vtkCellArray (legacy):
----------------------
Connectivity: {3, 0, 1, 2, 3, 5, 7, 2, 4, 3, 4, 6, 7, 2, 5, 8}
               |--Cell 0--||--Cell 1--||----Cell 2---||--C3-|

```

The methods require an external lookup table to allow random access, which  
was historically stored in the vtkCellTypes object. The following methods in  
vtkCellArray still support this style of indexing for compatibility  
purposes, but these are slow as they must perform some complex computations  
to convert the old “location” into the new “offset” and should be avoided.  
These methods (and their modern equivalents) are:

- GetCell (Prefer GetCellAtId)
- GetInsertLocation (Prefer GetNumberOfCells)
- GetTraversalLocation (Prefer GetTraversalCellId, or better, NewIterator)
- SetTraversalLocation (Prefer SetTraversalLocation, or better, NewIterator)
- ReverseCell (Prefer ReverseCellAtId)
- ReplaceCell (Prefer ReplaceCellAtId)
- SetCells (Use ImportLegacyFormat, or SetData)
- GetData (Use ExportLegacyFormat, or Get[Offsets|Connectivity]Array[|32|64])

Some other methods were completely removed, such as `GetPointer` /  
`WritePointer`, since they are simply not able to be emulated under the current  
design.

---

<div class="post-metadata">

### Author: ![Seun](https://discourse.vtk.org/user_avatar/discourse.vtk.org/seun/32/767_2.png) [@Seun](https://discourse.vtk.org/u/Seun)
#### Post date: [December 5, 2019, 4:25pm UTC](https://discourse.vtk.org/t/upcoming-changes-to-vtkcellarray/2066/2 "2019-12-05T16:25:57Z")

</div>

Hi Allison,  
Just a quick question, what effect does this have if any on the usage of a vtkCellLocator? If I have a polydata with its strips set to a vtkCellArray (using the updated format i.e both offsets and connectivity are built to create a valid vtkCellArray which is in turn set as the strip of the poly data), subsequently I set the vtkCellLocator’s Dataset to the polydata and turn on AutomaticOn and call buildLocator().

what I would like to know is is there anything special that I need to do regarding the new changes to vtkCellArray if I plan to use it along with a cell locator as described above.?

---

<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: [December 5, 2019, 4:30pm UTC](https://discourse.vtk.org/t/upcoming-changes-to-vtkcellarray/2066/3 "2019-12-05T16:30:26Z")

</div>

The `vtkCellLocator`s should work the same as before without any changes to your code.

---

<div class="post-metadata">

### Author: ![Seun](https://discourse.vtk.org/user_avatar/discourse.vtk.org/seun/32/767_2.png) [@Seun](https://discourse.vtk.org/u/Seun)
#### Post date: [December 5, 2019, 4:32pm UTC](https://discourse.vtk.org/t/upcoming-changes-to-vtkcellarray/2066/4 "2019-12-05T16:32:38Z")

</div>

Thanks for the expeditious reply.

---

<div class="post-metadata">

### Author: ![olesenm](https://discourse.vtk.org/user_avatar/discourse.vtk.org/olesenm/32/10443_2.png) [@olesenm](https://discourse.vtk.org/u/olesenm)
#### Post date: [January 20, 2020, 8:15pm UTC](https://discourse.vtk.org/t/upcoming-changes-to-vtkcellarray/2066/5 "2020-01-20T20:15:25Z")

</div>

> [@allison.vacanti](#):
>
> Internally, the connectivity table is represented as two arrays: Offsets and  
> Connectivity.
> 
> Offsets is an array of [numCells+1] values indicating the index in the  
> Connectivity array where each cell’s points start. The last value is always  
> the length of the Connectivity array.

The changes make a lot of sense. Is there anything similar to be expected regarding the handling of face/face-offfset for `vtkUnstructuredGrid`? I’m not really sure how it could be changed, but want to check before I start reworking my code that I have for [populating vtkCellArray manually](https://develop.openfoam.com/Development/openfoam/blob/master/src/fileFormats/vtk/part/foamVtuSizingTemplates.C#L640). Will need to juggle the allocation sizes accordingly, but only have `vtkCellArray` forward declared at that point…

---

<div class="post-metadata">

### Author: ![AllisonVacanti](https://discourse.vtk.org/user_avatar/discourse.vtk.org/allisonvacanti/32/2396_2.png) [@AllisonVacanti](https://discourse.vtk.org/u/AllisonVacanti)
#### Post date: [January 21, 2020, 5:29pm UTC](https://discourse.vtk.org/t/upcoming-changes-to-vtkcellarray/2066/6 "2020-01-21T17:29:13Z")

</div>

The polyhedral face data is stored the same as before, just translated into the new layout: Instead of inserting a cellSize prefix before the face data, the size is used to update the offsets array.

---

<div class="post-metadata">

### Author: ![dzenanz](https://discourse.vtk.org/user_avatar/discourse.vtk.org/dzenanz/32/212_2.png) [@dzenanz](https://discourse.vtk.org/u/dzenanz)
#### Post date: [May 8, 2020, 8:58pm UTC](https://discourse.vtk.org/t/upcoming-changes-to-vtkcellarray/2066/7 "2020-05-08T20:58:56Z")

</div>

In VTK 9.0, signature of `GetNextCell` has changed to require second parameter to be `const`, which makes it a breaking change. The following code no longer compiles:

```cpp
vtkIdType * indices;
vtkIdType numberOfPoints;
cellArray->InitTraversal();
cellArray->GetNextCell(numberOfPoints, indices);

```

to get it compiling with VTK 9.0, `indices` must be const:

```cpp
vtkIdType const * indices;
vtkIdType numberOfPoints;
cellArray->InitTraversal();
cellArray->GetNextCell(numberOfPoints, indices);

```

but the updated code does not compile with VTK 8.2.

Is this intended? For a traversal to work with both versions, is there anything more elegant than `#ifdef VTK_CELL_ARRAY_V2 ...`?

---

<div class="post-metadata">

### Author: ![AllisonVacanti](https://discourse.vtk.org/user_avatar/discourse.vtk.org/allisonvacanti/32/2396_2.png) [@AllisonVacanti](https://discourse.vtk.org/u/AllisonVacanti)
#### Post date: [May 8, 2020, 10:23pm UTC](https://discourse.vtk.org/t/upcoming-changes-to-vtkcellarray/2066/8 "2020-05-08T22:23:13Z")

</div>

> For a traversal to work with both versions, is there anything more elegant than `#ifdef VTK_CELL_ARRAY_V2 ...` ?

That’s the only way to have this work in both versions, unfortunately.

---

<div class="post-metadata">

### Author: ![pieper](https://discourse.vtk.org/user_avatar/discourse.vtk.org/pieper/32/17_2.png) [@pieper](https://discourse.vtk.org/u/pieper)
#### Post date: [October 12, 2021, 6:55pm UTC](https://discourse.vtk.org/t/upcoming-changes-to-vtkcellarray/2066/9 "2021-10-12T18:55:26Z")

</div>

Generally these changes to `vtkCellArray` seem very positive, but there was a regression that led to a bug in [SlicerDMRI](https://github.com/SlicerDMRI/SlicerDMRI). In earlier VTK versions, calling this method gave a pointer into the `vtkCellArray`

```auto
vtkIdTypeArray *cellArrayIds = cellArray->GetData();

```

but with the new API it returns a copy of the data using `ExportLegacyFormat` in the implementation.

This meant that our code, which operated no the `cellArrayIds` to add lines to the cell array, had no effect on the `vtkPolyData` and the lines were missing. After some investigation I was able to fix it with the patch linked below.

Realistically the change in `GetData` was an API regression because the behavior of the call changed. I’d argue that `vtkCellArray::GetData()` should have been removed along with `GetPointer` / `WritePointer` and replaced with a stub that generated a compile time error with a comment that described the replacement API and how to use it.

In addition, the current implementation of `GetData()` should have been renamed `GetLegacyDataCopy()`.

It’s probably not good to make such a change to the API now that it’s been released, but I wanted to flag this in case somebody else runs into a similar issue in the future.

Perhaps the best solution would be to mark `vtkCellArray::GetData()` as deprecated.

> <https://github.com/SlicerDMRI/SlicerDMRI/pull/151/files>
>
> The behavior of vtkCellArray::GetData changed with vtk9 such
> that is now return…s a copy of the data rather than the actual
> array, so manipulating it has no effect.
> 
> Instead now we must have the cell array import the legacy format.
> 
> This operation is no doubt slower but is a minimal change to restore
> funcationality. This code should really be threaded and reworked to
> use the new API if performance is critical.

---

<div class="post-metadata">

### Author: ![Yohann\_Bearzi](https://discourse.vtk.org/user_avatar/discourse.vtk.org/yohann_bearzi/32/671_2.png) [@Yohann\_Bearzi](https://discourse.vtk.org/u/Yohann_Bearzi)
#### Post date: [October 12, 2021, 7:01pm UTC](https://discourse.vtk.org/t/upcoming-changes-to-vtkcellarray/2066/10 "2021-10-12T19:01:42Z")

</div>

Why not updating the code in `SlicerDMRI` to use the new API instead to avoid an unnecessary copy? You can have access to the underlying arrays using `GetOffsetsArray` and `GetConnectivityArray`.

---

<div class="post-metadata">

### Author: ![pieper](https://discourse.vtk.org/user_avatar/discourse.vtk.org/pieper/32/17_2.png) [@pieper](https://discourse.vtk.org/u/pieper)
#### Post date: [October 12, 2021, 8:38pm UTC](https://discourse.vtk.org/t/upcoming-changes-to-vtkcellarray/2066/11 "2021-10-12T20:38:51Z")

</div>

> [@Yohann\_Bearzi](#):
>
> Why not updating the code in `SlicerDMRI` to use the new API

Of course we could do that but it’s not really the point. The point is that the API broke without warning.

---

<div class="post-metadata">

### Author: ![MicK7](https://discourse.vtk.org/user_avatar/discourse.vtk.org/mick7/32/3362_2.png) [@MicK7](https://discourse.vtk.org/u/MicK7)
#### Post date: [November 28, 2021, 1:03pm UTC](https://discourse.vtk.org/t/upcoming-changes-to-vtkcellarray/2066/12 "2021-11-28T13:03:26Z")

</div>

Is there a plan to move from a vtkIdTypeArray to this vtkCellArray structure or something equivalent for faces in vtkUnstructuredGrid ?

Then the method  
void vtkUnstructuredGrid::SetCells( vtkUnsignedCharArray \* cellTypes, vtkIdTypeArray \* cellLocations, vtkCellArray \* cells, vtkIdTypeArray \* faceLocations, vtkIdTypeArray \* faces)

could be replaced by something like that:

void vtkUnstructuredGrid::SetCells( vtkUnsignedCharArray \* cellTypes, vtkCellArray \* cells, vtkFaceArray\* faces)

It looks cleaner.

---

<div class="post-metadata">

### Author: ![will.schroeder](https://discourse.vtk.org/user_avatar/discourse.vtk.org/will.schroeder/32/233_2.png) [@will.schroeder](https://discourse.vtk.org/u/will.schroeder)
#### Post date: [November 28, 2021, 1:16pm UTC](https://discourse.vtk.org/t/upcoming-changes-to-vtkcellarray/2066/13 "2021-11-28T13:16:55Z")

</div>

I agree with you, it would be much cleaner and provide random access to cell faces. I’m not sure the implications for backwards compatibility though …

---

<div class="post-metadata">

### Author: ![Chris\_Rorden](https://discourse.vtk.org/user_avatar/discourse.vtk.org/chris_rorden/32/1217_2.png) [@Chris\_Rorden](https://discourse.vtk.org/u/Chris_Rorden)
#### Post date: [June 12, 2022, 11:52am UTC](https://discourse.vtk.org/t/upcoming-changes-to-vtkcellarray/2066/14 "2022-06-12T11:52:47Z")

</div>

Now that tools like the Slicer Preview Release and DiPy support reading and creating legacy VTK files that use these `OFFSETS` and `CONNECTIVITY` properties, can I suggest that the [documentation be updated to describe this](https://kitware.github.io/vtk-examples/site/VTKFileFormats/#binary-files) newly minted variation. This would help tools that attempt to support legacy VTK files without using VTK source as a dependency.

---

<div class="post-metadata">

### Author: ![lassoan](https://discourse.vtk.org/user_avatar/discourse.vtk.org/lassoan/32/50_2.png) [@lassoan](https://discourse.vtk.org/u/lassoan)
#### Post date: [June 14, 2022, 5:50am UTC](https://discourse.vtk.org/t/upcoming-changes-to-vtkcellarray/2066/15 "2022-06-14T05:50:09Z")

</div>

Slicer can read this new file format variant but it never writes it, as the files would be unreadable by all other software that implemented VTK file reading independently. The development version of Slicer accidentally used the new variant for a few weeks, but then we realized what changes were done in VTK and quickly reverted to writing the well-established VTK 4.2 file format.

Over the years, the .vtk file format has become a standard data exchange file format between many software. This is a great accomplishment. However, this also means that VTK library developers no longer have the freedom to change the file format.

To avoid upsetting VTK developers and users, and avoiding tarnishing VTK’s reputation in general, it would be better if .vtk file extension was only used for the 4.2 file format. If anyone needs the 5.1 format then a new file extension could be introduced for that instead that (e.g., vt5).

---

<div class="post-metadata">

### Author: ![will.schroeder](https://discourse.vtk.org/user_avatar/discourse.vtk.org/will.schroeder/32/233_2.png) [@will.schroeder](https://discourse.vtk.org/u/will.schroeder)
#### Post date: [June 14, 2022, 11:31am UTC](https://discourse.vtk.org/t/upcoming-changes-to-vtkcellarray/2066/16 "2022-06-14T11:31:53Z")

</div>

The file format change was unfortunate IMO and has caused no end of grief for users. Andras, to riff on what you are saying, another thought is to create a set of extensions: .vtk, vt4, vtk5, with .vtk compile-time specified (i.e., .vtk4 or .vt5, default to .vt4). I’m not sure this is worth the effort though…

---

<div class="post-metadata">

### Author: ![lassoan](https://discourse.vtk.org/user_avatar/discourse.vtk.org/lassoan/32/50_2.png) [@lassoan](https://discourse.vtk.org/u/lassoan)
#### Post date: [June 14, 2022, 12:06pm UTC](https://discourse.vtk.org/t/upcoming-changes-to-vtkcellarray/2066/17 "2022-06-14T12:06:56Z")

</div>

Yes, it would be sufficient to make VTK file writer default file version configurable in CMake, set to 4.2 by default and add a note in the documentation that .vtk5 extension is recommended for 5.x files.

VTK-based applications (ParaView, Slicer, etc.) could add support for this newb.vtk5 file format without worrying about breaking backward compatibility.
