[vtkusers] Placing volumes exactly adjacent to each other
Elvis Stansvik
elvis.stansvik at orexplore.com
Sun Sep 11 10:23:53 EDT 2016
2016-09-11 16:17 GMT+02:00 Elvis Stansvik <elvis.stansvik at orexplore.com>:
> 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>
>
Sorry, these files had a bit too many scalars in them (but the result is
the same of course). Here they are corrected:
<!-- 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
</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
</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
</DataArray>
</PointData>
</Piece>
</ImageData>
</VTKFile>
Elvis
> 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/e285f1d2/attachment.html>
More information about the vtkusers
mailing list