[Algorithmstaff] Bresenham Fast Linear algorithm

Source: Internet
Author: User

Operating system: Windows8.1

Graphics: Nivida gtx965m

Development tools: Unity2017.3 | Nativec

Recently when learning Unity tilemap Brush Custom brush function, see its linear brush Linebrush is implemented using Bresenham algorithm, so take this opportunity to record the learning process here, and finally give a complete implementation.

Introduction

The Bresenham is a rasterized linear algorithm, or a straight-line simulation through the like. For example, the pixel dots are shown to simulate a red line.

Given two beginnings P1 (x1, y1) | P2 (x2, y2), how to draw a connection between two points. Assuming that the slope is constrained here, then the algorithm's process is as follows:

    1. Draws the starting point (x1, y1) .
    2. Draw the next point, the x-coordinate plus 1, to determine whether to the end, if the algorithm is completed. Otherwise, find the next point, the point is to be drawn is not the right neighbor, or the upper right adjacency point.
    3. Draws a point.
    4. Jump back to the second step.
    5. End.

The exact process of the algorithm is to select the point with the smallest difference in the y-coordinate of the intersection of the line each time the point is plotted, as shown in:

So the question focuses on how to find the nearest point, logically every timexare incremented1ythen increase1or no increase. Specifically, the assumption has been drawn to theD1Point, then the nextxAdd1, but chooseD2Still isuPoint, intuitively, you know.D2With the target line andx + 1The intersection of the line is close, that is, the difference between the ordinate is small. Other words(x + 1, y + 1)Point ordinate difference is greater than0.5。 So chooseD2, and other points are executed according to the rule.

The Basic Bresenham

Assume (x, y) to draw the starting point, the general visual idea is to ask m = dy/dx ( y Increments of ), and then incrementally x ,  set a new point to x1 = x + j  , then y1 = round (y + j * m)   . As you can see, this process involves a lot of floating-point arithmetic, which is inefficient (especially in embedded applications, where the DSP can do 2 multiplication in one cycle, and one floating point is hundreds of cycles).

Let's take a look at bresenham Algorithm, 1, (x, y +ε) The next point is (x, y + ε+ m) , here ε The is a cumulative error. As you can see, when Ε+m < 0.5 , Draw (x + 1, y) Point, otherwise draw (x + 1, y + 1) Point. After each draw, ε will be updated to the new value:

ε=ε+ m , if (ε+ m) <0.5 (or represented as 2 * (ε+ m) < 1 )

ε=ε+ m–1, other cases

Multiply the above formula by DX and ε* DX with the new symbol ξ , which can be

ξ=ξ+ dy, if 2 * (ξ+ dy) < DX

ξ=ξ+ DY–DX, other cases

As you can see, the operation has all become integers. The following is the pseudo-code for the algorithm:

Ξ←0,y←y1

For x←x1 to X2 do

Plot Point at (x, y)

If (2 (ξ+ dy) < DX)

ξ←ξ+ dy

Else

Y←y + 1,ξ←ξ+ DY–DX

End If

End for

handing multiple slopes

In practical applications, we will find that when dy > dx or the right side of the case, the desired result is not obtained, this is because we only consider dx > dy, and (x, y) the increment is positive. After analysis, there are 8 different partitioning scenarios to consider, as shown in:

Of course, if the 8 cases are enumerated directly in the algorithm, then the duplicated code will be very bloated, so in the design of the algorithm must fully consider the generality of the above-mentioned situations. For example, the right side X positive and negative partition is only the relationship between the Y -axis mirroring, in the implementation of the specific set of the correct increment direction.

Implementation

The following is a C language-based implementation:

voidDraw_line (intX1,intY1,intX2,inty2) {    intDX = x2-X1; intdy = y2-Y1; intUX = (dx >0) <<1) -1; intUy = ((Dy >0) <<1) -1; intx = x1, y =Y1, EPS; EPS=0; DX = ABS (DX); DY =abs (DY); if(DX >dy) {         for(x = x1; x! = x2; x + =UX) {printf ("x =%d y =%d\n", x, y); EPS+=dy; if(EPS <<1) >=dx) {y+ = Uy; EPS-=DX; }        }    }    Else    {         for(y = y1; Y! = y2; y + =Uy) {printf ("x =%d y =%d\n", x, y); EPS+=DX; if(EPS <<1) >=dy) {x+ = UX; EPS-=dy; }        }    }}

The test data were Green line segments, starting point ( 10,10) and Blue Line, starting point ( 1, ten) end point (10,1).

The test data is a brown line, a start point ( 2,10) end point ( 4,1) , and a start point ( 6,9) endpoint ( 10,1) .

By populating the table with the test data that the program runs, you can visually see the connection path of the segment between two points.

Based on Unity

The Unity official example has given a C # implementation based on the following code:

// http://ericw.ca/notes/bresenhams-line-algorithm-in-csharp.html         Public StaticIenumerable<vector2int>getpointsonline (vector2int p1, vector2int p2) {intx0 =p1.x; intY0 =p1.y; intX1 =p2.x; intY1 =p2.y; BOOLSteep = Math.Abs (y1-y0) > Math.Abs (x1-x0); if(steep) {intT; T= x0;//swap x0 and y0x0 =y0; Y0=T; T= x1;//swap x1 and y1X1 =Y1; Y1=T; }            if(X0 >x1) {                intT; T= x0;//swap x0 and X1x0 =X1; X1=T; T= y0;//swap y0 and Y1Y0 =Y1; Y1=T; }            intDX = x1-x0; intDY = Math.Abs (Y1-y0); intError = DX/2; intYstep = (y0 < y1)?1: -1; inty =y0;  for(intx = x0; x <= x1; X + +)            {                yield return NewVector2int (Steep y:x), (steep?x:y)); Error= Error-dy; if(Error <0) {y+=Ystep; Error+=DX; }            }            yield  Break; }

Finally, the two previous sets of data are brought into unity to verify the consistency of the results:

You can see that the data results from the previous program algorithm output are consistent with the C # implementation results that unity uses.

Summary

Resources:

http://blog.csdn.net/jinbing_peng/article/details/44797993

Https://www.cnblogs.com/gamesky/archive/2012/08/21/2648623.html

Http://www.cnblogs.com/pheye/archive/2010/08/14/1799803.html

[Algorithmstaff] Bresenham Fast Linear algorithm

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.