25 , m_ITKAssumedSliceSpacing(0.0)
26 , m_NumberOfSlicesApart(0)
31 #define doublepoint(x) \ 38 #define doublevector(x) \ 47 unsigned int numberOfSlicesApart)
51 , m_NumberOfSlicesApart(numberOfSlicesApart)
53 assert(numberOfSlicesApart);
77 Vector3Dd normal = itk::CrossProduct(right, up);
78 Point3Dd pointAlongNormal = origin2 + normal;
80 double numerator = itk::CrossProduct( pointAlongNormal - origin2 , origin2 - origin1 ).GetSquaredNorm();
81 double denominator = (pointAlongNormal - origin2).GetSquaredNorm();
83 double distance = sqrt(numerator / denominator);
85 if ( distance > 0.001 )
87 MITK_DEBUG <<
" Series seems to contain a tilted (or sheared) geometry";
88 MITK_DEBUG <<
" Distance of expected slice origin from actual slice origin: " << distance;
89 MITK_DEBUG <<
" ==> storing this shift for later analysis:";
96 Point3Dd projectionRight = projectPointOnLine( origin1, origin2, right );
97 Point3Dd projectionNormal = projectPointOnLine( origin1, origin2, normal );
99 m_ShiftRight = (projectionRight - origin2).GetNorm();
100 m_ShiftNormal = (projectionNormal - origin2).GetNorm();
112 double signedDistance = (
113 planeNormal[0] * testPoint[0]
114 + planeNormal[1] * testPoint[1]
115 + planeNormal[2] * testPoint[2]
117 planeNormal[0] * origin2[0]
118 + planeNormal[1] * origin2[1]
119 + planeNormal[2] * origin2[2]
123 sqrt( planeNormal[0] * planeNormal[0]
124 + planeNormal[1] * planeNormal[1]
125 + planeNormal[2] * planeNormal[2]
128 m_ShiftUp = signedDistance;
130 m_ITKAssumedSliceSpacing = (origin2 - origin1).GetNorm();
134 MITK_DEBUG <<
" calculated from slices " << m_NumberOfSlicesApart <<
" slices apart";
135 MITK_DEBUG <<
" shift normal: " << m_ShiftNormal;
136 MITK_DEBUG <<
" shift normal assumed by ITK: " << m_ITKAssumedSliceSpacing;
138 MITK_DEBUG <<
" shift right: " << m_ShiftRight;
140 MITK_DEBUG <<
" tilt angle (deg): " << atan( m_ShiftUp / m_ShiftNormal ) * 180.0 / 3.1415926535;
147 const std::string& origin1String,
148 const std::string& origin2String,
149 const std::string& orientationString,
150 unsigned int numberOfSlicesApart)
154 bool orientationConversion(
false);
157 if (orientationConversion
158 && !origin1String.empty() && !origin2String.empty()
161 bool firstOriginConversion(
false);
162 bool lastOriginConversion(
false);
167 if (firstOriginConversion && lastOriginConversion)
173 std::stringstream ss;
174 ss <<
"Invalid tag values when constructing tilt information from origin1 '" << origin1String
175 <<
"', origin2 '" << origin2String
176 <<
"', and orientation '" << orientationString <<
"'";
178 throw std::invalid_argument(ss.str());
185 os <<
" calculated from slices " << m_NumberOfSlicesApart <<
" slices apart" << std::endl;
186 os <<
" shift normal: " << m_ShiftNormal << std::endl;
187 os <<
" shift normal assumed by ITK: " << m_ITKAssumedSliceSpacing << std::endl;
188 os <<
" shift up: " << m_ShiftUp << std::endl;
189 os <<
" shift right: " << m_ShiftRight << std::endl;
191 os <<
" tilt angle (deg): " << atan( m_ShiftUp / m_ShiftNormal ) * 180.0 / 3.1415926535 << std::endl;
203 Vector3Dd lineOriginToP = p - lineOrigin;
204 double innerProduct = lineOriginToP * lineDirection;
206 double factor = innerProduct / lineDirection.GetSquaredNorm();
207 Point3Dd projection = lineOrigin + factor * lineDirection;
215 return fabs(m_ShiftUp / static_cast<double>(m_NumberOfSlicesApart) * static_cast<double>(imageSizeZ-1));
221 return atan( fabs(m_ShiftUp) / m_ShiftNormal ) * 180.0 / 3.1415926535;
228 return m_ShiftUp /
static_cast<double>(m_NumberOfSlicesApart);
234 return m_ShiftNormal /
static_cast<double>(m_NumberOfSlicesApart);
241 return m_NumberOfSlicesApart &&
242 ( fabs(m_ShiftRight) > 0.001
243 || fabs(m_ShiftUp) > 0.001);
250 return m_NumberOfSlicesApart &&
251 ( fabs(m_ShiftRight) < 0.001
252 && fabs(m_ShiftUp) > 0.001);
void DICOMStringToOrientationVectors(const std::string &s, Vector3D &right, Vector3D &up, bool &successful)
Convert DICOM string describing a point two Vector3D.
Point3D DICOMStringToPoint3D(const std::string &s, bool &successful)
Convert DICOM string describing a point to Point3D.