/* This is our class to represent a pendulum and it's motion. This is a .pde file, instead of a .java file, because the Pendulum class needs to use the Processing methods for drawing to the screen and tracking mouse movement. */ class Pendulum { // Our pendulum uses a vector to calculate the location // of the ball at the end of the pendulum arm Vector2D loc; // Another vector keeps track of the fulcrum of the pendulum; // the fixed point from which it swings. Vector2D fulcrum; // We'll be working in polar coordinates for our // pendulum motion, so keep track of our radius // and our movement of theta float r; float theta; float theta_vel; float theta_accel; // The size of the ball float ballr; // Arbitrary dampening effect so the pendulum slows down float dampen; // Is the user dragging the pendulum? boolean dragging; // Construct a basic pendulum, with a lot of values // auto generated Pendulum(Vector2D origin_, float r_) { // store the fixed point of the pendulum fulcrum = origin_; // the length of the pendulum arm r = r_; // setup our theta values theta = 0.0f; theta_vel = 0.0f; theta_accel = 0.0f; // figure out the initial position of the ball float x = r * sin(theta); float y = r * cos(theta); // create the location vector describing the ball loc = new Vector2D(fulcrum.getX() + x, fulcrum.getY() + y); // finish off creating our settings dampen = 0.995f; ballr = 20.0f; dragging = false; } void simulate() { // update the position of the pendulum update(); // calculate any effects of the user dragging the pendulum drag(); // draw the pendulum to the screen render(); } void update() { // We'll only move the pendulum if the user // isn't dragging the pendulum if (!dragging) { // use an arbitrary value for gravity float G = 0.4; // calculate the angular acceleration due to gravity theta_accel = (-1 * G / r) * sin(theta); // apply the acceleration to our movement theta_vel += theta_accel; theta_vel *= dampen; theta += theta_vel; } // recalculate our position loc.setX(r * sin(theta)); loc.setY(r * cos(theta)); loc = loc.add(fulcrum); } void render() { // first we draw the line of the pendulum stroke(255, 50); line(fulcrum.getX(), fulcrum.getY(), loc.getX(), loc.getY()); // now draw the ball of the pendulum ellipseMode(CENTER); fill(200); // change the color of the ball if it is being dragged if (dragging) fill(32, 64, 128); noStroke(); ellipse(loc.getX(), loc.getY(), ballr, ballr); } /* The remaining functions deal with dragging the pendulum */ void clicked(int mx, int my) { // We're dragging the pendulum if the mouse is within the radius // of the ball float distance = dist(mx, my, loc.getX(), loc.getY()); if (distance < ballr) { dragging = true; } } void stopDragging() { dragging = false; } void drag() { // calculate the position the ball has been dragged too using // the arctangent, which determines the angle between the fulcrum // and the current mouse position if (dragging) { Vector2D diff = Vector2D.subtract(fulcrum, new Vector2D(mouseX, mouseY)); theta = atan2(-1 * diff.getY(), diff.getX()) - radians(90); } } }