/// <summary> /// Gets the directional matrix (image orientation to the patient) from the DICOM dataset. /// </summary> /// <param name="dicomDataset">The DICOM dataset.</param> /// <returns>The directional matrix (image orientation to the patient).</returns> /// <exception cref="ArgumentNullException">The provided DICOM dataset was null.</exception> /// <exception cref="ArgumentException">The provided DICOM dataset did not contain the 'ImageOrientationPatient' tag or the tag did not have 6 parts.</exception> public static Matrix3 GetDirectionalMatrix(this DicomDataset dicomDataset) { dicomDataset = dicomDataset ?? throw new ArgumentNullException(nameof(dicomDataset)); // Extract the 2 3-dimensional points from the 'ImageOrientationPatient' DICOM attribute. var imageOrientationPatientX = new Point3D( dicomDataset.GetRequiredDicomAttribute <double>(DicomTag.ImageOrientationPatient, 0), dicomDataset.GetRequiredDicomAttribute <double>(DicomTag.ImageOrientationPatient, 1), dicomDataset.GetRequiredDicomAttribute <double>(DicomTag.ImageOrientationPatient, 2)); var imageOrientationPatientY = new Point3D( dicomDataset.GetRequiredDicomAttribute <double>(DicomTag.ImageOrientationPatient, 3), dicomDataset.GetRequiredDicomAttribute <double>(DicomTag.ImageOrientationPatient, 4), dicomDataset.GetRequiredDicomAttribute <double>(DicomTag.ImageOrientationPatient, 5)); // Insist that the image orientations are of unit length, this is defined in the standard but // rounding in serialization can cause them to be slightly off with respect to the double representation. imageOrientationPatientX /= imageOrientationPatientX.Norm(); imageOrientationPatientY /= imageOrientationPatientY.Norm(); // The standard also insists iop[0] and iop[1] are orthogonal. return(Matrix3.FromColumns( imageOrientationPatientX, imageOrientationPatientY, Point3D.CrossProd(imageOrientationPatientX, imageOrientationPatientY))); }