Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
mitkSortByImagePositionPatient.cpp
Go to the documentation of this file.
1 /*===================================================================
2 
3 The Medical Imaging Interaction Toolkit (MITK)
4 
5 Copyright (c) German Cancer Research Center,
6 Division of Medical and Biological Informatics.
7 All rights reserved.
8 
9 This software is distributed WITHOUT ANY WARRANTY; without
10 even the implied warranty of MERCHANTABILITY or FITNESS FOR
11 A PARTICULAR PURPOSE.
12 
13 See LICENSE.txt or http://www.mitk.org for details.
14 
15 ===================================================================*/
16 
18 #include "mitkDICOMTag.h"
19 
22 :DICOMSortCriterion(secondaryCriterion)
23 {
24 }
25 
28 {
29 }
30 
33 :DICOMSortCriterion(other)
34 {
35 }
36 
40 {
41  if (this != &other)
42  {
44  }
45  return *this;
46 }
47 
48 bool
50 ::operator==(const DICOMSortCriterion& other) const
51 {
52  return dynamic_cast<const SortByImagePositionPatient*>(&other) != nullptr; // same class
53 }
54 
55 void
57 ::Print(std::ostream& os) const
58 {
59  os << "(0020,0032) Image Position (Patient) along normal of (0020,0037) Image Orientation (Patient)";
60 }
61 
65 {
66  DICOMTagList tags;
67  tags.push_back( DICOMTag(0x0020, 0x0032) ); // ImagePositionPatient
68  tags.push_back( DICOMTag(0x0020, 0x0037) ); // ImageOrientationPatient
69 
70  return tags;
71 }
72 
73 bool
76 {
77  bool possible(false);
78  double distance = InternalNumericDistance(left, right, possible); // returns 0.0 if not possible
79  if (possible)
80  {
81  return distance > 0.0;
82  }
83  else
84  {
85  return this->NextLevelIsLeftBeforeRight(left, right);
86  }
87 }
88 
89 double
92 {
93  // sort by distance to world origin, assuming (almost) equal orientation
94  static const DICOMTag tagImagePositionPatient = DICOMTag(0x0020,0x0032); // Image Position (Patient)
95  static const DICOMTag tagImageOrientation = DICOMTag(0x0020, 0x0037); // Image Orientation
96 
97  Vector3D leftRight; leftRight.Fill(0.0);
98  Vector3D leftUp; leftUp.Fill(0.0);
99  bool leftHasOrientation(false);
100  DICOMStringToOrientationVectors( left->GetTagValueAsString( tagImageOrientation ).value,
101  leftRight, leftUp, leftHasOrientation );
102 
103  Vector3D rightRight; rightRight.Fill(0.0);
104  Vector3D rightUp; rightUp.Fill(0.0);
105  bool rightHasOrientation(false);
106  DICOMStringToOrientationVectors(right->GetTagValueAsString(tagImageOrientation).value,
107  rightRight, rightUp, rightHasOrientation );
108 
109  Point3D leftOrigin; leftOrigin.Fill(0.0f);
110  bool leftHasOrigin(false);
111  leftOrigin = DICOMStringToPoint3D(left->GetTagValueAsString(tagImagePositionPatient).value, leftHasOrigin);
112 
113  Point3D rightOrigin; rightOrigin.Fill(0.0f);
114  bool rightHasOrigin(false);
115  rightOrigin = DICOMStringToPoint3D(right->GetTagValueAsString(tagImagePositionPatient).value, rightHasOrigin);
116 
117  // we tolerate very small differences in image orientation, since we got to know about
118  // acquisitions where these values change across a single series (7th decimal digit)
119  // (http://bugs.mitk.org/show_bug.cgi?id=12263)
120  // still, we want to check if our assumption of 'almost equal' orientations is valid
121  for (unsigned int dim = 0; dim < 3; ++dim)
122  {
123  if ( fabs(leftRight[dim] - rightRight[dim]) > 0.0001
124  || fabs(leftUp[dim] - rightUp[dim]) > 0.0001)
125  {
126  MITK_ERROR << "Dicom images have different orientations.";
127  throw std::logic_error("Dicom images have different orientations. Call GetSeries() first to separate images.");
128  }
129  }
130 
131  Vector3D normal;
132  normal[0] = leftRight[1] * leftUp[2] - leftRight[2] * leftUp[1];
133  normal[1] = leftRight[2] * leftUp[0] - leftRight[0] * leftUp[2];
134  normal[2] = leftRight[0] * leftUp[1] - leftRight[1] * leftUp[0];
135 
136  double leftDistance = 0.0;
137  double rightDistance = 0.0;
138 
139  // this computes the distance from world origin (0,0,0) ALONG THE NORMAL of the image planes
140  for (unsigned int dim = 0; dim < 3; ++dim)
141  {
142  leftDistance += normal[dim] * leftOrigin[dim];
143  rightDistance += normal[dim] * rightOrigin[dim];
144  }
145 
146  // if we can sort by just comparing the distance, we do exactly that
147  if ( fabs(leftDistance - rightDistance) >= mitk::eps)
148  {
149  possible = true;
150  // default: compare position
151  return rightDistance - leftDistance; // if (left < right> ==> diff > 0
152  }
153  else
154  {
155  possible = false;
156  return 0.0;
157  }
158 }
159 
160 
161 double
164 {
165  bool possible(false);
166  double retVal = InternalNumericDistance(from, to, possible); // returns 0.0 if not possible
167  return possible ? retVal : 0.0;
168 }
virtual bool operator==(const DICOMSortCriterion &other) const override
itk::SmartPointer< Self > Pointer
#define MITK_ERROR
Definition: mitkLogMacros.h:24
std::vector< DICOMTag > DICOMTagList
Definition: mitkDICOMTag.h:64
void DICOMStringToOrientationVectors(const std::string &s, Vector3D &right, Vector3D &up, bool &successful)
Convert DICOM string describing a point two Vector3D.
Representation of a DICOM tag.
Definition: mitkDICOMTag.h:37
use the deprecated old MITK testing style If possible
Sort by distance of image origin along image normal (for use in DICOMTagBasedSorter).
DICOMSortCriterion & operator=(const DICOMSortCriterion &other)
SortByImagePositionPatient(DICOMSortCriterion::Pointer secondaryCriterion=nullptr)
Interface to datasets that is presented to sorting classes such as DICOMDatasetSorter.
virtual void Print(std::ostream &os) const override
brief describe this class in given stream.
virtual DICOMDatasetFinding GetTagValueAsString(const DICOMTag &tag) const =0
Return a DICOMDatasetFinding instance of the tag. The return containes (if valid) the raw value of th...
virtual DICOMTagList GetTagsOfInterest() const override
Tags used for comparison.
virtual double NumericDistance(const mitk::DICOMDatasetAccess *from, const mitk::DICOMDatasetAccess *to) const override
Calculate a distance between two datasets. This ansers the question of consecutive datasets...
A tag based sorting criterion for use in DICOMTagBasedSorter.
MITKCORE_EXPORT const ScalarType eps
double InternalNumericDistance(const mitk::DICOMDatasetAccess *from, const mitk::DICOMDatasetAccess *to, bool &possible) const
Point3D DICOMStringToPoint3D(const std::string &s, bool &successful)
Convert DICOM string describing a point to Point3D.
SortByImagePositionPatient & operator=(const SortByImagePositionPatient &other)
virtual bool IsLeftBeforeRight(const mitk::DICOMDatasetAccess *left, const mitk::DICOMDatasetAccess *right) const override
Answer the sorting question.