From fc65f4ffc41075d59916afbe4ebcf4677f9b29c1 Mon Sep 17 00:00:00 2001
From: Mikhail Svechnikov <m.svechnikov@fz-juelich.de>
Date: Fri, 2 Aug 2024 13:16:31 +0200
Subject: [PATCH] serialize model

---
 GUI/Model/Sample/RoughnessItems.cpp     | 27 ++++++++++++++++++++-----
 GUI/Model/Sample/RoughnessItems.h       | 10 ++++-----
 GUI/Model/Sample/RoughnessModelItems.h  | 25 +++++++++++++++++++----
 GUI/Model/ToCore/SampleToCore.cpp       |  2 +-
 GUI/View/Realspace/RealspaceBuilder.cpp |  6 +++---
 GUI/View/Sample/PolyForm.cpp            |  2 +-
 GUI/View/Sample/PolyForm.h              |  2 +-
 7 files changed, 54 insertions(+), 20 deletions(-)

diff --git a/GUI/Model/Sample/RoughnessItems.cpp b/GUI/Model/Sample/RoughnessItems.cpp
index 6fa1a071c00..c08a4929531 100644
--- a/GUI/Model/Sample/RoughnessItems.cpp
+++ b/GUI/Model/Sample/RoughnessItems.cpp
@@ -18,6 +18,8 @@
 namespace {
 namespace Tag {
 
+const QString BaseData("BaseData");
+const QString HeightDistributionModel("HeightDistributionModel");
 const QString Sigma("Sigma");
 const QString Hurst("Hurst");
 const QString LateralCorrelationLength("LateralCorrelationLength");
@@ -25,17 +27,29 @@ const QString LateralCorrelationLength("LateralCorrelationLength");
 } // namespace Tag
 } // namespace
 
-void RoughnessItem::writeTo(QXmlStreamWriter* w) const {}
+void RoughnessItem::writeTo(QXmlStreamWriter* w) const
+{
+    XML::writeTaggedElement(w, Tag::HeightDistributionModel, m_roughness_model);
+}
+
+void RoughnessItem::readFrom(QXmlStreamReader* r)
+{
+    while (r->readNextStartElement()) {
+        QString tag = r->name().toString();
 
-void RoughnessItem::readFrom(QXmlStreamReader* r) {}
+        if (tag == Tag::HeightDistributionModel)
+            XML::readTaggedElement(r, tag, m_roughness_model);
+        else
+            r->skipCurrentElement();
+    }
+}
 
 RoughnessItem::RoughnessItem()
 {
-    DefaultRoughness default_roughness_type;
     m_roughness_model.simpleInit("Interlayer profile",
                                  "Laterally averaged profile of the interlayer transition (or "
                                  "roughness height distribution)",
-                                 RoughnessModelCatalog::type(&default_roughness_type));
+                                 RoughnessModelCatalog::Type::Tanh);
 }
 
 //------------------------------------------------------------------------------------------------
@@ -54,6 +68,7 @@ BasicRoughnessItem::BasicRoughnessItem(double sigma, double hurst, double corr_l
 
 void BasicRoughnessItem::writeTo(QXmlStreamWriter* w) const
 {
+    XML::writeBaseElement<RoughnessItem>(w, Tag::BaseData, this);
     m_sigma.writeTo2(w, Tag::Sigma);
     m_hurst.writeTo2(w, Tag::Hurst);
     m_lateral_correlation_length.writeTo2(w, Tag::LateralCorrelationLength);
@@ -64,7 +79,9 @@ void BasicRoughnessItem::readFrom(QXmlStreamReader* r)
     while (r->readNextStartElement()) {
         QString tag = r->name().toString();
 
-        if (tag == Tag::Sigma)
+        if (tag == Tag::BaseData)
+            XML::readBaseElement<RoughnessItem>(r, tag, this);
+        else if (tag == Tag::Sigma)
             m_sigma.readFrom2(r, tag);
         else if (tag == Tag::Hurst)
             m_hurst.readFrom2(r, tag);
diff --git a/GUI/Model/Sample/RoughnessItems.h b/GUI/Model/Sample/RoughnessItems.h
index 99464546f03..217642ef78e 100644
--- a/GUI/Model/Sample/RoughnessItems.h
+++ b/GUI/Model/Sample/RoughnessItems.h
@@ -18,7 +18,7 @@
 #include "GUI/Model/Descriptor/DoubleProperty.h"
 #include "GUI/Model/Descriptor/PolyPtr.h"
 #include "GUI/Model/Sample/RoughnessCatalog.h"
-#include "Sample/Interface/RoughnessModels.h"
+#include "GUI/Model/Sample/RoughnessModelItems.h"
 
 class RoughnessItem {
 public:
@@ -28,16 +28,16 @@ public:
     virtual void readFrom(QXmlStreamReader* r);
     virtual DoubleProperties roughnessProperties() = 0;
 
-    PolyPtr<RoughnessModel, RoughnessModelCatalog>& roughnessModelSelection()
+    PolyPtr<RoughnessModelItem, RoughnessModelCatalog>& roughnessModelSelection()
     {
         return m_roughness_model;
     }
-    RoughnessModel* certainRoughnessModel() const { return m_roughness_model.certainItem(); }
-    void setRoughnessModelType(RoughnessModel* p) { m_roughness_model.setCertainItem(p); }
+    RoughnessModelItem* certainRoughnessModel() const { return m_roughness_model.certainItem(); }
+    void setRoughnessModelType(RoughnessModelItem* p) { m_roughness_model.setCertainItem(p); }
 
 protected:
     RoughnessItem();
-    PolyPtr<RoughnessModel, RoughnessModelCatalog> m_roughness_model;
+    PolyPtr<RoughnessModelItem, RoughnessModelCatalog> m_roughness_model;
 };
 
 class BasicRoughnessItem : public RoughnessItem {
diff --git a/GUI/Model/Sample/RoughnessModelItems.h b/GUI/Model/Sample/RoughnessModelItems.h
index db93879eadc..dd9c5673006 100644
--- a/GUI/Model/Sample/RoughnessModelItems.h
+++ b/GUI/Model/Sample/RoughnessModelItems.h
@@ -16,17 +16,34 @@
 #define BORNAGAIN_GUI_MODEL_SAMPLE_ROUGHNESSMODELITEMS_H
 
 #include "Sample/Interface/RoughnessModels.h"
+#include <memory>
 
 class RoughnessModelItem {
 public:
     virtual ~RoughnessModelItem() = default;
 
-    virtual void writeTo(QXmlStreamWriter*) const = {};
-    virtual void readFrom(QXmlStreamReader*) = {};
+    virtual void writeTo(QXmlStreamWriter*) const {}
+    virtual void readFrom(QXmlStreamReader*) {}
+
+    virtual std::unique_ptr<RoughnessModel> createModel() const = 0;
+
+protected:
+    RoughnessModelItem() = default;
 };
 
-class ErfRoughnessItem : public RoughnessModelItem {};
+class ErfRoughnessItem : public RoughnessModelItem {
+public:
+    ErfRoughnessItem() = default;
+    std::unique_ptr<RoughnessModel> createModel() const { return std::make_unique<ErfRoughness>(); }
+};
 
-class TanhRoughnessItem : public RoughnessModelItem {};
+class TanhRoughnessItem : public RoughnessModelItem {
+public:
+    TanhRoughnessItem() = default;
+    std::unique_ptr<RoughnessModel> createModel() const
+    {
+        return std::make_unique<TanhRoughness>();
+    }
+};
 
 #endif // BORNAGAIN_GUI_MODEL_SAMPLE_ROUGHNESSMODELITEMS_H
diff --git a/GUI/Model/ToCore/SampleToCore.cpp b/GUI/Model/ToCore/SampleToCore.cpp
index b0c080881f2..c55cade30dc 100644
--- a/GUI/Model/ToCore/SampleToCore.cpp
+++ b/GUI/Model/ToCore/SampleToCore.cpp
@@ -121,7 +121,7 @@ std::unique_ptr<MultiLayer> GUI::ToCore::itemToSample(const SampleItem& sampleIt
                      layerItem->roughnessSelection().certainItem())) {
             LayerRoughness roughness(t->sigma().dVal(), t->hurst().dVal(),
                                      t->lateralCorrelationLength().dVal(),
-                                     t->certainRoughnessModel());
+                                     t->certainRoughnessModel()->createModel().release());
             sample->addLayerWithTopRoughness(*layer, roughness);
         } else
             sample->addLayer(*layer);
diff --git a/GUI/View/Realspace/RealspaceBuilder.cpp b/GUI/View/Realspace/RealspaceBuilder.cpp
index 25eda5e727f..995bae13efd 100644
--- a/GUI/View/Realspace/RealspaceBuilder.cpp
+++ b/GUI/View/Realspace/RealspaceBuilder.cpp
@@ -96,9 +96,9 @@ std::unique_ptr<const double2d_t> layerRoughnessMap(const LayerItem& layerItem,
     std::unique_ptr<const double2d_t> result;
 
     if (const auto* br = dynamic_cast<const BasicRoughnessItem*>(layerItem.certainRoughness())) {
-        auto roughness =
-            LayerRoughness(br->sigma().dVal(), br->hurst().dVal(),
-                           br->lateralCorrelationLength().dVal(), br->certainRoughnessModel());
+        auto roughness = LayerRoughness(br->sigma().dVal(), br->hurst().dVal(),
+                                        br->lateralCorrelationLength().dVal(),
+                                        br->certainRoughnessModel()->createModel().release());
         int n = sceneGeometry.numRoughnessPointsAlongAxis;
         double L = 2 * sceneGeometry.layerSize;
         auto rmap = RoughnessMap(n, n, L, L, &roughness, seed); // seed < 0 ==> random every time
diff --git a/GUI/View/Sample/PolyForm.cpp b/GUI/View/Sample/PolyForm.cpp
index 7d68a1d8ac0..1ec46bab2e5 100644
--- a/GUI/View/Sample/PolyForm.cpp
+++ b/GUI/View/Sample/PolyForm.cpp
@@ -53,7 +53,7 @@ DoubleProperties PolyForm::doublePropertiesOfItem(FormfactorItem* item)
     return item->geometryProperties();
 }
 
-DoubleProperties PolyForm::doublePropertiesOfItem(RoughnessModel*)
+DoubleProperties PolyForm::doublePropertiesOfItem(RoughnessModelItem*)
 {
     return {};
 }
diff --git a/GUI/View/Sample/PolyForm.h b/GUI/View/Sample/PolyForm.h
index a8cfeb50435..31174835872 100644
--- a/GUI/View/Sample/PolyForm.h
+++ b/GUI/View/Sample/PolyForm.h
@@ -52,7 +52,7 @@ public:
     virtual void createContent();
 
 private:
-    static DoubleProperties doublePropertiesOfItem(class RoughnessModel* item);
+    static DoubleProperties doublePropertiesOfItem(class RoughnessModelItem* item);
     static DoubleProperties doublePropertiesOfItem(class FormfactorItem* item);
     static DoubleProperties doublePropertiesOfItem(class Profile1DItem* item);
     static DoubleProperties doublePropertiesOfItem(class Profile2DItem* item);
-- 
GitLab