From c10b0ac93c0daa0d6a3d8881b3c5cbaeed5f9987 Mon Sep 17 00:00:00 2001
From: ralfulrich <ralf.ulrich@kit.edu>
Date: Wed, 25 Nov 2020 14:39:44 +0100
Subject: [PATCH] fixed all of Remy's comments

---
 CMakeLists.txt                                |   1 -
 .../detail/framework/geometry/BaseVector.inl  |   2 +-
 .../framework/geometry/CoordinateSystem.inl   | 160 ++++++------
 .../detail/framework/geometry/FourVector.inl  |  11 +-
 corsika/detail/framework/geometry/Helix.inl   |  10 +-
 corsika/detail/framework/geometry/Line.inl    |  10 +-
 corsika/detail/framework/geometry/Point.inl   |  62 +++--
 .../framework/geometry/QuantityVector.inl     | 123 +++++----
 .../detail/framework/geometry/Trajectory.inl  |   6 +-
 corsika/detail/framework/geometry/Vector.inl  | 244 ++++++++++--------
 corsika/detail/framework/utility/COMBoost.inl |   6 +-
 corsika/framework/geometry/BaseVector.hpp     |  13 +-
 .../framework/geometry/CoordinateSystem.hpp   | 102 ++++++--
 corsika/framework/geometry/FourVector.hpp     |  28 +-
 corsika/framework/geometry/Helix.hpp          |   8 +-
 corsika/framework/geometry/Line.hpp           |  29 +--
 corsika/framework/geometry/Point.hpp          |  43 ++-
 corsika/framework/geometry/QuantityVector.hpp |  39 +--
 corsika/framework/geometry/Sphere.hpp         |  13 +-
 corsika/framework/geometry/Trajectory.hpp     |   6 +-
 corsika/framework/geometry/Vector.hpp         |  56 ++--
 examples/geometry_example.cpp                 |  12 +-
 tests/framework/testGeometry.cpp              | 126 +++++----
 23 files changed, 652 insertions(+), 458 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 411e5faa3..a6bfab39a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -232,7 +232,6 @@ add_subdirectory (documentation)
 #+++++++++++++++++++++++++++++
 # modules
 #
-set (NO_BOOST 1) # do not use libboost_iostream in CorsikaData
 add_subdirectory (modules/data)
 add_subdirectory (modules/pythia)
 add_subdirectory (modules/sibyll)
diff --git a/corsika/detail/framework/geometry/BaseVector.inl b/corsika/detail/framework/geometry/BaseVector.inl
index 7fbb362e1..e5bd52b19 100644
--- a/corsika/detail/framework/geometry/BaseVector.inl
+++ b/corsika/detail/framework/geometry/BaseVector.inl
@@ -26,7 +26,7 @@ namespace corsika {
   }
 
   template <typename TDimension>
-  QuantityVector<TDimension>& BaseVector<TDimension>::quantityVector() {
+  QuantityVector<TDimension>& BaseVector<TDimension>::getQuantityVector() {
     return quantityVector_;
   }
 
diff --git a/corsika/detail/framework/geometry/CoordinateSystem.inl b/corsika/detail/framework/geometry/CoordinateSystem.inl
index e8eae9b1a..ce5aa9e93 100644
--- a/corsika/detail/framework/geometry/CoordinateSystem.inl
+++ b/corsika/detail/framework/geometry/CoordinateSystem.inl
@@ -20,76 +20,7 @@
 
 namespace corsika {
 
-  inline CoordinateSystemPtr CoordinateSystem::translate(
-      QuantityVector<length_d> vector) const {
-    EigenTransform const translation{EigenTranslation(vector.eigenVector_)};
-
-    return std::make_shared<CoordinateSystem const>(*(new CoordinateSystem(
-        std::make_shared<CoordinateSystem const>(*this), translation)));
-  }
-
-  template <typename TDim>
-  CoordinateSystemPtr CoordinateSystem::rotateToZ(Vector<TDim> vVec) const {
-    auto const a = vVec.normalized()
-                       .getComponents(std::make_shared<CoordinateSystem const>(*this))
-                       .getEigenVector();
-    auto const a1 = a(0), a2 = a(1), a3 = a(2);
-
-    Eigen::Matrix3d A, B;
-
-    if (a3 > 0) {
-      auto const c = 1 / (1 + a3);
-      A << 1, 0, a1,                      // comment to prevent clang-format
-          0, 1, a2,                       // .
-          -a1, -a2, 1;                    // .
-      B << -a1 * a1 * c, -a1 * a2 * c, 0, // .
-          -a1 * a2 * c, -a2 * a2 * c, 0,  // .
-          0, 0, -(a1 * a1 + a2 * a2) * c; // .
-
-    } else {
-      auto const c = 1 / (1 - a3);
-      A << 1, 0, a1,                      // .
-          0, -1, a2,                      // .
-          a1, -a2, -1;                    // .
-      B << -a1 * a1 * c, +a1 * a2 * c, 0, // .
-          -a1 * a2 * c, +a2 * a2 * c, 0,  // .
-          0, 0, (a1 * a1 + a2 * a2) * c;  // .
-    }
-
-    return std::make_shared<CoordinateSystem const>(*(new CoordinateSystem(
-        std::make_shared<CoordinateSystem const>(*this), EigenTransform(A + B))));
-  }
-
-  template <typename TDim>
-  CoordinateSystemPtr CoordinateSystem::rotate(QuantityVector<TDim> axis,
-                                               double angle) const {
-    if (axis.eigenVector_.isZero()) {
-      throw std::runtime_error("null-vector given as axis parameter");
-    }
-
-    EigenTransform const rotation{
-        Eigen::AngleAxisd(angle, axis.eigenVector_.normalized())};
-
-    return std::make_shared<CoordinateSystem const>(
-        CoordinateSystem(std::make_shared<CoordinateSystem const>(*this), rotation));
-  }
-
-  template <typename TDim>
-  CoordinateSystemPtr CoordinateSystem::translateAndRotate(
-      QuantityVector<length_d> translation, QuantityVector<TDim> axis, double angle) {
-    if (axis.eigenVector_.isZero()) {
-      throw std::runtime_error("null-vector given as axis parameter");
-    }
-
-    EigenTransform const transf{Eigen::AngleAxisd(angle, axis.eigenVector_.normalized()) *
-                                EigenTranslation(translation.eigenVector_)};
-
-    return std::make_shared<CoordinateSystem const>(CoordinateSystem(*this, transf));
-  }
-
-  CoordinateSystemPtr CoordinateSystem::getReferenceCS() const {
-    return referenceCS_; //*(referenceCS_.get());
-  }
+  CoordinateSystemPtr CoordinateSystem::getReferenceCS() const { return referenceCS_; }
 
   EigenTransform const& CoordinateSystem::getTransform() const { return transf_; }
 
@@ -101,30 +32,27 @@ namespace corsika {
     return !(cs == *this);
   }
 
-  /**
-   * returns the transformation matrix necessary to transform primitives with coordinates
-   * in \a pFrom to \a pTo, e.g.
-   * \f$ \vec{v}^{\text{(to)}} = \mathcal{M} \vec{v}^{\text{(from)}} \f$
-   * (\f$ \vec{v}^{(.)} \f$ denotes the coordinates/components of the component in
-   * the indicated CoordinateSystem).
-   */
-  inline EigenTransform getTransformation(CoordinateSystemPtr pFrom,
-                                          CoordinateSystemPtr pTo) {
+  /// find transformation between two CS, using most optimal common base
+  inline EigenTransform get_transformation(CoordinateSystemPtr const& pFrom,
+                                           CoordinateSystemPtr const& pTo) {
     CoordinateSystemPtr a{pFrom};
     CoordinateSystemPtr b{pTo};
     CoordinateSystemPtr commonBase{nullptr};
 
-    while (a != b && b != nullptr) {
-      a = pFrom;
+    while (a != b && b) {
 
-      while (a != b && a != nullptr) { a = a->getReferenceCS(); }
+      // traverse pFrom
+      a = pFrom;
+      while (a != b && a) {
+        a = a->getReferenceCS();
+      }
 
       if (a == b) break;
 
       b = b->getReferenceCS();
     }
 
-    if (a == b && a != nullptr) {
+    if (a == b && a) {
       commonBase = a;
 
     } else {
@@ -149,4 +77,70 @@ namespace corsika {
     return t;
   }
 
+  inline CoordinateSystemPtr make_translation(CoordinateSystemPtr const& cs,
+                                              QuantityVector<length_d> const& vector) {
+    EigenTransform const translation{EigenTranslation(vector.getEigenVector())};
+    return std::make_shared<CoordinateSystem const>(CoordinateSystem(cs, translation));
+  }
+
+  template <typename TDim>
+  inline CoordinateSystemPtr make_rotationToZ(CoordinateSystemPtr const& cs,
+                                              Vector<TDim> const& vVec) {
+    auto const a = vVec.normalized().getComponents(cs).getEigenVector();
+    auto const a1 = a(0), a2 = a(1), a3 = a(2);
+
+    Eigen::Matrix3d A, B;
+
+    if (a3 > 0) {
+      auto const c = 1 / (1 + a3);
+      A << 1, 0, a1,                      // comment to prevent clang-format
+          0, 1, a2,                       // .
+          -a1, -a2, 1;                    // .
+      B << -a1 * a1 * c, -a1 * a2 * c, 0, // .
+          -a1 * a2 * c, -a2 * a2 * c, 0,  // .
+          0, 0, -(a1 * a1 + a2 * a2) * c; // .
+
+    } else {
+      auto const c = 1 / (1 - a3);
+      A << 1, 0, a1,                      // .
+          0, -1, a2,                      // .
+          a1, -a2, -1;                    // .
+      B << -a1 * a1 * c, +a1 * a2 * c, 0, // .
+          -a1 * a2 * c, +a2 * a2 * c, 0,  // .
+          0, 0, (a1 * a1 + a2 * a2) * c;  // .
+    }
+
+    return std::make_shared<CoordinateSystem const>(
+        CoordinateSystem(cs, EigenTransform(A + B)));
+  }
+
+  template <typename TDim>
+  inline CoordinateSystemPtr make_rotation(CoordinateSystemPtr const& cs,
+                                           QuantityVector<TDim> const& axis,
+                                           double const angle) {
+    if (axis.getEigenVector().isZero()) {
+      throw std::runtime_error("null-vector given as axis parameter");
+    }
+
+    EigenTransform const rotation{
+        Eigen::AngleAxisd(angle, axis.getEigenVector().normalized())};
+
+    return std::make_shared<CoordinateSystem const>(CoordinateSystem(cs, rotation));
+  }
+
+  template <typename TDim>
+  inline CoordinateSystemPtr make_translationAndRotation(
+      CoordinateSystemPtr const& cs, QuantityVector<length_d> const& translation,
+      QuantityVector<TDim> const& axis, double const angle) {
+    if (axis.getEigenVector().isZero()) {
+      throw std::runtime_error("null-vector given as axis parameter");
+    }
+
+    EigenTransform const transf{
+        Eigen::AngleAxisd(angle, axis.getEigenVector().normalized()) *
+        EigenTranslation(translation.getEigenVector())};
+
+    return std::make_shared<CoordinateSystem const>(CoordinateSystem(cs, transf));
+  }
+
 } // namespace corsika
diff --git a/corsika/detail/framework/geometry/FourVector.inl b/corsika/detail/framework/geometry/FourVector.inl
index bd39af001..454854288 100644
--- a/corsika/detail/framework/geometry/FourVector.inl
+++ b/corsika/detail/framework/geometry/FourVector.inl
@@ -1,8 +1,6 @@
 /*
  * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
  *
- * See file AUTHORS for a list of contributors.
- *
  * This software is distributed under the terms of the GNU General Public
  * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
  * the license.
@@ -115,4 +113,13 @@ namespace corsika {
       return timeLike_ * timeLike_;
   }
 
+  template <typename TTimeType, typename TSpaceVecType>
+  inline std::ostream& operator<<(std::ostream& os,
+                                  corsika::FourVector<TTimeType, TSpaceVecType> const qv) {
+
+    os << '(' << qv.timeLike_ << ", " << qv.spaceLike_ << ") ";
+    return os;
+  }
+
+
 } // namespace corsika
diff --git a/corsika/detail/framework/geometry/Helix.inl b/corsika/detail/framework/geometry/Helix.inl
index 09cdd456c..fe740cf8e 100644
--- a/corsika/detail/framework/geometry/Helix.inl
+++ b/corsika/detail/framework/geometry/Helix.inl
@@ -11,29 +11,29 @@
 #pragma once
 
 #include <corsika/framework/geometry/Point.hpp>
-#include <cmath>
 #include <corsika/framework/core/PhysicalUnits.hpp>
 #include <corsika/framework/geometry/Vector.hpp>
+#include <cmath>
 
 namespace corsika {
 
   LengthType Helix::getRadius() const { return radius_; }
 
-  Point Helix::getPosition(TimeType t) const {
+  Point Helix::getPosition(TimeType const t) const {
     return r0_ + vPar_ * t +
            (vPerp_ * (std::cos(omegaC_ * t) - 1) + uPerp_ * std::sin(omegaC_ * t)) /
                omegaC_;
   }
 
-  Point Helix::getPositionFromArclength(LengthType l) const {
+  Point Helix::getPositionFromArclength(LengthType const l) const {
     return getPosition(getTimeFromArclength(l));
   }
 
-  LengthType Helix::getArcLength(TimeType t1, TimeType t2) const {
+  LengthType Helix::getArcLength(TimeType const t1, TimeType const t2) const {
     return (vPar_ + vPerp_).getNorm() * (t2 - t1);
   }
 
-  TimeType Helix::getTimeFromArclength(LengthType l) const {
+  TimeType Helix::getTimeFromArclength(LengthType const l) const {
     return l / (vPar_ + vPerp_).getNorm();
   }
 
diff --git a/corsika/detail/framework/geometry/Line.inl b/corsika/detail/framework/geometry/Line.inl
index 13f0292d1..e3a5ef6ee 100644
--- a/corsika/detail/framework/geometry/Line.inl
+++ b/corsika/detail/framework/geometry/Line.inl
@@ -1,8 +1,6 @@
 /*
  * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
  *
- * See file AUTHORS for a list of contributors.
- *
  * This software is distributed under the terms of the GNU General Public
  * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
  * the license.
@@ -16,17 +14,17 @@
 
 namespace corsika {
 
-  Point Line::getPosition(TimeType t) const { return start_point_ + velocity_ * t; }
+  Point Line::getPosition(TimeType const t) const { return start_point_ + velocity_ * t; }
 
-  Point Line::getPositionFromArclength(LengthType l) const {
+  Point Line::getPositionFromArclength(LengthType const l) const {
     return start_point_ + velocity_.normalized() * l;
   }
 
-  LengthType Line::getArcLength(TimeType t1, TimeType t2) const {
+  LengthType Line::getArcLength(TimeType const t1, TimeType const t2) const {
     return velocity_.getNorm() * (t2 - t1);
   }
 
-  TimeType Line::getTimeFromArclength(LengthType t) const {
+  TimeType Line::getTimeFromArclength(LengthType const t) const {
     return t / velocity_.getNorm();
   }
 
diff --git a/corsika/detail/framework/geometry/Point.inl b/corsika/detail/framework/geometry/Point.inl
index 9a24699f6..119de7f04 100644
--- a/corsika/detail/framework/geometry/Point.inl
+++ b/corsika/detail/framework/geometry/Point.inl
@@ -17,72 +17,82 @@
 
 namespace corsika {
 
-  auto Point::getCoordinates() const { return BaseVector<length_d>::getQuantityVector(); }
+  QuantityVector<length_d> const& Point::getCoordinates() const {
+    return BaseVector<length_d>::getQuantityVector();
+  }
+
+  QuantityVector<length_d>& Point::getCoordinates() {
+    return BaseVector<length_d>::getQuantityVector();
+  }
 
-  inline LengthType Point::getX(CoordinateSystemPtr cs) const {
-    if (*cs == *BaseVector<length_d>::getCoordinateSystem()) {
+  inline LengthType Point::getX(CoordinateSystemPtr const& pCS) const {
+    CoordinateSystemPtr const& cs = BaseVector<length_d>::getCoordinateSystem();
+    if (*pCS == *cs) {
       return BaseVector<length_d>::getQuantityVector().getX();
     } else {
       return QuantityVector<length_d>(
-                 getTransformation(BaseVector<length_d>::getCoordinateSystem(), cs) *
+                 get_transformation(cs, pCS) *
                  BaseVector<length_d>::getQuantityVector().eigenVector_)
           .getX();
     }
   }
 
-  inline LengthType Point::getY(CoordinateSystemPtr cs) const {
-    if (*cs == *BaseVector<length_d>::getCoordinateSystem()) {
+  inline LengthType Point::getY(CoordinateSystemPtr const& pCS) const {
+    CoordinateSystemPtr const& cs = BaseVector<length_d>::getCoordinateSystem();
+    if (*pCS == *cs) {
       return BaseVector<length_d>::getQuantityVector().getY();
     } else {
       return QuantityVector<length_d>(
-                 getTransformation(BaseVector<length_d>::getCoordinateSystem(), cs) *
+                 get_transformation(cs, pCS) *
                  BaseVector<length_d>::getQuantityVector().eigenVector_)
           .getY();
     }
   }
 
-  inline LengthType Point::getZ(CoordinateSystemPtr cs) const {
-    if (*cs == *BaseVector<length_d>::getCoordinateSystem()) {
+  inline LengthType Point::getZ(CoordinateSystemPtr const& pCS) const {
+    CoordinateSystemPtr const& cs = BaseVector<length_d>::getCoordinateSystem();
+    if (*pCS == *cs) {
       return BaseVector<length_d>::getQuantityVector().getZ();
     } else {
       return QuantityVector<length_d>(
-                 getTransformation(BaseVector<length_d>::getCoordinateSystem(), cs) *
+                 get_transformation(cs, pCS) *
                  BaseVector<length_d>::getQuantityVector().eigenVector_)
           .getZ();
     }
   }
 
   /// this always returns a QuantityVector as triple
-  auto Point::getCoordinates(CoordinateSystemPtr pCS) const {
-    if (*pCS == *BaseVector<length_d>::getCoordinateSystem()) {
+  QuantityVector<length_d> Point::getCoordinates(CoordinateSystemPtr const& pCS) const {
+    CoordinateSystemPtr const& cs = BaseVector<length_d>::getCoordinateSystem();
+    if (*pCS == *cs) {
       return BaseVector<length_d>::getQuantityVector();
     } else {
       return QuantityVector<length_d>(
-          getTransformation(BaseVector<length_d>::getCoordinateSystem(), pCS) *
+          get_transformation(cs, pCS) *
           BaseVector<length_d>::getQuantityVector().eigenVector_);
     }
   }
 
-  /*!
-   * transforms the Point into another CoordinateSystem by changing its
-   * coordinates interally
-   */
-  void Point::rebase(CoordinateSystemPtr pCS) {
-    BaseVector<length_d>::quantityVector() = getCoordinates(pCS);
+  /// this always returns a QuantityVector as triple
+  QuantityVector<length_d>& Point::getCoordinates(CoordinateSystemPtr const& pCS) {
+    if (*pCS != *BaseVector<length_d>::getCoordinateSystem()) { rebase(pCS); }
+    return BaseVector<length_d>::getQuantityVector();
+  }
+
+  void Point::rebase(CoordinateSystemPtr const& pCS) {
+    BaseVector<length_d>::setQuantityVector(QuantityVector<length_d>(
+        get_transformation(BaseVector<length_d>::getCoordinateSystem(), pCS) *
+        BaseVector<length_d>::getQuantityVector().eigenVector_));
     BaseVector<length_d>::setCoordinateSystem(pCS);
   }
 
   Point Point::operator+(Vector<length_d> const& pVec) const {
-    return Point(BaseVector<length_d>::getCoordinateSystem(),
-                 getCoordinates() +
-                     pVec.getComponents(BaseVector<length_d>::getCoordinateSystem()));
+    CoordinateSystemPtr const& cs = BaseVector<length_d>::getCoordinateSystem();
+    return Point(cs, getCoordinates() + pVec.getComponents(cs));
   }
 
-  /*!
-   * returns the distance Vector between two points
-   */
   Vector<length_d> Point::operator-(Point const& pB) const {
-    CoordinateSystemPtr cs = BaseVector<length_d>::getCoordinateSystem();
+    CoordinateSystemPtr const& cs = BaseVector<length_d>::getCoordinateSystem();
     return Vector<length_d>(cs, getCoordinates() - pB.getCoordinates(cs));
   }
 
diff --git a/corsika/detail/framework/geometry/QuantityVector.inl b/corsika/detail/framework/geometry/QuantityVector.inl
index 2b206d3e3..3b5118abe 100644
--- a/corsika/detail/framework/geometry/QuantityVector.inl
+++ b/corsika/detail/framework/geometry/QuantityVector.inl
@@ -18,58 +18,63 @@
 
 namespace corsika {
 
-  template <typename dim>
-  inline typename QuantityVector<dim>::quantity_type QuantityVector<dim>::operator[](
-      size_t index) const {
+  template <typename TDimension>
+  inline typename QuantityVector<TDimension>::quantity_type QuantityVector<TDimension>::
+  operator[](size_t const index) const {
     return quantity_type(phys::units::detail::magnitude_tag, eigenVector_[index]);
   }
 
-  template <typename dim>
-  inline typename QuantityVector<dim>::quantity_type QuantityVector<dim>::getX() const {
+  template <typename TDimension>
+  inline typename QuantityVector<TDimension>::quantity_type
+  QuantityVector<TDimension>::getX() const {
     return (*this)[0];
   }
 
-  template <typename dim>
-  inline typename QuantityVector<dim>::quantity_type QuantityVector<dim>::getY() const {
+  template <typename TDimension>
+  inline typename QuantityVector<TDimension>::quantity_type
+  QuantityVector<TDimension>::getY() const {
     return (*this)[1];
   }
 
-  template <typename dim>
-  inline typename QuantityVector<dim>::quantity_type QuantityVector<dim>::getZ() const {
+  template <typename TDimension>
+  inline typename QuantityVector<TDimension>::quantity_type
+  QuantityVector<TDimension>::getZ() const {
     return (*this)[2];
   }
 
-  template <typename dim>
-  inline typename QuantityVector<dim>::quantity_type QuantityVector<dim>::getNorm()
-      const {
+  template <typename TDimension>
+  inline typename QuantityVector<TDimension>::quantity_type
+  QuantityVector<TDimension>::getNorm() const {
     return quantity_type(phys::units::detail::magnitude_tag, eigenVector_.norm());
   }
 
-  template <typename dim>
-  inline auto QuantityVector<dim>::getSquaredNorm() const {
+  template <typename TDimension>
+  inline typename QuantityVector<TDimension>::quantity_square_type
+  QuantityVector<TDimension>::getSquaredNorm() const {
     using QuantitySquared =
         decltype(std::declval<quantity_type>() * std::declval<quantity_type>());
     return QuantitySquared(phys::units::detail::magnitude_tag,
                            eigenVector_.squaredNorm());
   }
 
-  template <typename dim>
-  inline QuantityVector<dim> QuantityVector<dim>::operator+(
-      QuantityVector<dim> const& pQVec) const {
-    return QuantityVector<dim>(eigenVector_ + pQVec.eigenVector_);
+  template <typename TDimension>
+  inline QuantityVector<TDimension> QuantityVector<TDimension>::operator+(
+      QuantityVector<TDimension> const& pQVec) const {
+    return QuantityVector<TDimension>(eigenVector_ + pQVec.eigenVector_);
   }
 
-  template <typename dim>
-  inline QuantityVector<dim> QuantityVector<dim>::operator-(
-      QuantityVector<dim> const& pQVec) const {
-    return QuantityVector<dim>(eigenVector_ - pQVec.eigenVector_);
+  template <typename TDimension>
+  inline QuantityVector<TDimension> QuantityVector<TDimension>::operator-(
+      QuantityVector<TDimension> const& pQVec) const {
+    return QuantityVector<TDimension>(eigenVector_ - pQVec.eigenVector_);
   }
 
-  template <typename dim>
-  template <typename ScalarDim>
-  inline auto QuantityVector<dim>::operator*(
-      phys::units::quantity<ScalarDim, double> const p) const {
-    using ResQuantity = phys::units::detail::Product<ScalarDim, dim, double, double>;
+  template <typename TDimension>
+  template <typename TScalarDim>
+  inline auto QuantityVector<TDimension>::operator*(
+      phys::units::quantity<TScalarDim, double> const p) const {
+    using ResQuantity =
+        phys::units::detail::Product<TScalarDim, TDimension, double, double>;
 
     if constexpr (std::is_same<ResQuantity, double>::value) // result dimensionless, not
                                                             // a "quantity_type" anymore
@@ -81,69 +86,73 @@ namespace corsika {
     }
   }
 
-  template <typename dim>
-  template <typename ScalarDim>
-  inline auto QuantityVector<dim>::operator/(
-      phys::units::quantity<ScalarDim, double> const p) const {
+  template <typename TDimension>
+  template <typename TScalarDim>
+  inline auto QuantityVector<TDimension>::operator/(
+      phys::units::quantity<TScalarDim, double> const p) const {
     return (*this) * (1 / p);
   }
 
-  template <typename dim>
-  inline auto QuantityVector<dim>::operator*(double const p) const {
-    return QuantityVector<dim>(eigenVector_ * p);
+  template <typename TDimension>
+  inline auto QuantityVector<TDimension>::operator*(double const p) const {
+    return QuantityVector<TDimension>(eigenVector_ * p);
   }
 
-  template <typename dim>
-  inline auto QuantityVector<dim>::operator/(double const p) const {
-    return QuantityVector<dim>(eigenVector_ / p);
+  template <typename TDimension>
+  inline auto QuantityVector<TDimension>::operator/(double const p) const {
+    return QuantityVector<TDimension>(eigenVector_ / p);
   }
 
-  template <typename dim>
-  inline auto& QuantityVector<dim>::operator/=(double const p) {
+  template <typename TDimension>
+  inline auto& QuantityVector<TDimension>::operator/=(double const p) {
     eigenVector_ /= p;
     return *this;
   }
 
-  template <typename dim>
-  inline auto& QuantityVector<dim>::operator*=(double const p) {
+  template <typename TDimension>
+  inline auto& QuantityVector<TDimension>::operator*=(double const p) {
     eigenVector_ *= p;
     return *this;
   }
 
-  template <typename dim>
-  inline auto& QuantityVector<dim>::operator+=(QuantityVector<dim> const& pQVec) {
+  template <typename TDimension>
+  inline auto& QuantityVector<TDimension>::operator+=(
+      QuantityVector<TDimension> const& pQVec) {
     eigenVector_ += pQVec.eigenVector_;
     return *this;
   }
 
-  template <typename dim>
-  inline auto& QuantityVector<dim>::operator-=(QuantityVector<dim> const& pQVec) {
+  template <typename TDimension>
+  inline auto& QuantityVector<TDimension>::operator-=(
+      QuantityVector<TDimension> const& pQVec) {
     eigenVector_ -= pQVec.eigenVector_;
     return *this;
   }
 
-  template <typename dim>
-  inline auto& QuantityVector<dim>::operator-() const {
-    return QuantityVector<dim>(-eigenVector_);
+  template <typename TDimension>
+  inline auto& QuantityVector<TDimension>::operator-() const {
+    return QuantityVector<TDimension>(-eigenVector_);
   }
 
-  template <typename dim>
-  inline auto QuantityVector<dim>::normalized() const {
-    return QuantityVector<dim>(eigenVector_.normalized());
+  template <typename TDimension>
+  inline auto QuantityVector<TDimension>::normalized() const {
+    return QuantityVector<TDimension>(eigenVector_.normalized());
   }
 
-  template <typename dim>
-  inline auto QuantityVector<dim>::operator==(QuantityVector<dim> const& p) const {
+  template <typename TDimension>
+  inline auto QuantityVector<TDimension>::operator==(
+      QuantityVector<TDimension> const& p) const {
     return eigenVector_ == p.eigenVector_;
   }
 
-  template <typename dim>
-  inline std::ostream& operator<<(std::ostream& os, corsika::QuantityVector<dim> qv) {
-    using quantity_type = phys::units::quantity<dim, double>;
+  template <typename TDimension>
+  inline std::ostream& operator<<(std::ostream& os,
+                                  corsika::QuantityVector<TDimension> const qv) {
+    using quantity_type = phys::units::quantity<TDimension, double>;
 
     os << '(' << qv.eigenVector_(0) << ' ' << qv.eigenVector_(1) << ' '
        << qv.eigenVector_(2) << ") "
-       << phys::units::to_unit_symbol<dim, double>(
+       << phys::units::to_unit_symbol<TDimension, double>(
               quantity_type(phys::units::detail::magnitude_tag, 1));
     return os;
   }
diff --git a/corsika/detail/framework/geometry/Trajectory.inl b/corsika/detail/framework/geometry/Trajectory.inl
index 89b02ad95..a43010c19 100644
--- a/corsika/detail/framework/geometry/Trajectory.inl
+++ b/corsika/detail/framework/geometry/Trajectory.inl
@@ -17,7 +17,7 @@
 namespace corsika {
 
   template <typename TType>
-  Point Trajectory<TType>::getPosition(double u) const {
+  Point Trajectory<TType>::getPosition(double const u) const {
     return TType::getPosition(timeLength_ * u);
   }
 
@@ -32,14 +32,14 @@ namespace corsika {
   }
 
   template <typename TType>
-  LengthType Trajectory<TType>::getDistance(TimeType t) const {
+  LengthType Trajectory<TType>::getDistance(TimeType const t) const {
     assert(t <= timeLength_);
     assert(t >= 0 * second);
     return TType::getArcLength(0 * second, t);
   }
 
   template <typename TType>
-  void Trajectory<TType>::getLimitEndTo(LengthType limit) {
+  void Trajectory<TType>::getLimitEndTo(LengthType const limit) {
     timeLength_ = TType::getTimeFromArclength(limit);
   }
 
diff --git a/corsika/detail/framework/geometry/Vector.inl b/corsika/detail/framework/geometry/Vector.inl
index 1df45dfc6..d11250be8 100644
--- a/corsika/detail/framework/geometry/Vector.inl
+++ b/corsika/detail/framework/geometry/Vector.inl
@@ -1,8 +1,6 @@
 /*
  * (c) Copyright 2018 CORSIKA Project, corsika-project@lists.kit.edu
  *
- * See file AUTHORS for a list of contributors.
- *
  * This software is distributed under the terms of the GNU General Public
  * Licence version 3 (GPL Version 3). See file LICENSE for a full version of
  * the license.
@@ -16,183 +14,209 @@
 
 namespace corsika {
 
-  template <typename dim>
-  QuantityVector<dim> Vector<dim>::getComponents() const {
-    return BaseVector<dim>::getQuantityVector();
+  template <typename TDimension>
+  inline QuantityVector<TDimension> const& Vector<TDimension>::getComponents() const {
+    return BaseVector<TDimension>::getQuantityVector();
+  }
+
+  template <typename TDimension>
+  inline QuantityVector<TDimension>& Vector<TDimension>::getComponents() {
+    return BaseVector<TDimension>::getQuantityVector();
   }
 
-  template <typename dim>
-  QuantityVector<dim> Vector<dim>::getComponents(CoordinateSystemPtr pCS) const {
-    if (*pCS == *BaseVector<dim>::getCoordinateSystem()) { // FIXME
-      return BaseVector<dim>::getQuantityVector();
+  template <typename TDimension>
+  inline QuantityVector<TDimension> Vector<TDimension>::getComponents(
+      CoordinateSystemPtr const& pCS) const {
+    if (*pCS == *BaseVector<TDimension>::getCoordinateSystem()) {
+      return BaseVector<TDimension>::getQuantityVector();
     } else {
-      return QuantityVector<dim>(
-          getTransformation(BaseVector<dim>::getCoordinateSystem(), pCS).linear() *
-          BaseVector<dim>::getQuantityVector().eigenVector_);
+      return QuantityVector<TDimension>(
+          get_transformation(BaseVector<TDimension>::getCoordinateSystem(), pCS)
+              .linear() *
+          BaseVector<TDimension>::getQuantityVector().eigenVector_);
     }
   }
 
-  template <typename dim>
-  inline typename Vector<dim>::quantity_type Vector<dim>::getX(
-      CoordinateSystemPtr pCS) const {
-    if (*pCS == *BaseVector<dim>::getCoordinateSystem()) {
-      return BaseVector<dim>::getQuantityVector()[0];
+  template <typename TDimension>
+  inline QuantityVector<TDimension>& Vector<TDimension>::getComponents(
+      CoordinateSystemPtr const& pCS) {
+    if (*pCS != *BaseVector<TDimension>::getCoordinateSystem()) { rebase(pCS); }
+    return BaseVector<TDimension>::getQuantityVector();
+  }
+
+  template <typename TDimension>
+  inline typename Vector<TDimension>::quantity_type Vector<TDimension>::getX(
+      CoordinateSystemPtr const& pCS) const {
+    if (*pCS == *BaseVector<TDimension>::getCoordinateSystem()) {
+      return BaseVector<TDimension>::getQuantityVector()[0];
     } else {
-      return QuantityVector<dim>(
-          getTransformation(BaseVector<dim>::getCoordinateSystem(), pCS).linear() *
-          BaseVector<dim>::getQuantityVector().eigenVector_)[0];
+      return QuantityVector<TDimension>(
+          get_transformation(BaseVector<TDimension>::getCoordinateSystem(), pCS)
+              .linear() *
+          BaseVector<TDimension>::getQuantityVector().eigenVector_)[0];
     }
   }
 
-  template <typename dim>
-  inline typename Vector<dim>::quantity_type Vector<dim>::getY(
-      CoordinateSystemPtr pCS) const {
-    if (*pCS == *BaseVector<dim>::getCoordinateSystem()) {
-      return BaseVector<dim>::getQuantityVector()[1];
+  template <typename TDimension>
+  inline typename Vector<TDimension>::quantity_type Vector<TDimension>::getY(
+      CoordinateSystemPtr const& pCS) const {
+    if (*pCS == *BaseVector<TDimension>::getCoordinateSystem()) {
+      return BaseVector<TDimension>::getQuantityVector()[1];
     } else {
-      return QuantityVector<dim>(
-          getTransformation(BaseVector<dim>::getCoordinateSystem(), pCS).linear() *
-          BaseVector<dim>::getQuantityVector().eigenVector_)[1];
+      return QuantityVector<TDimension>(
+          get_transformation(BaseVector<TDimension>::getCoordinateSystem(), pCS)
+              .linear() *
+          BaseVector<TDimension>::getQuantityVector().eigenVector_)[1];
     }
   }
 
-  template <typename dim>
-  inline typename Vector<dim>::quantity_type Vector<dim>::getZ(
-      CoordinateSystemPtr pCS) const {
-    if (*pCS == *BaseVector<dim>::getCoordinateSystem()) {
-      return BaseVector<dim>::getQuantityVector()[2];
+  template <typename TDimension>
+  inline typename Vector<TDimension>::quantity_type Vector<TDimension>::getZ(
+      CoordinateSystemPtr const& pCS) const {
+    if (*pCS == *BaseVector<TDimension>::getCoordinateSystem()) {
+      return BaseVector<TDimension>::getQuantityVector()[2];
     } else {
-      return QuantityVector<dim>(
-          getTransformation(BaseVector<dim>::getCoordinateSystem(), pCS).linear() *
-          BaseVector<dim>::getQuantityVector().eigenVector_)[2];
+      return QuantityVector<TDimension>(
+          get_transformation(BaseVector<TDimension>::getCoordinateSystem(), pCS)
+              .linear() *
+          BaseVector<TDimension>::getQuantityVector().eigenVector_)[2];
     }
   }
 
-  template <typename dim>
-  void Vector<dim>::rebase(CoordinateSystemPtr pCS) {
-    BaseVector<dim>::quantityVector() = getComponents(pCS);
-    BaseVector<dim>::setCoordinateSystem(pCS);
+  template <typename TDimension>
+  void Vector<TDimension>::rebase(CoordinateSystemPtr const& pCS) {
+    BaseVector<TDimension>::setQuantityVector(QuantityVector<TDimension>(
+        get_transformation(BaseVector<TDimension>::getCoordinateSystem(), pCS).linear() *
+        BaseVector<TDimension>::getQuantityVector().eigenVector_));
+    BaseVector<TDimension>::setCoordinateSystem(pCS);
   }
 
-  template <typename dim>
-  inline typename Vector<dim>::quantity_type Vector<dim>::getNorm() const {
-    return BaseVector<dim>::getQuantityVector().getNorm();
+  template <typename TDimension>
+  inline typename Vector<TDimension>::quantity_type Vector<TDimension>::getNorm() const {
+    return BaseVector<TDimension>::getQuantityVector().getNorm();
   }
 
-  template <typename dim>
-  auto Vector<dim>::getSquaredNorm() const {
-    return BaseVector<dim>::getQuantityVector().getSquaredNorm();
+  template <typename TDimension>
+  inline typename Vector<TDimension>::quantity_square_type
+  Vector<TDimension>::getSquaredNorm() const {
+    return BaseVector<TDimension>::getQuantityVector().getSquaredNorm();
   }
 
-  template <typename dim>
-  template <typename dim2>
-  auto Vector<dim>::getParallelProjectionOnto(Vector<dim2> const& pVec,
-                                              CoordinateSystemPtr pCS) const {
+  template <typename TDimension>
+  template <typename TDimension2>
+  auto Vector<TDimension>::getParallelProjectionOnto(
+      Vector<TDimension2> const& pVec, CoordinateSystemPtr const& pCS) const {
     auto const ourCompVec = getComponents(pCS);
     auto const otherCompVec = pVec.getComponents(pCS);
     auto const& a = ourCompVec.eigenVector_;
     auto const& b = otherCompVec.eigenVector_;
 
-    return Vector<dim>(pCS, QuantityVector<dim>(b * ((a.dot(b)) / b.squaredNorm())));
+    return Vector<TDimension>(
+        pCS, QuantityVector<TDimension>(b * ((a.dot(b)) / b.squaredNorm())));
   }
 
-  template <typename dim>
-  template <typename dim2>
-  auto Vector<dim>::getParallelProjectionOnto(Vector<dim2> const& pVec) const {
-    return getParallelProjectionOnto<dim2>(pVec, BaseVector<dim>::getCoordinateSystem());
+  template <typename TDimension>
+  template <typename TDimension2>
+  auto Vector<TDimension>::getParallelProjectionOnto(
+      Vector<TDimension2> const& pVec) const {
+    return getParallelProjectionOnto<TDimension2>(
+        pVec, BaseVector<TDimension>::getCoordinateSystem());
   }
 
-  template <typename dim>
-  Vector<dim> Vector<dim>::operator+(Vector<dim> const& pVec) const {
-    auto const components = getComponents(BaseVector<dim>::getCoordinateSystem()) +
-                            pVec.getComponents(BaseVector<dim>::getCoordinateSystem());
-    return Vector<dim>(BaseVector<dim>::getCoordinateSystem(), components);
+  template <typename TDimension>
+  Vector<TDimension> Vector<TDimension>::operator+(Vector<TDimension> const& pVec) const {
+    CoordinateSystemPtr const& cs = BaseVector<TDimension>::getCoordinateSystem();
+    auto const components = getComponents(cs) + pVec.getComponents(cs);
+    return Vector<TDimension>(BaseVector<TDimension>::getCoordinateSystem(), components);
   }
 
-  template <typename dim>
-  Vector<dim> Vector<dim>::operator-(Vector<dim> const& pVec) const {
-    auto const components =
-        getComponents() - pVec.getComponents(BaseVector<dim>::getCoordinateSystem());
-    return Vector<dim>(BaseVector<dim>::getCoordinateSystem(), components);
+  template <typename TDimension>
+  Vector<TDimension> Vector<TDimension>::operator-(Vector<TDimension> const& pVec) const {
+    CoordinateSystemPtr const& cs = BaseVector<TDimension>::getCoordinateSystem();
+    return Vector<TDimension>(cs, getComponents() - pVec.getComponents(cs));
   }
 
-  template <typename dim>
-  auto& Vector<dim>::operator*=(double const p) {
-    BaseVector<dim>::quantityVector() *= p;
+  template <typename TDimension>
+  auto& Vector<TDimension>::operator*=(double const p) {
+    BaseVector<TDimension>::getQuantityVector() *= p;
     return *this;
   }
 
-  template <typename dim>
-  template <typename ScalarDim>
-  auto Vector<dim>::operator*(phys::units::quantity<ScalarDim, double> const p) const {
-    using ProdDim = phys::units::detail::product_d<dim, ScalarDim>;
+  template <typename TDimension>
+  template <typename TScalarDim>
+  auto Vector<TDimension>::operator*(
+      phys::units::quantity<TScalarDim, double> const p) const {
+    using ProdDim = phys::units::detail::product_d<TDimension, TScalarDim>;
 
-    return Vector<ProdDim>(BaseVector<dim>::getCoordinateSystem(),
-                           BaseVector<dim>::getQuantityVector() * p);
+    return Vector<ProdDim>(BaseVector<TDimension>::getCoordinateSystem(),
+                           BaseVector<TDimension>::getQuantityVector() * p);
   }
 
-  template <typename dim>
-  template <typename ScalarDim>
-  auto Vector<dim>::operator/(phys::units::quantity<ScalarDim, double> const p) const {
+  template <typename TDimension>
+  template <typename TScalarDim>
+  auto Vector<TDimension>::operator/(
+      phys::units::quantity<TScalarDim, double> const p) const {
     return (*this) * (1 / p);
   }
 
-  template <typename dim>
-  auto Vector<dim>::operator*(double const p) const {
-    return Vector<dim>(BaseVector<dim>::getCoordinateSystem(),
-                       BaseVector<dim>::getQuantityVector() * p);
+  template <typename TDimension>
+  auto Vector<TDimension>::operator*(double const p) const {
+    return Vector<TDimension>(BaseVector<TDimension>::getCoordinateSystem(),
+                              BaseVector<TDimension>::getQuantityVector() * p);
   }
 
-  template <typename dim>
-  auto Vector<dim>::operator/(double const p) const {
-    return Vector<dim>(BaseVector<dim>::getCoordinateSystem(),
-                       BaseVector<dim>::quantityVector() / p);
+  template <typename TDimension>
+  auto Vector<TDimension>::operator/(double const p) const {
+    return Vector<TDimension>(BaseVector<TDimension>::getCoordinateSystem(),
+                              BaseVector<TDimension>::quantityVector() / p);
   }
 
-  template <typename dim>
-  auto& Vector<dim>::operator+=(Vector<dim> const& pVec) {
-    BaseVector<dim>::quantityVector() +=
-        pVec.getComponents(BaseVector<dim>::getCoordinateSystem());
+  template <typename TDimension>
+  auto& Vector<TDimension>::operator+=(Vector<TDimension> const& pVec) {
+    BaseVector<TDimension>::getQuantityVector() +=
+        pVec.getComponents(BaseVector<TDimension>::getCoordinateSystem());
     return *this;
   }
 
-  template <typename dim>
-  auto& Vector<dim>::operator-=(Vector<dim> const& pVec) {
-    BaseVector<dim>::quantityVector() -=
-        pVec.getComponents(BaseVector<dim>::getCoordinateSystem());
+  template <typename TDimension>
+  auto& Vector<TDimension>::operator-=(Vector<TDimension> const& pVec) {
+    BaseVector<TDimension>::getQuantityVector() -=
+        pVec.getComponents(BaseVector<TDimension>::getCoordinateSystem());
     return *this;
   }
 
-  template <typename dim>
-  auto& Vector<dim>::operator-() const {
-    return Vector<dim>(BaseVector<dim>::getCoordinateSystem(),
-                       -BaseVector<dim>::quantityVector());
+  template <typename TDimension>
+  auto& Vector<TDimension>::operator-() const {
+    return Vector<TDimension>(BaseVector<TDimension>::getCoordinateSystem(),
+                              -BaseVector<TDimension>::getQuantityVector());
   }
 
-  template <typename dim>
-  auto Vector<dim>::normalized() const {
+  template <typename TDimension>
+  auto Vector<TDimension>::normalized() const {
     return (*this) * (1 / getNorm());
   }
 
-  template <typename dim>
-  template <typename dim2>
-  auto Vector<dim>::cross(Vector<dim2> pV) const {
+  template <typename TDimension>
+  template <typename TDimension2>
+  auto Vector<TDimension>::cross(Vector<TDimension2> const& pV) const {
     auto const c1 = getComponents().eigenVector_;
-    auto const c2 = pV.getComponents(BaseVector<dim>::getCoordinateSystem()).eigenVector_;
+    auto const c2 =
+        pV.getComponents(BaseVector<TDimension>::getCoordinateSystem()).eigenVector_;
     auto const bareResult = c1.cross(c2);
 
-    using ProdDim = phys::units::detail::product_d<dim, dim2>;
-    return Vector<ProdDim>(BaseVector<dim>::getCoordinateSystem(), bareResult);
+    using ProdDim = phys::units::detail::product_d<TDimension, TDimension2>;
+    return Vector<ProdDim>(BaseVector<TDimension>::getCoordinateSystem(), bareResult);
   }
 
-  template <typename dim>
-  template <typename dim2>
-  auto Vector<dim>::dot(Vector<dim2> pV) const {
+  template <typename TDimension>
+  template <typename TDimension2>
+  auto Vector<TDimension>::dot(Vector<TDimension2> const& pV) const {
     auto const c1 = getComponents().eigenVector_;
-    auto const c2 = pV.getComponents(BaseVector<dim>::getCoordinateSystem()).eigenVector_;
+    auto const c2 =
+        pV.getComponents(BaseVector<TDimension>::getCoordinateSystem()).eigenVector_;
     auto const bareResult = c1.dot(c2);
 
-    using ProdDim = phys::units::detail::product_d<dim, dim2>;
+    using ProdDim = phys::units::detail::product_d<TDimension, TDimension2>;
 
     return phys::units::quantity<ProdDim, double>(phys::units::detail::magnitude_tag,
                                                   bareResult);
diff --git a/corsika/detail/framework/utility/COMBoost.inl b/corsika/detail/framework/utility/COMBoost.inl
index cef0ce97c..36111a2b9 100644
--- a/corsika/detail/framework/utility/COMBoost.inl
+++ b/corsika/detail/framework/utility/COMBoost.inl
@@ -26,7 +26,7 @@ namespace corsika {
   COMBoost::COMBoost(FourVector<HEPEnergyType, Vector<hepmomentum_d>> const& Pprojectile,
                      HEPMassType const massTarget)
       : originalCS_{Pprojectile.getSpaceLikeComponents().getCoordinateSystem()}
-      , rotatedCS_{originalCS_->rotateToZ(Pprojectile.getSpaceLikeComponents())} {
+      , rotatedCS_{make_rotationToZ(originalCS_, Pprojectile.getSpaceLikeComponents())} {
     auto const pProjectile = Pprojectile.getSpaceLikeComponents();
     auto const pProjNormSquared = pProjectile.getSquaredNorm();
     auto const pProjNorm = sqrt(pProjNormSquared);
@@ -48,7 +48,7 @@ namespace corsika {
 
   COMBoost::COMBoost(Vector<hepmomentum_d> const& momentum, HEPEnergyType mass)
       : originalCS_{momentum.getCoordinateSystem()}
-      , rotatedCS_{originalCS_->rotateToZ(momentum)} {
+      , rotatedCS_{make_rotationToZ(originalCS_, momentum)} {
     auto const squaredNorm = momentum.getSquaredNorm();
     auto const norm = sqrt(squaredNorm);
     auto const sinhEta = -norm / mass;
@@ -89,7 +89,7 @@ namespace corsika {
     auto const boostedZ = inverseBoost_ * com;
     auto const E_lab = boostedZ(0) * 1_GeV;
 
-    pCM.eigenVector()(2) = boostedZ(1) * (1_GeV).magnitude();
+    pCM.getEigenVector()[2] = boostedZ(1) * (1_GeV).magnitude();
 
     Vector<typename decltype(pCM)::dimension_type> pLab{rotatedCS_, pCM};
     pLab.rebase(originalCS_);
diff --git a/corsika/framework/geometry/BaseVector.hpp b/corsika/framework/geometry/BaseVector.hpp
index 21819df29..5569149c6 100644
--- a/corsika/framework/geometry/BaseVector.hpp
+++ b/corsika/framework/geometry/BaseVector.hpp
@@ -18,29 +18,32 @@ namespace corsika {
   /*!
    * Common base class for Vector and Point.
    *
-   * This holds a QuantityVector and a CoordinateSystem
+   * This holds a QuantityVector and a CoordinateSystem. The
+   * BaseVector manages resources for many geometry objects.
    *
    */
   template <typename TDimension>
   class BaseVector {
 
   public:
-    BaseVector(CoordinateSystemPtr pCS, QuantityVector<TDimension> const& pQVector)
+    BaseVector(CoordinateSystemPtr const& pCS, QuantityVector<TDimension> const& pQVector)
         : quantityVector_(pQVector)
         , cs_(pCS) {}
 
-    BaseVector() = delete;
+    BaseVector() = delete; // we only want to creat initialized
+			   // objects
     BaseVector(BaseVector const&) = default;
     BaseVector(BaseVector&& a) = default;
     BaseVector& operator=(BaseVector const&) = default;
     ~BaseVector() = default;
 
     CoordinateSystemPtr getCoordinateSystem() const;
-    void setCoordinateSystem(CoordinateSystemPtr cs) { cs_ = cs; }
+    void setCoordinateSystem(CoordinateSystemPtr const&  cs) { cs_ = cs; }
 
   protected:
     QuantityVector<TDimension> const& getQuantityVector() const;
-    QuantityVector<TDimension>& quantityVector();
+    QuantityVector<TDimension>& getQuantityVector();
+    void setQuantityVector(QuantityVector<TDimension> const& v) { quantityVector_=v; }
 
   private:
     QuantityVector<TDimension> quantityVector_;
diff --git a/corsika/framework/geometry/CoordinateSystem.hpp b/corsika/framework/geometry/CoordinateSystem.hpp
index 6cd5c4813..45d34e699 100644
--- a/corsika/framework/geometry/CoordinateSystem.hpp
+++ b/corsika/framework/geometry/CoordinateSystem.hpp
@@ -10,6 +10,7 @@ n/*
 
 #include <corsika/framework/core/PhysicalUnits.hpp>
 #include <corsika/framework/geometry/QuantityVector.hpp>
+#include <corsika/framework/logging/Logging.hpp>
 
 #include <Eigen/Dense>
 #include <stdexcept>
@@ -32,19 +33,48 @@ namespace corsika {
   class RootCoordinateSystem;                             // fwd decl
   static CoordinateSystemPtr get_root_CoordinateSystem(); // fwd decl
 
+  inline CoordinateSystemPtr make_translation(CoordinateSystemPtr const& cs,
+                                              QuantityVector<length_d> const& vector);
+
+  /**
+   * creates a new CS in which vVec points in direction of the new z-axis, \a vVec
+   */
+  template <typename TDim>
+  inline CoordinateSystemPtr make_rotationToZ(CoordinateSystemPtr const& cs,
+                                              Vector<TDim> const& vVec);
+
+  template <typename TDim>
+  inline CoordinateSystemPtr make_rotation(CoordinateSystemPtr const& cs,
+                                           QuantityVector<TDim> const& axis,
+                                           double const angle);
+
+  template <typename TDim>
+  inline CoordinateSystemPtr make_translationAndRotation(
+      CoordinateSystemPtr const& cs, QuantityVector<length_d> const& translation,
+      QuantityVector<TDim> const& axis, double const angle);
+
   /**
-   * A class to store the reference for a geometric object
+   * A class to store the reference coordinate system for a geometric object
    *
    * A CoordinateSystem can only be created in reference and relative
-   * to other CoordinateSystem sytems. Thus, the geometric
-   * transformation between all CoordinateSystems is known.
+   * to other CoordinateSystems. Thus, the geometric
+   * transformation between all CoordinateSystems is always known and stored.
    *
-   * Only the \sa RootCoordinateSystem can be created as a singleton
-   * as global main reference point.
+   * The static (sigleton) function \sa make_root_CoordinateSystem is
+   * the only way to create and access the global top-level
+   * CoordinateSystem obect. CoordinateSystem objects should be
+   * *abosulte* *only* handled in their form of CoordinateSystemPtr,
+   * which are shared_ptr that handle the lifetime of the entire
+   * CoordinateSystem hirarchy.
    *
-   * Thus, new CoordinateSystems can only be created using
-   * transformation: \sa rotateToZ, \sa rotate, \sa translateAndRotate
+   * Thus, new CoordinateSystem are only be created (via
+   * CoordinateSystemPtr) by transforing existing CoordinateSystem
+   * using: \sa rotateToZ, \sa rotate, or \sa translateAndRotate, see
    * below.
+   *
+   * Warning: As a consequence, never try to access, modify, copy, the raw
+   * CoordinateSystem objects directly, this will almost certainly result in undefined
+   * behaviour. Only access, copy, handle them via CoordinateSystemPtr.
    */
 
   class CoordinateSystem {
@@ -52,7 +82,7 @@ namespace corsika {
     /**
      * Constructor only from referenceCS, given the transformation matrix transf
      */
-    CoordinateSystem(CoordinateSystemPtr referenceCS, EigenTransform const& transf)
+    CoordinateSystem(CoordinateSystemPtr const& referenceCS, EigenTransform const& transf)
         : referenceCS_(referenceCS)
         , transf_(transf) {}
 
@@ -67,23 +97,14 @@ namespace corsika {
     // default resource allocation
     CoordinateSystem(CoordinateSystem const&) = default;
     CoordinateSystem(CoordinateSystem&&) = default;
-    CoordinateSystem& operator=(CoordinateSystem const& pCS) = default;
+    CoordinateSystem& operator=(CoordinateSystem const& pCS) =
+        delete; // avoid making copies
     ~CoordinateSystem() = default;
 
-    inline CoordinateSystemPtr translate(QuantityVector<length_d> vector) const;
-
     /**
-     * creates a new CS in which vVec points in direction of the new z-axis
+     * Checks, if this is the unique ROOT CS
      */
-    template <typename TDim>
-    CoordinateSystemPtr rotateToZ(Vector<TDim> vVec) const;
-
-    template <typename TDim>
-    CoordinateSystemPtr rotate(QuantityVector<TDim> axis, double angle) const;
-
-    template <typename TDim>
-    CoordinateSystemPtr translateAndRotate(QuantityVector<length_d> translation,
-                                           QuantityVector<TDim> axis, double angle);
+    inline bool isRoot() const { return !referenceCS_; }
 
     inline CoordinateSystemPtr getReferenceCS() const;
 
@@ -95,15 +116,46 @@ namespace corsika {
   protected:
     static CoordinateSystem createCS() { return CoordinateSystem(); }
 
-    friend CoordinateSystemPtr get_root_CoordinateSystem(); /// this is the only way to
-    /// create ONE unique root CS
+    /**
+     * \defgroup manipulation and creation function
+     * \{
+     **/
+
+    /** this is the only way to create ONE unique root CS **/
+    friend CoordinateSystemPtr get_root_CoordinateSystem();
+
+    friend CoordinateSystemPtr make_translation(CoordinateSystemPtr const& cs,
+                                                QuantityVector<length_d> const& vector);
+    template <typename TDim>
+    friend CoordinateSystemPtr make_rotationToZ(CoordinateSystemPtr const& cs,
+                                                Vector<TDim> const& vVec);
+    template <typename TDim>
+    friend CoordinateSystemPtr make_rotation(CoordinateSystemPtr const& cs,
+                                             QuantityVector<TDim> const& axis,
+                                             double const angle);
+    template <typename TDim>
+    friend CoordinateSystemPtr make_translationAndRotation(
+        CoordinateSystemPtr const& cs, QuantityVector<length_d> const& translation,
+        QuantityVector<TDim> const& axis, double const angle);
+
+    /** \} **/
 
   private:
-    std::shared_ptr<CoordinateSystem const> referenceCS_;
+    CoordinateSystemPtr referenceCS_;
     EigenTransform transf_;
   };
 
-  EigenTransform getTransformation(CoordinateSystemPtr c1, CoordinateSystemPtr c2);
+  /**
+   * Transformation matrix from one reference system to another.
+   *
+   * returns the transformation matrix necessary to transform primitives with coordinates
+   * in \a pFrom to \a pTo, e.g.
+   * \f$ \vec{v}^{\text{(to)}} = \mathcal{M} \vec{v}^{\text{(from)}} \f$
+   * (\f$ \vec{v}^{(.)} \f$ denotes the coordinates/components of the component in
+   * the indicated CoordinateSystem).
+   */
+  inline EigenTransform get_transformation(CoordinateSystemPtr const& c1,
+                                           CoordinateSystemPtr const& c2);
 
 } // namespace corsika
 
diff --git a/corsika/framework/geometry/FourVector.hpp b/corsika/framework/geometry/FourVector.hpp
index 55fefc2fb..4f4bea4de 100644
--- a/corsika/framework/geometry/FourVector.hpp
+++ b/corsika/framework/geometry/FourVector.hpp
@@ -59,16 +59,17 @@ namespace corsika {
         decltype(std::declval<norm_type>() * std::declval<norm_type>());
 
   public:
+    // resource management
     FourVector() = default;
-
+    FourVector(FourVector&&) = default;
+    FourVector(FourVector const&) = default;
+    FourVector& operator=(const FourVector&) = default;
+    ~FourVector() = default;
+    
     FourVector(TTimeType const& eT, TSpaceVecType const& eS)
         : timeLike_(eT)
         , spaceLike_(eS) {}
 
-    /*
-     * FIXME: These Getters are mis-leading and does not favor
-     * locality. Adhere to Getter/Setter
-     */
     /**
      *
      * @return timeLike_
@@ -106,18 +107,13 @@ namespace corsika {
      *
      * RU: then you have to decide in the constructor which avoids "lazyness"
      */
-    /**
-     *
-     * @return
-     */
     bool isTimelike() const;
+    bool isSpacelike() const;
 
     /**
      * @defgroup math operators (class members)
      * @{
      */
-    bool isSpacelike() const;
-
     FourVector& operator+=(FourVector const&);
     FourVector& operator-=(FourVector const&);
     FourVector& operator*=(double const);
@@ -174,7 +170,7 @@ namespace corsika {
     }
 
     friend FourVector<time_type, space_vec_type> operator/(FourVector const& a,
-                                                           double b) {
+                                                           double const b) {
       return FourVector<time_type, space_vec_type>(a.timeLike_ / b, a.spaceLike_ / b);
     }
 
@@ -188,6 +184,14 @@ namespace corsika {
     norm_square_type getTimeSquared() const;
   };
 
+  /**
+   * streaming operator
+   **/
+
+  template <typename TTimeType, typename TSpaceVecType>
+  inline std::ostream& operator<<(std::ostream& os,
+                                  corsika::FourVector<TTimeType, TSpaceVecType> const& qv);
+
 } // namespace corsika
 
 #include <corsika/detail/framework/geometry/FourVector.inl>
diff --git a/corsika/framework/geometry/Helix.hpp b/corsika/framework/geometry/Helix.hpp
index 05ca40be0..826b4c3fc 100644
--- a/corsika/framework/geometry/Helix.hpp
+++ b/corsika/framework/geometry/Helix.hpp
@@ -46,13 +46,13 @@ namespace corsika {
 
     inline LengthType getRadius() const;
 
-    inline Point getPosition(TimeType t) const;
+    inline Point getPosition(TimeType const t) const;
 
-    inline Point getPositionFromArclength(LengthType l) const;
+    inline Point getPositionFromArclength(LengthType const l) const;
 
-    inline LengthType getArcLength(TimeType t1, TimeType t2) const;
+    inline LengthType getArcLength(TimeType const t1, TimeType const t2) const;
 
-    inline TimeType getTimeFromArclength(LengthType l) const;
+    inline TimeType getTimeFromArclength(LengthType const l) const;
 
   private:
     Point r0_;             ///! origin of helix, but this is in the center of the
diff --git a/corsika/framework/geometry/Line.hpp b/corsika/framework/geometry/Line.hpp
index 2c27a0bc0..3e1e18564 100644
--- a/corsika/framework/geometry/Line.hpp
+++ b/corsika/framework/geometry/Line.hpp
@@ -15,15 +15,10 @@ n/*
 namespace corsika {
 
   /**
-   * \class Line
+   * Describes a straight line in space
    *
-   * A Line describes a movement in three dimensional space. It
-   * consists of a Point `$\vec{p_0}$` and and a speed-Vector
-   * `$\vec{v}$`, so that it can return GetPosition as
-   * `$\vec{p_0}*\vec{v}*t$` for any value of time `$t$`.
-   *
-   **/
-
+   */
+  
   class Line {
 
     ///! \toto move this to PhysicalUnits
@@ -34,21 +29,23 @@ namespace corsika {
         : start_point_(pR0)
         , velocity_(pV0) {}
 
-    inline Point getPosition(TimeType t) const;
+    inline Point getPosition(TimeType const t) const;
 
-    inline Point getPositionFromArclength(LengthType l) const;
+    inline Point getPositionFromArclength(LengthType const l) const;
 
-    inline LengthType getArcLength(TimeType t1, TimeType t2) const;
+    inline LengthType getArcLength(TimeType const t1, TimeType const t2) const;
 
-    inline TimeType getTimeFromArclength(LengthType t) const;
+    inline TimeType getTimeFromArclength(LengthType const t) const;
 
-    inline const Point& getStartPoint() const;
+    inline Point const& getStartPoint() const;
+    inline Point& startPoint() { return start_point_; }
 
-    inline const VelocityVec& getVelocity() const;
+    inline VelocityVec const& getVelocity() const;
+    inline VelocityVec& velocity() { return velocity_; }
 
   private:
-    Point const start_point_;
-    VelocityVec const velocity_;
+    Point start_point_;
+    VelocityVec velocity_;
   };
 
 } // namespace corsika
diff --git a/corsika/framework/geometry/Point.hpp b/corsika/framework/geometry/Point.hpp
index 06c302e1b..c302d14c8 100644
--- a/corsika/framework/geometry/Point.hpp
+++ b/corsika/framework/geometry/Point.hpp
@@ -22,29 +22,54 @@ namespace corsika {
   class Point : public BaseVector<length_d> {
 
   public:
-    Point(CoordinateSystemPtr pCS, QuantityVector<length_d> const& pQVector)
+    Point(CoordinateSystemPtr const& pCS, QuantityVector<length_d> const& pQVector)
         : BaseVector<length_d>(pCS, pQVector) {}
 
-    Point(CoordinateSystemPtr cs, LengthType x, LengthType y, LengthType z)
+    Point(CoordinateSystemPtr const& cs, LengthType x, LengthType y, LengthType z)
         : BaseVector<length_d>(cs, {x, y, z}) {}
 
     /** \todo TODO: this should be private or protected, we don NOT want to expose numbers
      * without reference to outside:
      */
-    inline auto getCoordinates() const;
+    inline QuantityVector<length_d> const& getCoordinates() const;
+    inline QuantityVector<length_d>& getCoordinates();
 
-    /// this always returns a QuantityVector as triple
-    inline auto getCoordinates(CoordinateSystemPtr pCS) const;
+    /**
+       this always returns a QuantityVector as triple
 
-    inline LengthType getX(CoordinateSystemPtr pCS) const;
-    inline LengthType getY(CoordinateSystemPtr pCS) const;
-    inline LengthType getZ(CoordinateSystemPtr pCS) const;
+       \returns A value type QuantityVector, since it may have to create a temporary
+       object to transform to pCS.
+    **/
+    inline QuantityVector<length_d> getCoordinates(CoordinateSystemPtr const& pCS) const;
+
+    /**
+     * this always returns a QuantityVector as triple
+     *
+     *  \returns A reference type QuantityVector&, but be aware, the underlying class data
+     *   is actually transformed to pCS, if needed. Thus, there may be an implicit call to
+     *   \sa rebase.
+     **/
+    inline QuantityVector<length_d>& getCoordinates(CoordinateSystemPtr const& pCS);
+
+    /**
+     * \defgroup access coordinate components
+     * \{
+     *
+     * Note, if you access components in a different CoordinateSystem
+     * pCS than the stored data, internally a temporary object will be
+     * created and destroyed each call. This can be avoided by using
+     * \sa rebase first.
+     **/
+    inline LengthType getX(CoordinateSystemPtr const& pCS) const;
+    inline LengthType getY(CoordinateSystemPtr const& pCS) const;
+    inline LengthType getZ(CoordinateSystemPtr const& pCS) const;
+    /** \} **/
 
     /*!
      * transforms the Point into another CoordinateSystem by changing its
      * coordinates interally
      */
-    inline void rebase(CoordinateSystemPtr pCS);
+    inline void rebase(CoordinateSystemPtr const& pCS);
 
     inline Point operator+(Vector<length_d> const& pVec) const;
 
diff --git a/corsika/framework/geometry/QuantityVector.hpp b/corsika/framework/geometry/QuantityVector.hpp
index e1f56d380..bc7e41e4e 100644
--- a/corsika/framework/geometry/QuantityVector.hpp
+++ b/corsika/framework/geometry/QuantityVector.hpp
@@ -17,9 +17,9 @@ n/*
 namespace corsika {
 
   class CoordinateSystem; // fwd decl
-  class Point;
+  class Point; // fwd decl
   template <typename T>
-  class Vector;
+  class Vector; // fwd decl
 
   /*!
    * A QuantityVector is a three-component container based on Eigen::Vector3d
@@ -37,43 +37,45 @@ namespace corsika {
     using quantity_type =
         phys::units::quantity<TDimension, double>; //< the phys::units::quantity
                                                    // corresponding to the dimension
+    using quantity_square_type =
+        decltype(std::declval<quantity_type>() * std::declval<quantity_type>());
 
-    QuantityVector(Eigen::Vector3d pBareVector)
+    QuantityVector(Eigen::Vector3d const& pBareVector)
         : eigenVector_(pBareVector) {}
 
   public:
     typedef TDimension dimension_type; //!< should be a phys::units::dimension
 
-    QuantityVector(quantity_type a, quantity_type b, quantity_type c)
+    QuantityVector(quantity_type const a, quantity_type const b, quantity_type const c)
         : eigenVector_{a.magnitude(), b.magnitude(), c.magnitude()} {}
 
-    QuantityVector(double a, double b, double c)
+    QuantityVector(double const a, double const b, double const c)
         : eigenVector_{a, b, c} {
       static_assert(
           std::is_same_v<TDimension, phys::units::dimensionless_d>,
-          "initialization of dimensionful QuantityVector with pure numbers not allowed!");
+          "initialization of dimensionfull QuantityVector with pure numbers not allowed!");
     }
 
-    quantity_type operator[](size_t index) const;
+    quantity_type operator[](size_t const index) const;
     quantity_type getX() const;
     quantity_type getY() const;
     quantity_type getZ() const;
     Eigen::Vector3d const& getEigenVector() const { return eigenVector_; }
-    Eigen::Vector3d& eigenVector() { return eigenVector_; }
+    Eigen::Vector3d& getEigenVector() { return eigenVector_; }
 
     quantity_type getNorm() const;
 
-    auto getSquaredNorm() const;
+    quantity_square_type getSquaredNorm() const;
 
     QuantityVector operator+(QuantityVector<TDimension> const& pQVec) const;
 
     QuantityVector operator-(QuantityVector<TDimension> const& pQVec) const;
 
-    template <typename ScalarDim>
-    auto operator*(phys::units::quantity<ScalarDim, double> const p) const;
+    template <typename TScalarDim>
+    auto operator*(phys::units::quantity<TScalarDim, double> const p) const;
 
-    template <typename ScalarDim>
-    auto operator/(phys::units::quantity<ScalarDim, double> const p) const;
+    template <typename TScalarDim>
+    auto operator/(phys::units::quantity<TScalarDim, double> const p) const;
 
     auto operator*(double const p) const;
 
@@ -93,25 +95,26 @@ namespace corsika {
 
     auto operator==(QuantityVector<TDimension> const& p) const;
 
+    // friends:
     friend class CoordinateSystem;
     friend class Point;
     template <typename T>
     friend class corsika::Vector;
-    template <typename dim>
-    friend std::ostream& operator<<(std::ostream& os, QuantityVector<dim> qv);
+    template <typename TDim>
+    friend std::ostream& operator<<(std::ostream& os, QuantityVector<TDim> qv);
 
   protected:
     Eigen::Vector3d
         eigenVector_; //!< the actual container where the raw numbers are stored
   };
 
-  /*
+  /**
    * streaming operator
-   */
+   **/
 
   template <typename TDimension>
   inline std::ostream& operator<<(std::ostream& os,
-                                  corsika::QuantityVector<TDimension> qv);
+                                  corsika::QuantityVector<TDimension> const qv);
 
 } // namespace corsika
 
diff --git a/corsika/framework/geometry/Sphere.hpp b/corsika/framework/geometry/Sphere.hpp
index d5f4c44a8..e014dd86d 100644
--- a/corsika/framework/geometry/Sphere.hpp
+++ b/corsika/framework/geometry/Sphere.hpp
@@ -14,6 +14,11 @@ n/*
 
 namespace corsika {
 
+  /**
+   * Describes a sphere in space
+   *
+   **/
+  
   class Sphere : public IVolume {
 
   public:
@@ -24,13 +29,15 @@ namespace corsika {
     //! returns true if the Point p is within the sphere
     inline bool isInside(Point const& p) const override;
 
-    inline const Point& getCenter() const;
+    inline Point const& getCenter() const;
+    inline Point& getCenter() { return center_; }
 
     inline LengthType getRadius() const;
+    inline LengthType& getRadius() { return radius_; }
 
   private:
-    Point const center_;
-    LengthType const radius_;
+    Point center_;
+    LengthType radius_;
   };
 
 } // namespace corsika
diff --git a/corsika/framework/geometry/Trajectory.hpp b/corsika/framework/geometry/Trajectory.hpp
index 0c26f9dcd..9aa7b917d 100644
--- a/corsika/framework/geometry/Trajectory.hpp
+++ b/corsika/framework/geometry/Trajectory.hpp
@@ -25,15 +25,15 @@ namespace corsika {
         : TType(theT)
         , timeLength_(timeLength) {}
 
-    Point getPosition(double u) const;
+    Point getPosition(double const u) const;
 
     TimeType getDuration() const;
 
     LengthType getLength() const;
 
-    LengthType getDistance(TimeType t) const;
+    LengthType getDistance(TimeType const t) const;
 
-    void getLimitEndTo(LengthType limit);
+    void getLimitEndTo(LengthType const limit);
 
     auto getNormalizedDirection() const;
 
diff --git a/corsika/framework/geometry/Vector.hpp b/corsika/framework/geometry/Vector.hpp
index 96a154562..83ea39dcf 100644
--- a/corsika/framework/geometry/Vector.hpp
+++ b/corsika/framework/geometry/Vector.hpp
@@ -15,7 +15,9 @@ n/*
 namespace corsika {
 
   /*!
-   * A Vector represents a 3-vector in Euclidean space. It is defined by components
+   * A Vector represents a 3-vector in Euclidean space.
+   *
+   * It is defined by components
    * given in a specific CoordinateSystem. It has a physical dimension ("unit")
    * as part of its type, so you cannot mix up e.g. electric with magnetic fields
    * (but you could calculate their cross-product to get an energy flux vector).
@@ -28,38 +30,61 @@ namespace corsika {
   class Vector : public BaseVector<TDimension> {
   public:
     using quantity_type = phys::units::quantity<TDimension, double>;
+    using quantity_square_type =
+        decltype(std::declval<quantity_type>() * std::declval<quantity_type>());
 
-  public:
-    Vector(CoordinateSystemPtr pCS, QuantityVector<TDimension> pQVector)
+    Vector(CoordinateSystemPtr const& pCS, QuantityVector<TDimension> const& pQVector)
         : BaseVector<TDimension>(pCS, pQVector) {}
 
-    Vector(CoordinateSystemPtr cs, quantity_type x, quantity_type y, quantity_type z)
+    Vector(CoordinateSystemPtr const& cs, quantity_type const x, quantity_type const y,
+           quantity_type const z)
         : BaseVector<TDimension>(cs, QuantityVector<TDimension>(x, y, z)) {}
 
     /*!
-     * returns a QuantityVector with the components given in the "home"
+     * \returns a QuantityVector with the components given in the "home"
      * CoordinateSystem of the Vector
      *
      * \todo this should best be protected, we don't want users to use
      * bare coordinates without reference frame
      */
-    QuantityVector<TDimension> getComponents() const;
+    inline QuantityVector<TDimension> const& getComponents() const;
+    inline QuantityVector<TDimension>& getComponents();
 
     /*!
      * returns a QuantityVector with the components given in an arbitrary
      * CoordinateSystem
      */
-    QuantityVector<TDimension> getComponents(CoordinateSystemPtr pCS) const;
+    inline QuantityVector<TDimension> getComponents(CoordinateSystemPtr const& pCS) const;
+
+    /**
+     * this always returns a QuantityVector as triple
+     *
+     *  \returns A reference type QuantityVector&, but be aware, the underlying class data
+     *   is actually transformed to pCS, if needed. Thus, there may be an implicit call to
+     *   \sa rebase.
+     **/
+    inline QuantityVector<TDimension>& getComponents(CoordinateSystemPtr const& pCS);
+
+    /**
+     * \defgroup access coordinate components
+     * \{
+     *
+     * Note, if you access components in a different CoordinateSystem
+     * pCS than the stored data, internally a temporary object will be
+     * created and destroyed each call. This can be avoided by using
+     * \sa rebase first.
+     **/
 
-    inline quantity_type getX(CoordinateSystemPtr pCS) const;
-    inline quantity_type getY(CoordinateSystemPtr pCS) const;
-    inline quantity_type getZ(CoordinateSystemPtr pCS) const;
+    inline quantity_type getX(CoordinateSystemPtr const& pCS) const;
+    inline quantity_type getY(CoordinateSystemPtr const& pCS) const;
+    inline quantity_type getZ(CoordinateSystemPtr const& pCS) const;
+    /** \} **/
 
     /*!
      * transforms the Vector into another CoordinateSystem by changing
      * its components internally
      */
-    inline void rebase(CoordinateSystemPtr pCS);
+    inline void rebase(CoordinateSystemPtr const& pCS);
 
     /*!
      * returns the norm/length of the Vector. Before using this method,
@@ -71,7 +96,8 @@ namespace corsika {
      * returns the squared norm of the Vector. Before using this method,
      * think about whether norm() might be cheaper for your computation.
      */
-    inline auto getSquaredNorm() const;
+    inline quantity_square_type getSquaredNorm() const;
+
     /*!
      * returns a Vector \f$ \vec{v}_{\parallel} \f$ which is the parallel projection
      * of this vector \f$ \vec{v}_1 \f$ along another Vector \f$ \vec{v}_2 \f$ given by
@@ -81,7 +107,7 @@ namespace corsika {
      */
     template <typename TDimension2>
     auto getParallelProjectionOnto(Vector<TDimension2> const& pVec,
-                                   CoordinateSystemPtr pCS) const;
+                                   CoordinateSystemPtr const& pCS) const;
     template <typename TDimension2>
     auto getParallelProjectionOnto(Vector<TDimension2> const& pVec) const;
 
@@ -109,10 +135,10 @@ namespace corsika {
     auto normalized() const;
 
     template <typename TDimension2>
-    auto cross(Vector<TDimension2> pV) const;
+    auto cross(Vector<TDimension2> const& pV) const;
 
     template <typename TDimension2>
-    auto dot(Vector<TDimension2> pV) const;
+    auto dot(Vector<TDimension2> const& pV) const;
   };
 
 } // namespace corsika
diff --git a/examples/geometry_example.cpp b/examples/geometry_example.cpp
index 0458c257f..5cdf6043c 100644
--- a/examples/geometry_example.cpp
+++ b/examples/geometry_example.cpp
@@ -11,28 +11,26 @@ n/*
 #include <corsika/framework/geometry/RootCoordinateSystem.hpp>
 #include <corsika/framework/geometry/Sphere.hpp>
 #include <corsika/framework/geometry/Vector.hpp>
+#include <corsika/framework/logging/Logging.hpp>
 
 #include <cstdlib>
 #include <iostream>
 #include <typeinfo>
 
 using namespace corsika;
-using namespace corsika::units::si;
 
 int main() {
 
-  std::cout << "geometry_example" << std::endl;
-
   // define the root coordinate system
-  corsika::CoordinateSystemPtr root = get_root_CoordinateSystem();
+  CoordinateSystemPtr root = get_root_CoordinateSystem();
 
   // another CS defined by a translation relative to the root CS
-  CoordinateSystemPtr cs2 = root->translate({0_m, 0_m, 1_m});
+  CoordinateSystemPtr cs2 = make_translation(root, {0_m, 0_m, 1_m});
 
   // rotations are possible, too; parameters are axis vector and angle
   CoordinateSystemPtr cs3 =
-      root->rotate(QuantityVector<length_d>{1_m, 0_m, 0_m}, 90 * degree_angle);
-
+    make_rotation(root, QuantityVector<length_d>{1_m, 0_m, 0_m}, 90 * degree_angle);
+  
   // now let's define some geometrical objects:
   Point const p1(root, {0_m, 0_m, 0_m}); // the origin of the root CS
   Point const p2(cs2, {0_m, 0_m, 0_m});  // the origin of cs2
diff --git a/tests/framework/testGeometry.cpp b/tests/framework/testGeometry.cpp
index e303e6419..1c03de501 100644
--- a/tests/framework/testGeometry.cpp
+++ b/tests/framework/testGeometry.cpp
@@ -24,76 +24,68 @@ double constexpr absMargin = 1.0e-8;
 TEST_CASE("transformations between CoordinateSystems") {
   CoordinateSystemPtr rootCS = get_root_CoordinateSystem();
 
-  REQUIRE(getTransformation(rootCS, rootCS).isApprox(EigenTransform::Identity()));
-
   QuantityVector<length_d> const coordinates{0_m, 0_m, 0_m};
   Point p1(rootCS, coordinates);
 
   QuantityVector<magnetic_flux_density_d> components{1. * tesla, 0. * tesla, 0. * tesla};
   Vector<magnetic_flux_density_d> v1(rootCS, components);
 
-  REQUIRE((p1.getCoordinates() - coordinates).getNorm().magnitude() ==
-          Approx(0).margin(absMargin));
-  REQUIRE((p1.getCoordinates(rootCS) - coordinates).getNorm().magnitude() ==
-          Approx(0).margin(absMargin));
-
-  /*
-  SECTION("unconnected CoordinateSystems") {
-    CoordinateSystem rootCS2 = CoordinateSystem::CreateRootCS();
-    REQUIRE_THROWS(CoordinateSystem::getTransformation(rootCS, rootCS2));
-    }*/
+  CHECK((p1.getCoordinates() - coordinates).getNorm().magnitude() ==
+        Approx(0).margin(absMargin));
+  CHECK((p1.getCoordinates(rootCS) - coordinates).getNorm().magnitude() ==
+        Approx(0).margin(absMargin));
 
   SECTION("translations") {
     QuantityVector<length_d> const translationVector{0_m, 4_m, 0_m};
 
-    CoordinateSystemPtr translatedCS = rootCS->translate(translationVector);
+    CoordinateSystemPtr translatedCS = make_translation(rootCS, translationVector);
 
-    REQUIRE(*translatedCS->getReferenceCS() == *rootCS);
+    CHECK(*translatedCS->getReferenceCS() == *rootCS);
 
-    REQUIRE((p1.getCoordinates(translatedCS) + translationVector).getNorm().magnitude() ==
-            Approx(0).margin(absMargin));
+    CHECK((p1.getCoordinates(translatedCS) + translationVector).getNorm().magnitude() ==
+          Approx(0).margin(absMargin));
 
     // Vectors are not subject to translations
-    REQUIRE((v1.getComponents(rootCS) - v1.getComponents(translatedCS))
-                .getNorm()
-                .magnitude() == Approx(0).margin(absMargin));
+    CHECK((v1.getComponents(rootCS) - v1.getComponents(translatedCS))
+              .getNorm()
+              .magnitude() == Approx(0).margin(absMargin));
 
     Point p2(translatedCS, {0_m, 0_m, 0_m});
-    REQUIRE(((p2 - p1).getComponents() - translationVector).getNorm().magnitude() ==
-            Approx(0).margin(absMargin));
+    CHECK(((p2 - p1).getComponents() - translationVector).getNorm().magnitude() ==
+          Approx(0).margin(absMargin));
   }
 
   SECTION("multiple translations") {
     QuantityVector<length_d> const tv1{0_m, 5_m, 0_m};
-    CoordinateSystemPtr cs2 = rootCS->translate(tv1);
+    CoordinateSystemPtr cs2 = make_translation(rootCS, tv1);
 
     QuantityVector<length_d> const tv2{3_m, 0_m, 0_m};
-    CoordinateSystemPtr cs3 = rootCS->translate(tv2);
+    CoordinateSystemPtr cs3 = make_translation(rootCS, tv2);
 
     QuantityVector<length_d> const tv3{0_m, 0_m, 2_m};
-    CoordinateSystemPtr cs4 = cs3->translate(tv3);
+    CoordinateSystemPtr cs4 = make_translation(cs3, tv3);
 
-    REQUIRE(*cs4->getReferenceCS()->getReferenceCS() == *rootCS);
+    CHECK(*cs4->getReferenceCS()->getReferenceCS() == *rootCS);
 
-    REQUIRE(getTransformation(cs3, cs2).isApprox(
-        rootCS->translate({3_m, -5_m, 0_m})->getTransform()));
-    REQUIRE(getTransformation(cs2, cs3).isApprox(
-        rootCS->translate({-3_m, +5_m, 0_m})->getTransform()));
+    CHECK(get_transformation(cs3, cs2).isApprox(
+        make_translation(rootCS, {3_m, -5_m, 0_m})->getTransform()));
+    CHECK(get_transformation(cs2, cs3).isApprox(
+        make_translation(rootCS, {-3_m, +5_m, 0_m})->getTransform()));
   }
 
   SECTION("rotations") {
     QuantityVector<length_d> const axis{0_m, 0_m, 1_km};
     double const angle = 90. / 180. * M_PI;
 
-    CoordinateSystemPtr rotatedCS = rootCS->rotate(axis, angle);
-    REQUIRE(*rotatedCS->getReferenceCS() == *rootCS);
+    CoordinateSystemPtr rotatedCS = make_rotation(rootCS, axis, angle);
+    CHECK(*rotatedCS->getReferenceCS() == *rootCS);
 
-    REQUIRE(v1.getComponents(rotatedCS)[1].magnitude() ==
-            Approx((-1. * tesla).magnitude()));
+    CHECK(v1.getComponents(rotatedCS)[1].magnitude() ==
+          Approx((-1. * tesla).magnitude()));
 
     // vector norm invariant under rotation
-    REQUIRE(v1.getComponents(rotatedCS).getNorm().magnitude() ==
-            Approx(v1.getComponents(rootCS).getNorm().magnitude()));
+    CHECK(v1.getComponents(rotatedCS).getNorm().magnitude() ==
+          Approx(v1.getComponents(rootCS).getNorm().magnitude()));
   }
 
   SECTION("multiple rotations") {
@@ -107,20 +99,20 @@ TEST_CASE("transformations between CoordinateSystems") {
 
     double const angle = 90. / 180. * M_PI;
 
-    CoordinateSystemPtr rotated1 = rootCS->rotate(zAxis, angle);
-    CoordinateSystemPtr rotated2 = rotated1->rotate(yAxis, angle);
-    CoordinateSystemPtr rotated3 = rotated2->rotate(zAxis, -angle);
+    CoordinateSystemPtr rotated1 = make_rotation(rootCS, zAxis, angle);
+    CoordinateSystemPtr rotated2 = make_rotation(rotated1, yAxis, angle);
+    CoordinateSystemPtr rotated3 = make_rotation(rotated2, zAxis, -angle);
 
-    CoordinateSystemPtr combined = rootCS->rotate(xAxis, -angle);
+    CoordinateSystemPtr combined = make_rotation(rootCS, xAxis, -angle);
 
     auto comp1 = v1.getComponents(rotated3);
     auto comp3 = v1.getComponents(combined);
-    REQUIRE((comp1 - comp3).getNorm().magnitude() == Approx(0).margin(absMargin));
+    CHECK((comp1 - comp3).getNorm().magnitude() == Approx(0).margin(absMargin));
   }
 
   SECTION("RotateToZ positive") {
     Vector const v{rootCS, 0_m, 1_m, 1_m};
-    auto const csPrime = rootCS->rotateToZ(v);
+    auto const csPrime = make_rotationToZ(rootCS, v);
     Vector const zPrime{csPrime, 0_m, 0_m, 5_m};
     Vector const xPrime{csPrime, 5_m, 0_m, 0_m};
     Vector const yPrime{csPrime, 0_m, 5_m, 0_m};
@@ -153,7 +145,7 @@ TEST_CASE("transformations between CoordinateSystems") {
 
   SECTION("RotateToZ negative") {
     Vector const v{rootCS, 0_m, 0_m, -1_m};
-    auto const csPrime = rootCS->rotateToZ(v);
+    auto const csPrime = make_rotationToZ(rootCS, v);
     Vector const zPrime{csPrime, 0_m, 0_m, 5_m};
     Vector const xPrime{csPrime, 5_m, 0_m, 0_m};
     Vector const yPrime{csPrime, 0_m, 5_m, 0_m};
@@ -241,6 +233,52 @@ TEST_CASE("transformations between CoordinateSystems") {
   }
 }
 
+TEST_CASE("CoordinateSystem hirarchy") {
+
+  CoordinateSystemPtr rootCS = get_root_CoordinateSystem();
+
+  CHECK(get_transformation(rootCS, rootCS).isApprox(EigenTransform::Identity()));
+
+  // define the root coordinate system
+  CoordinateSystemPtr root = get_root_CoordinateSystem();
+  Point const p1(root, {0_m, 0_m, 0_m}); // the origin of the root CS
+
+  // root -> cs2
+  CoordinateSystemPtr cs2 = make_translation(root, {0_m, 0_m, 1_m});
+  Point const p2(cs2, {0_m, 0_m, -1_m});
+
+  // root -> cs2 -> cs3
+  CoordinateSystemPtr cs3 = make_translation(cs2, {0_m, 0_m, -1_m});
+  Point const p3(cs3, {0_m, 0_m, 0_m});
+
+  // root -> cs2 -> cs4
+  CoordinateSystemPtr cs4 = make_translation(cs2, {0_m, 0_m, -1_m});
+  Point const p4(cs4, {0_m, 0_m, 0_m});
+
+  // root -> cs2 -> cs4 -> cs5
+  CoordinateSystemPtr cs5 =
+      make_rotation(cs4, QuantityVector<length_d>{1_m, 0_m, 0_m}, 90 * degree_angle);
+  Point const p5(cs5, {0_m, 0_m, 0_m});
+
+  // root -> cs6
+  CoordinateSystemPtr cs6 =
+      make_rotation(root, QuantityVector<length_d>{1_m, 0_m, 0_m}, 90 * degree_angle);
+  Point const p6(cs6, {0_m, 0_m, 0_m}); // the origin of the root CS
+
+  // all points should be on top of each other
+
+  CHECK_FALSE(get_transformation(root, cs2).isApprox(EigenTransform::Identity()));
+  CHECK(get_transformation(root, cs3).isApprox(EigenTransform::Identity()));
+  CHECK(get_transformation(root, cs4).isApprox(EigenTransform::Identity()));
+  CHECK(get_transformation(cs5, cs6).isApprox(EigenTransform::Identity()));
+
+  CHECK((p1 - p2).getNorm().magnitude() == Approx(0).margin(absMargin));
+  CHECK((p1 - p3).getNorm().magnitude() == Approx(0).margin(absMargin));
+  CHECK((p1 - p4).getNorm().magnitude() == Approx(0).margin(absMargin));
+  CHECK((p1 - p5).getNorm().magnitude() == Approx(0).margin(absMargin));
+  CHECK((p1 - p6).getNorm().magnitude() == Approx(0).margin(absMargin));
+}
+
 TEST_CASE("Sphere") {
   CoordinateSystemPtr rootCS = get_root_CoordinateSystem();
   Point center(rootCS, {0_m, 3_m, 4_m});
@@ -255,8 +293,8 @@ TEST_CASE("Sphere") {
   }
 
   SECTION("isInside") {
-    REQUIRE_FALSE(sphere.isInside(Point(rootCS, {100_m, 0_m, 0_m})));
-    REQUIRE(sphere.isInside(Point(rootCS, {2_m, 3_m, 4_m})));
+    CHECK_FALSE(sphere.isInside(Point(rootCS, {100_m, 0_m, 0_m})));
+    CHECK(sphere.isInside(Point(rootCS, {2_m, 3_m, 4_m})));
   }
 }
 
-- 
GitLab