Растеризация отрезка линии (пересечение отрезка и растра)
От: AntoxaDG  
Дата: 10.09.07 12:56
Оценка:
Функция принимает двухмерные координаты начала и конца отрезка линии, причем реальные, а не целочисленные (структуры 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++;
            }
        }
    }
}
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.