diff --git a/dumux/geometry/boundingboxtree.hh b/dumux/geometry/boundingboxtree.hh
index 85888341c424477bc2f1ff3c7d8101223999f34f..b9afa8ce463dbaf254e688859a77cf0cd625fd42 100644
--- a/dumux/geometry/boundingboxtree.hh
+++ b/dumux/geometry/boundingboxtree.hh
@@ -411,6 +411,25 @@ inline bool intersectsBoundingBoxBoundingBox(const ctypea* a, const ctypeb* b)
     return b[0] - eps0 <= a[1] && a[0] <= b[1] + eps0;
 }
 
+/*!
+ * \brief Compute squared distance between point and bounding box
+ * \param point The point
+ * \param b Pointer to bounding box coordinates
+ */
+template<int dimworld, class ctype>
+inline ctype squaredDistancePointBoundingBox(const Dune::FieldVector<ctype, dimworld>& point, const ctype* b)
+{
+    ctype squaredDistance = 0.0;
+    for (int d = 0; d < dimworld; ++d)
+    {
+        if (point[d] < b[d])
+            squaredDistance += (point[d] - b[d])*(point[d] - b[d]);
+        if (point[d] > b[d+dimworld])
+            squaredDistance += (point[d] - b[d+dimworld])*(point[d] - b[d+dimworld]);
+    }
+    return squaredDistance;
+}
+
 } // end namespace Dumux
 
 #endif
diff --git a/dumux/geometry/distance.hh b/dumux/geometry/distance.hh
index 84b2b614973d7e01c896a2829b4f46ac5d519991..faa1b7840411765a62f1e487d6d4922da90436e2 100644
--- a/dumux/geometry/distance.hh
+++ b/dumux/geometry/distance.hh
@@ -24,7 +24,9 @@
 
 #include <dune/common/fvector.hh>
 #include <dune/geometry/quadraturerules.hh>
+
 #include <dumux/common/math.hh>
+#include <dumux/geometry/boundingboxtree.hh>
 
 namespace Dumux {
 
@@ -380,6 +382,160 @@ template<class Geo1, class Geo2>
 static inline auto distance(const Geo1& geo1, const Geo2& geo2)
 { using std::sqrt; return sqrt(squaredDistance(geo1, geo2)); }
 
+
+//! Distance implementation details
+namespace Detail {
+
+/*!
+ * \ingroup Geometry
+ * \brief Compute the closest entity in an AABB tree (index and shortest squared distance) recursively
+ * \note specialization for geometries with dimension larger than points
+ */
+template<class EntitySet, class ctype, int dimworld,
+         typename std::enable_if_t<(EntitySet::Entity::Geometry::mydimension > 0), int> = 0>
+void closestEntity(const Dune::FieldVector<ctype, dimworld>& point,
+                   const BoundingBoxTree<EntitySet>& tree,
+                   std::size_t node,
+                   ctype& minSquaredDistance,
+                   std::size_t& eIdx)
+{
+    // Get the bounding box for the current node
+    const auto& bBox = tree.getBoundingBoxNode(node);
+
+    // If bounding box is outside radius, then don't search further
+    const auto squaredDistance = squaredDistancePointBoundingBox(
+        point, tree.getBoundingBoxCoordinates(node)
+    );
+
+    // do not continue if the AABB is further away than the current minimum
+    if (squaredDistance > minSquaredDistance) return;
+
+    // If the bounding box is a leaf, update distance and index with primitive test
+    else if (tree.isLeaf(bBox, node))
+    {
+        const std::size_t entityIdx = bBox.child1;
+        const auto squaredDistance = [&]{
+            const auto geometry = tree.entitySet().entity(entityIdx).geometry();
+            if constexpr (EntitySet::Entity::Geometry::mydimension == 2)
+                return squaredDistancePointPolygon(point, geometry);
+            else if constexpr (EntitySet::Entity::Geometry::mydimension == 1)
+                return squaredDistancePointSegment(point, geometry);
+            else
+                DUNE_THROW(Dune::NotImplemented, "squaredDistance to entity with dim>2");
+        }();
+
+        if (squaredDistance < minSquaredDistance)
+        {
+            eIdx = entityIdx;
+            minSquaredDistance = squaredDistance;
+        }
+    }
+
+    // Check the children nodes recursively
+    else
+    {
+        closestEntity(point, tree, bBox.child0, minSquaredDistance, eIdx);
+        closestEntity(point, tree, bBox.child1, minSquaredDistance, eIdx);
+    }
+}
+
+/*!
+ * \ingroup Geometry
+ * \brief Compute the closest entity in an AABB tree (index and shortest squared distance) recursively
+ * \note specialization for point geometries (point cloud AABB tree)
+ */
+template<class EntitySet, class ctype, int dimworld,
+         typename std::enable_if_t<(EntitySet::Entity::Geometry::mydimension == 0), int> = 0>
+void closestEntity(const Dune::FieldVector<ctype, dimworld>& point,
+                   const BoundingBoxTree<EntitySet>& tree,
+                   std::size_t node,
+                   ctype& minSquaredDistance,
+                   std::size_t& eIdx)
+{
+    // Get the bounding box for the current node
+    const auto& bBox = tree.getBoundingBoxNode(node);
+
+    // If the bounding box is a leaf, update distance and index with primitive test
+    if (tree.isLeaf(bBox, node))
+    {
+        const std::size_t entityIdx = bBox.child1;
+        const auto& p = tree.entitySet().entity(entityIdx).geometry().corner(0);
+        const auto squaredDistance = (p-point).two_norm2();
+
+        if (squaredDistance < minSquaredDistance)
+        {
+            eIdx = entityIdx;
+            minSquaredDistance = squaredDistance;
+        }
+    }
+
+    // Check the children nodes recursively
+    else
+    {
+        // If bounding box is outside radius, then don't search further
+        const auto squaredDistance = squaredDistancePointBoundingBox(
+            point, tree.getBoundingBoxCoordinates(node)
+        );
+
+        // do not continue if the AABB is further away than the current minimum
+        if (squaredDistance > minSquaredDistance) return;
+
+        closestEntity(point, tree, bBox.child0, minSquaredDistance, eIdx);
+        closestEntity(point, tree, bBox.child1, minSquaredDistance, eIdx);
+    }
+}
+
+} // end namespace Detail
+
+/*!
+ * \ingroup Geometry
+ * \brief Compute the closest entity in an AABB tree to a point (index and shortest squared distance)
+ * \param point the point
+ * \param tree the AABB tree
+ * \param minSquaredDistance conservative estimate of the minimum distance
+ *
+ * \note it is important that if an estimate is provided for minSquaredDistance to choose
+ *       this estimate to be larger than the expected result. If the minSquaredDistance is smaller
+ *       or equal to the result the returned entity index will be zero and the distance is equal
+ *       to the estimate. However, this can also be the correct result. When in doubt, use the
+ *       default parameter value.
+ */
+template<class EntitySet, class ctype, int dimworld>
+std::pair<ctype, std::size_t> closestEntity(const Dune::FieldVector<ctype, dimworld>& point,
+                                            const BoundingBoxTree<EntitySet>& tree,
+                                            ctype minSquaredDistance = std::numeric_limits<ctype>::max())
+{
+    std::size_t eIdx = 0;
+    Detail::closestEntity(point, tree, tree.numBoundingBoxes() - 1, minSquaredDistance, eIdx);
+    using std::sqrt;
+    return { minSquaredDistance, eIdx };
+}
+
+/*!
+ * \ingroup Geometry
+ * \brief Compute the shortest squared distance to entities in an AABB tree
+ */
+template<class EntitySet, class ctype, int dimworld>
+ctype squaredDistance(const Dune::FieldVector<ctype, dimworld>& point,
+                      const BoundingBoxTree<EntitySet>& tree,
+                      ctype minSquaredDistance = std::numeric_limits<ctype>::max())
+{
+    return closestEntity(point, tree, minSquaredDistance).first;
+}
+
+/*!
+ * \ingroup Geometry
+ * \brief Compute the shortest distance to entities in an AABB tree
+ */
+template<class EntitySet, class ctype, int dimworld>
+ctype distance(const Dune::FieldVector<ctype, dimworld>& point,
+               const BoundingBoxTree<EntitySet>& tree,
+               ctype minSquaredDistance = std::numeric_limits<ctype>::max())
+{
+    using std::sqrt;
+    return sqrt(squaredDistance(point, tree, minSquaredDistance));
+}
+
 } // end namespace Dumux
 
 #endif