17 #include <itkSpatialOrientationAdapter.h>
32 : m_EvenlySpaced(true), m_Slices(0), m_ReferenceGeometry(nullptr), m_SliceNavigationController(nullptr)
40 m_EvenlySpaced(other.m_EvenlySpaced),
41 m_Slices(other.m_Slices),
42 m_ReferenceGeometry(other.m_ReferenceGeometry),
43 m_SliceNavigationController(other.m_SliceNavigationController)
51 assert(!other.
m_PlaneGeometries.empty() &&
"This may happen when you use one of the old Initialize methods, which had a bool parameter that is implicitly casted to the number of slices now.");
53 assert(geometry.IsNotNull());
69 assert(geometry2D !=
nullptr);
84 if (this->IsValidSlice(s))
86 geometry2D = m_PlaneGeometries[s];
93 if ((m_EvenlySpaced) && (geometry2D.IsNull()))
97 if (firstSlice !=
nullptr &&
98 dynamic_cast<AbstractTransformGeometry *>(m_PlaneGeometries[0].GetPointer()) ==
nullptr)
100 if ((m_DirectionVector[0] == 0.0) && (m_DirectionVector[1] == 0.0) && (m_DirectionVector[2] == 0.0))
102 m_DirectionVector = firstSlice->
GetNormal();
103 m_DirectionVector.Normalize();
107 direction = m_DirectionVector * this->GetSpacing()[2];
112 requestedslice->SetOrigin(requestedslice->GetOrigin() + direction * s);
114 geometry2D = requestedslice;
115 m_PlaneGeometries[s] = geometry2D;
128 assert(this->IsBoundingBoxNull() ==
false);
129 return Superclass::GetBoundingBox();
134 if (this->IsValidSlice(s))
136 m_PlaneGeometries[s] = geometry2D;
145 Superclass::Initialize();
149 m_PlaneGeometries.assign(m_Slices, gnull);
153 this->SetSpacing(spacing);
155 m_DirectionVector.Fill(0);
160 assert(geometry2D !=
nullptr);
161 this->InitializeEvenlySpaced(geometry2D, geometry2D->
GetExtentInMM(2) / geometry2D->
GetExtent(2), slices);
168 assert(geometry2D !=
nullptr);
172 geometry2D->Register();
174 Superclass::Initialize();
183 m_PlaneGeometries.assign(m_Slices, gnull);
186 directionVector.Normalize();
187 directionVector *= zSpacing;
205 this->SetDirectionVector(directionVector);
206 this->SetBounds(bounds);
207 this->SetPlaneGeometry(geometry2D, 0);
208 this->SetSpacing(spacing,
true);
209 this->SetEvenlySpaced();
218 geometry2D->UnRegister();
227 m_ReferenceGeometry = geometry3D;
230 planeGeometry->InitializeStandardPlane(geometry3D, top, planeorientation, frontside, rotated);
240 matrix.GetVnlMatrix().normalize_columns();
241 mitk::AffineTransform3D::MatrixType::InternalMatrixType inverseMatrix = matrix.GetInverse();
243 int dominantAxis = itk::Function::Max3(
244 inverseMatrix[0][worldAxis],
245 inverseMatrix[1][worldAxis],
246 inverseMatrix[2][worldAxis]);
253 unsigned int slices =
static_cast<unsigned int>(geometry3D->
GetExtent(dominantAxis) + 0.5);
256 int upDirection = itk::Function::Sign(inverseMatrix[dominantAxis][worldAxis]);
262 Vector3D worldPlaneNormal = inverseMatrix.get_row(dominantAxis) * (upDirection * viewSpacing);
265 Vector3D standardPlaneNormal = planeGeometry->GetNormal();
270 assert((standardPlaneNormal - (top ? 1.0 : -1.0) * worldPlaneNormal).GetSquaredNorm() < 0.000001);
273 this->InitializeEvenlySpaced(planeGeometry, viewSpacing, slices);
276 Vector3D zAxisVector = this->GetAxisVector(2);
279 Vector3D upscaledStandardPlaneNormal = standardPlaneNormal;
280 upscaledStandardPlaneNormal *= slices;
281 assert((zAxisVector - upscaledStandardPlaneNormal).GetSquaredNorm() < 0.000001);
295 if (!m_ReferenceGeometry)
304 if (!firstPlane || dynamic_cast<AbstractTransformGeometry *>(firstPlane))
321 spacing[0] = this->CalculateSpacing(axis0);
322 spacing[1] = this->CalculateSpacing(axis1);
323 spacing[2] = this->CalculateSpacing(normal);
325 Superclass::SetSpacing(spacing);
332 ScalarType directedExtent = std::abs(m_ReferenceGeometry->GetExtentInMM(0) * normal[0]) +
333 std::abs(m_ReferenceGeometry->GetExtentInMM(1) * normal[1]) +
334 std::abs(m_ReferenceGeometry->GetExtentInMM(2) * normal[2]);
336 if (directedExtent >= spacing[2])
338 m_Slices =
static_cast<unsigned int>(directedExtent / spacing[2] + 0.5);
351 if (centerOfRotationDistance > 0)
353 firstPlane->
SetOrigin(firstPlane->
GetOrigin() + normal * (centerOfRotationDistance - directedExtent / 2.0));
354 m_DirectionVector = normal;
358 firstPlane->
SetOrigin(firstPlane->
GetOrigin() + normal * (directedExtent / 2.0 + centerOfRotationDistance));
359 m_DirectionVector = -normal;
367 int referencePointSlice =
static_cast<int>(referencePointDistance / spacing[2]);
369 double alignmentValue = referencePointDistance / spacing[2] - referencePointSlice;
371 firstPlane->
SetOrigin(firstPlane->
GetOrigin() + normal * alignmentValue * spacing[2]);
379 m_PlaneGeometries[0] = firstPlane;
383 m_SliceNavigationController->GetSlice()->SetSteps(m_Slices);
391 if (!m_ReferenceGeometry)
396 const mitk::Vector3D &spacing = m_ReferenceGeometry->GetSpacing();
409 double scaling = d[0] * d[0] / (spacing[0] * spacing[0]) + d[1] * d[1] / (spacing[1] * spacing[1]) +
410 d[2] * d[2] / (spacing[2] * spacing[2]);
412 scaling = sqrt(scaling);
414 return (sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]) / scaling);
420 m_ReferenceGeometry->GetIndexToWorldTransform()->GetInverse(inverse);
422 Vector3D transformedNormal = inverse->TransformVector(normal);
424 transformedNormal.Normalize();
425 return transformedNormal;
430 Superclass::SetImageGeometry(isAnImageGeometry);
433 for (s = 0; s < m_Slices; ++s)
436 if (geometry !=
nullptr)
446 for (s = 0; s < m_Slices; ++s)
449 if (geometry !=
nullptr)
455 Superclass::ChangeImageGeometryConsideringOriginOffset(isAnImageGeometry);
460 return ((s >= 0) && (s < (
int)m_Slices));
465 return m_ReferenceGeometry;
470 m_ReferenceGeometry = referenceGeometry;
472 std::vector<PlaneGeometry::Pointer>::iterator it;
474 for (it = m_PlaneGeometries.begin(); it != m_PlaneGeometries.end(); ++it)
476 (*it)->SetReferenceGeometry(referenceGeometry);
482 return ( m_ReferenceGeometry !=
nullptr );
487 bool hasEvenlySpacedPlaneGeometry =
false;
493 if (!(aSpacing[0] > 0 && aSpacing[1] > 0 && aSpacing[2] > 0))
495 mitkThrow() <<
"You try to set a spacing with at least one element equal or "
496 "smaller to \"0\". This might lead to a crash during rendering. Please double"
502 if ((m_EvenlySpaced) && (m_PlaneGeometries.size() > 0))
506 if (planeGeometry && !dynamic_cast<const AbstractTransformGeometry *>(planeGeometry))
508 this->WorldToIndex(planeGeometry->
GetOrigin(), origin);
509 this->WorldToIndex(planeGeometry->
GetAxisVector(0), rightDV);
510 this->WorldToIndex(planeGeometry->
GetAxisVector(1), bottomDV);
513 hasEvenlySpacedPlaneGeometry =
true;
523 if (hasEvenlySpacedPlaneGeometry)
526 this->IndexToWorld(origin, origin);
527 this->IndexToWorld(rightDV, rightDV);
528 this->IndexToWorld(bottomDV, bottomDV);
531 planeGeometry->SetImageGeometry(this->GetImageGeometry());
533 planeGeometry->SetReferenceGeometry(m_ReferenceGeometry);
537 planeGeometry->InitializeStandardPlane(rightDV.GetVnlVector(), bottomDV.GetVnlVector(), &lokalSpacing);
538 planeGeometry->SetOrigin(origin);
539 planeGeometry->SetBounds(bounds);
541 firstGeometry = planeGeometry;
543 else if ((m_EvenlySpaced) && (m_PlaneGeometries.size() > 0))
545 firstGeometry = m_PlaneGeometries[0].GetPointer();
550 m_PlaneGeometries.assign(m_Slices, gnull);
554 m_PlaneGeometries[0] = firstGeometry;
562 m_SliceNavigationController = snc;
567 return m_SliceNavigationController;
572 if (m_EvenlySpaced != on)
583 if (newDir != m_DirectionVector)
585 m_DirectionVector = newDir;
609 newGeometry->UnRegister();
610 return newGeometry.GetPointer();
615 Superclass::PrintSelf(os, indent);
616 os << indent <<
" EvenlySpaced: " << m_EvenlySpaced << std::endl;
619 os << indent <<
" DirectionVector: " << m_DirectionVector << std::endl;
621 os << indent <<
" Slices: " << m_Slices << std::endl;
624 os << indent <<
" GetPlaneGeometry(0): ";
625 if (this->GetPlaneGeometry(0) ==
nullptr)
627 os <<
"NULL" << std::endl;
631 this->GetPlaneGeometry(0)->Print(os, indent);
650 if (m_ReferenceGeometry)
664 Point3D center = m_ReferenceGeometry->GetCenter();
670 geometry2D->ExecuteOperation(¢eredRotation);
677 geometry2D->SetSpacing(this->GetSpacing());
679 if (m_SliceNavigationController)
682 m_SliceNavigationController->AdjustSliceStepperRange();
690 if (m_PlaneGeometries.size() > 0)
693 for (
auto iter = m_PlaneGeometries.begin(); iter != m_PlaneGeometries.end(); ++iter)
696 if ((*iter).IsNotNull())
698 (*iter)->ExecuteOperation(operation);
711 for (
auto iter = m_PlaneGeometries.begin(); iter != m_PlaneGeometries.end(); ++iter)
713 (*iter)->ExecuteOperation(operation);
729 if (!m_ReferenceGeometry ||
730 (!planeGeometry || dynamic_cast<AbstractTransformGeometry *>(planeGeometry.GetPointer())) || !planeOp)
757 currentNormal.Normalize();
758 newNormal.Normalize();
759 ScalarType rotationAngle = angle(currentNormal.GetVnlVector(), newNormal.GetVnlVector());
761 rotationAngle *= 180.0 / vnl_math::pi;
762 Vector3D rotationAxis = itk::CrossProduct(currentNormal, newNormal);
763 if (std::abs(rotationAngle - 180) <
mitk::eps)
768 helpNormal = currentNormal;
772 helpNormal.Normalize();
773 rotationAxis = itk::CrossProduct(helpNormal, currentNormal);
779 planeGeometry->ExecuteOperation(¢eredRotation);
786 this->ReinitializePlanes(center, planeOp->
GetPoint());
787 planeGeometry->SetSpacing(this->GetSpacing());
789 if (m_SliceNavigationController)
791 m_SliceNavigationController->SelectSliceByPoint(planeOp->
GetPoint());
792 m_SliceNavigationController->AdjustSliceStepperRange();
806 vecAxixNew.Normalize();
808 VecAxisCurr.Normalize();
810 ScalarType rotationAngle = angle(VecAxisCurr.GetVnlVector(), vecAxixNew.GetVnlVector());
811 rotationAngle = rotationAngle * 180 /
PI;
818 rotationAxis = itk::CrossProduct(VecAxisCurr, vecAxixNew);
819 if (std::abs(rotationAngle - 180) <
mitk::eps)
823 rotationAxis = newNormal;
828 planeGeometry->ExecuteOperation(&op);
831 this->ReinitializePlanes(center, planeOp->
GetPoint());
832 planeGeometry->SetSpacing(this->GetSpacing());
834 if (m_SliceNavigationController)
836 m_SliceNavigationController->SelectSliceByPoint(planeOp->
GetPoint());
837 m_SliceNavigationController->AdjustSliceStepperRange();
847 for (
auto iter = m_PlaneGeometries.begin(); iter != m_PlaneGeometries.end(); ++iter)
849 (*iter)->ExecuteOperation(operation);
864 if (m_ReferenceGeometry &&
865 (planeGeometry && dynamic_cast<AbstractTransformGeometry *>(planeGeometry.GetPointer()) ==
nullptr) &&
872 planeGeometry->ExecuteOperation(restorePlaneOp);
876 double centerOfRotationDistance = planeGeometry->SignedDistanceFromPlane(m_ReferenceGeometry->GetCenter());
878 if (centerOfRotationDistance <= 0)
880 m_DirectionVector = -m_DirectionVector;
885 Superclass::SetSpacing(spacing);
892 ScalarType directedExtent = std::abs(m_ReferenceGeometry->GetExtentInMM(0) * m_DirectionVector[0]) +
893 std::abs(m_ReferenceGeometry->GetExtentInMM(1) * m_DirectionVector[1]) +
894 std::abs(m_ReferenceGeometry->GetExtentInMM(2) * m_DirectionVector[2]);
896 if (directedExtent >= spacing[2])
898 m_Slices =
static_cast<unsigned int>(directedExtent / spacing[2] + 0.5);
909 m_PlaneGeometries[0] = planeGeometry;
912 m_SliceNavigationController->GetSlice()->SetSteps(m_Slices);
918 if (m_SliceNavigationController)
920 m_SliceNavigationController->GetSlice()->SetPos(restorePlaneOp->
GetPos());
921 m_SliceNavigationController->AdjustSliceStepperRange();
929 for (
auto iter = m_PlaneGeometries.begin(); iter != m_PlaneGeometries.end(); ++iter)
931 (*iter)->ExecuteOperation(operation);
942 geometry2D = m_PlaneGeometries[0];
947 geometry2D->ExecuteOperation(applyMatrixOp);
952 center = m_ReferenceGeometry->GetCenter();
ScalarType GetExtent(unsigned int direction) const
Set the time bounds (in ms)
const Point3D GetOrigin() const
Get the origin, e.g. the upper-left corner of the plane.
virtual void InitializePlanes(const mitk::BaseGeometry *geometry3D, mitk::PlaneGeometry::PlaneOrientation planeorientation, bool top=true, bool frontside=true, bool rotated=false)
Completely initialize this instance as evenly-spaced plane slices parallel to a side of the provided ...
mitk::Vector3D m_DirectionVector
itk::BoundingBox< unsigned long, 3, ScalarType > BoundingBox
Standard 3D-BoundingBox typedef.
itk::SmartPointer< Self > Pointer
bool HasReferenceGeometry() const
void SetSpacing(const mitk::Vector3D &aSpacing, bool enforceSetSpacing=false)
Set the spacing (m_Spacing).
virtual void InitializeSlicedGeometry(unsigned int slices)
Tell this instance how many PlaneGeometries it shall manage. Bounding box and the PlaneGeometries mus...
ScalarType SignedDistanceFromPlane(const Point3D &pt3d_mm) const
Signed distance of the point from the plane (bounding-box not considered)
virtual const Vector3D GetVectorOfRotation()
GetVectorOfRotation getter for the rotation axis.
Base class of all Operation-classes.
virtual const Point3D GetCenterOfRotation()
GetCenterOfRotation getter for the anchor point of rotation.
void _SetSpacing(const mitk::Vector3D &aSpacing, bool enforceSetSpacing=false)
virtual void ReinitializePlanes(const Point3D ¢er, const Point3D &referencePoint)
virtual void SetEvenlySpaced(bool on=true)
const mitk::Vector3D GetSpacing() const
Get the spacing (size of a pixel).
mitk::SliceNavigationController * GetSliceNavigationController()
virtual bool SetPlaneGeometry(mitk::PlaneGeometry *geometry2D, int s)
Set PlaneGeometry of slice s.
virtual const BaseGeometry * GetReferenceGeometry() const
Constants for most interaction classes, due to the generic StateMachines.
virtual itk::LightObject::Pointer InternalClone() const override
clones the geometry
const BoundsArrayType GetBounds() const
virtual void PreSetSpacing(const mitk::Vector3D &aSpacing) override
PreSetSpacing.
virtual void InitializeEvenlySpaced(mitk::PlaneGeometry *geometry2D, unsigned int slices)
Completely initialize this instance as evenly-spaced with slices parallel to the provided PlaneGeomet...
virtual void SetSliceNavigationController(mitk::SliceNavigationController *snc)
Set the SliceNavigationController corresponding to this sliced geometry.
std::vector< PlaneGeometry::Pointer > m_PlaneGeometries
void FillVector3D(Tout &out, mitk::ScalarType x, mitk::ScalarType y, mitk::ScalarType z)
Controls the selection of the slice the associated BaseRenderer will display.
virtual const mitk::BoundingBox * GetBoundingBox() const override
Vector3D GetNormal() const
Normal of the plane.
virtual unsigned int GetFrameOfReferenceID() const
Get the DICOM FrameOfReferenceID referring to the used world coordinate system.
const mitk::ScalarType PI
virtual void SetImageGeometry(const bool isAnImageGeometry) override
Define that this BaseGeometry is refering to an Image.
void PrintSelf(std::ostream &os, itk::Indent indent) const override
virtual ScalarType GetAngleOfRotation()
GetAngleOfRotation getter for rotation angle.
Vector3D GetAxisVector(unsigned int direction) const
Get vector along bounding-box in the specified direction in mm.
virtual void ChangeImageGeometryConsideringOriginOffset(const bool isAnImageGeometry) override
When switching from an Image Geometry to a normal Geometry (and the other way around), you have to.
void SetOrigin(const Point3D &origin)
Set the origin, i.e. the upper-left corner of the plane.
virtual mitk::PlaneGeometry * GetPlaneGeometry(int s) const
Returns the PlaneGeometry of the slice (s).
Operation for setting a plane (defined by its origin and normal)
void SetReferenceGeometry(const mitk::BaseGeometry *geometry)
Set the geometrical frame of reference in which this PlaneGeometry is placed.
Describes the geometry of a data object consisting of slices.
virtual void ChangeImageGeometryConsideringOriginOffset(const bool isAnImageGeometry)
When switching from an Image Geometry to a normal Geometry (and the other way around), you have to.
Vector3D GetDirectionVector()
virtual ~SlicedGeometry3D()
static double CalculateSpacing(const mitk::Vector3D &spacing, const mitk::Vector3D &d)
virtual const mitk::Vector3D & GetDirectionVector() const
MITKCORE_EXPORT const ScalarType eps
Describes a two-dimensional, rectangular plane.
mitk::Vector3D AdjustNormal(const mitk::Vector3D &normal) const
OperationType GetOperationType()
Operation, that holds everything necessary for an rotation operation on mitk::BaseData.
virtual void SetDirectionVector(const mitk::Vector3D &directionVector)
Set/Get the vector between slices for the evenly-spaced case (m_EvenlySpaced==true).
ScalarType GetExtentInMM(int direction) const
Get the extent of the bounding-box in the specified direction in mm.
virtual void SetReferenceGeometry(const BaseGeometry *referenceGeometry)
virtual void ExecuteOperation(Operation *operation) override
executes affine operations (translate, rotate, scale)
virtual bool GetImageGeometry() const
Is this an ImageGeometry?
virtual void SetImageGeometry(bool _arg)
Define that this BaseGeometry is refering to an Image.
BaseGeometry Describes the geometry of a data object.
virtual void ExecuteOperation(Operation *operation) override
executes affine operations (translate, rotate, scale)
virtual bool IsValidSlice(int s=0) const
Check whether a slice exists.
mitk::AffineTransform3D * GetIndexToWorldTransform()
Get the transformation used to convert from index to world coordinates.
BoundingBoxType::BoundsArrayType BoundsArrayType
static itkEventMacro(BoundingShapeInteractionEvent, itk::AnyEvent) class MITKBOUNDINGSHAPE_EXPORT BoundingShapeInteractor Pointer New()
Basic interaction methods for mitk::GeometryData.