Skip to content

Commit

Permalink
Port line function implementations
Browse files Browse the repository at this point in the history
  • Loading branch information
jbytheway committed Aug 19, 2019
1 parent 4296512 commit e85578b
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 78 deletions.
96 changes: 35 additions & 61 deletions src/line.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,49 +16,47 @@

extern bool trigdist;

void bresenham( const int x1, const int y1, const int x2, const int y2, int t,
void bresenham( const point &p1, const point &p2, int t,
const std::function<bool( const point & )> &interact )
{
// The slope components.
const int dx = x2 - x1;
const int dy = y2 - y1;
const point d = p2 - p1;
// Signs of slope values.
const int sx = ( dx == 0 ) ? 0 : sgn( dx );
const int sy = ( dy == 0 ) ? 0 : sgn( dy );
const int sx = ( d.x == 0 ) ? 0 : sgn( d.x );
const int sy = ( d.y == 0 ) ? 0 : sgn( d.y );
// Absolute values of slopes x2 to avoid rounding errors.
const int ax = abs( dx ) * 2;
const int ay = abs( dy ) * 2;
const point a = abs( d ) * 2;

point cur( x1, y1 );
point cur = p1;

if( ax == ay ) {
while( cur.x != x2 ) {
if( a.x == a.y ) {
while( cur.x != p2.x ) {
cur.y += sy;
cur.x += sx;
if( !interact( cur ) ) {
break;
}
}
} else if( ax > ay ) {
while( cur.x != x2 ) {
} else if( a.x > a.y ) {
while( cur.x != p2.x ) {
if( t > 0 ) {
cur.y += sy;
t -= ax;
t -= a.x;
}
cur.x += sx;
t += ay;
t += a.y;
if( !interact( cur ) ) {
break;
}
}
} else {
while( cur.y != y2 ) {
while( cur.y != p2.y ) {
if( t > 0 ) {
cur.x += sx;
t -= ay;
t -= a.y;
}
cur.y += sy;
t += ax;
t += a.x;
if( !interact( cur ) ) {
break;
}
Expand Down Expand Up @@ -198,28 +196,23 @@ void bresenham( const tripoint &loc1, const tripoint &loc2, int t, int t2,

//Trying to pull points out of a tripoint vector is messy and
//probably slow, so leaving two full functions for now
std::vector<point> line_to( const int x1, const int y1, const int x2, const int y2, int t )
std::vector<point> line_to( const point &p1, const point &p2, int t )
{
std::vector<point> line;
// Preallocate the number of cells we need instead of allocating them piecewise.
const int numCells = square_dist( tripoint( x1, y1, 0 ), tripoint( x2, y2, 0 ) );
const int numCells = square_dist( p1, p2 );
if( numCells == 0 ) {
line.push_back( {x1, y1} );
line.push_back( p1 );
} else {
line.reserve( numCells );
bresenham( x1, y1, x2, y2, t, [&line]( const point & new_point ) {
bresenham( p1, p2, t, [&line]( const point & new_point ) {
line.push_back( new_point );
return true;
} );
}
return line;
}

std::vector<point> line_to( const point &p1, const point &p2, const int t )
{
return line_to( p1.x, p1.y, p2.x, p2.y, t );
}

std::vector <tripoint> line_to( const tripoint &loc1, const tripoint &loc2, int t, int t2 )
{
std::vector<tripoint> line;
Expand All @@ -237,11 +230,6 @@ std::vector <tripoint> line_to( const tripoint &loc1, const tripoint &loc2, int
return line;
}

float trig_dist( const int x1, const int y1, const int x2, const int y2 )
{
return trig_dist( tripoint( x1, y1, 0 ), tripoint( x2, y2, 0 ) );
}

float trig_dist( const point &loc1, const point &loc2 )
{
return trig_dist( tripoint( loc1, 0 ), tripoint( loc2, 0 ) );
Expand All @@ -254,30 +242,16 @@ float trig_dist( const tripoint &loc1, const tripoint &loc2 )
( ( loc1.z - loc2.z ) * ( loc1.z - loc2.z ) ) );
}

int square_dist( const int x1, const int y1, const int x2, const int y2 )
{
return square_dist( point( x1, y1 ), point( x2, y2 ) );
}

int square_dist( const point &loc1, const point &loc2 )
{
const int dx = abs( loc1.x - loc2.x );
const int dy = abs( loc1.y - loc2.y );
return dx > dy ? dx : dy;
const point d = abs( loc1 - loc2 );
return std::max( d.x, d.y );
}

int square_dist( const tripoint &loc1, const tripoint &loc2 )
{
const int dx = abs( loc1.x - loc2.x );
const int dy = abs( loc1.y - loc2.y );
const int dz = abs( loc1.z - loc2.z );
int maxDxDy = ( dx > dy ? dx : dy ); // Sloppy, but should be quick.
return ( maxDxDy > dz ? maxDxDy : dz ); // Too bad it doesn't scale.
}

int rl_dist( const int x1, const int y1, const int x2, const int y2 )
{
return rl_dist( tripoint( x1, y1, 0 ), tripoint( x2, y2, 0 ) );
const tripoint d = abs( loc1 - loc2 );
return std::max( { d.x, d.y, d.z } );
}

int rl_dist( const point &a, const point &b )
Expand Down Expand Up @@ -406,9 +380,9 @@ direction direction_from( const tripoint &p ) noexcept
return static_cast<direction>( make_xyz( p ) );
}

direction direction_from( const int x1, const int y1, const int x2, const int y2 ) noexcept
direction direction_from( const point &p1, const point &p2 ) noexcept
{
return direction_from( point( x2 - x1, y2 - y1 ) );
return direction_from( p2 - p1 );
}

direction direction_from( const tripoint &p, const tripoint &q )
Expand Down Expand Up @@ -557,24 +531,24 @@ std::vector<tripoint> squares_closer_to( const tripoint &from, const tripoint &t

// Returns a vector of the adjacent square in the direction of the target,
// and the two squares flanking it.
std::vector<point> squares_in_direction( const int x1, const int y1, const int x2, const int y2 )
std::vector<point> squares_in_direction( const point &p1, const point &p2 )
{
int junk = 0;
point center_square = line_to( x1, y1, x2, y2, junk )[0];
point center_square = line_to( p1, p2, junk )[0];
std::vector<point> adjacent_squares;
adjacent_squares.push_back( center_square );
if( x1 == center_square.x ) {
if( p1.x == center_square.x ) {
// Horizontally adjacent.
adjacent_squares.push_back( point( x1 + 1, center_square.y ) );
adjacent_squares.push_back( point( x1 - 1, center_square.y ) );
} else if( y1 == center_square.y ) {
adjacent_squares.push_back( point( p1.x + 1, center_square.y ) );
adjacent_squares.push_back( point( p1.x - 1, center_square.y ) );
} else if( p1.y == center_square.y ) {
// Vertically adjacent.
adjacent_squares.push_back( point( center_square.x, y1 + 1 ) );
adjacent_squares.push_back( point( center_square.x, y1 - 1 ) );
adjacent_squares.push_back( point( center_square.x, p1.y + 1 ) );
adjacent_squares.push_back( point( center_square.x, p1.y - 1 ) );
} else {
// Diagonally adjacent.
adjacent_squares.push_back( point( x1, center_square.y ) );
adjacent_squares.push_back( point( center_square.x, y1 ) );
adjacent_squares.push_back( point( p1.x, center_square.y ) );
adjacent_squares.push_back( point( center_square.x, p1.y ) );
}
return adjacent_squares;
}
Expand Down
19 changes: 2 additions & 17 deletions src/line.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,6 @@ enum direction : unsigned {

direction direction_from( const point &p ) noexcept;
direction direction_from( const tripoint &p ) noexcept;
direction direction_from( int x1, int y1, int x2, int y2 ) noexcept;
direction direction_from( const point &p1, int x2, int y2 ) noexcept;
direction direction_from( const point &p1, const point &p2 ) noexcept;
direction direction_from( const tripoint &p, const tripoint &q );

Expand All @@ -99,10 +97,6 @@ std::string direction_suffix( const tripoint &p, const tripoint &q );
* The actual Bresenham algorithm in 2D and 3D, everything else should call these
* and pass in an interact functor to iterate across a line between two points.
*/
void bresenham( int x1, int y1, int x2, int y2, int t,
const std::function<bool( const point & )> &interact );
void bresenham( const point &p1, int x2, int y2, int t,
const std::function<bool( const point & )> &interact );
void bresenham( const point &p1, const point &p2, int t,
const std::function<bool( const point & )> &interact );
void bresenham( const tripoint &loc1, const tripoint &loc2, int t, int t2,
Expand All @@ -111,25 +105,18 @@ void bresenham( const tripoint &loc1, const tripoint &loc2, int t, int t2,
tripoint move_along_line( const tripoint &loc, const std::vector<tripoint> &line,
int distance );
// The "t" value decides WHICH Bresenham line is used.
std::vector<point> line_to( int x1, int y1, int x2, int y2, int t = 0 );
std::vector<point> line_to( const point &p1, int x2, int y2, int t = 0 );
std::vector<point> line_to( const point &p1, const point &p2, int t = 0 );
// t and t2 decide which Bresenham line is used.
std::vector<tripoint> line_to( const tripoint &loc1, const tripoint &loc2, int t = 0, int t2 = 0 );
// sqrt(dX^2 + dY^2)
float trig_dist( int x1, int y1, int x2, int y2 );
float trig_dist( const point &p1, int x2, int y2 );
float trig_dist( const point &loc1, const point &loc2 );
float trig_dist( const tripoint &loc1, const tripoint &loc2 );
// Roguelike distance; minimum of dX and dY
int square_dist( int x1, int y1, int x2, int y2 );
int square_dist( const point &p1, int x2, int y2 );
int square_dist( const point &loc1, const point &loc2 );
int square_dist( const tripoint &loc1, const tripoint &loc2 );
int rl_dist( int x1, int y1, int x2, int y2 );
int rl_dist( const point &p1, int x2, int y2 );
int rl_dist( const tripoint &loc1, const tripoint &loc2 );
// Choose between the above two according to the "circular distances" option
int rl_dist( const point &a, const point &b );
int rl_dist( const tripoint &loc1, const tripoint &loc2 );
// Sum of distance in both axes
int manhattan_dist( const point &loc1, const point &loc2 );

Expand All @@ -140,8 +127,6 @@ double atan2_degrees( const point & );
// Get the magnitude of the slope ranging from 0.0 to 1.0
float get_normalized_angle( const point &start, const point &end );
std::vector<tripoint> continue_line( const std::vector<tripoint> &line, int distance );
std::vector<point> squares_in_direction( int x1, int y1, int x2, int y2 );
std::vector<point> squares_in_direction( const point &p1, int x2, int y2 );
std::vector<point> squares_in_direction( const point &p1, const point &p2 );
// Returns a vector of squares adjacent to @from that are closer to @to than @from is.
// Currently limited to the same z-level as @from.
Expand Down

0 comments on commit e85578b

Please sign in to comment.