44 #include <vtkRenderer.h>
45 #include <vtkFloatArray.h>
46 #include <vtkPlaneSource.h>
47 #include <vtkPointData.h>
48 #include <vtkTriangleFilter.h>
49 #include <vtkStripper.h>
50 #include <vtkImageData.h>
51 #include <vtkPainterPolyDataMapper.h>
52 #include <vtkLookupTable.h>
60 #include <vtkOpenGLRenderWindow.h>
84 vtkOpenGLRenderWindow *context = vtkOpenGLRenderWindow::SafeDownCast(window);
97 mTargetSpaceIsR =
true;
102 mTargetSpaceIsR =
false;
103 mActor = vtkActorPtr::New();
104 mPainter = TextureSlicePainterPtr::New();
105 mPainterPolyDatamapper = vtkPainterPolyDataMapperPtr::New();
107 mPlaneSource = vtkPlaneSourcePtr::New();
110 triangleFilter->SetInputConnection(mPlaneSource->GetOutputPort());
113 stripper->SetInputConnection(triangleFilter->GetOutputPort());
115 mPolyDataAlgorithm = stripper;
116 mPolyDataAlgorithm->Update();
118 mPolyData = mPolyDataAlgorithm->GetOutput();
119 mPolyData->GetPointData()->SetNormals(NULL);
121 mPainter->SetDelegatePainter(mPainterPolyDatamapper->GetPainter());
122 mPainterPolyDatamapper->SetPainter(mPainter);
123 mPainterPolyDatamapper->SetInputData(mPolyData);
124 mActor->SetMapper(mPainterPolyDatamapper);
144 mPainter->setShaderPath(shaderFile);
158 if (!mTargetSpaceIsR)
163 this->resetGeometryPlane();
166 void Texture3DSlicerProxyImpl::resetGeometryPlane()
174 std::vector<Vector3D> pp_s;
175 for (
unsigned x=0; x<2; ++x)
176 for (
unsigned y=0; y<2; ++y)
177 for (
unsigned z=0; z<2; ++z)
178 pp_s.push_back(sMd.coord(bb_d.
corner(x,y,x)));
187 Vector3D origin(mBB_s[0], mBB_s[2], 0);
196 origin = rMs.coord(origin);
211 mPlaneSource->SetPoint1( point1_s.begin() );
212 mPlaneSource->SetPoint2( point2_s.begin() );
213 mPlaneSource->SetOrigin( origin_s.begin() );
215 mPolyDataAlgorithm->Update();
219 for (
unsigned i=0; i<mImages.size(); ++i)
221 updateCoordinates(i);
227 std::vector<ImagePtr> images(images_raw.size());
228 for (
unsigned i=0; i<images.size(); ++i)
230 images[i] = images_raw[i]->getUnsigned(images_raw[i]);
233 if (mImages.size() == images.size())
236 for (
unsigned i = 0; i < mImages.size(); ++i)
237 equal &= (mImages[i] == images[i]);
242 for (
unsigned i = 0; i < mImages.size(); ++i)
244 disconnect(mImages[i].
get(), SIGNAL(transformChanged()),
this, SLOT(transformChangedSlot()));
245 disconnect(mImages[i].
get(), SIGNAL(transferFunctionsChanged()),
this, SLOT(updateColorAttributeSlot()));
246 disconnect(mImages[i].
get(), SIGNAL(vtkImageDataChanged()),
this, SLOT(imageChanged()));
251 for (
unsigned i = 0; i < mImages .size(); ++i)
258 mPainter->SetVolumeBuffer(i, dataBuffer);
260 connect(mImages[i].
get(), SIGNAL(transformChanged()),
this, SLOT(transformChangedSlot()));
261 connect(mImages[i].
get(), SIGNAL(transferFunctionsChanged()),
this, SLOT(updateColorAttributeSlot()));
262 connect(mImages[i].
get(), SIGNAL(vtkImageDataChanged()),
this, SLOT(imageChanged()));
263 this->updateCoordinates(i);
265 this->updateColorAttributeSlot();
267 for (
unsigned i = 0; i < mImages.size(); ++i)
269 mPainterPolyDatamapper->MapDataArrayToMultiTextureAttribute(2 * i,
271 vtkDataObject::FIELD_ASSOCIATION_POINTS);
279 disconnect(mSliceProxy.get(), SIGNAL(transformChanged(
Transform3D)),
this, SLOT(transformChangedSlot()));
280 mSliceProxy = slicer;
283 connect(mSliceProxy.get(), SIGNAL(transformChanged(
Transform3D)),
this, SLOT(transformChangedSlot()));
284 for (
unsigned i=0; i < mImages.size(); ++i)
286 updateCoordinates(i);
291 QString Texture3DSlicerProxyImpl::getTCoordName(
int index)
296 void Texture3DSlicerProxyImpl::updateCoordinates(
int index)
298 if (!mPolyData || !mSliceProxy)
303 Vector3D origin(volume->GetOrigin());
304 Vector3D spacing(volume->GetSpacing());
305 DoubleBoundingBox3D imageSize(volume->GetExtent());
307 for (
int i = 0; i < 3; ++i)
309 imageSize[2 * i] = origin[i] + spacing[i] * (imageSize[2 * i] - 0.5);
310 imageSize[2 * i + 1] = origin[i] + spacing[i] * (imageSize[2 * i + 1] + 0.5);
314 DoubleBoundingBox3D textureSpace(0.0, 1.0, 0.0, 1.0, 0.0, 1.0);
317 Transform3D iMs = mImages[index]->get_rMd().inv() * mSliceProxy->get_sMr().inv();
323 std::vector<Vector3D> plane(4);
324 plane[0] = mBB_s.
corner(0, 0, 0);
325 plane[1] = mBB_s.
corner(1, 0, 0);
326 plane[2] = mBB_s.
corner(0, 1, 0);
327 plane[3] = mBB_s.
corner(1, 1, 0);
329 for (
unsigned i = 0; i < plane.size(); ++i)
331 plane[i] = nMs.coord(plane[i]);
334 vtkFloatArrayPtr TCoords = vtkFloatArray::SafeDownCast(mPolyData->GetPointData()->GetArray(
339 TCoords = vtkFloatArrayPtr::New();
340 TCoords->SetNumberOfComponents(3);
341 TCoords->Allocate(4 * 3);
342 TCoords->InsertNextTuple3(0.0, 0.0, 0.0);
343 TCoords->InsertNextTuple3(0.0, 0.0, 0.0);
344 TCoords->InsertNextTuple3(0.0, 0.0, 0.0);
345 TCoords->InsertNextTuple3(0.0, 0.0, 0.0);
347 mPolyData->GetPointData()->AddArray(TCoords);
350 for (
unsigned i = 0; i < plane.size(); ++i)
352 TCoords->SetTuple3(i, plane[i][0], plane[i][1], plane[i][2]);
355 mPolyData->Modified();
358 void Texture3DSlicerProxyImpl::updateColorAttributeSlot()
360 for (
unsigned i = 0; i < mImages.size(); ++i)
365 lut->GetTable()->Modified();
369 if (inputImage->GetNumberOfScalarComponents()==1)
371 mPainter->SetLutBuffer(i, lutBuffer);
374 int scalarTypeMax = (int)inputImage->GetScalarTypeMax();
375 double imin = lut->GetRange()[0];
376 double imax = lut->GetRange()[1];
378 float window = (float) (imax-imin) / scalarTypeMax;
379 float llr = (float) mImages[i]->getLookupTable2D()->getLLR() / scalarTypeMax;
380 float level = (float) imin/scalarTypeMax + window/2;
381 float alpha = (float) mImages[i]->getLookupTable2D()->getAlpha();
383 mPainter->SetColorAttribute(i, window, level, llr, alpha);
388 void Texture3DSlicerProxyImpl::transformChangedSlot()
391 this->resetGeometryPlane();
395 void Texture3DSlicerProxyImpl::imageChanged()
399 for (
unsigned i = 0; i < mImages .size(); ++i)
406 mPainter->SetVolumeBuffer(i, dataBuffer);
412 for (
unsigned i=0; i<mImages.size(); ++i)
414 updateCoordinates(i);
QString qstring_cast(const T &val)
DoubleBoundingBox3D transform(const Transform3D &m, const DoubleBoundingBox3D &bb)
vtkSmartPointer< class vtkActor > vtkActorPtr
Vector3D corner(int x, int y, int z) const
Transform3D Transform3D
Transform3D is a representation of an affine 3D transform.
static Texture3DSlicerProxyPtr New()
vtkSmartPointer< class vtkFloatArray > vtkFloatArrayPtr
vtkSmartPointer< class vtkRenderWindow > vtkRenderWindowPtr
cstring_cast_Placeholder cstring_cast(const T &val)
void setTargetSpaceToR()
use to draw the slice in 3D r space instead of in 2D s space.
Texture3DSlicerProxyImpl()
void setShaderPath(QString shaderFile)
static DoubleBoundingBox3D fromCloud(std::vector< Vector3D > cloud)
Transform3D createTransformNormalize(const DoubleBoundingBox3D &in, const DoubleBoundingBox3D &out)
bool similar(const DoubleBoundingBox3D &a, const DoubleBoundingBox3D &b, double tol)
GPUImageLutBufferPtr getGPUImageLutBuffer(vtkUnsignedCharArrayPtr lut)
void setViewportData(const Transform3D &vpMs, const DoubleBoundingBox3D &vp)
void setSliceProxy(SliceProxyPtr slicer)
static Texture3DSlicerProxyPtr New()
virtual ~Texture3DSlicerProxyImpl()
static bool LoadRequiredExtensions(vtkOpenGLExtensionManager *mgr)
vtkSmartPointer< class vtkTriangleFilter > vtkTriangleFilterPtr
void createGeometryPlane(Vector3D point1_s, Vector3D point2_s, Vector3D origin_s)
void setImages(std::vector< ImagePtr > images)
vtkSmartPointer< class vtkLookupTable > vtkLookupTablePtr
boost::shared_ptr< class Texture3DSlicerProxy > Texture3DSlicerProxyPtr
boost::shared_ptr< class GPUImageDataBuffer > GPUImageDataBufferPtr
vtkSmartPointer< class vtkStripper > vtkStripperPtr
Representation of a floating-point bounding box in 3D. The data are stored as {xmin,xmax,ymin,ymax,zmin,zmax}, in order to simplify communication with vtk.
Eigen::Vector3d Vector3D
Vector3D is a representation of a point or vector in 3D.
boost::shared_ptr< class GPUImageLutBuffer > GPUImageLutBufferPtr
GPUImageDataBufferPtr getGPUImageDataBuffer(vtkImageDataPtr volume)
static GPUImageBufferRepository * getInstance()
static bool isSupported(vtkRenderWindowPtr window)