Commit 1b12c6ed authored by Emmanuel Promayon's avatar Emmanuel Promayon

FIXED better arbitrary slice management (although not complete)

parent 20c7b693
......@@ -74,6 +74,7 @@ void Slice::init() {
pixelActor = nullptr;
pixelActorPointSet = nullptr;
image2DReslicer = nullptr;
imageTransform = nullptr;
resliceTransform = nullptr;
}
......@@ -111,7 +112,9 @@ void Slice::setOriginalVolume(vtkSmartPointer<vtkImageData> volume) {
// -------------------- setImageWorldTransform --------------------
void Slice::setImageWorldTransform(vtkSmartPointer<vtkTransform> transform) {
image3DActor->SetUserTransform(transform);
// store the transform to world as the 3D actor transformation for correct viewing
imageTransform = transform;
image3DActor->SetUserTransform(imageTransform);
}
// -------------------- pixelPicked --------------------
......@@ -142,9 +145,7 @@ int Slice::getNumberOfSlices() const {
int nbSlices;
switch (sliceOrientation) {
case ARBITRARY:
nbSlices = max(max(extent[1] - extent[0], extent[3] - extent[2]), extent[5] - extent[4]) + 1;
break;
case ARBITRARY: // for arbitrary, as it is initialized the same ways as an axial slice, just z extent
case AXIAL:
case AXIAL_NEURO:
nbSlices = extent[5] - extent[4] + 1;
......@@ -172,7 +173,7 @@ int Slice::getSlice() const {
void Slice::setSlice(int s) {
// Check if s is inside the volume bounds
if (s < 0) {
currentSliceIndex = 0.0;
currentSliceIndex = 0;
}
else {
if (s >= getNumberOfSlices()) {
......@@ -226,9 +227,8 @@ void Slice::setSlice(double x, double y, double z) {
volumeToReslicedCoords(xyz, ijk);
switch (sliceOrientation) {
default:
break;
case AXIAL:
case AXIAL_NEURO:
setSlice(rint(ijk[2]));
break;
case CORONAL:
......@@ -237,6 +237,8 @@ void Slice::setSlice(double x, double y, double z) {
case SAGITTAL:
setSlice(rint(ijk[0]));
break;
default:
break;
}
// Set pixel position in current slice.
......@@ -257,11 +259,11 @@ void Slice::setPixelRealPosition(double x, double y, double z) {
}
// -------------------- setReslicerTransform --------------------
void Slice::setReslicerTransform(vtkSmartPointer<vtkTransform> t) {
void Slice::setReslicerTransform(vtkSmartPointer<vtkTransform> transform) {
// store the transformation pointer
// (when the transformation is changed, you need to call updateReslice() in order
// to take the new transformation into account and update the arbitrary slice image
resliceTransform = t;
resliceTransform = transform;
}
// -------------------- get2DImageActor --------------------
......@@ -293,15 +295,6 @@ void Slice::initActors() {
// set the lookupTable
imgToMapFilter->SetLookupTable(lut);
// the 2D and 3D image actors are directly plugged to the output of imgToMapFilter
image3DActor = vtkSmartPointer<vtkImageActor>::New();
image3DActor->GetMapper()->SetInputConnection(imgToMapFilter->GetOutputPort());
image3DActor->InterpolateOn();
image2DActor = vtkSmartPointer<vtkImageActor>::New();
image2DActor->GetMapper()->SetInputConnection(imgToMapFilter->GetOutputPort());
image2DActor->InterpolateOn();
// reslicer for the arbitrary slice
// image2DChangeInfo builds a simple image from the original image
// that has default origin, extent and spacing
......@@ -316,11 +309,27 @@ void Slice::initActors() {
image2DReslicer->SetOutputOriginToDefault();
image2DReslicer->SetOutputExtentToDefault();
image2DReslicer->SetOutputSpacingToDefault();
image2DReslicer->SetOutputDimensionality(2);
// for the 2D and 3D image actors it is either directly plugged to the output of imgToMapFilter
// (if this is a perpendicular orientation) or to the reslicer (if this is an arbitrary orientation)
image3DActor = vtkSmartPointer<vtkImageActor>::New();
image3DActor->InterpolateOn();
image3DActor->GetMapper()->SetInputConnection(imgToMapFilter->GetOutputPort());
image2DActor = vtkSmartPointer<vtkImageActor>::New();
image2DActor->InterpolateOn();
if (sliceOrientation == ARBITRARY) {
image2DActor->GetMapper()->SetInputConnection(image2DReslicer->GetOutputPort());
}
else {
image2DActor->GetMapper()->SetInputConnection(imgToMapFilter->GetOutputPort());
}
// use identity by default for the arbitrary slice
resliceTransform = vtkSmartPointer<vtkTransform>::New();
resliceTransform->Identity();
// Picked plane
initPickPlaneActor();
updatePickPlane();
......@@ -611,8 +620,6 @@ void Slice::updatePixelActor(double x, double y, double z) {
// -------------------- updateReslice --------------------
void Slice::updateReslice() {
if (sliceOrientation == ARBITRARY) {
double wxyz[4];
// Original volume dimensions in number of voxels (x, y and z)
int originalDimensions[3];
originalVolume->GetDimensions(originalDimensions);
......@@ -621,38 +628,36 @@ void Slice::updateReslice() {
vtkSmartPointer<vtkTransform> transformationInsideVolume = vtkTransform::New();
transformationInsideVolume->Identity();
// go to the image center
transformationInsideVolume->Translate(originalDimensions[0] / 2, originalDimensions[1] / 2, originalDimensions[2] / 2);
// go to the image center
double imageCenter[3];
for (int i=0;i<3;i++) {
imageCenter[i] = /*originalSpacing[i]**/originalDimensions[i] / 2.0;
}
transformationInsideVolume->Translate(imageCenter[0], imageCenter[1], imageCenter[2]);
// apply the current rotation from the frame
resliceTransform->GetOrientationWXYZ(wxyz);
transformationInsideVolume->RotateWXYZ(wxyz[0], wxyz[1], wxyz[2], wxyz[3]);
double xyz[4];
resliceTransform->GetOrientation(xyz);
transformationInsideVolume->RotateWXYZ(xyz[0], xyz[1], xyz[2], xyz[3]);
// go back to the image origin
transformationInsideVolume->Translate(-originalDimensions[0] / 2, -originalDimensions[1] / 2, -originalDimensions[2] / 2);
transformationInsideVolume->Translate(-imageCenter[0], -imageCenter[1], -imageCenter[2]);
// translate to the current slice
transformationInsideVolume->Translate(0.0, 0.0, currentSliceIndex);
image2DReslicer->SetResliceAxes(transformationInsideVolume->GetMatrix());
resliceTransform->DeepCopy(transformationInsideVolume);
image2DReslicer->SetResliceAxes(resliceTransform->GetMatrix());
image2DReslicer->UpdateInformation();
image2DReslicer->Update();
image3DActor->SetUserMatrix(resliceTransform->GetMatrix());
image3DActor->SetInputData(image2DReslicer->GetOutput());
image3DActor->Update();
// image3DActor->SetUserMatrix(resliceTransform->GetMatrix());
// image3DActor->SetInputData(image2DReslicer->GetOutput());
// image3DActor->GetMapper()->SetInputConnection(image2DReslicer->GetOutputPort());
// image2DActor->Update();
// image3DActor->Update();
}
updateLocalTransformation();
updatePickPlane();
}
// -------------------- updateLocalTransformation --------------------
void Slice::updateLocalTransformation() {
image2DReslicer->SetOutputDimensionality(3);
image2DReslicer->UpdateInformation();
image2DReslicer->SetOutputDimensionality(2);
image2DReslicer->UpdateInformation();
}
......
......@@ -306,16 +306,18 @@ protected:
/// @name Management of the arbitrary slice
/// @{
/// Transformation relative to the 3D image actor (it is not parallel to one
/// Transformation relative to the world. This is required to place
/// the 3D actor properly in space
vtkSmartPointer<vtkTransform> imageTransform;
/// Transformation relative to the 3D image (it is not parallel to one
/// of the main axe, but has a specific rotation). This should be initialized
/// using the single image component transformation to the world or parent.
/// using the single image component transformation to the parent.
/// This is only required for arbitrary orientation.
vtkSmartPointer<vtkTransform> resliceTransform;
/// The image reslicer computes the arbitrary slice pixels
vtkSmartPointer<vtkImageReslice> image2DReslicer;
/// update the 2D reslicer
void updateLocalTransformation();
/// @}
......
......@@ -101,7 +101,7 @@ void SingleImageComponent::initRepresentation() {
break;
case Slice::ARBITRARY:
setVisibility(InteractiveViewer::getArbitraryViewer(), true);
mySlice->setReslicerTransform(getTransform());
mySlice->setReslicerTransform(getTransform());
break;
}
}
......@@ -111,55 +111,97 @@ void SingleImageComponent::pixelPicked(double i, double j, double k) {
((ImageComponent*)getParent())->pixelPicked(i, j, k, this);
}
/// rewritten to forbid any transorm from the ImageComponent
// All methods below are rewritten to forbid any transform from the ImageComponent,
// unless this is a arbitrary slice
// -------------------- setTransform --------------------
void SingleImageComponent::setTransform(vtkSmartPointer<vtkTransform> transform) {
// Do nothing, my parent (the ImageComponent) should move !!!
// Do nothing, my parent (the ImageComponent) should do that globally
// unless this is a arbitrary slice
if (sliceOrientation == Slice::ARBITRARY) {
myFrame->setTransform(transform);
mySlice->updateReslice();
}
}
// -------------------- resetTransform --------------------
void SingleImageComponent::resetTransform() {
// Do nothing, my parent (the ImageComponent) should move !!!
// Do nothing, my parent (the ImageComponent) should do that globally
// unless this is a arbitrary slice
if (sliceOrientation == Slice::ARBITRARY) {
myFrame->resetTransform();
mySlice->updateReslice();
}
}
// -------------------- rotate --------------------
void SingleImageComponent::rotate(double aroundX, double aroundY, double aroundZ) {
// Do nothing, my parent (the ImageComponent) should move !!!
if (sliceOrientation == Slice::ARBITRARY) {
myFrame->rotate(aroundX, aroundY, aroundZ);
mySlice->updateReslice();
}
// Do nothing, my parent (the ImageComponent) should do that globally
// unless this is a arbitrary slice
if (sliceOrientation == Slice::ARBITRARY) {
myFrame->rotate(aroundX, aroundY, aroundZ);
mySlice->updateReslice();
}
}
// -------------------- rotateVTK --------------------
void SingleImageComponent::rotateVTK(double aroundX, double aroundY, double aroundZ) {
// Do nothing, my parent (the ImageComponent) should move !!!
// Do nothing, my parent (the ImageComponent) should do that globally
// unless this is a arbitrary slice
if (sliceOrientation == Slice::ARBITRARY) {
myFrame->rotateVTK(aroundX, aroundY, aroundZ);
mySlice->updateReslice();
}
}
// -------------------- setTransformRotation --------------------
void SingleImageComponent::setTransformRotation(double aroundX, double aroundY, double aroundZ) {
// Do nothing, my parent (the ImageComponent) should move !!!
// Do nothing, my parent (the ImageComponent) should do that globally
// unless this is a arbitrary slice
if (sliceOrientation == Slice::ARBITRARY) {
myFrame->setTransformRotation(aroundX, aroundY, aroundZ);
mySlice->updateReslice();
}
}
// -------------------- setTransformRotationVTK --------------------
void SingleImageComponent::setTransformRotationVTK(double aroundX, double aroundY, double aroundZ) {
// Do nothing, my parent (the ImageComponent) should move !!!
// Do nothing, my parent (the ImageComponent) should do that globally
// unless this is a arbitrary slice
if (sliceOrientation == Slice::ARBITRARY) {
myFrame->setTransformRotationVTK(aroundX, aroundY, aroundZ);
mySlice->updateReslice();
}
}
// -------------------- setTransformTranslation --------------------
void SingleImageComponent::setTransformTranslation(double x, double y, double z) {
// Do nothing, my parent (the ImageComponent) should move !!!
// Do nothing, my parent (the ImageComponent) should do that globally
// unless this is a arbitrary slice
if (sliceOrientation == Slice::ARBITRARY) {
myFrame->setTransformTranslation(x, y, z);
mySlice->updateReslice();
}
}
// -------------------- setTransformTranslationVTK --------------------
void SingleImageComponent::setTransformTranslationVTK(double x, double y, double z) {
// Do nothing, my parent (the ImageComponent) should move !!!
// Do nothing, my parent (the ImageComponent) should do that globally
// unless this is a arbitrary slice
if (sliceOrientation == Slice::ARBITRARY) {
myFrame->setTransformTranslationVTK(x, y, z);
mySlice->updateReslice();
}
}
// -------------------- translate --------------------
void SingleImageComponent::translate(double x, double y, double z) {
// Do nothing, my parent (the ImageComponent) should move !!!
// Do nothing, my parent (the ImageComponent) should do that globally
// unless this is a arbitrary slice
if (sliceOrientation == Slice::ARBITRARY) {
myFrame->translate(x, y, z);
mySlice->updateReslice();
}
}
}
......@@ -71,18 +71,6 @@ public:
/// rewritten to synchronize everyone
void setSelected(const bool, const bool) override;
/// rewritten to forbid any transorm from the ImageComponent
/// (either all the ImageComponent moves or I do not move (without my other SingleImages...).
void setTransform(vtkSmartPointer<vtkTransform>) override;
void resetTransform() override;
void translate(double, double, double) override;
void rotate(double, double, double) override;
void rotateVTK(double, double, double) override;
void setTransformTranslation(double, double, double) override;
void setTransformTranslationVTK(double, double, double) override;
void setTransformRotation(double, double, double) override;
void setTransformRotationVTK(double, double, double) override;
/// new method used to call the Component set selected
void singleImageSelected(const bool);
......@@ -93,6 +81,22 @@ public:
*/
void setViewSliceIn3D(bool viewSliceIn3D);
/// @name overriden to group all frame transformation (unless it is an arbitrary slice
/// @{
/// rewritten to forbid any transform from the ImageComponent
/// (either all the ImageComponent moves or none move), unless this is an arbitrary sice
/// (which should have free independent movement)
void setTransform(vtkSmartPointer<vtkTransform>) override;
void resetTransform() override;
void translate(double, double, double) override;
void rotate(double, double, double) override;
void rotateVTK(double, double, double) override;
void setTransformTranslation(double, double, double) override;
void setTransformTranslationVTK(double, double, double) override;
void setTransformRotation(double, double, double) override;
void setTransformRotationVTK(double, double, double) override;
/// @}
protected:
/** The concrete building of the Service (Slice in this case, for a 2D representation). */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment