[vtkusers] Placing volumes exactly adjacent to each other

Elvis Stansvik elvis.stansvik at orexplore.com
Sun Sep 11 10:17:05 EDT 2016


2016-09-09 11:08 GMT+02:00 Elvis Stansvik <elvis.stansvik at orexplore.com>:

> 2016-09-09 11:04 GMT+02:00 Elvis Stansvik <elvis.stansvik at orexplore.com>:
>
>> Hi all,
>>
>> I have a hopefully simple question:
>>
>> Since the bounds of a vtkImageData start and end in the center of the
>> corner voxels, if I want to place two volumes in the world adjacent (right
>> next to eachother) using SetPosition, will I have to compensate for this,
>> to avoid the volumes overlapping by 0.5*spacing_of_first_volume +
>> 0.5*spacing_of_second_volume ?
>>
>
> I guess this is really two questions:
>
> 1) Is the (visual, in world) size of a volume in the first dimension
> (extent[1] - extent[0]) * spacing[2] or (extent[1] - extent[0] + 1) *
> spacing[2].
> 2) Will SetPosition move the volume such that the center of the corner
> voxel is at the given world position?
>

Okay, I made the following small test program:

#include <iostream>

#include <vtkColorTransferFunction.h>
#include <vtkGPUVolumeRayCastMapper.h>
#include <vtkPiecewiseFunction.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkSmartPointer.h>
#include <vtkVolume.h>
#include <vtkVolumeProperty.h>
#include <vtkXMLImageDataReader.h>
#include <vtkCubeAxesActor.h>
#include <vtkTextProperty.h>

int main(int argc, char* argv[])
{
  if (argc != 2) {
    std::cerr << "Usage: " << argv[0] << "<file>" << std::endl;
    return 1;
  }

  auto reader = vtkSmartPointer<vtkXMLImageDataReader>::New();
  reader->SetFileName(argv[1]);
  reader->Update();

  auto mapper = vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();
  mapper->SetInputConnection(reader->GetOutputPort());

  auto color = vtkSmartPointer<vtkColorTransferFunction>::New();
  color->AddRGBPoint(0.0, 0.0, 0.0, 1.0); // blue
  color->AddRGBPoint(1.0, 0.0, 0.0, 1.0); // blue

  auto opacity = vtkSmartPointer<vtkPiecewiseFunction>::New();
  opacity->AddPoint(0.0, 0.4);
  opacity->AddPoint(1.0, 0.4);

  auto property = vtkSmartPointer<vtkVolumeProperty>::New();
  property->SetColor(color);
  property->SetScalarOpacity(opacity);

  auto volume = vtkSmartPointer<vtkVolume>::New();
  volume->SetMapper(mapper);
  volume->SetProperty(property);
  volume->SetPosition(0, 0, 0);

  auto renderer = vtkSmartPointer<vtkRenderer>::New();
  renderer->AddVolume(volume);

  // Cube axes actor
  auto cubeAxesActor = vtkSmartPointer<vtkCubeAxesActor>::New();
  cubeAxesActor->SetBounds(0, 4, 0, 4, 0, 4);
  cubeAxesActor->SetCamera(renderer->GetActiveCamera());
  cubeAxesActor->GetTitleTextProperty(0)->SetColor(1.0, 0.0, 0.0);
  cubeAxesActor->GetLabelTextProperty(0)->SetColor(1.0, 0.0, 0.0);
  cubeAxesActor->GetTitleTextProperty(1)->SetColor(0.0, 1.0, 0.0);
  cubeAxesActor->GetLabelTextProperty(1)->SetColor(0.0, 1.0, 0.0);
  cubeAxesActor->GetTitleTextProperty(2)->SetColor(0.0, 0.0, 1.0);
  cubeAxesActor->GetLabelTextProperty(2)->SetColor(0.0, 0.0, 1.0);
  cubeAxesActor->DrawXGridlinesOn();
  cubeAxesActor->DrawYGridlinesOn();
  cubeAxesActor->DrawZGridlinesOn();
  cubeAxesActor->SetGridLineLocation(VTK_GRID_LINES_FURTHEST);
  renderer->AddActor(cubeAxesActor);

  renderer->ResetCamera();

  auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New();
  renderWindow->AddRenderer(renderer);

  auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();
  interactor->SetRenderWindow(renderWindow);
  interactor->Initialize();

  interactor->Start();

  return EXIT_SUCCESS;
}

And then loaded each of the following three files, containing a 2x2x2
(extent: 0 1 0 1 0 1), a 3x3x3 (extent: 0 2 0 2 0 2) and a 4x4x4 (extent: 0
3 0 3 0 3) image, all of them with spacing 1.0 1.0 1.0:

<!-- 2x2x2 image -->
<VTKFile type="ImageData" version="0.1" byte_order="LittleEndian">
    <ImageData WholeExtent="0 1 0 1 0 1" Origin="0 0 0" Spacing="1.0 1.0
1.0">
        <Piece Extent="0 1 0 1 0 1">
            <PointData Scalars="density">
                <DataArray type="Float32" Name="density" format="ascii">
                    1.0 1.0
                    1.0 1.0
                    1.0 1.0
                    1.0 1.0
                    1.0 1.0
                    1.0 1.0
                    1.0 1.0
                    1.0 1.0
                </DataArray>
            </PointData>
        </Piece>
    </ImageData>
</VTKFile>

<!-- 3x3x3 image -->
<VTKFile type="ImageData" version="0.1" byte_order="LittleEndian">
    <ImageData WholeExtent="0 2 0 2 0 2" Origin="0 0 0" Spacing="1.0 1.0
1.0">
        <Piece Extent="0 2 0 2 0 2">
            <PointData Scalars="density">
                <DataArray type="Float32" Name="density" format="ascii">
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                </DataArray>
            </PointData>
        </Piece>
    </ImageData>
</VTKFile>

<!-- 4x4x4 image -->
<VTKFile type="ImageData" version="0.1" byte_order="LittleEndian">
    <ImageData WholeExtent="0 3 0 3 0 3" Origin="0 0 0" Spacing="1.0 1.0
1.0">
        <Piece Extent="0 3 0 3 0 3">
            <PointData Scalars="density">
                <DataArray type="Float32" Name="density" format="ascii">
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                    1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0
                </DataArray>
            </PointData>
        </Piece>
    </ImageData>
</VTKFile>

I'm attaching the result.

As you can see, the 2x2x2 volume has a visual dimension of 1x1x1, the 3x3x3
a visual dimension of 2x2x2 and the 4x4x4 a visual dimension of 3x3x3, so
one less than what I would have expected.

I thought that with e.g. a 2x2x2 volume with spacing 1.0 1.0 1.0, I would
get 2x2x2 area occupied when the volume is mapped into the world.

If someone could clarify what is going on here, it would be much
appreciated.

I understand now that to "stack" my volumes adjacently on top of each
other, I should add extent[5] * spacing[2], not (extent[5] + 1) *
spacing[2] (I don't have access to the vtkVolume at that point, so can't
use GetBounds), and that it's precisely this position I should give to
SetPosition (no need to "compensate" for the half spacing to the voxel
center).

But I'm still surprised that a volume containing 2x2x2 voxels values gives
a 1x1x1 visual rendering.

Elvis


> Elvis
>
>
>> Thanks in advance,
>> Elvis
>>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/vtkusers/attachments/20160911/4b2340e8/attachment.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: result-2x2x2.png
Type: image/png
Size: 12788 bytes
Desc: not available
URL: <http://public.kitware.com/pipermail/vtkusers/attachments/20160911/4b2340e8/attachment.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: result-3x3x3.png
Type: image/png
Size: 13299 bytes
Desc: not available
URL: <http://public.kitware.com/pipermail/vtkusers/attachments/20160911/4b2340e8/attachment-0001.png>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: result-4x4x4.png
Type: image/png
Size: 14862 bytes
Desc: not available
URL: <http://public.kitware.com/pipermail/vtkusers/attachments/20160911/4b2340e8/attachment-0002.png>


More information about the vtkusers mailing list