What is the purpose of this line?

Hello, I am trying to understand vtkVoxelContourToSurface. I am looking at this example,

https://www.paraview.org/Wiki/VTK/Examples/Cxx/PolyData/ContoursToSurface

What is the purpose of these three lines?
pt[0] = static_cast( (pt[0] - origin[0]) / spacing[0] + 0.5 );
pt[1] = static_cast( (pt[1] - origin[1]) / spacing[1] + 0.5 );
pt[2] = static_cast( (pt[2] - origin[2]) / spacing[2] + 0.5 );

Also, could someone please explain the purpose of spacing (voxels) in vtkVoxelContourToSurface and its method (SetSpacing(double[3])).

Thank you.

I’m not very familiar with vtkVoxelContoursToSurfaceFilter, but those three lines are converting from data coords (i.e. physical) to voxel index coords. The use of “+ 0.5” when casting to int is a simple way to perform rounding.

In the example, it looks like they compute the spacing so that the resolution of each slice is 41x41. To me, this resolution seems incredibly low, and it immediately makes me suspect that there is something strange about this example.

And here is what is strange: the only reason that a person would want to divide the original coords by the spacing before calling the filter, is if the filter doesn’t understand ‘spacing’ (i.e. if the filter expected unit voxel spacing). But the example calls contoursToSurface->SetSpacing(spacing[0], spacing[1], spacing[2]) so obviously the filter does understand spacing. Suddenly alarm bells start going off…

So here’s what I think is going on:

This example uses a sphere with a radius of 1.0, so the original coordinate range is [-1.0, +1.0]. The example then divides the size of the bounding box by 40 to get a spacing of 0.05. Then the example subtracts ‘origin’ from the coords and divides by ‘spacing’, so the range of the new coordinates will be [0, 40].

Then the examples calls contoursToSurface->SetSpacing(0.05, ...) which causes the filter to subdivide even further, so that the actual resolution of its internal slices will be 801x801. In other words, the only reason that this example gives a decent-looking result is that the spacing was applied twice.

I will repeat my initial statement that I’m not familiar with this filter, nor with this example. So I don’t know exactly how either should be used. However, I think the safest approach would be to modify the example as follows.

First, specify a finer spacing by dividing by e.g. 511 instead of dividing by 40.

double spacing[3] = { (bounds[1] - bounds[0]) / 511,
                      (bounds[3] - bounds[2]) / 511,
                      deltaz / 31};

Second, inform the filter that the spacing has already been applied, to ensure that the spacing is not applied twice:

contoursToSurface->SetSpacing(1.0, 1.0, 1.0);

The new link for this example is: ContoursToSurface. It definitely needs an update along the lines of what @dgobbi suggested. If nobody updates it, I should be able to do it, along with a Python example, after 26 Aug.

I have had a quick look at the example.

Actually I don’t think there is anything wrong with the example:

Changing according to @dgobbi causes the left-hand image to be rendered as a series of flat disks:

Changing

contoursToSurface->SetSpacing(spacing[0], spacing[1], spacing[2]);

to

contoursToSurface->SetSpacing(1, 1, 1);

doesn’t seem to have any effect.

@amaclean Can you explain what causes it to render as disks? It still seems to me that there is strange, poorly-understood stuff going on in that example. At the very least, it needs comments to explain what is going on.

I can’t explain, when I get back, I’ll have a closer look. Hopefully someone else can do it in the meantime.