Added pendulum
This commit is contained in:
parent
0aabdb7d84
commit
db5d25c370
27
pendulum/index.html
Normal file
27
pendulum/index.html
Normal file
|
@ -0,0 +1,27 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Pendulum</title>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/p5@1.2.0/lib/p5.js"></script>
|
||||
<script src="main.js"></script>
|
||||
|
||||
<style>
|
||||
body {
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
canvas {
|
||||
display: blocK;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
266
pendulum/main.js
Normal file
266
pendulum/main.js
Normal file
|
@ -0,0 +1,266 @@
|
|||
let canvas;
|
||||
|
||||
let points = [];
|
||||
let shapeComplete = false;
|
||||
let mouseSnap = false;
|
||||
|
||||
let attachPoint;
|
||||
let attachPointSelected = false;
|
||||
|
||||
let m;
|
||||
let centerMass;
|
||||
let inertia;
|
||||
|
||||
let L;
|
||||
let g = 4.81;
|
||||
let acc = 0;
|
||||
let vel = 0;
|
||||
let theta = 0;
|
||||
|
||||
function insideShape(point)
|
||||
{
|
||||
if(!shapeComplete)
|
||||
return false;
|
||||
|
||||
// Raycasting algorithm
|
||||
var j = points.length - 1;
|
||||
var oddNodes = false;
|
||||
|
||||
var i;
|
||||
for (i = 0; i < points.length; i++)
|
||||
{
|
||||
if ((points[i].y < point.y && points[j].y >= point.y
|
||||
|| points[j].y < point.y && points[i].y >= point.y)
|
||||
&& (points[i].x <= point.x || points[j].y <= point.x))
|
||||
{
|
||||
if (points[i].x + (point.y - points[i].y) / (points[j].y - points[i].y) * (points[j].x - points[i].x) < point.x)
|
||||
{
|
||||
oddNodes = !oddNodes;
|
||||
}
|
||||
}
|
||||
j=i;
|
||||
}
|
||||
|
||||
return (oddNodes ? 1 : 0);
|
||||
}
|
||||
|
||||
function massHelper(y, samples)
|
||||
{
|
||||
var origin = createVector(0, 0);
|
||||
|
||||
var h = width / samples;
|
||||
var sum = 0.5 * (insideShape(createVector(0, y)) + insideShape(createVector(width, y)));
|
||||
|
||||
for(var i = 1; i <= samples - 1; i++)
|
||||
{
|
||||
var point = createVector(i * h, y);
|
||||
sum += insideShape(point);
|
||||
}
|
||||
|
||||
return h * sum;
|
||||
}
|
||||
|
||||
function mass(samples)
|
||||
{
|
||||
var h = height / samples;
|
||||
var sum = 0.5 * (massHelper(0, samples) + massHelper(height, samples));
|
||||
|
||||
for(var i = 1; i <= samples - 1; i++)
|
||||
{
|
||||
sum += massHelper(i * h, samples);
|
||||
}
|
||||
|
||||
return h * sum;
|
||||
}
|
||||
|
||||
function momentOfInertiaHelper(y, samples)
|
||||
{
|
||||
var origin = createVector(0, 0);
|
||||
|
||||
var h = width / samples;
|
||||
var sum = 0.5 * (
|
||||
insideShape(createVector(0, y)) * pow(createVector(0, y).dist(origin) / width, 2)
|
||||
+ insideShape(createVector(width, y)) * pow(createVector(0, y).dist(origin) / width, 2)
|
||||
);
|
||||
|
||||
for(var i = 1; i <= samples - 1; i++)
|
||||
{
|
||||
var point = createVector(i * h, y);
|
||||
sum += insideShape(point) * pow(point.dist(origin) / width, 2)
|
||||
}
|
||||
|
||||
return h * sum;
|
||||
}
|
||||
|
||||
function momentOfInertia(samples)
|
||||
{
|
||||
var h = height / samples;
|
||||
var sum = 0.5 * (momentOfInertiaHelper(0, samples) + momentOfInertiaHelper(height, samples));
|
||||
|
||||
for(var i = 1; i <= samples - 1; i++)
|
||||
{
|
||||
sum += momentOfInertiaHelper(i * h, samples);
|
||||
}
|
||||
|
||||
return h * sum;
|
||||
}
|
||||
|
||||
function centerOfMassHelper(y, samples)
|
||||
{
|
||||
var origin = createVector(0, 0);
|
||||
|
||||
var h = width / samples;
|
||||
|
||||
var v0 = createVector(0, y);
|
||||
var vn = createVector(width, y);
|
||||
v0.mult(insideShape(v0));
|
||||
vn.mult(insideShape(vn));
|
||||
|
||||
var sum = v0;
|
||||
sum.add(vn);
|
||||
sum.mult(0.5);
|
||||
|
||||
for(var i = 1; i <= samples - 1; i++)
|
||||
{
|
||||
var point = createVector(i * h, y);
|
||||
point.mult(insideShape(point));
|
||||
sum.add(point);
|
||||
}
|
||||
|
||||
sum.mult(h);
|
||||
return sum;
|
||||
}
|
||||
|
||||
function centerOfMass(samples) {
|
||||
m = mass(samples);
|
||||
|
||||
var h = height / samples;
|
||||
var sum = centerOfMassHelper(0, samples);
|
||||
sum.add(centerOfMassHelper(height, samples));
|
||||
sum.mult(0.5);
|
||||
for(var i = 1; i <= samples - 1; i++)
|
||||
{
|
||||
sum.add(centerOfMassHelper(i * h, samples));
|
||||
}
|
||||
|
||||
sum.mult(h);
|
||||
sum.mult(1 / m);
|
||||
|
||||
L = sum.dist(attachPoint);
|
||||
var helper = createVector(attachPoint.x, attachPoint.y);
|
||||
helper.sub(sum);
|
||||
theta = helper.angleBetween(createVector(0, -1));
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
function simulate()
|
||||
{
|
||||
acc = -m*g*L*sin(theta) / inertia - 2 * vel;
|
||||
console.log(degrees(theta));
|
||||
vel += acc * deltaTime / 10000;
|
||||
var dtheta = theta;
|
||||
theta += vel * deltaTime / 10000;
|
||||
dtheta -= theta;
|
||||
dtheta *= -1;
|
||||
|
||||
points.forEach(function(item, index) {
|
||||
item.sub(attachPoint);
|
||||
item.rotate(-dtheta);
|
||||
item.add(attachPoint);
|
||||
});
|
||||
|
||||
centerMass.sub(attachPoint);
|
||||
centerMass.rotate(-dtheta);
|
||||
centerMass.add(attachPoint);
|
||||
}
|
||||
|
||||
function setup()
|
||||
{
|
||||
canvas = createCanvas(1400, 800);
|
||||
canvas.mouseClicked(handleClick);
|
||||
}
|
||||
|
||||
function draw()
|
||||
{
|
||||
background(10);
|
||||
|
||||
// Draw vertices
|
||||
fill(255, 50, 50);
|
||||
stroke(0, 0, 0, 0);
|
||||
points.forEach(function(item, index) {
|
||||
rect(item.x - 5, item.y - 5, 10, 10);
|
||||
});
|
||||
|
||||
// Draw lines between vertices
|
||||
stroke(255);
|
||||
points.forEach(function(item, index) {
|
||||
if(index !== points.length - 1)
|
||||
line(item.x, item.y, points[index + 1].x, points[index + 1].y);
|
||||
});
|
||||
|
||||
if(!shapeComplete)
|
||||
{
|
||||
// Draw "cursor"
|
||||
fill(255, 150, 150);
|
||||
var cursorPos = createVector(mouseX, mouseY);
|
||||
|
||||
if(points.length > 2)
|
||||
{
|
||||
if(cursorPos.dist(points[0]) < 20)
|
||||
{
|
||||
cursorPos = points[0];
|
||||
mouseSnap = true;
|
||||
}
|
||||
else
|
||||
mouseSnap = false;
|
||||
}
|
||||
|
||||
rect(cursorPos.x - 5, cursorPos.y - 5, 10, 10);
|
||||
}
|
||||
else
|
||||
{
|
||||
line(points[points.length - 1].x, points[points.length - 1].y, points[0].x, points[0].y);
|
||||
}
|
||||
|
||||
if(shapeComplete && !attachPointSelected)
|
||||
{
|
||||
fill(150, 255, 150);
|
||||
rect(mouseX - 5, mouseY - 5, 10, 10);
|
||||
}
|
||||
else if(attachPointSelected)
|
||||
{
|
||||
fill(50, 255, 50);
|
||||
rect(attachPoint.x - 5, attachPoint.y - 5, 10, 10);
|
||||
|
||||
fill(50, 50, 255);
|
||||
rect(centerMass.x - 5, centerMass.y - 5, 10, 10);
|
||||
|
||||
simulate();
|
||||
}
|
||||
}
|
||||
|
||||
function handleClick(event)
|
||||
{
|
||||
if(!shapeComplete)
|
||||
{
|
||||
if(!mouseSnap)
|
||||
{
|
||||
points.push(createVector(mouseX, mouseY));
|
||||
// console.log(points);
|
||||
}
|
||||
else
|
||||
{
|
||||
shapeComplete = true;
|
||||
inertia = momentOfInertia(100);
|
||||
console.log("Moment of inertia: " + inertia + " ML²");
|
||||
}
|
||||
}
|
||||
else if(!attachPointSelected)
|
||||
{
|
||||
attachPoint = createVector(mouseX, mouseY);
|
||||
attachPointSelected = true;
|
||||
centerMass = centerOfMass(100);
|
||||
// simulate();
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue