December 03, 2020, 08:26:04 PM

Author Topic: [bmx] Draw Hollow Ellipse Pixel by Pixel with Integer Math by ImaginaryHuman [ 1+ years ago ]  (Read 806 times)

Offline BlitzBot

  • Jr. Member
  • **
  • Posts: 1
Title : Draw Hollow Ellipse Pixel
Author : Pixel with Integer Math by ImaginaryHuman
Posted : 1+ years ago

Description : This draws an unfilled ellipse one pixel at a time and uses only integer math to do it, except for one small part where two lines need to do a floating point calculation. Even so, there is no trigonometry involved. The ellipse is not rotatable unless the output method (ie Plot) can be drawn with rotated coordinates as part of the graphics system (ie rotating the camera, etc).

Code :
Code: BlitzMax
  1. 'Midpoint ellipse algorithm
  2.  
  3. Strict
  4. Graphics 640,480,0
  5.  
  6. Local xCenter:Int=320
  7. Local yCenter:Int=240
  8. Local Rx,Ry:Int
  9. Local p,px,py,x,y:Int
  10. Local Rx2,Ry2,twoRx2,twoRy2:Int
  11. Local pFloat:Float
  12. Repeat
  13.         Cls
  14.         If MouseDown(1)
  15.                 xCenter=MouseX()
  16.                 yCenter=MouseY()
  17.         EndIf
  18.         Rx=Abs(xCenter-MouseX())
  19.         Ry=Abs(yCenter-MouseY())
  20.         DrawText String(Rx)+" x "+String(Ry),20,20
  21.         Rx2=Rx*Rx
  22.         Ry2=Ry*Ry
  23.         twoRx2=Rx2 Shl 1
  24.         twoRy2=Ry2 Shl 1
  25.         'Region 1
  26.         x=0
  27.         y=Ry
  28.         Plot xCenter+x,yCenter+y
  29.         Plot xCenter-x,yCenter+y
  30.         Plot xCenter+x,yCenter-y
  31.         Plot xCenter-x,yCenter-y
  32.         pFloat=(Ry2-(Rx2*Ry))+(0.25*Rx2)
  33.         p=Int(pFloat)
  34.         If pFloat Mod 1.0>=0.5 Then p:+1
  35.         px=0
  36.         py=twoRx2*y
  37.         While px<py
  38.                 x:+1
  39.                 px:+twoRy2
  40.                 If p>=0
  41.                         y:-1
  42.                         py:-twoRx2
  43.                 EndIf
  44.                 If p<0 Then p:+Ry2+px Else p:+Ry2+px-py
  45.                 Plot xCenter+x,yCenter+y
  46.                 Plot xCenter-x,yCenter+y
  47.                 Plot xCenter+x,yCenter-y
  48.                 Plot xCenter-x,yCenter-y
  49.         Wend
  50.         'Region 2
  51.         pFloat=(Ry2*(x+0.5)*(x+0.5))+(Rx2*(y-1.0)*(y-1.0))-(Rx2*(Float(Ry2)))
  52.         p=Int(pFloat)
  53.         If pFloat Mod 1.0>=0.5 Then p:+1
  54.         While y>0
  55.                 y:-1
  56.                 py:-twoRx2
  57.                 If p<=0
  58.                         x:+1
  59.                         px:+twoRy2
  60.                 EndIf
  61.                 If p>0 Then p:+Rx2-py Else p:+Rx2-py+px
  62.                 Plot xCenter+x,yCenter+y
  63.                 Plot xCenter-x,yCenter+y
  64.                 Plot xCenter+x,yCenter-y
  65.                 Plot xCenter-x,yCenter-y
  66.         Wend
  67.         Flip
  68. Until KeyHit(KEY_ESCAPE)
  69. End


Comments :


ImaginaryHuman(Posted 1+ years ago)

 This is meant to be in the BlitzMax code section. Sorry about that.


Rck(Posted 1+ years ago)

 
Code: [Select]
;Midpoint ellipse algorithm

Graphics 640,480,0,2

Local xCenter% = 320
Local yCenter% = 240
Local Rx%, Ry%
Local p%, px%, py%, x%, y%
Local Rx2%, Ry2%, twoRx2%, twoRy2%
Local pFloat#

Repeat
        Cls
WaitEvent()


        If MouseDown(1)
            xCenter = MouseX()
            yCenter = MouseY()
        EndIf
        Rx = Abs(xCenter - MouseX())
        Ry = Abs(yCenter - MouseY())

        Rx2 = Rx * Rx
        Ry2 = Ry * Ry
        twoRx2 = Rx2 Shl 1
        twoRy2 = Ry2 Shl 1

msStart = MilliSecs()

        ;Region 1
        x = 0
        y = Ry

        Plot xCenter + x, yCenter + y
        Plot xCenter - x, yCenter + y
        Plot xCenter + x, yCenter - y
        Plot xCenter - x, yCenter - y
        pFloat = (Ry2 - (Rx2 * Ry)) + (0.25 * Rx2)
        p = Int(pFloat)
        If pFloat Mod 1.0 >= 0.5 Then p = p + 1

        px = 0
        py = twoRx2 * y

        While px < py
                x = x + 1
                px = px + twoRy2
                If p >= 0
                        y = y - 1
                        py = py - twoRx2
                EndIf
                If p < 0 Then p = p + Ry2 + px Else p = p + Ry2 + px - py
                Plot xCenter + x, yCenter + y
                Plot xCenter - x, yCenter + y
                Plot xCenter + x, yCenter - y
                Plot xCenter - x, yCenter - y
        Wend

        ;Region 2
        pFloat = (Ry2 * (x + 0.5) * (x + 0.5)) + (Rx2 * (y - 1.0) * (y - 1.0)) - (Rx2 * (Float(Ry2)))
        p = Int(pFloat)
        If pFloat Mod 1.0 >= 0.5 Then p = p + 1
        While y > 0
                y = y - 1
                py = py - twoRx2
                If p <= 0
                        x = x +1
                        px = px + twoRy2
                EndIf
                If p > 0 Then p = p + Rx2 - py Else p = p + Rx2 - py + px
                Plot xCenter + x, yCenter + y
                Plot xCenter - x, yCenter + y
                Plot xCenter + x, yCenter - y
                Plot xCenter - x, yCenter - y
        Wend

timeToDraw = MilliSecs() - msStart
Text 20, 20, Rx + " x " + Ry
Text 20, 30, "Draw time " + timeToDraw + " ms"

        Flip(False)
Until KeyHit(1)
Here is a port to BlitzPlus code for those interested (and an additional waitevent - oh how i love progs that aren't always 100% on my CPU). Oh, and I added an ms counter to see how long the calculations and drawing take.


Rck(Posted 1+ years ago)

 
Code: [Select]
;Midpoint ellipse algorithm

Const GAME_WIDTH = 800
Const GAME_HEIGHT = 600
Graphics  GAME_WIDTH, GAME_HEIGHT, 0, 2

Local xCenter% = GAME_WIDTH / 2
Local yCenter% = GAME_HEIGHT / 2
Local Rx%, Ry%
Local p%, px%, py%, x%, y%
Local Rx2%, Ry2%, twoRx2%, twoRy2%
Local pFloat#

Const fillColor% = $FF

Repeat
        Cls
WaitEvent()


        If MouseDown(1)
            xCenter = MouseX()
            yCenter = MouseY()
        EndIf
        Rx = Abs(xCenter - MouseX())
        Ry = Abs(yCenter - MouseY())

        Rx2 = Rx * Rx
        Ry2 = Ry * Ry
        twoRx2 = Rx2 Shl 1
        twoRy2 = Ry2 Shl 1

msStart = MilliSecs()

        ;Region 1
        x = 0
        y = Ry

LockBuffer(BackBuffer)

wpf(xCenter + x, yCenter + y)
        wpf(xCenter - x, yCenter + y)
        wpf(xCenter + x, yCenter - y)
        wpf(xCenter - x, yCenter - y)

        pFloat = (Ry2 - (Rx2 * Ry)) + (0.25 * Rx2)
        p = Int(pFloat)
        If pFloat Mod 1.0 >= 0.5 Then p = p + 1

        px = 0
        py = twoRx2 * y

        While px < py
                x = x + 1
                px = px + twoRy2
                If p >= 0
                        y = y - 1
                        py = py - twoRx2
                EndIf
                If p < 0 Then p = p + Ry2 + px Else p = p + Ry2 + px - py
                wpf(xCenter + x, yCenter + y)
                wpf(xCenter - x, yCenter + y)
                wpf(xCenter + x, yCenter - y)
                wpf(xCenter - x, yCenter - y)
        Wend

        ;Region 2
        pFloat = (Ry2 * (x + 0.5) * (x + 0.5)) + (Rx2 * (y - 1.0) * (y - 1.0)) - (Rx2 * (Float(Ry2)))
        p = Int(pFloat)
        If pFloat Mod 1.0 >= 0.5 Then p = p + 1
        While y > 0
                y = y - 1
                py = py - twoRx2
                If p <= 0
                        x = x +1
                        px = px + twoRy2
                EndIf
                If p > 0 Then p = p + Rx2 - py Else p = p + Rx2 - py + px
                wpf(xCenter + x, yCenter + y)
                wpf(xCenter - x, yCenter + y)
                wpf(xCenter + x, yCenter - y)
                wpf(xCenter - x, yCenter - y)
        Wend

UnlockBuffer(BackBuffer)


timeToDraw = MilliSecs() - msStart
Text 20, 20, Rx + " x " + Ry
Text 20, 30, "Draw time " + timeToDraw + " ms"

        Flip(False)
Until KeyHit(1)


Function wpf(x,y)
  ;safe WritePixelFast
  If x < 0 Or x >= GAME_WIDTH Then Return 0
  If y < 0 Or y >= GAME_HEIGHT Then Return 0
  WritePixelFast(x, y, fillColor%)
End Function
And here is virtually the same code just using writepixelfast on a locked buffer


ImaginaryHuman(Posted 1+ years ago)

 Cool, thanks. [/i]

 

SimplePortal 2.3.6 © 2008-2014, SimplePortal