Author Topic: Pendula  (Read 13895 times)

0 Members and 1 Guest are viewing this topic.

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 »
  • Best Answer
  • 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 »
  • Best Answer
  • @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 »
  • Best Answer
  • @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 »
  • Best Answer
  • @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 »
  • Best Answer
  • 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 »
  • Best Answer
  • 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 »
  • Best Answer
  • 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 »
  • Best Answer
  • 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 »
  • Best Answer
  • 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 »
  • Best Answer
  • 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 »
  • Best Answer
  • 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 »
  • Best Answer
  • 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 »
  • Best Answer
  • 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 »
  • Best Answer
  • 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.