diff --git a/point.hpp b/point.hpp index ff857d8a..5f437fa4 100644 --- a/point.hpp +++ b/point.hpp @@ -50,6 +50,9 @@ namespace util { template constexpr typename std::common_type::type distance2 (point, point); + template + constexpr typename std::common_type::type octile (point, point); + template constexpr typename std::common_type::type manhattan (point, point); diff --git a/point.ipp b/point.ipp index 6bf7aa44..e816c9c9 100644 --- a/point.ipp +++ b/point.ipp @@ -73,6 +73,30 @@ namespace util { } + //------------------------------------------------------------------------- + template + constexpr typename std::common_type::type + octile (point a, point b) + { + using type_t = typename std::common_type::type; + static_assert (!std::is_integral::value, + "octile requires more than integer precision"); + + const type_t D1 = 1; + const type_t D2 = std::sqrt (type_t {2}); + + auto diff = util::abs (a - b); + + // distance for axis-aligned walks + auto axis = D1 * (diff.x + diff.y); + + // the savings from diagonal walks + auto diag = (D2 - 2 * D1) * util::min (diff); + + return axis + diag; + } + + //------------------------------------------------------------------------- template constexpr typename std::common_type::type