Mercurial > hg > orthanc-stone
comparison UnitTestsSources/GeometryToolboxTests.cpp @ 1765:177f93c8371c
unit test SlicesSorter.HFP
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Tue, 11 May 2021 11:01:22 +0200 |
parents | 9ac2a65d4172 |
children | ae18b5cfbd3e |
comparison
equal
deleted
inserted
replaced
1764:adb59bcb0fc5 | 1765:177f93c8371c |
---|---|
19 **/ | 19 **/ |
20 | 20 |
21 | 21 |
22 #include <gtest/gtest.h> | 22 #include <gtest/gtest.h> |
23 | 23 |
24 #include "../OrthancStone/Sources/Toolbox/DicomInstanceParameters.h" | |
24 #include "../OrthancStone/Sources/Toolbox/FiniteProjectiveCamera.h" | 25 #include "../OrthancStone/Sources/Toolbox/FiniteProjectiveCamera.h" |
25 #include "../OrthancStone/Sources/Toolbox/GenericToolbox.h" | 26 #include "../OrthancStone/Sources/Toolbox/GenericToolbox.h" |
26 #include "../OrthancStone/Sources/Toolbox/GeometryToolbox.h" | 27 #include "../OrthancStone/Sources/Toolbox/GeometryToolbox.h" |
28 #include "../OrthancStone/Sources/Toolbox/SlicesSorter.h" | |
27 | 29 |
28 #include <Logging.h> | 30 #include <Logging.h> |
29 #include <OrthancException.h> | 31 #include <OrthancException.h> |
30 | 32 |
31 #include <boost/math/special_functions/round.hpp> | 33 #include <boost/math/special_functions/round.hpp> |
929 double r = d.GetNormal() [0] / 2.0; | 931 double r = d.GetNormal() [0] / 2.0; |
930 ASSERT_DOUBLE_EQ(-8 * r, d.GetNormal() [1]); | 932 ASSERT_DOUBLE_EQ(-8 * r, d.GetNormal() [1]); |
931 ASSERT_DOUBLE_EQ(5 * r, d.GetNormal() [2]); | 933 ASSERT_DOUBLE_EQ(5 * r, d.GetNormal() [2]); |
932 } | 934 } |
933 } | 935 } |
936 | |
937 | |
938 TEST(SlicesSorter, HFP) | |
939 { | |
940 // 2021-04-27-repro-bug-HFP-HFS-cartman | |
941 | |
942 { | |
943 // This is the last instance in the CT series ("InstanceNumber" is 368): | |
944 // CT1.2.752.243.1.1.20210202150623868.3730.61448.dcm | |
945 const OrthancStone::CoordinateSystem3D system("300\\302.5\\323.11", "-1\\0\\0\\0\\-1\\0"); | |
946 | |
947 /** | |
948 * The first instance in the series ("InstanceNumber" is 1) is | |
949 * CT1.2.752.243.1.1.20210202150623381.2000.76318.dcm, and its | |
950 * "ImagePositionPatient" is "300\\302.5\\690.11". It cannot be | |
951 * taken as the origin of the volume, otherwise the Z axis is | |
952 * shifted by the depth of the volume. | |
953 **/ | |
954 | |
955 const double spacingXY = 1.171875; | |
956 const double width = 512; | |
957 const double height = 512; | |
958 const double depth = 368; // Number of instances in the series | |
959 | |
960 OrthancStone::VolumeImageGeometry geometry; | |
961 geometry.SetAxialGeometry(system); | |
962 geometry.SetSizeInVoxels(width, height, depth); | |
963 geometry.SetVoxelDimensions(spacingXY, spacingXY, 1 /* pixel spacing Z */); | |
964 | |
965 OrthancStone::Vector p, q; | |
966 | |
967 p = OrthancStone::LinearAlgebra::CreateVector(0.5 / double(width), | |
968 0.5 / double(height), | |
969 0.5 / double(depth), 1); | |
970 q = OrthancStone::LinearAlgebra::Product(geometry.GetTransform(), p); | |
971 ASSERT_FLOAT_EQ(300, q[0]); | |
972 ASSERT_FLOAT_EQ(302.5, q[1]); | |
973 ASSERT_FLOAT_EQ(323.11, q[2]); | |
974 ASSERT_FLOAT_EQ(1, q[3]); | |
975 | |
976 p = OrthancStone::LinearAlgebra::CreateVector((width - 0.5) / double(width), | |
977 (height - 0.5) / double(height), | |
978 (depth - 0.5) / double(depth), 1); | |
979 q = OrthancStone::LinearAlgebra::Product(geometry.GetTransform(), p); | |
980 | |
981 ASSERT_FLOAT_EQ(300.0 - (width - 1.0) * spacingXY, q[0]); // "X" is swapped | |
982 ASSERT_FLOAT_EQ(302.5 - (height - 1.0) * spacingXY, q[1]); // "Y" is swapped | |
983 ASSERT_FLOAT_EQ(690.11, q[2]); | |
984 ASSERT_FLOAT_EQ(1, q[3]); | |
985 } | |
986 | |
987 { | |
988 // DOSE instance: RD1.2.752.243.1.1.20210202150624529.3790.85357_DoseTPS.dcm | |
989 OrthancStone::CoordinateSystem3D system("-217.0492\\-161.4141\\376.61", "1\\0\\0\\0\\1\\0"); | |
990 const double spacingXY = 3; | |
991 const double width = 146; // Columns | |
992 const double height = 84; // Row | |
993 const double depth = 86; // Number of frames, same as the length of "GridFrameOffsetVector" | |
994 | |
995 OrthancStone::VolumeImageGeometry geometry; | |
996 geometry.SetAxialGeometry(system); | |
997 geometry.SetSizeInVoxels(width, height, depth); | |
998 geometry.SetVoxelDimensions(spacingXY, spacingXY, 3 /* pixel spacing Z, cf. "GridFrameOffsetVector" */); | |
999 | |
1000 OrthancStone::Vector p, q; | |
1001 | |
1002 p = OrthancStone::LinearAlgebra::CreateVector(0.5 / double(width), 0.5 / double(height), 0.5 / double(depth), 1); | |
1003 q = OrthancStone::LinearAlgebra::Product(geometry.GetTransform(), p); | |
1004 ASSERT_FLOAT_EQ(-217.0492, q[0]); | |
1005 ASSERT_FLOAT_EQ(-161.4141, q[1]); | |
1006 ASSERT_FLOAT_EQ(376.61, q[2]); | |
1007 ASSERT_FLOAT_EQ(1, q[3]); | |
1008 | |
1009 p = OrthancStone::LinearAlgebra::CreateVector((width - 0.5) / double(width), | |
1010 (height - 0.5) / double(height), | |
1011 (depth - 0.5) / double(depth), 1); | |
1012 q = OrthancStone::LinearAlgebra::Product(geometry.GetTransform(), p); | |
1013 | |
1014 ASSERT_FLOAT_EQ(-217.0492 + (width - 1.0) * spacingXY, q[0]); | |
1015 ASSERT_FLOAT_EQ(-161.4141 + (height - 1.0) * spacingXY, q[1]); | |
1016 ASSERT_FLOAT_EQ(376.61 + 255.0 /* last item in "GridFrameOffsetVector" */, q[2]); | |
1017 ASSERT_FLOAT_EQ(1, q[3]); | |
1018 } | |
1019 | |
1020 for (unsigned int upward = 0; upward < 2; upward++) | |
1021 { | |
1022 OrthancStone::SlicesSorter slices; | |
1023 | |
1024 for (unsigned int i = 0; i < 368; i++) | |
1025 { | |
1026 unsigned int z = (upward ? 323 + i : 690 - i); | |
1027 OrthancStone::CoordinateSystem3D p("300\\302.5\\" + boost::lexical_cast<std::string>(z) + ".11", | |
1028 "-1\\0\\0\\0\\-1\\0"); | |
1029 slices.AddSlice(p, new Orthanc::SingleValueObject<unsigned int>(z)); | |
1030 } | |
1031 | |
1032 slices.Sort(); | |
1033 | |
1034 double spacingZ; | |
1035 ASSERT_TRUE(slices.ComputeSpacingBetweenSlices(spacingZ)); | |
1036 ASSERT_FLOAT_EQ(1, spacingZ); | |
1037 | |
1038 ASSERT_FLOAT_EQ(300.0, slices.GetSliceGeometry(0).GetOrigin() [0]); | |
1039 ASSERT_FLOAT_EQ(302.5, slices.GetSliceGeometry(0).GetOrigin() [1]); | |
1040 ASSERT_FLOAT_EQ(323.11, slices.GetSliceGeometry(0).GetOrigin() [2]); | |
1041 | |
1042 ASSERT_FLOAT_EQ(300.0, slices.GetSliceGeometry(367).GetOrigin() [0]); | |
1043 ASSERT_FLOAT_EQ(302.5, slices.GetSliceGeometry(367).GetOrigin() [1]); | |
1044 ASSERT_FLOAT_EQ(690.11, slices.GetSliceGeometry(367).GetOrigin() [2]); | |
1045 | |
1046 ASSERT_EQ(323u, dynamic_cast<const Orthanc::SingleValueObject<unsigned int>&>(slices.GetSlicePayload(0)).GetValue()); | |
1047 ASSERT_EQ(690u, dynamic_cast<const Orthanc::SingleValueObject<unsigned int>&>(slices.GetSlicePayload(367)).GetValue()); | |
1048 | |
1049 const unsigned int width = 512; | |
1050 const unsigned int height = 512; | |
1051 const unsigned int depth = 368; | |
1052 const double spacingXY = 1.171875; | |
1053 | |
1054 OrthancStone::VolumeImageGeometry geometry; | |
1055 geometry.SetSizeInVoxels(width, height, depth); | |
1056 geometry.SetVoxelDimensions(spacingXY, spacingXY, 1); | |
1057 geometry.SetAxialGeometry(slices.GetSliceGeometry(0)); | |
1058 | |
1059 OrthancStone::Vector p, q; | |
1060 | |
1061 p = OrthancStone::LinearAlgebra::CreateVector(0, 0, 0, 1); | |
1062 q = OrthancStone::LinearAlgebra::Product(geometry.GetTransform(), p); | |
1063 ASSERT_FLOAT_EQ(300 + spacingXY / 2.0, q[0]); | |
1064 ASSERT_FLOAT_EQ(302.5 + spacingXY / 2.0, q[1]); | |
1065 ASSERT_FLOAT_EQ(323.11 - 0.5, q[2]); | |
1066 ASSERT_FLOAT_EQ(1, q[3]); | |
1067 | |
1068 p = OrthancStone::LinearAlgebra::CreateVector(1, 1, 1, 1); | |
1069 q = OrthancStone::LinearAlgebra::Product(geometry.GetTransform(), p); | |
1070 ASSERT_FLOAT_EQ(300 - double(width) * spacingXY + spacingXY / 2.0, q[0]); | |
1071 ASSERT_FLOAT_EQ(302.5 - double(height) * spacingXY + spacingXY / 2.0, q[1]); | |
1072 ASSERT_FLOAT_EQ(323.11 + 368.0 - 0.5, q[2]); | |
1073 ASSERT_FLOAT_EQ(1, q[3]); | |
1074 } | |
1075 } |