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

0 Members and 1 Guest are viewing this topic.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #150 on: February 16, 2019, 09:52:04 am »
Alrighty, considering using this for the final submission. Super bare-bones as it should be (whoever wants some backstory will be able to click a link to this thread). The obvious contributors are, in ABC order, bplus, pete, smcneill, and yours truly. Anyone not in favor, speak now or forever hold your peace. (I'm interested in moving on to the next thing, as is probably everyone.)

I made an effort to unify the notation, so if you *do* have an edit to make, use what's posted below, or make sure the notation is maintained.

EDIT

Opps, didn't add the un-filled, yes-tilted ellipse yet. Luckily this is so easy even *I* can do that, as it won't be needing any newfangled underscore technology. Just my original post without the PAINT statement.

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(800, 600, 32)
  2.  
  3. DIM TransRed AS _UNSIGNED LONG
  4. DIM TransGreen AS _UNSIGNED LONG
  5. DIM TransBlue AS _UNSIGNED LONG
  6. TransRed = _RGBA(255, 0, 0, 128)
  7. TransGreen = _RGBA(0, 255, 0, 128)
  8. TransBlue = _RGBA(0, 0, 255, 128)
  9.  
  10. CALL CircleFill(100, 100, 75, TransRed)
  11. CALL CircleFill(120, 120, 75, TransBlue)
  12.  
  13. CALL EllipseFill(550, 100, 150, 75, TransBlue)
  14. CALL EllipseFill(570, 120, 150, 75, TransGreen)
  15.  
  16. CALL EllipseTiltFill(0, 350, 400, 150, 75, 3.14 / 6, TransGreen)
  17. CALL EllipseTiltFill(0, 370, 420, 150, 75, 3.14 / 4, TransRed)
  18.  
  19.  
  20. SUB CircleFill (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  21.     ' CX = center x coordinate
  22.     ' CY = center y coordinate
  23.     '  R = radius
  24.     '  C = fill color
  25.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  26.     DIM X AS INTEGER, Y AS INTEGER
  27.     Radius = ABS(R)
  28.     RadiusError = -Radius
  29.     X = Radius
  30.     Y = 0
  31.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  32.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  33.     WHILE X > Y
  34.         RadiusError = RadiusError + Y * 2 + 1
  35.         IF RadiusError >= 0 THEN
  36.             IF X <> Y + 1 THEN
  37.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  38.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  39.             END IF
  40.             X = X - 1
  41.             RadiusError = RadiusError - X * 2
  42.         END IF
  43.         Y = Y + 1
  44.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  45.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  46.     WEND
  47.  
  48. SUB EllipseFill (CX AS INTEGER, CY AS INTEGER, a AS INTEGER, b AS INTEGER, C AS _UNSIGNED LONG)
  49.     ' CX = center x coordinate
  50.     ' CY = center y coordinate
  51.     '  a = semimajor axis
  52.     '  b = semiminor axis
  53.     '  C = fill color
  54.     IF a = 0 OR b = 0 THEN EXIT SUB
  55.     DIM h2 AS _INTEGER64
  56.     DIM w2 AS _INTEGER64
  57.     DIM h2w2 AS _INTEGER64
  58.     DIM x AS INTEGER
  59.     DIM y AS INTEGER
  60.     w2 = a * a
  61.     h2 = b * b
  62.     h2w2 = h2 * w2
  63.     LINE (CX - a, CY)-(CX + a, CY), C, BF
  64.     DO WHILE y < b
  65.         y = y + 1
  66.         x = SQR((h2w2 - y * y * w2) \ h2)
  67.         LINE (CX - x, CY + y)-(CX + x, CY + y), C, BF
  68.         LINE (CX - x, CY - y)-(CX + x, CY - y), C, BF
  69.     LOOP
  70.  
  71. SUB EllipseTiltFill (destHandle&, CX, CY, a, b, ang, C AS _UNSIGNED LONG)
  72.     '  destHandle& = destination handle
  73.     '  CX = center x coordinate
  74.     '  CY = center y coordinate
  75.     '   a = semimajor axis
  76.     '   b = semiminor axis
  77.     ' ang = clockwise orientation of semimajor axis in radians (0 default)
  78.     '   C = fill color
  79.     DIM max AS INTEGER, mx2 AS INTEGER, i AS INTEGER, j AS INTEGER
  80.     DIM prc AS _UNSIGNED LONG
  81.     DIM D AS INTEGER, S AS INTEGER
  82.     D = _DEST: S = _SOURCE
  83.     prc = _RGB32(255, 255, 255, 255)
  84.     IF a > b THEN max = a + 1 ELSE max = b + 1
  85.     mx2 = max + max
  86.     tef& = _NEWIMAGE(mx2, mx2)
  87.     _DEST tef&
  88.     _SOURCE tef&
  89.     FOR k = 0 TO 6.283185307179586 + .025 STEP .025
  90.         i = max + a * COS(k) * COS(ang) + b * SIN(k) * SIN(ang)
  91.         j = max + a * COS(k) * SIN(ang) - b * SIN(k) * COS(ang)
  92.         IF k <> 0 THEN
  93.             LINE (lasti, lastj)-(i, j), prc
  94.         ELSE
  95.             PSET (i, j), prc
  96.         END IF
  97.         lasti = i: lastj = j
  98.     NEXT
  99.     DIM xleft(mx2) AS INTEGER, xright(mx2) AS INTEGER, x AS INTEGER, y AS INTEGER
  100.     FOR y = 0 TO mx2
  101.         x = 0
  102.         WHILE POINT(x, y) <> prc AND x < mx2
  103.             x = x + 1
  104.         WEND
  105.         xleft(y) = x
  106.         WHILE POINT(x, y) = prc AND x < mx2
  107.             x = x + 1
  108.         WEND
  109.         WHILE POINT(x, y) <> prc AND x < mx2
  110.             x = x + 1
  111.         WEND
  112.         IF x = mx2 THEN xright(y) = xleft(y) ELSE xright(y) = x
  113.     NEXT
  114.     _DEST destHandle&
  115.     FOR y = 0 TO mx2
  116.         IF xleft(y) <> mx2 THEN LINE (xleft(y) + CX - max, y + CY - max)-(xright(y) + CX - max, y + CY - max), C, BF
  117.     NEXT
  118.     _DEST D: _DEST S
  119.     _FREEIMAGE tef&
  120.  

A couple of things just from quick scan of Bill's 2nd final complete code post (above):

Bill:
Quote
Opps, didn't add the un-filled, yes-tilted ellipse yet. Luckily this is so easy even *I* can do that, as it won't be needing any newfangled underscore technology. Just my original post without the PAINT statement.

Bill that had problems using the Cartesian coordinate system with y-axis flipped and angles increasing in counter-clockwise direction. Build the Tilted Ellipse code from the TiltedEllipseFill code.

The a and b parameters represent NOT the major and minor axis respectively but the x and y axis respectively ie a is not always greater than or equal to b. And the angle of tilt when 0, would put the a radius parallel with the x-axis.
« Last Edit: February 16, 2019, 09:57:29 am by bplus »

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #151 on: February 16, 2019, 09:54:03 am »
crap, ran out of time for this, probably for weeks to come

ask Fell or luke for librarian creds
« Last Edit: February 16, 2019, 09:58:34 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 + ...
    • View Profile
Re: Seeking best ellipse fill function. (For everyone's sake.)
« Reply #152 on: February 16, 2019, 10:00:26 am »
... dang it, Bill had something else posted that I was replying to, now gone.

OK tested EllipseTilt and Bill did not use the original one without the PAINT because the current one fits TiltedEllipseFill and is changing angle correctly to Basic system coordinates. I still object to descriptions of a and b parameters and offer an alternate wording closer to the actual facts.

Code: QB64: [Select]
  1. _TITLE "Tilted Ellipse Angle test" ' B+ 2019-02-16 check Bill's code for EllipseTilt
  2.  
  3. SCREEN _NEWIMAGE(1000, 700, 32)
  4. _SCREENMOVE 100, 20
  5. CX = 500
  6. CY = 350
  7. a = 100
  8. b = 340
  9.  
  10. FOR ang = 0 TO 2 * _PI STEP _PI(2 / 12) 'draw ellipse at various heights and compare to CIRCLE with aspect i/300
  11.     CLS
  12.     PRINT "Angle tilt:"; INT(_R2D(ang) + .5)
  13.     TiltedEllipseFill 0, CX, CY, a, b, 0, _RGBA(255, 255, 255, 40)
  14.     TiltedEllipseFill 0, CX, CY, a, b, ang, _RGBA(255, 255, 255, 100)
  15.     EllipseTilt CX, CY, a, b, ang, _RGBA(255, 255, 255, 100)
  16.     CIRCLE (CX, CY), a
  17.     CIRCLE (CX, CY), b
  18.     LINE (CX, CY)-(CX + a * COS(ang), CY + a * SIN(ang))
  19.     _DISPLAY
  20.     IF a = _PI(2 / 12) THEN _DELAY 5 ELSE _LIMIT 1
  21.  
  22. SUB TiltedEllipseFill (destHandle&, ox, oy, a, b, ang, col AS _UNSIGNED LONG)
  23.     DIM max AS INTEGER, mx2 AS INTEGER, i AS INTEGER, j AS INTEGER
  24.     DIM prc AS _UNSIGNED LONG
  25.  
  26.     DIM D AS INTEGER, S AS INTEGER 'to preserve old settings
  27.     D = _DEST: S = _SOURCE
  28.  
  29.     prc = _RGB32(255, 255, 255, 255)
  30.     IF a > b THEN max = a + 1 ELSE max = b + 1
  31.     mx2 = max + max
  32.     tef& = _NEWIMAGE(mx2, mx2)
  33.     _DEST tef&
  34.     _SOURCE tef& 'point wont read without this!
  35.     FOR k = 0 TO 6.2832 + .05 STEP .1
  36.         i = max + a * COS(k) * COS(ang) + b * SIN(k) * SIN(ang)
  37.         j = max + a * COS(k) * SIN(ang) - b * SIN(k) * COS(ang)
  38.         IF k <> 0 THEN
  39.             LINE (lasti, lastj)-(i, j), prc
  40.         ELSE
  41.             PSET (i, j), prc
  42.         END IF
  43.         lasti = i: lastj = j
  44.     NEXT
  45.     DIM xleft(mx2) AS INTEGER, xright(mx2) AS INTEGER, x AS INTEGER, y AS INTEGER
  46.     FOR y = 0 TO mx2
  47.         x = 0
  48.         WHILE POINT(x, y) <> prc AND x < mx2
  49.             x = x + 1
  50.         WEND
  51.         xleft(y) = x
  52.         WHILE POINT(x, y) = prc AND x < mx2
  53.             x = x + 1
  54.         WEND
  55.         WHILE POINT(x, y) <> prc AND x < mx2
  56.             x = x + 1
  57.         WEND
  58.         IF x = mx2 THEN xright(y) = xleft(y) ELSE xright(y) = x
  59.     NEXT
  60.     _DEST destHandle&
  61.     FOR y = 0 TO mx2
  62.         IF xleft(y) <> mx2 THEN LINE (xleft(y) + ox - max, y + oy - max)-(xright(y) + ox - max, y + oy - max), col, BF
  63.     NEXT
  64.     _DEST D: _DEST S 'restore those old settings
  65.     _FREEIMAGE tef&
  66.  
  67. SUB EllipseTilt (CX, CY, a, b, ang, C AS _UNSIGNED LONG) 'by STATIC
  68.     '  CX = center x coordinate
  69.     '  CY = center y coordinate
  70.     '   a = Flat ellipse x-axis   '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< B+ changed comment
  71.     '   b = Flat ellipse y-axis   '<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< B+ changed comment
  72.     ' ang = clockwise orientation of semimajor axis in radians (0 default)
  73.     '   C = fill color
  74.     FOR k = 0 TO 6.283185307179586 + .025 STEP .025
  75.         i = a * COS(k) * COS(ang) + b * SIN(k) * SIN(ang)
  76.         j = -a * COS(k) * SIN(ang) + b * SIN(k) * COS(ang)
  77.         i = i + CX
  78.         j = -j + CY
  79.         IF k <> 0 THEN
  80.             LINE -(i, j), C
  81.         ELSE
  82.             PSET (i, j), C
  83.         END IF
  84.     NEXT
  85.  
  86.  
  87.  


 
Tilted Ellipse Angle test.PNG
« Last Edit: February 16, 2019, 11:00:43 am by bplus »