Главная страница


ru.algorithms

 
 - RU.ALGORITHMS ----------------------------------------------------------------
 From : Alexei Philippov                     2:5004/60.12   15 Feb 2003  04:25:44
 To : Igor Kasyanchuk
 Subject : Re: line
 -------------------------------------------------------------------------------- 
 
 
                Вкyсных плюшек и бессонных ночей тебе, Igor !
 
 Hаписав <13 Фев 03 в 19:50> послание для All,
                    Igor Kasyanchuk yже и не надеялся полyчить ответ...
 
  IK> Вот напpимеp есть линия AD котоpая задается двyмя точками.Кооpдинаты
  IK> их известны.
  IK> Вопpос : Как найти кооpдинаты всех пpомежyточных точек.
 
 === Hачало BRESENHA.TXT ===
 Д Алгоpитмы по-pyсски :) (2:5004/45.33) ДДДДДДДДДДДДДДДДДДДДДДД RU.ALGORITHMS Д
  От   : Nick Lubushko                       2:5030/611.117  08 Июн 00  22:50:40
  Тема : Кто из них алгоpитм Бpезенхема?
 ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
 
   IZ> Есть два алгоpитма. Оба пpетендyют на звание алгоpитма
   IZ> Бpезенхема для постpоения линии.
   IZ> Вопpос вот в чем: кто из них на самом деле есть алгоpитм Бpезенхема?
   IZ> Пpосьба по возможности ссылаться на достойные источники.
 
 [skip]
 Они оба - не бpезенхем :)
 Вот бpезенхем: ( R - количество бит дpобной части FP)
 ========================================
 D = ( ( yn - y0 ) << R ) / ( xn - x0 );
 yF = y0 << R + (int)( 0.5 * (1 << R) );
 for ( x = x0 ; x <= xn ; x ++ )
 {
     y = yF >> R;
     yF += D;
     PutPixel( x, y );
 }
 ========================================
 (это для dx>dy, остальные слyчаи - аналогично..)
 самом деле те алгоpитмы тоже бpезинхемистые, но этот лyчше - inner loop не
 содеpжит сpавнения.
 Д Алгоpитмы по-pyсски :) (2:5004/45.33) ДДДДДДДДДДДДДДДДДДДДДДД RU.ALGORITHMS Д
  От   : Alexander Kharkovsky                2:4624/8.147    27 Янв 00  00:34:30
  Тема : Бpезенхейм
 ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
 
  IT> Так никто и не pассказал как Бpезенхеймом линии pисyются.
 
 === Cut ===
           Hаиболее общий    метод    изобpажения    линий     включает
      использование  алгоpитма  Бpезенхама.  Хотя  основой в нем слyжит
      также отношение междy pасстояниями по кооpдинатам X и Y, в данном
      слyчае  не  тpебyется  выполнять  деление  или вычисление чисел с
      плавающей  точкой.  Вместо  этого,  отношение  междy   значениями
      кооpдинат  X  и  Y  пpедставляется  косвенным обpазом чеpез сеpии
      сложений  и  вычитаний.  Основной  идеей  алгоpитма   Бpезенхама,
      является   pегистpация   сpедних   значений   погpешностей  междy
      идеальным положением  каждой  точки  и  той  позицией  на  экpане
      дисплея,  в  котоpой она действительно отобpажается.  Погpешность
      междy идеальным и действительным положением точки возникает ввидy
      огpаниченных  возможностей  технических  сpедств.  Фактически  не
      сyществyет   дисплеев   с    бесконечно    большой    pазpешающей
      способностью,  и,  следовательно, действительное положение каждой
      точки на линии тpебyет наилyчшей аппpоксимации. В каждой итеpации
      цикла  вычеpчивания  линии вызываются две пеpеменные xerr и yerr,
      котоpые  yвеличиваются  в  зависимости   от   изменения   величин
      кооpдинат  X  и  Y  соответственно.  Когда  значение  погpешности
      достигает опpеделенного значения,  оно  вновь  yстанавливается  в
      исходное   положение,   а   соответствyющий   счетчик   кооpдинат
      yвеличивается.  Этот пpоцесс пpодолжается до тех поp,  пока линия
      не бyдет полностью вычеpчена.  Фyнкция line(),  пpиведенная ниже,
      pеализyет этот метод.  Вы должны изyчать ее до тех поp,  пока  не
      поймете механизма выполнения всех ее опеpаций. Заметим, что в ней
      использyется  фyнкция   mempoint(),   pазpаботанная   pанее   для
      отобpажения точки на экpане теpминала.
       /* Вычеpчивание линии заданного цвета с использованием
          алгоpитма Бpезенхама */
        void line(startx,starty,endx,endy,color)
        int startx,starty,endx,endy,color;
        {
          register int t,distаnce;
          int xerr=0,yerr=0,delta_x,delta_y;
          int incx,incy;
 
        /* вычисление pасстояния в обоих напpавлениях  */
          delta_x=endx-startx;
          delta_y=endy-starty;
 
        /* опpеделение напpавления шага,
           шаг вычисляется либо по веpтикальной, либо гоpизонтальной
           линии   */
           if (delta_x>0) incx=1;
           else  if (delta_x==0) incx=0;
           else  incx= -1;
           if (delta_y>0) incy=1;
           else  if (delta_y==0) incy=0;
           else  incy= -1;
 
         /* опpеделение какое pасстояние больше */
           delta_x=abs(delta_x);
           delta_y=abs(delta_y);
           if (delta_x>delta_y) distance=delta_x;
           else distance=delta_y;
 
         /* вычеpчивание линии */
           for (t=0; t<=distance+1; t++) {
              mempoint(startx,starty,color);
              xerr+=delta_x;
              yerr+=delta_y;
              if (xerr>distance) {
                 xerr-=distance;
                 startx+=incx;
              }
              if (yerr>distance) {
                 yerr-=distance;
                 starty+=incy;
              }
           }
        }
 === Cut ===
 Д Алгоpитмы по-pyсски :) (2:5004/45.33) ДДДДДДДДДДДДДДДДДДДДДДД RU.ALGORITHMS Д
  От   : Sergey Yermack                      2:452/50.33     26 Июл 00  22:14:22
  Тема : Линии.
 ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД
 
 Bresenham's Line and Circle Algorithms
                  ========================================
 
                   Written for the PC-GPE by Mark Feldman
                     e-mail address : pcgpe@ix.netcom.com
 
  -----------------------------------------------------------------------------
 
  NOTICE: This file is included with permission from the author and is
          part of the PC-GPE collection. This document may not be
          distributed separately from here.
 
          The entire PC-GPE collection may be downloaded from:
          ftp://x2ftp.oulu.fi/pub/msdos/programming/gpe/pcgpe10.zip
 
  -----------------------------------------------------------------------------
  =============================================================================
   Disclaimer
  ============
 
  I assume no responsibility whatsoever for any effect that this file, the
  information contained therein or the use thereof has on you, your sanity,
  computer, spouse, children, pets or anything else related to you or your
  existance. No warranty is provided nor implied with this information.
 
  =============================================================================
   Introduction
  ==============
 
  Bresenham is a pretty smart cookie (note the use of the word "is", last I
  heard he was still working for IBM). This file contains the algorithms he
  developped for drawing lines and circles on a pixelated display system
  such as the VGA.
 
  =============================================================================
   Line Algorithm
  ================
 
  The basic algorithm works for lines which look like this:
 
        o-----+-                         |
       p1       ------+-                 | deltay
                        -----+-      p2  |
                               -------o  |
 
        ----------------------------------
                    deltax
 
  where p1 = (x1,y1),
        p2 = (x2, y2),
        x and y are both increasing from p1 to p2,
        deltax = x2 - x1,
        deltay = y2 - y1 and
        deltax >= deltay.
 
  All other types of lines can be derived from this type. I'll get to this
  bit later.
 
  First you need to perform the following intialisation:
 
  x = x1
  y = y1
  d = (2 * deltay) - deltax
 
  x is the current x location, you will add 1 to this variable after every
  pixel you draw until all pixels have been drawn.
  y is the current y location. The decision variable is used to determine
  when to add 1 to this value. d is the decision variable which will be used
  to keep a track of what to do.
 
  Now you loop across the screen from x1 to x2 and for each loop perform the
  following operations for each pixel :
 
  PutPixel(x, y);  { Draw a pixel at the current point }
  if d < 0 then
      d := d + (2 * deltay)
  else
    begin
      d := d + 2 * (deltay - deltax);
      y := y + 1;
    end;
  x := x + 1;
 
  It's that simple!
 
  =============================================================================
   Speeding Up The Line Algorithm
  ================================
 
  There are several useful techniques for speeding up Bresenhams line
  algorithm.
 
  For starters, notice that all multiplications are by 2. This can be
  performed with a simple shift left instruction (Shl in Pascal, << in C).
 
  Next notice that the values you add to the decision variable do not change
  throughout the loop, so they can be precalculated beforehand.
 
  One property of lines is that they are symetrical about their mid-points,
  and we can use this property to speed up the algorithm. Store two x and y
  values, (xa, ya) and (xb, yb). Have each pair start on either end of the
  line. For each pass through the loop you draw the pixel at both points, add
  1 to xa and subtract one from xb. When d >= 0 add 1 to ya and subtract one
  from yb. You then only need to loop until xa = xb.
 
  It's also obvious that if the decision variable becomes the same value
  it was when it was initialised, then the rest of the line is just
  copies of the line you have already drawn up to that point. You might be
  able to speed the algorithm up by keeping an array of how y has been
  modified and then use this array if the line starts repeating itself. If
  you are using the Intel registers to store all values then you probably
  wouldn't get much of a speed increase (in fact it could slow it down), but
  it would probably be useful for thing like linear texture mapping (discussed
  below). I've never actually tried implementing this technique, and I would
  like to hear the results if anyone does.
 
  Above all remember that these optimisations will only significantly speed
  up the line drawing algorithm if the whole thing is done in assembly. A
  profile of the example program at the end of this file showed that 40% of
  CPU time was spent in the slow PutPixel routine I was using, the loop
  mechanics and testing the sign of the decision variable.
 
  =============================================================================
   Other Uses for the Line Algorithm
  ===================================
 
  A line can be represented by the equation y = mx + c, where
  m = deltay / deltax. Note that this is a version of the standard linear
  equation ax + bx + c = 0. There are many algorithms which use this equation.
 
  One good use for the bresenham line algorithm is for quickly drawing filled
  concave polygons (eg triangles). You can set up an array of minimum and
  maximum x values for every horizontal line on the screen. You then use
  bresenham's algorithm to loop along each of the polygon's sides, find where
  it's x value is on every line and adjust the min and max values accordingly.
  When you've done it for every line you simply loop down the screen drawing
  horizontal lines between the min and max values for each line.
 
  Another area is in linear texture mapping (see the PC-GPE article on texture
  mapping). This method involves taking a string of bitmap pixels and
  stretching them out (or squashing them in) to a line of pixels on the screen.
  Typically you would draw a vertical line down the screen and use Bresenhams
  to calculate which bitmap pixel should be drawn at each screen pixel.
 
  =============================================================================
   Circle Algorithm
  ==================
 
  Circles have the property of being highly symetrical, which is handy
  when it comes to drawing them on a display screen.
 
        |y          (This diagram is supposed to be a circle, try viewing
        |           it in 50 line mode).
    \ ..... /
     .  |  .        We know that there are 360 degrees in a circle. First we
    . \ | / .       see that a circle is symetrical about the x axis, so
    .  \|/  .       only the first 180 degrees need to be calculated. Next
  --.---+---.--     we see that it's also symetrical about the y axis, so now
    .  /|\  . x     we only need to calculate the first 90 degrees. Finally
    . / | \ .       we see that the circle is also symetrical about the 45
     .  |  .        degree diagonal axis, so we only need to calculate the
    / ..... \       first 45 degrees.
        |
        |
 
  Bresenhams circle algorithm calculates the locations of the pixels in the
  first 45 degrees. It assumes that the circle is centered on the origin. So
  for every pixel (x,y) it calculates we draw a pixel in each of the 8 octants
  of the circle :
 
  PutPixel(CenterX + X, Center Y + Y)
  PutPixel(CenterX + X, Center Y - Y)
  PutPixel(CenterX - X, Center Y + Y)
  PutPixel(CenterX - X, Center Y - Y)
  PutPixel(CenterX + Y, Center Y + X)
  PutPixel(CenterX + Y, Center Y - X)
  PutPixel(CenterX - Y, Center Y + X)
  PutPixel(CenterX - Y, Center Y - X)
 
  So let's get into the actual algorithm. Given a radius for the circle
  we perform this initialisation:
 
  d := 3 - (2 * RADIUS)
  x := 0
  y := RADIUS
 
  Now for each pixel we do the following operations:
 
  Draw the 8 circle pixels
  if d < 0 then
      d := d + (4 * x) + 6
  else
    begin
      d := d + 4 * (x - y) + 10
      y := y - 1;
    end;
 
  And we keep doing this until x = y. Note that the values added to the
  decision variable in this algorithm (x and y) are constantly changing, so
  we cannot precalculate them. The muliplications however are by 4, and we
  can accomplish this by shifting left twice.
 
  =============================================================================
   A Pascal General Line Procedure
  =================================
 
  The basic bresenham line algorithm can be modified to handle all types of
  lines. In this section assume that deltax = abs(x2 - x1) and
  deltay = abs(y2 - y1).
 
  First let's take lines where deltax >= deltay. Now if x1 > x2 then you will
  need to subtract 1 from x for every pass through the loop. Similarly if y1 >
  y2 then you will be also need to subtract 1 from y for every pass through the
  loop where d < 0.
 
  Lines where deltax < deltay can be handled the same way, you just swap all
  the deltax's and deltay's around.
 
  The fastest method of handling all cases is to write a custom routine for
  each of the 8 line types:
 
  1) x1 <= x2, y1 <= y2, deltax >= deltay
  2) x1 <= x2, y1 <= y2, deltax <  deltay
  3) x1 <= x2, y1 >  y2, deltax >= deltay
  4) x1 <= x2, y1 >  y2, deltax <  deltay
  5) x1 >  x2, y1 <= y2, deltax >= deltay
  6) x1 >  x2, y1 <= y2, deltax <  deltay
  7) x1 >  x2, y1 >  y2, deltax >= deltay
  8) x1 >  x2, y1 >  y2, deltax <  deltay
 
  This will give you the fastest results, but will also make your code 8
  times larger! Alternatively you can declare a few extra variables and
  use a common inner loop for all lines:
 
  numpixels = number of pixels to draw
            = deltax if deltax >= deltay or
            = deltay if deltax < deltay
  dinc1 = the amount to add to d when d < 0
  dinc2 = the amount to add to d when d >= 0
  xinc1 = the amount to add to x when d < 0
  xinc2 = the amount to add to x when d >= 0
  yinc1 = the amount to add to y when d < 0
  yinc2 = the amount to add to y when d >= 0
 
  The following is a simple example program which uses this technique:
 
  =============================================================================
 
  {
 
  BRESLINE.PAS - A general line drawing procedure.
                 By Mark Feldman
 
  This is a very simple implementation of bresenhams' line algorithm with
  no optimisations. It can draw about 6000 random lines a second in mode 13h
  on my 486SX33 with sloooooow Paradise Extended VGA.
 
  }
 
  procedure Line(x1, y1, x2, y2 : integer; color : byte);
  var i, deltax, deltay, numpixels,
      d, dinc1, dinc2,
      x, xinc1, xinc2,
      y, yinc1, yinc2 : integer;
  begin
 
    { Calculate deltax and deltay for initialisation }
    deltax := abs(x2 - x1);
    deltay := abs(y2 - y1);
 
    { Initialize all vars based on which is the independent variable }
    if deltax >= deltay then
      begin
 
        { x is independent variable }
        numpixels := deltax + 1;
        d := (2 * deltay) - deltax;
        dinc1 := deltay Shl 1;
        dinc2 := (deltay - deltax) shl 1;
        xinc1 := 1;
        xinc2 := 1;
        yinc1 := 0;
        yinc2 := 1;
      end
    else
      begin
 
        { y is independent variable }
        numpixels := deltay + 1;
        d := (2 * deltax) - deltay;
        dinc1 := deltax Shl 1;
        dinc2 := (deltax - deltay) shl 1;
        xinc1 := 0;
        xinc2 := 1;
        yinc1 := 1;
        yinc2 := 1;
      end;
 
    { Make sure x and y move in the right directions }
    if x1 > x2 then
      begin
        xinc1 := - xinc1;
        xinc2 := - xinc2;
      end;
    if y1 > y2 then
      begin
        yinc1 := - yinc1;
        yinc2 := - yinc2;
      end;
 
    { Start drawing at  }
    x := x1;
    y := y1;
 
    { Draw the pixels }
    for i := 1 to numpixels do
      begin
        PutPixel(x, y, color);
        if d < 0 then
          begin
            d := d + dinc1;
            x := x + xinc1;
            y := y + yinc1;
          end
        else
          begin
            d := d + dinc2;
            x := x + xinc2;
            y := y + yinc2;
          end;
      end;
  end;
 
  =============================================================================
 
  Note that if you are writing a line routine for mode 13h (for example) you
  can speed it up by converting the inner loop to assembly and including
  mode 13h specific code. This portion of the above routine works the same but
  the  values are stored in a single variable (screen) which holds the
  memory address of the current pixel, screeninc1 and screeninc2 are the
  update values for screen.
 
  =============================================================================
 
  var screen : word;
      screeninc1, screeninc2 : integer;
       .
       .
       .
    { Start drawing at  }
    screen := word(y1) * 320 + x1;
    screeninc1 := yinc1 * 320 + xinc1;
    screeninc2 := yinc2 * 320 + xinc2;
 
    { Draw the pixels }
    asm
 
      { Use as many registers as are available }
      push $A000
      pop es
      mov di, screen
      mov dx, d
      mov al, color
      mov cx, numpixels
      mov bx, dinc1
 
      @bres1:
 
      { Draw the current pixel and compare the decision variable to 0 }
      mov es:[di], al
      cmp dx, 0
      jnl @bres2
 
      { D < 0 }
      add dx, bx { bx = dinc1 }
      add di, screeninc1
      jmp @bres3
 
      @bres2:
 
      { D >= 0 }
      add dx, dinc2
      add di, screeninc2
 
      @bres3:
 
      loop @bres1
    end;
 
  =============================================================================
 === Конец BRESENHA.TXT ===
 
                                             Алёшка Филиппов АКА Филя
 
 --- филя, пpосто филя ...
  * Origin: Hям ! (2:5004/60.12)
 
 

Вернуться к списку тем, сортированных по: возрастание даты  уменьшение даты  тема  автор 

 Тема:    Автор:    Дата:  
 line   Igor Kasyanchuk   13 Feb 2003 20:50:00 
 Re: line   Vitaly Lugovsky   14 Feb 2003 03:54:35 
 line   Igor Kasyanchuk   14 Feb 2003 16:07:00 
 Re: line   Nick Kovaliov   14 Feb 2003 10:41:09 
 line   Igor Kasyanchuk   14 Feb 2003 16:10:00 
 Re: line   Ivan Boldyrev   14 Feb 2003 12:10:20 
 Re: line   Alexei Philippov   15 Feb 2003 04:25:44 
 line   Igor Kasyanchuk   15 Feb 2003 10:53:00 
Архивное /ru.algorithms/32583e4d5f13.html, оценка 3 из 5, голосов 10
Яндекс.Метрика
Valid HTML 4.01 Transitional