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