diff --git a/Modules/Core/Common/include/itkAnatomicalOrientation.h b/Modules/Core/Common/include/itkAnatomicalOrientation.h index 2a17408ab557..316956b8cee4 100644 --- a/Modules/Core/Common/include/itkAnatomicalOrientation.h +++ b/Modules/Core/Common/include/itkAnatomicalOrientation.h @@ -66,8 +66,8 @@ class ITKCommon_EXPORT AnatomicalOrientation LeftToRight = 3, PosteriorToAnterior = 4, ///< front - 0b0100 AnteriorToPosterior = 5, ///< back - InferiorToSuperior = 8, ///< above - 0b1000 - SuperiorToInferior = 9, ///< bottom + InferiorToSuperior = 8, ///< head - 0b1000 + SuperiorToInferior = 9, ///< foot }; private: @@ -91,7 +91,7 @@ class ITKCommon_EXPORT AnatomicalOrientation #define ITK_ORIENTATION_ENUM(P, S, T) m_OrientationValue - enum class ToOrientationEnum : uint32_t + enum class ToEnum : uint32_t { INVALID = 0, @@ -246,6 +246,162 @@ class ITKCommon_EXPORT AnatomicalOrientation CoordinateEnum::RightToLeft) }; + enum class FromEnum : uint32_t + + { + INVALID = 0, + RIP = ITK_ORIENTATION_ENUM(CoordinateEnum::RightToLeft, + CoordinateEnum::InferiorToSuperior, + CoordinateEnum::PosteriorToAnterior), + LIP = ITK_ORIENTATION_ENUM(CoordinateEnum::LeftToRight, + CoordinateEnum::InferiorToSuperior, + CoordinateEnum::PosteriorToAnterior), + RSP = ITK_ORIENTATION_ENUM(CoordinateEnum::RightToLeft, + CoordinateEnum::SuperiorToInferior, + CoordinateEnum::PosteriorToAnterior), + LSP = ITK_ORIENTATION_ENUM(CoordinateEnum::LeftToRight, + CoordinateEnum::SuperiorToInferior, + CoordinateEnum::PosteriorToAnterior), + RIA = ITK_ORIENTATION_ENUM(CoordinateEnum::RightToLeft, + CoordinateEnum::InferiorToSuperior, + CoordinateEnum::AnteriorToPosterior), + LIA = ITK_ORIENTATION_ENUM(CoordinateEnum::LeftToRight, + CoordinateEnum::InferiorToSuperior, + CoordinateEnum::AnteriorToPosterior), + RSA = ITK_ORIENTATION_ENUM(CoordinateEnum::RightToLeft, + CoordinateEnum::SuperiorToInferior, + CoordinateEnum::AnteriorToPosterior), + LSA = ITK_ORIENTATION_ENUM(CoordinateEnum::LeftToRight, + CoordinateEnum::SuperiorToInferior, + CoordinateEnum::AnteriorToPosterior), + + IRP = ITK_ORIENTATION_ENUM(CoordinateEnum::InferiorToSuperior, + CoordinateEnum::RightToLeft, + CoordinateEnum::PosteriorToAnterior), + ILP = ITK_ORIENTATION_ENUM(CoordinateEnum::InferiorToSuperior, + CoordinateEnum::LeftToRight, + CoordinateEnum::PosteriorToAnterior), + SRP = ITK_ORIENTATION_ENUM(CoordinateEnum::SuperiorToInferior, + CoordinateEnum::RightToLeft, + CoordinateEnum::PosteriorToAnterior), + SLP = ITK_ORIENTATION_ENUM(CoordinateEnum::SuperiorToInferior, + CoordinateEnum::LeftToRight, + CoordinateEnum::PosteriorToAnterior), + IRA = ITK_ORIENTATION_ENUM(CoordinateEnum::InferiorToSuperior, + CoordinateEnum::RightToLeft, + CoordinateEnum::AnteriorToPosterior), + ILA = ITK_ORIENTATION_ENUM(CoordinateEnum::InferiorToSuperior, + CoordinateEnum::LeftToRight, + CoordinateEnum::AnteriorToPosterior), + SRA = ITK_ORIENTATION_ENUM(CoordinateEnum::SuperiorToInferior, + CoordinateEnum::RightToLeft, + CoordinateEnum::AnteriorToPosterior), + SLA = ITK_ORIENTATION_ENUM(CoordinateEnum::SuperiorToInferior, + CoordinateEnum::LeftToRight, + CoordinateEnum::AnteriorToPosterior), + + RPI = ITK_ORIENTATION_ENUM(CoordinateEnum::RightToLeft, + CoordinateEnum::PosteriorToAnterior, + CoordinateEnum::InferiorToSuperior), + LPI = ITK_ORIENTATION_ENUM(CoordinateEnum::LeftToRight, + CoordinateEnum::PosteriorToAnterior, + CoordinateEnum::InferiorToSuperior), + RAI = ITK_ORIENTATION_ENUM(CoordinateEnum::RightToLeft, + CoordinateEnum::AnteriorToPosterior, + CoordinateEnum::InferiorToSuperior), + LAI = ITK_ORIENTATION_ENUM(CoordinateEnum::LeftToRight, + CoordinateEnum::AnteriorToPosterior, + CoordinateEnum::InferiorToSuperior), + RPS = ITK_ORIENTATION_ENUM(CoordinateEnum::RightToLeft, + CoordinateEnum::PosteriorToAnterior, + CoordinateEnum::SuperiorToInferior), + LPS = ITK_ORIENTATION_ENUM(CoordinateEnum::LeftToRight, + CoordinateEnum::PosteriorToAnterior, + CoordinateEnum::SuperiorToInferior), + RAS = ITK_ORIENTATION_ENUM(CoordinateEnum::RightToLeft, + CoordinateEnum::AnteriorToPosterior, + CoordinateEnum::SuperiorToInferior), + LAS = ITK_ORIENTATION_ENUM(CoordinateEnum::LeftToRight, + CoordinateEnum::AnteriorToPosterior, + CoordinateEnum::SuperiorToInferior), + + PRI = ITK_ORIENTATION_ENUM(CoordinateEnum::PosteriorToAnterior, + CoordinateEnum::RightToLeft, + CoordinateEnum::InferiorToSuperior), + PLI = ITK_ORIENTATION_ENUM(CoordinateEnum::PosteriorToAnterior, + CoordinateEnum::LeftToRight, + CoordinateEnum::InferiorToSuperior), + ARI = ITK_ORIENTATION_ENUM(CoordinateEnum::AnteriorToPosterior, + CoordinateEnum::RightToLeft, + CoordinateEnum::InferiorToSuperior), + ALI = ITK_ORIENTATION_ENUM(CoordinateEnum::AnteriorToPosterior, + CoordinateEnum::LeftToRight, + CoordinateEnum::InferiorToSuperior), + PRS = ITK_ORIENTATION_ENUM(CoordinateEnum::PosteriorToAnterior, + CoordinateEnum::RightToLeft, + CoordinateEnum::SuperiorToInferior), + PLS = ITK_ORIENTATION_ENUM(CoordinateEnum::PosteriorToAnterior, + CoordinateEnum::LeftToRight, + CoordinateEnum::SuperiorToInferior), + ARS = ITK_ORIENTATION_ENUM(CoordinateEnum::AnteriorToPosterior, + CoordinateEnum::RightToLeft, + CoordinateEnum::SuperiorToInferior), + ALS = ITK_ORIENTATION_ENUM(CoordinateEnum::AnteriorToPosterior, + CoordinateEnum::LeftToRight, + CoordinateEnum::SuperiorToInferior), + + IPR = ITK_ORIENTATION_ENUM(CoordinateEnum::InferiorToSuperior, + CoordinateEnum::PosteriorToAnterior, + CoordinateEnum::RightToLeft), + SPR = ITK_ORIENTATION_ENUM(CoordinateEnum::SuperiorToInferior, + CoordinateEnum::PosteriorToAnterior, + CoordinateEnum::RightToLeft), + IAR = ITK_ORIENTATION_ENUM(CoordinateEnum::InferiorToSuperior, + CoordinateEnum::AnteriorToPosterior, + CoordinateEnum::RightToLeft), + SAR = ITK_ORIENTATION_ENUM(CoordinateEnum::SuperiorToInferior, + CoordinateEnum::AnteriorToPosterior, + CoordinateEnum::RightToLeft), + IPL = ITK_ORIENTATION_ENUM(CoordinateEnum::InferiorToSuperior, + CoordinateEnum::PosteriorToAnterior, + CoordinateEnum::LeftToRight), + SPL = ITK_ORIENTATION_ENUM(CoordinateEnum::SuperiorToInferior, + CoordinateEnum::PosteriorToAnterior, + CoordinateEnum::LeftToRight), + IAL = ITK_ORIENTATION_ENUM(CoordinateEnum::InferiorToSuperior, + CoordinateEnum::AnteriorToPosterior, + CoordinateEnum::LeftToRight), + SAL = ITK_ORIENTATION_ENUM(CoordinateEnum::SuperiorToInferior, + CoordinateEnum::AnteriorToPosterior, + CoordinateEnum::LeftToRight), + + PIR = ITK_ORIENTATION_ENUM(CoordinateEnum::PosteriorToAnterior, + CoordinateEnum::InferiorToSuperior, + CoordinateEnum::RightToLeft), + PSR = ITK_ORIENTATION_ENUM(CoordinateEnum::PosteriorToAnterior, + CoordinateEnum::SuperiorToInferior, + CoordinateEnum::RightToLeft), + AIR = ITK_ORIENTATION_ENUM(CoordinateEnum::AnteriorToPosterior, + CoordinateEnum::InferiorToSuperior, + CoordinateEnum::RightToLeft), + ASR = ITK_ORIENTATION_ENUM(CoordinateEnum::AnteriorToPosterior, + CoordinateEnum::SuperiorToInferior, + CoordinateEnum::RightToLeft), + PIL = ITK_ORIENTATION_ENUM(CoordinateEnum::PosteriorToAnterior, + CoordinateEnum::InferiorToSuperior, + CoordinateEnum::LeftToRight), + PSL = ITK_ORIENTATION_ENUM(CoordinateEnum::PosteriorToAnterior, + CoordinateEnum::SuperiorToInferior, + CoordinateEnum::LeftToRight), + AIL = ITK_ORIENTATION_ENUM(CoordinateEnum::AnteriorToPosterior, + CoordinateEnum::InferiorToSuperior, + CoordinateEnum::LeftToRight), + ASL = ITK_ORIENTATION_ENUM(CoordinateEnum::AnteriorToPosterior, + CoordinateEnum::SuperiorToInferior, + CoordinateEnum::LeftToRight) + + }; + #undef ITK_ORIENTATION_ENUM @@ -255,7 +411,7 @@ class ITKCommon_EXPORT AnatomicalOrientation */ AnatomicalOrientation(CoordinateEnum primary, CoordinateEnum secondary, CoordinateEnum tertiary); - AnatomicalOrientation(ToOrientationEnum orientation) + AnatomicalOrientation(ToEnum orientation) : m_Value(orientation) {} @@ -265,18 +421,24 @@ class ITKCommon_EXPORT AnatomicalOrientation * * @param legacyOrientation */ - AnatomicalOrientation(LegacyOrientationType legacyOrientation); + AnatomicalOrientation(LegacyOrientationType legacyOrientation) +# ifdef ITK_FUTURE_LEGACY_REMOVE + [deprecated("Use the AnatomicalOrientation::FromEnum type instead.")] +# endif + ; #endif + AnatomicalOrientation(FromEnum orientation); + explicit AnatomicalOrientation(const DirectionType & d) : m_Value(DirectionCosinesToOrientation(d)) {} explicit AnatomicalOrientation(std::string str); - operator ToOrientationEnum() const { return m_Value; } + operator ToEnum() const { return m_Value; } - const std::string & + std::string GetAsString() const; DirectionType @@ -285,7 +447,7 @@ class ITKCommon_EXPORT AnatomicalOrientation return OrientationToDirectionCosines(m_Value); } - ToOrientationEnum + ToEnum GetAsOrientation() const { return m_Value; @@ -309,6 +471,11 @@ class ITKCommon_EXPORT AnatomicalOrientation return GetCoordinateTerm(CoordinateMajornessTermsEnum::TertiaryMinor); } + std::array + GetTerms() const + { + return { GetPrimaryTerm(), GetSecondaryTerm(), GetTertiaryTerm() }; + } static bool SameOrientationAxes(CoordinateEnum a, CoordinateEnum b) @@ -318,42 +485,43 @@ class ITKCommon_EXPORT AnatomicalOrientation } /** \brief Return the closest orientation for a direction cosine matrix. */ - static ToOrientationEnum + static ToEnum DirectionCosinesToOrientation(const DirectionType & dir); /** \brief Return the direction cosine matrix for a orientation. */ - static DirectionType OrientationToDirectionCosines(ToOrientationEnum); + static DirectionType OrientationToDirectionCosines(ToEnum); friend ITKCommon_EXPORT std::ostream & - operator<<(std::ostream & out, ToOrientationEnum value); + operator<<(std::ostream & out, ToEnum value); private: // Private methods to create the maps, these will only be called once. - static std::map + static std::map CreateCodeToString(); - static std::map - CreateStringToCode(); /** \brief Return the global instance of the map from orientation enum to strings. * * The implementation uses a function static local variable so the global is created only if needed, only once. */ - static const std::map & + static const std::map & GetCodeToString(); /** \brief Return the global instance of the map from string to orientation enum. */ - static const std::map & + static const std::map & GetStringToCode(); - ToOrientationEnum m_Value; + ToEnum m_Value; }; ITKCommon_EXPORT std::ostream & - operator<<(std::ostream & out, typename AnatomicalOrientation::ToOrientationEnum value); + operator<<(std::ostream & out, typename AnatomicalOrientation::CoordinateEnum value); + +ITKCommon_EXPORT std::ostream & + operator<<(std::ostream & out, typename AnatomicalOrientation::ToEnum value); ITKCommon_EXPORT std::ostream & operator<<(std::ostream & out, const AnatomicalOrientation & orientation); diff --git a/Modules/Core/Common/src/itkAnatomicalOrientation.cxx b/Modules/Core/Common/src/itkAnatomicalOrientation.cxx index 35a9e9aa2fb4..7588243e0056 100644 --- a/Modules/Core/Common/src/itkAnatomicalOrientation.cxx +++ b/Modules/Core/Common/src/itkAnatomicalOrientation.cxx @@ -29,11 +29,11 @@ AnatomicalOrientation::AnatomicalOrientation(CoordinateEnum primary, CoordinateE if (SameOrientationAxes(primary, secondary) || SameOrientationAxes(primary, tertiary) || SameOrientationAxes(secondary, tertiary)) { - m_Value = ToOrientationEnum::INVALID; + m_Value = ToEnum::INVALID; } else { - m_Value = static_cast( + m_Value = static_cast( (static_cast(primary) << static_cast(CoordinateMajornessTermsEnum::PrimaryMinor)) + (static_cast(secondary) << static_cast(CoordinateMajornessTermsEnum::SecondaryMinor)) + (static_cast(tertiary) << static_cast(CoordinateMajornessTermsEnum::TertiaryMinor))); @@ -41,11 +41,12 @@ AnatomicalOrientation::AnatomicalOrientation(CoordinateEnum primary, CoordinateE } AnatomicalOrientation::AnatomicalOrientation(std::string str) - : m_Value(ToOrientationEnum::INVALID) + : m_Value(ToEnum::INVALID) { std::transform(str.begin(), str.end(), str.begin(), ::toupper); - const std::map & stringToCode = GetStringToCode(); - auto iter = stringToCode.find(str); + + const std::map & stringToCode = GetStringToCode(); + auto iter = stringToCode.find(str); if (iter != stringToCode.end()) { m_Value = iter->second; @@ -61,18 +62,42 @@ AnatomicalOrientation::AnatomicalOrientation(LegacyOrientationType legacyOrienta } #endif +AnatomicalOrientation::AnatomicalOrientation(AnatomicalOrientation::FromEnum fromOrientation) + : m_Value(ToEnum(uint32_t(fromOrientation))) +{} + -const std::string & +std::string AnatomicalOrientation::GetAsString() const { - const auto & codeToString = GetCodeToString(); - auto iter = codeToString.find(m_Value); - if (iter != codeToString.end()) + + // a lambda function to convert a CoordinateEnum to a char + auto enumAsChar = [](CoordinateEnum coord) -> char { + switch (coord) + { + case CoordinateEnum::RightToLeft: + return 'L'; + case CoordinateEnum::LeftToRight: + return 'R'; + case CoordinateEnum::AnteriorToPosterior: + return 'P'; + case CoordinateEnum::PosteriorToAnterior: + return 'A'; + case CoordinateEnum::InferiorToSuperior: + return 'S'; + case CoordinateEnum::SuperiorToInferior: + return 'I'; + default: + return 'X'; + } + }; + + if (m_Value == ToEnum::INVALID) { - return iter->second; + return "INVALID"; } - assert(codeToString.find(ToOrientationEnum::INVALID) != codeToString.end()); - return codeToString.find(ToOrientationEnum::INVALID)->second; + + return std::string({ enumAsChar(GetPrimaryTerm()), enumAsChar(GetSecondaryTerm()), enumAsChar(GetTertiaryTerm()) }); } @@ -82,99 +107,96 @@ AnatomicalOrientation::GetCoordinateTerm(CoordinateMajornessTermsEnum cmt) const return static_cast(static_cast(m_Value) >> static_cast(cmt) & 0xff); } -std::map -AnatomicalOrientation::CreateStringToCode() -{ - std::map stringToCode; - const std::map & codeToString = GetCodeToString(); - - for (const auto & kv : codeToString) - { - stringToCode[kv.second] = kv.first; - } - return stringToCode; -} - -const std::map & +const std::map & AnatomicalOrientation::GetCodeToString() { - static const std::map codeToString = CreateCodeToString(); + static const std::map codeToString = CreateCodeToString(); return codeToString; } -const std::map & +const std::map & AnatomicalOrientation::GetStringToCode() { - static const std::map stringToCode = CreateStringToCode(); + + auto createStringToCode = []() -> std::map { + std::map stringToCode; + const std::map & codeToString = GetCodeToString(); + + for (const auto & kv : codeToString) + { + stringToCode[kv.second] = kv.first; + } + return stringToCode; + }; + + static const std::map stringToCode = createStringToCode(); return stringToCode; } -std::map +std::map AnatomicalOrientation::CreateCodeToString() { - std::map orientToString; - auto helperAddCode = [&orientToString](std::string str, ToOrientationEnum code) { - orientToString[code] = std::move(str); - }; + std::map orientToString; + auto helperAddCode = [&orientToString](std::string str, ToEnum code) { orientToString[code] = std::move(str); }; // Map between axis string labels and SpatialOrientation - helperAddCode("RIP", ToOrientationEnum::RIP); - helperAddCode("LIP", ToOrientationEnum::LIP); - helperAddCode("RSP", ToOrientationEnum::RSP); - helperAddCode("LSP", ToOrientationEnum::LSP); - helperAddCode("RIA", ToOrientationEnum::RIA); - helperAddCode("LIA", ToOrientationEnum::LIA); - helperAddCode("RSA", ToOrientationEnum::RSA); - helperAddCode("LSA", ToOrientationEnum::LSA); - helperAddCode("IRP", ToOrientationEnum::IRP); - helperAddCode("ILP", ToOrientationEnum::ILP); - helperAddCode("SRP", ToOrientationEnum::SRP); - helperAddCode("SLP", ToOrientationEnum::SLP); - helperAddCode("IRA", ToOrientationEnum::IRA); - helperAddCode("ILA", ToOrientationEnum::ILA); - helperAddCode("SRA", ToOrientationEnum::SRA); - helperAddCode("SLA", ToOrientationEnum::SLA); - helperAddCode("RPI", ToOrientationEnum::RPI); - helperAddCode("LPI", ToOrientationEnum::LPI); - helperAddCode("RAI", ToOrientationEnum::RAI); - helperAddCode("LAI", ToOrientationEnum::LAI); - helperAddCode("RPS", ToOrientationEnum::RPS); - helperAddCode("LPS", ToOrientationEnum::LPS); - helperAddCode("RAS", ToOrientationEnum::RAS); - helperAddCode("LAS", ToOrientationEnum::LAS); - helperAddCode("PRI", ToOrientationEnum::PRI); - helperAddCode("PLI", ToOrientationEnum::PLI); - helperAddCode("ARI", ToOrientationEnum::ARI); - helperAddCode("ALI", ToOrientationEnum::ALI); - helperAddCode("PRS", ToOrientationEnum::PRS); - helperAddCode("PLS", ToOrientationEnum::PLS); - helperAddCode("ARS", ToOrientationEnum::ARS); - helperAddCode("ALS", ToOrientationEnum::ALS); - helperAddCode("IPR", ToOrientationEnum::IPR); - helperAddCode("SPR", ToOrientationEnum::SPR); - helperAddCode("IAR", ToOrientationEnum::IAR); - helperAddCode("SAR", ToOrientationEnum::SAR); - helperAddCode("IPL", ToOrientationEnum::IPL); - helperAddCode("SPL", ToOrientationEnum::SPL); - helperAddCode("IAL", ToOrientationEnum::IAL); - helperAddCode("SAL", ToOrientationEnum::SAL); - helperAddCode("PIR", ToOrientationEnum::PIR); - helperAddCode("PSR", ToOrientationEnum::PSR); - helperAddCode("AIR", ToOrientationEnum::AIR); - helperAddCode("ASR", ToOrientationEnum::ASR); - helperAddCode("PIL", ToOrientationEnum::PIL); - helperAddCode("PSL", ToOrientationEnum::PSL); - helperAddCode("AIL", ToOrientationEnum::AIL); - helperAddCode("ASL", ToOrientationEnum::ASL); - helperAddCode("INVALID", ToOrientationEnum::INVALID); + helperAddCode("RIP", ToEnum::RIP); + helperAddCode("LIP", ToEnum::LIP); + helperAddCode("RSP", ToEnum::RSP); + helperAddCode("LSP", ToEnum::LSP); + helperAddCode("RIA", ToEnum::RIA); + helperAddCode("LIA", ToEnum::LIA); + helperAddCode("RSA", ToEnum::RSA); + helperAddCode("LSA", ToEnum::LSA); + helperAddCode("IRP", ToEnum::IRP); + helperAddCode("ILP", ToEnum::ILP); + helperAddCode("SRP", ToEnum::SRP); + helperAddCode("SLP", ToEnum::SLP); + helperAddCode("IRA", ToEnum::IRA); + helperAddCode("ILA", ToEnum::ILA); + helperAddCode("SRA", ToEnum::SRA); + helperAddCode("SLA", ToEnum::SLA); + helperAddCode("RPI", ToEnum::RPI); + helperAddCode("LPI", ToEnum::LPI); + helperAddCode("RAI", ToEnum::RAI); + helperAddCode("LAI", ToEnum::LAI); + helperAddCode("RPS", ToEnum::RPS); + helperAddCode("LPS", ToEnum::LPS); + helperAddCode("RAS", ToEnum::RAS); + helperAddCode("LAS", ToEnum::LAS); + helperAddCode("PRI", ToEnum::PRI); + helperAddCode("PLI", ToEnum::PLI); + helperAddCode("ARI", ToEnum::ARI); + helperAddCode("ALI", ToEnum::ALI); + helperAddCode("PRS", ToEnum::PRS); + helperAddCode("PLS", ToEnum::PLS); + helperAddCode("ARS", ToEnum::ARS); + helperAddCode("ALS", ToEnum::ALS); + helperAddCode("IPR", ToEnum::IPR); + helperAddCode("SPR", ToEnum::SPR); + helperAddCode("IAR", ToEnum::IAR); + helperAddCode("SAR", ToEnum::SAR); + helperAddCode("IPL", ToEnum::IPL); + helperAddCode("SPL", ToEnum::SPL); + helperAddCode("IAL", ToEnum::IAL); + helperAddCode("SAL", ToEnum::SAL); + helperAddCode("PIR", ToEnum::PIR); + helperAddCode("PSR", ToEnum::PSR); + helperAddCode("AIR", ToEnum::AIR); + helperAddCode("ASR", ToEnum::ASR); + helperAddCode("PIL", ToEnum::PIL); + helperAddCode("PSL", ToEnum::PSL); + helperAddCode("AIL", ToEnum::AIL); + helperAddCode("ASL", ToEnum::ASL); + helperAddCode("INVALID", ToEnum::INVALID); return orientToString; } -typename AnatomicalOrientation::ToOrientationEnum +typename AnatomicalOrientation::ToEnum AnatomicalOrientation::DirectionCosinesToOrientation(const DirectionType & dir) { // NOTE: This method was based off of itk::SpatialObjectAdaptor::FromDirectionCosines @@ -240,7 +262,7 @@ AnatomicalOrientation::DirectionCosinesToOrientation(const DirectionType & dir) typename AnatomicalOrientation::DirectionType -AnatomicalOrientation::OrientationToDirectionCosines(ToOrientationEnum orientationEnum) +AnatomicalOrientation::OrientationToDirectionCosines(ToEnum orientationEnum) { const AnatomicalOrientation o(orientationEnum); @@ -274,10 +296,38 @@ AnatomicalOrientation::OrientationToDirectionCosines(ToOrientationEnum orientati } std::ostream & -operator<<(std::ostream & out, typename AnatomicalOrientation::ToOrientationEnum value) +operator<<(std::ostream & out, typename AnatomicalOrientation::CoordinateEnum value) { + switch (value) + { + case AnatomicalOrientation::CoordinateEnum::RightToLeft: + return out << "right-to-left"; + case AnatomicalOrientation::CoordinateEnum::LeftToRight: + return out << "left-to-right"; + case AnatomicalOrientation::CoordinateEnum::AnteriorToPosterior: + return out << "anterior-to-posterior"; + case AnatomicalOrientation::CoordinateEnum::PosteriorToAnterior: + return out << "posterior-to-anterior"; + case AnatomicalOrientation::CoordinateEnum::InferiorToSuperior: + return out << "inferior-to-superior"; + case AnatomicalOrientation::CoordinateEnum::SuperiorToInferior: + return out << "superior-to-inferior"; + case AnatomicalOrientation::CoordinateEnum::UNKNOWN: + return out << "unknown"; + default: + return out << "invalid"; + } +} + +std::ostream & +operator<<(std::ostream & out, typename AnatomicalOrientation::ToEnum value) +{ + auto iter = AnatomicalOrientation::GetCodeToString().find(value); - assert(iter != AnatomicalOrientation::GetCodeToString().end()); + if (iter == AnatomicalOrientation::GetCodeToString().end()) + { + return (out << "invalid"); + } return (out << iter->second); } @@ -285,7 +335,9 @@ operator<<(std::ostream & out, typename AnatomicalOrientation::ToOrientationEnum std::ostream & operator<<(std::ostream & out, const AnatomicalOrientation & orientation) { - return (out << orientation.GetAsString()); + const auto terms = orientation.GetTerms(); + static_assert(std::tuple_size{} == 3); + return out << terms[0] << " " << terms[1] << " " << terms[2]; } } // namespace itk diff --git a/Modules/Core/Common/test/itkAnatomicalOrientationGTest.cxx b/Modules/Core/Common/test/itkAnatomicalOrientationGTest.cxx index 5c311e1a6b82..2be4f52f812e 100644 --- a/Modules/Core/Common/test/itkAnatomicalOrientationGTest.cxx +++ b/Modules/Core/Common/test/itkAnatomicalOrientationGTest.cxx @@ -27,7 +27,7 @@ TEST(AnatomicalOrientation, ConstructionAndValues) { using itk::AnatomicalOrientation; - using OE = AnatomicalOrientation::ToOrientationEnum; + using OE = AnatomicalOrientation::ToEnum; using CE = AnatomicalOrientation::CoordinateEnum; using ImageType = itk::Image; @@ -105,7 +105,7 @@ TEST(AnatomicalOrientation, ConstructionAndValues) TEST(AnatomicalOrientation, DirectionCosinesToOrientation) { using itk::AnatomicalOrientation; - using OE = AnatomicalOrientation::ToOrientationEnum; + using OE = AnatomicalOrientation::ToEnum; using ImageType = itk::Image; ImageType::DirectionType d; d.SetIdentity(); @@ -160,7 +160,7 @@ TEST(AnatomicalOrientation, OrientationToDirectionCosines) { using itk::AnatomicalOrientation; using ImageType = itk::Image; - using OE = AnatomicalOrientation::ToOrientationEnum; + using OE = AnatomicalOrientation::ToEnum; ImageType::DirectionType d; d.SetIdentity(); @@ -204,12 +204,35 @@ TEST(AnatomicalOrientation, OrientationToDirectionCosines) EXPECT_EQ(d, AnatomicalOrientation::OrientationToDirectionCosines(OE::SPL)); } +TEST(AntomicalOrientation, ToFromEnumInteroperability) +{ + + using OE = itk::AnatomicalOrientation::ToEnum; + using FromOE = itk::AnatomicalOrientation::FromEnum; + using CE = itk::AnatomicalOrientation::CoordinateEnum; + + static_assert(int(OE::RAI) == int(FromOE::LPS)); + static_assert(int(OE::LPS) == int(FromOE::RAI)); + static_assert(int(OE::RAS) == int(FromOE::LPI)); + static_assert(int(OE::LPI) == int(FromOE::RAS)); + static_assert(int(OE::PIR) == int(FromOE::ASL)); + static_assert(int(OE::ASL) == int(FromOE::PIR)); + + itk::AnatomicalOrientation itk_rai(FromOE::RAI); + + EXPECT_EQ(itk_rai, itk::AnatomicalOrientation(OE::LPS)); + EXPECT_EQ(itk_rai.GetAsOrientation(), OE::LPS); + EXPECT_EQ(itk_rai.GetAsString(), "LPS"); + const std::array expected_terms = { { CE::RightToLeft, CE::AnteriorToPosterior, CE::InferiorToSuperior } }; + EXPECT_EQ(itk_rai.GetTerms(), expected_terms); +} + #ifndef ITK_FUTURE_LEGACY_REMOVE # include "itkSpatialOrientation.h" TEST(AnatomicalOrientation, LegacyInteroperability) { - using OE = itk::AnatomicalOrientation::ToOrientationEnum; + using OE = itk::AnatomicalOrientation::ToEnum; using SOE = itk::SpatialOrientationEnums::ValidCoordinateOrientations; // byte for byte compatibility, may assist with migration of bindings when types are not strictly enforced. diff --git a/Modules/IO/IPL/include/itkGEImageHeader.h b/Modules/IO/IPL/include/itkGEImageHeader.h index dcfbec0d14ce..bb477d8e6647 100644 --- a/Modules/IO/IPL/include/itkGEImageHeader.h +++ b/Modules/IO/IPL/include/itkGEImageHeader.h @@ -87,7 +87,7 @@ struct GEImageHeader float imageXres; float imageYres; - itk::AnatomicalOrientation::ToOrientationEnum coordinateOrientation; // uint32_t + itk::AnatomicalOrientation::ToEnum coordinateOrientation; // uint32_t short numberOfSlices; short offset; diff --git a/Modules/IO/NIFTI/src/itkNiftiImageIO.cxx b/Modules/IO/NIFTI/src/itkNiftiImageIO.cxx index 5b50d1d97f23..f00808619989 100644 --- a/Modules/IO/NIFTI/src/itkNiftiImageIO.cxx +++ b/Modules/IO/NIFTI/src/itkNiftiImageIO.cxx @@ -1885,7 +1885,7 @@ NiftiImageIO::SetImageIOOrientationFromNIfTI(unsigned short dims, double spacing this->GetLegacyAnalyze75Mode() != NiftiImageIOEnums::Analyze75Flavor::AnalyzeITK4 && this->GetLegacyAnalyze75Mode() != NiftiImageIOEnums::Analyze75Flavor::AnalyzeITK4Warning) { // only do this for Analyze file format - AnatomicalOrientation orient(AnatomicalOrientation::ToOrientationEnum::INVALID); + AnatomicalOrientation orient(AnatomicalOrientation::ToEnum::INVALID); switch (this->m_NiftiImage->analyze75_orient) { case a75_transverse_unflipped: