Medical Imaging Interaction Toolkit  2016.11.0
Medical Imaging Interaction Toolkit
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
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.