Author Topic: Pendula  (Read 9265 times)

0 Members and 1 Guest are viewing this topic.

This topic contains a post which is marked as Best Answer. Press here if you would like to see it.

FellippeHeitor

  • Guest
Pendula
« 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.

ezgif.com-video-to-gif.gif

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.
« Last Edit: September 27, 2020, 04:18:31 pm by FellippeHeitor »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Pendula
« Reply #1 on: September 27, 2020, 04:07:27 pm »
Nice effect with many pendulum.

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Pendula
« Reply #2 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!
« Last Edit: September 27, 2020, 04:09:38 pm by SpriggsySpriggs »
Shuwatch!

FellippeHeitor

  • Guest
Re: Pendula
« Reply #3 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!

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Pendula
« Reply #4 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!
Shuwatch!

FellippeHeitor

  • Guest
Re: Pendula
« Reply #5 on: September 27, 2020, 04:19:48 pm »
Map() is really useful. Highly recommended video on the matter:


Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Re: Pendula
« Reply #6 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.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Pendula
« Reply #7 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.

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Pendula
« Reply #8 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.
You're not done when it works, you're done when it's right.

FellippeHeitor

  • Guest
Re: Pendula
« Reply #9 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.

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Pendula
« Reply #10 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.
You're not done when it works, you're done when it's right.

Offline OldMoses

  • Seasoned Forum Regular
  • Posts: 469
    • View Profile
Re: Pendula
« Reply #11 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.

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Pendula
« Reply #12 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
You're not done when it works, you're done when it's right.

Offline _vince

  • Seasoned Forum Regular
  • Posts: 422
    • View Profile
Re: Pendula
« Reply #13 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

FellippeHeitor

  • Guest
Re: Pendula
« Reply #14 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

That is always a fun render to watch, STx.