Last active
December 20, 2023 09:04
-
-
Save duyixian1234/2a380814edc8542d280950a9225c510f to your computer and use it in GitHub Desktop.
Double Pendulum Animation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html lang="en"> | |
| <head> | |
| <meta charset="UTF-8" /> | |
| <meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
| <title>Double Pendulum Animation</title> | |
| </head> | |
| <body> | |
| <canvas id="canvas" width="800" height="600"></canvas> | |
| <script src="script.js"></script> | |
| </body> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const canvas = document.getElementById("canvas"); | |
| const ctx = canvas.getContext("2d"); | |
| const width = canvas.width; | |
| const height = canvas.height; | |
| const pivot1 = { x: width / 2, y: height / 2 }; | |
| const pivot2 = { x: width / 2, y: height / 2 + 100 }; | |
| const arm1Length = 100; | |
| const arm2Length = 80; | |
| const arm1Mass = 10; | |
| const arm2Mass = 10; | |
| const gravity = 1; | |
| const showTrace = true; | |
| const damping = 1; | |
| let angle1 = Math.PI / 2; | |
| let angle2 = Math.PI / 2; | |
| let angle1Velocity = 0; | |
| let angle2Velocity = 0; | |
| const tracePoints = []; // Array to store trace points | |
| function draw() { | |
| ctx.clearRect(0, 0, width, height); | |
| const arm1X = pivot1.x + Math.sin(angle1) * arm1Length; | |
| const arm1Y = pivot1.y + Math.cos(angle1) * arm1Length; | |
| const arm2X = arm1X + Math.sin(angle2) * arm2Length; | |
| const arm2Y = arm1Y + Math.cos(angle2) * arm2Length; | |
| ctx.beginPath(); | |
| ctx.moveTo(pivot1.x, pivot1.y); | |
| ctx.lineTo(arm1X, arm1Y); | |
| ctx.stroke(); | |
| ctx.beginPath(); | |
| ctx.moveTo(arm1X, arm1Y); | |
| ctx.lineTo(arm2X, arm2Y); | |
| ctx.stroke(); | |
| ctx.beginPath(); | |
| ctx.arc(arm1X, arm1Y, arm1Mass, 0, Math.PI * 2); | |
| ctx.fillStyle = "red"; | |
| ctx.fill(); | |
| ctx.beginPath(); | |
| ctx.arc(arm2X, arm2Y, arm2Mass, 0, Math.PI * 2); | |
| ctx.fillStyle = "blue"; | |
| ctx.fill(); | |
| if (showTrace) { | |
| tracePoints.push({ x: arm2X, y: arm2Y }); // Add current point to tracePoints array | |
| if (tracePoints.length > 300) { | |
| tracePoints.shift(); // Remove first element from array | |
| } | |
| ctx.beginPath(); | |
| ctx.moveTo(tracePoints[0].x, tracePoints[0].y); | |
| for (let i = 1; i < tracePoints.length; i++) { | |
| ctx.lineTo(tracePoints[i].x, tracePoints[i].y); | |
| } | |
| ctx.strokeStyle = "gray"; | |
| ctx.stroke(); | |
| } | |
| const num1 = -gravity * (2 * arm1Mass + arm2Mass) * Math.sin(angle1); | |
| const num2 = -arm2Mass * gravity * Math.sin(angle1 - 2 * angle2); | |
| const num3 = -2 * Math.sin(angle1 - angle2) * arm2Mass; | |
| const num4 = | |
| angle2Velocity * angle2Velocity * arm2Length + | |
| angle1Velocity * angle1Velocity * arm1Length * Math.cos(angle1 - angle2); | |
| const den = | |
| arm1Length * | |
| (2 * arm1Mass + arm2Mass - arm2Mass * Math.cos(2 * angle1 - 2 * angle2)); | |
| const angle1Acceleration = (num1 + num2 + num3 * num4) / den; | |
| const num5 = 2 * Math.sin(angle1 - angle2); | |
| const num6 = | |
| angle1Velocity * angle1Velocity * arm1Length * (arm1Mass + arm2Mass); | |
| const num7 = gravity * (arm1Mass + arm2Mass) * Math.cos(angle1); | |
| const num8 = | |
| angle2Velocity * | |
| angle2Velocity * | |
| arm2Length * | |
| arm2Mass * | |
| Math.cos(angle1 - angle2); | |
| const den2 = | |
| arm2Length * | |
| (2 * arm1Mass + arm2Mass - arm2Mass * Math.cos(2 * angle1 - 2 * angle2)); | |
| const angle2Acceleration = (num5 * (num6 + num7 + num8)) / den2; | |
| angle1Velocity = damping * (angle1Velocity + angle1Acceleration); | |
| angle2Velocity = damping * (angle2Velocity + angle2Acceleration); | |
| angle1 += angle1Velocity; | |
| angle2 += angle2Velocity; | |
| requestAnimationFrame(draw); | |
| } | |
| draw(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment