diff --git a/include/kami/grid.h b/include/kami/grid.h index 20c6bef..e820a06 100644 --- a/include/kami/grid.h +++ b/include/kami/grid.h @@ -110,7 +110,30 @@ namespace kami { * * @details All gridded coordinates are expected to subclass `GridCoord`. */ - class LIBKAMI_EXPORT GridCoord : public Coord {}; + class LIBKAMI_EXPORT GridCoord : public Coord { + + public: + + /** + * @brief Find the distance between two points + * + * @details Find the distance between two points using the + * specified metric. There are three options provided by + * the `GridDistanceType` class. + * + * However, the coordinate class is not aware of the + * properties of the `GridDomain` it is operating on. Accordingly, + * if the direct path is measured, without accounting for + * and toroidal wrapping of the underlying `GridDomain`. + * + * @param p the point to measure the distance to + * @param distance_type specify the distance type + * + * @returns the distance as a `double` + */ + virtual std::optional distance(std::shared_ptr &p, GridDistanceType distance_type) const = 0; + + }; } // namespace kami diff --git a/include/kami/grid1d.h b/include/kami/grid1d.h index aaa8386..35b3a50 100644 --- a/include/kami/grid1d.h +++ b/include/kami/grid1d.h @@ -64,6 +64,28 @@ namespace kami { */ [[nodiscard]] std::string to_string() const override; + /** + * @brief Find the distance between two points + * + * @details Find the distance between two points using the + * specified metric. There are three options provided by + * the `GridDistanceType` class. However, of the three + * distance types provided, all provide the same result so + * the value is ignored and the single result is returned. + * + * However, the coordinate class is not aware of the + * properties of the `Grid1D` it is operating on. Accordingly, + * if the direct path is measured, without accounting for + * and toroidal wrapping of the underlying `Grid1D`. + * + * @param p the point to measure the distance to + * @param distance_type specify the distance type + * + * @returns the distance as a `double` + */ + std::optional + distance(std::shared_ptr &p, [[maybe_unused]] GridDistanceType distance_type) const override; + /** * @brief Test if two coordinates are equal */ diff --git a/include/kami/grid2d.h b/include/kami/grid2d.h index 147bb43..ee16bca 100644 --- a/include/kami/grid2d.h +++ b/include/kami/grid2d.h @@ -29,6 +29,8 @@ #define KAMI_GRID2D_H //! @endcond +#include +#include #include #include #include @@ -46,12 +48,25 @@ namespace kami { * @brief Two-dimensional coordinates */ class LIBKAMI_EXPORT GridCoord2D : public GridCoord { + protected: + inline double distance_chebyshev(std::shared_ptr &p) const { + return static_cast(fmax(abs(_x_coord - p->_x_coord), abs(_x_coord - p->_x_coord))); + }; + + inline double distance_euclidean(std::shared_ptr &p) const { + return sqrt(pow(_x_coord - p->_x_coord, 2) + pow(_x_coord - p->_x_coord, 2)); + }; + + inline double distance_manhattan(std::shared_ptr &p) const { + return static_cast(abs(_x_coord - p->_x_coord) + abs(_x_coord - p->_x_coord)); + }; + public: /** * @brief Constructor for two-dimensional coordinates */ GridCoord2D(int x_coord, int y_coord) - : _x_coord(x_coord), _y_coord(y_coord){}; + : _x_coord(x_coord), _y_coord(y_coord) {}; /** * @brief Get the coordinate in the first dimension or `x`. @@ -70,6 +85,25 @@ namespace kami { */ [[nodiscard]] std::string to_string() const override; + /** + * @brief Find the distance between two points + * + * @details Find the distance between two points using the + * specified metric. There are three options provided by + * the `GridDistanceType` class. + * + * However, the coordinate class is not aware of the + * properties of the `Grid2D` it is operating on. Accordingly, + * if the direct path is measured, without accounting for + * and toroidal wrapping of the underlying `Grid2D`. + * + * @param p the point to measure the distance to + * @param distance_type specify the distance type + * + * @returns the distance as a `double` + */ + std::optional distance(std::shared_ptr &p, GridDistanceType distance_type) const override; + /** * @brief Test if two coordinates are equal */ diff --git a/src/libkami/grid1d.cc b/src/libkami/grid1d.cc index 165ee00..84e84be 100644 --- a/src/libkami/grid1d.cc +++ b/src/libkami/grid1d.cc @@ -45,6 +45,14 @@ namespace kami { return std::string("(" + std::to_string(_x_coord) + ")"); } + std::optional + GridCoord1D::distance(std::shared_ptr &p, [[maybe_unused]] GridDistanceType distance_type) const { + // We are going to ignore distance type since they all + // have the same result in one dimension. + auto p1d = std::static_pointer_cast(p); + return static_cast(abs(_x_coord - p1d->_x_coord)); + } + bool operator==(const GridCoord1D &lhs, const GridCoord1D &rhs) { return (lhs._x_coord == rhs._x_coord); } diff --git a/src/libkami/grid2d.cc b/src/libkami/grid2d.cc index 168ba37..54755a9 100644 --- a/src/libkami/grid2d.cc +++ b/src/libkami/grid2d.cc @@ -48,6 +48,20 @@ namespace kami { return std::string("(" + std::to_string(_x_coord) + ", " + std::to_string(_y_coord) + ")"); } + std::optional GridCoord2D::distance(std::shared_ptr &p, GridDistanceType distance_type) const { + auto p2d = std::static_pointer_cast(p); + + switch (distance_type) { + case GridDistanceType::Chebyshev: + return distance_chebyshev(p2d); + case GridDistanceType::Manhattan: + return distance_manhattan(p2d); + case GridDistanceType::Euclidean: + return distance_euclidean(p2d); + } + return std::nullopt; + } + bool operator==(const GridCoord2D &lhs, const GridCoord2D &rhs) { return (lhs._x_coord == rhs._x_coord && lhs._y_coord == rhs._y_coord); }