{"id":3315,"date":"2024-12-23T17:52:26","date_gmt":"2024-12-23T17:52:26","guid":{"rendered":"https:\/\/www.byteblueprints.com\/?p=3315"},"modified":"2025-05-05T14:24:12","modified_gmt":"2025-05-05T14:24:12","slug":"how-computers-draw-lines-part-2-math-behind-breshenham-algorithm","status":"publish","type":"post","link":"https:\/\/www.byteblueprints.com\/?p=3315","title":{"rendered":"How Computers Draw Lines Part 2 (Math Behind Breshenham Algorithm)"},"content":{"rendered":"\n<p>In mathematics, a straight line is represented by the equation $y = mx + c$:<\/p>\n\n\n\n<p>where <strong><em>m<\/em><\/strong> is the slope and <strong><em>c<\/em><\/strong> is the <strong><em>y-intercept<\/em><\/strong>. On paper, this equation allows us to draw a line smoothly, as points on the line can have continuous values (including decimals).<\/p>\n\n\n\n<p>However, in computer graphics, we face a challenge: displays consist of discrete pixels, so lines cannot be drawn with infinite precision. Instead, we must determine which pixels should be colored to best approximate the line. This process is called <strong><em>rasterization<\/em><\/strong>.<\/p>\n\n\n\n<p>Bresenham\u2019s line algorithm is a well-known method for <em><strong>rasterizing <\/strong><\/em>lines. Let\u2019s derive the key variables and equations for this algorithm using the basic line equation.<\/p>\n\n\n\n<p><strong><em>Note:<\/em> <em>A line can fall into one of eight octants, as shown in the image. To derive the equations for the Breshenham line drawing algorithm, we will focus on a line in the first octant, where the slope satisfies 0 \u2264 m \u2264 1<\/em><\/strong><em>.<\/em> <strong><em>Later, we can extend this to derive the equations for other octants.<\/em><\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"709\" height=\"395\" src=\"https:\/\/www.byteblueprints.com\/wp-content\/uploads\/2024\/12\/1paTZCgIBW3beB8TicUUXgA.png\" alt=\"\" class=\"wp-image-3324\"\/><\/figure>\n\n\n\n<p class=\"has-text-align-center\"><strong><em>Figure 1<\/em><\/strong><\/p>\n\n\n\n<p><strong><em>Assumption 1: In computer displays, pixel counting starts from the top-left corner. The x-coordinate increases to the right, and the y-coordinate increases downward. However, for simplicity in deriving equations, let\u2019s assume x and y follow the behavior of standard cartesian coordinates<\/em><\/strong>:<\/p>\n\n\n\n<p><strong><em>Assumption 2: Assume the center of a pixel represents its continuous value. This means the length of the $y_{k}$ pixel is the distance from the bottom-most point of the display to the center of the <strong><em>$y_{k}$<\/em><\/strong> pixel.<\/em><\/strong> <strong>(See <em>Figure 2<\/em><\/strong>)<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Understanding Pixel Selection<\/h4>\n\n\n\n<p>When drawing a line between two points, the line may pass between pixels. Consider the following situation<\/p>\n\n\n\n<p>As shown in the image below, let\u2019s assume we are currently at the <strong><em>k-th<\/em><\/strong> position for both <strong><em>x<\/em><\/strong> and <strong><em>y<\/em><\/strong>. Our task is to predict the next pixel to draw. Since we are in the first octant, we know the next <strong><em>x-coordinate<\/em><\/strong> will be <strong>$x_{k}$+<\/strong>1. However, we need to decide whether to color the current <strong><em><strong><em>$y_{k}$<\/em><\/strong><\/em><\/strong> pixel or the next <strong><em><strong><em>$y_{k}$<\/em><\/strong> +<\/em><\/strong><em>1<\/em> pixel.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"615\" height=\"613\" src=\"https:\/\/www.byteblueprints.com\/wp-content\/uploads\/2024\/12\/math-behind-the-bresh-graph-2_4-last.png\" alt=\"\" class=\"wp-image-3603\"\/><\/figure>\n\n\n\n<p class=\"has-text-align-center\"><strong><em>Figure 2<\/em><\/strong><\/p>\n\n\n\n<p>To make this decision, we need to calculate two values, <strong><em>d1<\/em><\/strong> and <strong><em>d2<\/em><\/strong>, and choose the pixel that is closer to the actual line to minimize visual error.<\/p>\n\n\n\n<p>We will define this decision as a parameter <strong><em>d<\/em><\/strong>, and our goal is to derive <strong><em>d<\/em><\/strong> from the line equation <strong><em>$y = mx + c$<\/em><\/strong>. Using this parameter, we can determine which <strong><em>y-value<\/em><\/strong> to color next.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">Derivation of Decision Variable(d)<\/h4>\n\n\n\n<p>The line equation is given as $y = mx + c$:<\/p>\n\n\n\n<p>Let the <strong><em>y-coordinate<\/em><\/strong> of the current pixel be <em>$y_{k}$<\/em>\u200b, and the next consecutive pixel in the <strong><em>y-direction<\/em><\/strong> be <em>$y_{k}$+1($y_{next}$)<\/em><strong><em>\u200b<\/em><\/strong>.<\/p>\n\n\n\n<p>Let the <strong><em>x-coordinate<\/em><\/strong> of the current pixel be <em>$x_{k}$<\/em><strong><em>\u200b<\/em><\/strong>, and the next consecutive pixel in the <strong><em>x-direction<\/em><\/strong> be <em><em>$x_{k}$+1($x_{next}$)<\/em><\/em>.<\/p>\n\n\n\n<p>Define key variables:<\/p>\n\n\n\n<p class=\"has-text-align-left\">$\\text{current x} = x_{k}$<br>$\\text{current y} = y_{k}$<br>$\\text{next x} = x_{next} = x_{k} + 1 \\text{ always }$<br>$\\text{next y} = y_{next} = y_{k} + 1 \\text{ or } y_{k}$<\/p>\n\n\n\n<p>The distances <strong><em>d1<\/em><\/strong>\u200b and <strong><em>d2<\/em><\/strong>\u200b are defined as:<\/p>\n\n\n\n<p class=\"has-text-align-left\">$y = y_{k} + d_{1}$<br>$d_{1} = y \\text{ } &#8211;  \\text{ } y_{k}$<br>$y_{k} + 1 = y + d_{2}$<br>$d_{2} = y_{k} + 1 \\text{ } &#8211;  \\text{ } y$<\/p>\n\n\n\n<p>Using the line equation <strong><em>$y = mx + c$<\/em><\/strong><\/p>\n\n\n\n<p>$d_{1} = y   \\text{ } &#8211;  \\text{ }  y_{k }$<br>$\\text{since } y = mx_{\\text{next}} + c $<br>$d_{1} = mx_{\\text{next}} + c  \\text{ } &#8211;  \\text{ } y_{k}$<br>$d_{2} = y_{k} + 1  \\text{ } &#8211;  \\text{ } y$<br>$\\text{since } y = mx_{\\text{next}} + c$<br>$d_{2} = y_{k} + 1  \\text{ } &#8211;  \\text{ } (mx_{\\text{next}} + c)$<br>$d_{2} = y_{k} + 1  \\text{ } &#8211;  \\text{ } mx_{\\text{next}}  \\text{ } &#8211;  \\text{ } c$<\/p>\n\n\n\n<p>Subtracting <strong><em>d1<\/em><\/strong>\u200b from <em><strong>d2<\/strong><\/em>:<\/p>\n\n\n\n<p>$d_{1}  \\text{ } &#8211;  \\text{ } d_{2} = mx_{next} + c  \\text{ } &#8211;  \\text{ } y_{k} \\text{ } &#8211;  \\text{ } (y_{k} + 1 \\text{ } &#8211;  \\text{ } mx_{next} \\text{ } &#8211;  \\text{ } c) $<br>$d_{1}  \\text{ } &#8211;  \\text{ } d_{2} = mx_{next} + c  \\text{ } &#8211;  \\text{ } y_{k} \\text{ } &#8211;  \\text{ } y_{k} \\text{ } &#8211;  \\text{ } 1 + mx_{next} + c $<br>$d_{1}  \\text{ } &#8211;  \\text{ } d_{2} = 2mx_{next}  \\text{ } &#8211;  \\text{ } 2y_{k} + 2c  \\text{ } &#8211;  \\text{ } 1$<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Removing the Slope&nbsp;(m)<\/h3>\n\n\n\n<p>We need to <strong>remove the slope <em>(m)<\/em><\/strong> in Bresenham\u2019s Line Algorithm because:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li><strong>Avoid Floating-Point Calculations<\/strong>:<br>The slope \\(m = \\dfrac{\\nabla y}{\\nabla x}\\) often results in fractional values, requiring floating-point arithmetic. Floating-point operations are slower and less efficient compared to integer arithmetic, especially on older or resource-constrained systems.<\/li>\n\n\n\n<li><strong>Use Only Integers<\/strong>:<br>By eliminating <strong><em>m<\/em><\/strong>, we can reformulate the decision-making process entirely using integers. This makes the algorithm faster and avoids precision errors that can occur with floating-point numbers.<\/li>\n\n\n\n<li><strong>Simplify Computations<\/strong>:<br>Removing <strong><em>m<\/em><\/strong> simplifies the math by focusing only on differences <strong><em>(\u0394x and \u0394y)<\/em><\/strong> between pixel coordinates. This makes the algorithm easier to implement and more computationally efficient.<\/li>\n<\/ol>\n\n\n\n<p><em> <\/em>\\(m = \\dfrac{\\nabla y}{\\nabla x}\\)<\/p>\n\n\n\n<p>Substituting <strong><em>m <\/em><\/strong>into the equation:<\/p>\n\n\n\n<p>\\(\\nabla x \\times (d_{1} &#8211; d_{2}) = (2 \\dfrac{\\nabla y}{\\nabla x} x_{next} &#8211; 2y_{k} + 2c &#8211; 1) \\times \\nabla x \\)<br>\\(\\nabla x \\times (d_{1} &#8211; d_{2}) = 2 \\nabla y x_{next} &#8211; 2y_{k} \\nabla x + 2c\\nabla x &#8211; \\nabla x \\)<br>\\(\\nabla x \\times (d_{1} &#8211; d_{2}) = 2 \\nabla y (x_{k} + 1) &#8211; 2y_{k} \\nabla x + 2c\\nabla x &#8211; \\nabla x \\)<br>\\(\\nabla x \\times (d_{1} &#8211; d_{2}) = 2 \\nabla y x_{k} + 2 \\nabla y &#8211; 2y_{k} \\nabla x + 2c\\nabla x &#8211; \\nabla x \\)<br>\\(\\nabla x \\times (d_{1} &#8211; d_{2}) = 2 \\nabla y x_{k} &#8211; 2\\nabla xy_{k} \\textcolor{red}{ + (2 \\nabla y + 2c\\nabla x &#8211; \\nabla x)} \\)<\/p>\n\n\n\n<p>Ignoring constant terms (as they do not affect the decision-making):<\/p>\n\n\n\n<p>\\(\\nabla x \\times (d_{1} &#8211; d_{2}) = 2 \\nabla y x_{k} &#8211; 2\\nabla xy_{k} \\)<br>\\(\\text{Here we need to know about } (d_{1} &#8211; d_{2}) \\text{ is } &gt;0 \\text{ or } &lt; 0 \\)<br>\\(\\text{Then we can ignore } \\nabla x \\)<br>\\(\\text{We will take } \\nabla x \\times (d_{1} &#8211; d_{2}) \\text{ as } d_{k} (\\text{Decision variable k})\\)<br>\\(d_{k} = 2 \\nabla y x_{k} &#8211; 2\\nabla xy_{k}\\)<\/p>\n\n\n\n<p>\\(\\text{So } d_{next} = 2 \\nabla y x_{next} &#8211; 2\\nabla xy_{next} \\)<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Updating the Decision&nbsp;Variable<\/h3>\n\n\n\n<p>For the next step, the decision variable <em>\\(d_{next}\\)\u200b<\/em> is calculated as:<\/p>\n\n\n\n<p>\\(d_{next} = 2 \\nabla y x_{next} &#8211; 2\\nabla xy_{next} \\)<br>\\(\\text{Lets&#8217;s subtract } d_{k} \\text{ from } d_{next}\\)<br>\\(d_{next} &#8211; d_{k} = (2 \\nabla y x_{next} &#8211; 2\\nabla xy_{next}) &#8211; (2 \\nabla y x_{k} &#8211; 2\\nabla xy_{k}) \\)<br>\\(d_{next} &#8211; d_{k} = 2 \\nabla y x_{next} &#8211; 2\\nabla xy_{next} &#8211; 2 \\nabla y x_{k} + 2\\nabla xy_{k} \\)<br>\\(d_{next} &#8211; d_{k} = 2 \\nabla y x_{next} &#8211; 2 \\nabla y x_{k} &#8211; 2\\nabla xy_{next} + 2\\nabla xy_{k} \\)<br>\\(d_{next} &#8211; d_{k} = 2 \\nabla y (x_{next} &#8211; x_{k}) &#8211; 2\\nabla x (y_{next} &#8211; y_{k}) \\)<br>\\(d_{next} = [2 \\nabla y (x_{next} &#8211; x_{k}) &#8211; 2\\nabla x (y_{next} &#8211; y_{k})] + d_{k} \\)<\/p>\n\n\n\n<p>Depending on the value of \\(d_{k}\\)\u200b:<\/p>\n\n\n\n<p>\\(\\textcolor{black}{\\text{If }} \\textcolor{red}{d_{k}} &lt; 0 \\)<br>\\(y_{next} = y_{k} \\)<br>\\(d_{next} = [2 \\nabla y (x_{next} &#8211; x_{k}) &#8211; 2\\nabla x (y_{next} &#8211; y_{k})] + d_{k} \\)<br>\\(d_{next} = [2 \\nabla y (x_{k} + 1 &#8211; x_{k}) &#8211; 2\\nabla x (y_{k} &#8211; y_{k})] + d_{k} \\)<br>\\(d_{next} = 2 \\nabla y + d_{k} \\)<\/p>\n\n\n\n<p>\\(\\textcolor{black}{\\text{If }} \\textcolor{red}{d_{k}} \\geq 0 \\)<br>\\(y_{next} = y_{k} + 1 \\)<br>\\(d_{next} = [2 \\nabla y (x_{next} &#8211; x_{k}) &#8211; 2\\nabla x (y_{next} &#8211; y_{k})] + d_{k} \\)<br>\\(d_{next} = [2 \\nabla y (x_{k} + 1 &#8211; x_{k}) &#8211; 2\\nabla x (y_{k} + 1 &#8211; y_{k})] + d_{k} \\)<br>\\(d_{next} = 2 \\nabla y &#8211; 2 \\nabla x + d_{k} \\)<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Initializing the Algorithm<\/h3>\n\n\n\n<p>To start the algorithm, we calculate the initial decision variable \\(d_{1}\\)\u200b:<\/p>\n\n\n\n<p>\\(d_{1} = 2 \\nabla y x_{1} &#8211; 2\\nabla xy_{1} \\textcolor{red}{ + (2 \\nabla y + 2c\\nabla x &#8211; \\nabla x)}\\)<br>\\(d_{1} = 2 \\nabla y x_{1} &#8211; 2\\nabla xy_{1} + 2 \\nabla y + 2c\\nabla x &#8211; \\nabla x\\)<br>\\(\\textcolor{black}{\\text{Now we have to get rid of }} \\textcolor{red}{c} \\textcolor{black}{\\text{ because it is unknown}} \\)<br>\\(d_{1} = 2 \\nabla y x_{1} &#8211; 2\\nabla xy_{1} + 2 \\nabla y + 2c\\nabla x &#8211; \\nabla x\\)<br>\\(\\textcolor{black}{\\text{According to }} y = mx+c\\)<br>\\(c = y -mx \\)<br>\\(m = \\dfrac{\\nabla y}{\\nabla x}\\)<br>\\(c=y-\\dfrac{\\nabla y}{\\nabla x}x\\)<br>\\(d_{1} = 2 \\nabla y x_{1} &#8211; 2\\nabla xy_{1} + 2 \\nabla y + 2c\\nabla x &#8211; \\nabla x \\textcolor{black}{\\text{ Let&#8217;s apply it here,}}\\)<br>\\(d_{1} = 2 \\nabla y x_{1} &#8211; 2\\nabla xy_{1} + 2 \\nabla y + 2(y_{1}-\\dfrac{\\nabla y}{\\nabla x}x_{1})\\nabla x &#8211; \\nabla x \\)<br>\\(d_{1} = 2 \\nabla y x_{1} &#8211; 2\\nabla xy_{1} + 2 \\nabla y + 2\\nabla x(y_{1}-\\dfrac{\\nabla y}{\\nabla x}x_{1}) &#8211; \\nabla x \\)<br>\\(d_{1} = 2 \\nabla y x_{1} &#8211; 2\\nabla xy_{1} + 2 \\nabla y + 2\\nabla xy_{1}-\\dfrac{\\nabla y}{\\nabla x}x_{1}2\\nabla x &#8211; \\nabla x \\)<br>\\(d_{1} = 2 \\nabla y x_{1} &#8211; 2\\nabla xy_{1} + 2 \\nabla y + 2\\nabla xy_{1}-<br>2\\nabla yx_{1} &#8211; \\nabla x \\)<br>\\(d_{1} = 2 \\nabla y &#8211; \\nabla x \\)<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Summary of the Algorithm<\/h3>\n\n\n\n<ol class=\"wp-block-list\">\n<li>Start at the initial pixel <strong><em>(x0,y0\u200b)<\/em><\/strong>.<\/li>\n\n\n\n<li>Compute the initial decision variable: <strong><em>\\(d_{1} = 2 \\nabla y &#8211; \\nabla x \\)<\/em><\/strong><\/li>\n\n\n\n<li>At each step, update the decision variable:<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>If  \\(d_{k} &lt; 0\\) : Move horizontally, \\(d_{next} = 2 \\nabla y + d_{k} \\).<\/li>\n\n\n\n<li>If  \\(d_{k} \\geq 0\\)  : Move diagonally, \\(d_{next} = 2 \\nabla y &#8211; 2 \\nabla x + d_{k} \\)<\/li>\n<\/ul>\n\n\n\n<p>4. Repeat until the end of the line.<\/p>\n\n\n\n<p>This method ensures that the line is rasterized efficiently with minimal visual errors.<\/p>\n\n\n\n<p>To derive the decision variable for the 2nd octant, you can follow a similar process as for the 1st octant. In this case:<\/p>\n\n\n\n<ol class=\"wp-block-list\">\n<li>The next <strong><em>y-coordinate<\/em><\/strong> will always be \\(y_{next} = y_{k} + 1\\)<\/li>\n\n\n\n<li>Based on the decision variable, you need to determine whether the next <strong><em>x-coordinate<\/em><\/strong> remains the same (\\(x_{k}\\)\u200b) or increments by 1 (\\(x_{k} + 1\\)\u200b).<\/li>\n<\/ol>\n\n\n\n<ul class=\"wp-block-list\">\n<li>If \\(d_{k}&lt;0\\)\u200b: Move horizontally, \\(d_{next} = d_{k} &#8211; 2 \\nabla x \\).<\/li>\n\n\n\n<li>If \\(d_{k} \\geq 0\\): Move diagonally, \\(d_{next} = 2 \\nabla y &#8211; 2 \\nabla x + d_{k} \\)<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">References<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/en.wikipedia.org\/wiki\/Bresenham%27s_line_algorithm\" target=\"_blank\" rel=\"noreferrer noopener\">Bresenham\u2019s line algorithm\u200a\u2014\u200aWikipedia<\/a><\/li>\n<\/ul>\n\n\n\n<p>Next :- <a href=\"https:\/\/www.byteblueprints.com\/?p=3333\">Implement Breshenham Algorithm Python<\/a><\/p>\n\n\n\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In mathematics, a straight line is represented by the equation $y = mx + c$: where m is the slope and c is the y-intercept. On paper, this equation allows us to draw a line smoothly, as points on the line can have continuous values (including decimals). However, in computer graphics, we face a challenge: [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3379,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[14,15],"tags":[],"class_list":["post-3315","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-algorithm","category-bresenham"],"blocksy_meta":{"has_hero_section":"default","styles_descriptor":{"styles":{"desktop":"","tablet":"","mobile":""},"google_fonts":[],"version":6}},"_links":{"self":[{"href":"https:\/\/www.byteblueprints.com\/index.php?rest_route=\/wp\/v2\/posts\/3315","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.byteblueprints.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.byteblueprints.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.byteblueprints.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.byteblueprints.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=3315"}],"version-history":[{"count":111,"href":"https:\/\/www.byteblueprints.com\/index.php?rest_route=\/wp\/v2\/posts\/3315\/revisions"}],"predecessor-version":[{"id":3739,"href":"https:\/\/www.byteblueprints.com\/index.php?rest_route=\/wp\/v2\/posts\/3315\/revisions\/3739"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.byteblueprints.com\/index.php?rest_route=\/wp\/v2\/media\/3379"}],"wp:attachment":[{"href":"https:\/\/www.byteblueprints.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=3315"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.byteblueprints.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=3315"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.byteblueprints.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=3315"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}