From a2f719b89c2aad2a8f262cceae46dd9b4b6aa0e6 Mon Sep 17 00:00:00 2001
From: Thomas Fischer <thomas.fischer@ufz.de>
Date: Mon, 14 Jun 2021 10:10:04 +0200
Subject: [PATCH] [GL/OctTree] Use Eigen::Vector3d instead of MathLib::Point3d.

---
 GeoLib/OctTree-impl.h        | 35 +++++++++++++++++--------------
 GeoLib/OctTree.h             | 18 ++++++++--------
 GeoLib/PointVec.cpp          | 17 ++++++++++++---
 Tests/GeoLib/TestOctTree.cpp | 40 +++++++++++++++++++++++-------------
 4 files changed, 68 insertions(+), 42 deletions(-)

diff --git a/GeoLib/OctTree-impl.h b/GeoLib/OctTree-impl.h
index e044e7609e6..45ea89d9feb 100644
--- a/GeoLib/OctTree-impl.h
+++ b/GeoLib/OctTree-impl.h
@@ -13,9 +13,8 @@
 namespace GeoLib
 {
 template <typename POINT, std::size_t MAX_POINTS>
-template <typename T>
 OctTree<POINT, MAX_POINTS>* OctTree<POINT, MAX_POINTS>::createOctTree(
-    T ll, T ur, double eps)
+    Eigen::Vector3d ll, Eigen::Vector3d ur, double eps)
 {
     // compute an axis aligned cube around the points ll and ur
     const double dx(ur[0] - ll[0]);
@@ -60,7 +59,9 @@ OctTree<POINT, MAX_POINTS>* OctTree<POINT, MAX_POINTS>::createOctTree(
             ur[k] += eps;
         }
     }
-    return new OctTree<POINT, MAX_POINTS>(ll, ur, eps);
+    Eigen::Vector3d lower_left{ll[0], ll[1], ll[2]};
+    Eigen::Vector3d upper_right{ur[0], ur[1], ur[2]};
+    return new OctTree<POINT, MAX_POINTS>(lower_left, upper_right, eps);
 }
 
 template <typename POINT, std::size_t MAX_POINTS>
@@ -77,15 +78,19 @@ bool OctTree<POINT, MAX_POINTS>::addPoint(POINT* pnt, POINT*& ret_pnt)
 {
     // first do a range query using a epsilon box around the point pnt
     std::vector<POINT*> query_pnts;
-    MathLib::Point3d min(std::array<double, 3>{
-        {(*pnt)[0] - _eps, (*pnt)[1] - _eps, (*pnt)[2] - _eps}});
-    MathLib::Point3d max(std::array<double, 3>{
-        {(*pnt)[0] + _eps, (*pnt)[1] + _eps, (*pnt)[2] + _eps}});
+    Eigen::Vector3d const min =
+        Eigen::Map<Eigen::Vector3d>(pnt->getCoords()).array() - _eps;
+    Eigen::Vector3d const max =
+        Eigen::Map<Eigen::Vector3d>(pnt->getCoords()).array() + _eps;
     getPointsInRange(min, max, query_pnts);
-    auto const it =
-        std::find_if(query_pnts.begin(), query_pnts.end(),
-                     [pnt, this](auto const* p)
-                     { return MathLib::sqrDist(*p, *pnt) < _eps * _eps; });
+    auto const it = std::find_if(
+        query_pnts.begin(), query_pnts.end(),
+        [pnt, this](auto const* p)
+        {
+            return (Eigen::Map<Eigen::Vector3d const>(p->getCoords()) -
+                    Eigen::Map<Eigen::Vector3d const>(pnt->getCoords()))
+                       .squaredNorm() < _eps * _eps;
+        });
     if (it != query_pnts.end())
     {
         ret_pnt = *it;
@@ -164,8 +169,8 @@ void OctTree<POINT, MAX_POINTS>::getPointsInRange(
 }
 
 template <typename POINT, std::size_t MAX_POINTS>
-OctTree<POINT, MAX_POINTS>::OctTree(MathLib::Point3d const& ll,
-                                    MathLib::Point3d const& ur, double eps)
+OctTree<POINT, MAX_POINTS>::OctTree(Eigen::Vector3d const& ll,
+                                    Eigen::Vector3d const& ur, double eps)
     : _ll(ll), _ur(ur), _is_leaf(true), _eps(eps)
 {
     _children.fill(nullptr);
@@ -235,8 +240,8 @@ void OctTree<POINT, MAX_POINTS>::splitNode(POINT* pnt)
     const double x_mid((_ur[0] + _ll[0]) / 2.0);
     const double y_mid((_ur[1] + _ll[1]) / 2.0);
     const double z_mid((_ur[2] + _ll[2]) / 2.0);
-    MathLib::Point3d p0(std::array<double, 3>{{x_mid, y_mid, _ll[2]}});
-    MathLib::Point3d p1(std::array<double, 3>{{_ur[0], _ur[1], z_mid}});
+    Eigen::Vector3d p0{x_mid, y_mid, _ll[2]};
+    Eigen::Vector3d p1{_ur[0], _ur[1], z_mid};
 
     // create child NEL
     _children[static_cast<std::int8_t>(Quadrant::NEL)] =
diff --git a/GeoLib/OctTree.h b/GeoLib/OctTree.h
index 3b1d17ff42a..b780945234e 100644
--- a/GeoLib/OctTree.h
+++ b/GeoLib/OctTree.h
@@ -14,13 +14,11 @@
 
 #pragma once
 
+#include <Eigen/Eigen>
 #include <cstdint>
 #include <limits>
 #include <vector>
 
-#include "MathLib/MathTools.h"
-#include "MathLib/Point3d.h"
-
 namespace GeoLib
 {
 /// @tparam POINT point data type the OctTree will use
@@ -45,9 +43,9 @@ public:
     /// the memory requirements for the OctTree may be lower but the search
     /// inside a OctTree leaf may be more expensive. The value should be
     /// chosen application dependent. [default 8]
-    template <typename T>
     static OctTree<POINT, MAX_POINTS>* createOctTree(
-        T ll, T ur, double eps = std::numeric_limits<double>::epsilon());
+        Eigen::Vector3d ll, Eigen::Vector3d ur,
+        double eps = std::numeric_limits<double>::epsilon());
 
     /// Destroys the children of this node. @attention Does not destroy the
     /// pointers to the managed objects.
@@ -76,8 +74,8 @@ public:
                           std::vector<POINT*>& pnts) const;
 
 #ifndef NDEBUG
-    MathLib::Point3d const& getLowerLeftCornerPoint() const { return _ll; }
-    MathLib::Point3d const& getUpperRightCornerPoint() const { return _ur; }
+    Eigen::Vector3d const& getLowerLeftCornerPoint() const { return _ll; }
+    Eigen::Vector3d const& getUpperRightCornerPoint() const { return _ur; }
     OctTree<POINT, MAX_POINTS> const* getChild(std::size_t i) const
     {
         return _children[i];
@@ -90,7 +88,7 @@ private:
     /// @param ll lower left point
     /// @param ur upper right point
     /// @param eps the euclidean distance as a threshold to make objects unique
-    OctTree(MathLib::Point3d const& ll, MathLib::Point3d const& ur, double eps);
+    OctTree(Eigen::Vector3d const& ll, Eigen::Vector3d const& ur, double eps);
 
     enum class Quadrant : std::int8_t
     {
@@ -140,9 +138,9 @@ private:
     ///   _children[7] is south east upper child
     std::array<OctTree<POINT, MAX_POINTS>*, 8> _children;
     /// lower left front face point of the cube
-    MathLib::Point3d const _ll;
+    Eigen::Vector3d const _ll;
     /// upper right back face point of the cube
-    MathLib::Point3d const _ur;
+    Eigen::Vector3d const _ur;
     /// vector of pointers to POINT objects
     std::vector<POINT*> _pnts;
     /// flag if this OctTree is a leaf
diff --git a/GeoLib/PointVec.cpp b/GeoLib/PointVec.cpp
index 6822171f434..5fb55a23751 100644
--- a/GeoLib/PointVec.cpp
+++ b/GeoLib/PointVec.cpp
@@ -21,6 +21,14 @@
 
 namespace GeoLib
 {
+namespace details
+{
+Eigen::Vector3d convertToEigen(MathLib::Point3d point3d)
+{
+    return Eigen::Vector3d{point3d[0], point3d[1], point3d[2]};
+}
+}  // namespace details
+
 PointVec::PointVec(
     const std::string& name, std::unique_ptr<std::vector<Point*>> points,
     std::unique_ptr<std::map<std::string, std::size_t>> name_id_map,
@@ -31,7 +39,8 @@ PointVec::PointVec(
       _rel_eps(rel_eps * std::sqrt(MathLib::sqrDist(_aabb.getMinPoint(),
                                                     _aabb.getMaxPoint()))),
       _oct_tree(OctTree<GeoLib::Point, 16>::createOctTree(
-          _aabb.getMinPoint(), _aabb.getMaxPoint(), _rel_eps))
+          details::convertToEigen(_aabb.getMinPoint()),
+          details::convertToEigen(_aabb.getMaxPoint()), _rel_eps))
 {
     assert(_data_vec);
     std::size_t const number_of_all_input_pnts(_data_vec->size());
@@ -180,7 +189,8 @@ std::size_t PointVec::uniqueInsert(Point* pnt)
         _aabb.update(*pnt);
         // recreate the (enlarged) OctTree
         _oct_tree.reset(GeoLib::OctTree<GeoLib::Point, 16>::createOctTree(
-            _aabb.getMinPoint(), _aabb.getMaxPoint(), _rel_eps));
+            details::convertToEigen(_aabb.getMinPoint()),
+            details::convertToEigen(_aabb.getMaxPoint()), _rel_eps));
         // add all points that are already in the _data_vec
         for (std::size_t k(0); k < _data_vec->size(); ++k)
         {
@@ -267,7 +277,8 @@ void PointVec::resetInternalDataStructures()
                                                     _aabb.getMaxPoint()));
 
     _oct_tree.reset(OctTree<GeoLib::Point, 16>::createOctTree(
-        _aabb.getMinPoint(), _aabb.getMaxPoint(), _rel_eps));
+        details::convertToEigen(_aabb.getMinPoint()),
+        details::convertToEigen(_aabb.getMaxPoint()), _rel_eps));
 
     GeoLib::Point* ret_pnt(nullptr);
     for (auto const p : *_data_vec)
diff --git a/Tests/GeoLib/TestOctTree.cpp b/Tests/GeoLib/TestOctTree.cpp
index 62cb5930118..acd99a6a749 100644
--- a/Tests/GeoLib/TestOctTree.cpp
+++ b/Tests/GeoLib/TestOctTree.cpp
@@ -17,6 +17,14 @@
 #include "GeoLib/OctTree.h"
 #include "GeoLib/Point.h"
 
+namespace
+{
+Eigen::Vector3d convertToEigen(MathLib::Point3d point3d)
+{
+    return Eigen::Vector3d{point3d[0], point3d[1], point3d[2]};
+}
+}  // namespace
+
 class GeoLibOctTree : public testing::Test
 {
 public:
@@ -89,12 +97,13 @@ TEST_F(GeoLibOctTree, TestWithEquidistantPoints3d)
     generateEquidistantPoints3d();
     double const eps(10 * std::numeric_limits<double>::epsilon());
     std::unique_ptr<GeoLib::OctTree<GeoLib::Point, 2>> oct_tree(
-        GeoLib::OctTree<GeoLib::Point, 2>::createOctTree(*ps_ptr.front(),
-                                                         *ps_ptr.back(), eps));
+        GeoLib::OctTree<GeoLib::Point, 2>::createOctTree(
+            convertToEigen(*ps_ptr.front()), convertToEigen(*ps_ptr.back()),
+            eps));
 
 #ifndef NDEBUG
-    MathLib::Point3d const& ll(oct_tree->getLowerLeftCornerPoint());
-    MathLib::Point3d const& ur(oct_tree->getUpperRightCornerPoint());
+    Eigen::Vector3d const& ll(oct_tree->getLowerLeftCornerPoint());
+    Eigen::Vector3d const& ur(oct_tree->getUpperRightCornerPoint());
 
     EXPECT_EQ((*ps_ptr.front())[0], ll[0]);
     EXPECT_EQ((*ps_ptr.front())[1], ll[1]);
@@ -277,8 +286,8 @@ TEST_F(GeoLibOctTree, TestWithAlternatingPoints3d)
     ps_ptr.push_back(new GeoLib::Point(5 * small_displacement, 1, 0, 6));
 
     GeoLib::AABB const aabb(ps_ptr.cbegin(), ps_ptr.cend());
-    const MathLib::Point3d& min(aabb.getMinPoint());
-    const MathLib::Point3d& max(aabb.getMaxPoint());
+    auto const min(convertToEigen(aabb.getMinPoint()));
+    auto const max(convertToEigen(aabb.getMaxPoint()));
     std::unique_ptr<GeoLib::OctTree<GeoLib::Point, 8>> oct_tree(
         GeoLib::OctTree<GeoLib::Point, 8>::createOctTree(min, max, eps));
 
@@ -332,8 +341,8 @@ TEST_F(GeoLibOctTree, TestSmallDistanceDifferentLeaves)
 
     // create OctTree
     GeoLib::AABB const aabb(ps_ptr.cbegin(), ps_ptr.cend());
-    const MathLib::Point3d& min(aabb.getMinPoint());
-    const MathLib::Point3d& max(aabb.getMaxPoint());
+    auto const min(convertToEigen(aabb.getMinPoint()));
+    auto const max(convertToEigen(aabb.getMaxPoint()));
     std::unique_ptr<GeoLib::OctTree<GeoLib::Point, 2>> oct_tree(
         GeoLib::OctTree<GeoLib::Point, 2>::createOctTree(min, max, eps));
 
@@ -364,9 +373,10 @@ TEST_F(GeoLibOctTree, TestOctTreeWithTwoEqualPoints)
     double const eps(0.0);
 
     GeoLib::AABB aabb(ps_ptr.begin(), ps_ptr.end());
+    auto const min(convertToEigen(aabb.getMinPoint()));
+    auto const max(convertToEigen(aabb.getMaxPoint()));
     std::unique_ptr<GeoLib::OctTree<GeoLib::Point, 2>> oct_tree(
-        GeoLib::OctTree<GeoLib::Point, 2>::createOctTree(
-            aabb.getMinPoint(), aabb.getMaxPoint(), eps));
+        GeoLib::OctTree<GeoLib::Point, 2>::createOctTree(min, max, eps));
 
     GeoLib::Point* ret_pnt(nullptr);
     ASSERT_TRUE(oct_tree->addPoint(ps_ptr[0], ret_pnt));
@@ -382,9 +392,10 @@ TEST_F(GeoLibOctTree, TestOctTreeWithTwoEqualPointsOne)
     double const eps(0.0);
 
     GeoLib::AABB aabb(ps_ptr.begin(), ps_ptr.end());
+    auto const min(convertToEigen(aabb.getMinPoint()));
+    auto const max(convertToEigen(aabb.getMaxPoint()));
     std::unique_ptr<GeoLib::OctTree<GeoLib::Point, 2>> oct_tree(
-        GeoLib::OctTree<GeoLib::Point, 2>::createOctTree(
-            aabb.getMinPoint(), aabb.getMaxPoint(), eps));
+        GeoLib::OctTree<GeoLib::Point, 2>::createOctTree(min, max, eps));
 
     GeoLib::Point* ret_pnt(nullptr);
     ASSERT_TRUE(oct_tree->addPoint(ps_ptr[0], ret_pnt));
@@ -400,9 +411,10 @@ TEST_F(GeoLibOctTree, TestOctTreeOnCubicDomain)
     double const eps(0.0);
 
     GeoLib::AABB aabb(ps_ptr.begin(), ps_ptr.end());
+    auto const min(convertToEigen(aabb.getMinPoint()));
+    auto const max(convertToEigen(aabb.getMaxPoint()));
     std::unique_ptr<GeoLib::OctTree<GeoLib::Point, 2>> oct_tree(
-        GeoLib::OctTree<GeoLib::Point, 2>::createOctTree(
-            aabb.getMinPoint(), aabb.getMaxPoint(), eps));
+        GeoLib::OctTree<GeoLib::Point, 2>::createOctTree(min, max, eps));
 
     GeoLib::Point* ret_pnt(nullptr);
     ASSERT_TRUE(oct_tree->addPoint(ps_ptr[0], ret_pnt));
-- 
GitLab