@@ -117,21 +117,42 @@ std::istream &operator>>( std::istream &is, tripoint &pos )
117117 return is;
118118}
119119
120+ std::optional<int > rectangle_size ( int min_dist, int max_dist )
121+ {
122+ min_dist = std::max ( min_dist, 0 );
123+ max_dist = std::max ( max_dist, 0 );
124+
125+ if ( min_dist > max_dist ) {
126+ return std::nullopt ;
127+ }
128+
129+ const int min_edge = min_dist * 2 + 1 ;
130+ const int max_edge = max_dist * 2 + 1 ;
131+
132+ const int n = max_edge * max_edge - ( min_edge - 2 ) * ( min_edge - 2 ) + ( min_dist == 0 ? 1 : 0 );
133+ return n;
134+ }
135+
120136std::vector<tripoint> closest_points_first ( const tripoint ¢er, int max_dist )
121137{
122138 return closest_points_first ( center, 0 , max_dist );
123139}
124140
125141std::vector<tripoint> closest_points_first ( const tripoint ¢er, int min_dist, int max_dist )
126142{
127- const std::vector<point> points = closest_points_first ( center.xy (), min_dist, max_dist );
143+ std::optional<int > n = rectangle_size ( min_dist, max_dist );
144+
145+ if ( n == std::nullopt ) {
146+ return {};
147+ }
128148
129149 std::vector<tripoint> result;
130- result.reserve ( points. size () );
150+ result.reserve ( *n );
131151
132- for ( const point &p : points ) {
133- result.emplace_back ( p, center.z );
134- }
152+ find_point_closest_first ( center, min_dist, max_dist, [&result]( const tripoint & p ) {
153+ result.push_back ( p );
154+ return false ;
155+ } );
135156
136157 return result;
137158}
@@ -143,42 +164,26 @@ std::vector<point> closest_points_first( const point ¢er, int max_dist )
143164
144165std::vector<point> closest_points_first ( const point ¢er, int min_dist, int max_dist )
145166{
146- min_dist = std::max ( min_dist, 0 );
147- max_dist = std::max ( max_dist, 0 );
167+ std::optional<int > n = rectangle_size ( min_dist, max_dist );
148168
149- if ( min_dist > max_dist ) {
169+ if ( n == std:: nullopt ) {
150170 return {};
151171 }
152172
153- const int min_edge = min_dist * 2 + 1 ;
154- const int max_edge = max_dist * 2 + 1 ;
155-
156- const int n = max_edge * max_edge - ( min_edge - 2 ) * ( min_edge - 2 );
157- const bool is_center_included = min_dist == 0 ;
158-
159173 std::vector<point> result;
160- result.reserve ( n + ( is_center_included ? 1 : 0 ) );
161-
162- if ( is_center_included ) {
163- result.push_back ( center );
164- }
174+ result.reserve ( *n );
165175
166- int x_init = std::max ( min_dist, 1 );
167- point p ( x_init, 1 - x_init );
168-
169- point d ( point::east );
170-
171- for ( int i = 0 ; i < n; i++ ) {
172- result.push_back ( center + p );
173-
174- if ( p.x == p.y || ( p.x < 0 && p.x == -p.y ) || ( p.x > 0 && p.x == 1 - p.y ) ) {
175- std::swap ( d.x , d.y );
176- d.x = -d.x ;
177- }
178-
179- p.x += d.x ;
180- p.y += d.y ;
181- }
176+ find_point_closest_first ( center, min_dist, max_dist, [&result]( const point & p ) {
177+ result.push_back ( p );
178+ return false ;
179+ } );
182180
183181 return result;
184182}
183+
184+ template <typename PredicateFn, typename Point>
185+ std::optional<Point> find_point_closest_first ( const Point ¢er, int max_dist,
186+ PredicateFn &&fn )
187+ {
188+ return find_point_closest_first ( center, 0 , max_dist, fn );
189+ }
0 commit comments