From 79074f8dc9101d96f8bcb5157dbba1aa47731ef8 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Mon, 18 May 2020 17:26:57 +0200
Subject: [PATCH] Full GUI support for all three subtypes of Ripple1

---
 Doc/dev-notes/modify-formfactor.md            |  4 ++
 GUI/ba3d/ba3d/model/model.cpp                 |  4 ++
 GUI/ba3d/ba3d/model/particles.cpp             | 22 +++++++-
 GUI/ba3d/ba3d/model/particles.h               | 14 ++++++
 GUI/coregui/Models/FormFactorItems.cpp        | 46 +++++++++++++++++
 GUI/coregui/Models/FormFactorItems.h          | 20 ++++++++
 GUI/coregui/Models/GUIDomainSampleVisitor.cpp | 20 ++++++++
 GUI/coregui/Models/GUIDomainSampleVisitor.h   |  2 +
 GUI/coregui/Models/ItemCatalogue.cpp          |  2 +
 .../RealSpaceMesoCrystalUtils.cpp             | 12 +++++
 .../Views/RealSpaceWidgets/TransformTo3D.cpp  | 10 ++++
 GUI/coregui/Views/widgetbox/widgetbox.xml     | 50 ++++++++++++++-----
 12 files changed, 192 insertions(+), 14 deletions(-)

diff --git a/Doc/dev-notes/modify-formfactor.md b/Doc/dev-notes/modify-formfactor.md
index 83339398f70..7b8b7636b66 100644
--- a/Doc/dev-notes/modify-formfactor.md
+++ b/Doc/dev-notes/modify-formfactor.md
@@ -31,9 +31,13 @@ If the form factor is supported by the GUI, then also:
 * GUI/coregui/Models/GUIDomainSampleVisitor.h and .cpp
 * GUI/coregui/Models/ItemCatalogue.cpp
 * GUI/coregui/Models/item_constants.h
+* GUI/coregui/Views/RealSpaceWidgets/RealSpaceMesoCrystalUtils.cpp
+* GUI/coregui/Views/widgetbox/widgetbox.qrc
+* GUI/coregui/Views/widgetbox/widgetbox.xml
 
 If there is a real-space view:
 * GUI/coregui/Models/item_constants.h
+* GUI/ba3d/ba3d/model/model.cpp
 * GUI/ba3d/ba3d/model/particles.h and .cpp
 * GUI/coregui/Views/RealSpaceWidgets/RealSpaceMesoCrystalUtils.cpp
 * GUI/coregui/Views/RealSpaceWidgets/TransformTo3D.cpp
diff --git a/GUI/ba3d/ba3d/model/model.cpp b/GUI/ba3d/ba3d/model/model.cpp
index d0872ad4965..d32e8320b9c 100644
--- a/GUI/ba3d/ba3d/model/model.cpp
+++ b/GUI/ba3d/ba3d/model/model.cpp
@@ -96,6 +96,10 @@ Particles::Particle* Model::newParticle(Particles::EShape k, float R)
         return new Dot();
     case EShape::Ripple1Box:
         return new Ripple1Box(D, D, D); // TODO ripples should be elongated
+    case EShape::Ripple1Gauss:
+        return new Ripple1Gauss(D, D, D); // TODO ripples should be elongated
+    case EShape::Ripple1Lorentz:
+        return new Ripple1Lorentz(D, D, D); // TODO ripples should be elongated
     case EShape::Ripple2:
         return new Ripple2(D, D, D, 0.3f);
     case EShape::AnisoPyramid:
diff --git a/GUI/ba3d/ba3d/model/particles.cpp b/GUI/ba3d/ba3d/model/particles.cpp
index 0ef9eaade63..181d23f7c8c 100644
--- a/GUI/ba3d/ba3d/model/particles.cpp
+++ b/GUI/ba3d/ba3d/model/particles.cpp
@@ -43,7 +43,9 @@ QString const& name(EShape k)
         "Box",
         "HemiEllipsoid",
         "Dot",
-        "Ripple1",
+        "Ripple1Box",
+        "Ripple1Gauss",
+        "Ripple1Lorentz",
         "Ripple2",
         "AnisoPyramid",
     };
@@ -248,6 +250,24 @@ Ripple1Box::Ripple1Box(float L, float W, float H) : Particle(Key(BaseShape::Ripp
     set();
 }
 
+Ripple1Gauss::Ripple1Gauss(float L, float W, float H) : Particle(Key(BaseShape::Ripple, 0, 0))
+{
+    isNull = (L < 0 || W < 0 || H < 0) || (L <= 0 && W <= 0 && H <= 0);
+    turn = Vector3D(0, 0, 0);
+    scale = Vector3D(L, W, H);
+    offset = Vector3D(0, 0, 0);
+    set();
+}
+
+Ripple1Lorentz::Ripple1Lorentz(float L, float W, float H) : Particle(Key(BaseShape::Ripple, 0, 0))
+{
+    isNull = (L < 0 || W < 0 || H < 0) || (L <= 0 && W <= 0 && H <= 0);
+    turn = Vector3D(0, 0, 0);
+    scale = Vector3D(L, W, H);
+    offset = Vector3D(0, 0, 0);
+    set();
+}
+
 Ripple2::Ripple2(float L, float W, float H, float asymmetry)
     : Particle(Key(BaseShape::Ripple, 3, asymmetry / W))
 {
diff --git a/GUI/ba3d/ba3d/model/particles.h b/GUI/ba3d/ba3d/model/particles.h
index 1c6bc152b33..117aeff6ce9 100644
--- a/GUI/ba3d/ba3d/model/particles.h
+++ b/GUI/ba3d/ba3d/model/particles.h
@@ -44,6 +44,8 @@ enum class EShape {
     HemiEllipsoid,
     Dot,
     Ripple1Box,
+    Ripple1Gauss,
+    Ripple1Lorentz,
     Ripple2,
     AnisoPyramid,
 };
@@ -198,6 +200,18 @@ public:
     Ripple1Box(float L, float W, float H);
 };
 
+class Ripple1Gauss : public Particle
+{
+public:
+    Ripple1Gauss(float L, float W, float H);
+};
+
+class Ripple1Lorentz : public Particle
+{
+public:
+    Ripple1Lorentz(float L, float W, float H);
+};
+
 class Ripple2 : public Particle
 {
 public:
diff --git a/GUI/coregui/Models/FormFactorItems.cpp b/GUI/coregui/Models/FormFactorItems.cpp
index 9e7985c9266..f1f2be74e98 100644
--- a/GUI/coregui/Models/FormFactorItems.cpp
+++ b/GUI/coregui/Models/FormFactorItems.cpp
@@ -380,6 +380,52 @@ std::unique_ptr<IFormFactor> Ripple1BoxItem::createFormFactor() const
 
 /* ------------------------------------------------ */
 
+const QString Ripple1GaussItem::P_LENGTH = QString::fromStdString(BornAgain::Length);
+const QString Ripple1GaussItem::P_WIDTH = QString::fromStdString(BornAgain::Width);
+const QString Ripple1GaussItem::P_HEIGHT = QString::fromStdString(BornAgain::Height);
+
+Ripple1GaussItem::Ripple1GaussItem() : FormFactorItem(Constants::Ripple1GaussType)
+{
+    setToolTip(QStringLiteral("Particle with a cosine profile and a rectangular base"));
+    addProperty(P_LENGTH, 27.0)
+        ->setToolTip(QStringLiteral("Length of the rectangular base in nanometers"));
+    addProperty(P_WIDTH, 20.0)
+        ->setToolTip(QStringLiteral("Width of the rectangular base in nanometers"));
+    addProperty(P_HEIGHT, 14.0)->setToolTip(QStringLiteral("Height of the ripple in nanometers"));
+}
+
+std::unique_ptr<IFormFactor> Ripple1GaussItem::createFormFactor() const
+{
+    return std::make_unique<FormFactorRipple1Gauss>(getItemValue(P_LENGTH).toDouble(),
+                                                  getItemValue(P_WIDTH).toDouble(),
+                                                  getItemValue(P_HEIGHT).toDouble());
+}
+
+/* ------------------------------------------------ */
+
+const QString Ripple1LorentzItem::P_LENGTH = QString::fromStdString(BornAgain::Length);
+const QString Ripple1LorentzItem::P_WIDTH = QString::fromStdString(BornAgain::Width);
+const QString Ripple1LorentzItem::P_HEIGHT = QString::fromStdString(BornAgain::Height);
+
+Ripple1LorentzItem::Ripple1LorentzItem() : FormFactorItem(Constants::Ripple1LorentzType)
+{
+    setToolTip(QStringLiteral("Particle with a cosine profile and a rectangular base"));
+    addProperty(P_LENGTH, 27.0)
+        ->setToolTip(QStringLiteral("Length of the rectangular base in nanometers"));
+    addProperty(P_WIDTH, 20.0)
+        ->setToolTip(QStringLiteral("Width of the rectangular base in nanometers"));
+    addProperty(P_HEIGHT, 14.0)->setToolTip(QStringLiteral("Height of the ripple in nanometers"));
+}
+
+std::unique_ptr<IFormFactor> Ripple1LorentzItem::createFormFactor() const
+{
+    return std::make_unique<FormFactorRipple1Lorentz>(getItemValue(P_LENGTH).toDouble(),
+                                                  getItemValue(P_WIDTH).toDouble(),
+                                                  getItemValue(P_HEIGHT).toDouble());
+}
+
+/* ------------------------------------------------ */
+
 const QString Ripple2Item::P_LENGTH = QString::fromStdString(BornAgain::Length);
 const QString Ripple2Item::P_WIDTH = QString::fromStdString(BornAgain::Width);
 const QString Ripple2Item::P_HEIGHT = QString::fromStdString(BornAgain::Height);
diff --git a/GUI/coregui/Models/FormFactorItems.h b/GUI/coregui/Models/FormFactorItems.h
index f5aeb342872..4bd0c2dfab5 100644
--- a/GUI/coregui/Models/FormFactorItems.h
+++ b/GUI/coregui/Models/FormFactorItems.h
@@ -186,6 +186,26 @@ public:
     std::unique_ptr<IFormFactor> createFormFactor() const;
 };
 
+class BA_CORE_API_ Ripple1GaussItem : public FormFactorItem
+{
+public:
+    static const QString P_LENGTH;
+    static const QString P_WIDTH;
+    static const QString P_HEIGHT;
+    Ripple1GaussItem();
+    std::unique_ptr<IFormFactor> createFormFactor() const;
+};
+
+class BA_CORE_API_ Ripple1LorentzItem : public FormFactorItem
+{
+public:
+    static const QString P_LENGTH;
+    static const QString P_WIDTH;
+    static const QString P_HEIGHT;
+    Ripple1LorentzItem();
+    std::unique_ptr<IFormFactor> createFormFactor() const;
+};
+
 class BA_CORE_API_ Ripple2Item : public FormFactorItem
 {
 public:
diff --git a/GUI/coregui/Models/GUIDomainSampleVisitor.cpp b/GUI/coregui/Models/GUIDomainSampleVisitor.cpp
index 8f2819a114d..82021a684ed 100644
--- a/GUI/coregui/Models/GUIDomainSampleVisitor.cpp
+++ b/GUI/coregui/Models/GUIDomainSampleVisitor.cpp
@@ -342,6 +342,26 @@ void GUIDomainSampleVisitor::visit(const FormFactorRipple1Box* p_sample)
     m_levelToParentItem[depth()] = p_particle_item;
 }
 
+void GUIDomainSampleVisitor::visit(const FormFactorRipple1Gauss* p_sample)
+{
+    SessionItem* p_particle_item = m_levelToParentItem[depth() - 1];
+    SessionItem* p_ff_item = AddFormFactorItem(p_particle_item, Constants::Ripple1GaussType);
+    p_ff_item->setItemValue(Ripple1GaussItem::P_LENGTH, p_sample->getLength());
+    p_ff_item->setItemValue(Ripple1GaussItem::P_WIDTH, p_sample->getWidth());
+    p_ff_item->setItemValue(Ripple1GaussItem::P_HEIGHT, p_sample->getHeight());
+    m_levelToParentItem[depth()] = p_particle_item;
+}
+
+void GUIDomainSampleVisitor::visit(const FormFactorRipple1Lorentz* p_sample)
+{
+    SessionItem* p_particle_item = m_levelToParentItem[depth() - 1];
+    SessionItem* p_ff_item = AddFormFactorItem(p_particle_item, Constants::Ripple1LorentzType);
+    p_ff_item->setItemValue(Ripple1LorentzItem::P_LENGTH, p_sample->getLength());
+    p_ff_item->setItemValue(Ripple1LorentzItem::P_WIDTH, p_sample->getWidth());
+    p_ff_item->setItemValue(Ripple1LorentzItem::P_HEIGHT, p_sample->getHeight());
+    m_levelToParentItem[depth()] = p_particle_item;
+}
+
 void GUIDomainSampleVisitor::visit(const FormFactorRipple2* p_sample)
 {
     SessionItem* p_particle_item = m_levelToParentItem[depth() - 1];
diff --git a/GUI/coregui/Models/GUIDomainSampleVisitor.h b/GUI/coregui/Models/GUIDomainSampleVisitor.h
index 3633fbd5b9d..6da972f6c0d 100644
--- a/GUI/coregui/Models/GUIDomainSampleVisitor.h
+++ b/GUI/coregui/Models/GUIDomainSampleVisitor.h
@@ -70,6 +70,8 @@ public:
     void visit(const FormFactorPrism6*);
     void visit(const FormFactorPyramid*);
     void visit(const FormFactorRipple1Box*);
+    void visit(const FormFactorRipple1Gauss*);
+    void visit(const FormFactorRipple1Lorentz*);
     void visit(const FormFactorRipple2*);
     void visit(const FormFactorTetrahedron*);
     void visit(const FormFactorDot*);
diff --git a/GUI/coregui/Models/ItemCatalogue.cpp b/GUI/coregui/Models/ItemCatalogue.cpp
index 2e781e94fc7..95c044249e6 100644
--- a/GUI/coregui/Models/ItemCatalogue.cpp
+++ b/GUI/coregui/Models/ItemCatalogue.cpp
@@ -121,6 +121,8 @@ ItemCatalogue::ItemCatalogue()
     add(Constants::Prism6Type, create_new<Prism6Item>);
     add(Constants::PyramidType, create_new<PyramidItem>);
     add(Constants::Ripple1BoxType, create_new<Ripple1BoxItem>);
+    add(Constants::Ripple1GaussType, create_new<Ripple1GaussItem>);
+    add(Constants::Ripple1LorentzType, create_new<Ripple1LorentzItem>);
     add(Constants::Ripple2Type, create_new<Ripple2Item>);
     add(Constants::TetrahedronType, create_new<TetrahedronItem>);
     add(Constants::TruncatedCubeType, create_new<TruncatedCubeItem>);
diff --git a/GUI/coregui/Views/RealSpaceWidgets/RealSpaceMesoCrystalUtils.cpp b/GUI/coregui/Views/RealSpaceWidgets/RealSpaceMesoCrystalUtils.cpp
index 7d2db220700..7c09eabc0c3 100644
--- a/GUI/coregui/Views/RealSpaceWidgets/RealSpaceMesoCrystalUtils.cpp
+++ b/GUI/coregui/Views/RealSpaceWidgets/RealSpaceMesoCrystalUtils.cpp
@@ -245,6 +245,18 @@ bool isPositionInsideMesoCrystal(const IFormFactor* outerShape, kvector_t positi
         ostr << "Sorry, outer shape Ripple1Box not yet implemented for Mesocrystal";
         ostr << "\n\nStay tuned!";
         throw Exceptions::ClassInitializationException(ostr.str());
+    } else if (dynamic_cast<const FormFactorRipple1Gauss*>(outerShape)) {
+        // TODO: Implement Ripple1Gauss
+        std::ostringstream ostr;
+        ostr << "Sorry, outer shape Ripple1Gauss not yet implemented for Mesocrystal";
+        ostr << "\n\nStay tuned!";
+        throw Exceptions::ClassInitializationException(ostr.str());
+    } else if (dynamic_cast<const FormFactorRipple1Lorentz*>(outerShape)) {
+        // TODO: Implement Ripple1Lorentz
+        std::ostringstream ostr;
+        ostr << "Sorry, outer shape Ripple1Lorentz not yet implemented for Mesocrystal";
+        ostr << "\n\nStay tuned!";
+        throw Exceptions::ClassInitializationException(ostr.str());
     } else if (dynamic_cast<const FormFactorRipple2*>(outerShape)) {
         // TODO: Implement Ripple2
         std::ostringstream ostr;
diff --git a/GUI/coregui/Views/RealSpaceWidgets/TransformTo3D.cpp b/GUI/coregui/Views/RealSpaceWidgets/TransformTo3D.cpp
index 0871247f22c..30bc6b2602d 100644
--- a/GUI/coregui/Views/RealSpaceWidgets/TransformTo3D.cpp
+++ b/GUI/coregui/Views/RealSpaceWidgets/TransformTo3D.cpp
@@ -183,6 +183,16 @@ TransformTo3D::createParticlefromIFormFactor(const IFormFactor* ff)
         double width = ff_Ripple1Box->getWidth();
         double height = ff_Ripple1Box->getHeight();
         result = std::make_unique<RealSpace::Particles::Ripple1Box>(length, width, height);
+    } else if (auto ff_Ripple1Gauss = dynamic_cast<const FormFactorRipple1Gauss*>(ff)) {
+        double length = ff_Ripple1Gauss->getLength();
+        double width = ff_Ripple1Gauss->getWidth();
+        double height = ff_Ripple1Gauss->getHeight();
+        result = std::make_unique<RealSpace::Particles::Ripple1Gauss>(length, width, height);
+    } else if (auto ff_Ripple1Lorentz = dynamic_cast<const FormFactorRipple1Lorentz*>(ff)) {
+        double length = ff_Ripple1Lorentz->getLength();
+        double width = ff_Ripple1Lorentz->getWidth();
+        double height = ff_Ripple1Lorentz->getHeight();
+        result = std::make_unique<RealSpace::Particles::Ripple1Lorentz>(length, width, height);
     } else if (auto ff_Ripple2 = dynamic_cast<const FormFactorRipple2*>(ff)) {
         double length = ff_Ripple2->getLength();
         double width = ff_Ripple2->getWidth();
diff --git a/GUI/coregui/Views/widgetbox/widgetbox.xml b/GUI/coregui/Views/widgetbox/widgetbox.xml
index 947d48adb6d..4f55ec1947b 100644
--- a/GUI/coregui/Views/widgetbox/widgetbox.xml
+++ b/GUI/coregui/Views/widgetbox/widgetbox.xml
@@ -85,7 +85,7 @@
 
     </category>
 
-    <category name="Particles">
+    <category name="Hard particles">
 
         <categoryentry name="Anisotropic pyramid" icon="images/ff_AnisoPyramid_64x64.png">
             <widget class="FormFactorAnisoPyramid">
@@ -215,54 +215,78 @@
             </widget>
         </categoryentry>
 
-        <categoryentry name="Ripple1" icon="images/ff_Ripple1_64x64.png">
-            <widget class="FormFactorRipple1">
+        <categoryentry name="Tetrahedron" icon="images/ff_Tetrahedron_64x64.png">
+            <widget class="FormFactorTetrahedron">
                 <property name="objectName">
                     <string notr="true">somestring</string>
                 </property>
             </widget>
         </categoryentry>
 
-        <categoryentry name="Ripple2" icon="images/ff_Ripple2_64x64.png">
-            <widget class="FormFactorRipple2">
+        <categoryentry name="Truncated cube" icon="images/ff_TruncatedCube_64x64.png">
+            <widget class="FormFactorTruncatedCube">
                 <property name="objectName">
                     <string notr="true">somestring</string>
                 </property>
             </widget>
         </categoryentry>
 
-        <categoryentry name="Tetrahedron" icon="images/ff_Tetrahedron_64x64.png">
-            <widget class="FormFactorTetrahedron">
+        <categoryentry name="Truncated sphere" icon="images/ff_TruncatedSphere_64x64.png">
+            <widget class="FormFactorTruncatedSphere">
                 <property name="objectName">
                     <string notr="true">somestring</string>
                 </property>
             </widget>
         </categoryentry>
 
-        <categoryentry name="Truncated cube" icon="images/ff_TruncatedCube_64x64.png">
-            <widget class="FormFactorTruncatedCube">
+        <categoryentry name="Truncated spheroid" icon="images/ff_TruncatedSpheroid_64x64.png">
+            <widget class="FormFactorTruncatedSpheroid">
                 <property name="objectName">
                     <string notr="true">somestring</string>
                 </property>
             </widget>
         </categoryentry>
 
-        <categoryentry name="Truncated sphere" icon="images/ff_TruncatedSphere_64x64.png">
-            <widget class="FormFactorTruncatedSphere">
+    </category>
+
+    <category name="Ripples">
+
+        <categoryentry name="Ripple1Box" icon="images/ff_Ripple1_64x64.png">
+            <widget class="FormFactorRipple1Box">
                 <property name="objectName">
                     <string notr="true">somestring</string>
                 </property>
             </widget>
         </categoryentry>
 
-        <categoryentry name="Truncated spheroid" icon="images/ff_TruncatedSpheroid_64x64.png">
-            <widget class="FormFactorTruncatedSpheroid">
+        <categoryentry name="Ripple1Gauss" icon="images/ff_Ripple1_64x64.png">
+            <widget class="FormFactorRipple1Gauss">
+                <property name="objectName">
+                    <string notr="true">somestring</string>
+                </property>
+            </widget>
+        </categoryentry>
+
+        <categoryentry name="Ripple1Lorentz" icon="images/ff_Ripple1_64x64.png">
+            <widget class="FormFactorRipple1Lorentz">
                 <property name="objectName">
                     <string notr="true">somestring</string>
                 </property>
             </widget>
         </categoryentry>
 
+        <categoryentry name="Ripple2" icon="images/ff_Ripple2_64x64.png">
+            <widget class="FormFactorRipple2">
+                <property name="objectName">
+                    <string notr="true">somestring</string>
+                </property>
+            </widget>
+        </categoryentry>
+
+    </category>
+
+    <category name="Soft particles">
+
     </category>
 
     <category name="Transformations">
-- 
GitLab