QB64.org Forum

Active Forums => Programs => Topic started by: FellippeHeitor on October 09, 2018, 04:28:14 am

Title: Lissajous Curve Table
Post by: FellippeHeitor on October 09, 2018, 04:28:14 am
Adapted from https://editor.p5js.org/codingtrain/sketches/BJbj5l3Y7 (https://editor.p5js.org/codingtrain/sketches/BJbj5l3Y7) (as seen on YouTube: https://www.youtube.com/watch?v=--6eyLO78CY (https://www.youtube.com/watch?v=--6eyLO78CY))

Window is resizable to display more patterns.

Code: QB64: [Select]
  1. _TITLE "Lissajous Curve Table"
  2.  
  3.  
  4. TYPE vector
  5.     x AS SINGLE
  6.     y AS SINGLE
  7.  
  8. DIM SHARED angle
  9. DIM SHARED rows, cols
  10.  
  11. SCREEN _NEWIMAGE(800, 800, 32)
  12.  
  13. setup:
  14. angle = 0
  15. w = 80
  16. rows = INT(_HEIGHT / w) - 1
  17. cols = INT(_WIDTH / w) - 1
  18. REDIM dot(rows, cols) AS vector
  19.  
  20. plot = _NEWIMAGE(_WIDTH, _HEIGHT, 32)
  21. _DEST plot
  22.  
  23.         oldScreen = _DEST
  24.         _FREEIMAGE oldScreen
  25.         _FREEIMAGE plot
  26.         GOTO setup
  27.     END IF
  28.  
  29.     _PUTIMAGE , plot
  30.  
  31.     d = w - 0.2 * w
  32.     r = d / 2
  33.  
  34.     FOR i = 0 TO cols
  35.         cx = w + i * w + w / 2
  36.         cy = w / 2
  37.         CIRCLE (cx, cy), r
  38.  
  39.         x = r * COS(angle * (i + 1) - _PI(.5))
  40.         y = r * SIN(angle * (i + 1) - _PI(.5))
  41.  
  42.         LINE (cx + x, 0)-(cx + x, _HEIGHT), _RGB32(127, 127, 127)
  43.         CircleFill cx + x, cy + y, 4, _RGB32(28, 222, 50)
  44.         CircleFill cx + x, cy + y, 2, _RGB32(11, 33, 249)
  45.  
  46.         FOR j = 0 TO rows
  47.             dot(j, i).x = cx + x
  48.         NEXT
  49.     NEXT
  50.  
  51.     FOR i = 0 TO rows
  52.         cx = w / 2
  53.         cy = w + i * w + w / 2
  54.         CIRCLE (cx, cy), r
  55.  
  56.         x = r * COS(angle * (i + 1) - _PI(.5))
  57.         y = r * SIN(angle * (i + 1) - _PI(.5))
  58.  
  59.         LINE (0, cy + y)-(_WIDTH, cy + y), _RGB32(127, 127, 127)
  60.         CircleFill cx + x, cy + y, 4, _RGB32(28, 222, 50)
  61.         CircleFill cx + x, cy + y, 2, _RGB32(11, 33, 249)
  62.  
  63.         FOR j = 0 TO cols
  64.             dot(i, j).y = cy + y
  65.         NEXT
  66.     NEXT
  67.  
  68.     _DEST plot
  69.     LINE (0, 0)-(_WIDTH, _HEIGHT), _RGBA32(0, 0, 0, 2), BF
  70.     FOR j = 0 TO rows
  71.         FOR i = 0 TO cols
  72.             CircleFill dot(j, i).x, dot(j, i).y, 1, _RGB32(255, 0, 0)
  73.         NEXT
  74.     NEXT
  75.  
  76.     angle = angle + 0.01
  77.     IF angle > _PI(2) THEN angle = 0
  78.  
  79.     _DEST 0
  80.  
  81.     _DISPLAY
  82.     _LIMIT 30
  83.  
  84. SUB CircleFill (x AS LONG, y AS LONG, R AS LONG, C AS _UNSIGNED LONG)
  85.     DIM x0 AS SINGLE, y0 AS SINGLE
  86.     DIM e AS SINGLE
  87.  
  88.     x0 = R
  89.     y0 = 0
  90.     e = -R
  91.     DO WHILE y0 < x0
  92.         IF e <= 0 THEN
  93.             y0 = y0 + 1
  94.             LINE (x - x0, y + y0)-(x + x0, y + y0), C, BF
  95.             LINE (x - x0, y - y0)-(x + x0, y - y0), C, BF
  96.             e = e + 2 * y0
  97.         ELSE
  98.             LINE (x - y0, y - x0)-(x + y0, y - x0), C, BF
  99.             LINE (x - y0, y + x0)-(x + y0, y + x0), C, BF
  100.             x0 = x0 - 1
  101.             e = e - 2 * x0
  102.         END IF
  103.     LOOP
  104.     LINE (x - R, y)-(x + R, y), C, BF
  105.  

Title: Re: Lissajous Curve Table
Post by: STxAxTIC on October 09, 2018, 08:27:00 am
Why code them when you can make them?

Stretch a balloon or rubber piece over a drinking glass, tight as a drum. Mount a tiny mirror or piece of foil in the center, roughly 1cm^2. Next mount a laser pointer a few feet away, and aim carefully so the beam hits the mirror when the system is at rest. Observe the stationary dot on a wall or screen that is reflected from the mirror. When you play sound into the glass or vibrate the table, the reflected dot will produce those curves, depending on the energy added. Some of the modes are hard to capture...

Yeah on second thought, just code it. Looks beautiful as ever Fellippe!
Title: Re: Lissajous Curve Table
Post by: bplus on October 09, 2018, 08:28:30 am
This is best demo of Lissajous I've ever seen!
Title: Re: Lissajous Curve Table
Post by: FellippeHeitor on October 09, 2018, 08:55:54 am
Thanks, guys! I take little credit (color choice, slow fade). Calculations were all done as stated.
Title: Re: Lissajous Curve Table
Post by: TerryRitchie on October 09, 2018, 12:21:39 pm
After studying the video and reading on-line I realize that I could use these curves for path making functions in my library.

Very interesting stuff. Thanks!
Title: Re: Lissajous Curve Table
Post by: FellippeHeitor on October 09, 2018, 12:27:13 pm
I remember Walter had a flying saucer demo in his forum that used Lissajous Curves for the path of the sprite as well. Sounds like a good idea.
Title: Re: Lissajous Curve Table
Post by: bplus on October 09, 2018, 12:48:08 pm
I used something like it for Air Hockey AI defender, talk about Ninja fingers! ;)
Title: Re: Lissajous Curve Table
Post by: Dav on October 09, 2018, 12:57:25 pm
Nice coding, Fellippe!

- Dav
Title: Re: Lissajous Curve Table
Post by: FellippeHeitor on October 09, 2018, 02:48:07 pm
Thanks, Dav!

For added eye-candy-ness, I've changed the plot line to paint using HSB colors (functions borrowed from p5js.bas (https://github.com/FellippeHeitor/p5js.bas)) so that ink color will vary according to the current rotational angle.

Code: QB64: [Select]
  1. _TITLE "Lissajous Curve Table"
  2.  
  3.  
  4. TYPE vector
  5.     x AS SINGLE
  6.     y AS SINGLE
  7.  
  8. DIM SHARED angle
  9. DIM SHARED rows, cols
  10.  
  11. SCREEN _NEWIMAGE(800, 800, 32)
  12.  
  13. setup:
  14. angle = 0
  15. w = 80
  16. rows = INT(_HEIGHT / w) - 1
  17. cols = INT(_WIDTH / w) - 1
  18. REDIM dot(rows, cols) AS vector
  19.  
  20. plot = _NEWIMAGE(_WIDTH, _HEIGHT, 32)
  21. _DEST plot
  22.  
  23.         oldScreen = _DEST
  24.         _FREEIMAGE oldScreen
  25.         _FREEIMAGE plot
  26.         GOTO setup
  27.     END IF
  28.  
  29.     _PUTIMAGE , plot
  30.  
  31.     d = w - 0.2 * w
  32.     r = d / 2
  33.  
  34.     FOR i = 0 TO cols
  35.         cx = w + i * w + w / 2
  36.         cy = w / 2
  37.         CIRCLE (cx, cy), r
  38.  
  39.         x = r * COS(angle * (i + 1) - _PI(.5))
  40.         y = r * SIN(angle * (i + 1) - _PI(.5))
  41.  
  42.         LINE (cx + x, 0)-(cx + x, _HEIGHT), _RGB32(127, 127, 127)
  43.         CircleFill cx + x, cy + y, 4, _RGB32(28, 222, 50)
  44.         CircleFill cx + x, cy + y, 2, _RGB32(11, 33, 249)
  45.  
  46.         FOR j = 0 TO rows
  47.             dot(j, i).x = cx + x
  48.         NEXT
  49.     NEXT
  50.  
  51.     FOR i = 0 TO rows
  52.         cx = w / 2
  53.         cy = w + i * w + w / 2
  54.         CIRCLE (cx, cy), r
  55.  
  56.         x = r * COS(angle * (i + 1) - _PI(.5))
  57.         y = r * SIN(angle * (i + 1) - _PI(.5))
  58.  
  59.         LINE (0, cy + y)-(_WIDTH, cy + y), _RGB32(127, 127, 127)
  60.         CircleFill cx + x, cy + y, 4, _RGB32(28, 222, 50)
  61.         CircleFill cx + x, cy + y, 2, _RGB32(11, 33, 249)
  62.  
  63.         FOR j = 0 TO cols
  64.             dot(i, j).y = cy + y
  65.         NEXT
  66.     NEXT
  67.  
  68.     _DEST plot
  69.     LINE (0, 0)-(_WIDTH, _HEIGHT), _RGBA32(0, 0, 0, 4), BF
  70.     FOR j = 0 TO rows
  71.         FOR i = 0 TO cols
  72.             CircleFill dot(j, i).x, dot(j, i).y, 1, hsb(_R2D(angle), 127, 127, 255)
  73.         NEXT
  74.     NEXT
  75.  
  76.     angle = angle + 0.01
  77.     IF angle > _PI(2) THEN angle = 0
  78.  
  79.     _DEST 0
  80.  
  81.     _DISPLAY
  82.     _LIMIT 30
  83.  
  84. SUB CircleFill (x AS LONG, y AS LONG, R AS LONG, C AS _UNSIGNED LONG)
  85.     DIM x0 AS SINGLE, y0 AS SINGLE
  86.     DIM e AS SINGLE
  87.  
  88.     x0 = R
  89.     y0 = 0
  90.     e = -R
  91.     DO WHILE y0 < x0
  92.         IF e <= 0 THEN
  93.             y0 = y0 + 1
  94.             LINE (x - x0, y + y0)-(x + x0, y + y0), C, BF
  95.             LINE (x - x0, y - y0)-(x + x0, y - y0), C, BF
  96.             e = e + 2 * y0
  97.         ELSE
  98.             LINE (x - y0, y - x0)-(x + y0, y - x0), C, BF
  99.             LINE (x - y0, y + x0)-(x + y0, y + x0), C, BF
  100.             x0 = x0 - 1
  101.             e = e - 2 * x0
  102.         END IF
  103.     LOOP
  104.     LINE (x - R, y)-(x + R, y), C, BF
  105.  
  106. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  107.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  108.  
  109. FUNCTION hsb~& (__H AS _FLOAT, __S AS _FLOAT, __B AS _FLOAT, A AS _FLOAT)
  110.     DIM H AS _FLOAT, S AS _FLOAT, B AS _FLOAT
  111.  
  112.     H = map(__H, 0, 255, 0, 360)
  113.     S = map(__S, 0, 255, 0, 1)
  114.     B = map(__B, 0, 255, 0, 1)
  115.  
  116.     IF S = 0 THEN
  117.         hsb~& = _RGBA32(B * 255, B * 255, B * 255, A)
  118.         EXIT FUNCTION
  119.     END IF
  120.  
  121.     DIM fmx AS _FLOAT, fmn AS _FLOAT
  122.     DIM fmd AS _FLOAT, iSextant AS INTEGER
  123.     DIM imx AS INTEGER, imd AS INTEGER, imn AS INTEGER
  124.  
  125.     IF B > .5 THEN
  126.         fmx = B - (B * S) + S
  127.         fmn = B + (B * S) - S
  128.     ELSE
  129.         fmx = B + (B * S)
  130.         fmn = B - (B * S)
  131.     END IF
  132.  
  133.     iSextant = INT(H / 60)
  134.  
  135.     IF H >= 300 THEN
  136.         H = H - 360
  137.     END IF
  138.  
  139.     H = H / 60
  140.     H = H - (2 * INT(((iSextant + 1) MOD 6) / 2))
  141.  
  142.     IF iSextant MOD 2 = 0 THEN
  143.         fmd = (H * (fmx - fmn)) + fmn
  144.     ELSE
  145.         fmd = fmn - (H * (fmx - fmn))
  146.     END IF
  147.  
  148.     imx = _ROUND(fmx * 255)
  149.     imd = _ROUND(fmd * 255)
  150.     imn = _ROUND(fmn * 255)
  151.  
  152.     SELECT CASE INT(iSextant)
  153.         CASE 1
  154.             hsb~& = _RGBA32(imd, imx, imn, A)
  155.         CASE 2
  156.             hsb~& = _RGBA32(imn, imx, imd, A)
  157.         CASE 3
  158.             hsb~& = _RGBA32(imn, imd, imx, A)
  159.         CASE 4
  160.             hsb~& = _RGBA32(imd, imn, imx, A)
  161.         CASE 5
  162.             hsb~& = _RGBA32(imx, imn, imd, A)
  163.         CASE ELSE
  164.             hsb~& = _RGBA32(imx, imd, imn, A)
  165.     END SELECT
  166.  

Title: Re: Lissajous Curve Table
Post by: STxAxTIC on October 09, 2018, 04:27:39 pm
Alright we've had our fun. Time for a splash of water: when it comes to applying this stuff to actual paths of motion for physical objects in other coding projects... by all means go ahead, but the motions will be inconsistent with whatever laws of physics the rest of the program uses, supposing you're using any. These kinds of curves typically appear when taking the plot or projection of some kind of harmonic system, or looking at a phase diagram. This means that no projectile, airplane, mosquito, or other flying, gliding, or floating thing will *actually* trace out paths like this. Springy stuff at best like my balloon-laser example from above. Just sayin.
Title: Re: Lissajous Curve Table
Post by: FellippeHeitor on October 09, 2018, 04:35:32 pm
I understand the technicalities may render anything seriously physics-intense useless, but it does look darn close.

I realize now my trash can with flies had similar paths in the end now that Lissajous is on the table: https://www.qb64.org/forum/index.php?action=dlattach;topic=255.0;attach=605 (https://www.qb64.org/forum/index.php?action=dlattach;topic=255.0;attach=605)
Title: Re: Lissajous Curve Table
Post by: STxAxTIC on October 09, 2018, 04:51:52 pm
Not that I'm nitpicking (I guess I am)... but "darn close" to what? The only physical Lissajous curves I've ever seen were made by devices contrived to produce them.
Title: Re: Lissajous Curve Table
Post by: FellippeHeitor on October 09, 2018, 05:01:01 pm
Looks like a fly, buzzes like a fly,... you know the drill. "Darn Close" as in the layman will look and say "oh, flies!".
Title: Re: Lissajous Curve Table
Post by: STxAxTIC on October 09, 2018, 07:03:59 pm
Ah, my bad buddy - didn't see the fly demo earlier. Incidentally, the projection (shadow) of spiral-ish things can make such a figure... So the shadow of a moth perpetually finding the streetlight is one "natural" example... basically...

EDIT: Ha, just noticed this too... So on the main *.org page, the icon for Samples is my 3D world in screen zero. It turns out that the 3d pink "snake" on the bottom-right, when animated and viewed from flat-on - is yet again a Lissajous curve. This begs an interesting question - are all Lissajous figures in 2d actually the projections of something else in 3d? Or just some....?
Title: Re: Lissajous Curve Table
Post by: codeguy on October 09, 2018, 10:43:17 pm
I liked this demo. It was actually fine without the _DELAY.
Here's a flight pattern for a drunken fly:
Code: QB64: [Select]
  1. demo& = _NEWIMAGE(1366, 768, 256)
  2. CONST Iterations = 8191
  3. SCREEN demo&
  4. pi! = 4 * ATN(1)
  5. r = 100
  6. time! = .001
  7. M& = 100
  8.     FOR k = 0 TO Iterations
  9.  
  10.         X = r * _WIDTH / 2 * COS(14 * pi! * k / Iterations) * (1 - (3 / 4) * (SIN(2 * pi! * k / Iterations)) ^ 4 - (1 / 4) * (COS(6 * pi! * k / Iterations)) ^ 3)
  11.  
  12.  
  13.         Y = r * _HEIGHT / 2 * SIN(14 * pi! * k / Iterations) * (1 - (3 / 4) * (SIN(2 * pi! * k / Iterations)) ^ 4 - (1 / 4) * (COS(6 * pi! * k / Iterations)) ^ 3)
  14.  
  15.  
  16.         r = M& * (1 / 120) + (1 / 18) * (SIN(6 * pi! * k / Iterations)) ^ 4 + (1 / 18) * (SIN(16 * pi! * k / Iterations)) ^ 4
  17.  
  18.         PSET (_WIDTH / 2 + r * X, _HEIGHT / 2 + r * Y), 255 * (k / Iterations)
  19.         _LIMIT Iterations / time!
  20.     NEXT
  21.     _DISPLAY
  22.     M& = M& - 1
  23. LOOP UNTIL M& < 1
  24.