18 #include <itkSpatialOrientationAdapter.h> 20 #include <vtkTransform.h> 22 #include <vnl/vnl_cross.h> 37 auto matrix = transform->GetMatrix().GetVnlMatrix();
38 matrix.normalize_columns();
40 auto det = vnl_determinant(matrix);
41 if (fabs(det-1.0) > epsilon)
43 MITK_WARN <<
"Invalid rotation matrix! Determinant != 1 (" << det <<
")";
47 vnl_matrix_fixed<double, 3, 3> id;
id.set_identity();
48 auto should_be_id = matrix*matrix.transpose();
50 auto max = should_be_id.absolute_value_max();
53 MITK_WARN <<
"Invalid rotation matrix! R*R^T != ID. Max value: " <<
max <<
" (should be 0)";
73 assert(bounds[0] == 0);
74 assert(bounds[2] == 0);
76 assert(bounds[1] > 0);
77 assert(bounds[3] > 0);
94 MITK_WARN <<
"Warning! Call of the deprecated function PlaneGeometry::IndexToWorld(point, vec, vec). Use " 95 "PlaneGeometry::IndexToWorld(vec, vec) instead!";
107 MITK_WARN <<
"Warning! Call of the deprecated function PlaneGeometry::WorldToIndex(point, vec, vec). Use " 108 "PlaneGeometry::WorldToIndex(vec, vec) instead!";
127 AffineTransform3D::Pointer transform;
129 transform = AffineTransform3D::New();
130 AffineTransform3D::MatrixType matrix;
131 AffineTransform3D::MatrixType::InternalMatrixType &vnlmatrix = matrix.GetVnlMatrix();
133 vnlmatrix.set_identity();
134 vnlmatrix(0, 0) = spacing[0];
135 vnlmatrix(1, 1) = spacing[1];
136 vnlmatrix(2, 2) = spacing[2];
137 transform->SetIdentity();
138 transform->SetMatrix(matrix);
140 InitializeStandardPlane(width, height, transform.GetPointer(), planeorientation, zPosition, frontside, rotated, top);
188 switch (planeorientation)
196 if (rotated ==
false)
223 if (rotated ==
false)
244 if (rotated ==
false)
259 if (rotated ==
false)
278 if (rotated ==
false)
293 if (rotated ==
false)
310 itkExceptionMacro(
"unknown PlaneOrientation");
315 normal[normalDirection] = top ? 1 : -1;
317 if ( transform !=
nullptr )
319 origin = transform->TransformPoint( origin );
320 rightDV = transform->TransformVector( rightDV );
321 bottomDV = transform->TransformVector( bottomDV );
322 normal = transform->TransformVector( normal );
325 ScalarType bounds[6] = {0, width, 0, height, 0, 1};
328 AffineTransform3D::Pointer planeTransform = AffineTransform3D::New();
330 matrix.GetVnlMatrix().set_column(0, rightDV);
331 matrix.GetVnlMatrix().set_column(1, bottomDV);
332 matrix.GetVnlMatrix().set_column(2, normal);
333 planeTransform->SetMatrix(matrix);
342 std::vector< int > axes;
344 bool dominant_axis_error =
false;
345 for (
int i = 0; i < 3; ++i)
347 int dominantAxis = itk::Function::Max3(
348 rotation_matrix[0][i],
349 rotation_matrix[1][i],
350 rotation_matrix[2][i]
353 for (
int j=0; j<i; ++j)
354 if (axes[j] == dominantAxis)
356 dominant_axis_error =
true;
359 if (dominant_axis_error)
362 axes.push_back(dominantAxis);
365 if (dominant_axis_error)
367 MITK_DEBUG <<
"Error during dominant axis calculation. Using default.";
368 MITK_DEBUG <<
"This is either caused by an imperfect rotation matrix or if the rotation is axactly 45° around one or more axis.";
370 for (
int i = 0; i < 3; ++i)
393 matrix.GetVnlMatrix().normalize_columns();
394 mitk::AffineTransform3D::MatrixType::InternalMatrixType inverseMatrix = matrix.GetTranspose();
404 for (
int i=0; i<3; ++i)
406 int dominantAxis = axes.at(i);
407 directions[i] = itk::Function::Sign(inverseMatrix[dominantAxis][i]);
408 extents[i] = geometry3D->
GetExtent(dominantAxis);
409 spacings[i] = geometry3D->
GetSpacing()[dominantAxis];
413 matrix[0][0] = inverseMatrix[axes[0]][0] * directions[0] * spacings[0];
414 matrix[1][0] = inverseMatrix[axes[0]][1] * directions[0] * spacings[0];
415 matrix[2][0] = inverseMatrix[axes[0]][2] * directions[0] * spacings[0];
416 matrix[0][1] = inverseMatrix[axes[1]][0] * directions[1] * spacings[1];
417 matrix[1][1] = inverseMatrix[axes[1]][1] * directions[1] * spacings[1];
418 matrix[2][1] = inverseMatrix[axes[1]][2] * directions[1] * spacings[1];
419 matrix[0][2] = inverseMatrix[axes[2]][0] * directions[2] * spacings[2];
420 matrix[1][2] = inverseMatrix[axes[2]][1] * directions[2] * spacings[2];
421 matrix[2][2] = inverseMatrix[axes[2]][2] * directions[2] * spacings[2];
427 for (
int i = 0; i < 3; ++i)
430 double offset = directions[i] > 0 ? 0.0 : extents[i];
434 offset += directions[i] * 0.5;
437 for (
int j = 0; j < 3; ++j)
439 worldOrigin[j] -= offset * matrix[j][i];
443 switch(planeorientation)
461 itkExceptionMacro(
"unknown PlaneOrientation");
464 ScalarType bounds[6]= { 0, width, 0, height, 0, 1 };
467 AffineTransform3D::Pointer transform = AffineTransform3D::New();
468 transform->SetMatrix(matrix);
469 transform->SetOffset(worldOrigin.GetVectorFromOrigin());
472 width, height, transform, planeorientation, zPosition, frontside, rotated, top);
480 switch(planeorientation)
495 itkExceptionMacro(
"unknown PlaneOrientation");
502 mitk::AffineTransform3D::MatrixType matrix = affineTransform->GetMatrix();
503 matrix.GetVnlMatrix().normalize_columns();
504 mitk::AffineTransform3D::MatrixType::InternalMatrixType inverseMatrix = matrix.GetInverse();
553 VnlVector normal = vnl_cross_3d(rightVector, downVector);
559 if (spacing !=
nullptr)
561 rightDV *= (*spacing)[0];
562 downDV *= (*spacing)[1];
563 normal *= (*spacing)[2];
566 AffineTransform3D::Pointer transform = AffineTransform3D::New();
568 matrix.GetVnlMatrix().set_column(0, rightDV);
569 matrix.GetVnlMatrix().set_column(1, downDV);
570 matrix.GetVnlMatrix().set_column(2, normal);
571 transform->SetMatrix(matrix);
574 ScalarType bounds[6] = {0, width, 0, height, 0, 1};
582 VnlVector rightVectorVnl(3), downVectorVnl;
584 if (
Equal(normal[1], 0.0f) ==
false)
586 FillVector3D(rightVectorVnl, 1.0f, -normal[0] / normal[1], 0.0f);
587 rightVectorVnl.normalize();
593 downVectorVnl = vnl_cross_3d(normal.GetVnlVector(), rightVectorVnl);
594 downVectorVnl.normalize();
606 VnlVector normal = vnl_cross_3d(rightVector, downVector);
613 AffineTransform3D::Pointer transform = AffineTransform3D::New();
615 matrix.GetVnlMatrix().set_column(0, rightVector);
616 matrix.GetVnlMatrix().set_column(1, downVector);
617 matrix.GetVnlMatrix().set_column(2, normal);
618 transform->SetMatrix(matrix);
640 if (considerBoundingBox)
656 planeNormal.Normalize();
658 Vector3D direction = itk::CrossProduct(normal, planeNormal);
660 if (direction.GetSquaredNorm() <
eps)
665 double N1dN2 = normal * planeNormal;
666 double determinant = 1.0 - N1dN2 * N1dN2;
671 double d1 = normal * origin;
672 double d2 = planeNormal * planeOrigin;
674 double c1 = (d1 - d2 * N1dN2) / determinant;
675 double c2 = (d2 - d1 * N1dN2) / determinant;
677 Vector3D p = normal * c1 + planeNormal * c2;
678 crossline.
GetPoint().GetVnlVector() = p.GetVnlVector();
712 planeNormal.Normalize();
715 lineDirection.Normalize();
717 double t = planeNormal * lineDirection;
725 t = (planeNormal * diff) / t;
727 intersectionPoint = line.
GetPoint() + lineDirection * t;
737 t = planeNormal * lineDirection;
746 t = (planeNormal * diff) / t;
775 newGeometry->UnRegister();
776 return newGeometry.GetPointer();
781 vtkTransform *transform = vtkTransform::New();
789 if (planeOp ==
nullptr)
794 Point3D center = planeOp->GetPoint();
796 Vector3D orientationVector = planeOp->GetNormal();
800 Vector3D rotationAxis = itk::CrossProduct(orientationVector, defaultVector);
803 double rotationAngle = atan2((
double)rotationAxis.GetNorm(), (double)(orientationVector * defaultVector));
804 rotationAngle *= 180.0 / vnl_math::pi;
806 transform->PostMultiply();
807 transform->Identity();
808 transform->Translate(center[0], center[1], center[2]);
809 transform->RotateWXYZ(rotationAngle, rotationAxis[0], rotationAxis[1], rotationAxis[2]);
810 transform->Translate(-center[0], -center[1], -center[2]);
821 AffineTransform3D::Pointer transform2 = AffineTransform3D::New();
823 matrix.GetVnlMatrix().set_column(0, op->GetTransform()->GetMatrix().GetVnlMatrix().get_column(0));
824 matrix.GetVnlMatrix().set_column(1, op->GetTransform()->GetMatrix().GetVnlMatrix().get_column(1));
825 matrix.GetVnlMatrix().set_column(2, op->GetTransform()->GetMatrix().GetVnlMatrix().get_column(2));
826 transform2->SetMatrix(matrix);
828 transform2->SetOffset(offset);
831 ScalarType bounds[6] = {0, op->GetWidth(), 0, op->GetHeight(), 0, 1};
853 os << indent <<
" Normal: " <<
GetNormal() << std::endl;
885 ScalarType bounds[6] = {0, width, 0, height, 0, 1};
934 MITK_WARN <<
"Deprecated function! Call Project(vec3D,vec3D) instead.";
951 Point2D pt2d_mm_start, pt2d_mm_end;
953 bool inside =
Map(atPt3d_mm, pt2d_mm_start);
954 pt3d_mm_end = atPt3d_mm + vec3d_mm;
955 inside &=
Map(pt3d_mm_end, pt2d_mm_end);
956 vec2d_mm = pt2d_mm_end - pt2d_mm_start;
VnlVector GetNormalVnl() const
Normal of the plane as VnlVector.
virtual ScalarType SignedDistance(const Point3D &pt3d_mm) const
virtual bool GetImageGeometry() const
Is this an ImageGeometry?
static std::vector< int > CalculateDominantAxes(mitk::AffineTransform3D::MatrixType::InternalMatrixType &rotation_matrix)
vtkMatrix4x4 * GetVtkMatrix()
void ExecuteOperation(Operation *operation) override
void SetDirection(const itk::Vector< TCoordRep, NPointDimension > &direction)
Set the direction vector of the line.
void SetIndexToWorldTransform(mitk::AffineTransform3D *transform)
bool IsBoundingBoxNull() const
void PrintSelf(std::ostream &os, itk::Indent indent) const override
Base class of all Operation-classes.
void PrintSelf(std::ostream &os, itk::Indent indent) const override
vnl_vector< ScalarType > VnlVector
static bool CheckRotationMatrix(AffineTransform3D *transform, double epsilon=mitk::eps)
Check if matrix is a rotation matrix:
bool IntersectionPointParam(const Line3D &line, double &t) const
Calculate line parameter of intersection point between the plane and a line.
unsigned int IntersectWithPlane2D(const PlaneGeometry *plane, Point2D &lineFrom, Point2D &lineTo) const
Calculate two points where another plane intersects the border of this plane.
bool IsOnPlane(const Point3D &point) const
Returns whether the point is on the plane (bounding-box not considered)
bool IntersectionPoint(const Line3D &line, Point3D &intersectionPoint) const
Calculate intersection point between the plane and a line.
ScalarType GetExtent(unsigned int direction) const
Set the time bounds (in ms)
DataCollection - Class to facilitate loading/accessing structured data.
void Initialize()
Initialize the BaseGeometry.
Constants for most interaction classes, due to the generic StateMachines.
virtual bool Map(const mitk::Point3D &pt3d_mm, mitk::Point2D &pt2d_mm) const
Project a 3D point given in mm (pt3d_mm) onto the 2D geometry. The result is a 2D point in mm (pt2d_m...
virtual bool Project(const mitk::Point3D &pt3d_mm, mitk::Point3D &projectedPt3d_mm) const
Project a 3D point given in mm (pt3d_mm) onto the 2D geometry. The result is a 3D point in mm (projec...
void CheckIndexToWorldTransform(mitk::AffineTransform3D *transform) override
CheckIndexToWorldTransform.
void FillVector3D(Tout &out, mitk::ScalarType x, mitk::ScalarType y, mitk::ScalarType z)
ScalarType GetExtentInMM(int direction) const
Get the extent of the bounding-box in the specified direction in mm.
const BaseGeometry * GetReferenceGeometry() const
Get the geometrical frame of reference for this PlaneGeometry.
virtual void IndexToWorld(const Point2D &pt_units, Point2D &pt_mm) const
const itk::Point< TCoordRep, NPointDimension > & GetPoint() const
Get start point of the line.
const mitk::BaseGeometry * m_ReferenceGeometry
bool HasReferenceGeometry() const
bool IntersectionLine(const PlaneGeometry *plane, Line3D &crossline) const
Calculate the intersecting line of two planes.
const itk::Vector< TCoordRep, NPointDimension > & GetDirection() const
Get the direction vector of the line.
void SetVtkMatrixDeepCopy(vtkTransform *vtktransform)
ScalarType DistanceFromPlane(const Point3D &pt3d_mm) const
Distance of the point from the plane (bounding-box not considered)
virtual void SetSizeInUnits(mitk::ScalarType width, mitk::ScalarType height)
Set the width and height of this 2D-geometry in units by calling SetBounds. This does not change the ...
virtual void WorldToIndex(const Point2D &pt_mm, Point2D &pt_units) const
double Angle(const PlaneGeometry *plane) const
Calculate the angle between two planes.
virtual bool IsAbove(const Point3D &pt3d_mm, bool considerBoundingBox=false) const
Calculates, whether a point is below or above the plane. There are two different calculation methods...
void SetOrigin(const Point3D &origin)
Set the origin, i.e. the upper-left corner of the plane.
ScalarType SignedDistanceFromPlane(const Point3D &pt3d_mm) const
Signed distance of the point from the plane (bounding-box not considered)
void Modified() const override
Overload of function Modified() to prohibit several calls of Modified() using the ModifiedLock class...
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.
itk::AffineGeometryFrame< ScalarType, 3 >::TransformType AffineTransform3D
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.
Point3D ProjectPointOntoPlane(const Point3D &pt) const
Returns the lot from the point to the plane.
bool IsParallel(const PlaneGeometry *plane) const
Returns whether the plane is parallel to another plane.
MITKCORE_EXPORT const ScalarType sqrteps
Vector3D GetNormal() const
Normal of the plane.
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)
itk::Point< TCoordRep, NPointDimension > GetPoint2() const
Get end point of the line.
const mitk::Vector3D GetSpacing() const
Get the spacing (size of a pixel).
itk::LightObject::Pointer InternalClone() const override
clones the geometry
void SetExtentInMM(int direction, ScalarType extentInMM)
Set the extent of the bounding-box in the specified direction in mm.
static int RectangleLineIntersection(TCoordRep x1, TCoordRep y1, TCoordRep x2, TCoordRep y2, itk::Point< TCoordRep, 2 > p, itk::Vector< TCoordRep, 2 > d, itk::Point< TCoordRep, 2 > &s1, itk::Point< TCoordRep, 2 > &s2)
Calculates the intersection points of a straight line in 2D with a rectangle.
void SetMatrixByVectors(const VnlVector &rightVector, const VnlVector &downVector, ScalarType thickness=1.0)
Initialize plane by right-/down-vector.
void CheckBounds(const BoundsArrayType &bounds) override
CheckBounds.
virtual void InitializePlane(const Point3D &origin, const Vector3D &normal)
Initialize plane by origin and normal (size is 1.0 mm in all directions, direction of right-/down-vec...
MITKCORE_EXPORT const ScalarType eps
ScalarType Distance(const Point3D &pt3d_mm) const
Distance of the point from the geometry (bounding-box not considered)
virtual void InitializeStandardPlane(const BaseGeometry *geometry3D, PlaneOrientation planeorientation=Axial, ScalarType zPosition=0, bool frontside=true, bool rotated=false, bool top=true)
Initialize a plane with orientation planeorientation (default: axial) with respect to BaseGeometry (d...
Describes a two-dimensional, rectangular plane.
OperationType GetOperationType()
~PlaneGeometry() override
const BoundsArrayType GetBounds() const
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
virtual const BoundingBoxType * GetBoundingBox()