QB64.org Forum

Active Forums => Programs => Topic started by: SMcNeill on November 03, 2018, 06:18:38 am

Title: EllipseFill
Post by: SMcNeill on November 03, 2018, 06:18:38 am
An ellipse filling routine, as fast as (or faster than) CircleFill:

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(1000, 800, 32)
  2.  
  3.  
  4. t# = TIMER
  5. FOR i = 1 TO 1000
  6.     CircleFill 500, 400, 400, -1
  7. t2# = TIMER
  8. FOR i = 1 TO 1000
  9.     EllipseFill 500, 400, 400, 400, -1
  10. t3# = TIMER
  11.  
  12.  
  13. PRINT "Time for CircleFill:"; t2# - t#
  14. PRINT "Time for EllipseFill:"; t3# - t2#
  15.  
  16.  
  17. EllipseFill 500, 400, 400, 200, &HAFFF0000
  18. CircleFill 500, 400, 180, &HFF000000
  19. EllipseFill 500, 400, 20, 160, &HAFFF0000
  20.  
  21.  
  22. EllipseFill 500, 400, 500, 400, &HAFFF0000
  23.  
  24. SUB CircleFill (CX AS LONG, CY AS LONG, R AS LONG, C AS LONG)
  25.     DIM Radius AS LONG, RadiusError AS LONG
  26.     DIM X AS LONG, Y AS LONG
  27.  
  28.     Radius = ABS(R)
  29.     RadiusError = -Radius
  30.     X = Radius
  31.     Y = 0
  32.  
  33.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  34.  
  35.     ' Draw the middle span here so we don't draw it twice in the main loop,
  36.     ' which would be a problem with blending turned on.
  37.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  38.  
  39.     WHILE X > Y
  40.         RadiusError = RadiusError + Y * 2 + 1
  41.         IF RadiusError >= 0 THEN
  42.             IF X <> Y + 1 THEN
  43.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  44.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  45.             END IF
  46.             X = X - 1
  47.             RadiusError = RadiusError - X * 2
  48.         END IF
  49.         Y = Y + 1
  50.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  51.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  52.     WEND
  53.  
  54. SUB EllipseFill (cx AS INTEGER, cy AS INTEGER, rx AS INTEGER, ry AS INTEGER, c AS LONG)
  55.     DIM a AS LONG, b AS LONG
  56.     DIM x AS LONG, y AS LONG
  57.     DIM xx AS LONG, yy AS LONG
  58.     DIM sx AS LONG, sy AS LONG
  59.     DIM e AS LONG
  60.  
  61.     a = 2 * rx * rx
  62.     b = 2 * ry * ry
  63.     x = rx
  64.     xx = ry * ry * (1 - rx - rx)
  65.     yy = rx * rx
  66.     sx = b * rx
  67.  
  68.     DO WHILE sx >= sy
  69.         LINE (cx - x, cy - y)-(cx + x, cy - y), c, BF
  70.         IF y <> 0 THEN LINE (cx - x, cy + y)-(cx + x, cy + y), c, BF
  71.  
  72.         y = y + 1
  73.         sy = sy + a
  74.         e = e + yy
  75.         yy = yy + a
  76.  
  77.         IF (e + e + xx) > 0 THEN
  78.             x = x - 1
  79.             sx = sx - b
  80.             e = e + xx
  81.             xx = xx + b
  82.         END IF
  83.     LOOP
  84.  
  85.     x = 0
  86.     y = ry
  87.     xx = rx * ry
  88.     yy = rx * rx * (1 - ry - ry)
  89.     e = 0
  90.     sx = 0
  91.     sy = a * ry
  92.  
  93.     DO WHILE sx <= sy
  94.         LINE (cx - x, cy - y)-(cx + x, cy - y), c, BF
  95.         LINE (cx - x, cy + y)-(cx + x, cy + y), c, BF
  96.  
  97.         DO
  98.             x = x + 1
  99.             sx = sx + b
  100.             e = e + xx
  101.             xx = xx + b
  102.         LOOP UNTIL (e + e + yy) > 0
  103.  
  104.         y = y - 1
  105.         sy = sy - a
  106.         e = e + yy
  107.         yy = yy + a
  108.  
  109.     LOOP
  110.  
  111.  

Note: I take no credit for this EllipseFill, as I found it on an old archive on my drive and then promptly lost it again while closing tabs and testing things.  I dunno who came up with this originally, but I'll see if I can find where the crap the source was hiding so I can give proper credit where credit is due later.

Edit: Original routine that I'd posted was created by unknown author.  Version up now has been modified to remove streaking (as described by bplus below) and improve performance slightly, by yours truly.  Enjoy!
Title: Re: EllipseFill
Post by: bplus on November 03, 2018, 12:57:30 pm
Steve, you are on a hot streak! One great post after another.

From another forum I learned that if you have code for an ellipse, you don't need to also carry code for a circle.

Oh, one more test...
Title: Re: EllipseFill
Post by: bplus on November 03, 2018, 01:03:17 pm
Fails! but sure does look neat.

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(1000, 700, 32)
  2.  
  3.  
  4. t# = TIMER
  5. FOR i = 1 TO 1000
  6.     CircleFill 500, 400, 400, -1
  7. t2# = TIMER
  8. FOR i = 1 TO 1000
  9.     EllipseFill 500, 400, 400, 400, -1
  10. t3# = TIMER
  11.  
  12.  
  13. PRINT "Time for CircleFill:"; t2# - t#
  14. PRINT "Time for EllipseFill:"; t3# - t2#
  15.  
  16.  
  17. WHILE _KEYDOWN(27) = 0
  18.     EllipseFill RND * 1000, RND * 700, RND * 100, RND * 100, _RGBA32(255 * RND, 255 * RND, 255 * RND, 100 * RND)
  19.     _LIMIT 5
  20.  
  21. SUB CircleFill (CX AS LONG, CY AS LONG, R AS LONG, C AS LONG)
  22.     DIM Radius AS LONG, RadiusError AS LONG
  23.     DIM X AS LONG, Y AS LONG
  24.  
  25.     Radius = ABS(R)
  26.     RadiusError = -Radius
  27.     X = Radius
  28.     Y = 0
  29.  
  30.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  31.  
  32.     ' Draw the middle span here so we don't draw it twice in the main loop,
  33.     ' which would be a problem with blending turned on.
  34.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  35.  
  36.     WHILE X > Y
  37.         RadiusError = RadiusError + Y * 2 + 1
  38.         IF RadiusError >= 0 THEN
  39.             IF X <> Y + 1 THEN
  40.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  41.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  42.             END IF
  43.             X = X - 1
  44.             RadiusError = RadiusError - X * 2
  45.         END IF
  46.         Y = Y + 1
  47.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  48.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  49.     WEND
  50.  
  51. SUB EllipseFill (cx AS INTEGER, cy AS INTEGER, rx AS INTEGER, ry AS INTEGER, c AS _UNSIGNED LONG)
  52.     DIM a AS LONG, b AS LONG
  53.     DIM x AS LONG, y AS LONG
  54.     DIM xx AS LONG, yy AS LONG
  55.     DIM sx AS LONG, sy AS LONG
  56.     DIM e AS LONG
  57.  
  58.     a = 2 * rx * rx
  59.     b = 2 * ry * ry
  60.     x = rx
  61.     xx = ry * ry * (1 - rx - rx)
  62.     yy = rx * rx
  63.     sx = b * rx
  64.  
  65.     DO WHILE sx >= sy
  66.         LINE (cx - x, cy - y)-(cx + x, cy - y), c, BF
  67.         LINE (cx - x, cy + y)-(cx + x, cy + y), c, BF
  68.  
  69.         y = y + 1
  70.         sy = sy + a
  71.         e = e + yy
  72.         yy = yy + a
  73.  
  74.         IF (e + e + xx) > 0 THEN
  75.             x = x - 1
  76.             sx = sx - b
  77.             e = e + xx
  78.             xx = xx + b
  79.         END IF
  80.     LOOP
  81.  
  82.     x = 0
  83.     y = ry
  84.     xx = rx * ry
  85.     yy = rx * rx * (1 - ry - ry)
  86.     e = 0
  87.     sx = 0
  88.     sy = a * ry
  89.  
  90.     DO WHILE sx <= sy
  91.         LINE (cx - x, cy - y)-(cx + x, cy - y), c, BF
  92.         LINE (cx - x, cy + y)-(cx + x, cy + y), c, BF
  93.  
  94.         x = x + 1
  95.         sx = sx + b
  96.         e = e + xx
  97.         xx = xx + b
  98.  
  99.         IF (e + e + yy) > 0 THEN
  100.             y = y - 1
  101.             sy = sy - a
  102.             e = e + yy
  103.             yy = yy + a
  104.         END IF
  105.     LOOP
  106.  
  107.  
  108.  
Title: Re: EllipseFill
Post by: TerryRitchie on November 03, 2018, 01:50:31 pm
Steve, you are on a hot streak! One great post after another.

My SMcNeill examples folder is getting quite large with code snippets :)
Title: Re: EllipseFill
Post by: SMcNeill on November 03, 2018, 02:45:52 pm
Steve, you are on a hot streak! One great post after another.

From another forum I learned that if you have code for an ellipse, you don't need to also carry code for a circle.

Oh, one more test...

Exactly!  After all, a circle is nothing more than an ellipse whose Xradius is the same as the Yradius.  Think of it exactly as you would a square -- nothing more than a rectangle whose length is the same as its width.

If you can draw a rectangle, you can create a square.  If you can draw an ellipse, you can create a circle.

This is a little slower than CircleFill, but for the added flexibility, and the minor performance lost, I think it's more than acceptable as a "go to routine", in most instances.
Title: Re: EllipseFill
Post by: bplus on November 03, 2018, 02:52:34 pm
Well I would use it to replace circle fill because the time is so close but it is failing the alpha test, it's lines are overlapping and leaving streaks which I thought you might see in screen shot above.
Title: Re: EllipseFill
Post by: SMcNeill on November 03, 2018, 02:56:58 pm
I'm on my iPad right now; didn't zoom in that close to look good.  I'll play around with it later; it might be something easy enough to correct.  :)
Title: Re: EllipseFill
Post by: SMcNeill on November 03, 2018, 03:24:22 pm
Try this version, bplus, and see if it fixes the line issue for you:

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(1000, 800, 32)
  2.  
  3.  
  4. t# = TIMER
  5. FOR i = 1 TO 1000
  6.     CircleFill 500, 400, 400, -1
  7. t2# = TIMER
  8. FOR i = 1 TO 1000
  9.     EllipseFill 500, 400, 200, 400, -1
  10. t3# = TIMER
  11.  
  12.  
  13. PRINT "Time for CircleFill:"; t2# - t#
  14. PRINT "Time for EllipseFill:"; t3# - t2#
  15.  
  16.  
  17. EllipseFill 500, 400, 400, 200, &H7FFFFF00
  18. CircleFill 500, 400, 180, &HFF000000
  19. EllipseFill 500, 400, 20, 160, &H7FF00FF0
  20.  
  21.  
  22. SUB CircleFill (CX AS LONG, CY AS LONG, R AS LONG, C AS LONG)
  23.     DIM Radius AS LONG, RadiusError AS LONG
  24.     DIM X AS LONG, Y AS LONG
  25.  
  26.     Radius = ABS(R)
  27.     RadiusError = -Radius
  28.     X = Radius
  29.     Y = 0
  30.  
  31.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  32.  
  33.     ' Draw the middle span here so we don't draw it twice in the main loop,
  34.     ' which would be a problem with blending turned on.
  35.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  36.  
  37.     WHILE X > Y
  38.         RadiusError = RadiusError + Y * 2 + 1
  39.         IF RadiusError >= 0 THEN
  40.             IF X <> Y + 1 THEN
  41.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  42.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  43.             END IF
  44.             X = X - 1
  45.             RadiusError = RadiusError - X * 2
  46.         END IF
  47.         Y = Y + 1
  48.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  49.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  50.     WEND
  51.  
  52. SUB EllipseFill (cx AS INTEGER, cy AS INTEGER, rx AS INTEGER, ry AS INTEGER, c AS LONG)
  53.     DIM a AS LONG, b AS LONG
  54.     DIM x AS LONG, y AS LONG
  55.     DIM xx AS LONG, yy AS LONG
  56.     DIM sx AS LONG, sy AS LONG
  57.     DIM e AS LONG
  58.  
  59.     a = 2 * rx * rx
  60.     b = 2 * ry * ry
  61.     x = rx
  62.     xx = ry * ry * (1 - rx - rx)
  63.     yy = rx * rx
  64.     sx = b * rx
  65.  
  66.     DO WHILE sx >= sy
  67.         LINE (cx - x, cy - y)-(cx + x, cy - y), c
  68.         IF y <> -y THEN LINE (cx - x, cy + y)-(cx + x, cy + y), c, BF
  69.         y = y + 1
  70.         sy = sy + a
  71.         e = e + yy
  72.         yy = yy + a
  73.  
  74.         IF (e + e + xx) > 0 THEN
  75.             x = x - 1
  76.             sx = sx - b
  77.             e = e + xx
  78.             xx = xx + b
  79.         END IF
  80.     LOOP
  81.  
  82.     x = 0
  83.     y = ry
  84.     xx = rx * ry
  85.     yy = rx * rx * (1 - ry - ry)
  86.     e = 0
  87.     sx = 1
  88.     sy = a * ry
  89.  
  90.     DO WHILE sx <= sy
  91.  
  92.         LINE (cx - x, cy - y)-(cx + x, cy - y), c, BF
  93.         LINE (cx - x, cy + y)-(cx + x, cy + y), c, BF
  94.  
  95.         DO
  96.             x = x + 1
  97.             sx = sx + b
  98.             e = e + xx
  99.             xx = xx + b
  100.         LOOP UNTIL (e + e + yy) > 0
  101.  
  102.         y = y - 1
  103.         sy = sy - a
  104.         e = e + yy
  105.         yy = yy + a
  106.  
  107.     LOOP
  108.  
Title: Re: EllipseFill
Post by: bplus on November 03, 2018, 03:33:33 pm
Thanks Steve,

Yes, overlap fixed but now time is 1.32 for circle and 2.47 for ellipse, so I will keep circle but use this for ellipse because I don't think I will find better.
Title: Re: EllipseFill
Post by: SMcNeill on November 03, 2018, 03:41:59 pm
Thanks Steve,

Yes, overlap fixed but now time is 1.32 for circle and 2.47 for ellipse, so I will keep circle but use this for ellipse because I don't think I will find better.

I found better:

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(1000, 800, 32)
  2.  
  3.  
  4. t# = TIMER
  5. FOR i = 1 TO 1000
  6.     CircleFill 500, 400, 400, -1
  7. t2# = TIMER
  8. FOR i = 1 TO 1000
  9.     EllipseFill 500, 400, 400, 400, -1
  10. t3# = TIMER
  11.  
  12.  
  13. PRINT "Time for CircleFill:"; t2# - t#
  14. PRINT "Time for EllipseFill:"; t3# - t2#
  15.  
  16.  
  17. EllipseFill 500, 400, 400, 200, &HAFFF0000
  18. CircleFill 500, 400, 180, &HFF000000
  19. EllipseFill 500, 400, 20, 160, &HAFFF0000
  20.  
  21.  
  22. EllipseFill 500, 400, 500, 400, &HAFFF0000
  23.  
  24. SUB CircleFill (CX AS LONG, CY AS LONG, R AS LONG, C AS LONG)
  25.     DIM Radius AS LONG, RadiusError AS LONG
  26.     DIM X AS LONG, Y AS LONG
  27.  
  28.     Radius = ABS(R)
  29.     RadiusError = -Radius
  30.     X = Radius
  31.     Y = 0
  32.  
  33.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  34.  
  35.     ' Draw the middle span here so we don't draw it twice in the main loop,
  36.     ' which would be a problem with blending turned on.
  37.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  38.  
  39.     WHILE X > Y
  40.         RadiusError = RadiusError + Y * 2 + 1
  41.         IF RadiusError >= 0 THEN
  42.             IF X <> Y + 1 THEN
  43.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  44.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  45.             END IF
  46.             X = X - 1
  47.             RadiusError = RadiusError - X * 2
  48.         END IF
  49.         Y = Y + 1
  50.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  51.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  52.     WEND
  53.  
  54. SUB EllipseFill (cx AS INTEGER, cy AS INTEGER, rx AS INTEGER, ry AS INTEGER, c AS LONG)
  55.     DIM a AS LONG, b AS LONG
  56.     DIM x AS LONG, y AS LONG
  57.     DIM xx AS LONG, yy AS LONG
  58.     DIM sx AS LONG, sy AS LONG
  59.     DIM e AS LONG
  60.  
  61.     a = 2 * rx * rx
  62.     b = 2 * ry * ry
  63.     x = rx
  64.     xx = ry * ry * (1 - rx - rx)
  65.     yy = rx * rx
  66.     sx = b * rx
  67.  
  68.     DO WHILE sx >= sy
  69.         LINE (cx - x, cy - y)-(cx + x, cy - y), c, BF
  70.         IF y <> 0 THEN LINE (cx - x, cy + y)-(cx + x, cy + y), c, BF
  71.  
  72.         y = y + 1
  73.         sy = sy + a
  74.         e = e + yy
  75.         yy = yy + a
  76.  
  77.         IF (e + e + xx) > 0 THEN
  78.             x = x - 1
  79.             sx = sx - b
  80.             e = e + xx
  81.             xx = xx + b
  82.         END IF
  83.     LOOP
  84.  
  85.     x = 0
  86.     y = ry
  87.     xx = rx * ry
  88.     yy = rx * rx * (1 - ry - ry)
  89.     e = 0
  90.     sx = 0
  91.     sy = a * ry
  92.  
  93.     DO WHILE sx <= sy
  94.         LINE (cx - x, cy - y)-(cx + x, cy - y), c, BF
  95.         LINE (cx - x, cy + y)-(cx + x, cy + y), c, BF
  96.  
  97.         DO
  98.             x = x + 1
  99.             sx = sx + b
  100.             e = e + xx
  101.             xx = xx + b
  102.         LOOP UNTIL (e + e + yy) > 0
  103.  
  104.         y = y - 1
  105.         sy = sy - a
  106.         e = e + yy
  107.         yy = yy + a
  108.  
  109.     LOOP
  110.  
  111.  

This is now running AT THE EXACT SAME SPEED AS CIRCLEFILL on my machine.  And, I'm not seeing any lines in the output.   Try it out and see what you think.  :D
Title: Re: EllipseFill
Post by: Petr on November 03, 2018, 03:48:29 pm
Excellent! CircleFill: 1.8671875, EllipseFill: 1.59375
Title: Re: EllipseFill
Post by: SMcNeill on November 03, 2018, 03:52:05 pm
Excellent! CircleFill: 1.8671875, EllipseFill: 1.59375

In QB64x64, I get EllipseFill running faster than CircleFill, as well.
In QB64x32, I get them running at almost the exact same speed.

I think I've found a nice little replacement for CircleFill with this routine.  :D
Title: Re: EllipseFill
Post by: bplus on November 03, 2018, 04:22:18 pm
Well if that don't beat all!

We couldn't find a faster way to do circles faster until started trying ellipse! I am getting faster circle fill with ellipse fill.

Nice one, Steve!
Title: Re: EllipseFill
Post by: SMcNeill on November 03, 2018, 05:22:42 pm
Well if that don't beat all!

We couldn't find a faster way to do circles faster until started trying ellipse! I am getting faster circle fill with ellipse fill.

Nice one, Steve!

I think it's good enough now, it's earned itself a spot over in my forum as well: http://qb64.freeforums.net/thread/9/circlefill-ellipsefill

Title: Re: EllipseFill
Post by: SMcNeill on November 03, 2018, 07:22:59 pm
And, after playing around with EllipseFill, I also now have a second way to do CircleFill:

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(1000, 800, 32)
  2.  
  3.  
  4. t# = TIMER
  5. FOR i = 1 TO 1000
  6.     NewCircleFill 500, 400, 400, -1
  7. t2# = TIMER
  8.  
  9. FOR i = 1 TO 1000
  10.     CircleFill 500, 400, 400, -1
  11. t3# = TIMER
  12.  
  13. FOR i = 1 TO 1000
  14.     EllipseFill 500, 400, 400, 400, -1
  15. t4# = TIMER
  16.  
  17.  
  18. PRINT "Time for NewCircleFill:"; t2# - t#
  19. PRINT "Time for CircleFill:"; t3# - t2#
  20. PRINT "Time for EllipseFill:"; t4# - t3#
  21.  
  22.  
  23. EllipseFill 500, 400, 400, 200, &HAFFF0000
  24. CircleFill 500, 400, 180, &HFF000000
  25. EllipseFill 500, 400, 20, 160, &HAFFF0000
  26.  
  27.  
  28. EllipseFill 500, 400, 500, 400, &HAFFF0000
  29.  
  30. SUB CircleFill (CX AS LONG, CY AS LONG, R AS LONG, C AS LONG)
  31.     DIM Radius AS LONG, RadiusError AS LONG
  32.     DIM X AS LONG, Y AS LONG
  33.  
  34.     Radius = ABS(R)
  35.     RadiusError = -Radius
  36.     X = Radius
  37.     Y = 0
  38.  
  39.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  40.  
  41.     ' Draw the middle span here so we don't draw it twice in the main loop,
  42.     ' which would be a problem with blending turned on.
  43.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  44.  
  45.     WHILE X > Y
  46.         RadiusError = RadiusError + Y * 2 + 1
  47.         IF RadiusError >= 0 THEN
  48.             IF X <> Y + 1 THEN
  49.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  50.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  51.             END IF
  52.             X = X - 1
  53.             RadiusError = RadiusError - X * 2
  54.         END IF
  55.         Y = Y + 1
  56.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  57.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  58.     WEND
  59.  
  60. SUB NewCircleFill (cx AS INTEGER, cy AS INTEGER, r AS INTEGER, c AS LONG)
  61.     DIM x AS LONG
  62.     DIM y AS LONG
  63.     DIM e AS LONG
  64.  
  65.     x = r
  66.     e = -x
  67.  
  68.     DO WHILE x >= y
  69.         LINE (cx - x, cy - y)-(cx + x, cy - y), c, BF
  70.         IF y <> 0 THEN LINE (cx - x, cy + y)-(cx + x, cy + y), c, BF
  71.  
  72.         y = y + 1
  73.         e = e + y + y
  74.         IF e > 0 THEN
  75.             x = x - 1
  76.             e = e - x - x
  77.         END IF
  78.     LOOP
  79.     x = r
  80.     e = -x
  81.     y = 0
  82.  
  83.     DO WHILE x >= y
  84.         LINE (cx - y, cy - x)-(cx + y, cy - x), c, BF
  85.         LINE (cx - y, cy + x)-(cx + y, cy + x), c, BF
  86.         DO
  87.             y = y + 1
  88.             e = e + y + y
  89.         LOOP UNTIL e > 0
  90.         x = x - 1
  91.         e = e - x - x
  92.     LOOP
  93.  
  94.  
  95.  
  96. SUB EllipseFill (cx AS INTEGER, cy AS INTEGER, rx AS INTEGER, ry AS INTEGER, c AS LONG)
  97.     DIM a AS LONG, b AS LONG
  98.     DIM x AS LONG, y AS LONG
  99.     DIM xx AS LONG, yy AS LONG
  100.     DIM sx AS LONG, sy AS LONG
  101.     DIM e AS LONG
  102.  
  103.     a = 2 * rx * rx
  104.     b = 2 * ry * ry
  105.     x = rx
  106.     xx = ry * ry * (1 - rx - rx)
  107.     yy = rx * rx
  108.     sx = b * rx
  109.  
  110.     DO WHILE sx >= sy
  111.         LINE (cx - x, cy - y)-(cx + x, cy - y), c, BF
  112.         IF y <> 0 THEN LINE (cx - x, cy + y)-(cx + x, cy + y), c, BF
  113.  
  114.         y = y + 1
  115.         sy = sy + a
  116.         e = e + yy
  117.         yy = yy + a
  118.  
  119.         IF (e + e + xx) > 0 THEN
  120.             x = x - 1
  121.             sx = sx - b
  122.             e = e + xx
  123.             xx = xx + b
  124.         END IF
  125.     LOOP
  126.  
  127.     x = 0
  128.     y = ry
  129.     xx = rx * ry
  130.     yy = rx * rx * (1 - ry - ry)
  131.     e = 0
  132.     sx = 1
  133.     sy = a * ry
  134.  
  135.     DO WHILE sx <= sy
  136.         LINE (cx - x, cy - y)-(cx + x, cy - y), c, BF
  137.         LINE (cx - x, cy + y)-(cx + x, cy + y), c, BF
  138.  
  139.         DO
  140.             x = x + 1
  141.             sx = sx + b
  142.             e = e + xx
  143.             xx = xx + b
  144.         LOOP UNTIL (e + e + yy) > 0
  145.  
  146.         y = y - 1
  147.         sy = sy - a
  148.         e = e + yy
  149.         yy = yy + a
  150.  
  151.     LOOP
  152.  

NewCircleFill is as fast as the old version, or faster, on my machine.  I'm curious how it'll perform for other folks, on different systems, so kindly share results, if you don't mind.  :)
Title: Re: EllipseFill
Post by: bplus on November 03, 2018, 08:50:27 pm
Hi Steve,

The New Circle method is failing the alpha test with 1 overlapping line in upper and lower halves and it is being edged out by the old circle method in the long loop time test.

Amazingly the Ellipse Fill method is edging out the old gold standard circle fill method and still passing the alpha test.

Here is my test code, comment and uncomment as needed in method block and time report line:
Code: QB64: [Select]
  1. DEFINT A-Z
  2. SCREEN _NEWIMAGE(1220, 620, 32)
  3. _SCREENMOVE 100, 20
  4. FOR i = 0 TO 1000
  5.     t = t + i
  6. 'who goes first might be disadvantage in time
  7.  
  8. 'comment out the one not being tested against the old circle method
  9. 'start## = TIMER
  10. 'CIRCLE (915, 305), 300, _RGBA32(100, 100, 100, 100), , , 1
  11. 'NewCircleFill 915, 305, 300, _RGBA32(0, 100, 0, 100)
  12. 'FOR i = 1 TO 10000
  13. '    NewCircleFill 915, 305, 300, _RGBA32(0, 100, 0, 100)
  14. 'NEXT
  15. 'NewCircleTime## = TIMER - start##
  16.  
  17. start## = TIMER
  18. CIRCLE (915, 305), 300, _RGBA32(100, 100, 100, 100), , , 1
  19. EllipseFill 915, 305, 300, 300, _RGBA32(0, 100, 0, 100)
  20. FOR i = 1 TO 10000
  21.     EllipseFill 915, 305, 300, 300, _RGBA32(0, 100, 0, 100)
  22. EllipseTime## = TIMER - start##
  23.  
  24. ' ==================================================== compare to the old gold standard
  25. start## = TIMER
  26. CIRCLE (305, 305), 300, _RGBA32(100, 100, 100, 100), , , 1
  27. CircleFill 305, 305, 300, _RGBA32(0, 100, 0, 100)
  28. FOR i = 1 TO 10000
  29.     CircleFill 305, 305, 300, _RGBA32(0, 100, 0, 100)
  30. OldCircleTime## = TIMER - start##
  31.  
  32. 'Comment out one of next 2 below
  33.  
  34. 'PRINT "Old circle time:"; OldCircleTime##; ", New circle time:"; NewCircleTime##
  35.  
  36. PRINT "Old circle time:"; OldCircleTime##; ", Ellipse fill time:"; EllipseTime##
  37.  
  38.  
  39. 'old circle fill
  40. SUB CircleFill (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  41.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  42.     DIM X AS INTEGER, Y AS INTEGER
  43.  
  44.     Radius = ABS(R)
  45.     RadiusError = -Radius
  46.     X = Radius
  47.     Y = 0
  48.  
  49.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  50.  
  51.     ' Draw the middle span here so we don't draw it twice in the main loop,
  52.     ' which would be a problem with blending turned on.
  53.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  54.  
  55.     WHILE X > Y
  56.         RadiusError = RadiusError + Y * 2 + 1
  57.         IF RadiusError >= 0 THEN
  58.             IF X <> Y + 1 THEN
  59.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  60.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  61.             END IF
  62.             X = X - 1
  63.             RadiusError = RadiusError - X * 2
  64.         END IF
  65.         Y = Y + 1
  66.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  67.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  68.     WEND
  69.  
  70.  
  71. SUB NewCircleFill (cx AS INTEGER, cy AS INTEGER, r AS INTEGER, c AS _UNSIGNED LONG)
  72.     DIM x AS INTEGER
  73.     DIM y AS INTEGER
  74.     DIM e AS INTEGER
  75.  
  76.     x = r
  77.     e = -x
  78.  
  79.     DO WHILE x >= y
  80.         LINE (cx - x, cy - y)-(cx + x, cy - y), c, BF
  81.         IF y <> 0 THEN LINE (cx - x, cy + y)-(cx + x, cy + y), c, BF
  82.  
  83.         y = y + 1
  84.         e = e + y + y
  85.         IF e > 0 THEN
  86.             x = x - 1
  87.             e = e - x - x
  88.         END IF
  89.     LOOP
  90.     x = r
  91.     e = -x
  92.     y = 0
  93.  
  94.     DO WHILE x >= y
  95.         LINE (cx - y, cy - x)-(cx + y, cy - x), c, BF
  96.         LINE (cx - y, cy + x)-(cx + y, cy + x), c, BF
  97.         DO
  98.             y = y + 1
  99.             e = e + y + y
  100.         LOOP UNTIL e > 0
  101.         x = x - 1
  102.         e = e - x - x
  103.     LOOP
  104.  
  105. SUB EllipseFill (cx AS INTEGER, cy AS INTEGER, rx AS INTEGER, ry AS INTEGER, c AS _UNSIGNED LONG)
  106.     DIM a AS LONG, b AS LONG
  107.     DIM x AS LONG, y AS LONG
  108.     DIM xx AS LONG, yy AS LONG
  109.     DIM sx AS LONG, sy AS LONG
  110.     DIM e AS LONG
  111.  
  112.     a = 2 * rx * rx
  113.     b = 2 * ry * ry
  114.     x = rx
  115.     xx = ry * ry * (1 - rx - rx)
  116.     yy = rx * rx
  117.     sx = b * rx
  118.  
  119.     DO WHILE sx >= sy
  120.         LINE (cx - x, cy - y)-(cx + x, cy - y), c, BF
  121.         IF y <> 0 THEN LINE (cx - x, cy + y)-(cx + x, cy + y), c, BF
  122.  
  123.         y = y + 1
  124.         sy = sy + a
  125.         e = e + yy
  126.         yy = yy + a
  127.  
  128.         IF (e + e + xx) > 0 THEN
  129.             x = x - 1
  130.             sx = sx - b
  131.             e = e + xx
  132.             xx = xx + b
  133.         END IF
  134.     LOOP
  135.  
  136.     x = 0
  137.     y = ry
  138.     xx = rx * ry
  139.     yy = rx * rx * (1 - ry - ry)
  140.     e = 0
  141.     sx = 1
  142.     sy = a * ry
  143.  
  144.     DO WHILE sx <= sy
  145.         LINE (cx - x, cy - y)-(cx + x, cy - y), c, BF
  146.         LINE (cx - x, cy + y)-(cx + x, cy + y), c, BF
  147.  
  148.         DO
  149.             x = x + 1
  150.             sx = sx + b
  151.             e = e + xx
  152.             xx = xx + b
  153.         LOOP UNTIL (e + e + yy) > 0
  154.  
  155.         y = y - 1
  156.         sy = sy - a
  157.         e = e + yy
  158.         yy = yy + a
  159.  
  160.     LOOP
  161.  
  162.  
  163.  

I first test one drawing of each for alpha test, then I run them through long loops of redrawing for timed test.

BTW, the first CIRCLE just draws a circle to compare border edges to QB64's circle.