Author Topic: Seeking best ellipse fill function. (For everyone's sake.)  (Read 41009 times)

0 Members and 1 Guest are viewing this topic.

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #90 on: February 12, 2019, 01:50:51 pm »
Steve, Yes, I thought of using STATIC that way, too, but no go, because all of those values are subject to change when a new different sized ellipse is made. I mean as a constant, sure w2 will always be a * a, but each time a new ellipse is made, with a new value for a, that equation has to be redone in the sub.

Mark, I'll get rid of the GOTO. Thanks for testing that.

This looks like my finished modifications. I also removed the y = 0 part, as I presume if this gets put into the tool box forum we will talk about renaming the variables to less commonly used names, names unique to the sub.

Code: QB64: [Select]
  1. SUB FlatEllipseFill (ox AS INTEGER, oy AS INTEGER, a AS INTEGER, b AS INTEGER, col AS _UNSIGNED LONG)
  2. IF a = 0 OR b = 0 THEN EXIT SUB
  3. w2 = a * a
  4. h2 = b * b
  5. h2w2 = h2 * w2
  6. x = a
  7. LINE (ox - a, oy)-(ox + a, oy), col, BF
  8.     y = y + 1
  9.     yyw2 = y * y * w2
  10.     x = SQR((h2w2 - yyw2) / h2)
  11.     LINE (ox - x, oy + y)-(ox + x, oy + y), col, BF
  12.     LINE (ox - x, oy - y)-(ox + x, oy - y), col, BF
  13. LOOP UNTIL y = b

Pete
« Last Edit: February 12, 2019, 06:07:32 pm by Pete »
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #91 on: February 12, 2019, 02:43:02 pm »
I'm blown away that a version of the function that includes SQR is actually performing quickly!

A deep bow for having the balls to try that out again!

As for variable names - scope should save us. As part of good design, we should avoid globals (DIM SHAREDs) whenever possible, and there should be no collision whatsoever between simple variables like "y" causing interference. If it's *other* functions/subs/elements in someone's program that cause a problem with variable names, we shouldn't be obligated to hold their hand on this. Then again, qb64 functions have a bug (I refuse to call this a feature, it's a genuine "bad part") where functions can edit variables passed to them. Just terrible, and I always code to avoid being bitten by this. If we need to muck around with variable names to save people from being confused, then so be it I suppose.
You're not done when it works, you're done when it's right.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #92 on: February 12, 2019, 02:53:40 pm »
Code: QB64: [Select]
  1. _TITLE "STATIC Ellipse Fill versus Steve Circle Fill"
  2. DEFINT A-Z
  3. SCREEN _NEWIMAGE(1220, 680, 32)
  4. _SCREENMOVE 100, 20
  5.  
  6. FlatEllipseFill 915, 305, 300, 300, _RGBA32(0, 100, 0, 40)
  7. FlatEllipseFill 915, 305, 300, 300, _RGBA32(0, 100, 0, 40)
  8. INPUT "Flat EllipseFill overlap test, press enter to continue "; wate$
  9. LINE (0, 0)-(600, 20), _RGB32(0, 0, 0), BF
  10. start## = TIMER
  11. FOR i = 1 TO 10000
  12.     FlatEllipseFill 915, 305, 300, 300, _RGBA32(0, 100, 0, 100)
  13. EllipseTime## = TIMER - start##
  14. _PRINTSTRING (800, 615), "Time for 10000 Flat Ellipse Fills:" + STR$(EllipseTime##)
  15.  
  16.  
  17. ' ==================================================== compare to the old gold standard
  18.  
  19. CircleFill 305, 305, 300, _RGBA32(0, 100, 0, 40)
  20. CircleFill 305, 305, 300, _RGBA32(0, 100, 0, 40)
  21. LOCATE 1, 1: INPUT "CircleFill overlap test, press enter to continue "; wate$
  22. LINE (0, 0)-(600, 20), _RGB32(0, 0, 0), BF
  23.  
  24. start## = TIMER
  25. FOR i = 1 TO 10000
  26.     CircleFill 305, 305, 300, _RGBA32(0, 100, 0, 100)
  27. OldCircleTime## = TIMER - start##
  28. _PRINTSTRING (200, 615), "Time for 10000 Circle Fills:" + STR$(OldCircleTime##)
  29.  
  30. 'old circle fill
  31. SUB CircleFill (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  32.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  33.     DIM X AS INTEGER, Y AS INTEGER
  34.  
  35.     Radius = ABS(R)
  36.     RadiusError = -Radius
  37.     X = Radius
  38.     Y = 0
  39.  
  40.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  41.  
  42.     ' Draw the middle span here so we don't draw it twice in the main loop,
  43.     ' which would be a problem with blending turned on.
  44.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  45.  
  46.     WHILE X > Y
  47.         RadiusError = RadiusError + Y * 2 + 1
  48.         IF RadiusError >= 0 THEN
  49.             IF X <> Y + 1 THEN
  50.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  51.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  52.             END IF
  53.             X = X - 1
  54.             RadiusError = RadiusError - X * 2
  55.         END IF
  56.         Y = Y + 1
  57.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  58.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  59.     WEND
  60.  
  61.  
  62. SUB FlatEllipseFill (ox AS _INTEGER64, oy AS _INTEGER64, a AS _INTEGER64, b AS _INTEGER64, col AS _UNSIGNED LONG)
  63.     DIM h2 AS _INTEGER64
  64.     DIM w2 AS _INTEGER64
  65.     DIM h2w2 AS _INTEGER64
  66.     DIM xi AS _INTEGER64
  67.     DIM dx AS _INTEGER64
  68.     DIM x AS _INTEGER64
  69.     DIM y AS _INTEGER64
  70.     IF a = 0 OR b = 0 THEN EXIT SUB ' B+ added this
  71.     w2 = a * a
  72.     h2 = b * b
  73.     h2w2 = h2 * w2
  74.     xi = a
  75.     dx = 0
  76.     LINE (ox - a, oy)-(ox + a, oy), col, BF
  77.     ''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' y = 0 ' B+ added this to eliminate FOR loop
  78.     WHILE y < b 'b+ no FOR loop
  79.         y = y + 1
  80.         x = xi - dx + 2
  81.         WHILE x >= 1
  82.             x = x - 1
  83.             IF x * x * h2 + y * y * w2 <= h2w2 THEN EXIT WHILE
  84.         WEND
  85.         dx = xi - x
  86.         xi = x
  87.         LINE (ox - xi, oy + y)-(ox + xi, oy + y), col, BF
  88.         LINE (ox - xi, oy - y)-(ox + xi, oy - y), col, BF
  89.     WEND
  90.  
  91.  

I commented out one line in above code and now it is consistently matching or beating the Gold Standard Circle fill AND matching Circle fill's lowest time.

Here is the code for test I am using:
Code: QB64: [Select]
  1. _TITLE "STATIC Ellipse Fill versus Steve Circle Fill"
  2. '2019-02-12 add Pete's variation
  3.  
  4.  
  5. SCREEN _NEWIMAGE(1220, 680, 32)
  6. _SCREENMOVE 100, 20
  7.  
  8. FlatEllipseFill 915, 305, 300, 300, _RGBA32(0, 100, 0, 40)
  9. FlatEllipseFill 915, 305, 300, 300, _RGBA32(0, 100, 0, 40)
  10. INPUT "Flat EllipseFill overlap test, press enter to continue "; wate$
  11. LINE (0, 0)-(600, 20), _RGB32(0, 0, 0), BF
  12. start## = TIMER
  13. FOR i = 1 TO 10000
  14.     FlatEllipseFill 915, 305, 300, 300, _RGBA32(0, 100, 0, 100)
  15. EllipseTime## = TIMER - start##
  16. _PRINTSTRING (800, 615), "Time for 10000 Flat Ellipse Fills:" + STR$(EllipseTime##)
  17.  
  18.  
  19. ' ==================================================== compare to the old gold standard
  20.  
  21. CircleFill 305, 305, 300, _RGBA32(0, 100, 0, 40)
  22. CircleFill 305, 305, 300, _RGBA32(0, 100, 0, 40)
  23. LOCATE 1, 1: INPUT "CircleFill overlap test, press enter to continue "; wate$
  24. LINE (0, 0)-(600, 20), _RGB32(0, 0, 0), BF
  25.  
  26. start## = TIMER
  27. FOR i = 1 TO 10000
  28.     CircleFill 305, 305, 300, _RGBA32(0, 100, 0, 100)
  29. OldCircleTime## = TIMER - start##
  30. _PRINTSTRING (200, 615), "Time for 10000 Circle Fills:" + STR$(OldCircleTime##)
  31.  
  32. 'old circle fill
  33. SUB CircleFill (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  34.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  35.     DIM X AS INTEGER, Y AS INTEGER
  36.  
  37.     Radius = ABS(R)
  38.     RadiusError = -Radius
  39.     X = Radius
  40.     Y = 0
  41.  
  42.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  43.  
  44.     ' Draw the middle span here so we don't draw it twice in the main loop,
  45.     ' which would be a problem with blending turned on.
  46.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  47.  
  48.     WHILE X > Y
  49.         RadiusError = RadiusError + Y * 2 + 1
  50.         IF RadiusError >= 0 THEN
  51.             IF X <> Y + 1 THEN
  52.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  53.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  54.             END IF
  55.             X = X - 1
  56.             RadiusError = RadiusError - X * 2
  57.         END IF
  58.         Y = Y + 1
  59.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  60.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  61.     WEND
  62.  
  63.  
  64. SUB FlatEllipseFill (ox AS _INTEGER64, oy AS _INTEGER64, a AS _INTEGER64, b AS _INTEGER64, col AS _UNSIGNED LONG)
  65.     DIM h2 AS _INTEGER64
  66.     DIM w2 AS _INTEGER64
  67.     DIM h2w2 AS _INTEGER64
  68.     DIM xi AS _INTEGER64
  69.     DIM dx AS _INTEGER64
  70.     DIM x AS _INTEGER64
  71.     DIM y AS _INTEGER64
  72.     IF a = 0 OR b = 0 THEN EXIT SUB ' B+ added this
  73.     w2 = a * a
  74.     h2 = b * b
  75.     h2w2 = h2 * w2
  76.     xi = a
  77.     dx = 0
  78.     LINE (ox - a, oy)-(ox + a, oy), col, BF
  79.     'y = 0 ' B+ added this to eliminate FOR loop
  80.     WHILE y < b 'b+ no FOR loop
  81.         y = y + 1
  82.         x = xi - dx + 2
  83.         WHILE x >= 1
  84.             x = x - 1
  85.             IF x * x * h2 + y * y * w2 <= h2w2 THEN EXIT WHILE
  86.         WEND
  87.         dx = xi - x
  88.         xi = x
  89.         LINE (ox - xi, oy + y)-(ox + xi, oy + y), col, BF
  90.         LINE (ox - xi, oy - y)-(ox + xi, oy - y), col, BF
  91.     WEND
  92.  
  93. 'pete's variation 2019-02-12
  94. SUB FlatEllipseFill1 (ox AS INTEGER, oy AS INTEGER, a AS INTEGER, b AS INTEGER, col AS _UNSIGNED LONG)
  95.     IF a = 0 OR b = 0 THEN EXIT SUB
  96.     DIM h2 AS _INTEGER64
  97.     DIM w2 AS _INTEGER64
  98.     DIM h2w2 AS _INTEGER64
  99.     DIM yyw2 AS _INTEGER64
  100.     DIM xi AS INTEGER
  101.     DIM dx AS INTEGER
  102.     DIM x AS INTEGER
  103.     DIM y AS INTEGER
  104.     w2 = a * a
  105.     h2 = b * b
  106.     h2w2 = h2 * w2
  107.     xi = a
  108.     dx = 0
  109.     y = 0
  110.     LINE (ox - a, oy)-(ox + a, oy), col, BF
  111.     DO
  112.         y = y + 1
  113.         yyw2 = y * y * w2
  114.         x = xi - dx + 1
  115.         DO
  116.             IF x * x * h2 + yyw2 <= h2w2 THEN EXIT DO
  117.             x = x - 1
  118.         LOOP
  119.         dx = xi - x
  120.         xi = x
  121.         LINE (ox - xi, oy + y)-(ox + xi, oy + y), col, BF
  122.         LINE (ox - xi, oy - y)-(ox + xi, oy - y), col, BF
  123.     LOOP UNTIL y = b
  124.  
  125. 'vince variation on Steve  2019-02-12
  126. SUB FlatEllipseFill2 (x0, y0, rx, ry, c AS _UNSIGNED LONG)
  127.     a = 2 * rx * rx
  128.     b = 2 * ry * ry
  129.  
  130.  
  131.     x = 0
  132.     y = ry
  133.     dx = ry * ry
  134.     dy = rx * rx * (1 - 2 * ry)
  135.     e = 0
  136.     sx = 0
  137.     sy = a * ry
  138.  
  139.     DO WHILE sx <= sy
  140.         LINE (x0 - x, y0 + y)-STEP(2 * x, 0), c, BF
  141.         LINE (x0 - x, y0 - y)-STEP(2 * x, 0), c, BF
  142.  
  143.         x = x + 1
  144.         sx = sx + b
  145.         e = e + dx
  146.         dx = dx + b
  147.  
  148.         IF 2 * e + dy > 0 THEN
  149.             y = y - 1
  150.             sy = sy - a
  151.             e = e + dy
  152.             dy = dy + a
  153.         END IF
  154.     LOOP
  155.  
  156.     x1 = x0 - x
  157.     x2 = x0 + x
  158.     y1 = y0 - y
  159.  
  160.     x = rx
  161.     y = 0
  162.     dx = ry * ry * (1 - 2 * rx)
  163.     dy = rx * rx
  164.     e = 0
  165.     sx = b * rx
  166.     sy = 0
  167.  
  168.     x3 = x0 - x
  169.  
  170.     DO WHILE sx >= sy
  171.         LINE (x0 - x, y0 + y)-(x1, y0 + y), c, BF
  172.         LINE (x0 - x, y0 - y)-(x1, y0 - y), c, BF
  173.         LINE (x0 + x, y0 + y)-(x2, y0 + y), c, BF
  174.         LINE (x0 + x, y0 - y)-(x2, y0 - y), c, BF
  175.  
  176.         y = y + 1
  177.         sy = sy + a
  178.         e = e + dy
  179.         dy = dy + a
  180.  
  181.         IF 2 * e + dx > 0 THEN
  182.             x = x - 1
  183.             sx = sx - b
  184.             e = e + dx
  185.             dx = dx + b
  186.         END IF
  187.     LOOP
  188.  
  189.     LINE (x1, y1)-(x2, y0 + y), c, BF
  190.  
  191.  
  192.  
  193. 'pete's reversion back to SQR   WTH? it's fine time wise!
  194. 'pete's final? 2019-02-12  variation
  195. SUB FlatEllipseFill3 (ox AS INTEGER, oy AS INTEGER, a AS INTEGER, b AS INTEGER, col AS _UNSIGNED LONG)
  196.     IF a = 0 OR b = 0 THEN EXIT SUB
  197.     DIM h2 AS _INTEGER64
  198.     DIM w2 AS _INTEGER64
  199.     DIM h2w2 AS _INTEGER64
  200.     DIM yyw2 AS _INTEGER64
  201.     DIM x AS INTEGER
  202.     DIM y AS INTEGER
  203.     w2 = a * a
  204.     h2 = b * b
  205.     h2w2 = h2 * w2
  206.     x = a
  207.     LINE (ox - a, oy)-(ox + a, oy), col, BF
  208.     DO
  209.         y = y + 1
  210.         yyw2 = y * y * w2
  211.         x = SQR((h2w2 - yyw2) / h2)
  212.         LINE (ox - x, oy + y)-(ox + x, oy + y), col, BF
  213.         LINE (ox - x, oy - y)-(ox + x, oy - y), col, BF
  214.     LOOP UNTIL y = b
  215.  
  216. 'bplus reversion back to SQR  nope over twice the time!
  217. SUB FlatEllipseFill4 (CX AS LONG, CY AS LONG, xRadius AS LONG, yRadius AS LONG, c AS _UNSIGNED LONG)
  218.     DIM scale AS SINGLE, x AS LONG, y AS LONG, xr2 AS LONG
  219.     IF xRadius = 0 OR yRadius = 0 THEN EXIT SUB '<<<<<<<<<<<<< really do need to skip out with 0
  220.     scale = yRadius / xRadius
  221.     LINE (CX, CY - yRadius)-(CX, CY + yRadius), c, BF
  222.     xr2 = xRadius * xRadius
  223.     FOR x = 1 TO xRadius
  224.         y = scale * SQR(xr2 - x * x)
  225.         LINE (CX + x, CY - y)-(CX + x, CY + y), c, BF
  226.         LINE (CX - x, CY - y)-(CX - x, CY + y), c, BF
  227.     NEXT
  228.  
  229.  
  230.  

HA! I see a Y = 0 in circle fill code, maybe we could apply what we have learned to optimize it more. Radius = ABS(R) ???
« Last Edit: February 12, 2019, 03:08:59 pm by bplus »

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #93 on: February 12, 2019, 03:15:48 pm »
Mark, I tried your test program against my ellipse fill, #3 in your list, and got a better speed test than circle fill...

speedtest.jpg
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #94 on: February 12, 2019, 03:20:44 pm »
Dang! what's your system, my tests are running well under 17 secs.

I will try this in 32 bit QB64.

BTW, be sure to run tests with Browser OFF.
« Last Edit: February 12, 2019, 03:21:58 pm by bplus »

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #95 on: February 12, 2019, 03:25:09 pm »
LOL. My kid has the gaming computers. I'm on a $200 laptop that can't keep up with my typing most of the time! :D

OK 3 more tests with browser off. 225 total seconds for 3 runs for mine, 227 total seconds for Circle Fill. Basically a tie of 75 seconds each. Funny that both were slower with the browser off, but with so many things in Windows running in the background, who knows?

Pete
« Last Edit: February 12, 2019, 03:53:49 pm by Pete »
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #96 on: February 12, 2019, 04:13:28 pm »
OK I wrote timings down. This ran allot closer than I expected.
Quote
My system is Windows 10 64 bit laptop, intel core i5

Running tests on QB64, 32 bit version
circle Fill      Pete's Fill
14.3945         14.5039
14.3945         14.3984
14.2891         14.3945
14.2851         14.3984
14.3945         14.4039

circle Fill    STATIC Fill mod B+
14.2305         14.4531
14.2891         14.4492
14.3945         14.4531
14.1758         14.3984
14.2305         14.3984


Running tests on QB64, 64 bit version
circle Fill      Pete's Fill
16.8672         17.0313
16.9258         16.8672
16.8125         16.9219
16.8125         16.8125
16.8711         17.0352

circle Fill      STATIC Fill mod B+
16.9219         16.9766
16.9258         16.9766
16.8164         16.8711
16.8125         16.8672
16.8125         16.8125      

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #97 on: February 12, 2019, 05:04:24 pm »
No real speed variance with SQR, pretty cool! Mark, if you wondered why your try at SQR was twice as slow, it was because if used SQR in a loop. Mine just uses it it once per every two lines.

The double draw method Steve submitted is about 20% slower, and the changes Vince made slowed it down about 20% more. Oops. Feel free to challenge that, anyone.

I don't think I want to bother making a hash table form here, but that's where I'd go next to remove SQR from my modification. If we can establish that there is a limit for how wide an ellipse can be, then that's certainly possible. I'm only presuming it would be faster though, I don't know for certain.

I favor the SQR one I came up with, just because it is so simplistic. It would also piss off the C people who posted the other one Bill found, with the inner x loop. Pissing off C people with BASIC just makes me happy!  Oh, if you guys think I'm the only one, check this out, it's hilarious... https://social.microsoft.com/Forums/en-US/ed0e97aa-ea86-49dd-b5b0-01fd41c82cf2/using-com-port-with-qb64

Although... who knows, maybe someone will post some other method that eats our collective lunch. Stay tuned!

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #98 on: February 12, 2019, 05:25:44 pm »
Weird, I wasn't aware that I found my function somewhere, because I remember using a whiteboard and the equation of the ellipse to derive my most recent submission. Once a function is simple enough though, it becomes an irreducible mousetrap, and sortof a universal truth. Translation: I bet other smart people derived the same thing, it just *has* to be true. We're too late in computing history to have actually discovered something here.
You're not done when it works, you're done when it's right.

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #99 on: February 12, 2019, 06:06:56 pm »
https://stackoverflow.com/questions/10322341/simple-algorithm-for-drawing-filled-ellipse-in-c-c

That's why I like to use unique variables, like pete!

Well kudos for grinding it out on your own! I was about half way there, when you posted. After that, I looked around at some stuff on the net and determined I was just heading in the same direction, except that SQR thing was bugging me, so I went on with that after making some tests to see if Steve's find was out of the running. I couldn't see how working on the boob effect would be productive, if the routine ended up being slower, which it is. So on to this single draw system, which looks like the one we will wind up with, unless someone

This is fun stuff, and again kudos. What we need now is either a new method or a way to speed up that SQR calculation in my modification. I wonder how much the internal works grinds out the SQR calculations? It only needs to be rounded as an integer. I mean we could use a square root algorithm to do that, since a hash table is a bit of overkill. It's still a bit tricky to calculate square roots, and requires loops to approximate, even with the "trick" division.

Pete
« Last Edit: February 12, 2019, 06:08:31 pm by Pete »
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #100 on: February 12, 2019, 06:18:21 pm »
Say, there's a mother load of info!

The one with the ascii *-characters in the curved shape is a dead ringer for my method. They even use the same Leibnitz "dx" notation for the tiny increments because this is the same exact setup used to find the area of the ellipse. Calculus is a language after all, you say certain things the same way. Staring at it harder: yikes, do they not have a LINE statement?

I see someone even attempted to do the tilted case but chickened out before arriving at any code. I know exactly why this is, and is why I was so stubborn about solving that issue this week too. The reason? A tilted ellipse does not permit (that I could derive) a strict XY-equation for its position - there's always an extra parameter. After conceding to this, I unleashed the tilted function that takes the punch and uses an extra variable.

At this exact point, I'm not even sure which is the fastest anymore. As the dust settles on this, can anyone (namely Pete or bplus) paste the newest and the greatest below this? Are we going to need a separate function for just circles?
« Last Edit: February 12, 2019, 07:11:06 pm by STxAxTIC »
You're not done when it works, you're done when it's right.

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #101 on: February 12, 2019, 11:22:21 pm »
Bill: I don't think we need a separate circle routine. As long as the height and the width are the same... BAM, circle. Every bit as fast, too.

The two fastest routines are yours, as modified with different variable types and DO/LOOP replacing FOR/NEXT, and yours with my modifications to substitute SQR for the inner loop. The SQR one is just a tad faster in my tests.

Guys: Do you know in th e last loop x is always zero? That means this routine puts down a horizontal line and dots the top and bottom of any ellipse. I hope that's OK with everyone. Oh, to see what I'm yacking about, here are the numbers...

Code: QB64: [Select]
  1. FOR a = 1 TO 10
  2.     FOR b = 1 TO 10
  3.         CALL p(a, b)
  4.     NEXT
  5.  
  6. SUB p (a, b)
  7. w2 = a * a
  8. h2 = b * b
  9. h2w2 = h2 * w2
  10.     y = y + 1
  11.     yyw2 = y * y * w2
  12.     x = SQR((h2w2 - yyw2) / h2)
  13.     PRINT y; a; b; x; (h2w2 - yyw2) / h2
  14.     SLEEP
  15. LOOP UNTIL y = b
  16. PRINT "============================="
  17.  

I got rid of one more line and a variable in my SQR code. I'll repost it here. What I want to do now is compare it with ellipses of varying size. I also want to make sure I'm getting the same x values as the one that avoids SQR with an inner loop.

Latest SQR code:
Code: QB64: [Select]
  1. SUB FlatEllipseFill5 (ox AS INTEGER, oy AS INTEGER, a AS INTEGER, b AS INTEGER, col AS _UNSIGNED LONG)
  2. IF a = 0 OR b = 0 THEN EXIT SUB
  3. w2 = a * a
  4. h2 = b * b
  5. h2w2 = h2 * w2
  6. LINE (ox - a, oy)-(ox + a, oy), col, BF
  7. DO WHILE y < b
  8.     y = y + 1
  9.     x = SQR((h2w2 - y * y * w2) / h2)
  10.     LINE (ox - x, oy + y)-(ox + x, oy + y), col, BF
  11.     LINE (ox - x, oy - y)-(ox + x, oy - y), col, BF
  12.  

You have to admit, it's pretty freakin' optimized.

Edit: removed unnecessary x = a statement. Thanks Mark!

Pete
« Last Edit: February 12, 2019, 11:54:12 pm by Pete »
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #102 on: February 12, 2019, 11:33:30 pm »
You don't need x = a either but won't count for much.

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #103 on: February 13, 2019, 12:02:29 am »
Wow, thanks. I forgot that the single line uses a, not x. Woohoo, another one bites the dust. I'm putting together a test now just to make sure the SQR one does the same size lines as the loop one. I'll let you guys know the results soon.

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #104 on: February 13, 2019, 12:25:05 am »
Change the division to integer division.  It shaves off about a second on my test runs and still doesn't generate any duplicate lines from my preliminary testing:

Code: QB64: [Select]
  1. SUB FlatEllipseFill6 (ox AS INTEGER, oy AS INTEGER, a AS INTEGER, b AS INTEGER, col AS _UNSIGNED LONG)
  2.     IF a = 0 OR b = 0 THEN EXIT SUB
  3.     DIM h2 AS _INTEGER64
  4.     DIM w2 AS _INTEGER64
  5.     DIM h2w2 AS _INTEGER64
  6.     DIM x AS INTEGER
  7.     DIM y AS INTEGER
  8.     w2 = a * a
  9.     h2 = b * b
  10.     h2w2 = h2 * w2
  11.     LINE (ox - a, oy)-(ox + a, oy), col, BF
  12.     DO WHILE y < b
  13.         y = y + 1
  14.         x = SQR((h2w2 - y * y * w2) \ h2) ' <<<< HERE
  15.         LINE (ox - x, oy + y)-(ox + x, oy + y), col, BF
  16.         LINE (ox - x, oy - y)-(ox + x, oy - y), col, BF
  17.     LOOP
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!