diff --git a/Core/Aggregate/InterferenceFunction2DLattice.h b/Core/Aggregate/InterferenceFunction2DLattice.h
index ab88392ff75eda3370a00825201d38d40578a0ac..aad2fef4467c6dfc00574556f2e7c900ae06327a 100644
--- a/Core/Aggregate/InterferenceFunction2DLattice.h
+++ b/Core/Aggregate/InterferenceFunction2DLattice.h
@@ -18,7 +18,7 @@
 
 #include "IInterferenceFunction.h"
 #include "FTDecayFunctions.h"
-#include "Lattice2DParameters.h"
+#include "Lattice2D.h"
 
 //! Interference function of 2D lattice.
 //! @ingroup interference
diff --git a/Core/Aggregate/InterferenceFunction2DParaCrystal.cpp b/Core/Aggregate/InterferenceFunction2DParaCrystal.cpp
index 96c004b1f79dd0c89de21b63904180183b595919..24f5056cdbee4618d9dcf0bc6fd75554ee7b2a9b 100644
--- a/Core/Aggregate/InterferenceFunction2DParaCrystal.cpp
+++ b/Core/Aggregate/InterferenceFunction2DParaCrystal.cpp
@@ -28,28 +28,21 @@
 //! @param xi Angle between first basis vector and the x-axis of incoming beam.
 //! @param damping_length Damping length for removing delta function singularity at q=0.
 InterferenceFunction2DParaCrystal::InterferenceFunction2DParaCrystal(
-        double length_1, double length_2, double alpha_lattice, double xi, double damping_length)
+    double length_1, double length_2, double alpha_lattice, double xi, double damping_length)
     : m_integrate_xi(false)
     , m_damping_length(damping_length)
     , m_use_damping_length(true)
 {
     setName(BornAgain::InterferenceFunction2DParaCrystalType);
-
-//    m_lattice_params.m_length_1 = length_1;
-//    m_lattice_params.m_length_2 = length_2;
-//    m_lattice_params.m_angle = alpha_lattice;
-//    m_lattice_params.m_xi = xi;
-
     setLattice(BasicLattice(length_1, length_2, alpha_lattice, xi));
 
     m_domain_sizes[0] = 0.0;
     m_domain_sizes[1] = 0.0;
 
-    if (m_damping_length==0.0)
+    if (m_damping_length == 0.0)
         m_use_damping_length = false;
+
     init_parameters();
-    mP_integrator = make_integrator_real(
-        this, &InterferenceFunction2DParaCrystal::interferenceForXi);
 }
 
 InterferenceFunction2DParaCrystal::~InterferenceFunction2DParaCrystal()
@@ -58,22 +51,14 @@ InterferenceFunction2DParaCrystal::~InterferenceFunction2DParaCrystal()
 
 InterferenceFunction2DParaCrystal* InterferenceFunction2DParaCrystal::clone() const
 {
-//    InterferenceFunction2DParaCrystal* result = new InterferenceFunction2DParaCrystal(
-//        m_lattice_params.m_length_1, m_lattice_params.m_length_2, m_lattice_params.m_angle,
-//        m_lattice_params.m_xi, m_damping_length);
-//    result->setDomainSizes(m_domain_sizes[0], m_domain_sizes[1]);
-//    if (m_pdf1 && m_pdf2)
-//        result->setProbabilityDistributions(*m_pdf1, *m_pdf2);
-//    result->setIntegrationOverXi(m_integrate_xi);
-//    return result;
     return new InterferenceFunction2DParaCrystal(*this);
 }
 
 //! Sets the probability distributions (Fourier transformed) for the two lattice directions.
 //! @param pdf_1: probability distribution in first lattice direction
 //! @param pdf_2: probability distribution in second lattice direction
-void InterferenceFunction2DParaCrystal::setProbabilityDistributions(
-        const IFTDistribution2D& pdf_1, const IFTDistribution2D& pdf_2)
+void InterferenceFunction2DParaCrystal::setProbabilityDistributions(const IFTDistribution2D& pdf_1,
+                                                                    const IFTDistribution2D& pdf_2)
 {
     m_pdf1.reset(pdf_1.clone());
     registerChild(m_pdf1.get());
@@ -84,7 +69,7 @@ void InterferenceFunction2DParaCrystal::setProbabilityDistributions(
 void InterferenceFunction2DParaCrystal::setDampingLength(double damping_length)
 {
     m_damping_length = damping_length;
-    if (m_damping_length==0.0)
+    if (m_damping_length == 0.0)
         m_use_damping_length = false;
 }
 
@@ -92,18 +77,15 @@ double InterferenceFunction2DParaCrystal::evaluate(const kvector_t q) const
 {
     m_qx = q.x();
     m_qy = q.y();
-//    if (!m_integrate_xi)
-//        return interferenceForXi(m_lattice_params.m_xi);
     if (!m_integrate_xi)
         return interferenceForXi(m_lattice->rotationAngle());
-    return mP_integrator->integrate(0.0, M_TWOPI)/M_TWOPI;
+    return mP_integrator->integrate(0.0, M_TWOPI) / M_TWOPI;
 }
 
 double InterferenceFunction2DParaCrystal::getParticleDensity() const
 {
-//    double area = m_lattice_params.getUnitCellArea();
     double area = m_lattice->unitCellArea();
-    return area == 0.0 ? 0.0 : 1.0/area;
+    return area == 0.0 ? 0.0 : 1.0 / area;
 }
 
 std::vector<const INode*> InterferenceFunction2DParaCrystal::getChildren() const
@@ -121,22 +103,18 @@ InterferenceFunction2DParaCrystal::InterferenceFunction2DParaCrystal()
     m_domain_sizes[0] = 0.0;
     m_domain_sizes[1] = 0.0;
 
-    mP_integrator = make_integrator_real(
-        this, &InterferenceFunction2DParaCrystal::interferenceForXi);
     init_parameters();
 }
 
-
 InterferenceFunction2DParaCrystal::InterferenceFunction2DParaCrystal(
-        const InterferenceFunction2DParaCrystal& other)
+    const InterferenceFunction2DParaCrystal& other)
 {
     setName(other.getName());
 
-//    m_lattice_params = other.m_lattice_params;
     m_damping_length = other.m_damping_length;
     m_use_damping_length = other.m_use_damping_length;
 
-    if(other.m_lattice)
+    if (other.m_lattice)
         setLattice(*other.m_lattice);
 
     if (other.m_pdf1 && other.m_pdf2)
@@ -145,9 +123,6 @@ InterferenceFunction2DParaCrystal::InterferenceFunction2DParaCrystal(
     setDomainSizes(other.m_domain_sizes[0], other.m_domain_sizes[1]);
     setIntegrationOverXi(other.m_integrate_xi);
 
-    mP_integrator = make_integrator_real(
-        this, &InterferenceFunction2DParaCrystal::interferenceForXi);
-
     init_parameters();
 }
 
@@ -157,25 +132,28 @@ void InterferenceFunction2DParaCrystal::setLattice(const Lattice2D& lattice)
     registerChild(m_lattice.get());
 }
 
-InterferenceFunction2DParaCrystal* InterferenceFunction2DParaCrystal::createSquare(
-    double peak_distance, double damping_length, double domain_size_1, double domain_size_2)
+InterferenceFunction2DParaCrystal*
+InterferenceFunction2DParaCrystal::createSquare(double peak_distance, double damping_length,
+                                                double domain_size_1, double domain_size_2)
 {
-    InterferenceFunction2DParaCrystal* p_new =
-            new InterferenceFunction2DParaCrystal(peak_distance, peak_distance,
-                    M_PI_2, 0.0, damping_length);
-    p_new->setDomainSizes(domain_size_1, domain_size_2);
-    p_new->setIntegrationOverXi(true);
-    return p_new;
+    auto result = new InterferenceFunction2DParaCrystal;
+    result->setLattice(SquareLattice(peak_distance));
+    result->setDampingLength(damping_length);
+    result->setDomainSizes(domain_size_1, domain_size_2);
+    result->setIntegrationOverXi(true);
+    return result;
 }
 
-InterferenceFunction2DParaCrystal* InterferenceFunction2DParaCrystal::createHexagonal(
-    double peak_distance, double damping_length, double domain_size_1, double domain_size_2)
+InterferenceFunction2DParaCrystal*
+InterferenceFunction2DParaCrystal::createHexagonal(double peak_distance, double damping_length,
+                                                   double domain_size_1, double domain_size_2)
 {
-    auto p_new = new InterferenceFunction2DParaCrystal(
-        peak_distance, peak_distance, M_TWOPI/3.0, 0.0, damping_length);
-    p_new->setDomainSizes(domain_size_1, domain_size_2);
-    p_new->setIntegrationOverXi(true);
-    return p_new;
+    auto result = new InterferenceFunction2DParaCrystal;
+    result->setLattice(HexagonalLattice(peak_distance));
+    result->setDampingLength(damping_length);
+    result->setDomainSizes(domain_size_1, domain_size_2);
+    result->setIntegrationOverXi(true);
+    return result;
 }
 
 //! Sets the sizes of coherence domains.
@@ -187,19 +165,19 @@ void InterferenceFunction2DParaCrystal::setDomainSizes(double size_1, double siz
     m_domain_sizes[1] = size_2;
 }
 
-void InterferenceFunction2DParaCrystal::transformToPrincipalAxes(
-        double qx, double qy, double gamma, double delta, double& q_pa_1, double& q_pa_2) const
+void InterferenceFunction2DParaCrystal::transformToPrincipalAxes(double qx, double qy, double gamma,
+                                                                 double delta, double& q_pa_1,
+                                                                 double& q_pa_2) const
 {
-    q_pa_1 = qx*std::cos(gamma) + qy*std::sin(gamma);
-    q_pa_2 = qx*std::cos(gamma+delta) + qy*std::sin(gamma+delta);
+    q_pa_1 = qx * std::cos(gamma) + qy * std::sin(gamma);
+    q_pa_2 = qx * std::cos(gamma + delta) + qy * std::sin(gamma + delta);
 }
 
 void InterferenceFunction2DParaCrystal::init_parameters()
 {
-//    registerParameter(BornAgain::LatticeLength1, &m_lattice_params.m_length_1).setUnit("nm");
-//    registerParameter(BornAgain::LatticeLength2, &m_lattice_params.m_length_2).setUnit("nm");
-//    registerParameter(BornAgain::LatticeAngle, &m_lattice_params.m_angle).setUnit("rad");
-//    registerParameter(BornAgain::Xi, &m_lattice_params.m_xi).setUnit("rad");
+    mP_integrator
+        = make_integrator_real(this, &InterferenceFunction2DParaCrystal::interferenceForXi);
+
     registerParameter(BornAgain::DampingLength, &m_damping_length).setUnit("nm").setNonnegative();
     registerParameter(BornAgain::DomainSize1, &m_domain_sizes[0]).setUnit("nm").setNonnegative();
     registerParameter(BornAgain::DomainSize2, &m_domain_sizes[1]).setUnit("nm").setNonnegative();
@@ -208,63 +186,64 @@ void InterferenceFunction2DParaCrystal::init_parameters()
 //! Returns interference function for fixed angle xi.
 double InterferenceFunction2DParaCrystal::interferenceForXi(double xi) const
 {
-//    double result = interference1D(m_qx, m_qy, xi, 0)*
-//        interference1D(m_qx, m_qy, xi + m_lattice_params.m_angle, 1);
-    double result = interference1D(m_qx, m_qy, xi, 0)*
-        interference1D(m_qx, m_qy, xi + m_lattice->latticeAngle(), 1);
+    double result = interference1D(m_qx, m_qy, xi, 0)
+                    * interference1D(m_qx, m_qy, xi + m_lattice->latticeAngle(), 1);
     return result;
 }
 
 //! Returns interference function for fixed xi in the dimension determined by the given index.
-double InterferenceFunction2DParaCrystal::interference1D(
-    double qx, double qy, double xi, size_t index) const
+double InterferenceFunction2DParaCrystal::interference1D(double qx, double qy, double xi,
+                                                         size_t index) const
 {
     if (index > 1)
-        throw Exceptions::OutOfBoundsException("InterferenceFunction2DParaCrystal::"
-                "interference1D() -> Error! Index of interference function "
-                "probability must be < 2");
+        throw Exceptions::OutOfBoundsException(
+            "InterferenceFunction2DParaCrystal::"
+            "interference1D() -> Error! Index of interference function "
+            "probability must be < 2");
     if (!m_pdf1 || !m_pdf2)
-        throw Exceptions::NullPointerException("InterferenceFunction2DParaCrystal::"
-                "interference1D() -> Error! Probability distributions for "
-                "interference funtion not properly initialized");
-    double result;
-//    double length = index ? m_lattice_params.m_length_2 : m_lattice_params.m_length_1;
+        throw Exceptions::NullPointerException(
+            "InterferenceFunction2DParaCrystal::"
+            "interference1D() -> Error! Probability distributions for "
+            "interference funtion not properly initialized");
+
+    double result(0.0);
     double length = index ? m_lattice->length2() : m_lattice->length1();
-    int n = (int)std::abs(m_domain_sizes[index]/length);
+    int n = (int)std::abs(m_domain_sizes[index] / length);
     double nd = (double)n;
     complex_t fp = FTPDF(qx, qy, xi, index);
-    if (n<1) {
-        result = ((1.0 + fp)/(1.0 - fp)).real();
+    if (n < 1) {
+        result = ((1.0 + fp) / (1.0 - fp)).real();
     } else {
-        if (std::norm(1.0-fp) < std::numeric_limits<double>::epsilon() )
+        if (std::norm(1.0 - fp) < std::numeric_limits<double>::epsilon())
             result = nd;
         // for (1-fp)*nd small, take the series expansion to second order in nd*(1-fp)
-        else if (std::abs(1.0-fp)*nd < 2e-4) {
-            complex_t intermediate = (nd-1.0)/2.0 + (nd*nd-1.0)*(fp-1.0)/6.0
-                    + (nd*nd*nd-2.0*nd*nd-nd+2.0)*(fp-1.0)*(fp-1.0)/24.0;
-            result = 1.0 + 2.0*intermediate.real();
+        else if (std::abs(1.0 - fp) * nd < 2e-4) {
+            complex_t intermediate
+                = (nd - 1.0) / 2.0 + (nd * nd - 1.0) * (fp - 1.0) / 6.0
+                  + (nd * nd * nd - 2.0 * nd * nd - nd + 2.0) * (fp - 1.0) * (fp - 1.0) / 24.0;
+            result = 1.0 + 2.0 * intermediate.real();
         } else {
             complex_t tmp;
-            if (std::abs(fp)==0.0
-             || std::log(std::abs(fp))*nd < std::log(std::numeric_limits<double>::min()))
+            if (std::abs(fp) == 0.0
+                || std::log(std::abs(fp)) * nd < std::log(std::numeric_limits<double>::min()))
                 tmp = 0.0;
             else
-                tmp = std::pow(fp,n);
-            complex_t intermediate = fp/(1.0-fp) - fp*(1.0-tmp)/nd/(1.0-fp)/(1.0-fp);
-            result = 1.0 + 2.0*intermediate.real();
+                tmp = std::pow(fp, n);
+            complex_t intermediate
+                = fp / (1.0 - fp) - fp * (1.0 - tmp) / nd / (1.0 - fp) / (1.0 - fp);
+            result = 1.0 + 2.0 * intermediate.real();
         }
     }
     return result;
 }
 
-complex_t InterferenceFunction2DParaCrystal::FTPDF(
-    double qx, double qy, double xi, size_t index) const
+complex_t InterferenceFunction2DParaCrystal::FTPDF(double qx, double qy, double xi,
+                                                   size_t index) const
 {
-//    double length = (index ? m_lattice_params.m_length_2 : m_lattice_params.m_length_1);
     double length = (index ? m_lattice->length2() : m_lattice->length1());
 
     const IFTDistribution2D* pdf = (index ? m_pdf2.get() : m_pdf1.get());
-    double qa = qx*length*std::cos(xi) + qy*length*std::sin(xi);
+    double qa = qx * length * std::cos(xi) + qy * length * std::sin(xi);
     complex_t phase = exp_I(qa);
     // transform q to principal axes:
     double qp1, qp2;
@@ -272,9 +251,9 @@ complex_t InterferenceFunction2DParaCrystal::FTPDF(
     double delta = pdf->getDelta();
     transformToPrincipalAxes(qx, qy, gamma, delta, qp1, qp2);
     double amplitude = pdf->evaluate(qp1, qp2);
-    complex_t result = phase*amplitude;
+    complex_t result = phase * amplitude;
     if (m_use_damping_length)
-        result *= std::exp(-length/m_damping_length);
+        result *= std::exp(-length / m_damping_length);
     return result;
 }
 
@@ -289,19 +268,9 @@ InterferenceFunction2DParaCrystal::getProbabilityDistributions() const
     return {m_pdf1.get(), m_pdf2.get()};
 }
 
-//Lattice2DParameters InterferenceFunction2DParaCrystal::getLatticeParameters() const
-//{
-//    Lattice2DParameters result;
-//    result.m_length_1 = m_lattice->length1();
-//    result.m_length_2 = m_lattice->length2();
-//    result.m_angle = m_lattice->latticeAngle();
-//    result.m_xi = m_lattice->rotationAngle();
-//    return result;
-//}
-
-const Lattice2D&InterferenceFunction2DParaCrystal::lattice() const
+const Lattice2D& InterferenceFunction2DParaCrystal::lattice() const
 {
-    if(!m_lattice)
+    if (!m_lattice)
         throw std::runtime_error("InterferenceFunction2DParaCrystal::lattice() -> Error. "
                                  "No lattice defined.");
     return *m_lattice;
diff --git a/Core/Aggregate/InterferenceFunction2DParaCrystal.h b/Core/Aggregate/InterferenceFunction2DParaCrystal.h
index c3f236d267e56947f97875c1bb5a4c3830887eb5..f1f70ccfbe3b14f1241039a9e376824bee280990 100644
--- a/Core/Aggregate/InterferenceFunction2DParaCrystal.h
+++ b/Core/Aggregate/InterferenceFunction2DParaCrystal.h
@@ -19,7 +19,7 @@
 #include "IInterferenceFunction.h"
 #include "Complex.h"
 #include "FTDistributions2D.h"
-#include "Lattice2DParameters.h"
+#include "Lattice2D.h"
 #include <memory>
 
 template <class T> class IntegratorReal;
@@ -65,7 +65,6 @@ public:
     bool getIntegrationOverXi() const { return m_integrate_xi; }
     double getDampingLength() const { return m_damping_length; }
 
-//    Lattice2DParameters getLatticeParameters() const;
     const Lattice2D& lattice() const;
 
     double getParticleDensity() const final;
@@ -84,7 +83,6 @@ private:
     void transformToPrincipalAxes(double qx, double qy, double gamma, double delta, double& q_pa_1,
                                   double& q_pa_2) const;
 
-//    Lattice2DParameters m_lattice_params; //!< Lattice parameters
     bool m_integrate_xi; //!< Integrate over the orientation xi
     std::unique_ptr<IFTDistribution2D> m_pdf1, m_pdf2;
     std::unique_ptr<Lattice2D> m_lattice;
diff --git a/Core/Lattice/Lattice2DParameters.cpp b/Core/Lattice/Lattice2D.cpp
similarity index 96%
rename from Core/Lattice/Lattice2DParameters.cpp
rename to Core/Lattice/Lattice2D.cpp
index 755f7cdce96d4e3eee1802c3e41879a035f700b4..6a85e552074c20c61c1503b25a07a246f49700c4 100644
--- a/Core/Lattice/Lattice2DParameters.cpp
+++ b/Core/Lattice/Lattice2D.cpp
@@ -13,15 +13,11 @@
 //
 // ************************************************************************** //
 
-#include "Lattice2DParameters.h"
+#include "Lattice2D.h"
 #include "BornAgainNamespace.h"
 #include "RealParameter.h"
 #include "MathConstants.h"
-
-double Lattice2DParameters::getUnitCellArea() const
-{
-    return std::abs(m_length_1*m_length_2*std::sin(m_angle));
-}
+#include <cmath>
 
 Lattice2D::Lattice2D(double length1, double length2, double angle, double rotation_angle)
     : m_length1(length1)
diff --git a/Core/Lattice/Lattice2DParameters.h b/Core/Lattice/Lattice2D.h
similarity index 89%
rename from Core/Lattice/Lattice2DParameters.h
rename to Core/Lattice/Lattice2D.h
index 6073c4d9fd00a0bcada209b31bf05768d646a288..8fba8ff8329585c6f8c10608be95c5881766cef9 100644
--- a/Core/Lattice/Lattice2DParameters.h
+++ b/Core/Lattice/Lattice2D.h
@@ -18,22 +18,6 @@
 
 #include "ICloneable.h"
 #include "INode.h"
-#include <cmath>
-
-//! Additional parameters for 2D lattice.
-//! @ingroup samples
-
-class Lattice2DParameters
-{
-public:
-    Lattice2DParameters() : m_length_1(0), m_length_2(0), m_angle(0), m_xi(0) {}
-
-    double getUnitCellArea() const;
-
-    double m_length_1, m_length_2;
-    double m_angle;
-    double m_xi;
-};
 
 class Lattice2D : public ICloneable, public INode
 {
diff --git a/Core/Scattering/INodeVisitor.h b/Core/Scattering/INodeVisitor.h
index 039d0c6c033640e6e38b7821881441a9ee0ec31b..cc84713781f310e111e95a7b6fd21a1332067216 100644
--- a/Core/Scattering/INodeVisitor.h
+++ b/Core/Scattering/INodeVisitor.h
@@ -134,6 +134,10 @@ class OffSpecSimulation;
 class IntensityNormalizer;
 class IntensityScaleAndShiftNormalizer;
 
+class BasicLattice;
+class SquareLattice;
+class HexagonalLattice;
+
 //! Visitor interface to visit ISample objects.
 //! @ingroup samples_internal
 
@@ -261,6 +265,10 @@ public:
     virtual void visit(const IntensityNormalizer*) {}
     virtual void visit(const IntensityScaleAndShiftNormalizer*) {}
 
+    virtual void visit(const BasicLattice*) {}
+    virtual void visit(const SquareLattice*) {}
+    virtual void visit(const HexagonalLattice*) {}
+
     //! Returns depth of the visitor in the composite hierarchy
     int depth() const { return m_depth; }
 
diff --git a/Tests/UnitTests/Core/Sample/LatticeTest.h b/Tests/UnitTests/Core/Sample/Lattice2DTest.h
similarity index 91%
rename from Tests/UnitTests/Core/Sample/LatticeTest.h
rename to Tests/UnitTests/Core/Sample/Lattice2DTest.h
index f239a4de75d2d2e36455a2ba07de185f9896496b..2a200bdfe935c7601120e564e2506fb347252d0f 100644
--- a/Tests/UnitTests/Core/Sample/LatticeTest.h
+++ b/Tests/UnitTests/Core/Sample/Lattice2DTest.h
@@ -1,16 +1,16 @@
-#include "Lattice2DParameters.h"
+#include "Lattice2D.h"
 #include "BornAgainNamespace.h"
 
 #include <iostream>
 
-class LatticeTest : public ::testing::Test
+class Lattice2DTest : public ::testing::Test
 {
 protected:
-    LatticeTest(){}
+    Lattice2DTest(){}
 };
 
 
-TEST_F(LatticeTest, basicLattice)
+TEST_F(Lattice2DTest, basicLattice)
 {
     const double length1(1.0), length2(2.0), angle(3.0);
     BasicLattice lattice(length1, length2, angle);
@@ -31,7 +31,7 @@ TEST_F(LatticeTest, basicLattice)
     EXPECT_EQ(lattice.rotationAngle(), new_value);
 }
 
-TEST_F(LatticeTest, basicLatticeClone)
+TEST_F(Lattice2DTest, basicLatticeClone)
 {
     const double length1(1.0), length2(2.0), angle(3.0), xi(4.0);
     BasicLattice lattice(length1, length2, angle, xi);
@@ -44,7 +44,7 @@ TEST_F(LatticeTest, basicLatticeClone)
     EXPECT_EQ(clone->getName(), BornAgain::BasicLatticeType);
 }
 
-TEST_F(LatticeTest, squareLatticeClone)
+TEST_F(Lattice2DTest, squareLatticeClone)
 {
     const double length(1.0), xi(4.0);
     SquareLattice lattice(length, xi);
@@ -65,7 +65,7 @@ TEST_F(LatticeTest, squareLatticeClone)
     EXPECT_EQ(clone->rotationAngle(), new_value);
 }
 
-TEST_F(LatticeTest, hexagonalLatticeClone)
+TEST_F(Lattice2DTest, hexagonalLatticeClone)
 {
     const double length(1.0), xi(4.0);
     HexagonalLattice lattice(length, xi);
@@ -86,7 +86,7 @@ TEST_F(LatticeTest, hexagonalLatticeClone)
     EXPECT_EQ(clone->rotationAngle(), new_value);
 }
 
-TEST_F(LatticeTest, onChange)
+TEST_F(Lattice2DTest, onChange)
 {
     class Parent : public INode{
     public:
diff --git a/Tests/UnitTests/Core/Sample/testlist.h b/Tests/UnitTests/Core/Sample/testlist.h
index db46193e80e536155079a2d9ac36f1b872b420fb..f7f44f80cb7384fea3798dcdf28193d1379668b0 100644
--- a/Tests/UnitTests/Core/Sample/testlist.h
+++ b/Tests/UnitTests/Core/Sample/testlist.h
@@ -15,4 +15,4 @@
 #include "CrystalTest.h"
 #include "MesoCrystalTest.h"
 #include "INodeTest.h"
-#include "LatticeTest.h"
+#include "Lattice2DTest.h"
diff --git a/Wrap/swig/libBornAgainCore.i b/Wrap/swig/libBornAgainCore.i
index be3e110dc042eabafdf612e8417da008c948da9a..696efbac471d24d8f17cb90bfabc776817d68a54 100644
--- a/Wrap/swig/libBornAgainCore.i
+++ b/Wrap/swig/libBornAgainCore.i
@@ -178,7 +178,7 @@
 #include "IsGISAXSDetector.h"
 #include "Lattice.h"
 #include "Lattice1DParameters.h"
-#include "Lattice2DParameters.h"
+#include "Lattice2D.h"
 #include "Layer.h"
 #include "LayerInterface.h"
 #include "LayerRoughness.h"
@@ -392,7 +392,7 @@
 %include "IsGISAXSDetector.h"
 %include "Lattice.h"
 %include "Lattice1DParameters.h"
-%include "Lattice2DParameters.h"
+%include "Lattice2D.h"
 %include "Layer.h"
 %include "LayerRoughness.h"
 %include "Line.h"
diff --git a/auto/Wrap/libBornAgainCore.py b/auto/Wrap/libBornAgainCore.py
index a096007baeda2561ef51a9972ed91d07a1a70946..3c13eb416b341de75752999750158851590c3721 100644
--- a/auto/Wrap/libBornAgainCore.py
+++ b/auto/Wrap/libBornAgainCore.py
@@ -7348,6 +7348,9 @@ class INodeVisitor(_object):
         visit(INodeVisitor self, OffSpecSimulation arg2)
         visit(INodeVisitor self, IntensityNormalizer arg2)
         visit(INodeVisitor self, IntensityScaleAndShiftNormalizer arg2)
+        visit(INodeVisitor self, BasicLattice arg2)
+        visit(INodeVisitor self, SquareLattice arg2)
+        visit(INodeVisitor self, HexagonalLattice arg2)
         """
         return _libBornAgainCore.INodeVisitor_visit(self, *args)
 
@@ -20596,65 +20599,6 @@ class Lattice1DParameters(_object):
 Lattice1DParameters_swigregister = _libBornAgainCore.Lattice1DParameters_swigregister
 Lattice1DParameters_swigregister(Lattice1DParameters)
 
-class Lattice2DParameters(_object):
-    """
-
-
-    Additional parameters for 2D lattice.
-
-    C++ includes: Lattice2DParameters.h
-
-    """
-
-    __swig_setmethods__ = {}
-    __setattr__ = lambda self, name, value: _swig_setattr(self, Lattice2DParameters, name, value)
-    __swig_getmethods__ = {}
-    __getattr__ = lambda self, name: _swig_getattr(self, Lattice2DParameters, name)
-    __repr__ = _swig_repr
-
-    def __init__(self):
-        """
-        __init__(Lattice2DParameters self) -> Lattice2DParameters
-
-        Lattice2DParameters::Lattice2DParameters()
-
-        """
-        this = _libBornAgainCore.new_Lattice2DParameters()
-        try:
-            self.this.append(this)
-        except Exception:
-            self.this = this
-
-    def getUnitCellArea(self):
-        """
-        getUnitCellArea(Lattice2DParameters self) -> double
-
-        double Lattice2DParameters::getUnitCellArea() const 
-
-        """
-        return _libBornAgainCore.Lattice2DParameters_getUnitCellArea(self)
-
-    __swig_setmethods__["m_length_1"] = _libBornAgainCore.Lattice2DParameters_m_length_1_set
-    __swig_getmethods__["m_length_1"] = _libBornAgainCore.Lattice2DParameters_m_length_1_get
-    if _newclass:
-        m_length_1 = _swig_property(_libBornAgainCore.Lattice2DParameters_m_length_1_get, _libBornAgainCore.Lattice2DParameters_m_length_1_set)
-    __swig_setmethods__["m_length_2"] = _libBornAgainCore.Lattice2DParameters_m_length_2_set
-    __swig_getmethods__["m_length_2"] = _libBornAgainCore.Lattice2DParameters_m_length_2_get
-    if _newclass:
-        m_length_2 = _swig_property(_libBornAgainCore.Lattice2DParameters_m_length_2_get, _libBornAgainCore.Lattice2DParameters_m_length_2_set)
-    __swig_setmethods__["m_angle"] = _libBornAgainCore.Lattice2DParameters_m_angle_set
-    __swig_getmethods__["m_angle"] = _libBornAgainCore.Lattice2DParameters_m_angle_get
-    if _newclass:
-        m_angle = _swig_property(_libBornAgainCore.Lattice2DParameters_m_angle_get, _libBornAgainCore.Lattice2DParameters_m_angle_set)
-    __swig_setmethods__["m_xi"] = _libBornAgainCore.Lattice2DParameters_m_xi_set
-    __swig_getmethods__["m_xi"] = _libBornAgainCore.Lattice2DParameters_m_xi_get
-    if _newclass:
-        m_xi = _swig_property(_libBornAgainCore.Lattice2DParameters_m_xi_get, _libBornAgainCore.Lattice2DParameters_m_xi_set)
-    __swig_destroy__ = _libBornAgainCore.delete_Lattice2DParameters
-    __del__ = lambda self: None
-Lattice2DParameters_swigregister = _libBornAgainCore.Lattice2DParameters_swigregister
-Lattice2DParameters_swigregister(Lattice2DParameters)
-
 class Lattice2D(ICloneable, INode):
     """Proxy of C++ Lattice2D class."""
 
diff --git a/auto/Wrap/libBornAgainCore_wrap.cpp b/auto/Wrap/libBornAgainCore_wrap.cpp
index 57baf5566e7e9b7207519cc6d935db1ed057d0a1..9d1ab40557a97e2af5efa3102a065d0cc0df7c4b 100644
--- a/auto/Wrap/libBornAgainCore_wrap.cpp
+++ b/auto/Wrap/libBornAgainCore_wrap.cpp
@@ -3622,143 +3622,142 @@ namespace Swig {
 #define SWIGTYPE_p_Lattice swig_types[165]
 #define SWIGTYPE_p_Lattice1DParameters swig_types[166]
 #define SWIGTYPE_p_Lattice2D swig_types[167]
-#define SWIGTYPE_p_Lattice2DParameters swig_types[168]
-#define SWIGTYPE_p_Lattice2D__ReciprocalBases swig_types[169]
-#define SWIGTYPE_p_Layer swig_types[170]
-#define SWIGTYPE_p_LayerInterface swig_types[171]
-#define SWIGTYPE_p_LayerRTCoefficients_t swig_types[172]
-#define SWIGTYPE_p_LayerRoughness swig_types[173]
-#define SWIGTYPE_p_Line swig_types[174]
-#define SWIGTYPE_p_Logging__Logger swig_types[175]
-#define SWIGTYPE_p_MesoCrystal swig_types[176]
-#define SWIGTYPE_p_MultiLayer swig_types[177]
-#define SWIGTYPE_p_MultiLayerRTCoefficients_t swig_types[178]
-#define SWIGTYPE_p_OffSpecSimulation swig_types[179]
-#define SWIGTYPE_p_OutputDataIteratorT_double_OutputDataT_double_t_t swig_types[180]
-#define SWIGTYPE_p_OutputDataIteratorT_double_const_OutputDataT_double_t_const_t swig_types[181]
-#define SWIGTYPE_p_OutputDataT_CumulativeValue_t swig_types[182]
-#define SWIGTYPE_p_OutputDataT_bool_t swig_types[183]
-#define SWIGTYPE_p_OutputDataT_double_t swig_types[184]
-#define SWIGTYPE_p_ParameterDistribution swig_types[185]
-#define SWIGTYPE_p_ParameterPool swig_types[186]
-#define SWIGTYPE_p_ParameterSample swig_types[187]
-#define SWIGTYPE_p_Particle swig_types[188]
-#define SWIGTYPE_p_ParticleComposition swig_types[189]
-#define SWIGTYPE_p_ParticleCoreShell swig_types[190]
-#define SWIGTYPE_p_ParticleDistribution swig_types[191]
-#define SWIGTYPE_p_ParticleLayout swig_types[192]
-#define SWIGTYPE_p_Polygon swig_types[193]
-#define SWIGTYPE_p_PolygonPrivate swig_types[194]
-#define SWIGTYPE_p_PolygonalTopology swig_types[195]
-#define SWIGTYPE_p_PolyhedralEdge swig_types[196]
-#define SWIGTYPE_p_PolyhedralFace swig_types[197]
-#define SWIGTYPE_p_PolyhedralTopology swig_types[198]
-#define SWIGTYPE_p_ProgressHandler__Callback_t swig_types[199]
-#define SWIGTYPE_p_RealLimits swig_types[200]
-#define SWIGTYPE_p_RealParameter swig_types[201]
-#define SWIGTYPE_p_Rectangle swig_types[202]
-#define SWIGTYPE_p_RectangularDetector swig_types[203]
-#define SWIGTYPE_p_RectangularPixel swig_types[204]
-#define SWIGTYPE_p_RegionOfInterest swig_types[205]
-#define SWIGTYPE_p_ResolutionFunction2DGaussian swig_types[206]
-#define SWIGTYPE_p_RotationEuler swig_types[207]
-#define SWIGTYPE_p_RotationX swig_types[208]
-#define SWIGTYPE_p_RotationY swig_types[209]
-#define SWIGTYPE_p_RotationZ swig_types[210]
-#define SWIGTYPE_p_SafePointerVectorT_FitObject_t__iterator swig_types[211]
-#define SWIGTYPE_p_SafePointerVectorT_IParticle_const_t swig_types[212]
-#define SWIGTYPE_p_SampleBuilderFactory swig_types[213]
-#define SWIGTYPE_p_SimpleSelectionRule swig_types[214]
-#define SWIGTYPE_p_Simulation swig_types[215]
-#define SWIGTYPE_p_SimulationFactory swig_types[216]
-#define SWIGTYPE_p_SimulationOptions swig_types[217]
-#define SWIGTYPE_p_SpecularSimulation swig_types[218]
-#define SWIGTYPE_p_SphericalDetector swig_types[219]
-#define SWIGTYPE_p_SphericalPixel swig_types[220]
-#define SWIGTYPE_p_SquareLattice swig_types[221]
-#define SWIGTYPE_p_SquaredFunctionDefault swig_types[222]
-#define SWIGTYPE_p_SquaredFunctionGaussianError swig_types[223]
-#define SWIGTYPE_p_SquaredFunctionMeanSquaredError swig_types[224]
-#define SWIGTYPE_p_SquaredFunctionSimError swig_types[225]
-#define SWIGTYPE_p_SquaredFunctionSystematicError swig_types[226]
-#define SWIGTYPE_p_ThreadInfo swig_types[227]
-#define SWIGTYPE_p_Transform3D swig_types[228]
-#define SWIGTYPE_p_VariableBinAxis swig_types[229]
-#define SWIGTYPE_p_VerticalLine swig_types[230]
-#define SWIGTYPE_p_WavevectorInfo swig_types[231]
-#define SWIGTYPE_p__object swig_types[232]
-#define SWIGTYPE_p_allocator_type swig_types[233]
-#define SWIGTYPE_p_bool swig_types[234]
-#define SWIGTYPE_p_char swig_types[235]
-#define SWIGTYPE_p_const_iterator swig_types[236]
-#define SWIGTYPE_p_const_reference swig_types[237]
-#define SWIGTYPE_p_difference_type swig_types[238]
-#define SWIGTYPE_p_double swig_types[239]
-#define SWIGTYPE_p_int swig_types[240]
-#define SWIGTYPE_p_iterator swig_types[241]
-#define SWIGTYPE_p_long_long swig_types[242]
-#define SWIGTYPE_p_observer_t swig_types[243]
-#define SWIGTYPE_p_observerlist_t swig_types[244]
-#define SWIGTYPE_p_p__object swig_types[245]
-#define SWIGTYPE_p_reference swig_types[246]
-#define SWIGTYPE_p_short swig_types[247]
-#define SWIGTYPE_p_signed_char swig_types[248]
-#define SWIGTYPE_p_size_type swig_types[249]
-#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_double_t_t swig_types[250]
-#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t swig_types[251]
-#define SWIGTYPE_p_std__allocatorT_IFormFactor_p_t swig_types[252]
-#define SWIGTYPE_p_std__allocatorT_INode_const_p_t swig_types[253]
-#define SWIGTYPE_p_std__allocatorT_INode_p_t swig_types[254]
-#define SWIGTYPE_p_std__allocatorT_ParameterSample_t swig_types[255]
-#define SWIGTYPE_p_std__allocatorT_double_t swig_types[256]
-#define SWIGTYPE_p_std__allocatorT_int_t swig_types[257]
-#define SWIGTYPE_p_std__allocatorT_std__complexT_double_t_t swig_types[258]
-#define SWIGTYPE_p_std__allocatorT_std__string_t swig_types[259]
-#define SWIGTYPE_p_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t swig_types[260]
-#define SWIGTYPE_p_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t swig_types[261]
-#define SWIGTYPE_p_std__allocatorT_unsigned_long_t swig_types[262]
-#define SWIGTYPE_p_std__complexT_double_t swig_types[263]
-#define SWIGTYPE_p_std__functionT_GISASSimulation_pfF_t swig_types[264]
-#define SWIGTYPE_p_std__functionT_IMultiLayerBuilder_pfF_t swig_types[265]
-#define SWIGTYPE_p_std__functionT_void_fF_t swig_types[266]
-#define SWIGTYPE_p_std__invalid_argument swig_types[267]
-#define SWIGTYPE_p_std__mapT_std__string_std__string_t__const_iterator swig_types[268]
-#define SWIGTYPE_p_std__shared_ptrT_IFitObserver_t swig_types[269]
-#define SWIGTYPE_p_std__shared_ptrT_ILayerRTCoefficients_const_t swig_types[270]
-#define SWIGTYPE_p_std__shared_ptrT_IMultiLayerBuilder_t swig_types[271]
-#define SWIGTYPE_p_std__shared_ptrT_IObserver_t swig_types[272]
-#define SWIGTYPE_p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t swig_types[273]
-#define SWIGTYPE_p_std__vectorT_BasicVector3DT_std__complexT_double_t_t_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t_t swig_types[274]
-#define SWIGTYPE_p_std__vectorT_FitElement_std__allocatorT_FitElement_t_t swig_types[275]
-#define SWIGTYPE_p_std__vectorT_FitElement_std__allocatorT_FitElement_t_t__const_iterator swig_types[276]
-#define SWIGTYPE_p_std__vectorT_FitElement_std__allocatorT_FitElement_t_t__iterator swig_types[277]
-#define SWIGTYPE_p_std__vectorT_IDetector2D__EAxesUnits_std__allocatorT_IDetector2D__EAxesUnits_t_t swig_types[278]
-#define SWIGTYPE_p_std__vectorT_IFTDistribution2D_const_p_std__allocatorT_IFTDistribution2D_const_p_t_t swig_types[279]
-#define SWIGTYPE_p_std__vectorT_IFormFactor_p_std__allocatorT_IFormFactor_p_t_t swig_types[280]
-#define SWIGTYPE_p_std__vectorT_IMaterial_const_p_std__allocatorT_IMaterial_const_p_t_t swig_types[281]
-#define SWIGTYPE_p_std__vectorT_INode_const_p_std__allocatorT_INode_const_p_t_t swig_types[282]
-#define SWIGTYPE_p_std__vectorT_INode_p_std__allocatorT_INode_p_t_t swig_types[283]
-#define SWIGTYPE_p_std__vectorT_IParticle_const_p_std__allocatorT_IParticle_const_p_t_t swig_types[284]
-#define SWIGTYPE_p_std__vectorT_ParameterSample_std__allocatorT_ParameterSample_t_t swig_types[285]
-#define SWIGTYPE_p_std__vectorT_PolygonalTopology_std__allocatorT_PolygonalTopology_t_t swig_types[286]
-#define SWIGTYPE_p_std__vectorT_RealParameter_p_std__allocatorT_RealParameter_p_t_t swig_types[287]
-#define SWIGTYPE_p_std__vectorT_SimulationElement_std__allocatorT_SimulationElement_t_t swig_types[288]
-#define SWIGTYPE_p_std__vectorT_double_std__allocatorT_double_t_t swig_types[289]
-#define SWIGTYPE_p_std__vectorT_int_std__allocatorT_int_t_t swig_types[290]
-#define SWIGTYPE_p_std__vectorT_size_t_std__allocatorT_size_t_t_t swig_types[291]
-#define SWIGTYPE_p_std__vectorT_std__complexT_double_t_std__allocatorT_std__complexT_double_t_t_t swig_types[292]
-#define SWIGTYPE_p_std__vectorT_std__string_std__allocatorT_std__string_t_t swig_types[293]
-#define SWIGTYPE_p_std__vectorT_std__vectorT_double_std__allocatorT_double_t_t_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t_t swig_types[294]
-#define SWIGTYPE_p_std__vectorT_std__vectorT_int_std__allocatorT_int_t_t_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t_t swig_types[295]
-#define SWIGTYPE_p_std__vectorT_unsigned_long_std__allocatorT_unsigned_long_t_t swig_types[296]
-#define SWIGTYPE_p_swig__SwigPyIterator swig_types[297]
-#define SWIGTYPE_p_unsigned_char swig_types[298]
-#define SWIGTYPE_p_unsigned_int swig_types[299]
-#define SWIGTYPE_p_unsigned_long_long swig_types[300]
-#define SWIGTYPE_p_unsigned_short swig_types[301]
-#define SWIGTYPE_p_value_type swig_types[302]
-static swig_type_info *swig_types[304];
-static swig_module_info swig_module = {swig_types, 303, 0, 0, 0, 0};
+#define SWIGTYPE_p_Lattice2D__ReciprocalBases swig_types[168]
+#define SWIGTYPE_p_Layer swig_types[169]
+#define SWIGTYPE_p_LayerInterface swig_types[170]
+#define SWIGTYPE_p_LayerRTCoefficients_t swig_types[171]
+#define SWIGTYPE_p_LayerRoughness swig_types[172]
+#define SWIGTYPE_p_Line swig_types[173]
+#define SWIGTYPE_p_Logging__Logger swig_types[174]
+#define SWIGTYPE_p_MesoCrystal swig_types[175]
+#define SWIGTYPE_p_MultiLayer swig_types[176]
+#define SWIGTYPE_p_MultiLayerRTCoefficients_t swig_types[177]
+#define SWIGTYPE_p_OffSpecSimulation swig_types[178]
+#define SWIGTYPE_p_OutputDataIteratorT_double_OutputDataT_double_t_t swig_types[179]
+#define SWIGTYPE_p_OutputDataIteratorT_double_const_OutputDataT_double_t_const_t swig_types[180]
+#define SWIGTYPE_p_OutputDataT_CumulativeValue_t swig_types[181]
+#define SWIGTYPE_p_OutputDataT_bool_t swig_types[182]
+#define SWIGTYPE_p_OutputDataT_double_t swig_types[183]
+#define SWIGTYPE_p_ParameterDistribution swig_types[184]
+#define SWIGTYPE_p_ParameterPool swig_types[185]
+#define SWIGTYPE_p_ParameterSample swig_types[186]
+#define SWIGTYPE_p_Particle swig_types[187]
+#define SWIGTYPE_p_ParticleComposition swig_types[188]
+#define SWIGTYPE_p_ParticleCoreShell swig_types[189]
+#define SWIGTYPE_p_ParticleDistribution swig_types[190]
+#define SWIGTYPE_p_ParticleLayout swig_types[191]
+#define SWIGTYPE_p_Polygon swig_types[192]
+#define SWIGTYPE_p_PolygonPrivate swig_types[193]
+#define SWIGTYPE_p_PolygonalTopology swig_types[194]
+#define SWIGTYPE_p_PolyhedralEdge swig_types[195]
+#define SWIGTYPE_p_PolyhedralFace swig_types[196]
+#define SWIGTYPE_p_PolyhedralTopology swig_types[197]
+#define SWIGTYPE_p_ProgressHandler__Callback_t swig_types[198]
+#define SWIGTYPE_p_RealLimits swig_types[199]
+#define SWIGTYPE_p_RealParameter swig_types[200]
+#define SWIGTYPE_p_Rectangle swig_types[201]
+#define SWIGTYPE_p_RectangularDetector swig_types[202]
+#define SWIGTYPE_p_RectangularPixel swig_types[203]
+#define SWIGTYPE_p_RegionOfInterest swig_types[204]
+#define SWIGTYPE_p_ResolutionFunction2DGaussian swig_types[205]
+#define SWIGTYPE_p_RotationEuler swig_types[206]
+#define SWIGTYPE_p_RotationX swig_types[207]
+#define SWIGTYPE_p_RotationY swig_types[208]
+#define SWIGTYPE_p_RotationZ swig_types[209]
+#define SWIGTYPE_p_SafePointerVectorT_FitObject_t__iterator swig_types[210]
+#define SWIGTYPE_p_SafePointerVectorT_IParticle_const_t swig_types[211]
+#define SWIGTYPE_p_SampleBuilderFactory swig_types[212]
+#define SWIGTYPE_p_SimpleSelectionRule swig_types[213]
+#define SWIGTYPE_p_Simulation swig_types[214]
+#define SWIGTYPE_p_SimulationFactory swig_types[215]
+#define SWIGTYPE_p_SimulationOptions swig_types[216]
+#define SWIGTYPE_p_SpecularSimulation swig_types[217]
+#define SWIGTYPE_p_SphericalDetector swig_types[218]
+#define SWIGTYPE_p_SphericalPixel swig_types[219]
+#define SWIGTYPE_p_SquareLattice swig_types[220]
+#define SWIGTYPE_p_SquaredFunctionDefault swig_types[221]
+#define SWIGTYPE_p_SquaredFunctionGaussianError swig_types[222]
+#define SWIGTYPE_p_SquaredFunctionMeanSquaredError swig_types[223]
+#define SWIGTYPE_p_SquaredFunctionSimError swig_types[224]
+#define SWIGTYPE_p_SquaredFunctionSystematicError swig_types[225]
+#define SWIGTYPE_p_ThreadInfo swig_types[226]
+#define SWIGTYPE_p_Transform3D swig_types[227]
+#define SWIGTYPE_p_VariableBinAxis swig_types[228]
+#define SWIGTYPE_p_VerticalLine swig_types[229]
+#define SWIGTYPE_p_WavevectorInfo swig_types[230]
+#define SWIGTYPE_p__object swig_types[231]
+#define SWIGTYPE_p_allocator_type swig_types[232]
+#define SWIGTYPE_p_bool swig_types[233]
+#define SWIGTYPE_p_char swig_types[234]
+#define SWIGTYPE_p_const_iterator swig_types[235]
+#define SWIGTYPE_p_const_reference swig_types[236]
+#define SWIGTYPE_p_difference_type swig_types[237]
+#define SWIGTYPE_p_double swig_types[238]
+#define SWIGTYPE_p_int swig_types[239]
+#define SWIGTYPE_p_iterator swig_types[240]
+#define SWIGTYPE_p_long_long swig_types[241]
+#define SWIGTYPE_p_observer_t swig_types[242]
+#define SWIGTYPE_p_observerlist_t swig_types[243]
+#define SWIGTYPE_p_p__object swig_types[244]
+#define SWIGTYPE_p_reference swig_types[245]
+#define SWIGTYPE_p_short swig_types[246]
+#define SWIGTYPE_p_signed_char swig_types[247]
+#define SWIGTYPE_p_size_type swig_types[248]
+#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_double_t_t swig_types[249]
+#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t swig_types[250]
+#define SWIGTYPE_p_std__allocatorT_IFormFactor_p_t swig_types[251]
+#define SWIGTYPE_p_std__allocatorT_INode_const_p_t swig_types[252]
+#define SWIGTYPE_p_std__allocatorT_INode_p_t swig_types[253]
+#define SWIGTYPE_p_std__allocatorT_ParameterSample_t swig_types[254]
+#define SWIGTYPE_p_std__allocatorT_double_t swig_types[255]
+#define SWIGTYPE_p_std__allocatorT_int_t swig_types[256]
+#define SWIGTYPE_p_std__allocatorT_std__complexT_double_t_t swig_types[257]
+#define SWIGTYPE_p_std__allocatorT_std__string_t swig_types[258]
+#define SWIGTYPE_p_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t swig_types[259]
+#define SWIGTYPE_p_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t swig_types[260]
+#define SWIGTYPE_p_std__allocatorT_unsigned_long_t swig_types[261]
+#define SWIGTYPE_p_std__complexT_double_t swig_types[262]
+#define SWIGTYPE_p_std__functionT_GISASSimulation_pfF_t swig_types[263]
+#define SWIGTYPE_p_std__functionT_IMultiLayerBuilder_pfF_t swig_types[264]
+#define SWIGTYPE_p_std__functionT_void_fF_t swig_types[265]
+#define SWIGTYPE_p_std__invalid_argument swig_types[266]
+#define SWIGTYPE_p_std__mapT_std__string_std__string_t__const_iterator swig_types[267]
+#define SWIGTYPE_p_std__shared_ptrT_IFitObserver_t swig_types[268]
+#define SWIGTYPE_p_std__shared_ptrT_ILayerRTCoefficients_const_t swig_types[269]
+#define SWIGTYPE_p_std__shared_ptrT_IMultiLayerBuilder_t swig_types[270]
+#define SWIGTYPE_p_std__shared_ptrT_IObserver_t swig_types[271]
+#define SWIGTYPE_p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t swig_types[272]
+#define SWIGTYPE_p_std__vectorT_BasicVector3DT_std__complexT_double_t_t_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t_t swig_types[273]
+#define SWIGTYPE_p_std__vectorT_FitElement_std__allocatorT_FitElement_t_t swig_types[274]
+#define SWIGTYPE_p_std__vectorT_FitElement_std__allocatorT_FitElement_t_t__const_iterator swig_types[275]
+#define SWIGTYPE_p_std__vectorT_FitElement_std__allocatorT_FitElement_t_t__iterator swig_types[276]
+#define SWIGTYPE_p_std__vectorT_IDetector2D__EAxesUnits_std__allocatorT_IDetector2D__EAxesUnits_t_t swig_types[277]
+#define SWIGTYPE_p_std__vectorT_IFTDistribution2D_const_p_std__allocatorT_IFTDistribution2D_const_p_t_t swig_types[278]
+#define SWIGTYPE_p_std__vectorT_IFormFactor_p_std__allocatorT_IFormFactor_p_t_t swig_types[279]
+#define SWIGTYPE_p_std__vectorT_IMaterial_const_p_std__allocatorT_IMaterial_const_p_t_t swig_types[280]
+#define SWIGTYPE_p_std__vectorT_INode_const_p_std__allocatorT_INode_const_p_t_t swig_types[281]
+#define SWIGTYPE_p_std__vectorT_INode_p_std__allocatorT_INode_p_t_t swig_types[282]
+#define SWIGTYPE_p_std__vectorT_IParticle_const_p_std__allocatorT_IParticle_const_p_t_t swig_types[283]
+#define SWIGTYPE_p_std__vectorT_ParameterSample_std__allocatorT_ParameterSample_t_t swig_types[284]
+#define SWIGTYPE_p_std__vectorT_PolygonalTopology_std__allocatorT_PolygonalTopology_t_t swig_types[285]
+#define SWIGTYPE_p_std__vectorT_RealParameter_p_std__allocatorT_RealParameter_p_t_t swig_types[286]
+#define SWIGTYPE_p_std__vectorT_SimulationElement_std__allocatorT_SimulationElement_t_t swig_types[287]
+#define SWIGTYPE_p_std__vectorT_double_std__allocatorT_double_t_t swig_types[288]
+#define SWIGTYPE_p_std__vectorT_int_std__allocatorT_int_t_t swig_types[289]
+#define SWIGTYPE_p_std__vectorT_size_t_std__allocatorT_size_t_t_t swig_types[290]
+#define SWIGTYPE_p_std__vectorT_std__complexT_double_t_std__allocatorT_std__complexT_double_t_t_t swig_types[291]
+#define SWIGTYPE_p_std__vectorT_std__string_std__allocatorT_std__string_t_t swig_types[292]
+#define SWIGTYPE_p_std__vectorT_std__vectorT_double_std__allocatorT_double_t_t_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t_t swig_types[293]
+#define SWIGTYPE_p_std__vectorT_std__vectorT_int_std__allocatorT_int_t_t_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t_t swig_types[294]
+#define SWIGTYPE_p_std__vectorT_unsigned_long_std__allocatorT_unsigned_long_t_t swig_types[295]
+#define SWIGTYPE_p_swig__SwigPyIterator swig_types[296]
+#define SWIGTYPE_p_unsigned_char swig_types[297]
+#define SWIGTYPE_p_unsigned_int swig_types[298]
+#define SWIGTYPE_p_unsigned_long_long swig_types[299]
+#define SWIGTYPE_p_unsigned_short swig_types[300]
+#define SWIGTYPE_p_value_type swig_types[301]
+static swig_type_info *swig_types[303];
+static swig_module_info swig_module = {swig_types, 302, 0, 0, 0, 0};
 #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
 #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
 
@@ -6554,7 +6553,7 @@ SWIGINTERN void std_vector_Sl_std_string_Sg__insert__SWIG_1(std::vector< std::st
 #include "IsGISAXSDetector.h"
 #include "Lattice.h"
 #include "Lattice1DParameters.h"
-#include "Lattice2DParameters.h"
+#include "Lattice2D.h"
 #include "Layer.h"
 #include "LayerInterface.h"
 #include "LayerRoughness.h"
@@ -49545,6 +49544,96 @@ fail:
 }
 
 
+SWIGINTERN PyObject *_wrap_INodeVisitor_visit__SWIG_93(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  INodeVisitor *arg1 = (INodeVisitor *) 0 ;
+  BasicLattice *arg2 = (BasicLattice *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:INodeVisitor_visit",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_INodeVisitor, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "INodeVisitor_visit" "', argument " "1"" of type '" "INodeVisitor *""'"); 
+  }
+  arg1 = reinterpret_cast< INodeVisitor * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_BasicLattice, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "INodeVisitor_visit" "', argument " "2"" of type '" "BasicLattice const *""'"); 
+  }
+  arg2 = reinterpret_cast< BasicLattice * >(argp2);
+  (arg1)->visit((BasicLattice const *)arg2);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_INodeVisitor_visit__SWIG_94(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  INodeVisitor *arg1 = (INodeVisitor *) 0 ;
+  SquareLattice *arg2 = (SquareLattice *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:INodeVisitor_visit",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_INodeVisitor, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "INodeVisitor_visit" "', argument " "1"" of type '" "INodeVisitor *""'"); 
+  }
+  arg1 = reinterpret_cast< INodeVisitor * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_SquareLattice, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "INodeVisitor_visit" "', argument " "2"" of type '" "SquareLattice const *""'"); 
+  }
+  arg2 = reinterpret_cast< SquareLattice * >(argp2);
+  (arg1)->visit((SquareLattice const *)arg2);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_INodeVisitor_visit__SWIG_95(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
+  PyObject *resultobj = 0;
+  INodeVisitor *arg1 = (INodeVisitor *) 0 ;
+  HexagonalLattice *arg2 = (HexagonalLattice *) 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  PyObject * obj0 = 0 ;
+  PyObject * obj1 = 0 ;
+  
+  if (!PyArg_ParseTuple(args,(char *)"OO:INodeVisitor_visit",&obj0,&obj1)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_INodeVisitor, 0 |  0 );
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "INodeVisitor_visit" "', argument " "1"" of type '" "INodeVisitor *""'"); 
+  }
+  arg1 = reinterpret_cast< INodeVisitor * >(argp1);
+  res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_HexagonalLattice, 0 |  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "INodeVisitor_visit" "', argument " "2"" of type '" "HexagonalLattice const *""'"); 
+  }
+  arg2 = reinterpret_cast< HexagonalLattice * >(argp2);
+  (arg1)->visit((HexagonalLattice const *)arg2);
+  resultobj = SWIG_Py_Void();
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
 SWIGINTERN PyObject *_wrap_INodeVisitor_visit(PyObject *self, PyObject *args) {
   Py_ssize_t argc;
   PyObject *argv[3] = {
@@ -50845,6 +50934,48 @@ SWIGINTERN PyObject *_wrap_INodeVisitor_visit(PyObject *self, PyObject *args) {
       }
     }
   }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_INodeVisitor, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      void *vptr = 0;
+      int res = SWIG_ConvertPtr(argv[1], &vptr, SWIGTYPE_p_BasicLattice, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_INodeVisitor_visit__SWIG_93(self, args);
+      }
+    }
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_INodeVisitor, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      void *vptr = 0;
+      int res = SWIG_ConvertPtr(argv[1], &vptr, SWIGTYPE_p_SquareLattice, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_INodeVisitor_visit__SWIG_94(self, args);
+      }
+    }
+  }
+  if (argc == 2) {
+    int _v;
+    void *vptr = 0;
+    int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_INodeVisitor, 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      void *vptr = 0;
+      int res = SWIG_ConvertPtr(argv[1], &vptr, SWIGTYPE_p_HexagonalLattice, 0);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_INodeVisitor_visit__SWIG_95(self, args);
+      }
+    }
+  }
   if (argc == 2) {
     int _v;
     void *vptr = 0;
@@ -50955,7 +51086,10 @@ fail:
     "    INodeVisitor::visit(GISASSimulation const *)\n"
     "    INodeVisitor::visit(OffSpecSimulation const *)\n"
     "    INodeVisitor::visit(IntensityNormalizer const *)\n"
-    "    INodeVisitor::visit(IntensityScaleAndShiftNormalizer const *)\n");
+    "    INodeVisitor::visit(IntensityScaleAndShiftNormalizer const *)\n"
+    "    INodeVisitor::visit(BasicLattice const *)\n"
+    "    INodeVisitor::visit(SquareLattice const *)\n"
+    "    INodeVisitor::visit(HexagonalLattice const *)\n");
   return 0;
 }
 
@@ -89575,277 +89709,6 @@ SWIGINTERN PyObject *Lattice1DParameters_swigregister(PyObject *SWIGUNUSEDPARM(s
   return SWIG_Py_Void();
 }
 
-SWIGINTERN PyObject *_wrap_new_Lattice2DParameters(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Lattice2DParameters *result = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)":new_Lattice2DParameters")) SWIG_fail;
-  result = (Lattice2DParameters *)new Lattice2DParameters();
-  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_Lattice2DParameters, SWIG_POINTER_NEW |  0 );
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Lattice2DParameters_getUnitCellArea(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Lattice2DParameters *arg1 = (Lattice2DParameters *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
-  double result;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O:Lattice2DParameters_getUnitCellArea",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Lattice2DParameters, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Lattice2DParameters_getUnitCellArea" "', argument " "1"" of type '" "Lattice2DParameters const *""'"); 
-  }
-  arg1 = reinterpret_cast< Lattice2DParameters * >(argp1);
-  result = (double)((Lattice2DParameters const *)arg1)->getUnitCellArea();
-  resultobj = SWIG_From_double(static_cast< double >(result));
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Lattice2DParameters_m_length_1_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Lattice2DParameters *arg1 = (Lattice2DParameters *) 0 ;
-  double arg2 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  double val2 ;
-  int ecode2 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"OO:Lattice2DParameters_m_length_1_set",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Lattice2DParameters, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Lattice2DParameters_m_length_1_set" "', argument " "1"" of type '" "Lattice2DParameters *""'"); 
-  }
-  arg1 = reinterpret_cast< Lattice2DParameters * >(argp1);
-  ecode2 = SWIG_AsVal_double(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Lattice2DParameters_m_length_1_set" "', argument " "2"" of type '" "double""'");
-  } 
-  arg2 = static_cast< double >(val2);
-  if (arg1) (arg1)->m_length_1 = arg2;
-  resultobj = SWIG_Py_Void();
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Lattice2DParameters_m_length_1_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Lattice2DParameters *arg1 = (Lattice2DParameters *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
-  double result;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O:Lattice2DParameters_m_length_1_get",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Lattice2DParameters, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Lattice2DParameters_m_length_1_get" "', argument " "1"" of type '" "Lattice2DParameters *""'"); 
-  }
-  arg1 = reinterpret_cast< Lattice2DParameters * >(argp1);
-  result = (double) ((arg1)->m_length_1);
-  resultobj = SWIG_From_double(static_cast< double >(result));
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Lattice2DParameters_m_length_2_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Lattice2DParameters *arg1 = (Lattice2DParameters *) 0 ;
-  double arg2 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  double val2 ;
-  int ecode2 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"OO:Lattice2DParameters_m_length_2_set",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Lattice2DParameters, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Lattice2DParameters_m_length_2_set" "', argument " "1"" of type '" "Lattice2DParameters *""'"); 
-  }
-  arg1 = reinterpret_cast< Lattice2DParameters * >(argp1);
-  ecode2 = SWIG_AsVal_double(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Lattice2DParameters_m_length_2_set" "', argument " "2"" of type '" "double""'");
-  } 
-  arg2 = static_cast< double >(val2);
-  if (arg1) (arg1)->m_length_2 = arg2;
-  resultobj = SWIG_Py_Void();
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Lattice2DParameters_m_length_2_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Lattice2DParameters *arg1 = (Lattice2DParameters *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
-  double result;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O:Lattice2DParameters_m_length_2_get",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Lattice2DParameters, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Lattice2DParameters_m_length_2_get" "', argument " "1"" of type '" "Lattice2DParameters *""'"); 
-  }
-  arg1 = reinterpret_cast< Lattice2DParameters * >(argp1);
-  result = (double) ((arg1)->m_length_2);
-  resultobj = SWIG_From_double(static_cast< double >(result));
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Lattice2DParameters_m_angle_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Lattice2DParameters *arg1 = (Lattice2DParameters *) 0 ;
-  double arg2 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  double val2 ;
-  int ecode2 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"OO:Lattice2DParameters_m_angle_set",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Lattice2DParameters, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Lattice2DParameters_m_angle_set" "', argument " "1"" of type '" "Lattice2DParameters *""'"); 
-  }
-  arg1 = reinterpret_cast< Lattice2DParameters * >(argp1);
-  ecode2 = SWIG_AsVal_double(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Lattice2DParameters_m_angle_set" "', argument " "2"" of type '" "double""'");
-  } 
-  arg2 = static_cast< double >(val2);
-  if (arg1) (arg1)->m_angle = arg2;
-  resultobj = SWIG_Py_Void();
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Lattice2DParameters_m_angle_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Lattice2DParameters *arg1 = (Lattice2DParameters *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
-  double result;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O:Lattice2DParameters_m_angle_get",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Lattice2DParameters, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Lattice2DParameters_m_angle_get" "', argument " "1"" of type '" "Lattice2DParameters *""'"); 
-  }
-  arg1 = reinterpret_cast< Lattice2DParameters * >(argp1);
-  result = (double) ((arg1)->m_angle);
-  resultobj = SWIG_From_double(static_cast< double >(result));
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Lattice2DParameters_m_xi_set(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Lattice2DParameters *arg1 = (Lattice2DParameters *) 0 ;
-  double arg2 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  double val2 ;
-  int ecode2 = 0 ;
-  PyObject * obj0 = 0 ;
-  PyObject * obj1 = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"OO:Lattice2DParameters_m_xi_set",&obj0,&obj1)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Lattice2DParameters, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Lattice2DParameters_m_xi_set" "', argument " "1"" of type '" "Lattice2DParameters *""'"); 
-  }
-  arg1 = reinterpret_cast< Lattice2DParameters * >(argp1);
-  ecode2 = SWIG_AsVal_double(obj1, &val2);
-  if (!SWIG_IsOK(ecode2)) {
-    SWIG_exception_fail(SWIG_ArgError(ecode2), "in method '" "Lattice2DParameters_m_xi_set" "', argument " "2"" of type '" "double""'");
-  } 
-  arg2 = static_cast< double >(val2);
-  if (arg1) (arg1)->m_xi = arg2;
-  resultobj = SWIG_Py_Void();
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_Lattice2DParameters_m_xi_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Lattice2DParameters *arg1 = (Lattice2DParameters *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
-  double result;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O:Lattice2DParameters_m_xi_get",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Lattice2DParameters, 0 |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "Lattice2DParameters_m_xi_get" "', argument " "1"" of type '" "Lattice2DParameters *""'"); 
-  }
-  arg1 = reinterpret_cast< Lattice2DParameters * >(argp1);
-  result = (double) ((arg1)->m_xi);
-  resultobj = SWIG_From_double(static_cast< double >(result));
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *_wrap_delete_Lattice2DParameters(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *resultobj = 0;
-  Lattice2DParameters *arg1 = (Lattice2DParameters *) 0 ;
-  void *argp1 = 0 ;
-  int res1 = 0 ;
-  PyObject * obj0 = 0 ;
-  
-  if (!PyArg_ParseTuple(args,(char *)"O:delete_Lattice2DParameters",&obj0)) SWIG_fail;
-  res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_Lattice2DParameters, SWIG_POINTER_DISOWN |  0 );
-  if (!SWIG_IsOK(res1)) {
-    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_Lattice2DParameters" "', argument " "1"" of type '" "Lattice2DParameters *""'"); 
-  }
-  arg1 = reinterpret_cast< Lattice2DParameters * >(argp1);
-  delete arg1;
-  resultobj = SWIG_Py_Void();
-  return resultobj;
-fail:
-  return NULL;
-}
-
-
-SWIGINTERN PyObject *Lattice2DParameters_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
-  PyObject *obj;
-  if (!PyArg_ParseTuple(args,(char*)"O:swigregister", &obj)) return NULL;
-  SWIG_TypeNewClientData(SWIGTYPE_p_Lattice2DParameters, SWIG_NewClientData(obj));
-  return SWIG_Py_Void();
-}
-
 SWIGINTERN PyObject *_wrap_Lattice2D_clone(PyObject *SWIGUNUSEDPARM(self), PyObject *args) {
   PyObject *resultobj = 0;
   Lattice2D *arg1 = (Lattice2D *) 0 ;
@@ -110520,7 +110383,10 @@ static PyMethodDef SwigMethods[] = {
 		"visit(GISASSimulation arg2)\n"
 		"visit(OffSpecSimulation arg2)\n"
 		"visit(IntensityNormalizer arg2)\n"
-		"INodeVisitor_visit(INodeVisitor self, IntensityScaleAndShiftNormalizer arg3)\n"
+		"visit(IntensityScaleAndShiftNormalizer arg2)\n"
+		"visit(BasicLattice arg2)\n"
+		"visit(SquareLattice arg2)\n"
+		"INodeVisitor_visit(INodeVisitor self, HexagonalLattice arg3)\n"
 		""},
 	 { (char *)"INodeVisitor_depth", _wrap_INodeVisitor_depth, METH_VARARGS, (char *)"INodeVisitor_depth(INodeVisitor self) -> int"},
 	 { (char *)"INodeVisitor_setDepth", _wrap_INodeVisitor_setDepth, METH_VARARGS, (char *)"INodeVisitor_setDepth(INodeVisitor self, int depth)"},
@@ -117415,28 +117281,6 @@ static PyMethodDef SwigMethods[] = {
 	 { (char *)"Lattice1DParameters_m_xi_get", _wrap_Lattice1DParameters_m_xi_get, METH_VARARGS, (char *)"Lattice1DParameters_m_xi_get(Lattice1DParameters self) -> double"},
 	 { (char *)"delete_Lattice1DParameters", _wrap_delete_Lattice1DParameters, METH_VARARGS, (char *)"delete_Lattice1DParameters(Lattice1DParameters self)"},
 	 { (char *)"Lattice1DParameters_swigregister", Lattice1DParameters_swigregister, METH_VARARGS, NULL},
-	 { (char *)"new_Lattice2DParameters", _wrap_new_Lattice2DParameters, METH_VARARGS, (char *)"\n"
-		"new_Lattice2DParameters() -> Lattice2DParameters\n"
-		"\n"
-		"Lattice2DParameters::Lattice2DParameters()\n"
-		"\n"
-		""},
-	 { (char *)"Lattice2DParameters_getUnitCellArea", _wrap_Lattice2DParameters_getUnitCellArea, METH_VARARGS, (char *)"\n"
-		"Lattice2DParameters_getUnitCellArea(Lattice2DParameters self) -> double\n"
-		"\n"
-		"double Lattice2DParameters::getUnitCellArea() const \n"
-		"\n"
-		""},
-	 { (char *)"Lattice2DParameters_m_length_1_set", _wrap_Lattice2DParameters_m_length_1_set, METH_VARARGS, (char *)"Lattice2DParameters_m_length_1_set(Lattice2DParameters self, double m_length_1)"},
-	 { (char *)"Lattice2DParameters_m_length_1_get", _wrap_Lattice2DParameters_m_length_1_get, METH_VARARGS, (char *)"Lattice2DParameters_m_length_1_get(Lattice2DParameters self) -> double"},
-	 { (char *)"Lattice2DParameters_m_length_2_set", _wrap_Lattice2DParameters_m_length_2_set, METH_VARARGS, (char *)"Lattice2DParameters_m_length_2_set(Lattice2DParameters self, double m_length_2)"},
-	 { (char *)"Lattice2DParameters_m_length_2_get", _wrap_Lattice2DParameters_m_length_2_get, METH_VARARGS, (char *)"Lattice2DParameters_m_length_2_get(Lattice2DParameters self) -> double"},
-	 { (char *)"Lattice2DParameters_m_angle_set", _wrap_Lattice2DParameters_m_angle_set, METH_VARARGS, (char *)"Lattice2DParameters_m_angle_set(Lattice2DParameters self, double m_angle)"},
-	 { (char *)"Lattice2DParameters_m_angle_get", _wrap_Lattice2DParameters_m_angle_get, METH_VARARGS, (char *)"Lattice2DParameters_m_angle_get(Lattice2DParameters self) -> double"},
-	 { (char *)"Lattice2DParameters_m_xi_set", _wrap_Lattice2DParameters_m_xi_set, METH_VARARGS, (char *)"Lattice2DParameters_m_xi_set(Lattice2DParameters self, double m_xi)"},
-	 { (char *)"Lattice2DParameters_m_xi_get", _wrap_Lattice2DParameters_m_xi_get, METH_VARARGS, (char *)"Lattice2DParameters_m_xi_get(Lattice2DParameters self) -> double"},
-	 { (char *)"delete_Lattice2DParameters", _wrap_delete_Lattice2DParameters, METH_VARARGS, (char *)"delete_Lattice2DParameters(Lattice2DParameters self)"},
-	 { (char *)"Lattice2DParameters_swigregister", Lattice2DParameters_swigregister, METH_VARARGS, NULL},
 	 { (char *)"Lattice2D_clone", _wrap_Lattice2D_clone, METH_VARARGS, (char *)"\n"
 		"Lattice2D_clone(Lattice2D self) -> Lattice2D\n"
 		"\n"
@@ -122697,7 +122541,6 @@ static swig_type_info _swigt__p_IsGISAXSDetector = {"_p_IsGISAXSDetector", "IsGI
 static swig_type_info _swigt__p_Lattice = {"_p_Lattice", "Lattice *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Lattice1DParameters = {"_p_Lattice1DParameters", "Lattice1DParameters *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Lattice2D = {"_p_Lattice2D", "Lattice2D *", 0, 0, (void*)0, 0};
-static swig_type_info _swigt__p_Lattice2DParameters = {"_p_Lattice2DParameters", "Lattice2DParameters *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Lattice2D__ReciprocalBases = {"_p_Lattice2D__ReciprocalBases", "Lattice2D::ReciprocalBases *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_Layer = {"_p_Layer", "Layer *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_LayerInterface = {"_p_LayerInterface", "LayerInterface *", 0, 0, (void*)0, 0};
@@ -123002,7 +122845,6 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_Lattice,
   &_swigt__p_Lattice1DParameters,
   &_swigt__p_Lattice2D,
-  &_swigt__p_Lattice2DParameters,
   &_swigt__p_Lattice2D__ReciprocalBases,
   &_swigt__p_Layer,
   &_swigt__p_LayerInterface,
@@ -123307,7 +123149,6 @@ static swig_cast_info _swigc__p_IsGISAXSDetector[] = {  {&_swigt__p_IsGISAXSDete
 static swig_cast_info _swigc__p_Lattice[] = {  {&_swigt__p_Lattice, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Lattice1DParameters[] = {  {&_swigt__p_Lattice1DParameters, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Lattice2D[] = {  {&_swigt__p_Lattice2D, 0, 0, 0},  {&_swigt__p_BasicLattice, _p_BasicLatticeTo_p_Lattice2D, 0, 0},  {&_swigt__p_SquareLattice, _p_SquareLatticeTo_p_Lattice2D, 0, 0},  {&_swigt__p_HexagonalLattice, _p_HexagonalLatticeTo_p_Lattice2D, 0, 0},{0, 0, 0, 0}};
-static swig_cast_info _swigc__p_Lattice2DParameters[] = {  {&_swigt__p_Lattice2DParameters, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Lattice2D__ReciprocalBases[] = {  {&_swigt__p_Lattice2D__ReciprocalBases, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_Layer[] = {  {&_swigt__p_Layer, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_LayerInterface[] = {  {&_swigt__p_LayerInterface, 0, 0, 0},{0, 0, 0, 0}};
@@ -123612,7 +123453,6 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_Lattice,
   _swigc__p_Lattice1DParameters,
   _swigc__p_Lattice2D,
-  _swigc__p_Lattice2DParameters,
   _swigc__p_Lattice2D__ReciprocalBases,
   _swigc__p_Layer,
   _swigc__p_LayerInterface,