Commit d773164f authored by cfouard's avatar cfouard
Browse files

Temporary Must commit before removing imageorientation component

git-svn-id: svn+ssh://scm.forge.imag.fr/var/lib/gforge/chroot/scmrepos/svn/camitk/trunk/camitk@1579 ec899d31-69d1-42ba-9299-647d76f65fb3
parent 00c09ad4
# Call CamiTK CMake Macro to define the action
camitk_extension(ACTION_EXTENSION
NEEDS_COMPONENT_EXTENSION imageorientation
INCLUDE_DIRECTORIES ../../../components/imageorientation
NEEDS_COMPONENT_EXTENSION vtkmesh
INCLUDE_DIRECTORIES ../../../components/vtkmesh
)
......@@ -35,19 +35,31 @@
#include <QMetaEnum>
// From Vtk
#include <vtkProperty.h>
#include <vtkImageReslice.h>
#include <vtkTransform.h>
#include <vtkAxesActor.h>
#include <vtkCaptionActor2D.h>
#include <vtkTextActor.h>
#include <vtkTextProperty.h>
#include <vtkProperty2D.h>
#include <vtkAnnotatedCubeActor.h>
#include <vtkAssembly.h>
// CamiTK
#include <InteractiveViewer.h>
#include <Core.h>
#include <Log.h>
#include <Application.h>
#include <InteractiveViewer.h>
#include <RendererWidget.h>
#include <ImageComponent.h>
#include <ImageOrientationHelper.h>
#include <VtkMeshUtil.h>
// Local Components
#include <ImageOrientation.h>
//#include <ImageOrientation.h>
#include <MeshComponent.h>
using namespace camitk;
......@@ -70,9 +82,6 @@ ReorientImage::ReorientImage(ActionExtension* extension) : Action(extension) {
setFamily("Image Processing");
addTag("Dicom");
addTag("Orientation");
dialog = NULL;
imgOrientation = NULL;
internalViewer = NULL;
lettersMeaning.insert('R', RMeaning);
lettersMeaning.insert('L', LMeaning);
......@@ -81,6 +90,44 @@ ReorientImage::ReorientImage(ActionExtension* extension) : Action(extension) {
lettersMeaning.insert('I', IMeaning);
lettersMeaning.insert('S', SMeaning);
dialog = NULL;
axes = NULL;
buildAxes();
annotatedCube = NULL;
buildCube();
orientationTransform = NULL;
axesTransform = NULL;
orientationCubeTransform = NULL;
cubeTransform = NULL;
buildTransforms();
modelBoundingBox = NULL;
maleModel = NULL;
femaleModel = NULL;
buildGeometries();
internalViewer = NULL;
}
void ReorientImage::buildGeometries() {
QString testDataDir = Core::getTestDataDir();
QString boundingBoxFilename = testDataDir + "/ImageBoundingBox.vtk";
modelBoundingBox = VtkMeshUtil::vtkToGeometry(boundingBoxFilename.toStdString());
modelBoundingBox->setRenderingModes(InterfaceGeometry::Wireframe);
QString maleModelFilename = testDataDir + "/male.vtk";
maleModel = VtkMeshUtil::vtkToGeometry(maleModelFilename.toStdString());
maleModel->setColor(1.0, 0.75, 0.64);
QString femaleModelFilename = testDataDir + "/female.vtk";
femaleModel = VtkMeshUtil::vtkToGeometry(femaleModelFilename.toStdString());
femaleModel->setColor(1.0, 0.75, 0.64);
}
......@@ -91,6 +138,10 @@ void ReorientImage::initDialog() {
//-- init user interface
ui.setupUi(dialog);
//-- add the internal viewer
initInternalViewer();
ui.illustrationLayout->addWidget(internalViewer->getWidget(dialog));
ui.xDirection->setTextFormat(Qt::RichText);
ui.yDirection->setTextFormat(Qt::RichText);
ui.zDirection->setTextFormat(Qt::RichText);
......@@ -110,42 +161,34 @@ void ReorientImage::initDialog() {
// Reset image origin
ui.resetImageOriginRadioButton->setChecked(true);
// Set up the 3D viewer to visualize actual origin/orientation locations
internalViewer = InteractiveViewer::getNewViewer("Image Orientation Viewer", InteractiveViewer::GEOMETRY_VIEWER);
internalViewer->setHighlightMode(InteractiveViewer::OFF);
internalViewer->toggleCopyright(false);
internalViewer->getRendererWidget()->setCameraOrientation(RendererWidget::RIGHT_DOWN);
ui.illustrationLayout->addWidget(internalViewer->getWidget(dialog));
imgOrientation = new ImageOrientation();
imgOrientation->refreshInterfaceNode();
imgOrientation->refresh();
Application::refresh();
imgOrientation->changeVisibility(InteractiveViewer::get3DViewer(), false);
imgOrientation->changeVisibility(internalViewer, true);
internalViewer->refresh();
// Set the Dicom RCS Labels Menu
int indexOfEnum = imgOrientation->metaObject()->indexOfEnumerator("PossibleImageOrientations");
QMetaEnum enumType = imgOrientation->metaObject()->enumerator(indexOfEnum);
QStringList possibleVals;
int nbVals = enumType.keyCount();
for (int key = 0; key < nbVals; key++)
{
possibleVals << enumType.key(key);
}
ui.rcsComboBox->addItems(possibleVals);
ui.rcsComboBox->addItems(ImageOrientationHelper::getPossibleImageOrientations());
// Connect the slot
connect(ui.rcsComboBox, SIGNAL(currentIndexChanged(const QString&)), this, SLOT(rcsChanged(const QString&)));
connect(ui.savePushButton, SIGNAL(clicked()), this, SLOT(apply()));
connect(ui.maleRadioButton, SIGNAL(toggled(bool)), this, SLOT(modelChanged(bool)));
Application::refresh();
modelChanged(true);
rcsChanged(QString("RAI"));
internalViewer->refresh();
}
void ReorientImage::initInternalViewer() {
// Set up the 3D viewer to visualize actual origin/orientation locations
internalViewer = InteractiveViewer::getNewViewer("Image Orientation Viewer", InteractiveViewer::GEOMETRY_VIEWER);
internalViewer->setHighlightMode(InteractiveViewer::OFF);
internalViewer->toggleCopyright(false);
internalViewer->getRendererWidget()->setCameraOrientation(RendererWidget::RIGHT_DOWN);
internalViewer->getRendererWidget()->addProp(modelBoundingBox->getActor(InterfaceGeometry::Wireframe));
internalViewer->getRendererWidget()->addProp(axes);
internalViewer->getRendererWidget()->addProp(annotatedCube);
}
......@@ -160,27 +203,21 @@ void ReorientImage::rcsChanged(const QString index)
ui.yDirection->setText(lettersMeaning.value(yLetter));
ui.zDirection->setText(lettersMeaning.value(zLetter));
int indexOfEnum = imgOrientation->metaObject()->indexOfEnumerator("PossibleImageOrientations");
QMetaEnum enumType = imgOrientation->metaObject()->enumerator(indexOfEnum);
ImageOrientation::PossibleImageOrientations orient = (ImageOrientation::PossibleImageOrientations) (enumType.keysToValue(index.toStdString().c_str()));
imgOrientation->setProperty("Image Orientation", orient);
setAxesOrientation(index);
}
void ReorientImage::modelChanged(bool maleModel)
void ReorientImage::modelChanged(bool displayMaleModel)
{
if (maleModel)
imgOrientation->setProperty("Model display", ImageOrientation::MALE);
else
imgOrientation->setProperty("Model display", ImageOrientation::FEMALE);
if (internalViewer != NULL)
{
imgOrientation->changeVisibility(InteractiveViewer::get3DViewer(), false);
imgOrientation->changeVisibility(internalViewer, true);
internalViewer->refresh();
if (displayMaleModel) {
internalViewer->getRendererWidget()->removeProp(femaleModel->getActor(InterfaceGeometry::Surface));
internalViewer->getRendererWidget()->addProp(maleModel->getActor(InterfaceGeometry::Surface));
}
else {
internalViewer->getRendererWidget()->removeProp(maleModel->getActor(InterfaceGeometry::Surface));
internalViewer->getRendererWidget()->addProp(femaleModel->getActor(InterfaceGeometry::Surface));
}
internalViewer->refresh();
}
// --------------- destructor -------------------
ReorientImage::~ReorientImage() {
......@@ -196,7 +233,8 @@ QWidget * ReorientImage::getWidget() {
if (!dialog)
initDialog();
rcsChanged("RAI");
// rcsChanged("RAI");
ui.rcsComboBox->setCurrentIndex(0);
return dialog;
}
......@@ -213,20 +251,17 @@ Action::ApplyStatus ReorientImage::process( ImageComponent * image)
return ABORTED;
// 1- Get the selected new orientation
QString index = ui.rcsComboBox->currentText();
QChar xLetter = index.at(0);
QChar yLetter = index.at(1);
QChar zLetter = index.at(2);
int index = ui.rcsComboBox->currentIndex();
QString indexText = ui.rcsComboBox->currentText();
QChar xLetter = indexText.at(0);
QChar yLetter = indexText.at(1);
QChar zLetter = indexText.at(2);
ui.xDirection->setText(lettersMeaning.value(xLetter));
ui.yDirection->setText(lettersMeaning.value(yLetter));
ui.zDirection->setText(lettersMeaning.value(zLetter));
int indexOfEnum = imgOrientation->metaObject()->indexOfEnumerator("PossibleImageOrientations");
QMetaEnum enumType = imgOrientation->metaObject()->enumerator(indexOfEnum);
ImageOrientation::PossibleImageOrientations orient = (ImageOrientation::PossibleImageOrientations) (enumType.keysToValue(index.toStdString().c_str()));
ImageOrientationHelper::PossibleImageOrientations orient = (ImageOrientationHelper::PossibleImageOrientations) (index);
// 2- Compute the reslice matrix according to the new orientation
double * imgSpacing = img->getImageData()->GetSpacing();
int * imgDims = img->getImageData()->GetDimensions();
......@@ -235,7 +270,9 @@ Action::ApplyStatus ReorientImage::process( ImageComponent * image)
dims[1] = imgSpacing[1] * imgDims[1];
dims[2] = imgSpacing[2] * imgDims[2];
vtkSmartPointer<vtkTransform> transform = ImageOrientation::getTransformToRAI(orient, dims[0], dims[1], dims[2]);
vtkSmartPointer<vtkMatrix4x4> transformMatrix = ImageOrientationHelper::getTransformToRAI(orient, dims[0], dims[1], dims[2]);
vtkSmartPointer<vtkTransform> transform = vtkSmartPointer<vtkTransform>::New();
transform->SetMatrix(transformMatrix);
// 3- Create a new ImageComponent with the resliced image.
......@@ -251,7 +288,9 @@ Action::ApplyStatus ReorientImage::process( ImageComponent * image)
// Move the image back to the origin thanks to Frame
if (ui.resetImageOriginRadioButton->isChecked()) {
vtkSmartPointer<vtkTransform> backToOrigin = ImageOrientation::getTransformToRAI(orient, dims[0], dims[1], dims[2]);
vtkSmartPointer<vtkMatrix4x4> backToOriginMatrix = ImageOrientationHelper::getTransformToRAI(orient, dims[0], dims[1], dims[2]);
vtkSmartPointer<vtkTransform> backToOrigin = vtkSmartPointer<vtkTransform>::New();
backToOrigin->SetMatrix(backToOriginMatrix);
result->setTransformFromParent(backToOrigin);
}
......@@ -273,3 +312,198 @@ Action::ApplyStatus ReorientImage::process( ImageComponent * image)
return SUCCESS;
}
void ReorientImage::buildAxes()
{
//-- axes
axes = vtkSmartPointer<vtkAxesActor>::New();
axes->SetShaftTypeToCylinder();
axes->SetXAxisLabelText("x");
axes->SetYAxisLabelText("y");
axes->SetZAxisLabelText("z");
axes->SetTotalLength(0.2, 0.2, 0.2); // 10% of unit length
vtkSmartPointer<vtkTextProperty> axeXTextProp = vtkSmartPointer<vtkTextProperty>::New();
axeXTextProp->SetFontSize(20);
axeXTextProp->BoldOn();
axeXTextProp->ItalicOn();
axeXTextProp->ShadowOff();
axeXTextProp->SetFontFamilyToArial();
axes->GetXAxisCaptionActor2D()->SetCaptionTextProperty(axeXTextProp);
// remove the autoscaling so that the font size is smaller than default autoscale
axes->GetXAxisCaptionActor2D()->GetTextActor()->SetTextScaleModeToNone();
// set the color
axes->GetXAxisCaptionActor2D()->GetCaptionTextProperty()->SetColor(1, 0.3, 0.3);
// make sure the label can be hidden by any geometry, like the axes
axes->GetXAxisCaptionActor2D()->GetProperty()->SetDisplayLocationToBackground();
vtkSmartPointer<vtkTextProperty> axeYTextProp = vtkSmartPointer<vtkTextProperty>::New();
axeYTextProp->ShallowCopy(axeXTextProp);
axes->GetYAxisCaptionActor2D()->SetCaptionTextProperty(axeYTextProp);
axes->GetYAxisCaptionActor2D()->GetTextActor()->SetTextScaleModeToNone();
axes->GetYAxisCaptionActor2D()->GetCaptionTextProperty()->SetColor(0.3, 1, 0.3);
axes->GetYAxisCaptionActor2D()->GetProperty()->SetDisplayLocationToBackground();
vtkSmartPointer<vtkTextProperty> axeZTextProp = vtkSmartPointer<vtkTextProperty>::New();
axeZTextProp->ShallowCopy(axeXTextProp);
axes->GetZAxisCaptionActor2D()->SetCaptionTextProperty(axeZTextProp);
axes->GetZAxisCaptionActor2D()->GetTextActor()->SetTextScaleModeToNone();
axes->GetZAxisCaptionActor2D()->GetCaptionTextProperty()->SetColor(0.3, 0.3, 1.0);
axes->GetZAxisCaptionActor2D()->GetProperty()->SetDisplayLocationToBackground();
}
void ReorientImage::buildCube()
{
//-- annotated cube (right, left, anterior, posterior, inferior, superior)
// For image Display, the axis should be RAI :
// - X: from Right [R] (the Right of the patient) to Left [L] (the Left of the patient)
// - Y: from Anterior [A] (the Face of the patient) to Posterior [P] (the Back of the patient)
// - Z: from Inferior [I] (the Feet of the patient) to Superior [S] (the Head of the patient)
annotatedCube = vtkSmartPointer<vtkAnnotatedCubeActor>::New();
annotatedCube->SetXMinusFaceText("R");
annotatedCube->SetXPlusFaceText("L");
annotatedCube->SetYMinusFaceText("A");
annotatedCube->SetYPlusFaceText("P");
annotatedCube->SetZMinusFaceText("I");
annotatedCube->SetZPlusFaceText("S");
annotatedCube->SetXFaceTextRotation(90);
annotatedCube->SetZFaceTextRotation(90);
annotatedCube->SetFaceTextScale(0.65);
vtkSmartPointer<vtkProperty> acProp = annotatedCube->GetCubeProperty();
acProp->SetColor(0.5, 1, 1);
acProp = annotatedCube->GetTextEdgesProperty();
acProp->SetLineWidth(1);
acProp->SetDiffuse(0);
acProp->SetAmbient(1);
acProp->SetColor(0.18, 0.28, 0.23);
acProp = annotatedCube->GetXPlusFaceProperty();
acProp->SetColor(1, 0, 0);
acProp->SetInterpolationToFlat();
acProp = annotatedCube->GetXMinusFaceProperty();
acProp->SetColor(1, 0, 0);
acProp->SetInterpolationToFlat();
acProp = annotatedCube->GetYPlusFaceProperty();
acProp->SetColor(0, 1, 0);
acProp->SetInterpolationToFlat();
acProp = annotatedCube->GetYMinusFaceProperty();
acProp->SetColor(0, 1, 0);
acProp->SetInterpolationToFlat();
acProp = annotatedCube->GetZPlusFaceProperty();
acProp->SetColor(0, 0, 1);
acProp->SetInterpolationToFlat();
acProp = annotatedCube->GetZMinusFaceProperty();
acProp->SetColor(0, 0, 1);
acProp->SetInterpolationToFlat();
}
void ReorientImage::buildTransforms()
{
axesTransform = vtkSmartPointer<vtkTransform>::New();
axesTransform->PostMultiply();
axesTransform->Identity();
axes->SetUserTransform(axesTransform);
cubeTransform = vtkSmartPointer<vtkTransform>::New();
cubeTransform->PostMultiply();
cubeTransform->Identity();
cubeTransform->Scale(0.1, 0.1, 0.1);
annotatedCube->GetAssembly()->SetUserTransform( cubeTransform );
orientationTransform = vtkSmartPointer<vtkTransform>::New();
orientationTransform->Identity();
axesTransform->Concatenate(orientationTransform);
orientationCubeTransform = vtkSmartPointer<vtkTransform>::New();
orientationCubeTransform->Identity();
cubeTransform->Concatenate(orientationCubeTransform);
}
void ReorientImage::setAxesOrientation(const QString orientationStr)
{
ImageOrientationHelper::PossibleImageOrientations orientation = ImageOrientationHelper::getOrientationAsEnum(orientationStr);
double dimX = 1.0;
double dimY = 1.0;
double dimZ = 2.0;
orientationTransform->Identity();
orientationTransform->SetMatrix(ImageOrientationHelper::getTransformFromRAI(orientation, dimX, dimY, dimZ));
orientationCubeTransform->Identity();
switch (orientation) {
default:
case camitk::ImageOrientationHelper::RAI:
// Keep Identity for RAI (default orientation)
break;
case camitk::ImageOrientationHelper::RPS:
// For the cube, just translate (in original axis then...)
orientationCubeTransform->Translate(0.0, dimY, dimZ);
break;
case camitk::ImageOrientationHelper::RIP:
orientationCubeTransform->Translate(0.0, dimY, 0.0);
break;
case camitk::ImageOrientationHelper::RSA:
orientationCubeTransform->Translate(0.0, 0.0, dimZ);
break;
case camitk::ImageOrientationHelper::LAS:
orientationCubeTransform->Translate(dimX, 0.0, dimZ);
break;
case camitk::ImageOrientationHelper::LPI:
orientationCubeTransform->Translate(dimX, dimY, 0.0);
break;
case camitk::ImageOrientationHelper::LIA:
orientationCubeTransform->Translate(dimX, 0.0, 0.0);
break;
case camitk::ImageOrientationHelper::ARS:
orientationCubeTransform->Translate(0.0, 0.0, dimZ);
break;
case camitk::ImageOrientationHelper::ALI:
orientationCubeTransform->Translate(dimX, 0.0, 0.0);
break;
case camitk::ImageOrientationHelper::AIR:
break;
case camitk::ImageOrientationHelper::ASL:
orientationCubeTransform->Translate(dimX, 0.0, dimZ);
break;
case camitk::ImageOrientationHelper::PRI:
orientationCubeTransform->Translate(0.0, dimY, 0.0);
break;
case camitk::ImageOrientationHelper::PLS:
orientationCubeTransform->Translate(dimX, dimY, dimZ);
break;
case camitk::ImageOrientationHelper::PIL:
orientationCubeTransform->Translate(dimX, dimY, 0.0);
break;
case camitk::ImageOrientationHelper::PSR:
orientationCubeTransform->Translate(0.0, dimY, dimZ);
break;
case camitk::ImageOrientationHelper::IRA:
break;
case camitk::ImageOrientationHelper::ILP:
orientationCubeTransform->Translate(dimX, dimY, 0.0);
break;
case camitk::ImageOrientationHelper::IAL:
orientationCubeTransform->Translate(dimX, 0.0, 0.0);
break;
case camitk::ImageOrientationHelper::IPR:
orientationCubeTransform->Translate(0.0, dimY, 0.0);
break;
case camitk::ImageOrientationHelper::SRP:
orientationCubeTransform->Translate(0.0, dimY, dimZ);
break;
case camitk::ImageOrientationHelper::SLA:
orientationCubeTransform->Translate(dimX, 0.0, dimZ);
break;
case camitk::ImageOrientationHelper::SAR:
orientationCubeTransform->Translate(0.0, 0.0, dimZ);
break;
case camitk::ImageOrientationHelper::SPL:
orientationCubeTransform->Translate(dimX, dimY, dimZ);
break;
}
internalViewer->refresh();
}
......@@ -26,21 +26,15 @@
#ifndef MOVEFRAME_H
#define MOVEFRAME_H
// Include Action.h to be able to inherit from Action
#include "Action.h"
#include "Component.h"
#include <QVector3D>
#include <vtkTransform.h>
#include <vtkTransformFilter.h>
#include <vtkSmartPointer.h>
// Include ui_ReorientImage.h to be able to declare an instance of Ui::ReorientImage
#include "ui_ReorientImage.h"
//class ImageOrientation;
#include "ImageOrientation.h"
class vtkTransform;
class vtkAnnotatedCubeActor;
namespace camitk {
class Geometry;
class ImageComponent;
class InteractiveViewer;
}
......@@ -65,12 +59,23 @@ public slots:
virtual void rcsChanged(const QString index);
virtual void modelChanged(bool maleModel);
virtual void modelChanged(bool displayMaleModel);
private:
/// initialize the dialog
void initDialog();
/// Build Geometries
void buildGeometries();
void buildAxes();
void buildCube();
void buildTransforms();
void initInternalViewer();
void setAxesOrientation(const QString orientation);
camitk::InteractiveViewer * internalViewer;
/// Actually perform the image transformation
......@@ -82,7 +87,23 @@ private:
/// the dialog
QDialog *dialog;
ImageOrientation * imgOrientation;
/// axes actor
vtkSmartPointer<vtkAxesActor> axes;
/// annotated cube actor
vtkSmartPointer<vtkAnnotatedCubeActor> annotatedCube;
vtkSmartPointer<vtkTransform> orientationTransform;
// The cube should not rotate, just translate...
vtkSmartPointer<vtkTransform> orientationCubeTransform;
vtkSmartPointer<vtkTransform> cubeTransform;
vtkSmartPointer<vtkTransform> axesTransform;
camitk::Geometry * modelBoundingBox;
camitk::Geometry * maleModel;
camitk::Geometry * femaleModel;
QMap<QChar, QString> lettersMeaning;
......
#include "ImageOrientation.h"
// Qt Includes
......@@ -35,7 +33,7 @@
#include <Core.h>
#include <Property.h>
#include <MeshComponent.h>
#include <VtkMeshComponent.h>
//#include <VtkMeshComponent.h>
#include <InteractiveViewer.h>
#include <Application.h>
......@@ -54,13 +52,12 @@ ImageOrientation::ImageOrientation()
void ImageOrientation::buildProperties()
{
imageOrientation = new Property("Image Orientation", ImageOrientation::RAI, "Orientation of image acquisition", "RCS");
imageOrientation->setEnumTypeName("PossibleImageOrientations");
imageOrientation = new Property("Image Orientation", ImageOrientationHelper::RAI, "Orientation of image acquisition", "RCS");
imageOrientation->setEnumTypeName("ImageOrientationHelper::PossibleImageOrientations");
// register the new prop as an action parameter
addProperty(imageOrientation);
model = new Property("Model display", ImageOrientation::MALE, "Choose male or female model (created with MakeHuman)", "");
// model = new Property("Model display", PossibleModels::MALE, "Choose male or female model (created with MakeHuman)", "");
model->setEnumTypeName("PossibleModels");
addProperty(model);
......@@ -197,7 +194,7 @@ void ImageOrientation::updateProperty(QString name, QVariant value)
Component::updateProperty(name, value);
if (name == QString("Image Orientation")) {
setImageOrientation((PossibleImageOrientations) value.toInt());
setImageOrientation((ImageOrientationHelper::PossibleImageOrientations) value.toInt());
}
else if (name == QString("Model display")) {
......@@ -214,15 +211,21 @@ void ImageOrientation::setModel(PossibleModels model)
removeModel();
MeshComponent * newModel = NULL;
Component * tmpComp = NULL;
switch (model) {
default:
case MALE:
newModel = new VtkMeshComponent(testDataDir + "/male.vtk");
// newModel = new VtkMeshComponent(testDataDir + "/male.vtk");
// Application::open already implements try/catch
tmpComp = Application::open(testDataDir + "/male.vtk");
newModel = dynamic_cast<MeshComponent *>(tmpComp);
break;