AnatomicalOrientation describes the relationship between 3D axes of a FrameOfReference and medical image anatomical orientation labels.
AnatomicalOrientation describes the relationship between 3D axes of a FrameOfReference and medical image anatomical orientation labelsFor most methods, each axis is referred to by its index:
The label of the positive direction is called "maxLabel". The label of the negative direction is called "minLabel".
Three letter codes are supported, e.g. "RAI", "LAS", or its "+"" variant "LPS+".
Supported letters are R (right), L (left), A (anterior),
P (posterior), I (inferior) or F (foot), S (superior) or H (head).
3 letter code "RAI" means
- axis 0 (X) goes from Right (negative direction) to left (positive direction)
- axis 1 (Y) goes from Anterior to posterior
- axis 2 (Z) goes from Inferior to superior.
The "+" variant reverses this convention, so LPS+ is equivalent to RAI
Using custom labels is also supported (this is incompatible with three letter code convention). In this case you can set positive and/or negative direction labels for any axis. Custom labels should only be used for specialized context / specific organ anatomy description (e.g. heart imaging along apex/base axis), as the standard viewer can only deal with the standard axial/coronal/sagittal orientation. Using standard 3-letter orientation is recommended.
This replaces and extend ImageOrientationHelper.
#ifndef ANATOMICALORIENTATION_H
#define ANATOMICALORIENTATION_H
#include <array>
#include <QVariantList>
#include <QVariantMap>
#include <QVariant>
#include <QString>
#include <QUuid>
class AnatomicalOrientation: public InterfacePersistence {
public:
}
}
AnatomicalOrientation(QString minXLabel, QString maxXLabel, QString minYLabel, QString maxYLabel, QString minZLabel, QString maxZLabel) {
setOrientation(minXLabel, maxXLabel, minYLabel, maxYLabel, minZLabel, maxZLabel);
}
known = false;
code = "";
minLabels.fill("");
maxLabels.fill("");
}
return !known;
}
if (this->set3LetterCode(threeLetterCode)) {
known = true;
}
else {
known = false;
}
}
void setOrientation(QString minXLabel, QString maxXLabel, QString minYLabel, QString maxYLabel, QString minZLabel, QString maxZLabel) {
code = "";
minLabels = {minXLabel, minYLabel, minZLabel};
maxLabels = {maxXLabel, maxYLabel, maxZLabel};
known = true;
}
if (axis >= 0 && axis < 3) {
code = "";
minLabels[axis] = minLabel;
known = true;
}
}
if (axis >= 0 && axis < 3) {
code = "";
maxLabels[axis] = maxLabel;
known = true;
}
}
void setLabels(
int axis, QString minLabel, QString maxLabel) {
};
if (axis >= 0 && axis < 3) {
return minLabels[axis];
}
else {
return "";
}
}
if (axis >= 0 && axis < 3) {
return maxLabels[axis];
}
else {
return "";
}
}
for (unsigned int ax = 0; ax < 3; ++ax) {
if (minLabels[ax] == name) {
return {ax, true};
}
else if (maxLabels[ax] == name) {
return {ax, false};
}
}
return {-1, false};
}
QString invertedCode = code;
for (int i = 0; i < code.size(); ++i) {
if (code[i] == 'R') {
invertedCode[i] = 'L';
}
else if (code[i] == 'L') {
invertedCode[i] = 'R';
}
else if (code[i] == 'A') {
invertedCode[i] = 'P';
}
else if (code[i] == 'P') {
invertedCode[i] = 'A';
}
else if (code[i] == 'I') {
invertedCode[i] = 'S';
}
else if (code[i] == 'S') {
invertedCode[i] = 'I';
}
else if (code[i] == 'F') {
invertedCode[i] = 'H';
}
else if (code[i] == 'H') {
invertedCode[i] = 'F';
}
}
return invertedCode;
}
if (!known || code.isEmpty()) {
return "";
}
if (plus) {
plusCode.append('+');
return plusCode;
}
else {
return code;
}
}
QString
getLabel(
int axis,
bool minDirection)
const {
if (axis >= 0 && axis < 3) {
return minDirection ? minLabels[axis] : maxLabels[axis];
}
return "";
}
if (known) {
return QVariantMap {
{"code", code},
{"minLabels", QVariantList{minLabels[0], minLabels[1], minLabels[2]}},
{"maxLabels", QVariantList{maxLabels[0], maxLabels[1], maxLabels[2]}},
};
}
else {
return QVariantMap();
}
}
known = false;
code = "";
QVariantMap map = variant.toMap();
QVariantList list;
if (map.contains("code")) {
known = true;
code = map.value("code").toString();
}
if (map.contains("minLabels") && map.contains("maxLabels")) {
known = true;
list = map.value("minLabels").toList();
if (list.size() == 3) {
minLabels[0] = list[0].toString();
minLabels[1] = list[1].toString();
minLabels[2] = list[2].toString();
}
else {
minLabels.fill("");
}
list = map.value("maxLabels").toList();
if (list.size() == 3) {
maxLabels[0] = list[0].toString();
maxLabels[1] = list[1].toString();
maxLabels[2] = list[2].toString();
}
else {
maxLabels.fill("");
}
}
else {
if (code.isEmpty()) {
minLabels.fill("");
maxLabels.fill("");
}
else {
set3LetterCode(code);
}
}
}
bool setUuid(QUuid newid)
override {
return false;
}
return QUuid();
}
private:
std::array<QString, 3> minLabels;
std::array<QString, 3> maxLabels;
bool known;
QString code;
bool set3LetterCode(QString code = "", bool forcePlus = false) {
if (code.size() < 3 || code.size() > 4) {
return false;
}
if ((code.size() > 3 && code[3] == '+') || forcePlus) {
}
else {
this->code = code;
}
this->code.truncate(3);
minLabels[0] = code[0];
minLabels[1] = code[1];
minLabels[2] = code[2];
maxLabels[0] = invertedCode[0];
maxLabels[1] = invertedCode[1];
maxLabels[2] = invertedCode[2];
known = true;
return true;
}
};
}
#endif
void setMaxLabel(int axis, QString maxLabel)
Set the label of the corresponding axis positive direction.
Definition AnatomicalOrientation.h:161
bool setUuid(QUuid newid) override
SetUuid does nothing It does not store the uuid, but is needed to implement InterfacePersistence.
Definition AnatomicalOrientation.h:367
QString getMaxLabel(int axis) const
Get the label of the positive/maximum direction of the specified axis.
Definition AnatomicalOrientation.h:194
QString getLabel(int axis, bool minDirection) const
Returns the label of the corresponding axis/direction (or empty string if there is no label).
Definition AnatomicalOrientation.h:289
QString getMinLabel(int axis) const
Get the label of the negative/minimum direction of the specified axis.
Definition AnatomicalOrientation.h:182
void setOrientation(QString threeLetterCode)
Sets the orientation using the standard 3-letter code.
Definition AnatomicalOrientation.h:127
void setLabels(int axis, QString minLabel, QString maxLabel)
Set both negative and positive direction labels for an axis.
Definition AnatomicalOrientation.h:174
QString get3LetterCode(bool plus=false) const
Return the current 3 letter code or an empty string if it is unknown or custom.
Definition AnatomicalOrientation.h:269
void setUnkown()
Reset anatomical information to unknown.
Definition AnatomicalOrientation.h:110
QVariant toVariant() const override
Convert all data from the object to a QVariantMap.
Definition AnatomicalOrientation.h:302
bool isUnknown() const
Check if anatomical information is unknown.
Definition AnatomicalOrientation.h:120
AnatomicalOrientation()
Default constructor.
Definition AnatomicalOrientation.h:89
void fromVariant(const QVariant &variant) override
Load data from a QVariant to initialize the current object.
Definition AnatomicalOrientation.h:318
QUuid getUuid() const override
Returns an invalid uuid because AnatomicalOrientation is part of a FrameOfReference which has its own...
Definition AnatomicalOrientation.h:375
static QString invert3LetterCode(const QString &code)
Returns the inverted 3-letter code (e.g.
Definition AnatomicalOrientation.h:231
void setMinLabel(int axis, QString minLabel)
Set the label of the corresponding axis negative direction.
Definition AnatomicalOrientation.h:150
std::pair< int, bool > getAxisFromName(QString name) const
Definition AnatomicalOrientation.h:215