QB64.org Forum

Active Forums => Programs => Topic started by: FellippeHeitor on September 27, 2020, 04:04:40 pm

Title: Pendula
Post by: FellippeHeitor on September 27, 2020, 04:04:40 pm
Pendula of varying mass, hanging by strings of varying lengths.

Inspired by watching this post on reddit (https://www.reddit.com/r/BetterEveryLoop/comments/j0sdgz/slightly_different_string_lengths_cause_patterns/?utm_source=share&utm_medium=ios_app&utm_name=iossmf).


Code: QB64: [Select]
  1.  
  2. SCREEN _NEWIMAGE(1000, 600, 32)
  3.  
  4. CONST maxPendulum = 15
  5. DIM theta(maxPendulum), accel(maxPendulum), speed(maxPendulum)
  6. DIM length(maxPendulum), mass(maxPendulum), c(maxPendulum) AS _UNSIGNED LONG
  7. DIM px, py, bx, by
  8. g = 9.81
  9. FOR i = 0 TO maxPendulum
  10.     theta(i) = _PI / 1.5
  11.     speed(i) = 0
  12.     length(i) = 100 + i * 30
  13.     mass(i) = 1 - i * .01
  14.     c(i) = _RGB32(255 * RND, 255 * RND, 255 * RND)
  15.  
  16. px = _WIDTH / 2
  17. py = 0
  18.  
  19. _TITLE "Pendula"
  20.  
  21.     CLS
  22.     FOR i = 0 TO maxPendulum
  23.         IF _MOUSEBUTTON(1) THEN
  24.             theta(i) = map(_MOUSEX, 0, _WIDTH - 1, 4.7, 1.57)
  25.             speed(i) = 0
  26.         ELSE
  27.             accel(i) = mass(i) * g * SIN(theta(i)) / 100
  28.             speed(i) = speed(i) + accel(i) / 100
  29.             theta(i) = theta(i) + speed(i)
  30.         END IF
  31.         bx = px + length(i) * SIN(theta(i))
  32.         by = py - length(i) * COS(theta(i))
  33.         LINE (px, py)-(bx, by), c(i)
  34.         CircleFill bx, by, map(i, 0, maxPendulum, 20, 40), c(i)
  35.     NEXT
  36.     _DISPLAY
  37.     _LIMIT 60
  38.  
  39. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  40.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  41.  
  42. SUB CircleFill (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  43.     ' CX = center x coordinate
  44.     ' CY = center y coordinate
  45.     '  R = radius
  46.     '  C = fill color
  47.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  48.     DIM X AS INTEGER, Y AS INTEGER
  49.     Radius = ABS(R)
  50.     RadiusError = -Radius
  51.     X = Radius
  52.     Y = 0
  53.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  54.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  55.     WHILE X > Y
  56.         RadiusError = RadiusError + Y * 2 + 1
  57.         IF RadiusError >= 0 THEN
  58.             IF X <> Y + 1 THEN
  59.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  60.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  61.             END IF
  62.             X = X - 1
  63.             RadiusError = RadiusError - X * 2
  64.         END IF
  65.         Y = Y + 1
  66.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  67.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  68.     WEND
  69.  

PS: You can use your mouse.
Title: Re: Pendula
Post by: bplus on September 27, 2020, 04:07:27 pm
Nice effect with many pendulum.
Title: Re: Pendula
Post by: SpriggsySpriggs on September 27, 2020, 04:07:38 pm
@FellippeHeitor This blows my mind away!!!!

EDIT: Gasp! You have the map function! That is the function I needed to make a clock in p5js!
Title: Re: Pendula
Post by: FellippeHeitor on September 27, 2020, 04:11:10 pm
@bplus thank you!

@SpriggsySpriggs here's mine and Ashish's translation of p5.js into p5js.bas: https://github.com/FellippeHeitor/p5js.bas <-- grab what you need!
Title: Re: Pendula
Post by: SpriggsySpriggs on September 27, 2020, 04:17:47 pm
@FellippeHeitor I do have p5js.bas but I didn't know what to do with the map function so it was good to see this example!
Title: Re: Pendula
Post by: FellippeHeitor on September 27, 2020, 04:19:48 pm
Map() is really useful. Highly recommended video on the matter:

Title: Re: Pendula
Post by: OldMoses on September 27, 2020, 04:37:07 pm
Great effect. I like that map function too. I seem to be doing things like it fairly often and have always been reinventing the wheel when I do.
Title: Re: Pendula
Post by: bplus on September 27, 2020, 04:51:57 pm
Yeah that map function is probably particularly handy when one or the other ranges don't start at 0.
Title: Re: Pendula
Post by: STxAxTIC on September 27, 2020, 05:20:45 pm
Are those pendulums connected in this simulation or do they hang separate, but are just plotted closely?

If not connected, meaning each swings free, then the varying mass should not matter.

Angular frequency equals square root of gravity constant divided by pendulum length, mass cancels out. Try changing your masses to random numbers, the output should be identical.

If they are connected then nevermind, different equation.
Title: Re: Pendula
Post by: FellippeHeitor on September 27, 2020, 05:23:04 pm
They're... just... there... this is as close as I could get from the original post.

I tried using the pendulum code you'd provided for my pendulum game, but then there's the extra tweaks that got added for the game itself.

I copied the core calculations in this one from the rosetta stone page on pendulum animations. And tweaked it from there.
Title: Re: Pendula
Post by: STxAxTIC on September 27, 2020, 05:27:32 pm
Say, remember my post on integrators and  that pdf on how to "compute anything"? Just before covid... I will dig that up if nobody links it sooner, but it fleshes this out pretty well.
Title: Re: Pendula
Post by: OldMoses on September 27, 2020, 05:29:52 pm
Yeah that map function is probably particularly handy when one or the other ranges don't start at 0.

Indeed it is, I define a WINDOW that is 620 x 620 actual, but -1000 to 1000 left to right X and 1000 to -1000 top to bottom Y and starts at upper left corner 19,560 on the main screen. It was a PITA calculation to convert _MOUSEX and _MOUSEY, but map walked in and took over like a boss.
Title: Re: Pendula
Post by: STxAxTIC on September 27, 2020, 05:53:29 pm
Stopped home in the middle of work just to dig out that code. Here is every right way and wrong way to do a pendulum:

Code: QB64: [Select]
  1. CONST Black = _RGB32(0, 0, 0)
  2. CONST Blue = _RGB32(0, 0, 255)
  3. CONST Gray = _RGB32(128, 128, 128)
  4. CONST Green = _RGB32(0, 128, 0)
  5. CONST Red = _RGB32(255, 0, 0)
  6. CONST White = _RGB32(255, 255, 255)
  7. CONST Yellow = _RGB32(255, 255, 0)
  8.  
  9. SCREEN _NEWIMAGE(1280, 480, 32)
  10.  
  11. showmenu:
  12. COLOR White
  13. PRINT " Type a problem number and press ENTER."
  14. PRINT " PROBLEM"
  15. PRINT " 1) Particle in r^-1 central potential"
  16. PRINT "    a) Perturbed motion ......................... Stable, Symplectic"
  17. PRINT "    b) Elliptical motion ........................ Stable, Symplectic"
  18. PRINT "    c) Eccentric elliptical motion .............. Stable, Symplectic"
  19. PRINT " 2) Particle in r^-2 central potential"
  20. PRINT "    a) Attempted circular motion ................ Unstable, Symplectic"
  21. PRINT " 3) Mass on a spring"
  22. PRINT "    a) Initial Momentum ..........*Incorrect*.... Unstable, Euler"
  23. PRINT "    b) Initial Displacement ......*Incorrect*.... Unstable, Euler"
  24. PRINT " 4) Two equal masses connected by three springs"
  25. PRINT "    a) Symmetric mode ........................... Stable, Symplectic"
  26. PRINT "    b) Antisymmetric mode ....................... Stable, Symplectic"
  27. PRINT "    c) Perturbed motion ......................... Stable, Symplectic"
  28. PRINT " 5) Plane pendulum (Part I)"
  29. PRINT "    a) Initial Momentum ..........*Incorrect*.... Unstable, Euler"
  30. PRINT " 6) Plane pendulum (Part III)"
  31. PRINT "    a) Sub-critical case ........................ Stable, RK4"
  32. PRINT "    b) Over-critical case ....................... Stable, RK4"
  33. PRINT " 7) Plane pendulum (Part III)"
  34. PRINT "    a) Initial Displacement ..................... Stable, Symplectic"
  35. PRINT "    b) Sub-critical case ........................ Stable, Symplectic"
  36. PRINT "    c) Over-critical case ....................... Stable, Symplectic"
  37. PRINT " 8) Plane pendulum (Part IV)"
  38. PRINT "    a) Initial Displacement ..................... Stable, Mixed Euler"; ""
  39. INPUT " Enter a problem (ex. 1a): ", problem$
  40. problem$ = LTRIM$(RTRIM$(LCASE$(problem$)))
  41.  
  42. ' Initial conditions
  43. q10 = 0
  44. p10 = 0
  45. q20 = 0
  46. p20 = 0
  47. SELECT CASE VAL(LEFT$(problem$, 1))
  48.     CASE 1
  49.         dt = .003
  50.         cyclic = 1
  51.         delayfactor = 1000
  52.         scalebig = 20
  53.         scalesmall = dt * 5
  54.         m1 = 1
  55.         m2 = 1
  56.         g = 1
  57.         SELECT CASE (RIGHT$(problem$, 1))
  58.             CASE "a"
  59.                 q10 = 1: p10 = -.2: q20 = 0: p20 = 1
  60.             CASE "b"
  61.                 q10 = .5: p10 = 1: q20 = -.5: p20 = 1
  62.             CASE "c"
  63.                 q10 = 1: p10 = .5: q20 = 0: p20 = 1.15
  64.         END SELECT
  65.     CASE 2
  66.         dt = .001
  67.         cyclic = 0
  68.         delayfactor = 1000
  69.         scalebig = 20
  70.         scalesmall = dt * 10
  71.         m1 = 1
  72.         m2 = 1
  73.         g = 1
  74.         SELECT CASE (RIGHT$(problem$, 1))
  75.             CASE "a"
  76.                 q10 = 1: p10 = 0: q20 = 0: p20 = 1.22437
  77.         END SELECT
  78.     CASE 3
  79.         dt = .03
  80.         cyclic = 0
  81.         delayfactor = 1000
  82.         scalebig = 10
  83.         scalesmall = dt * 7.5
  84.         m = 1
  85.         k = 1
  86.         SELECT CASE (RIGHT$(problem$, 1))
  87.             CASE "a"
  88.                 q10 = 0: p10 = 2
  89.             CASE "b"
  90.                 q10 = 2: p10 = 0
  91.         END SELECT
  92.     CASE 4
  93.         dt = .003
  94.         cyclic = 1
  95.         delayfactor = 50000
  96.         scalebig = 12
  97.         scalesmall = dt * 7.5
  98.         m = 1
  99.         k = 1
  100.         SELECT CASE (RIGHT$(problem$, 1))
  101.             CASE "a"
  102.                 q10 = 0: p10 = 2: q20 = 0: p20 = 2
  103.             CASE "b"
  104.                 q10 = 2: p10 = 0: q20 = -2: p20 = 0
  105.             CASE "c"
  106.                 q10 = 2: p10 = 0: q20 = 0: p20 = 0
  107.         END SELECT
  108.     CASE 5
  109.         dt = .03
  110.         cyclic = 1
  111.         delayfactor = 500000
  112.         scalebig = 10
  113.         scalesmall = dt * 5
  114.         m = 1
  115.         g = 1
  116.         l = 1
  117.         SELECT CASE (RIGHT$(problem$, 1))
  118.             CASE "a"
  119.                 q10 = 0: p10 = 1.5: scalebig = 10
  120.         END SELECT
  121.     CASE 6
  122.         dt = .03
  123.         cyclic = 1
  124.         delayfactor = 500000
  125.         scalebig = 10
  126.         scalesmall = dt * 5
  127.         m = 1
  128.         g = 1
  129.         l = 1
  130.         SELECT CASE (RIGHT$(problem$, 1))
  131.             CASE "a"
  132.                 q10 = 0: p10 = 2.19
  133.             CASE "b"
  134.                 q10 = 0: p10 = 2.25
  135.         END SELECT
  136.     CASE 7, 8
  137.         dt = .03
  138.         cyclic = 1
  139.         delayfactor = 500000
  140.         scalebig = 10
  141.         scalesmall = dt * 5
  142.         m = 1
  143.         g = 1
  144.         l = 1
  145.         SELECT CASE (RIGHT$(problem$, 1))
  146.             CASE "a"
  147.                 q10 = 0: p10 = -1.5
  148.             CASE "b"
  149.                 q10 = 0: p10 = 1.999
  150.             CASE "c"
  151.                 q10 = 0: p10 = 2.001
  152.         END SELECT
  153.     CASE ELSE
  154.         GOTO showmenu
  155.  
  156. GOSUB drawaxes
  157.  
  158. ' Main loop.
  159. iterations = 0
  160. q1 = q10
  161. p1 = p10
  162. q2 = q20
  163. p2 = p20
  164.  
  165.  
  166.     FOR thedelay = 0 TO delayfactor: NEXT
  167.  
  168.     q1temp = q1
  169.     p1temp = p1
  170.     q2temp = q2
  171.     p2temp = p2
  172.  
  173.     SELECT CASE VAL(LEFT$(problem$, 1))
  174.         CASE 1
  175.             ' Particle in r^-1 central potential - Symplectic integrator
  176.             q1 = q1temp + dt * (p1temp / m2)
  177.             q2 = q2temp + dt * (p2temp / m2)
  178.             p1 = p1temp - dt * g * m1 * m2 * (q1 / ((q1 ^ 2 + q2 ^ 2) ^ (3 / 2)))
  179.             p2 = p2temp - dt * g * m1 * m2 * (q2 / ((q1 ^ 2 + q2 ^ 2) ^ (3 / 2)))
  180.         CASE 2
  181.             ' Particle in r^-2 central potential - Symplectic integrator
  182.             q1 = q1temp + dt * (p1temp / m2)
  183.             q2 = q2temp + dt * (p2temp / m2)
  184.             p1 = p1temp - dt * g * m1 * m2 * ((3 / 2) * q1 / ((q1 ^ 2 + q2 ^ 2) ^ (5 / 2)))
  185.             p2 = p2temp - dt * g * m1 * m2 * ((3 / 2) * q2 / ((q1 ^ 2 + q2 ^ 2) ^ (5 / 2)))
  186.         CASE 3
  187.             ' Mass on a spring - Forward Euler method
  188.             q1 = q1temp + (p1temp / m) * dt
  189.             p1 = p1temp - (q1temp * k) * dt
  190.             ' Mass on a spring - Backward Euler method
  191.             q2 = (q2temp + (p2temp / m) * dt) / (1 + dt ^ 2)
  192.             p2 = (p2temp - (q2temp * k) * dt) / (1 + dt ^ 2)
  193.         CASE 4
  194.             ' Two equal masses connected by three springs - Symplectic integrator
  195.             q1 = q1temp + m * (p1temp) * dt
  196.             p1 = p1temp - dt * k * (2 * (q1temp + m * (p1temp) * dt) - (q2temp + m * (p2temp) * dt))
  197.             q2 = q2temp + m * (p2temp) * dt
  198.             p2 = p2temp - dt * k * (2 * (q2temp + m * (p2temp) * dt) - (q1temp + m * (p1temp) * dt))
  199.         CASE 5
  200.             ' Plane pendulum - Forward Euler method
  201.             q1 = q1temp + (p1temp / m) * dt
  202.             p1 = p1temp - (g / l) * SIN(q1temp) * dt
  203.         CASE 6
  204.             ' Plane pendulum - Runge-Kutta 4th
  205.             k1w = -(g / l) * SIN(q1temp)
  206.             k1t = p1temp
  207.             w2 = p1temp + k1w * dt / 2
  208.             t2 = q1temp + k1t * dt / 2
  209.             k2w = -(g / l) * SIN(t2)
  210.             k2t = w2
  211.             w3 = p1temp + k2w * dt / 2
  212.             t3 = q1temp + k2t * dt / 2
  213.             k3w = -(g / l) * SIN(t3)
  214.             k3t = w3
  215.             w4 = p1temp + k3w * dt
  216.             t4 = q1temp + k3t * dt
  217.             k4w = -(g / l) * SIN(t4)
  218.             dwdt = (k1w + 2 * k2w + 2 * k3w + k4w) / 6
  219.             dtdt = (k1t + 2 * k2t + 2 * k3t + k4t) / 6
  220.             p1 = p1temp + dwdt * dt
  221.             q1 = q1temp + dtdt * dt
  222.         CASE 7
  223.             ' Plane pendulum - Symplectic integrator
  224.             q1 = q1temp + dt * (p1temp / m)
  225.             p1 = p1temp - dt * (g / l) * (SIN(q1))
  226.         CASE 8
  227.             ' Plane pendulum - Modified Euler method
  228.             q1 = q1temp + (p1temp / m) * dt
  229.             p1 = p1temp - (g / l) * SIN(q1) * dt
  230.     END SELECT
  231.  
  232.     x = (iterations * scalesmall - 180)
  233.     IF (x <= 80) THEN
  234.         x = x + (320 - _WIDTH / 2)
  235.         CALL cpset(x, (q1 * scalebig + 160), Yellow) ' q1 plot
  236.         CALL cpset(x, (p1 * scalebig + 60), Yellow) ' p1 plot
  237.         CALL cpset(x, (q2 * scalebig - 60), Red) ' q2 plot
  238.         CALL cpset(x, (p2 * scalebig - 160), Red) ' p2 plot
  239.     ELSE
  240.         IF (cyclic = 1) THEN
  241.             iterations = 0
  242.             PAINT (1, 1), _RGBA(0, 0, 0, 100)
  243.             GOSUB drawaxes
  244.         ELSE
  245.             EXIT DO
  246.         END IF
  247.     END IF
  248.  
  249.     ' Phase portrait
  250.     CALL cpset((q1temp * (2 * scalebig) + (190 + (320 - _WIDTH / 2))), (p1temp * (2 * scalebig) + 100), Yellow)
  251.     CALL cpset((q1 * (2 * scalebig) + (190 + (320 - _WIDTH / 2))), (p1 * (2 * scalebig) + 100), Gray)
  252.     CALL cpset((q2temp * (2 * scalebig) + (190 + (320 - _WIDTH / 2))), (p2temp * (2 * scalebig) + 100), Red)
  253.     CALL cpset((q2 * (2 * scalebig) + (190 + (320 - _WIDTH / 2))), (p2 * (2 * scalebig) + 100), White)
  254.  
  255.     ' Position portrait
  256.     CALL cpset((q1temp * (2 * scalebig) + (190 + (320 - _WIDTH / 2))), (q2temp * (2 * scalebig) - 100), Blue)
  257.     CALL cpset((q1 * (2 * scalebig) + (190 + (320 - _WIDTH / 2))), (q2 * (2 * scalebig) - 100), White)
  258.  
  259.     ' System portrait - Requires 2x wide window.
  260.     SELECT CASE VAL(LEFT$(problem$, 1))
  261.         CASE 4
  262.             CALL cline(160, 0, 220 + 20 * q1, 0, Green)
  263.             CALL cline(220 + 20 * q1, 0, 380 + 20 * q2, 0, Yellow)
  264.             CALL cline(380 + 20 * q2, 0, 440, 0, Green)
  265.             CALL ccircle(220 + 20 * q1temp, 0, 15, Black)
  266.             CALL ccircle(220 + 20 * q1, 0, 15, Blue)
  267.             CALL ccircle(380 + 20 * q2temp, 0, 15, Black)
  268.             CALL ccircle(380 + 20 * q2, 0, 15, Red)
  269.         CASE 5, 6, 7, 8
  270.             CALL cline(200, 0, 400, 0, White)
  271.             CALL cline(300, 0, 300 + 100 * SIN(q1temp), -100 * COS(q1temp), Black)
  272.             CALL cline(300, 0, 300 + 100 * SIN(q1), -100 * COS(q1), Blue)
  273.     END SELECT
  274.  
  275.     iterations = iterations + 1
  276.  
  277.     '_DISPLAY
  278.  
  279. GOTO showmenu
  280.  
  281.  
  282. drawaxes:
  283. ' Axis for q1 plot
  284. COLOR White
  285. LOCATE 2, 3: PRINT "Generalized"
  286. LOCATE 3, 3: PRINT "Coordinates"
  287. CALL cline(-_WIDTH / 2 + 140, 160, -_WIDTH / 2 + 400, 160, Gray)
  288. COLOR White: LOCATE 5, 3: PRINT "Position q1(t)"
  289. COLOR Gray: LOCATE 6, 3: PRINT "q1(0) ="; q10
  290. ' Axis for p1 plot
  291. CALL cline(-_WIDTH / 2 + 140, 60, -_WIDTH / 2 + 400, 60, Gray)
  292. COLOR White: LOCATE 11, 3: PRINT "Momentum p1(t)"
  293. COLOR Gray: LOCATE 12, 3: PRINT "p1(0) ="; p10
  294. ' Axis for q2 plot
  295. CALL cline(-_WIDTH / 2 + 140, -60, -_WIDTH / 2 + 400, -60, Gray)
  296. COLOR White: LOCATE 18, 3: PRINT "Position q2(t)"
  297. COLOR Gray: LOCATE 19, 3: PRINT "q2(0) ="; q20
  298. ' Axis for p2 plot
  299. CALL cline(-_WIDTH / 2 + 140, -160, -_WIDTH / 2 + 400, -160, Gray)
  300. COLOR White: LOCATE 25, 3: PRINT "Momentum p2(t)"
  301. COLOR Gray: LOCATE 26, 3: PRINT "p2(0) ="; p20
  302. ' Axes for q & p plots
  303. COLOR White
  304. LOCATE 2, 60: PRINT "Phase and"
  305. LOCATE 3, 58: PRINT "Position Plots"
  306. LOCATE 4, 66: PRINT "p"
  307. LOCATE 10, 76: PRINT "q"
  308. CALL cline((190 + (320 - _WIDTH / 2)), 80 + 100, (190 + (320 - _WIDTH / 2)), -80 + 100, Gray)
  309. CALL cline((190 + (320 - _WIDTH / 2)) - 100, 100, (190 + (320 - _WIDTH / 2)) + 100, 100, Gray)
  310. LOCATE 17, 66: PRINT "q2"
  311. LOCATE 23, 75: PRINT "q1"
  312. CALL cline((190 + (320 - _WIDTH / 2)), -80 - 100, (190 + (320 - _WIDTH / 2)), 80 - 100, Gray)
  313. CALL cline((190 + (320 - _WIDTH / 2)) - 100, -100, (190 + (320 - _WIDTH / 2)) + 100, -100, Gray)
  314.  
  315. SUB cline (x1, y1, x2, y2, col AS _UNSIGNED LONG)
  316.     LINE (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2)-(_WIDTH / 2 + x2, -y2 + _HEIGHT / 2), col
  317.  
  318. SUB ccircle (x1, y1, rad, col AS _UNSIGNED LONG)
  319.     CIRCLE (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2), rad, col
  320.  
  321. SUB cpset (x1, y1, col AS _UNSIGNED LONG)
  322.     PSET (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2), col
  323.  

... And the accompanying document is a tad calculus heavy but justifies everything in the above:

http://wfbarnes.net/homedata/Mechalculus.pdf (http://wfbarnes.net/homedata/Mechalculus.pdf)
Title: Re: Pendula
Post by: _vince on September 28, 2020, 04:51:23 pm
I'm now extremely curious to see a nth order generalization to the chaotic double pendulum -- too much work for me
Title: Re: Pendula
Post by: FellippeHeitor on September 28, 2020, 05:26:08 pm
Stopped home in the middle of work just to dig out that code. Here is every right way and wrong way to do a pendulum:

<code>

... And the accompanying document is a tad calculus heavy but justifies everything in the above:

http://wfbarnes.net/homedata/Mechalculus.pdf (http://wfbarnes.net/homedata/Mechalculus.pdf)

That is always a fun render to watch, STx.
Title: Re: Pendula
Post by: DANILIN on September 29, 2020, 04:07:06 pm
more  of pendulums: long read text

http://rosettacode.org/wiki/Animate_a_pendulum
rosettacode.org/wiki/Animate_a_pendulum

and me learn another language graphic by this page
Title: Re: Pendula
Post by: Ashish on September 30, 2020, 09:06:40 am
My attempt to recreate this in 3D -

Code: QB64: [Select]
  1. 'Pendula in 3D : By Ashish in QB64 using OpenGL
  2. 'idea from here - https://www.qb64.org/forum/index.php?topic=3056.msg123288#msg123288
  3. _TITLE "Pendula in 3D"
  4. SCREEN _NEWIMAGE(800, 600, 32)
  5.  
  6. TYPE pendulum_type
  7.     ang AS SINGLE 'angle
  8.     ang_factor AS SINGLE
  9.     min_ang AS SINGLE
  10.     max_ang AS SINGLE
  11.     mass AS SINGLE
  12.     clr AS _UNSIGNED LONG 'color of the sphere
  13.     rad AS SINGLE 'radius of the sphere
  14.     rope_length AS SINGLE 'length of the rope on which the sphere is hanging
  15.  
  16.     SUB glutSolidSphere (BYVAL radius AS DOUBLE, BYVAL slices AS LONG, BYVAL stack AS LONG) 'use to draw a sphere
  17.     SUB gluLookAt (BYVAL eyeX#, BYVAL eyeY#, BYVAL eyeZ#, BYVAL centerX#, BYVAL centerY#, BYVAL centerZ#, BYVAL upX#, BYVAL upY#, BYVAL upZ#) 'for camera purpose
  18.  
  19. CONST MAX_PENDULUM = 15
  20.  
  21. DIM SHARED pendulum(1 TO MAX_PENDULUM) AS pendulum_type, init AS _BYTE
  22. DIM SHARED ix, iy, iz
  23.  
  24. ix = 0: iy = 1.5: iz = 2
  25.  
  26. FOR i = 1 TO MAX_PENDULUM
  27.     pendulum(i).rad = 0.25
  28.     pendulum(i).min_ang = _PI(1.25)
  29.     pendulum(i).max_ang = _PI(1.75)
  30.     pendulum(i).clr = _RGB(RND * 255, RND * 255, RND * 255)
  31.     pendulum(i).rope_length = 2
  32.     pendulum(i).mass = 3 + i * 0.5
  33.  
  34. init = 1
  35.     FOR i = 1 TO MAX_PENDULUM
  36.         pendulum(i).ang_factor = pendulum(i).ang_factor + 0.01 * pendulum(i).mass
  37.         pendulum(i).ang = map(SIN(pendulum(i).ang_factor), -1, 1, pendulum(i).min_ang, pendulum(i).max_ang)
  38.     NEXT
  39.     _LIMIT 60
  40.  
  41. SUB _GL ()
  42.     STATIC t
  43.     t = t + 0.01
  44.     IF init = 0 THEN EXIT SUB
  45.    
  46.     ' _glClearColor 0.3,0.3,0.3,1
  47.     _glClear _GL_COLOR_BUFFER_BIT OR _GL_DEPTH_BUFFER_BIT
  48.    
  49.     _glEnable _GL_LIGHTING
  50.     _glEnable _GL_LIGHT0
  51.     _glEnable _GL_DEPTH_TEST
  52.     _glEnable _GL_COLOR_MATERIAL
  53.    
  54.     DIM v(3) AS SINGLE
  55.     v(0) = 0: v(1) = 0: v(2) = 1: v(3) = 0
  56.    
  57.     _glLightfv _GL_LIGHT0, _GL_POSITION, _OFFSET(v())
  58.    
  59.     _glMatrixMode _GL_PROJECTION
  60.     _gluPerspective 50, _WIDTH / _HEIGHT, 0.1, 25
  61.    
  62.     _glMatrixMode _GL_MODELVIEW
  63.    
  64.     gluLookAt 0, 2, 5, 0, 0, 0, 0, 1, 0
  65.    
  66.     drawXZPlane 0, -2, 0, 8, 16, -1
  67.    
  68.     DIM z
  69.     z = iz
  70.     _glLineWidth 5.0
  71.     FOR i = 1 TO MAX_PENDULUM
  72.         _glColor3ub 255, 255, 0
  73.         _glBegin _GL_LINES
  74.         _glVertex3f ix, iy, z
  75.         _glVertex3f ix + pendulum(i).rope_length * COS(pendulum(i).ang), iy + pendulum(i).rope_length * SIN(pendulum(i).ang), z
  76.         _glEnd
  77.        
  78.         _glPushMatrix
  79.         _glTranslatef ix + (pendulum(i).rope_length + pendulum(i).rad) * COS(pendulum(i).ang), iy + (pendulum(i).rope_length + pendulum(i).rad) * SIN(pendulum(i).ang), z
  80.         _glColor3ub _RED(pendulum(i).clr), _GREEN(pendulum(i).clr), _BLUE(pendulum(i).clr)
  81.         glutSolidSphere pendulum(i).rad, 50, 50
  82.         _glPopMatrix
  83.        
  84.         z = z - 2.3 * pendulum(i).rad
  85.     NEXT
  86.     _glColor3ub 255, 255, 0
  87.     _glBegin _GL_LINES
  88.     _glVertex3f ix, iy, iz
  89.     _glVertex3f ix, iy, z
  90.     _glEnd
  91.    
  92.     _glFlush
  93.  
  94. SUB drawXZPlane (x, y, z, w, d, n) '(x,z)->location to draw, w->width, d->depth of the plane, n->normal direction in Y direction
  95.     _glBegin _GL_QUADS
  96.     _glTexCoord2f 1, 0
  97.     _glNormal3f 0, n, 0
  98.     _glVertex3f x - (w / 2), y, z - d / 2
  99.     _glTexCoord2f 1, 1
  100.     _glNormal3f 0, n, 0
  101.     _glVertex3f x + (w / 2), y, z - d / 2
  102.     _glTexCoord2f 0, 1
  103.     _glNormal3f 0, n, 0
  104.     _glVertex3f x + (w / 2), y, z + d / 2
  105.     _glTexCoord2f 0, 0
  106.     _glNormal3f 0, n, 0
  107.     _glVertex3f x - (w / 2), y, z + d / 2
  108.     _glEnd
  109.  
  110. 'from p5js.bas
  111. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  112.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  113.  
  114.  
Title: Re: Pendula
Post by: FellippeHeitor on September 30, 2020, 09:20:35 am
My attempt to recreate this in 3D -

Whoooooooooa!
🤩
Title: Re: Pendula
Post by: DANILIN on January 06, 2022, 12:38:38 am
improvement:

for colorize:
Randomize Timer

thik lines:
_glLineWidth 0.0

or symbol ':
'_glBegin _GL_LINES 
Title: Re: Pendula
Post by: _vince on January 07, 2022, 05:13:58 am
We've all seen the chaotic double pendulum.  I'll leave my simple Runge-Kutta one done with canned formulas from wikipedia at the end.

Challenge:  Generalize it to n-pendulum!  Triple, quadruple, whatever the user wants.  The next ball is to be attached to the previous.  It's going to be a fairly tedious system of differential equations based on the lagrangian of the system (https://en.wikipedia.org/wiki/Double_pendulum#Analysis_and_interpretation (https://en.wikipedia.org/wiki/Double_pendulum#Analysis_and_interpretation)).  Probably so tedious you're going to need a large matrix and some linear algebra.  But goddamn I'll be so impressed if you do it, you'll come out of it totally competent to program everything DEs.

Here's the trivial case:
Code: QB64: [Select]
  1. defsng a-z
  2. pi = 3.141593
  3. r = 100
  4. a1 = -pi/2
  5. a2 = -pi/2
  6. h=0.001
  7. m=1000
  8. g=1000
  9. sw = 640
  10. sh = 480
  11.  
  12. p1 = _newimage(sw,sh,12)
  13. screen _newimage(sw,sh,12)
  14.  
  15.         a1p = (6/(m*r^2))*(2*m*v1-3*cos(a1-a2)*m*v2)/(16-9*(cos(a1-a2))^2)
  16.         a1k1 = a1p
  17.         a1k2 = a1p + h*a1k1/2
  18.         a1k3 = a1p + h*a1k2/2
  19.         a1k4 = a1p + h*a1k3
  20.         a2p = (6/(m*r^2))*(8*m*v2-3*cos(a1-a2)*m*v1)/(16-9*(cos(a1-a2))^2)
  21.         a2k1 = a2p
  22.         a2k2 = a2p + h*a2k1/2
  23.         a2k3 = a2p + h*a2k2/2
  24.         a2k4 = a2p + h*a2k3
  25.         na1=a1+h*(a1k1+2*a1k2+2*a1k3+a1k4)/6
  26.         na2=a2+h*(a2k1+2*a2k2+2*a2k3+a2k4)/6
  27.         v1p = -0.5*r^2*(a1p*a2p*sin(a1-a2)+3*g*sin(a1)/r)
  28.         v1k1 = v1p
  29.         v1k2 = v1p + h*v1k1/2
  30.         v1k3 = v1p + h*v1k2/2
  31.         v1k4 = v1p + h*v1k3
  32.         v2p = -0.5*r^2*(-a1p*a2p*sin(a1-a2)+g*sin(a2)/r)
  33.         v2k1 = v2p
  34.         v2k2 = v2p + h*v2k1/2
  35.         v2k3 = v2p + h*v2k2/2
  36.         v2k4 = v2p + h*v2k3
  37.         nv1=v1+h*(v1k1+2*v1k2+2*v1k3+v1k4)/6
  38.         nv2=v2+h*(v2k1+2*v2k2+2*v2k3+v2k4)/6
  39.         a1=na1
  40.         a2=na2
  41.         v1=nv1
  42.         v2=nv2
  43.  
  44.         _dest p1
  45.         pset (sw/2+r*cos(a1-pi/2)+r*cos(a2-pi/2), sh/2-r*sin(a1-pi/2)-r*sin(a2-pi/2)),12
  46.         _dest 0
  47.         _putimage, p1
  48.  
  49.         line (sw/2, sh/2)-step(r*cos(a1-pi/2), -r*sin(a1-pi/2))
  50.         circle step(0,0),5
  51.         line -step(r*cos(a2-pi/2), -r*sin(a2-pi/2))
  52.         circle step(0,0),5
  53.  
  54.         _limit 200
  55.         _display
  56.  
Title: Re: Pendula
Post by: STxAxTIC on January 07, 2022, 10:14:12 am
That's an interesting challenge. Bonus points if all pendula are constrained to never self-intersect, so that the resulting object should be like a hanging chain and exhibit the same physics. I wonder if this is even *that* terrible to do, becau - ya know what? I'll shut up.... Nice challenge!