Author Topic: Too different Tilt Ellipse fills  (Read 3664 times)

0 Members and 1 Guest are viewing this topic.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Too different Tilt Ellipse fills
« on: December 15, 2019, 09:13:50 pm »
I don't get it, in the following app demo of the Toolbox TiltedEllipseFill routine, it works beautifully and the fTiltEllipse routine I came up with today stinks! The Toolbox code can handle very subtle and many layers of transparency but not mine, that needs to start way way more opaque just to be seen and can't do nearly as many layers. Probably something about backgrounds??
Code: QB64: [Select]
  1. _TITLE "Tilted Ellipse app" ' B+ 2019-02-12  add fTiltEllipse routine for comparison
  2.  
  3. CONST xmx = 640
  4. CONST ymx = 640
  5. SCREEN _NEWIMAGE(xmx, ymx, 32)
  6. _SCREENMOVE 340, 40
  7. DIM k AS _UNSIGNED LONG, c, r, stepper, offset, a, x, y
  8. c = xmx / 2
  9. FOR r = 210 TO 0 STEP -30
  10.     stepper = stepper + 30
  11.     offset = offset - _PI(2 / 24)
  12.     FOR a = 0 TO 2 * _PI - .001 STEP _PI(2 / 12)
  13.         x = c + r * COS(a + offset)
  14.         y = c + r * SIN(a + offset)
  15.         k = _RGBA32(0, 0, 200, 15)
  16.         'TiltedEllipseFill 0, x, y, 250 - stepper, stepper, a + offset, k
  17.         fTiltEllipse 0, x, y, 250 - stepper, stepper, a + offset, &H67000090
  18.         _LIMIT 12
  19.     NEXT
  20.  
  21. SUB TiltedEllipseFill (destHandle&, x0, y0, a, b, ang, c AS _UNSIGNED LONG)
  22.     DIM max AS INTEGER, mx2 AS INTEGER, i AS INTEGER, j AS INTEGER, lasti, lastj
  23.     DIM prc AS _UNSIGNED LONG, tef&, k
  24.     prc = _RGB32(255, 255, 255, 255)
  25.     IF a > b THEN max = a + 1 ELSE max = b + 1
  26.     mx2 = max + max
  27.     tef& = _NEWIMAGE(mx2, mx2)
  28.     _DEST tef&
  29.     _SOURCE tef& 'point wont read without this!
  30.     FOR k = 0 TO 6.2832 + .05 STEP .1
  31.         i = max + a * COS(k) * COS(ang) + b * SIN(k) * SIN(ang)
  32.         j = max + a * COS(k) * SIN(ang) - b * SIN(k) * COS(ang)
  33.         IF k <> 0 THEN
  34.             LINE (lasti, lastj)-(i, j), prc
  35.         ELSE
  36.             PSET (i, j), prc
  37.         END IF
  38.         lasti = i: lastj = j
  39.     NEXT
  40.     DIM xleft(mx2) AS INTEGER, xright(mx2) AS INTEGER, x AS INTEGER, y AS INTEGER
  41.     FOR y = 0 TO mx2
  42.         x = 0
  43.         WHILE POINT(x, y) <> prc AND x < mx2
  44.             x = x + 1
  45.         WEND
  46.         xleft(y) = x
  47.         WHILE POINT(x, y) = prc AND x < mx2
  48.             x = x + 1
  49.         WEND
  50.         WHILE POINT(x, y) <> prc AND x < mx2
  51.             x = x + 1
  52.         WEND
  53.         IF x = mx2 THEN xright(y) = xleft(y) ELSE xright(y) = x
  54.     NEXT
  55.     _DEST destHandle&
  56.     FOR y = 0 TO mx2
  57.         IF xleft(y) <> mx2 THEN LINE (xleft(y) + x0 - max, y + y0 - max)-(xright(y) + x0 - max, y + y0 - max), c, BF
  58.     NEXT
  59.     _FREEIMAGE tef&
  60.  
  61.  
  62. 'replace broken toolbox code
  63. 'this needs RotoZoom3 to rotate image BUT it can now scale it also!
  64. SUB fTiltEllipse (destH AS LONG, ox AS INTEGER, oy AS INTEGER, majorRadius AS INTEGER, minorRadius AS INTEGER, radianAngle AS SINGLE, c AS _UNSIGNED LONG)
  65.     'setup isolated area, draw fFlatEllipse and then RotoZoom the image into destination
  66.     'ox, oy is center of ellipse
  67.     'majorRadius is 1/2 the lonest axis
  68.     'minorRadius is 1/2 the short axis
  69.     'radianAngle is the Radian Angle of Tilt
  70.     'c is of course color
  71.     DIM sd&, temp&
  72.     sd& = _DEST
  73.     temp& = _NEWIMAGE(2 * majorRadius, 2 * minorRadius, 32)
  74.     _DEST temp&
  75.     fEllipse majorRadius, minorRadius, majorRadius, minorRadius, c
  76.     _DEST destH
  77.     RotoZoom3 ox, oy, temp&, 1, 1, radianAngle
  78.     _FREEIMAGE temp&
  79.     _DEST sd&
  80.  
  81. 'modified 2019-12-15 _seamless added, rotation convert to radians
  82. SUB RotoZoom3 (X AS LONG, Y AS LONG, Image AS LONG, xScale AS SINGLE, yScale AS SINGLE, radianRotation AS SINGLE) ' 0 at end means no scaling of x or y
  83.     DIM px(3) AS SINGLE: DIM py(3) AS SINGLE
  84.     DIM W&, H&, sinr!, cosr!, i&, x2&, y2&
  85.     W& = _WIDTH(Image&): H& = _HEIGHT(Image&)
  86.     px(0) = -W& / 2: py(0) = -H& / 2: px(1) = -W& / 2: py(1) = H& / 2
  87.     px(2) = W& / 2: py(2) = H& / 2: px(3) = W& / 2: py(3) = -H& / 2
  88.     sinr! = SIN(-radianRotation): cosr! = COS(-radianRotation)
  89.     FOR i& = 0 TO 3
  90.         x2& = (px(i&) * cosr! + sinr! * py(i&)) + X * xScale: y2& = (py(i&) * cosr! - px(i&) * sinr!) + Y * yScale
  91.         px(i&) = x2&: py(i&) = y2&
  92.     NEXT
  93.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, H& - 1)-(W& - 1, H& - 1), Image& TO(px(0), py(0))-(px(1), py(1))-(px(2), py(2))
  94.     _MAPTRIANGLE _SEAMLESS(0, 0)-(W& - 1, 0)-(W& - 1, H& - 1), Image& TO(px(0), py(0))-(px(3), py(3))-(px(2), py(2))
  95.  
  96. 'this seems to work as well as any
  97. SUB fEllipse (CX AS LONG, CY AS LONG, xRadius AS LONG, yRadius AS LONG, c AS _UNSIGNED LONG)
  98.     DIM scale AS SINGLE, x AS LONG, y AS LONG
  99.     scale = yRadius / xRadius
  100.     LINE (CX, CY - yRadius)-(CX, CY + yRadius), c, BF
  101.     FOR x = 1 TO xRadius
  102.         y = scale * SQR(xRadius * xRadius - x * x)
  103.         LINE (CX + x, CY - y)-(CX + x, CY + y), c, BF
  104.         LINE (CX - x, CY - y)-(CX - x, CY + y), c, BF
  105.     NEXT
  106.  
  107.  


But in the recent megaphone drawing app, the toolbox code leaves a striping of horizontal lines often, using transparencies or not, whereas my fTiltEllipse routine of today does fine filling with a nice smooth layer:

Code: QB64: [Select]
  1. _TITLE "fTiltEllipse tests" 'b+ 2019-12-15
  2. 'test code from "Draw megaphone Test, click 4 points in clockwise direction first pair is one opening and 2nd is 2nd." 'B+ 2019-12-15
  3.  
  4. CONST xmax = 800, ymax = 600
  5. SCREEN _NEWIMAGE(xmax, ymax, 32)
  6. _SCREENMOVE 300, 40
  7.  
  8.     CLS
  9.     WHILE pi < 4 'get 4 mouse clicks
  10.         _PRINTSTRING (5, 5), SPACE$(20)
  11.         _PRINTSTRING (5, 5), "Need 4 clicks, have" + STR$(pi)
  12.         WHILE _MOUSEINPUT: WEND
  13.         IF _MOUSEBUTTON(1) AND oldMouse = 0 THEN 'new mouse down
  14.             pi = pi + 1
  15.             mx(pi) = _MOUSEX: my(pi) = _MOUSEY
  16.             CIRCLE (mx(pi), my(pi)), 2
  17.         END IF
  18.         oldMouse = _MOUSEBUTTON(1)
  19.         _DISPLAY
  20.         _LIMIT 60
  21.     WEND
  22.     LINE (mx(2), my(2))-(mx(3), my(3))
  23.     LINE (mx(4), my(4))-(mx(1), my(1))
  24.     ang1 = _ATAN2(my(2) - my(1), mx(2) - mx(1))
  25.     maj1 = (_HYPOT(mx(1) - mx(2), my(1) - my(2))) / 2
  26.     min1 = .1 * maj1
  27.     cx1 = (mx(1) + mx(2)) / 2
  28.     cy1 = (my(1) + my(2)) / 2
  29.     EllipseTilt cx1, cy1, maj1, min1, ang1, &HFFFFFFFF
  30.     ang2 = _ATAN2(my(3) - my(4), mx(3) - mx(4))
  31.     maj2 = (_HYPOT(mx(3) - mx(4), my(3) - my(4))) / 2
  32.     min2 = .1 * maj2
  33.     cx2 = (mx(3) + mx(4)) / 2
  34.     cy2 = (my(3) + my(4)) / 2
  35.     EllipseTilt cx2, cy2, maj2, min2, ang2, &HFFFFFFFF
  36.     _DISPLAY
  37.     _DELAY 3
  38.     CLS
  39.     _PRINTSTRING (5, 5), "Sleeping, wake with click or keypress..."
  40.     'fTiltEllipse 0, cx2, cy2, maj2, min2, ang2, &H880000FF 'check trnasparency
  41.     TiltedEllipseFill 0, cx2, cy2, maj2, min2, ang2, &HFF0000FF 'check trnasparency <<< Toolbox fill
  42.     fquad mx(1), my(1), mx(2), my(2), mx(3), my(3), mx(4), my(4), &H880000FF
  43.     'fTiltEllipse 0, cx1, cy1, maj1, min1, ang1, &H88FFFF00
  44.     TiltedEllipseFill 0, cx1, cy1, maj1, min1, ang1, &HFFFFFF00 '<<<<<<<<<<<<<<<<<<<<<<< Toolbox fill
  45.     _DISPLAY
  46.     cSleep 45
  47.  
  48.     pi = 0 'point index
  49.  
  50. 'thanks STxAxTIC from Toolbox
  51. SUB EllipseTilt (CX, CY, a, b, ang, C AS _UNSIGNED LONG)
  52.     DIM k, i, j
  53.     '  CX = center x coordinate
  54.     '  CY = center y coordinate
  55.     '   a = semimajor axis  major radius
  56.     '   b = semiminor axis  minor radius
  57.     ' ang = clockwise orientation of semimajor axis in radians (0 default)
  58.     '   C = fill color
  59.     FOR k = 0 TO 6.283185307179586 + .025 STEP .025
  60.         i = a * COS(k) * COS(ang) + b * SIN(k) * SIN(ang)
  61.         j = -a * COS(k) * SIN(ang) + b * SIN(k) * COS(ang)
  62.         i = i + CX
  63.         j = -j + CY
  64.         IF k <> 0 THEN
  65.             LINE -(i, j), C
  66.         ELSE
  67.             PSET (i, j), C
  68.         END IF
  69.     NEXT
  70.  
  71. 'relace broken toolbax code
  72. 'this needs RotoZoom3 to rotate image BUT it can now scale it also!
  73. SUB fTiltEllipse (destH AS LONG, ox AS INTEGER, oy AS INTEGER, majorRadius AS INTEGER, minorRadius AS INTEGER, radianAngle AS SINGLE, c AS _UNSIGNED LONG)
  74.     'setup isolated area, draw fFlatEllipse and then RotoZoom the image into destination
  75.     'ox, oy is center of ellipse
  76.     'majorRadius is 1/2 the lonest axis
  77.     'minorRadius is 1/2 the short axis
  78.     'radianAngle is the Radian Angle of Tilt
  79.     'c is of course color
  80.     sd& = _DEST
  81.     temp& = _NEWIMAGE(2 * majorRadius, 2 * minorRadius, 32)
  82.     _DEST temp&
  83.     fEllipse majorRadius, minorRadius, majorRadius, minorRadius, c
  84.     _DEST destH
  85.     RotoZoom3 ox, oy, temp&, 1, 1, radianAngle
  86.     _FREEIMAGE temp&
  87.     _DEST sd&
  88.  
  89. 'modified 2019-12-15 _seamless added, rotation convert to radians
  90. SUB RotoZoom3 (X AS LONG, Y AS LONG, Image AS LONG, xScale AS SINGLE, yScale AS SINGLE, radianRotation AS SINGLE) ' 0 at end means no scaling of x or y
  91.     DIM px(3) AS SINGLE: DIM py(3) AS SINGLE
  92.     W& = _WIDTH(Image&): H& = _HEIGHT(Image&)
  93.     px(0) = -W& / 2: py(0) = -H& / 2: px(1) = -W& / 2: py(1) = H& / 2
  94.     px(2) = W& / 2: py(2) = H& / 2: px(3) = W& / 2: py(3) = -H& / 2
  95.     sinr! = SIN(-radianRotation): cosr! = COS(-radianRotation)
  96.     FOR i& = 0 TO 3
  97.         x2& = (px(i&) * cosr! + sinr! * py(i&)) + X * xScale: y2& = (py(i&) * cosr! - px(i&) * sinr!) + Y * yScale
  98.         px(i&) = x2&: py(i&) = y2&
  99.     NEXT
  100.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, H& - 1)-(W& - 1, H& - 1), Image& TO(px(0), py(0))-(px(1), py(1))-(px(2), py(2))
  101.     _MAPTRIANGLE _SEAMLESS(0, 0)-(W& - 1, 0)-(W& - 1, H& - 1), Image& TO(px(0), py(0))-(px(3), py(3))-(px(2), py(2))
  102.  
  103. 'this seems to work as well as any
  104. SUB fEllipse (CX AS LONG, CY AS LONG, xRadius AS LONG, yRadius AS LONG, c AS _UNSIGNED LONG)
  105.     DIM scale AS SINGLE, x AS LONG, y AS LONG
  106.     scale = yRadius / xRadius
  107.     LINE (CX, CY - yRadius)-(CX, CY + yRadius), c, BF
  108.     FOR x = 1 TO xRadius
  109.         y = scale * SQR(xRadius * xRadius - x * x)
  110.         LINE (CX + x, CY - y)-(CX + x, CY + y), c, BF
  111.         LINE (CX - x, CY - y)-(CX - x, CY + y), c, BF
  112.     NEXT
  113.  
  114. ' found at [abandoned, outdated and now likely malicious qb64 dot net website - don’t go there]:    http://www.[abandoned, outdated and now likely malicious qb64 dot net website - don’t go there]/forum/index.php?topic=14425.0
  115. SUB ftri (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  116.     DIM D AS LONG
  117.     D = _DEST
  118.     a& = _NEWIMAGE(1, 1, 32)
  119.     _DEST a&
  120.     PSET (0, 0), K
  121.     _DEST D
  122.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  123.     _FREEIMAGE a& '<<< this is important!
  124.  
  125. '2019-11-20 Steve saves some time with STATIC and saves and restores last dest
  126. SUB ftri1 (x1, y1, x2, y2, x3, y3, K AS _UNSIGNED LONG)
  127.     DIM D AS LONG
  128.     STATIC a&
  129.     D = _DEST
  130.     IF a& = 0 THEN a& = _NEWIMAGE(1, 1, 32)
  131.     _DEST a&
  132.     PSET (0, 0), K
  133.     _DEST D
  134.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, 0)-(0, 0), a& TO(x1, y1)-(x2, y2)-(x3, y3)
  135.  
  136. 'need 4 non linear points (not all on 1 line) list them clockwise so x2, y2 is opposite of x4, y4
  137. SUB fquad (x1, y1, x2, y2, x3, y3, x4, y4, K AS _UNSIGNED LONG)
  138.     ftri x1, y1, x2, y2, x4, y4, K
  139.     ftri x3, y3, x2, y2, x4, y4, K
  140.  
  141. SUB cSleep (secsWait AS DOUBLE) 'wait for keypress or mouseclick, solves midnight problem nicely I think
  142.     DIM wayt AS INTEGER, oldMouse AS INTEGER, k AS LONG, startTime AS DOUBLE
  143.  
  144.     startTime = TIMER
  145.     wayt = 1
  146.     _KEYCLEAR
  147.     WHILE wayt
  148.         WHILE _MOUSEINPUT: WEND
  149.         IF _MOUSEBUTTON(1) AND oldMouse = 0 THEN wayt = 0
  150.         oldMouse = _MOUSEBUTTON(1) ' <<< this is Steve's cool way to get clear of mouse click
  151.         k = _KEYHIT: IF k > 0 THEN _KEYCLEAR: wayt = 0
  152.         IF TIMER - startTime < 0 THEN 'past midnight
  153.             IF TIMER + 24 * 60 * 60 - startTime > secsWait THEN wayt = 0
  154.         ELSE
  155.             IF TIMER - startTime >= secsWait THEN wayt = 0
  156.         END IF
  157.         _LIMIT 30
  158.     WEND
  159.  
  160. SUB TiltedEllipseFill (destHandle&, x0, y0, a, b, ang, c AS _UNSIGNED LONG)
  161.     DIM max AS INTEGER, mx2 AS INTEGER, i AS INTEGER, j AS INTEGER, lasti, lastj
  162.     DIM prc AS _UNSIGNED LONG, tef&, k
  163.     prc = _RGB32(255, 255, 255, 255)
  164.     IF a > b THEN max = a + 1 ELSE max = b + 1
  165.     mx2 = max + max
  166.     tef& = _NEWIMAGE(mx2, mx2)
  167.     _DEST tef&
  168.     _SOURCE tef& 'point wont read without this!
  169.     FOR k = 0 TO 6.2832 + .05 STEP .1
  170.         i = max + a * COS(k) * COS(ang) + b * SIN(k) * SIN(ang)
  171.         j = max + a * COS(k) * SIN(ang) - b * SIN(k) * COS(ang)
  172.         IF k <> 0 THEN
  173.             LINE (lasti, lastj)-(i, j), prc
  174.         ELSE
  175.             PSET (i, j), prc
  176.         END IF
  177.         lasti = i: lastj = j
  178.     NEXT
  179.     DIM xleft(mx2) AS INTEGER, xright(mx2) AS INTEGER, x AS INTEGER, y AS INTEGER
  180.     FOR y = 0 TO mx2
  181.         x = 0
  182.         WHILE POINT(x, y) <> prc AND x < mx2
  183.             x = x + 1
  184.         WEND
  185.         xleft(y) = x
  186.         WHILE POINT(x, y) = prc AND x < mx2
  187.             x = x + 1
  188.         WEND
  189.         WHILE POINT(x, y) <> prc AND x < mx2
  190.             x = x + 1
  191.         WEND
  192.         IF x = mx2 THEN xright(y) = xleft(y) ELSE xright(y) = x
  193.     NEXT
  194.     _DEST destHandle&
  195.     FOR y = 0 TO mx2
  196.         IF xleft(y) <> mx2 THEN LINE (xleft(y) + x0 - max, y + y0 - max)-(xright(y) + x0 - max, y + y0 - max), c, BF
  197.     NEXT
  198.     _FREEIMAGE tef&
  199.  
  200.  
  201.  

Why such radically different results?
« Last Edit: December 15, 2019, 09:20:26 pm by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Too different Tilt Ellipse fills
« Reply #1 on: December 16, 2019, 04:50:53 pm »
OK the _DONTBLEND / _BLEND trick worked to fix my stinky fTiltEllipse in the first code app so both versions work equally well in display quality. Not even sure I need _BLEND in that sub since I throw away the handle for a different size ellipse if needed.
Code: QB64: [Select]
  1. _TITLE "Tilted Ellipse app" ' B+ 2019-02-12  add fTiltEllipse routine for comparison
  2.  
  3. CONST xmx = 640
  4. CONST ymx = 640
  5. SCREEN _NEWIMAGE(xmx, ymx, 32)
  6. _SCREENMOVE 340, 40
  7. DIM k AS _UNSIGNED LONG, c, r, stepper, offset, a, x, y, start!
  8. c = xmx / 2
  9. start! = TIMER(.001)
  10. FOR r = 210 TO 0 STEP -30
  11.     stepper = stepper + 30
  12.     offset = offset - _PI(2 / 24)
  13.     FOR a = 0 TO 2 * _PI - .001 STEP _PI(2 / 12)
  14.         x = c + r * COS(a + offset)
  15.         y = c + r * SIN(a + offset)
  16.         k = _RGBA32(0, 0, 200, 15)
  17.         TiltedEllipseFill 0, x, y, 250 - stepper, stepper, a + offset, k
  18.         'fTiltEllipse 0, x, y, 250 - stepper, stepper, a + offset, k
  19.         '_LIMIT 12
  20.     NEXT
  21. PRINT INT((TIMER(.001) - start!) * 100) / 100; "secs"
  22.  
  23. SUB TiltedEllipseFill (destHandle&, x0, y0, a, b, ang, c AS _UNSIGNED LONG)
  24.     DIM max AS INTEGER, mx2 AS INTEGER, i AS INTEGER, j AS INTEGER, lasti, lastj
  25.     DIM prc AS _UNSIGNED LONG, tef&, k
  26.     prc = _RGB32(255, 255, 255, 255)
  27.     IF a > b THEN max = a + 1 ELSE max = b + 1
  28.     mx2 = max + max
  29.     tef& = _NEWIMAGE(mx2, mx2)
  30.     _DEST tef&
  31.     _SOURCE tef& 'point wont read without this!
  32.     FOR k = 0 TO 6.2832 + .05 STEP .1
  33.         i = max + a * COS(k) * COS(ang) + b * SIN(k) * SIN(ang)
  34.         j = max + a * COS(k) * SIN(ang) - b * SIN(k) * COS(ang)
  35.         IF k <> 0 THEN
  36.             LINE (lasti, lastj)-(i, j), prc
  37.         ELSE
  38.             PSET (i, j), prc
  39.         END IF
  40.         lasti = i: lastj = j
  41.     NEXT
  42.     DIM xleft(mx2) AS INTEGER, xright(mx2) AS INTEGER, x AS INTEGER, y AS INTEGER
  43.     FOR y = 0 TO mx2
  44.         x = 0
  45.         WHILE POINT(x, y) <> prc AND x < mx2
  46.             x = x + 1
  47.         WEND
  48.         xleft(y) = x
  49.         WHILE POINT(x, y) = prc AND x < mx2
  50.             x = x + 1
  51.         WEND
  52.         WHILE POINT(x, y) <> prc AND x < mx2
  53.             x = x + 1
  54.         WEND
  55.         IF x = mx2 THEN xright(y) = xleft(y) ELSE xright(y) = x
  56.     NEXT
  57.     _DEST destHandle&
  58.     FOR y = 0 TO mx2
  59.         IF xleft(y) <> mx2 THEN LINE (xleft(y) + x0 - max, y + y0 - max)-(xright(y) + x0 - max, y + y0 - max), c, BF
  60.     NEXT
  61.     _FREEIMAGE tef&
  62.  
  63.  
  64. 'relace broken toolbox code
  65. 'this needs RotoZoom3 to rotate image and fEllipse to make an image BUT it can now scale it also!
  66. SUB fTiltEllipse (destH AS LONG, ox AS INTEGER, oy AS INTEGER, majorRadius AS INTEGER, minorRadius AS INTEGER, radianAngle AS SINGLE, c AS _UNSIGNED LONG)
  67.     'setup isolated area, draw fFlatEllipse and then RotoZoom the image into destination
  68.     'ox, oy is center of ellipse
  69.     'majorRadius is 1/2 the lonest axis
  70.     'minorRadius is 1/2 the short axis
  71.     'radianAngle is the Radian Angle of Tilt
  72.     'c is of course color
  73.     DIM sd&, temp&
  74.     sd& = _DEST
  75.     temp& = _NEWIMAGE(2 * majorRadius, 2 * minorRadius, 32)
  76.     _DEST temp&
  77.     _DONTBLEND temp& '<< test 12-16
  78.     fEllipse majorRadius, minorRadius, majorRadius, minorRadius, c
  79.     _BLEND temp& '<< test 12-16
  80.     _DEST destH
  81.     RotoZoom3 ox, oy, temp&, 1, 1, radianAngle
  82.     _FREEIMAGE temp&
  83.     _DEST sd&
  84.  
  85. 'modified 2019-12-15 _seamless added, rotation convert to radians
  86. SUB RotoZoom3 (X AS LONG, Y AS LONG, Image AS LONG, xScale AS SINGLE, yScale AS SINGLE, radianRotation AS SINGLE) ' 0 at end means no scaling of x or y
  87.     DIM px(3) AS SINGLE: DIM py(3) AS SINGLE
  88.     DIM W&, H&, sinr!, cosr!, i&, x2&, y2&
  89.     W& = _WIDTH(Image&): H& = _HEIGHT(Image&)
  90.     px(0) = -W& / 2: py(0) = -H& / 2: px(1) = -W& / 2: py(1) = H& / 2
  91.     px(2) = W& / 2: py(2) = H& / 2: px(3) = W& / 2: py(3) = -H& / 2
  92.     sinr! = SIN(-radianRotation): cosr! = COS(-radianRotation)
  93.     FOR i& = 0 TO 3
  94.         x2& = (px(i&) * cosr! + sinr! * py(i&)) + X * xScale: y2& = (py(i&) * cosr! - px(i&) * sinr!) + Y * yScale
  95.         px(i&) = x2&: py(i&) = y2&
  96.     NEXT
  97.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, H& - 1)-(W& - 1, H& - 1), Image& TO(px(0), py(0))-(px(1), py(1))-(px(2), py(2))
  98.     _MAPTRIANGLE _SEAMLESS(0, 0)-(W& - 1, 0)-(W& - 1, H& - 1), Image& TO(px(0), py(0))-(px(3), py(3))-(px(2), py(2))
  99.  
  100. 'this seems to work as well as any
  101. SUB fEllipse (CX AS LONG, CY AS LONG, xRadius AS LONG, yRadius AS LONG, c AS _UNSIGNED LONG)
  102.     DIM scale AS SINGLE, x AS LONG, y AS LONG
  103.     scale = yRadius / xRadius
  104.     LINE (CX, CY - yRadius)-(CX, CY + yRadius), c, BF
  105.     FOR x = 1 TO xRadius
  106.         y = scale * SQR(xRadius * xRadius - x * x)
  107.         LINE (CX + x, CY - y)-(CX + x, CY + y), c, BF
  108.         LINE (CX - x, CY - y)-(CX - x, CY + y), c, BF
  109.     NEXT
  110.  
  111.  
  112.  

Oh hell yeah! I need the _BLEND also  LOL

Update: fTiltEllipse is about 3 times faster and has the same or less code lines including 2 subs you can use for other things.
« Last Edit: December 16, 2019, 06:35:44 pm by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Too different Tilt Ellipse fills
« Reply #2 on: December 16, 2019, 07:17:10 pm »
Turns out Toolbox code wasn't broken so much as it just needed it's parameter types declared:
Code: QB64: [Select]
  1. 'fixed 2019-12-16 B+
  2. SUB TiltedEllipseFill (destHandle&, x0 AS INTEGER, y0 AS INTEGER, a AS SINGLE, b AS SINGLE, ang AS SINGLE, c AS _UNSIGNED LONG)
  3.     DIM max AS INTEGER, mx2 AS INTEGER, i AS INTEGER, j AS INTEGER, lasti AS INTEGER, lastj AS INTEGER
  4.     DIM prc AS _UNSIGNED LONG, tef&, k AS SINGLE, x AS INTEGER, y AS INTEGER
  5.     prc = _RGB32(255, 255, 255, 255)
  6.     IF a > b THEN max = a + 1 ELSE max = b + 1
  7.     mx2 = max + max
  8.     DIM xleft(mx2) AS INTEGER, xright(mx2) AS INTEGER
  9.     tef& = _NEWIMAGE(mx2, mx2)
  10.     _DEST tef&
  11.     _SOURCE tef& 'point wont read without this!
  12.     FOR k = 0 TO 6.2832 + .05 STEP .05
  13.         i = max + a * COS(k) * COS(ang) + b * SIN(k) * SIN(ang)
  14.         j = max + a * COS(k) * SIN(ang) - b * SIN(k) * COS(ang)
  15.         IF k <> 0 THEN
  16.             LINE (lasti, lastj)-(i, j), prc
  17.         ELSE
  18.             PSET (i, j), prc
  19.         END IF
  20.         lasti = i: lastj = j
  21.     NEXT
  22.     FOR y = 0 TO mx2
  23.         x = 0
  24.         WHILE POINT(x, y) <> prc AND x < mx2
  25.             x = x + 1
  26.         WEND
  27.         xleft(y) = x
  28.         WHILE POINT(x, y) = prc AND x < mx2
  29.             x = x + 1
  30.         WEND
  31.         WHILE POINT(x, y) <> prc AND x < mx2
  32.             x = x + 1
  33.         WEND
  34.         IF x = mx2 THEN xright(y) = xleft(y) ELSE xright(y) = x
  35.     NEXT
  36.     _DEST destHandle&
  37.     FOR y = 0 TO mx2
  38.         IF xleft(y) <> mx2 THEN LINE (xleft(y) + x0 - max, y + y0 - max)-(xright(y) + x0 - max, y + y0 - max), c, BF
  39.     NEXT
  40.     _FREEIMAGE tef&
  41.  

Unfortunately it didn't speed up the code all that much, but overall our fortunes have been improved because if it weren't for sloppy declares of parameters would never have found code that does the same thing 3 times faster, the error I had in fTri since it's inception, the fix for cSleep or Steve's Pause, the improvement in RotoZoom3 and what Steve and all who paid attention found about _DONTBLEND.

How Blunderfull. ;-))
« Last Edit: December 16, 2019, 07:19:55 pm by bplus »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Too different Tilt Ellipse fills
« Reply #3 on: December 16, 2019, 08:45:41 pm »
I just tracked down the big discussion of Ellipse Fills
https://www.qb64.org/forum/index.php?topic=1044.0

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Too different Tilt Ellipse fills
« Reply #4 on: December 16, 2019, 09:47:20 pm »
(In case it wasn't super obvious, that thread is linked at the top of the Toolbox header for the filled ellipse page.)
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: Too different Tilt Ellipse fills
« Reply #5 on: December 16, 2019, 09:58:38 pm »
(In case it wasn't super obvious, that thread is linked at the top of the Toolbox header for the filled ellipse page.)

Yikes! another great reading job by bplus...

OK so just skimmed through 11 pages of ... oh boy more reading...

Anyway, I tried the other code for a Flat EllipseFill and shaved a couple .01's of a second off the time on average for this nice little app for testing TiltedEllipseFills versus fTiltEllipse so now maybe fTiltEllipse is 3-4 times faster than what we came up with in Feb, 2019.
Code: QB64: [Select]
  1. _TITLE "Tilted Ellipse app" ' B+ 2019-02-12  add fTiltEllipse routine for comparison 2019-12-16 plus added
  2. '2 Flat Ellipse Fill routines for the new fTiltEllipse routine looking to be almost 4 times faster now.
  3.  
  4. CONST xmx = 640
  5. CONST ymx = 640
  6. SCREEN _NEWIMAGE(xmx, ymx, 32)
  7. _SCREENMOVE 340, 40
  8. DIM k AS _UNSIGNED LONG, c, r, stepper, offset, a, x, y, start!
  9. c = xmx / 2
  10. start! = TIMER(.001)
  11. FOR r = 210 TO 0 STEP -30
  12.     stepper = stepper + 30
  13.     offset = offset - _PI(2 / 24)
  14.     FOR a = 0 TO 2 * _PI - .001 STEP _PI(2 / 12)
  15.         x = c + r * COS(a + offset)
  16.         y = c + r * SIN(a + offset)
  17.         k = _RGBA32(0, 0, 200, 15)
  18.         'TiltedEllipseFill 0, x, y, 250 - stepper, stepper, a + offset, k
  19.         fTiltEllipse 0, x, y, 250 - stepper, stepper, a + offset, k
  20.         '_LIMIT 12
  21.     NEXT
  22. PRINT INT((TIMER(.001) - start!) * 100) / 100; "secs"
  23.  
  24. 'fixed Toolbox code
  25. SUB TiltedEllipseFill (destHandle&, x0 AS INTEGER, y0 AS INTEGER, a AS SINGLE, b AS SINGLE, ang AS SINGLE, c AS _UNSIGNED LONG)
  26.     DIM max AS INTEGER, mx2 AS INTEGER, i AS INTEGER, j AS INTEGER, lasti AS INTEGER, lastj AS INTEGER
  27.     DIM prc AS _UNSIGNED LONG, tef&, k AS SINGLE, x AS INTEGER, y AS INTEGER
  28.     prc = _RGB32(255, 255, 255, 255)
  29.     IF a > b THEN max = a + 1 ELSE max = b + 1
  30.     mx2 = max + max
  31.     DIM xleft(mx2) AS INTEGER, xright(mx2) AS INTEGER
  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 .05
  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.     FOR y = 0 TO mx2
  46.         x = 0
  47.         WHILE POINT(x, y) <> prc AND x < mx2
  48.             x = x + 1
  49.         WEND
  50.         xleft(y) = x
  51.         WHILE POINT(x, y) = prc AND x < mx2
  52.             x = x + 1
  53.         WEND
  54.         WHILE POINT(x, y) <> prc AND x < mx2
  55.             x = x + 1
  56.         WEND
  57.         IF x = mx2 THEN xright(y) = xleft(y) ELSE xright(y) = x
  58.     NEXT
  59.     _DEST destHandle&
  60.     FOR y = 0 TO mx2
  61.         IF xleft(y) <> mx2 THEN LINE (xleft(y) + x0 - max, y + y0 - max)-(xright(y) + x0 - max, y + y0 - max), c, BF
  62.     NEXT
  63.     _FREEIMAGE tef&
  64.  
  65. 'relace broken toolbox code
  66. 'this needs RotoZoom3 to rotate image and fEllipse to make th eimage BUT it can now scale it also!
  67. SUB fTiltEllipse (destH AS LONG, ox AS INTEGER, oy AS INTEGER, majorRadius AS INTEGER, minorRadius AS INTEGER, radianAngle AS SINGLE, c AS _UNSIGNED LONG)
  68.     'setup isolated area, draw fFlatEllipse and then RotoZoom the image into destination
  69.     'ox, oy is center of ellipse
  70.     'majorRadius is 1/2 the lonest axis
  71.     'minorRadius is 1/2 the short axis
  72.     'radianAngle is the Radian Angle of Tilt
  73.     'c is of course color
  74.     DIM sd&, temp&
  75.     sd& = _DEST
  76.     temp& = _NEWIMAGE(2 * majorRadius, 2 * minorRadius, 32)
  77.     _DEST temp&
  78.     _DONTBLEND temp& '<< test 12-16
  79.     'fEllipse majorRadius, minorRadius, majorRadius, minorRadius, c
  80.     EllipseFill majorRadius, minorRadius, majorRadius, minorRadius, c
  81.     _BLEND temp& '<< test 12-16
  82.     _DEST destH
  83.     RotoZoom3 ox, oy, temp&, 1, 1, radianAngle
  84.     _FREEIMAGE temp&
  85.     _DEST sd&
  86.  
  87. 'modified 2019-12-15 _seamless added, rotation convert to radians
  88. SUB RotoZoom3 (X AS LONG, Y AS LONG, Image AS LONG, xScale AS SINGLE, yScale AS SINGLE, radianRotation AS SINGLE) ' 0 at end means no scaling of x or y
  89.     DIM px(3) AS SINGLE: DIM py(3) AS SINGLE
  90.     DIM W&, H&, sinr!, cosr!, i&, x2&, y2&
  91.     W& = _WIDTH(Image&): H& = _HEIGHT(Image&)
  92.     px(0) = -W& / 2: py(0) = -H& / 2: px(1) = -W& / 2: py(1) = H& / 2
  93.     px(2) = W& / 2: py(2) = H& / 2: px(3) = W& / 2: py(3) = -H& / 2
  94.     sinr! = SIN(-radianRotation): cosr! = COS(-radianRotation)
  95.     FOR i& = 0 TO 3
  96.         x2& = (px(i&) * cosr! + sinr! * py(i&)) + X * xScale: y2& = (py(i&) * cosr! - px(i&) * sinr!) + Y * yScale
  97.         px(i&) = x2&: py(i&) = y2&
  98.     NEXT
  99.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, H& - 1)-(W& - 1, H& - 1), Image& TO(px(0), py(0))-(px(1), py(1))-(px(2), py(2))
  100.     _MAPTRIANGLE _SEAMLESS(0, 0)-(W& - 1, 0)-(W& - 1, H& - 1), Image& TO(px(0), py(0))-(px(3), py(3))-(px(2), py(2))
  101.  
  102. 'this seems to work as well as any
  103. SUB fEllipse (CX AS LONG, CY AS LONG, xRadius AS LONG, yRadius AS LONG, c AS _UNSIGNED LONG)
  104.     DIM scale AS SINGLE, x AS LONG, y AS LONG
  105.     scale = yRadius / xRadius
  106.     LINE (CX, CY - yRadius)-(CX, CY + yRadius), c, BF
  107.     FOR x = 1 TO xRadius
  108.         y = scale * SQR(xRadius * xRadius - x * x)
  109.         LINE (CX + x, CY - y)-(CX + x, CY + y), c, BF
  110.         LINE (CX - x, CY - y)-(CX - x, CY + y), c, BF
  111.     NEXT
  112.  
  113. SUB EllipseFill (CX AS INTEGER, CY AS INTEGER, a AS INTEGER, b AS INTEGER, C AS _UNSIGNED LONG)
  114.     ' CX = center x coordinate
  115.     ' CY = center y coordinate
  116.     '  a = semimajor axis
  117.     '  b = semiminor axis
  118.     '  C = fill color
  119.     IF a = 0 OR b = 0 THEN EXIT SUB
  120.     DIM h2 AS _INTEGER64
  121.     DIM w2 AS _INTEGER64
  122.     DIM h2w2 AS _INTEGER64
  123.     DIM x AS INTEGER
  124.     DIM y AS INTEGER
  125.     w2 = a * a
  126.     h2 = b * b
  127.     h2w2 = h2 * w2
  128.     LINE (CX - a, CY)-(CX + a, CY), C, BF
  129.     DO WHILE y < b
  130.         y = y + 1
  131.         x = SQR((h2w2 - y * y * w2) \ h2)
  132.         LINE (CX - x, CY + y)-(CX + x, CY + y), C, BF
  133.         LINE (CX - x, CY - y)-(CX + x, CY - y), C, BF
  134.     LOOP
  135.  

We put maybe the most people and time getting that last EllipseFill listed here worked out, should of used it to begin with.
« Last Edit: December 16, 2019, 10:16:24 pm by bplus »