Marching cube behavior changed


Since updating to vtk 9 from vtk8.1.1 I have noticed a slight difference in the marching cube operation.
The Spacing used is not rounded as it was before. so the conversion from float (here 0.15) return 0.1500000597XXXXX. Which influence the output or marching cube ever so slightly but is significant enough in the application I have.

Is there a way of setting a lower precision for the spacing so that this rounding may happen (it was considered as 0.15 before) ?


Precisely what is the name of the filter you are executing? Are you using vtkMarchingCubes or vtkContourFilter? or something else? There is delegation of vtkContourFilter to other filters and this might be related.

I am using the vtkmarchingcubes one !

Unless someone has a better idea, look at code differences between the versions. Not a great solution but off the top of my head I can’t think what might have changed to affect this. (Also, just to state the obvious, make sure that the underlying hardware and/or system libraries have not changed.)

I was actually wondering if any dependency was upgraded that could justify this change in precision in the spacing representation

That does seem fishy, can you show us the code where you

  1. set the spacing, and
  2. print the spacing?

If the spacing is set by the reader that you use to read the data, then let us know what reader you are using.

The spacing is set by the reader (its an itk reader (ReadNdImage)). Then this itk image is converted to a vtkImage using itk::ImageToVTKImageFilter.

What is really surprising is the fact that if I “cout” the spacing I get 0.15 (in both cases vtk8 and vtk9),
but when I write an mhd of the obtained results I get different spacing in the header

(top is vtk 9 output and bottom is vtk 8)
The mhd file are written out with vtkMetaImageWriter in both case. There seems to be a rounding in vtk8 that dissapeared in vtk 9…

Don’t forget that 0.15 cannot be exactly represented with floating-point numbers. With double, the closest you can get is 0.1499999999999999944XX, and with float, the closest you can get is 0.1500000059604644775XX. When you see “0.15” it’s because “cout” itself does some rounding by not printing all the digits.

So what you’re most likely seeing is the result of a float-to-double conversion, and this conversion might be happening anywhere in your pipeline. That’s why I asked to see your code.

Yes I understand the representation issue which mean that the representation should be the same as before but the written number is different hence my belief that the rounding appears.

About the code:
Here is the code that produces a different output based on version:

Here is the detail for each function:
Read int volume : Read Int text code | WTOOLS
IntVolumeToVtkImageData : IntVolumetoVtkImageData text code | WTOOLS
Smoothing operation: Smoothing operatiobn text code | WTOOLS
marching cube : Marching cube text code | WTOOLS

Thanks for providing the code, I’ve taken a look through the classes that you use in your pipeline. The importer and gaussian smoother have not changed since VTK 8 in any way that should affect the results. I’m still unsure about the reader, what is the actual file type that you are reading? The vtkMarchingCubes filter has changed, so I’ll investigate it further. The change is not a change in precision but rather a change in the way it preps its data.

As for the spacing that you’re seeing, that is caused by changes in MetaIO rather than changes in VTK itself. See commit a5d4d2a88 in MetaIO, for example. The ElementSpacing in MetaIO changed from float to double between VTK 8 release and VTK 9, which is a compatibility-breaking change. So be warned if you are using MetaIO as your primary image format.

VTK 9, in fact, still assumes that MetaIO uses float, as can be seen in this code. And that is why, for VTK 9, the .mhd has those extra digits for ElementSpacing. VTK passes the spacing to MetaIO as floats, but the new MetaIO converts the spacing to double before printing it with cout. Hence the extra digits, since cout prints more digits for double than it would for float.

The input here is a .mhd file with a raw image that comes out of itk image of short integer. I have saved it with WriteNDImage. In the pipeline I want to use the itk output is fed to the gaussian smoothing part.
Thanks a lot for your time !

Here’s the answer about how vtkMarchingCubes has changed. Previously, it prepped the data by converting the i,j,k voxel indices into x,y,z data coordinates, and then it performed the marching cubes algorithm to generate the surface. In VTK 9, it performs the marching cubes algorithm directly on i,j,k, and afterwards it converts the surface points to data coordinates by multiplying by the spacing and adding the origin. The reason for the change was to improve efficiency.

This change in the order of operations is the only thing in vtkMarchingCubes that should have changed your results. And the change is expected to be very small, probably less than a 1e-12 difference in the final point positions.

The difference is of 1e-6 which is probably due to a float conversion… But yes that error then snowball to something quite big due to itksquredlengthedgefilter.
Thanks you for your time !