Commit 4df1ce0e authored by Alexis Girault's avatar Alexis Girault
Browse files

Add class to handle conversion between anatomical orientations

parent 0a9fb2bd
set(classes
vtkAmoebaMinimizer
vtkAnatomicalOrientation
vtkFunctionSet
vtkInitialValueProblemSolver
vtkMatrix3x3
......
/*=========================================================================
Program: Visualization Toolkit
Module: vtkAnatomicalOrientation.cxx
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
#include "vtkAnatomicalOrientation.h"
#include <iostream>
#include <sstream>
#include <algorithm>
//----------------------------------------------------------------------------
const vtkAnatomicalOrientation::Axis vtkAnatomicalOrientation::ValidAxes[6] =
{
Axis::L,
Axis::R,
Axis::P,
Axis::A,
Axis::S,
Axis::I
};
//----------------------------------------------------------------------------
vtkAnatomicalOrientation::Axis vtkAnatomicalOrientation::AxisInverse(Axis axis)
{
switch (axis)
{
case Axis::L: return Axis::R;
case Axis::R: return Axis::L;
case Axis::P: return Axis::A;
case Axis::A: return Axis::P;
case Axis::S: return Axis::I;
case Axis::I: return Axis::S;
case Axis::None: return Axis::None;
}
}
//----------------------------------------------------------------------------
char vtkAnatomicalOrientation::AxisToChar(Axis dir)
{
switch (dir)
{
case Axis::L: return 'L';
case Axis::R: return 'R';
case Axis::P: return 'P';
case Axis::A: return 'A';
case Axis::S: return 'S';
case Axis::I: return 'I';
case Axis::None: return 0;
}
}
//----------------------------------------------------------------------------
vtkAnatomicalOrientation::Axis vtkAnatomicalOrientation::AxisFromChar(char letter)
{
for (const Axis& axis : ValidAxes)
{
if (letter == AxisToChar(axis))
{
return axis;
}
}
return Axis::None;
}
//----------------------------------------------------------------------------
std::string vtkAnatomicalOrientation::AxisToString(Axis axis)
{
switch (axis)
{
case Axis::L: return "Left";
case Axis::R: return "Right";
case Axis::P: return "Posterior";
case Axis::A: return "Anterior";
case Axis::S: return "Superior";
case Axis::I: return "Inferior";
case Axis::None: return "";
}
}
//----------------------------------------------------------------------------
std::string vtkAnatomicalOrientation::AxisToLowercaseString(Axis axis)
{
std::string name = AxisToString(axis);
std::transform(name.begin(), name.end(), name.begin(), ::tolower);
return name;
}
//----------------------------------------------------------------------------
vtkAnatomicalOrientation::Axis vtkAnatomicalOrientation::AxisFromString(std::string name)
{
for (const Axis& axis : ValidAxes)
{
if (name == AxisToString(axis) || name == AxisToLowercaseString(axis))
{
return axis;
}
}
return Axis::None;
}
//----------------------------------------------------------------------------
vtkAnatomicalOrientation::vtkAnatomicalOrientation(Axis X, Axis Y, Axis Z)
: X(X), Y(Y), Z(Z)
{
}
//----------------------------------------------------------------------------
vtkAnatomicalOrientation::vtkAnatomicalOrientation(std::string str)
{
this->SetForAcronym(str);
if (X == Axis::None || Y == Axis::None)
{
this->SetForString(str, '-');
}
}
//----------------------------------------------------------------------------
const vtkAnatomicalOrientation vtkAnatomicalOrientation::LPS = vtkAnatomicalOrientation("LPS");
//----------------------------------------------------------------------------
bool vtkAnatomicalOrientation::operator==(const vtkAnatomicalOrientation& rhs)
{
return this->X == rhs.X && this->Y == rhs.X && this->Z == rhs.Z;
}
//----------------------------------------------------------------------------
bool vtkAnatomicalOrientation::operator!=(const vtkAnatomicalOrientation& rhs)
{
return !(*this == rhs);
}
//----------------------------------------------------------------------------
vtkAnatomicalOrientation::Axis& vtkAnatomicalOrientation::operator[](int i)
{
if (i == 0) return this->X;
if (i == 1) return this->Y;
if (i == 2) return this->Z;
else
{
std::cerr << "Out of bounds of the coordinate system" << std::endl;
exit(0);
}
}
//----------------------------------------------------------------------------
bool vtkAnatomicalOrientation::IsValid() const
{
return
this->X != Axis::None &&
this->Y != Axis::None &&
this->Z != Axis::None &&
this->Z != this->Y &&
this->Z != this->X &&
this->Y != this->X &&
this->Z != AxisInverse(this->Y) &&
this->Z != AxisInverse(this->X) &&
this->Y != AxisInverse(this->X);
}
//----------------------------------------------------------------------------
std::string vtkAnatomicalOrientation::GetAsAcronym() const
{
std::string acronym = "";
acronym += AxisToChar(this->X);
acronym += AxisToChar(this->Y);
acronym += AxisToChar(this->Z);
return acronym;
}
//----------------------------------------------------------------------------
void vtkAnatomicalOrientation::SetForAcronym(std::string acronym)
{
try {
this->X = AxisFromChar(acronym.at(0));
} catch (const std::exception&) {
this->X = Axis::None;
}
try {
this->Y = AxisFromChar(acronym.at(1));
} catch (const std::exception&) {
this->Y = Axis::None;
}
try {
this->Z = AxisFromChar(acronym.at(2));
} catch (const std::exception&) {
this->Z = Axis::None;
}
}
//----------------------------------------------------------------------------
std::string vtkAnatomicalOrientation::GetAsString(std::string separator) const
{
std::string XStr = AxisToLowercaseString(this->X);
std::string YStr = AxisToLowercaseString(this->Y);
std::string ZStr = AxisToLowercaseString(this->Z);
std::string str = XStr;
if (YStr.length() > 0)
{
if (str.length() > 0)
{
str += separator;
}
str += YStr;
}
if (ZStr.length() > 0)
{
if (str.length() > 0)
{
str += separator;
}
str += ZStr;
}
return str;
}
//----------------------------------------------------------------------------
void vtkAnatomicalOrientation::SetForString(std::string str, char delim)
{
std::string XYZStr[3];
int i = 0;
std::stringstream ss(str);
std::string token;
while (std::getline(ss, token, delim) && i < 3)
{
XYZStr[i] = token;
i++;
}
this->X = AxisFromString(XYZStr[0]);
this->Y = AxisFromString(XYZStr[1]);
this->Z = AxisFromString(XYZStr[2]);
}
//----------------------------------------------------------------------------
void vtkAnatomicalOrientation::GetTransformTo(vtkAnatomicalOrientation finalOrientation,
double* transform)
{
for (int i = 0; i < 3; ++i) {
for (int j = 0; j < 3; ++j) {
if ((*this)[i] == finalOrientation[j])
transform[i*3+j] = 1;
else if ((*this)[i] == AxisInverse(finalOrientation[j]))
transform[i*3+j] = -1;
else
transform[i*3+j] = 0;
}
}
}
/*=========================================================================
Program: Visualization Toolkit
Module: vtkAnatomicalOrientation.h
Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
All rights reserved.
See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
This software is distributed WITHOUT ANY WARRANTY; without even
the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE. See the above copyright notice for more information.
=========================================================================*/
/**
* @class vtkAnatomicalOrientation
* @brief Define anatomical orientation axis, coordinates and transforms
*
* This class defines the different anatomical axes that are used in
* orientated images, typically in the medical field: L (left), R (right),
* P (posterior), A (anterior), S (superior) and I (inferior). This class
* exposes static methods to handle those axes. An instance of this class
* represents a coordinate system composed of three of those axes (XYZ),
* which can be accessed by the X, Y, Z variables, or with the [] operator.
*
* In VTK, images are defined in the LPS coordinate system. The main
* purpose of this class is to be able to convert images read from
* third-party formats which are not in LPS coordinates, by providing a
* transform to go from that coordinate system to LPS. That transform can
* be applied to the data or to the direction matrix of the image.
*
* @sa
* vtkImageReader2
*/
#ifndef vtkAnatomicalOrientation_h
#define vtkAnatomicalOrientation_h
#include "vtkCommonMathModule.h" // For export macro
#include <string>
class VTKCOMMONMATH_EXPORT vtkAnatomicalOrientation
{
public:
//@{
/**
* Anatomical Axis enumeration. The valid ones are stored in ValidAxes.
*/
enum class Axis { L, R, P, A, S, I, None };
static const Axis ValidAxes[6];
//@}
/**
* Get the opposite axis of an axis
*/
static Axis AxisInverse(Axis axis);
//@{
/**
* Get a string or char representation of an axis, and vice-versa
*/
static char AxisToChar(Axis dir);
static Axis AxisFromChar(char letter);
static std::string AxisToString(Axis axis);
static std::string AxisToLowercaseString(Axis axis);
static Axis AxisFromString(std::string name);
//@}
/**
* Constructor defaulting to invalid axes (None).
* X, Y and Z can be inputed.
*/
vtkAnatomicalOrientation(Axis X = Axis::None, Axis Y = Axis::None, Axis Z = Axis::None);
/**
* String parsing constructor.
* @sa AxisFromString AxisFromChar
*/
vtkAnatomicalOrientation(std::string str);
/**
* Static constant instance of the class set to Left-Posterior-Superior (LPS)
* which is the coordinate system used in VTK for images.
*/
static const vtkAnatomicalOrientation LPS;
/**
* Returns true if the coordinate system is 3D (no None), and the axes
* all differ from each other, and each other's opposite.
*/
bool IsValid() const;
//@{
/**
* Get/Set the string or char representation of the coordinate system
*/
std::string GetAsString(std::string separator) const;
void SetForString(std::string str, char delim);
std::string GetAsAcronym() const;
void SetForAcronym(std::string acronym);
//@}
/**
* Get the 9 values of the 3x3 matrix to project from this
* system of coordinate to a given system of coordinates
*/
void GetTransformTo(vtkAnatomicalOrientation finalOrientation, double* transform);
  • The wrappers prefer parameter declarations like "double transform[9]" that indicate the size. If the wrappers know the expected size, they can generate code that is safer and much more efficient.

  • Thanks. Changed in cdf1cd7d.

Please register or sign in to reply
//@{
/**
* The world axis values of the coordinate system
*/
Axis X;
Axis Y;
Axis Z;
//@}
bool operator==(const vtkAnatomicalOrientation& rhs);
bool operator!=(const vtkAnatomicalOrientation& rhs);
Axis& operator[](int i);
};
#endif
Supports Markdown
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