Skip to content

Instantly share code, notes, and snippets.

@maxtruxa
Last active August 29, 2015 14:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maxtruxa/facc3cbcb32f06d63630 to your computer and use it in GitHub Desktop.
Save maxtruxa/facc3cbcb32f06d63630 to your computer and use it in GitHub Desktop.
#include "StdAfx.h"
#include <cmath>
bresenham_line::bresenham_line()
: _x{}, _y{}, _error{}, _first_iteration{} { }
void bresenham_line::initialize(point_t const& start, point_t const& end)
{
this->initialize(start.X, start.Y, end.X, end.Y);
}
void bresenham_line::initialize(int start_x, int start_y, int end_x, int end_y)
{
this->_x = this->initialize_direction(start_x, end_x);
this->_y = this->initialize_direction(start_y, end_y);
if (this->_x.delta >= this->_y.delta) {
this->_error = this->_y.delta - (this->_x.delta >> 1);
} else {
this->_error = this->_x.delta - (this->_y.delta >> 1);
}
this->_first_iteration = true;
}
bool bresenham_line::next_point(point_t& point)
{
int x;
int y;
bool result = this->next_point(x, y);
point.X = x;
point.Y = y;
return result;
}
bool bresenham_line::next_point(int& x, int& y)
{
if (this->_first_iteration) {
// First iteration; return the very first point (same as start point passed to initialize).
x = this->_x.current;
y = this->_y.current;
this->_first_iteration = false;
return true;
}
bool x_is_primary = this->_x.delta >= this->_y.delta;
directional_context_t& direction1 = x_is_primary ? this->_x : this->_y;
directional_context_t& direction2 = x_is_primary ? this->_y : this->_x;
if (direction1.current == direction1.end) {
// Already at end; just return the last point again.
x = this->_x.current;
y = this->_y.current;
return false;
}
if ((this->_error >= 0) && (this->_error || direction1.step > 0)) {
this->_error -= direction1.delta;
direction2.current += direction2.step;
}
this->_error += direction2.delta;
direction1.current += direction1.step;
x = this->_x.current;
y = this->_y.current;
return true;
}
bresenham_line::directional_context_t bresenham_line::initialize_direction(int start, int end)
{
int delta = end - start;
// step == 0 if x == 0
// step == 1 if x > 0
// step == -1 if x < 0
int step{static_cast<int>(delta > 0) - static_cast<int>(delta < 0)};
delta = std::abs(delta) << 1;
return directional_context_t{start, end, delta, step};
}
#pragma once
class bresenham_line
{
public:
typedef COORD point_t;
bresenham_line();
void initialize(point_t const& start, point_t const& end);
void initialize(int start_x, int start_y, int end_x, int end_y);
bool next_point(point_t& point);
bool next_point(int& x, int& y);
private:
struct directional_context_t
{
int current;
int end;
int delta;
int step;
};
directional_context_t initialize_direction(int start, int end);
directional_context_t _x;
directional_context_t _y;
int _error;
bool _first_iteration;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment