Функция принимает двухмерные координаты начала и конца отрезка линии, причем реальные, а не целочисленные (структуры PointF). Функция растеризует данную линию, вызывая некую PutPixel( int x, int y ) для всех точек (x, y) растра, которые КАСАЮТСЯ данного отрезка. Исходник написан на C#. Функция отлажена и протестирована в жестких условиях.
P.S. Стоит уточнить. Алгоритм работает так, что координаты (0,0) соответствуют углу пикселя растра, а не его центру. Центр же точки растра будет иметь координаты (0.5, 0.5).
public void RasterizeLine( PointF start, PointF end )
{
float lineDx = end.X - start.X;
float lineDy = end.Y - start.Y;
// Horizontal tracing.
if ( Math.Abs( lineDx ) >= Math.Abs( lineDy ) )
{
// Swap points.
if ( lineDx < 0 )
{
lineDx *= -1;
lineDy *= -1;
PointF temp = start;
start = end;
end = temp;
}
PointF dv = new PointF( 1, lineDy / lineDx );
int x = (int)Math.Floor( start.X );
int y = (int)Math.Floor( start.Y );
int endX = (int)Math.Ceiling( end.X );
int endY = (int)Math.Floor( end.Y );
// Line(x) = Y0 + dY/dX * (x - X0);
// Get point V = Line( x );
PointF v = new PointF( x, start.Y + ( x - start.X ) * dv.Y );
if ( lineDy > 0 )
{
while ( x != endX )
{
PutPixel( x, y );
v.X += dv.X; v.Y += dv.Y;
if ( ( v.Y > y + 1 ) && ( y != endY ) )
PutPixel( x, ++y );
x++;
}
}
else
{
while ( x != endX )
{
PutPixel( x, y );
v.X += dv.X; v.Y += dv.Y;
if ( ( v.Y < y ) && ( y != endY ) )
PutPixel( x, --y );
x++;
}
}
}
else // Vertical tracing.
{
if ( lineDy < 0 )
{
lineDx *= -1;
lineDy *= -1;
PointF temp = start;
start = end;
end = temp;
}
PointF dv = new PointF( lineDx / lineDy, 1 );
int x = (int)Math.Floor( start.X );
int y = (int)Math.Floor( start.Y );
int endX = (int)Math.Floor( end.X );
int endY = (int)Math.Ceiling( end.Y );
PointF v = new PointF(start.X + ( y - start.Y ) * dv.X, y);
if ( lineDx > 0 )
{
while ( y != endY )
{
PutPixel( x, y );
v.X += dv.X; v.Y += dv.Y;
if ( ( v.X > x + 1 ) && ( x != endX ) )
PutPixel( ++x, y );
y++;
}
}
else
{
while ( y != endY )
{
PutPixel( x, y );
v.X += dv.X; v.Y += dv.Y;
if ( ( v.X < x ) && ( x != endX ) )
PutPixel( --x, y );
y++;
}
}
}
}