From 1e7c133e96d1bbc690290019bdb8d7928fe8ee50 Mon Sep 17 00:00:00 2001
From: "Joachim Wuttke (h)" <j.wuttke@fz-juelich.de>
Date: Wed, 23 Sep 2020 11:12:20 +0200
Subject: [PATCH] Core FF Prism now in pimpl idiom

---
 Core/HardParticle/IFormFactorPolyhedron.h |  4 +-
 Core/HardParticle/IFormFactorPrism.cpp    | 84 ++++++++++++++---------
 Core/HardParticle/IFormFactorPrism.h      | 21 +++++-
 3 files changed, 74 insertions(+), 35 deletions(-)

diff --git a/Core/HardParticle/IFormFactorPolyhedron.h b/Core/HardParticle/IFormFactorPolyhedron.h
index 525e188d52a..e21c3675509 100644
--- a/Core/HardParticle/IFormFactorPolyhedron.h
+++ b/Core/HardParticle/IFormFactorPolyhedron.h
@@ -22,9 +22,11 @@
 
 //! A polyhedron, implementation class for use in IFormFactorPolyhedron
 
-class Polyhedron
+class BA_CORE_API_ Polyhedron
 {
 public:
+    Polyhedron() = delete;
+    Polyhedron(const Polyhedron&) = delete;
     Polyhedron(const PolyhedralTopology& topology, double z_bottom,
                const std::vector<kvector_t>& vertices);
     void assert_platonic() const;
diff --git a/Core/HardParticle/IFormFactorPrism.cpp b/Core/HardParticle/IFormFactorPrism.cpp
index 3e3dfff7d05..0bc572d69a2 100644
--- a/Core/HardParticle/IFormFactorPrism.cpp
+++ b/Core/HardParticle/IFormFactorPrism.cpp
@@ -27,54 +27,38 @@ namespace
 const double eps = 2e-16;
 } // namespace
 
-IFormFactorPrism::IFormFactorPrism(const NodeMeta& meta, const std::vector<double>& PValues)
-    : IFormFactorBorn(meta, PValues)
-{
-}
-
-void IFormFactorPrism::setPrism(bool symmetry_Ci, const std::vector<kvector_t>& vertices)
+Prism::Prism(bool symmetry_Ci, double height, const std::vector<kvector_t>& vertices)
 {
+    m_height = height;
     m_vertices.clear();
     for (const kvector_t& vertex : vertices) {
         m_vertices.push_back(vertex);
-        m_vertices.push_back(vertex + kvector_t{0, 0, height()});
+        m_vertices.push_back(vertex + kvector_t{0, 0, m_height});
     }
 
     try {
         m_base = std::unique_ptr<PolyhedralFace>(new PolyhedralFace(vertices, symmetry_Ci));
     } catch (std::invalid_argument& e) {
-        throw std::invalid_argument("Invalid parameterization of " + getName() + ": " + e.what());
+        throw std::invalid_argument(std::string("Invalid parameterization of Prism: ")
+                                    + e.what());
     } catch (std::logic_error& e) {
-        throw std::logic_error("Bug in " + getName() + ": " + e.what()
+        throw std::logic_error(std::string("Bug in Prism: ") + e.what()
                                + " [please report to the maintainers]");
     } catch (std::exception& e) {
-        throw std::runtime_error("Unexpected exception in " + getName() + ": " + e.what()
+        throw std::runtime_error(std::string("Unexpected exception in Prism: ") + e.what()
                                  + " [please report to the maintainers]");
     }
 }
 
-double IFormFactorPrism::bottomZ(const IRotation& rotation) const
-{
-    return BottomZ(m_vertices, rotation);
-}
-
-double IFormFactorPrism::topZ(const IRotation& rotation) const
-{
-    return TopZ(m_vertices, rotation);
-}
+double Prism::area() const { return m_base->area(); }
 
-//! Returns the volume of this prism.
-double IFormFactorPrism::volume() const
+const std::vector<kvector_t>& Prism::vertices()
 {
-    return height() * m_base->area();
+    return m_vertices;
 }
 
-double IFormFactorPrism::getHeight() const { return height(); }
-double IFormFactorPrism::radialExtension() const { return std::sqrt(m_base->area()); }
 
-//! Returns the form factor F(q) of this polyhedron, respecting the offset height/2.
-
-complex_t IFormFactorPrism::evaluate_for_q(cvector_t q) const
+complex_t Prism::evaluate_for_q(const cvector_t& q) const
 {
     try {
 #ifdef POLYHEDRAL_DIAGNOSTIC
@@ -82,16 +66,54 @@ complex_t IFormFactorPrism::evaluate_for_q(cvector_t q) const
         diagnosis.nExpandedFaces = 0;
 #endif
         cvector_t qxy(q.x(), q.y(), 0.);
-        return height() * exp_I(height() / 2 * q.z()) * MathFunctions::sinc(height() / 2 * q.z())
+        return m_height * exp_I(m_height / 2 * q.z()) * MathFunctions::sinc(m_height / 2 * q.z())
                * m_base->ff_2D(qxy);
     } catch (std::logic_error& e) {
-        throw std::logic_error("Bug in " + getName() + ": " + e.what()
+        throw std::logic_error(std::string("Bug in Prism: ") + e.what()
                                + " [please report to the maintainers]");
     } catch (std::runtime_error& e) {
-        throw std::runtime_error("Numeric computation failed in " + getName() + ": " + e.what()
+        throw std::runtime_error(std::string("Numeric computation failed in Prism: ") + e.what()
                                  + " [please report to the maintainers]");
     } catch (std::exception& e) {
-        throw std::runtime_error("Unexpected exception in " + getName() + ": " + e.what()
+        throw std::runtime_error(std::string("Unexpected exception in Prism: ") + e.what()
                                  + " [please report to the maintainers]");
     }
 }
+
+
+
+IFormFactorPrism::IFormFactorPrism(const NodeMeta& meta, const std::vector<double>& PValues)
+    : IFormFactorBorn(meta, PValues)
+{
+}
+
+void IFormFactorPrism::setPrism(bool symmetry_Ci, const std::vector<kvector_t>& vertices)
+{
+    pimpl = std::make_unique<Prism>(symmetry_Ci, height(), vertices);
+}
+
+double IFormFactorPrism::bottomZ(const IRotation& rotation) const
+{
+    return BottomZ(pimpl->vertices(), rotation);
+}
+
+double IFormFactorPrism::topZ(const IRotation& rotation) const
+{
+    return TopZ(pimpl->vertices(), rotation);
+}
+
+//! Returns the volume of this prism.
+double IFormFactorPrism::volume() const
+{
+    return height() * pimpl->area();
+}
+
+double IFormFactorPrism::getHeight() const { return height(); }
+double IFormFactorPrism::radialExtension() const { return std::sqrt(pimpl->area()); }
+
+//! Returns the form factor F(q) of this polyhedron, respecting the offset height/2.
+
+complex_t IFormFactorPrism::evaluate_for_q(cvector_t q) const
+{
+    return pimpl->evaluate_for_q(q);
+}
diff --git a/Core/HardParticle/IFormFactorPrism.h b/Core/HardParticle/IFormFactorPrism.h
index dbad76ea93d..c1aeffa6279 100644
--- a/Core/HardParticle/IFormFactorPrism.h
+++ b/Core/HardParticle/IFormFactorPrism.h
@@ -20,6 +20,22 @@
 #include "Core/Scattering/IFormFactorBorn.h"
 #include <memory>
 
+class BA_CORE_API_ Prism
+{
+public:
+    Prism() = delete;
+    Prism(const Prism&) = delete;
+    Prism(bool symmetry_Ci, double height, const std::vector<kvector_t>& vertices);
+    double area() const;
+    const std::vector<kvector_t>& vertices(); //! needed for topZ, bottomZ computation
+    complex_t evaluate_for_q(const cvector_t& q) const;
+    // complex_t evaluate_centered(const cvector_t& q) const;
+private:
+    std::unique_ptr<PolyhedralFace> m_base;
+    double m_height;
+    std::vector<kvector_t> m_vertices; //! for topZ, bottomZ computation only
+};
+
 //! A prism with a polygonal base, for form factor computation.
 
 class BA_CORE_API_ IFormFactorPrism : public IFormFactorBorn
@@ -38,11 +54,10 @@ public:
 
 protected:
     void setPrism(bool symmetry_Ci, const std::vector<kvector_t>& vertices);
+    virtual double height() const = 0; // TODO mv parameter m_height back from children to this
 
 private:
-    virtual double height() const = 0;
-    std::unique_ptr<PolyhedralFace> m_base;
-    std::vector<kvector_t> m_vertices; //! for topZ, bottomZ computation only
+    std::unique_ptr<Prism> pimpl;
 };
 
 #endif // BORNAGAIN_CORE_HARDPARTICLE_IFORMFACTORPRISM_H
-- 
GitLab