From 7963339c29aed2b3654f4fc998fa83ab5ac94b62 Mon Sep 17 00:00:00 2001
From: Matthias Puchner <github@mpuchner.de>
Date: Mon, 16 Aug 2021 07:41:58 +0200
Subject: [PATCH] reduce item hierarchy usage and exposure on public class
 interface for rotation information

---
 GUI/Models/ItemWithParticles.cpp |  6 +++++
 GUI/Models/ItemWithParticles.h   |  6 ++++-
 GUI/Models/RotationItems.cpp     | 39 ++++++++++++++++++++------------
 GUI/Models/RotationItems.h       | 26 ++++++++++++++-------
 GUI/Models/TransformToDomain.cpp | 24 +++++---------------
 GUI/Models/TransformToDomain.h   |  2 --
 6 files changed, 60 insertions(+), 43 deletions(-)

diff --git a/GUI/Models/ItemWithParticles.cpp b/GUI/Models/ItemWithParticles.cpp
index d1a5c0f6064..51be13cb207 100644
--- a/GUI/Models/ItemWithParticles.cpp
+++ b/GUI/Models/ItemWithParticles.cpp
@@ -13,6 +13,7 @@
 //  ************************************************************************************************
 
 #include "GUI/Models/ItemWithParticles.h"
+#include "Base/Vector/Transform3D.h"
 #include "GUI/Models/RotationItems.h"
 #include "GUI/Models/SessionItemUtils.h"
 #include "GUI/Models/SessionModel.h"
@@ -73,6 +74,11 @@ bool ItemWithParticles::isTransformationTagName(const QString& name)
     return name == T_TRANSFORMATION;
 }
 
+Transform3D ItemWithParticles::rotation() const
+{
+    return transformationItem() ? transformationItem()->rotationItem()->rotation() : Transform3D();
+}
+
 ItemWithParticles::ItemWithParticles(const QString& model_type, const QString& abundance_tooltip,
                                      const QString& position_tooltip)
     : SessionGraphicsItem(model_type)
diff --git a/GUI/Models/ItemWithParticles.h b/GUI/Models/ItemWithParticles.h
index 1a653005a86..24ac47a10a3 100644
--- a/GUI/Models/ItemWithParticles.h
+++ b/GUI/Models/ItemWithParticles.h
@@ -21,6 +21,7 @@
 class RotationItem;
 class TransformationItem;
 class VectorItem;
+class Transform3D;
 
 class BA_CORE_API_ ItemWithParticles : public virtual SessionGraphicsItem {
 private:
@@ -37,11 +38,13 @@ public:
     void setPosition(const R3& position);
     VectorItem* positionItem() const;
 
-    TransformationItem* transformationItem() const;
     TransformationItem* createTransformationItem();
     void setTransformation(RotationItem* transformation);
     static bool isTransformationTagName(const QString& name);
 
+    //! Returns identity transformation if no rotation is defined at all
+    Transform3D rotation() const;
+
 protected:
     ItemWithParticles(const QString& model_type, const QString& abundance_tooltip,
                       const QString& position_tooltip);
@@ -50,6 +53,7 @@ protected:
 
 private:
     virtual bool isShellParticle() const;
+    TransformationItem* transformationItem() const;
 };
 
 #endif // BORNAGAIN_GUI_MODELS_ITEMWITHMATERIAL_H
diff --git a/GUI/Models/RotationItems.cpp b/GUI/Models/RotationItems.cpp
index 72f6817c589..da3fa8b66ed 100644
--- a/GUI/Models/RotationItems.cpp
+++ b/GUI/Models/RotationItems.cpp
@@ -14,10 +14,21 @@
 
 #include "GUI/Models/RotationItems.h"
 #include "Base/Const/Units.h"
+#include "Base/Vector/Transform3D.h"
 #include "Sample/Scattering/Rotations.h"
 
 // ----------------------------------------------------------------------------
 
+RotationItem::RotationItem(const QString& name) : SessionItem(name) {}
+
+Transform3D RotationItem::rotation() const
+{
+    std::unique_ptr<IRotation> p(createRotation());
+    return (p != nullptr) ? p->getTransform3D() : Transform3D();
+}
+
+// ----------------------------------------------------------------------------
+
 const QString XRotationItem::P_ANGLE = "Angle";
 
 const QString XRotationItem::M_TYPE = "XRotation";
@@ -28,10 +39,10 @@ XRotationItem::XRotationItem() : RotationItem(M_TYPE)
     addProperty(P_ANGLE, 0.0)->setToolTip("Rotation angle around x-axis in degrees");
 }
 
-std::unique_ptr<IRotation> XRotationItem::createRotation() const
+IRotation* XRotationItem::createRotation() const
 {
-    double alpha = Units::deg2rad(getItemValue(P_ANGLE).toDouble());
-    return std::make_unique<RotationX>(alpha);
+    const double alpha = Units::deg2rad(getItemValue(P_ANGLE).toDouble());
+    return new RotationX(alpha);
 }
 
 void XRotationItem::setAngleValue(const double angle)
@@ -51,10 +62,10 @@ YRotationItem::YRotationItem() : RotationItem(M_TYPE)
     addProperty(P_ANGLE, 0.0)->setToolTip("Rotation angle around y-axis in degrees");
 }
 
-std::unique_ptr<IRotation> YRotationItem::createRotation() const
+IRotation* YRotationItem::createRotation() const
 {
-    double alpha = Units::deg2rad(getItemValue(P_ANGLE).toDouble());
-    return std::make_unique<RotationY>(alpha);
+    const double alpha = Units::deg2rad(getItemValue(P_ANGLE).toDouble());
+    return new RotationY(alpha);
 }
 
 void YRotationItem::setAngleValue(const double angle)
@@ -74,10 +85,10 @@ ZRotationItem::ZRotationItem() : RotationItem(M_TYPE)
     addProperty(P_ANGLE, 0.0)->setToolTip("Rotation angle around z-axis in degrees");
 }
 
-std::unique_ptr<IRotation> ZRotationItem::createRotation() const
+IRotation* ZRotationItem::createRotation() const
 {
-    double alpha = Units::deg2rad(getItemValue(P_ANGLE).toDouble());
-    return std::make_unique<RotationZ>(alpha);
+    const double alpha = Units::deg2rad(getItemValue(P_ANGLE).toDouble());
+    return new RotationZ(alpha);
 }
 
 void ZRotationItem::setAngleValue(const double angle)
@@ -102,12 +113,12 @@ EulerRotationItem::EulerRotationItem() : RotationItem(M_TYPE)
     addProperty(P_GAMMA, 0.0)->setToolTip("Third Euler anle in z-x'-z' sequence in degrees");
 }
 
-std::unique_ptr<IRotation> EulerRotationItem::createRotation() const
+IRotation* EulerRotationItem::createRotation() const
 {
-    double alpha = Units::deg2rad(getItemValue(P_ALPHA).toDouble());
-    double beta = Units::deg2rad(getItemValue(P_BETA).toDouble());
-    double gamma = Units::deg2rad(getItemValue(P_GAMMA).toDouble());
-    return std::make_unique<RotationEuler>(alpha, beta, gamma);
+    const double alpha = Units::deg2rad(getItemValue(P_ALPHA).toDouble());
+    const double beta = Units::deg2rad(getItemValue(P_BETA).toDouble());
+    const double gamma = Units::deg2rad(getItemValue(P_GAMMA).toDouble());
+    return new RotationEuler(alpha, beta, gamma);
 }
 
 void EulerRotationItem::setAlphaValue(const double alpha)
diff --git a/GUI/Models/RotationItems.h b/GUI/Models/RotationItems.h
index 07092734bf2..f0e101b56a5 100644
--- a/GUI/Models/RotationItems.h
+++ b/GUI/Models/RotationItems.h
@@ -18,13 +18,15 @@
 #include "GUI/Models/SessionItem.h"
 
 class IRotation;
+class Transform3D;
 
 class BA_CORE_API_ RotationItem : public SessionItem {
-protected:
-    explicit RotationItem(const QString& name) : SessionItem(name) {}
-
 public:
-    virtual std::unique_ptr<IRotation> createRotation() const = 0;
+    Transform3D rotation() const;
+
+protected:
+    explicit RotationItem(const QString& name);
+    virtual IRotation* createRotation() const = 0;
 };
 
 class BA_CORE_API_ XRotationItem : public RotationItem {
@@ -34,8 +36,10 @@ private:
 public:
     static const QString M_TYPE;
     XRotationItem();
-    std::unique_ptr<IRotation> createRotation() const;
     void setAngleValue(double angle);
+
+protected:
+    IRotation* createRotation() const override;
 };
 
 class BA_CORE_API_ YRotationItem : public RotationItem {
@@ -45,8 +49,10 @@ private:
 public:
     static const QString M_TYPE;
     YRotationItem();
-    std::unique_ptr<IRotation> createRotation() const;
     void setAngleValue(double angle);
+
+protected:
+    IRotation* createRotation() const override;
 };
 
 class BA_CORE_API_ ZRotationItem : public RotationItem {
@@ -56,8 +62,10 @@ private:
 public:
     static const QString M_TYPE;
     ZRotationItem();
-    std::unique_ptr<IRotation> createRotation() const;
     void setAngleValue(double angle);
+
+protected:
+    IRotation* createRotation() const override;
 };
 
 class BA_CORE_API_ EulerRotationItem : public RotationItem {
@@ -69,10 +77,12 @@ private:
 public:
     static const QString M_TYPE;
     EulerRotationItem();
-    std::unique_ptr<IRotation> createRotation() const;
     void setAlphaValue(double alpha);
     void setBetaValue(double beta);
     void setGammaValue(double gamma);
+
+protected:
+    IRotation* createRotation() const override;
 };
 
 #endif // BORNAGAIN_GUI_MODELS_ROTATIONITEMS_H
diff --git a/GUI/Models/TransformToDomain.cpp b/GUI/Models/TransformToDomain.cpp
index 996ed53e49f..0289b36489e 100644
--- a/GUI/Models/TransformToDomain.cpp
+++ b/GUI/Models/TransformToDomain.cpp
@@ -13,6 +13,7 @@
 //  ************************************************************************************************
 
 #include "GUI/Models/TransformToDomain.h"
+#include "Base/Vector/Transform3D.h"
 #include "Core/Scan/AlphaScan.h"
 #include "Core/Simulation/GISASSimulation.h"
 #include "Device/Resolution/ScanResolution.h"
@@ -185,24 +186,11 @@ void GUI::Transform::ToDomain::setSimulationOptions(ISimulation* simulation,
 void GUI::Transform::ToDomain::setTransformationInfo(IParticle* result,
                                                      const ItemWithParticles& item)
 {
-    setPositionInfo(result, item);
-    setRotationInfo(result, item);
-}
-
-void GUI::Transform::ToDomain::setPositionInfo(IParticle* result, const ItemWithParticles& item)
-{
-    R3 pos = item.position();
-    result->setPosition(pos.x(), pos.y(), pos.z());
-}
-
-void GUI::Transform::ToDomain::setRotationInfo(IParticle* result, const ItemWithParticles& item)
-{
-    TransformationItem* trans_item = item.transformationItem();
-    if (trans_item) {
-        RotationItem* rot_item = trans_item->rotationItem();
-        auto rotation = rot_item->createRotation();
-        if (rotation)
-            result->setRotation(*rotation);
+    result->setPosition(item.position());
+    const Transform3D r = item.rotation();
+    if (!r.isIdentity()) {
+        std::unique_ptr<IRotation> rotation(IRotation::createRotation(r));
+        result->setRotation(*rotation);
     }
 }
 
diff --git a/GUI/Models/TransformToDomain.h b/GUI/Models/TransformToDomain.h
index d5ac106ecd7..9c33e11ff0a 100644
--- a/GUI/Models/TransformToDomain.h
+++ b/GUI/Models/TransformToDomain.h
@@ -57,8 +57,6 @@ void setBeamDistribution(ParameterDistribution::WhichParameter which,
 
 void setSimulationOptions(ISimulation* simulation, const SessionItem& item);
 void setTransformationInfo(IParticle* result, const ItemWithParticles& item);
-void setPositionInfo(IParticle* result, const ItemWithParticles& item);
-void setRotationInfo(IParticle* result, const ItemWithParticles& item);
 
 } // namespace GUI::Transform::ToDomain
 
-- 
GitLab