Medical Imaging Interaction Toolkit  2018.4.99-b7f3afaa
Medical Imaging Interaction Toolkit
mitkBaseGeometry.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 (DKFZ)
6 All rights reserved.
7 
8 Use of this source code is governed by a 3-clause BSD license that can be
9 found in the LICENSE file.
10 
11 ============================================================================*/
12 
13 #include <iomanip>
14 #include <sstream>
15 
16 #include <vtkMatrix4x4.h>
17 #include <vtkMatrixToLinearTransform.h>
18 
20 #include "mitkBaseGeometry.h"
22 #include "mitkInteractionConst.h"
23 #include "mitkMatrixConvert.h"
24 #include "mitkModifiedLock.h"
25 #include "mitkPointOperation.h"
27 #include "mitkRotationOperation.h"
28 #include "mitkScaleOperation.h"
29 #include "mitkVector.h"
30 
32  : Superclass(),
34  m_FrameOfReferenceID(0),
35  m_IndexToWorldTransformLastModified(0),
36  m_ImageGeometry(false),
37  m_ModifiedLockFlag(false),
38  m_ModifiedCalledFlag(false)
39 {
40  m_GeometryTransform = new GeometryTransformHolder();
41  Initialize();
42 }
43 
45  : Superclass(),
47  m_FrameOfReferenceID(other.m_FrameOfReferenceID),
48  m_IndexToWorldTransformLastModified(other.m_IndexToWorldTransformLastModified),
49  m_ImageGeometry(other.m_ImageGeometry),
50  m_ModifiedLockFlag(false),
51  m_ModifiedCalledFlag(false)
52 {
53  m_GeometryTransform = new GeometryTransformHolder(*other.GetGeometryTransformHolder());
54  other.InitializeGeometry(this);
55 }
56 
58 {
59  delete m_GeometryTransform;
60 }
61 
62 void mitk::BaseGeometry::SetVtkMatrixDeepCopy(vtkTransform *vtktransform)
63 {
64  m_GeometryTransform->SetVtkMatrixDeepCopy(vtktransform);
65 }
66 
68 {
69  return m_GeometryTransform->GetOrigin();
70 }
71 
73 {
74  mitk::ModifiedLock lock(this);
75 
76  if (origin != GetOrigin())
77  {
78  m_GeometryTransform->SetOrigin(origin);
79  Modified();
80  }
81 }
82 
84 {
85  return m_GeometryTransform->GetSpacing();
86 }
87 
89 {
90  float b[6] = {0, 1, 0, 1, 0, 1};
91  SetFloatBounds(b);
92 
93  m_GeometryTransform->Initialize();
94 
95  m_FrameOfReferenceID = 0;
96 
97  m_ImageGeometry = false;
98 }
99 
100 void mitk::BaseGeometry::SetFloatBounds(const float bounds[6])
101 {
103  const float *input = bounds;
104  int i = 0;
105  for (mitk::BoundingBox::BoundsArrayType::Iterator it = b.Begin(); i < 6; ++i)
106  *it++ = (mitk::ScalarType)*input++;
107  SetBounds(b);
108 }
109 
110 void mitk::BaseGeometry::SetFloatBounds(const double bounds[6])
111 {
113  const double *input = bounds;
114  int i = 0;
115  for (mitk::BoundingBox::BoundsArrayType::Iterator it = b.Begin(); i < 6; ++i)
116  *it++ = (mitk::ScalarType)*input++;
117  SetBounds(b);
118 }
119 
122 {
123  newGeometry->SetBounds(m_BoundingBox->GetBounds());
124 
126 
127  newGeometry->InitializeGeometryTransformHolder(this);
128 
129  newGeometry->m_ImageGeometry = m_ImageGeometry;
130 }
131 
132 void mitk::BaseGeometry::InitializeGeometryTransformHolder(const BaseGeometry *otherGeometry)
133 {
134  this->m_GeometryTransform->Initialize(otherGeometry->GetGeometryTransformHolder());
135 }
136 
139 {
140  mitk::ModifiedLock lock(this);
141 
142  this->CheckBounds(bounds);
143 
144  m_BoundingBox = BoundingBoxType::New();
145 
146  BoundingBoxType::PointsContainer::Pointer pointscontainer = BoundingBoxType::PointsContainer::New();
147  BoundingBoxType::PointType p;
148  BoundingBoxType::PointIdentifier pointid;
149 
150  for (pointid = 0; pointid < 2; ++pointid)
151  {
152  unsigned int i;
153  for (i = 0; i < m_NDimensions; ++i)
154  {
155  p[i] = bounds[2 * i + pointid];
156  }
157  pointscontainer->InsertElement(pointid, p);
158  }
159 
160  m_BoundingBox->SetPoints(pointscontainer);
161  m_BoundingBox->ComputeBoundingBox();
162  this->Modified();
163 }
164 
166 {
167  mitk::ModifiedLock lock(this);
168 
169  CheckIndexToWorldTransform(transform);
170 
171  m_GeometryTransform->SetIndexToWorldTransform(transform);
172  Modified();
173 }
174 
176 {
177  // security check
178  mitk::Vector3D originalSpacing = this->GetSpacing();
179 
180  mitk::ModifiedLock lock(this);
181 
182  CheckIndexToWorldTransform(transform);
183 
184  m_GeometryTransform->SetIndexToWorldTransformWithoutChangingSpacing(transform);
185  Modified();
186 
187  // Security check. Spacig must not have changed
188  if (!mitk::Equal(originalSpacing, this->GetSpacing()))
189  {
190  MITK_WARN << "Spacing has changed in a method, where the spacing must not change.";
191  assert(false);
192  }
193 }
194 
196 {
197  assert(m_BoundingBox.IsNotNull());
198  return m_BoundingBox->GetBounds();
199 }
200 
202 {
203  return true;
204 }
205 
206 void mitk::BaseGeometry::SetSpacing(const mitk::Vector3D &aSpacing, bool enforceSetSpacing)
207 {
208  PreSetSpacing(aSpacing);
209  _SetSpacing(aSpacing, enforceSetSpacing);
210 }
211 
212 void mitk::BaseGeometry::_SetSpacing(const mitk::Vector3D &aSpacing, bool enforceSetSpacing)
213 {
214  m_GeometryTransform->SetSpacing(aSpacing, enforceSetSpacing);
215 }
216 
218 {
219  Vector3D frontToBack;
220  frontToBack.SetVnlVector(this->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(direction));
221  frontToBack *= GetExtent(direction);
222  return frontToBack;
223 }
224 
225 mitk::ScalarType mitk::BaseGeometry::GetExtent(unsigned int direction) const
226 {
227  assert(m_BoundingBox.IsNotNull());
228  if (direction >= m_NDimensions)
229  mitkThrow() << "Direction is too big. This geometry is for 3D Data";
230  BoundsArrayType bounds = m_BoundingBox->GetBounds();
231  return bounds[direction * 2 + 1] - bounds[direction * 2];
232 }
233 
235 {
236  bool isConvertableWithoutLoss = true;
237  do
238  {
239  if (this->GetSpacing()[2] != 1)
240  {
241  isConvertableWithoutLoss = false;
242  break;
243  }
244  if (this->GetOrigin()[2] != 0)
245  {
246  isConvertableWithoutLoss = false;
247  break;
248  }
249  mitk::Vector3D col0, col1, col2;
250  col0.SetVnlVector(this->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(0));
251  col1.SetVnlVector(this->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(1));
252  col2.SetVnlVector(this->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(2));
253 
254  if ((col0[2] != 0) || (col1[2] != 0) || (col2[0] != 0) || (col2[1] != 0) || (col2[2] != 1))
255  {
256  isConvertableWithoutLoss = false;
257  break;
258  }
259  } while (false);
260 
261  return isConvertableWithoutLoss;
262 }
263 
265 {
266  assert(m_BoundingBox.IsNotNull());
267  Point3D c = m_BoundingBox->GetCenter();
268  if (m_ImageGeometry)
269  {
270  // Get Center returns the middel of min and max pixel index. In corner based images, this is the right position.
271  // In center based images (imageGeometry == true), the index needs to be shifted back.
272  c[0] -= 0.5;
273  c[1] -= 0.5;
274  c[2] -= 0.5;
275  }
276  this->IndexToWorld(c, c);
277  return c;
278 }
279 
281 {
282  Vector3D diagonalvector = GetCornerPoint() - GetCornerPoint(false, false, false);
283  return diagonalvector.GetSquaredNorm();
284 }
285 
287 {
288  return sqrt(GetDiagonalLength2());
289 }
290 
292 {
293  assert(id >= 0);
294  assert(this->IsBoundingBoxNull() == false);
295 
296  BoundingBox::BoundsArrayType bounds = this->GetBoundingBox()->GetBounds();
297 
298  Point3D cornerpoint;
299  switch (id)
300  {
301  case 0:
302  FillVector3D(cornerpoint, bounds[0], bounds[2], bounds[4]);
303  break;
304  case 1:
305  FillVector3D(cornerpoint, bounds[0], bounds[2], bounds[5]);
306  break;
307  case 2:
308  FillVector3D(cornerpoint, bounds[0], bounds[3], bounds[4]);
309  break;
310  case 3:
311  FillVector3D(cornerpoint, bounds[0], bounds[3], bounds[5]);
312  break;
313  case 4:
314  FillVector3D(cornerpoint, bounds[1], bounds[2], bounds[4]);
315  break;
316  case 5:
317  FillVector3D(cornerpoint, bounds[1], bounds[2], bounds[5]);
318  break;
319  case 6:
320  FillVector3D(cornerpoint, bounds[1], bounds[3], bounds[4]);
321  break;
322  case 7:
323  FillVector3D(cornerpoint, bounds[1], bounds[3], bounds[5]);
324  break;
325  default:
326  {
327  itkExceptionMacro(<< "A cube only has 8 corners. These are labeled 0-7.");
328  }
329  }
330  if (m_ImageGeometry)
331  {
332  // Here i have to adjust the 0.5 offset manually, because the cornerpoint is the corner of the
333  // bounding box. The bounding box itself is no image, so it is corner-based
334  FillVector3D(cornerpoint, cornerpoint[0] - 0.5, cornerpoint[1] - 0.5, cornerpoint[2] - 0.5);
335  }
336  return this->GetIndexToWorldTransform()->TransformPoint(cornerpoint);
337 }
338 
339 mitk::Point3D mitk::BaseGeometry::GetCornerPoint(bool xFront, bool yFront, bool zFront) const
340 {
341  assert(this->IsBoundingBoxNull() == false);
342  BoundingBox::BoundsArrayType bounds = this->GetBoundingBox()->GetBounds();
343 
344  Point3D cornerpoint;
345  cornerpoint[0] = (xFront ? bounds[0] : bounds[1]);
346  cornerpoint[1] = (yFront ? bounds[2] : bounds[3]);
347  cornerpoint[2] = (zFront ? bounds[4] : bounds[5]);
348  if (m_ImageGeometry)
349  {
350  // Here i have to adjust the 0.5 offset manually, because the cornerpoint is the corner of the
351  // bounding box. The bounding box itself is no image, so it is corner-based
352  FillVector3D(cornerpoint, cornerpoint[0] - 0.5, cornerpoint[1] - 0.5, cornerpoint[2] - 0.5);
353  }
354 
355  return this->GetIndexToWorldTransform()->TransformPoint(cornerpoint);
356 }
357 
359 {
360  return this->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(direction).magnitude() *
361  GetExtent(direction);
362 }
363 
364 void mitk::BaseGeometry::SetExtentInMM(int direction, ScalarType extentInMM)
365 {
366  mitk::ModifiedLock lock(this);
367 
368  ScalarType len = GetExtentInMM(direction);
369  if (fabs(len - extentInMM) >= mitk::eps)
370  {
371  AffineTransform3D::MatrixType::InternalMatrixType vnlmatrix;
372  vnlmatrix = m_GeometryTransform->GetVnlMatrix();
373  if (len > extentInMM)
374  vnlmatrix.set_column(direction, vnlmatrix.get_column(direction) / len * extentInMM);
375  else
376  vnlmatrix.set_column(direction, vnlmatrix.get_column(direction) * extentInMM / len);
377  Matrix3D matrix;
378  matrix = vnlmatrix;
379  m_GeometryTransform->SetMatrix(matrix);
380 
381  Modified();
382  }
383 }
384 
386 {
387  mitk::Point3D index;
388  WorldToIndex(p, index);
389  return IsIndexInside(index);
390 }
391 
393 {
394  bool inside = false;
395  // if it is an image geometry, we need to convert the index to discrete values
396  // this is done by applying the rounding function also used in WorldToIndex (see line 323)
397  if (m_ImageGeometry)
398  {
399  mitk::Point3D discretIndex;
400  discretIndex[0] = itk::Math::RoundHalfIntegerUp<mitk::ScalarType>(index[0]);
401  discretIndex[1] = itk::Math::RoundHalfIntegerUp<mitk::ScalarType>(index[1]);
402  discretIndex[2] = itk::Math::RoundHalfIntegerUp<mitk::ScalarType>(index[2]);
403 
404  inside = this->GetBoundingBox()->IsInside(discretIndex);
405  // we have to check if the index is at the upper border of each dimension,
406  // because the boundingbox is not centerbased
407  if (inside)
408  {
409  const BoundingBox::BoundsArrayType &bounds = this->GetBoundingBox()->GetBounds();
410  if ((discretIndex[0] == bounds[1]) || (discretIndex[1] == bounds[3]) || (discretIndex[2] == bounds[5]))
411  inside = false;
412  }
413  }
414  else
415  inside = this->GetBoundingBox()->IsInside(index);
416 
417  return inside;
418 }
419 
421 {
422  mitk::Vector3D tempIn, tempOut;
423  const TransformType::OffsetType &offset = this->GetIndexToWorldTransform()->GetOffset();
424  tempIn = pt_mm.GetVectorFromOrigin() - offset;
425 
426  WorldToIndex(tempIn, tempOut);
427 
428  pt_units = tempOut;
429 }
430 
432 {
433  // Get WorldToIndex transform
434  if (m_IndexToWorldTransformLastModified != this->GetIndexToWorldTransform()->GetMTime())
435  {
436  if (!m_InvertedTransform)
437  {
438  m_InvertedTransform = TransformType::New();
439  }
440  if (!this->GetIndexToWorldTransform()->GetInverse(m_InvertedTransform.GetPointer()))
441  {
442  itkExceptionMacro("Internal ITK matrix inversion error, cannot proceed.");
443  }
444  m_IndexToWorldTransformLastModified = this->GetIndexToWorldTransform()->GetMTime();
445  }
446 
447  // Check for valid matrix inversion
448  const TransformType::MatrixType &inverse = m_InvertedTransform->GetMatrix();
449  if (inverse.GetVnlMatrix().has_nans())
450  {
451  itkExceptionMacro("Internal ITK matrix inversion error, cannot proceed. Matrix was: "
452  << std::endl
453  << this->GetIndexToWorldTransform()->GetMatrix()
454  << "Suggested inverted matrix is:"
455  << std::endl
456  << inverse);
457  }
458 
459  vec_units = inverse * vec_mm;
460 }
461 
463  const mitk::Vector3D &vec_mm,
464  mitk::Vector3D &vec_units) const
465 {
466  MITK_WARN << "Warning! Call of the deprecated function BaseGeometry::WorldToIndex(point, vec, vec). Use "
467  "BaseGeometry::WorldToIndex(vec, vec) instead!";
468  this->WorldToIndex(vec_mm, vec_units);
469 }
470 
472 {
473  return GetOrigin().GetVnlVector();
474 }
475 
476 vtkLinearTransform *mitk::BaseGeometry::GetVtkTransform() const
477 {
478  return m_GeometryTransform->GetVtkTransform();
479 }
480 
482 {
483  mitk::ModifiedLock lock(this);
484 
485  m_GeometryTransform->SetIdentity();
486  Modified();
487 }
488 
490 {
491  mitk::ModifiedLock lock(this);
492  m_GeometryTransform->Compose(other, pre);
493  Modified();
494 }
495 
496 void mitk::BaseGeometry::Compose(const vtkMatrix4x4 *vtkmatrix, bool pre)
497 {
498  mitk::BaseGeometry::TransformType::Pointer itkTransform = mitk::BaseGeometry::TransformType::New();
499  TransferVtkMatrixToItkTransform(vtkmatrix, itkTransform.GetPointer());
500  Compose(itkTransform, pre);
501 }
502 
504 {
505  if ((vector[0] != 0) || (vector[1] != 0) || (vector[2] != 0))
506  {
507  this->SetOrigin(this->GetOrigin() + vector);
508  }
509 }
510 
512 {
513  pt_mm = this->GetIndexToWorldTransform()->TransformPoint(pt_units);
514 }
515 
517 {
518  vec_mm = this->GetIndexToWorldTransform()->TransformVector(vec_units);
519 }
520 
522 {
523  mitk::ModifiedLock lock(this);
524 
525  vtkTransform *vtktransform = vtkTransform::New();
526  vtktransform->SetMatrix(this->GetVtkMatrix());
527  switch (operation->GetOperationType())
528  {
529  case OpNOTHING:
530  break;
531  case OpMOVE:
532  {
533  auto *pointOp = dynamic_cast<mitk::PointOperation *>(operation);
534  if (pointOp == nullptr)
535  {
536  MITK_ERROR << "Point move operation is null!";
537  return;
538  }
539  mitk::Point3D newPos = pointOp->GetPoint();
540  ScalarType data[3];
541  vtktransform->GetPosition(data);
542  vtktransform->PostMultiply();
543  vtktransform->Translate(newPos[0], newPos[1], newPos[2]);
544  vtktransform->PreMultiply();
545  break;
546  }
547  case OpSCALE:
548  {
549  auto *scaleOp = dynamic_cast<mitk::ScaleOperation *>(operation);
550  if (scaleOp == nullptr)
551  {
552  MITK_ERROR << "Scale operation is null!";
553  return;
554  }
555  mitk::Point3D newScale = scaleOp->GetScaleFactor();
556  ScalarType scalefactor[3];
557 
558  scalefactor[0] = 1 + (newScale[0] / GetMatrixColumn(0).magnitude());
559  scalefactor[1] = 1 + (newScale[1] / GetMatrixColumn(1).magnitude());
560  scalefactor[2] = 1 + (newScale[2] / GetMatrixColumn(2).magnitude());
561 
562  mitk::Point3D anchor = scaleOp->GetScaleAnchorPoint();
563 
564  vtktransform->PostMultiply();
565  vtktransform->Translate(-anchor[0], -anchor[1], -anchor[2]);
566  vtktransform->Scale(scalefactor[0], scalefactor[1], scalefactor[2]);
567  vtktransform->Translate(anchor[0], anchor[1], anchor[2]);
568  break;
569  }
570  case OpROTATE:
571  {
572  auto *rotateOp = dynamic_cast<mitk::RotationOperation *>(operation);
573  if (rotateOp == nullptr)
574  {
575  MITK_ERROR << "Rotation operation is null!";
576  return;
577  }
578  Vector3D rotationVector = rotateOp->GetVectorOfRotation();
579  Point3D center = rotateOp->GetCenterOfRotation();
580  ScalarType angle = rotateOp->GetAngleOfRotation();
581  vtktransform->PostMultiply();
582  vtktransform->Translate(-center[0], -center[1], -center[2]);
583  vtktransform->RotateWXYZ(angle, rotationVector[0], rotationVector[1], rotationVector[2]);
584  vtktransform->Translate(center[0], center[1], center[2]);
585  vtktransform->PreMultiply();
586  break;
587  }
589  {
590  // Copy necessary to avoid vtk warning
591  vtkMatrix4x4 *matrix = vtkMatrix4x4::New();
593  dynamic_cast<mitk::RestorePlanePositionOperation *>(operation)->GetTransform().GetPointer(), matrix);
594  vtktransform->SetMatrix(matrix);
595  matrix->Delete();
596  break;
597  }
599  {
600  auto *applyMatrixOp = dynamic_cast<ApplyTransformMatrixOperation *>(operation);
601  vtktransform->SetMatrix(applyMatrixOp->GetMatrix());
602  break;
603  }
604  default:
605  vtktransform->Delete();
606  return;
607  }
608  this->SetVtkMatrixDeepCopy(vtktransform);
609  Modified();
610  vtktransform->Delete();
611 }
612 
614 {
615  return this->GetIndexToWorldTransform()->GetMatrix().GetVnlMatrix().get_column(direction);
616 }
617 
619  const mitk::AffineTransform3D *transform) const
620 {
621  mitk::BoundingBox::PointsContainer::Pointer pointscontainer = mitk::BoundingBox::PointsContainer::New();
622 
623  mitk::BoundingBox::PointIdentifier pointid = 0;
624 
625  unsigned char i;
626  if (transform != nullptr)
627  {
628  mitk::AffineTransform3D::Pointer inverse = mitk::AffineTransform3D::New();
629  transform->GetInverse(inverse);
630  for (i = 0; i < 8; ++i)
631  pointscontainer->InsertElement(pointid++, inverse->TransformPoint(GetCornerPoint(i)));
632  }
633  else
634  {
635  for (i = 0; i < 8; ++i)
636  pointscontainer->InsertElement(pointid++, GetCornerPoint(i));
637  }
638 
639  mitk::BoundingBox::Pointer result = mitk::BoundingBox::New();
640  result->SetPoints(pointscontainer);
641  result->ComputeBoundingBox();
642 
643  return result;
644 }
645 
647 {
648  std::ostringstream out;
649 
650  out << '[';
651 
652  for (int i = 0; i < 3; ++i)
653  {
654  out << '[';
655  for (int j = 0; j < 3; ++j)
656  out << transformType->GetMatrix().GetVnlMatrix().get(i, j) << ' ';
657  out << ']';
658  }
659 
660  out << "][";
661 
662  for (int i = 0; i < 3; ++i)
663  out << transformType->GetOffset()[i] << ' ';
664 
665  out << "]\0";
666 
667  return out.str();
668 }
669 
671 {
672  m_GeometryTransform->SetIndexToWorldTransformByVtkMatrix(vtkmatrix);
673 }
674 
676 {
677  m_GeometryTransform->SetIndexToWorldTransformByVtkMatrixWithoutChangingSpacing(vtkmatrix);
678 }
679 
680 void mitk::BaseGeometry::IndexToWorld(const mitk::Point3D & /*atPt3d_units*/,
681  const mitk::Vector3D &vec_units,
682  mitk::Vector3D &vec_mm) const
683 {
684  MITK_WARN << "Warning! Call of the deprecated function BaseGeometry::IndexToWorld(point, vec, vec). Use "
685  "BaseGeometry::IndexToWorld(vec, vec) instead!";
686  // vec_mm = m_IndexToWorldTransform->TransformVector(vec_units);
687  this->IndexToWorld(vec_units, vec_mm);
688 }
689 
691 {
692  return m_GeometryTransform->GetVtkMatrix();
693 }
694 
696 {
697  return m_BoundingBox.IsNull();
698 }
699 
701 {
702  return m_GeometryTransform->IsIndexToWorldTransformNull();
703 }
704 
706 {
707  // If Geometry is switched to ImageGeometry, you have to put an offset to the origin, because
708  // imageGeometries origins are pixel-center-based
709  // ... and remove the offset, if you switch an imageGeometry back to a normal geometry
710  // For more information please see the Geometry documentation page
711 
712  if (m_ImageGeometry == isAnImageGeometry)
713  return;
714 
715  const BoundingBox::BoundsArrayType &boundsarray = this->GetBoundingBox()->GetBounds();
716 
717  Point3D originIndex;
718  FillVector3D(originIndex, boundsarray[0], boundsarray[2], boundsarray[4]);
719 
720  if (isAnImageGeometry == true)
721  FillVector3D(originIndex, originIndex[0] + 0.5, originIndex[1] + 0.5, originIndex[2] + 0.5);
722  else
723  FillVector3D(originIndex, originIndex[0] - 0.5, originIndex[1] - 0.5, originIndex[2] - 0.5);
724 
725  Point3D originWorld;
726 
727  originWorld = GetIndexToWorldTransform()->TransformPoint(originIndex);
728  // instead could as well call IndexToWorld(originIndex,originWorld);
729 
730  SetOrigin(originWorld);
731 
732  this->SetImageGeometry(isAnImageGeometry);
733 }
734 
735 void mitk::BaseGeometry::PrintSelf(std::ostream &os, itk::Indent indent) const
736 {
737  os << indent << " IndexToWorldTransform: ";
738  if (this->IsIndexToWorldTransformNull())
739  os << "nullptr" << std::endl;
740  else
741  {
742  // from itk::MatrixOffsetTransformBase
743  unsigned int i, j;
744  os << std::endl;
745  os << indent << "Matrix: " << std::endl;
746  for (i = 0; i < 3; i++)
747  {
748  os << indent.GetNextIndent();
749  for (j = 0; j < 3; j++)
750  {
751  os << this->GetIndexToWorldTransform()->GetMatrix()[i][j] << " ";
752  }
753  os << std::endl;
754  }
755 
756  os << indent << "Offset: " << this->GetIndexToWorldTransform()->GetOffset() << std::endl;
757  os << indent << "Center: " << this->GetIndexToWorldTransform()->GetCenter() << std::endl;
758  os << indent << "Translation: " << this->GetIndexToWorldTransform()->GetTranslation() << std::endl;
759 
760  os << indent << "Inverse: " << std::endl;
761  for (i = 0; i < 3; i++)
762  {
763  os << indent.GetNextIndent();
764  for (j = 0; j < 3; j++)
765  {
766  os << this->GetIndexToWorldTransform()->GetInverseMatrix()[i][j] << " ";
767  }
768  os << std::endl;
769  }
770 
771  // from itk::ScalableAffineTransform
772  os << indent << "Scale : ";
773  for (i = 0; i < 3; i++)
774  {
775  os << this->GetIndexToWorldTransform()->GetScale()[i] << " ";
776  }
777  os << std::endl;
778  }
779 
780  os << indent << " BoundingBox: ";
781  if (this->IsBoundingBoxNull())
782  os << "nullptr" << std::endl;
783  else
784  {
785  os << indent << "( ";
786  for (unsigned int i = 0; i < 3; i++)
787  {
788  os << this->GetBoundingBox()->GetBounds()[2 * i] << "," << this->GetBoundingBox()->GetBounds()[2 * i + 1] << " ";
789  }
790  os << " )" << std::endl;
791  }
792 
793  os << indent << " Origin: " << this->GetOrigin() << std::endl;
794  os << indent << " ImageGeometry: " << this->GetImageGeometry() << std::endl;
795  os << indent << " Spacing: " << this->GetSpacing() << std::endl;
796 }
797 
799 {
800  if (!m_ModifiedLockFlag)
801  Superclass::Modified();
802  else
803  m_ModifiedCalledFlag = true;
804 }
805 
807 {
808  return m_GeometryTransform->GetIndexToWorldTransform();
809 }
810 
812 {
813  return m_GeometryTransform->GetIndexToWorldTransform();
814 }
815 
817 {
818  return m_GeometryTransform;
819 }
820 
822  const mitk::BaseGeometry::BoundingBoxType *rightHandSide,
823  ScalarType eps,
824  bool verbose)
825 {
826  if ((leftHandSide == nullptr) || (rightHandSide == nullptr))
827  {
828  MITK_ERROR << "mitk::Equal( const mitk::Geometry3D::BoundingBoxType *leftHandSide, const "
829  "mitk::Geometry3D::BoundingBoxType *rightHandSide, ScalarType eps, bool verbose ) does not with nullptr "
830  "pointer input.";
831  return false;
832  }
833  return Equal(*leftHandSide, *rightHandSide, eps, verbose);
834 }
835 
837  const mitk::BaseGeometry::BoundingBoxType &rightHandSide,
838  ScalarType eps,
839  bool verbose)
840 {
841  bool result = true;
842 
843  BaseGeometry::BoundsArrayType rightBounds = rightHandSide.GetBounds();
844  BaseGeometry::BoundsArrayType leftBounds = leftHandSide.GetBounds();
845  BaseGeometry::BoundsArrayType::Iterator itLeft = leftBounds.Begin();
846  for (BaseGeometry::BoundsArrayType::Iterator itRight = rightBounds.Begin(); itRight != rightBounds.End(); ++itRight)
847  {
848  if ((!mitk::Equal(*itLeft, *itRight, eps)))
849  {
850  if (verbose)
851  {
852  MITK_INFO << "[( Geometry3D::BoundingBoxType )] bounds are not equal.";
853  MITK_INFO << "rightHandSide is " << setprecision(12) << *itRight << " : leftHandSide is " << *itLeft
854  << " and tolerance is " << eps;
855  }
856  result = false;
857  }
858  itLeft++;
859  }
860  return result;
861 }
862 
863 bool mitk::Equal(const mitk::BaseGeometry *leftHandSide,
864  const mitk::BaseGeometry *rightHandSide,
865  ScalarType eps,
866  bool verbose)
867 {
868  if ((leftHandSide == nullptr) || (rightHandSide == nullptr))
869  {
870  MITK_ERROR << "mitk::Equal(const mitk::Geometry3D *leftHandSide, const mitk::Geometry3D *rightHandSide, ScalarType "
871  "eps, bool verbose) does not with nullptr pointer input.";
872  return false;
873  }
874  return Equal(*leftHandSide, *rightHandSide, eps, verbose);
875 }
876 
877 bool mitk::Equal(const mitk::BaseGeometry &leftHandSide,
878  const mitk::BaseGeometry &rightHandSide,
879  ScalarType eps,
880  bool verbose)
881 {
882  bool result = true;
883 
884  // Compare spacings
885  if (!mitk::Equal(leftHandSide.GetSpacing(), rightHandSide.GetSpacing(), eps))
886  {
887  if (verbose)
888  {
889  MITK_INFO << "[( Geometry3D )] Spacing differs.";
890  MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetSpacing() << " : leftHandSide is "
891  << leftHandSide.GetSpacing() << " and tolerance is " << eps;
892  }
893  result = false;
894  }
895 
896  // Compare Origins
897  if (!mitk::Equal(leftHandSide.GetOrigin(), rightHandSide.GetOrigin(), eps))
898  {
899  if (verbose)
900  {
901  MITK_INFO << "[( Geometry3D )] Origin differs.";
902  MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetOrigin() << " : leftHandSide is "
903  << leftHandSide.GetOrigin() << " and tolerance is " << eps;
904  }
905  result = false;
906  }
907 
908  // Compare Axis and Extents
909  for (unsigned int i = 0; i < 3; ++i)
910  {
911  if (!mitk::Equal(leftHandSide.GetAxisVector(i), rightHandSide.GetAxisVector(i), eps))
912  {
913  if (verbose)
914  {
915  MITK_INFO << "[( Geometry3D )] AxisVector #" << i << " differ";
916  MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetAxisVector(i) << " : leftHandSide is "
917  << leftHandSide.GetAxisVector(i) << " and tolerance is " << eps;
918  }
919  result = false;
920  }
921 
922  if (!mitk::Equal(leftHandSide.GetExtent(i), rightHandSide.GetExtent(i), eps))
923  {
924  if (verbose)
925  {
926  MITK_INFO << "[( Geometry3D )] Extent #" << i << " differ";
927  MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetExtent(i) << " : leftHandSide is "
928  << leftHandSide.GetExtent(i) << " and tolerance is " << eps;
929  }
930  result = false;
931  }
932  }
933 
934  // Compare ImageGeometry Flag
935  if (rightHandSide.GetImageGeometry() != leftHandSide.GetImageGeometry())
936  {
937  if (verbose)
938  {
939  MITK_INFO << "[( Geometry3D )] GetImageGeometry is different.";
940  MITK_INFO << "rightHandSide is " << rightHandSide.GetImageGeometry() << " : leftHandSide is "
941  << leftHandSide.GetImageGeometry();
942  }
943  result = false;
944  }
945 
946  // Compare FrameOfReference ID
947  if (rightHandSide.GetFrameOfReferenceID() != leftHandSide.GetFrameOfReferenceID())
948  {
949  if (verbose)
950  {
951  MITK_INFO << "[( Geometry3D )] GetFrameOfReferenceID is different.";
952  MITK_INFO << "rightHandSide is " << rightHandSide.GetFrameOfReferenceID() << " : leftHandSide is "
953  << leftHandSide.GetFrameOfReferenceID();
954  }
955  result = false;
956  }
957 
958  // Compare BoundingBoxes
959  if (!mitk::Equal(*leftHandSide.GetBoundingBox(), *rightHandSide.GetBoundingBox(), eps, verbose))
960  {
961  result = false;
962  }
963 
964  // Compare IndexToWorldTransform Matrix
965  if (!mitk::Equal(*leftHandSide.GetIndexToWorldTransform(), *rightHandSide.GetIndexToWorldTransform(), eps, verbose))
966  {
967  result = false;
968  }
969  return result;
970 }
971 
973  const mitk::BaseGeometry::TransformType *rightHandSide,
974  ScalarType eps,
975  bool verbose)
976 {
977  if ((leftHandSide == nullptr) || (rightHandSide == nullptr))
978  {
979  MITK_ERROR << "mitk::Equal(const Geometry3D::TransformType *leftHandSide, const Geometry3D::TransformType "
980  "*rightHandSide, ScalarType eps, bool verbose ) does not with nullptr pointer input.";
981  return false;
982  }
983  return Equal(*leftHandSide, *rightHandSide, eps, verbose);
984 }
985 
987  const mitk::BaseGeometry::TransformType &rightHandSide,
988  ScalarType eps,
989  bool verbose)
990 {
991  // Compare IndexToWorldTransform Matrix
992  if (!mitk::MatrixEqualElementWise(leftHandSide.GetMatrix(), rightHandSide.GetMatrix(), eps))
993  {
994  if (verbose)
995  {
996  MITK_INFO << "[( Geometry3D::TransformType )] Index to World Transformation matrix differs.";
997  MITK_INFO << "rightHandSide is " << setprecision(12) << rightHandSide.GetMatrix() << " : leftHandSide is "
998  << leftHandSide.GetMatrix() << " and tolerance is " << eps;
999  }
1000  return false;
1001  }
1002  return true;
1003 }
void TransferVtkMatrixToItkTransform(const vtkMatrix4x4 *vtkmatrix, TTransformType *itkTransform)
void SetVtkMatrixDeepCopy(vtkTransform *vtktransform)
itk::BoundingBox< unsigned long, 3, ScalarType > BoundingBoxType
void IndexToWorld(const mitk::Vector3D &vec_units, mitk::Vector3D &vec_mm) const
Convert (continuous or discrete) index coordinates of a vector vec_units to world coordinates (in mm)...
virtual bool GetImageGeometry() const
Is this an ImageGeometry?
vtkMatrix4x4 * GetVtkMatrix()
void SetIndexToWorldTransformByVtkMatrixWithoutChangingSpacing(vtkMatrix4x4 *vtkmatrix)
Convenience method for setting the ITK transform (m_IndexToWorldTransform) via an vtkMatrix4x4...
void SetSpacing(const mitk::Vector3D &aSpacing, bool enforceSetSpacing=false)
Set the spacing (m_Spacing).
void SetIndexToWorldTransformWithoutChangingSpacing(mitk::AffineTransform3D *transform)
void SetIndexToWorldTransform(mitk::AffineTransform3D *transform)
bool MatrixEqualElementWise(const vnl_matrix_fixed< TCoordRep, NRows, NCols > &matrix1, const vnl_matrix_fixed< TCoordRep, NRows, NCols > &matrix2, mitk::ScalarType epsilon=mitk::eps)
Check for element-wise matrix equality with a user defined accuracy.
Definition: mitkMatrix.h:140
bool IsBoundingBoxNull() const
BoundingBoxType::BoundsArrayType BoundsArrayType
#define MITK_INFO
Definition: mitkLogMacros.h:18
Vector3D GetAxisVector(unsigned int direction) const
Get vector along bounding-box in the specified direction in mm.
void PrintSelf(std::ostream &os, itk::Indent indent) const override
Base class of all Operation-classes.
Definition: mitkOperation.h:29
vnl_vector< ScalarType > VnlVector
Definition: mitkVector.h:134
#define MITK_ERROR
Definition: mitkLogMacros.h:20
bool IsIndexInside(const mitk::Point3D &index) const
Test whether the point p ((continous!)index coordinates in units) is inside the bounding box...
double ScalarType
void SetIdentity()
Set the transform to identity, the spacing to 1 and origin to 0.
vtkLinearTransform * GetVtkTransform() const
Get the m_IndexToWorldTransform as a vtkLinearTransform.
bool IsInside(const mitk::Point3D &p) const
Test whether the point p (world coordinates in mm) is inside the bounding box.
void _SetSpacing(const mitk::Vector3D &aSpacing, bool enforceSetSpacing=false)
double GetDiagonalLength2() const
Get the squared length of the diagonal of the bounding-box in mm.
GeometryTransformHolder::TransformType TransformType
ModifiedLock manages the calls of Modified() functions.
ScalarType GetExtent(unsigned int direction) const
Set the time bounds (in ms)
DataCollection - Class to facilitate loading/accessing structured data.
Point3D GetCornerPoint(int id) const
Get the position of the corner number id (in world coordinates)
void TransferItkTransformToVtkMatrix(const TTransformType *itkTransform, vtkMatrix4x4 *vtkmatrix)
AffineTransform3D::MatrixType::InternalMatrixType GetVnlMatrix()
void Initialize()
Initialize the BaseGeometry.
Constants for most interaction classes, due to the generic StateMachines.
void SetSpacing(const mitk::Vector3D &aSpacing, bool enforceSetSpacing=false)
Set the spacing (m_Spacing).
void SetIndexToWorldTransformWithoutChangingSpacing(mitk::AffineTransform3D *transform)
Point3D GetCenter() const
Get the center of the bounding-box in mm.
void Translate(const Vector3D &vector)
Translate the origin by a vector.
virtual void CheckIndexToWorldTransform(mitk::AffineTransform3D *)
CheckIndexToWorldTransform.
abstract class, that can be used by Undo to undo an operation.
void FillVector3D(Tout &out, mitk::ScalarType x, mitk::ScalarType y, mitk::ScalarType z)
Definition: mitkArray.h:106
ScalarType GetExtentInMM(int direction) const
Get the extent of the bounding-box in the specified direction in mm.
const GeometryTransformHolder * GetGeometryTransformHolder() const
void Compose(const TransformType *other, bool pre=false)
Compose new IndexToWorldTransform with a given transform.
virtual void CheckBounds(const BoundsArrayType &)
CheckBounds.
void InitializeGeometry(Self *newGeometry) const
virtual void PreSetSpacing(const mitk::Vector3D &)
PreSetSpacing.
static Vector3D offset
static const std::string GetTransformAsString(TransformType *transformType)
void SetVtkMatrixDeepCopy(vtkTransform *vtktransform)
#define MITK_WARN
Definition: mitkLogMacros.h:19
void Compose(const TransformType *other, bool pre=false)
const mitk::Vector3D GetSpacing() const
Get the spacing (size of a pixel).
#define mitkThrow()
bool verbose(false)
void SetOrigin(const Point3D &origin)
Set the origin, i.e. the upper-left corner of the plane.
vtkLinearTransform * GetVtkTransform() const
Get the m_IndexToWorldTransform as a vtkLinearTransform.
void Modified() const override
Overload of function Modified() to prohibit several calls of Modified() using the ModifiedLock class...
Operation that handles all actions on one Point.
bool IsIndexToWorldTransformNull() const
itk::AffineGeometryFrame< ScalarType, 3 >::TransformType AffineTransform3D
virtual unsigned int GetFrameOfReferenceID() const
Get the DICOM FrameOfReferenceID referring to the used world coordinate system.
void SetIndexToWorldTransform(mitk::AffineTransform3D *transform)
const Point3D GetOrigin() const
Get the origin, e.g. the upper-left corner of the plane.
void WorldToIndex(const mitk::Point3D &pt_mm, mitk::Point3D &pt_units) const
Convert world coordinates (in mm) of a point to (continuous!) index coordinates.
virtual bool IsValid() const
Is this BaseGeometry in a state that is valid?
virtual void ChangeImageGeometryConsideringOriginOffset(const bool isAnImageGeometry)
When switching from an Image Geometry to a normal Geometry (and the other way around), you have to.
MITKNEWMODULE_EXPORT bool Equal(mitk::ExampleDataStructure *leftHandSide, mitk::ExampleDataStructure *rightHandSide, mitk::ScalarType eps, bool verbose)
Returns true if the example data structures are considered equal.
void SetBounds(const BoundsArrayType &bounds)
Set the bounding box (in index/unit coordinates)
const mitk::Vector3D GetSpacing() const
Get the spacing (size of a pixel).
The ScaleOperation is an operation to scale any mitk::BaseGeometry.
void SetExtentInMM(int direction, ScalarType extentInMM)
Set the extent of the bounding-box in the specified direction in mm.
double GetDiagonalLength() const
Get the length of the diagonal of the bounding-box in mm.
void SetIndexToWorldTransformByVtkMatrix(vtkMatrix4x4 *vtkmatrix)
Convenience method for setting the ITK transform (m_IndexToWorldTransform) via an vtkMatrix4x4...
VnlVector GetOriginVnl() const
Get the origin as VnlVector.
virtual void SetFrameOfReferenceID(unsigned int _arg)
Set the DICOM FrameOfReferenceID referring to the used world coordinate system.
mitk::BoundingBox::Pointer CalculateBoundingBoxRelativeToTransform(const mitk::AffineTransform3D *transform) const
Calculates a bounding-box around the geometry relative to a coordinate system defined by a transform...
MITKCORE_EXPORT const ScalarType eps
void SetIndexToWorldTransformByVtkMatrixWithoutChangingSpacing(vtkMatrix4x4 *vtkmatrix)
Convenience method for setting the ITK transform (m_IndexToWorldTransform) via an vtkMatrix4x4...
virtual void SetIndexToWorldTransformByVtkMatrix(vtkMatrix4x4 *vtkmatrix)
Convenience method for setting the ITK transform (m_IndexToWorldTransform) via an vtkMatrix4x4...
mitk::AffineTransform3D * GetIndexToWorldTransform()
Get the transformation used to convert from index to world coordinates.
OperationType GetOperationType()
virtual bool Is2DConvertable()
Checks, if the given geometry can be converted to 2D without information loss e.g. when a 2D image is saved, the matrix is usually cropped to 2x2, and when you load it back to MITK it will be filled with standard values. This function checks, if information would be lost during this procedure.
Operation, that holds everything necessary for an rotation operation on mitk::BaseData.
void SetOrigin(const Point3D &origin)
Set the origin, i.e. the upper-left corner of the plane.
const Point3D GetOrigin() const
Get the origin, e.g. the upper-left corner of the plane.
const BoundsArrayType GetBounds() const
virtual void SetImageGeometry(bool _arg)
Define that this BaseGeometry is refering to an Image.
BaseGeometry Describes the geometry of a data object.
void ExecuteOperation(Operation *operation) override
executes affine operations (translate, rotate, scale)
mitk::AffineTransform3D * GetIndexToWorldTransform()
Get the transformation used to convert from index to world coordinates.
VnlVector GetMatrixColumn(unsigned int direction) const
Get a VnlVector along bounding-box in the specified direction, length is spacing. ...
BoundingBoxType::BoundsArrayType BoundsArrayType
void SetFloatBounds(const float bounds[6])
Set the bounding box (in index/unit coordinates) via a float array.
virtual const BoundingBoxType * GetBoundingBox()