<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">2016-09-09 11:08 GMT+02:00 Elvis Stansvik <span dir="ltr"><<a href="mailto:elvis.stansvik@orexplore.com" target="_blank">elvis.stansvik@orexplore.com</a>></span>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><span class="gmail-">2016-09-09 11:04 GMT+02:00 Elvis Stansvik <span dir="ltr"><<a href="mailto:elvis.stansvik@orexplore.com" target="_blank">elvis.stansvik@orexplore.com</a>></span><wbr>:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><div><div>Hi all,<br><br></div>I have a hopefully simple question:<br><br></div>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 ?<br></div></div></div></blockquote><div><br></div></span><div>I guess this is really two questions:<br><br></div><div>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].<br>2) Will SetPosition move the volume such that the center of the corner voxel is at the given world position?<br></div></div></div></div></blockquote><div><br></div><div>Okay, I made the following small test program:<br><br>#include <iostream><br><br>#include <vtkColorTransferFunction.h><br>#include <vtkGPUVolumeRayCastMapper.h><br>#include <vtkPiecewiseFunction.h><br>#include <vtkRenderer.h><br>#include <vtkRenderWindow.h><br>#include <vtkRenderWindowInteractor.h><br>#include <vtkSmartPointer.h><br>#include <vtkVolume.h><br>#include <vtkVolumeProperty.h><br>#include <vtkXMLImageDataReader.h><br>#include <vtkCubeAxesActor.h><br>#include <vtkTextProperty.h><br><br>int main(int argc, char* argv[])<br>{<br> if (argc != 2) {<br> std::cerr << "Usage: " << argv[0] << "<file>" << std::endl;<br> return 1;<br> }<br> <br> auto reader = vtkSmartPointer<vtkXMLImageDataReader>::New();<br> reader->SetFileName(argv[1]);<br> reader->Update();<br> <br> auto mapper = vtkSmartPointer<vtkGPUVolumeRayCastMapper>::New();<br> mapper->SetInputConnection(reader->GetOutputPort());<br> <br> auto color = vtkSmartPointer<vtkColorTransferFunction>::New();<br> color->AddRGBPoint(0.0, 0.0, 0.0, 1.0); // blue<br> color->AddRGBPoint(1.0, 0.0, 0.0, 1.0); // blue<br><br> auto opacity = vtkSmartPointer<vtkPiecewiseFunction>::New();<br> opacity->AddPoint(0.0, 0.4);<br> opacity->AddPoint(1.0, 0.4);<br><br> auto property = vtkSmartPointer<vtkVolumeProperty>::New();<br> property->SetColor(color);<br> property->SetScalarOpacity(opacity);<br><br> auto volume = vtkSmartPointer<vtkVolume>::New();<br> volume->SetMapper(mapper);<br> volume->SetProperty(property);<br> volume->SetPosition(0, 0, 0);<br><br> auto renderer = vtkSmartPointer<vtkRenderer>::New();<br> renderer->AddVolume(volume);<br><br> // Cube axes actor<br> auto cubeAxesActor = vtkSmartPointer<vtkCubeAxesActor>::New();<br> cubeAxesActor->SetBounds(0, 4, 0, 4, 0, 4);<br> cubeAxesActor->SetCamera(renderer->GetActiveCamera());<br> cubeAxesActor->GetTitleTextProperty(0)->SetColor(1.0, 0.0, 0.0);<br> cubeAxesActor->GetLabelTextProperty(0)->SetColor(1.0, 0.0, 0.0);<br> cubeAxesActor->GetTitleTextProperty(1)->SetColor(0.0, 1.0, 0.0);<br> cubeAxesActor->GetLabelTextProperty(1)->SetColor(0.0, 1.0, 0.0);<br> cubeAxesActor->GetTitleTextProperty(2)->SetColor(0.0, 0.0, 1.0);<br> cubeAxesActor->GetLabelTextProperty(2)->SetColor(0.0, 0.0, 1.0);<br> cubeAxesActor->DrawXGridlinesOn();<br> cubeAxesActor->DrawYGridlinesOn();<br> cubeAxesActor->DrawZGridlinesOn();<br> cubeAxesActor->SetGridLineLocation(VTK_GRID_LINES_FURTHEST);<br> renderer->AddActor(cubeAxesActor);<br><br> renderer->ResetCamera();<br><br> auto renderWindow = vtkSmartPointer<vtkRenderWindow>::New();<br> renderWindow->AddRenderer(renderer);<br> <br> auto interactor = vtkSmartPointer<vtkRenderWindowInteractor>::New();<br> interactor->SetRenderWindow(renderWindow);<br> interactor->Initialize();<br> <br> interactor->Start();<br> <br> return EXIT_SUCCESS;<br>}<br><br></div><div>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:<br><br><!-- 2x2x2 image --><br><VTKFile type="ImageData" version="0.1" byte_order="LittleEndian"><br> <ImageData WholeExtent="0 1 0 1 0 1" Origin="0 0 0" Spacing="1.0 1.0 1.0"><br> <Piece Extent="0 1 0 1 0 1"><br> <PointData Scalars="density"><br> <DataArray type="Float32" Name="density" format="ascii"><br> 1.0 1.0<br> 1.0 1.0<br> 1.0 1.0<br> 1.0 1.0<br> 1.0 1.0<br> 1.0 1.0<br> 1.0 1.0<br> 1.0 1.0<br> </DataArray><br> </PointData><br> </Piece><br> </ImageData><br></VTKFile><br><br><!-- 3x3x3 image --><br><VTKFile type="ImageData" version="0.1" byte_order="LittleEndian"><br> <ImageData WholeExtent="0 2 0 2 0 2" Origin="0 0 0" Spacing="1.0 1.0 1.0"><br> <Piece Extent="0 2 0 2 0 2"><br> <PointData Scalars="density"><br> <DataArray type="Float32" Name="density" format="ascii"><br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> </DataArray><br> </PointData><br> </Piece><br> </ImageData><br></VTKFile><br><br><!-- 4x4x4 image --><br><VTKFile type="ImageData" version="0.1" byte_order="LittleEndian"><br> <ImageData WholeExtent="0 3 0 3 0 3" Origin="0 0 0" Spacing="1.0 1.0 1.0"><br> <Piece Extent="0 3 0 3 0 3"><br> <PointData Scalars="density"><br> <DataArray type="Float32" Name="density" format="ascii"><br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> 1.0 1.0 1.0 1.0 1.0 1.0 1.0 1.0<br> </DataArray><br> </PointData><br> </Piece><br> </ImageData><br></VTKFile><br><br></div><div>I'm attaching the result.<br><br></div><div>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.<br><br></div><div>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.<br><br></div><div>If someone could clarify what is going on here, it would be much appreciated.<br><br></div><div>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).<br><br></div><div>But I'm still surprised that a volume containing 2x2x2 voxels values gives a 1x1x1 visual rendering.<br><br></div><div>Elvis<br></div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div class="gmail_extra"><div class="gmail_quote"><div><br></div><div>Elvis<br><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr"><div><div><br></div>Thanks in advance,<br></div>Elvis<br></div>
</blockquote></div><br></div></div>
</blockquote></div><br></div></div>