Skip to content

Commit

Permalink
Add a variant of closest_points_first that takes a predicate
Browse files Browse the repository at this point in the history
Part of CleverRaven#75945. The variant will be used in pathfinding to find the nearest
ramp or stairs without having to enumerate all points.
  • Loading branch information
CLIDragon committed Aug 26, 2024
1 parent 18b13f1 commit 30d0ada
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 20 deletions.
24 changes: 4 additions & 20 deletions src/point.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,26 +159,10 @@ std::vector<point> closest_points_first( const point &center, int min_dist, int
std::vector<point> result;
result.reserve( n + ( is_center_included ? 1 : 0 ) );

if( is_center_included ) {
result.push_back( center );
}

int x_init = std::max( min_dist, 1 );
point p( x_init, 1 - x_init );

point d( point_east );

for( int i = 0; i < n; i++ ) {
result.push_back( center + p );

if( p.x == p.y || ( p.x < 0 && p.x == -p.y ) || ( p.x > 0 && p.x == 1 - p.y ) ) {
std::swap( d.x, d.y );
d.x = -d.x;
}

p.x += d.x;
p.y += d.y;
}
find_point_closest_first( center, min_dist, max_dist, [&result]( const point & p ) {
result.push_back( p );
return false;
} );

return result;
}
52 changes: 52 additions & 0 deletions src/point.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <cstdint>
#include <cstdlib>
#include <functional>
#include <optional>
#include <ostream>
#include <vector>

Expand Down Expand Up @@ -290,6 +291,11 @@ std::vector<tripoint> closest_points_first( const tripoint &center, int min_dist
std::vector<point> closest_points_first( const point &center, int max_dist );
std::vector<point> closest_points_first( const point &center, int min_dist, int max_dist );

// TODO: Make this into an Input Iterator.
template <typename PredicateFn>
std::optional<point> find_point_closest_first( const point &center, int min_dist, int max_dist,
PredicateFn &&fn );

inline constexpr tripoint tripoint_min { INT_MIN, INT_MIN, INT_MIN };
inline constexpr tripoint tripoint_max{ INT_MAX, INT_MAX, INT_MAX };

Expand Down Expand Up @@ -363,4 +369,50 @@ inline const std::array<tripoint, 8> eight_horizontal_neighbors = { {
}
};

template <typename PredicateFn>
std::optional<point> find_point_closest_first( const point &center, int min_dist, int max_dist,
PredicateFn &&predicate_fn )
{
min_dist = std::max( min_dist, 0 );
max_dist = std::max( max_dist, 0 );

if( min_dist > max_dist ) {
return std::nullopt;
}

const int min_edge = min_dist * 2 + 1;
const int max_edge = max_dist * 2 + 1;

const int n = max_edge * max_edge - ( min_edge - 2 ) * ( min_edge - 2 );
const bool is_center_included = min_dist == 0;

if( is_center_included ) {
if( predicate_fn( center ) ) {
return center;
}
}

int x_init = std::max( min_dist, 1 );
point p( x_init, 1 - x_init );

point d( point_east );

for( int i = 0; i < n; i++ ) {
const point next = center + p;
if( predicate_fn( next ) ) {
return next;
}

if( p.x == p.y || ( p.x < 0 && p.x == -p.y ) || ( p.x > 0 && p.x == 1 - p.y ) ) {
std::swap( d.x, d.y );
d.x = -d.x;
}

p.x += d.x;
p.y += d.y;
}

return std::nullopt;
}

#endif // CATA_SRC_POINT_H

0 comments on commit 30d0ada

Please sign in to comment.