Examples

download zipped archive of all examples

Reading

  • Some links about vectors: Working with vectors, Describing Motion, Vectors: Velocities, Accelerations, and Forces
  • Mathematics and Physics for Programmers, Chapter 5 — Vectors, Danny Kodicek (suggested)
  • Hackers and Painters, Paul Graham
  • Two’s Company

    To animate an object in a virtual space, we need a way of storing information about the object’s location, movement, etc. In a two dimensional space (such as our computer screen), a location is expressed as an x and y coordinate. This pairing of two pieces of information is the essential building block for the systems we will create. We will have both “Points” and “Vectors”. A point represents a location and a vector represents the displacement between two points.

    Consider a rectangle moving across the screen. At any given instant it has the following:

  • Position — the object’s location, expressed in two dimensions as a point.
  • Velocity — the rate at which the object’s position changes per time unit, expressed as a two dimensional vector
  • Acceleration — the rate at which the object’s velocity changes per time unit, expressed as a two dimensional vector
  • Technically, Position is a point and Velocity/Acceleration are vectors. For our purposes, however, we will consider all three as vectors to simplify our coding (with the xy components of our location vector storing location coordinates instead of values for rate of change). Examine the following pseudo-ish code. Assume three vectors, velocity, acceleration, and location. This simple algorithm will form the basis for our first week examples.

    velocity = velocity + acceleration
    location = location + velocity
    draw thing @ location
    

    Since vectors represent pairs of values, we cannot simply use traditional addition/multiplication/etc. Instead, we’ll need to do some “vector” math.

    Assume vector v = (vx,vy), vector w,u, etc.

    u = v + w -->  ux = vx + wx, uy = vy + wy
    u = v - w -->  ux = vx - wx, uy = vy - wy
    

    Also, note that the algebraic rules for vectors are similar to real numbers:

    v + w = w + v (commutative)
    u + (v + w) = (u + v) + w (associative)
    

    For vectors, we also have scalar multiplication by a single real number (n & m below), i.e.

    v = w * n --> vx = wx * n, vy = wy * n
    v = w / n --> vx = wx / n, vy = wy / n
    (n*m)*v = n*(m*v)
    (n+m)*v = n*v + m*v
    n*(v+u) = n*v + n*u
    

    Vectors also have a dot product (or inner product), which is a means for comparing the direction of two vectors. We may examine dot product in a later class as it is not necessary for the current examples.

    A common operation we will need to perform is to compute the length (or magnitude) of a vector (for any vector v, length is often expressed as ||v||). This is done using the pythagorean theorem and can be expressed as follows:

    ||v|| = sqrt ( vx*vx + vy*vy )
    

    Once we have the magnitude of a vector, this allows us to normalize it, i.e. compute its unit vector (a vector with the same direction, but with a length of one.) Knowing the unit vector is very useful since it describes a vector’s direction w/o regard to length. For any given vector u, its unit vector (expressed as û) is calculated as follows:

    û = u / || u ||
    

    A Two (or is it 3?) Dimensional Vector Class

    Object Oriented Programming refers to art of breaking down a program into a set of self-contained parts. Before we can begin to code any simple physics / motion simulation, we need to create a template class to store the data and perform the calculations associated with a vector. Our first instinct might be to turn to the java class Vector. This class, though named Vector, refers to an expandable array of objects, and won’t do us any good.

    There is the package javax.vecmath — if you look at this package, you’ll find Point2D and Vector2D — importing this package into our processing projects and using these classes would give us what we need. However, for the purpose of better understanding how vectors work, we will develop our own code for this class (but you may choose not to use this class and import other java classes instead.)

    For a review of object oriented programming visit:
    http://www.processing.org/learning/tutorials/objects/ (more examples: Learning Processing.

    Our Vector class starts with declaring the instance variables for each Vector object (an x and y coordinate) as well as a constructor to fill the instance variables.

    public class PVector {
      public float x;
      public float y;
      public float z;
    
      PVector(float x_, float y_, float z_) {
        x = x_; y = y_; z = z_;
      }
    
      PVector(float x_, float y_) {
        x = x_; y = y_; z = 0f;
      }
    
      /**functionality to go here -- see below**/
    }
    
    Instance methods are methods that are tied to an actual instance of an object and can only be called via an object’s reference.
    PVector v1 = new PVector(0,1);
    PVector v2 = new PVector(1,0);
    v1.add(v2);

    Static methods make no use of the instance variables of any object of the class. They act like “global” methods for a class and are called directly via the class name, without first creating an object from the class.
    PVector v1 = new PVector(0,1);
    PVector v2 = new PVector(1,0);
    PVector v3 = PVector.add(v1,v2);

    Note the use of an overloaded constructor above. We have two constructors (methods with the same name: “PVector”). We would think that the compiler would be confused — how can you have two functions with the same name! It’s important to remember, however, that a method’s signature is not just its name, but its arguments (and return type while we’re at it) as well. Therefore, two functions with the same name with different arguments is allowed. Here it’s particularly useful since we can use the same PVector class for both 2D and 3D vectors. When we want a 2D vector, we just create one with only an ‘x’ and ‘y’ value. Behind the scenes, the PVector class manages the information for ‘z’, setting the value to zero (which will render it irrelevent for all calculations.)

    Once we’ve set up the constructor, we can start to implement functions that take care of the Vector math for us. Note the use of both static and non-static (instance) methods. We’ll use instance methods when we want to perform an operation on a specific instance of a PVector object, and static methods when we want to create a new PVector object from an operation.

      public float mag() {
        return (float) Math.sqrt(x*x + y*y + z*z);
      }
    
      public void add(PVector v) {
        x += v.x;
        y += v.y;
        z += v.z;
      }
    
      public static PVector add(PVector v1, PVector v2) {
        PVector v = new PVector(v1.x + v2.x,v1.y + v2.y, v1.z + v2.z);
        return v;
      }
    

    The full java source for the PVector class is here: PVector.java.

    Integrating with Processing

    There used to be a section here about integrating the concept of “PVector” with Processing. I’m pleased to announce that as of Processing 1.0, PVector is now built into Processing and named PVector. Documentation is here: http://www.processing.org/reference/PVector.html.

    Encapsulation

    Java supports different levels of access for variables (see: Controlling Access to Members of a Class). In the PVector class, for example, we have the option of making x and y private — from the java tutorial: “A private member is accessible only to the class in which it is defined. Use this access to declare members that should only be used by the class. This includes variables that contain information that if accessed by an outsider could put the object in an inconsistent state, or methods that, if invoked by an outsider, could jeopardize the state of the object or the program in which it’s running. Private members are like secrets you never tell anybody.”

    This is a questionable call here and we might choose to make x & y private. Indeed, one of the foundations of object oriented programming is “Encapsulation”. Making our instance variables private is good practice. By using encapsulation, the data associated with an object is hidden and the caller of that object deals only with its behaviors, not directly with the internal implementation. We can think of it more simply as “Never access your object’s data directly; use only its methods.”

    Consider a car as an object. Encapsulation would hide all the details associated with the car’s internal wiring, etc. so that we could just say things like “car.drive()” and “car.turn()”, etc. This gives us three advantages:

  • We don’t need to know the details of how an object works to operate it
  • If we change the way an object works (i.e. rewire a car, change its engine, etc.), we still use the same functionality with the car (car.drive() doesn’t change).
  • The caller of the car object cannot break the car if the details of the implementation cannot be accessed
  • Nevertheless, to keep things somewhat simple, it’s very convenient to keep the x, y, and z components of the Vector class public. We’ll consider this an exception, and try to make sure we practice good encapsulation techniques with our other classes. For example, with in the above Mouse interaction example, we only access the location, velocity, and acceleration methods of the class via methods. The PVector object is also always copied before it is taken out of the class, so that the reference to the actual PVector object itself cannot be manipulated. (The function for copy is get().)

    class Thing {
      // Using private now to encapsulate data
      private PVector loc;
      private PVector vel;
      private PVector acc;
      private float maxvel;
    
      // The Constructor (called when the object is first created)
      Thing(PVector a, PVector v, PVector l) {
        acc = a;
        vel = v;
        loc = l;
        maxvel = 8;
      }
    
      // Add functions to our thing object to access the location,
      // velocity and acceleration from outside the class
      PVector getVel() {
        return vel.get();
      }
    
      PVector getAcc() {
        return acc.get();
      }
    
      PVector getLoc() {
        return loc.get();
      }
    
      void setLoc(PVector v) {
        loc = v.get();
      }
    
      void setVel(PVector v) {
        vel = v.get();
      }
    
      void setAcc(PVector v) {
        acc = v.get();
      }
    

    3 Responses to “Vectors”  

    1. 1 Shaun

      Thanks for the great introduction into vector motion. I went through your examples and created an applet with an array of projectiles with fading dotted-line trails and gravity. I placed the acceleration arrow at the start of the velocity one since acceleration steers velocity. I’m in the process of writing a recursive collision function to keep the projectiles from being pushed out of the window. All in all, I learned a lot from your examples and I’m starting to branch off into many different topics of interest because of this. Thank you very much!

    2. 2 lenny

      very useful intro, thanks a lot.

    1. 1 Create Digital Motion » New Processing Libraries Added: Vector3D, xmlrpclib, 2 GUIs and ID3


    Leave a Reply