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

0 Members and 1 Guest are viewing this topic.

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #15 on: February 09, 2019, 09:50:36 pm »
There's always an edge case I guess.

Welp, it turns out that the off-circle-ness is called the eccentricity, given by e=sqrt(1-b^2/a^2), where circles have e=0. In practice with this function, the programmer should rethink what he's doing if looking to apply this function to very eccentric shapes that are fussy down to the pixel.
You're not done when it works, you're done when it's right.

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #16 on: February 09, 2019, 09:58:54 pm »
... With all of the above said, do we all agree that:

(i) The code Steve brought to the table is the best flat ellipse fill
(ii) Bplus's mod to my tilted ellipse thing is basically ready to ship.

If that's true, then we have the first trickle of entries for a new subforum. Any last minute thoughts on these?
You're not done when it works, you're done when it's right.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #17 on: February 09, 2019, 11:06:07 pm »
Hold on, I am not ready to ship, I found a solution to alpha, still checking results.
« Last Edit: February 09, 2019, 11:10:36 pm by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #18 on: February 09, 2019, 11:19:15 pm »
No PAINT, no _PUTIMAGE, using rectilinear lines with BF! Now have alpha AND perfect narrow ellipse fills.
Code: QB64: [Select]
  1. _TITLE "Tilted Ellipse test" ' B+ 2019-02-09 Thanks to STxAxTIC's formula's
  2. SCREEN _NEWIMAGE(800, 600, 32)
  3. _SCREENMOVE 200, 40
  4. clr = _RGBA32(255, 128, 30, 50)
  5. TiltedEllipseFill 0, 400, 300, 300, 200, _PI(1 / 4), clr
  6. CIRCLE (400, 300), 300
  7. CIRCLE (400, 300), 200
  8. INPUT "Hopefully the ellipse radii fits in both circles, press enter..."; wate$
  9. WHILE _KEYDOWN(27) = 0
  10.     TiltedEllipseFill 0, RND * 600 + 100, RND * 400 + 100, RND * 100 + 1, RND * 100 + 1, _PI(RND * 2), _RGBA32(RND * 255, RND * 255, RND * 255, RND * 255)
  11.     _DISPLAY
  12.     _LIMIT 10
  13.  
  14. SUB TiltedEllipseFill (destHandle&, x0, y0, a, b, ang, c AS _UNSIGNED LONG)
  15.     DIM max AS INTEGER, mx2 AS INTEGER, i AS INTEGER, j AS INTEGER
  16.     DIM prc AS _UNSIGNED LONG
  17.     prc = _RGB32(255, 255, 255, 255)  ' prc for Paint Readable Color
  18.     IF a > b THEN max = a + 1 ELSE max = b + 1
  19.     mx2 = max + max
  20.     tef& = _NEWIMAGE(mx2, mx2)
  21.     _DEST tef&
  22.     _SOURCE tef& 'point wont read without this!
  23.     FOR k = 0 TO 6.2832 + .05 STEP .1
  24.         i = max + a * COS(k) * COS(ang) + b * SIN(k) * SIN(ang)
  25.         j = max - a * COS(k) * SIN(ang) + b * SIN(k) * COS(ang)
  26.         IF k <> 0 THEN
  27.             LINE (lasti, lastj)-(i, j), prc
  28.         ELSE
  29.             PSET (i, j), prc
  30.         END IF
  31.         lasti = i: lastj = j
  32.     NEXT
  33.     DIM xleft(mx2) AS INTEGER, xright(mx2) AS INTEGER, x AS INTEGER, y AS INTEGER
  34.     FOR y = 0 TO mx2
  35.         x = 0
  36.         WHILE POINT(x, y) <> prc AND x < mx2
  37.             x = x + 1
  38.         WEND
  39.         xleft(y) = x
  40.         WHILE POINT(x, y) = prc AND x < mx2
  41.             x = x + 1
  42.         WEND
  43.         WHILE POINT(x, y) <> prc AND x < mx2
  44.             x = x + 1
  45.         WEND
  46.         IF x = mx2 THEN xright(y) = xleft(y) ELSE xright(y) = x
  47.     NEXT
  48.     _DEST destHandle&
  49.     FOR y = 0 TO mx2
  50.         IF xleft(y) <> mx2 THEN LINE (xleft(y) + x0 - max, y + y0 - max)-(xright(y) + x0 - max, y + y0 - max), c, BF
  51.     NEXT
  52.     _FREEIMAGE tef&
  53.  
TEC 1 with alpha.PNG

 
tec 2 with alpha.PNG
« Last Edit: February 09, 2019, 11:23:36 pm by bplus »

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #19 on: February 09, 2019, 11:22:50 pm »
Nice work guys! For non-SCREEN 0 stuff, that is. ;)

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
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #20 on: February 09, 2019, 11:28:58 pm »
Hehe, leave it to Pete to beat me to the first comment. Thanks for following this!

Absolutely lovely work bplus. I'm shocked the whole thing came together so quickly.

As everyone probably noticed, these efforts will wind up in a place of their own, so that anytime these questions come up again, we have the answer in a nice section without a flame war occurring underneath. (My own fault usually.)
You're not done when it works, you're done when it's right.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • Steve’s QB64 Archive Forum
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #21 on: February 09, 2019, 11:49:52 pm »
Paint can handle alpha if _DONTBLEND is in use.  If you’re blending alpha, draw to a separate image first, then _PUTIMAGE the finished ellipseto the main screen.
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #22 on: February 09, 2019, 11:55:01 pm »
Found two small things that only help:

Code: QB64: [Select]
  1. FOR k = 0 TO 6.2832 + .05 STEP .05

The small offset next to the factor of 2*pi should agree with the step size.

And more interestingly:

Code: QB64: [Select]
  1. IF xleft(y) <> mx2 THEN LINE (xleft(y) + x0 - max, y + y0 - max)-(xright(y) + x0 - max, y + y0 - max), c

... doesn't need BF or even B. Every line is strictly horizontal as y + y0 - max is the only y-argument in the LINE statement above.
« Last Edit: February 09, 2019, 11:58:44 pm by STxAxTIC »
You're not done when it works, you're done when it's right.

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #23 on: February 10, 2019, 12:00:30 am »
And since the function has broken the underscore barrier, so to speak - what about what Steve just said? Can that make the whole thing smaller and faster?

Damn, while I love my armchair over here in the Science department, I should mingle more with the engineers who use QB64 commands a little more often...
« Last Edit: February 10, 2019, 12:09:09 am by STxAxTIC »
You're not done when it works, you're done when it's right.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #24 on: February 10, 2019, 12:15:12 am »
Well I found another correction, the angle and equations work for a Cartesian coordinate system but unfortunately Basic angles start 0 due east and rotate clockwise, so I adjusted equations to follow Basic Angle system.

BF used for lines because according to Steve it is faster than drawing a line. It was a part of the optimizations for CircleFill.

I rounded pi * 2 up so .05 would have worked with .1 STEP (it was) but I did forget I changed back to .1 with STEP. That, BTW is another place that could be optimized for best size to step depending on big or small ellipse circumference.

Here is TiltedEllipseFill with QB64 Basic System of Angle designations:
Code: QB64: [Select]
  1. _TITLE "Tilted Ellipse Oops" ' B+ 2019-02-10 oops we have a problem with Angle designation
  2. ' Thanks to STxAxTIC's formula's
  3.  
  4. ' Oops! I forgot to take into account STxAxTIC's Cartisian Coordinate System: Angles
  5.  
  6. SCREEN _NEWIMAGE(800, 600, 32)
  7. _SCREENMOVE 200, 40
  8. clr = _RGBA32(255, 128, 30, 50)
  9. WHILE _KEYDOWN(27) = 0
  10.     CLS
  11.     a = a + _PI(1 / 180)
  12.     PRINT "Angle:"; INT(_R2D(a))
  13.     TiltedEllipseFill 0, 400, 300, 300, 200, a, clr
  14.     LINE (400, 300)-(400 + 300 * COS(a), 300 + 300 * SIN(a))
  15.     _DISPLAY
  16.     _LIMIT 10
  17.  
  18. SUB TiltedEllipseFill (destHandle&, x0, y0, a, b, ang, c AS _UNSIGNED LONG)
  19.     DIM max AS INTEGER, mx2 AS INTEGER, i AS INTEGER, j AS INTEGER
  20.     DIM prc AS _UNSIGNED LONG
  21.     prc = _RGB32(255, 255, 255, 255)
  22.     IF a > b THEN max = a + 1 ELSE max = b + 1
  23.     mx2 = max + max
  24.     tef& = _NEWIMAGE(mx2, mx2)
  25.     _DEST tef&
  26.     _SOURCE tef& 'point wont read without this!
  27.     FOR k = 0 TO 6.2832 + .05 STEP .1
  28.         i = max + a * COS(k) * COS(ang) + b * SIN(k) * SIN(ang)
  29.         j = max + a * COS(k) * SIN(ang) - b * SIN(k) * COS(ang)
  30.         IF k <> 0 THEN
  31.             LINE (lasti, lastj)-(i, j), prc
  32.         ELSE
  33.             PSET (i, j), prc
  34.         END IF
  35.         lasti = i: lastj = j
  36.     NEXT
  37.     DIM xleft(mx2) AS INTEGER, xright(mx2) AS INTEGER, x AS INTEGER, y AS INTEGER
  38.     FOR y = 0 TO mx2
  39.         x = 0
  40.         WHILE POINT(x, y) <> prc AND x < mx2
  41.             x = x + 1
  42.         WEND
  43.         xleft(y) = x
  44.         WHILE POINT(x, y) = prc AND x < mx2
  45.             x = x + 1
  46.         WEND
  47.         WHILE POINT(x, y) <> prc AND x < mx2
  48.             x = x + 1
  49.         WEND
  50.         IF x = mx2 THEN xright(y) = xleft(y) ELSE xright(y) = x
  51.     NEXT
  52.     _DEST destHandle&
  53.     FOR y = 0 TO mx2
  54.         IF xleft(y) <> mx2 THEN LINE (xleft(y) + x0 - max, y + y0 - max)-(xright(y) + x0 - max, y + y0 - max), c, BF
  55.     NEXT
  56.     _FREEIMAGE tef&
  57.  
TEF angle fix.PNG
* TEF angle fix.PNG (Filesize: 9.39 KB, Dimensions: 803x627, Views: 401)
« Last Edit: February 10, 2019, 12:20:04 am by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #25 on: February 10, 2019, 12:23:36 am »
The _DONTBLEND might fix the paint issue but not the poor painting job done with narrow ellipsii.

It's timed tests time if Steve is correct.

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #26 on: February 10, 2019, 12:27:23 am »
Again your thoroughness is appreciated. Once this thread cools down we'll crystallize the results in the new section. In the meantime, anyone with works that may fit there - sorting routines and the like - are welcome to post that stuff to Programs, or bump it to resurrect the thread.

(That reminds me - Steve, is your screen capture stuff hanging around? We could use a bump on that one, plus a handful of your other things that I'll try to name if they don't surface naturally soon.)
« Last Edit: February 10, 2019, 10:53:39 pm by STxAxTIC »
You're not done when it works, you're done when it's right.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #27 on: February 10, 2019, 12:43:07 am »
For me, _DONTBLEND makes everything Opaque so whole image rectangle (yuck!!), black and all, is transferred over with _PUTIMAGE, with no alpha transparencies.

Steve may have solution?

Meanwhile a timed test with the alpha beauties.
« Last Edit: February 10, 2019, 12:48:48 am by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #28 on: February 10, 2019, 11:53:18 am »
Problem!

While doing speed tests, I found Steve's EllipseFill was drawing overlapping lines at regular intervals with a held at 400 and b increased from 0 to 400.

Overlaps at b=45, 57, 67, 81, 86, 93... that is just the first few found.
Code: QB64: [Select]
  1. _TITLE "Ellipsefill from Steve"
  2. SCREEN _NEWIMAGE(1000, 700, 32)
  3. _SCREENMOVE 180, 20
  4. 'B+ 2019-02-10 resave this code to
  5. 'just test this code for proper filling without overlap, timed tests are else where
  6.  
  7. FOR i = 0 TO 400 'draw ellipse at various heights
  8.  
  9.     CLS
  10.     PRINT "b Radius"; i; "   press any to get to 400, <backspace> to go back one, <esc> for next test."
  11.  
  12.     EllipseFill 500, 350, 400, i, _RGBA(255, 255, 255, 40)
  13.     k$ = ""
  14.     WHILE LEN(k$) = 0: k$ = INKEY$: WEND
  15.     IF k$ = CHR$(8) THEN i = i - 2
  16.     IF k$ = CHR$(27) THEN EXIT FOR
  17.  
  18. WHILE _KEYDOWN(32) = 0 'check all sorts random stuff
  19.     EllipseFill RND * 1000, RND * 700, RND * 100, RND * 100, _RGBA32(255 * RND, 255 * RND, 255 * RND, 100 * RND)
  20.     _LIMIT 1
  21.  
  22.  
  23.  
  24. ' with Steve's EllipseFill, who needs CircleFill? fix for 0 radii 2019-02-05
  25. ' Is this fast enough for general circle fill (June 2018):  https://www.qb64.org/forum/index.php?topic=298.msg1942#msg1942
  26. '  EllipseFill SMcNeill (Nov 3, 2018) https://www.qb64.org/forum/index.php?topic=755.msg6506#msg6506
  27. SUB EllipseFill (cx AS INTEGER, cy AS INTEGER, rx AS INTEGER, ry AS INTEGER, c AS _UNSIGNED LONG)
  28.     DIM a AS LONG, b AS LONG
  29.     DIM x AS LONG, y AS LONG
  30.     DIM xx AS LONG, yy AS LONG
  31.     DIM sx AS LONG, sy AS LONG
  32.     DIM e AS LONG
  33.  
  34.     IF rx = 0 OR ry = 0 THEN EXIT SUB 'nothing to draw, B+ added this to avoid errors when b was 0
  35.  
  36.     a = 2 * rx * rx
  37.     b = 2 * ry * ry
  38.     x = rx
  39.     xx = ry * ry * (1 - rx - rx)
  40.     yy = rx * rx
  41.     sx = b * rx
  42.  
  43.     DO WHILE sx >= sy 'no = ? , nope that didn't help
  44.         LINE (cx - x, cy - y)-(cx + x, cy - y), c, BF
  45.         IF y <> 0 THEN LINE (cx - x, cy + y)-(cx + x, cy + y), c, BF
  46.  
  47.         y = y + 1
  48.         sy = sy + a
  49.         e = e + yy
  50.         yy = yy + a
  51.  
  52.         IF (e + e + xx) > 0 THEN 'add = ? nope no fix
  53.             x = x - 1
  54.             sx = sx - b
  55.             e = e + xx
  56.             xx = xx + b
  57.         END IF
  58.     LOOP
  59.  
  60.     x = 0
  61.     y = ry
  62.     xx = rx * ry
  63.     yy = rx * rx * (1 - ry - ry)
  64.     e = 0
  65.     sx = 0
  66.     sy = a * ry
  67.  
  68.     DO WHILE sx <= sy ' no  =  ? fixed once but mostly no fix
  69.         LINE (cx - x, cy - y)-(cx + x, cy - y), c, BF
  70.         LINE (cx - x, cy + y)-(cx + x, cy + y), c, BF
  71.  
  72.         DO
  73.             x = x + 1
  74.             sx = sx + b
  75.             e = e + xx
  76.             xx = xx + b
  77.         LOOP UNTIL (e + e + yy) > 0 'add = ? nope no fix
  78.  
  79.         y = y - 1
  80.         sy = sy - a
  81.         e = e + yy
  82.         yy = yy + a
  83.  
  84.     LOOP
  85.  
  86.  
  87.  
« Last Edit: February 10, 2019, 12:00:28 pm by bplus »

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #29 on: February 10, 2019, 11:59:36 am »
Your attention to detail is indispensable plus! I wonder if the algorithm can be torn apart to find out why that happens... The thing seems to be *so* optimized that it became fragile. As soon as I get near a PC I will join your efforts...
« Last Edit: February 10, 2019, 10:54:08 pm by STxAxTIC »
You're not done when it works, you're done when it's right.