com.google.gwt.sample.guestbook.client.Orbital.java Source code

Java tutorial

Introduction

Here is the source code for com.google.gwt.sample.guestbook.client.Orbital.java

Source

package com.google.gwt.sample.guestbook.client;

import java.util.ArrayList;

import com.google.gwt.user.client.Timer;

public class Orbital {
    interface OrbitalObserver {
        void orbiterMovedTo(double x, double y);

        void numberOfBodiesChanged(Mass[] bodies);
    }

    class Mass {
        double x;
        double y;
        double v_x;
        double v_y;
        int mass;
    }

    enum BodyNumber {
        ONE, TWO
    }

    static final double G = 25;
    //    static final double G = 6.67;
    static final double MAX_FORCE = 0.8;
    static final int TIME_STEP = 1;
    private double dragCoefficient = 0.995;
    private final int width, height;
    Mass b1 = new Mass();
    Mass b2 = new Mass();
    Mass orbiter = new Mass();
    Mass[] bodies = new Mass[] { b1, b2 };
    private Timer timer;
    int itrCount = 0;
    private boolean isForceInversed = false;
    ArrayList<OrbitalObserver> observers = new ArrayList<OrbitalObserver>();

    public Orbital(int width, int height) {
        this.width = width;
        this.height = height;
        orbiter.mass = 1;
        setBodyNumber(BodyNumber.ONE);
        init();
        timer = new Timer() {
            @Override
            public void run() {
                iterate();
            }

        };
    }

    public void init() {
        orbiter.x = 0.5 * width;
        orbiter.y = 0.6 * height;
        orbiter.v_x = 0.006 * width;
        orbiter.v_y = 0;
    }

    public void setEnabled(boolean isEnabled) {
        if (isEnabled) {
            timer.scheduleRepeating(25);
        } else {
            timer.cancel();
        }
    }

    public void getOrbiterLocation(double[] coords) {
        if (coords.length < 2) {
            return;
        }
        coords[0] = orbiter.x;
        coords[1] = orbiter.y;
    }

    public Mass[] getBodies() {
        return bodies;
    }

    public void setBodyNumber(BodyNumber bodyNumber) {
        switch (bodyNumber) {
        case ONE:
            bodies = new Mass[1];
            bodies[0] = new Mass();
            bodies[0].x = (int) (0.5 * width);
            bodies[0].y = (int) (0.5 * width);
            bodies[0].mass = 125;
            break;
        case TWO:
            bodies = new Mass[2];
            bodies[0] = new Mass();
            bodies[0].x = (int) (0.3 * width);
            bodies[0].y = (int) (0.5 * width);
            bodies[0].mass = 125;
            bodies[1] = new Mass();
            bodies[1].x = (int) (0.7 * width);
            bodies[1].y = (int) (0.5 * width);
            bodies[1].mass = 125;
            break;
        }
        for (OrbitalObserver observer : observers) {
            observer.numberOfBodiesChanged(bodies);
        }
    }

    public void setDragCoefficient(double milliDragCoefficient) {
        if (milliDragCoefficient > 0.9999) {
            dragCoefficient = 0.9999;
        } else if (milliDragCoefficient < 0.9900) {
            dragCoefficient = 0.9900;
        } else {
            dragCoefficient = milliDragCoefficient;
        }
    }

    public double getDragCoefficient() {
        return dragCoefficient;
    }

    public void setInverseForce(boolean isInversed) {
        isForceInversed = isInversed;
    }

    public synchronized void iterate() //Synchronised irrelevant in GWT (single threaded).
    {
        double[] force = new double[] { 0, 0 };
        double[] addedForce = new double[2];
        for (Mass body : bodies) {
            calcAcceleration(orbiter, body, addedForce);
            force[0] += addedForce[0];
            force[1] += addedForce[1];
        }
        orbiter.x += (orbiter.v_x * TIME_STEP) + (0.5 * force[0] * Math.pow(TIME_STEP, 2));
        orbiter.y += (orbiter.v_y * TIME_STEP) + (0.5 * force[1] * Math.pow(TIME_STEP, 2));
        orbiter.v_x += force[0] * TIME_STEP;
        orbiter.v_y += force[1] * TIME_STEP;
        orbiter.v_x *= dragCoefficient;
        orbiter.v_y *= dragCoefficient;
        for (OrbitalObserver observer : observers) {
            observer.orbiterMovedTo(orbiter.x, orbiter.y);
        }
    }

    private void calcAcceleration(Mass actedOn, Mass actedBy, double[] force_vect) {
        double offset_x = actedBy.x - actedOn.x;
        double offset_y = actedBy.y - actedOn.y;
        double distance = Math.sqrt(Math.pow(offset_x, 2) + Math.pow(offset_y, 2));
        double force = (G * actedOn.mass * actedBy.mass) / Math.pow(distance, 2);
        force = isForceInversed ? 1 / force : force;
        if (force > MAX_FORCE) {
            force = MAX_FORCE;
        }
        if (force < -MAX_FORCE) {
            force = -MAX_FORCE;
        }
        double force_x = (force / distance) * offset_x;
        double force_y = (force / distance) * offset_y;
        force_vect[0] = force_x / actedOn.mass;
        force_vect[1] = force_y / actedOn.mass;
    }

    public void addObserver(OrbitalObserver observer) {
        observers.add(observer);
    }
}