[vtkusers] Placing volumes exactly adjacent to each other
Elvis Stansvik
elvis.stansvik at orexplore.com
Sun Sep 11 10:48:07 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>
>
> 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.
>
Okay, I think I understand now: The voxel values are mapped to grid
intersections in the world. So in the 2x2x2 case, the 8 scalar values are
mapped to (0,0,0), (0,0,1), (0,1,0), (0,1,1), (1,0,0), (1,0,1), (1,1,0) and
(1,1,1) in world coordinates, and the visual representation of that is a
cube with corners in those points, colored according to scalars. When I
played around with the 2x2x2 example and colored it in alternating red/blue
it helped me understand. Quite interesting to see how it calculates the
colors based on how you look at that little volume actually :)
Elvis
> Elvis
>
>
>> Elvis
>>
>>
>>> Thanks in advance,
>>> Elvis
>>>
>>
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://public.kitware.com/pipermail/vtkusers/attachments/20160911/0e4da42c/attachment.html>
More information about the vtkusers
mailing list