First commit, aggregated repos
This commit is contained in:
158
Orbital-Bodies/Matrix.java
Normal file
158
Orbital-Bodies/Matrix.java
Normal file
@@ -0,0 +1,158 @@
|
||||
/**
|
||||
* A simple m x n matrix class.
|
||||
*
|
||||
* TODO All of the methods currently just return default values. You need to make them match the Javadoc comments.
|
||||
*
|
||||
* @author YOUR NAME HERE
|
||||
* @version Sept. 2017
|
||||
*/
|
||||
|
||||
public class Matrix {
|
||||
|
||||
private int m, n;
|
||||
private double[][] M;
|
||||
|
||||
public Matrix(double[][] array) {
|
||||
M = array;
|
||||
m = array.length;
|
||||
n = array[0].length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The number of columns in the matrix.
|
||||
*/
|
||||
public int nCols() { return n; }
|
||||
|
||||
/**
|
||||
* @return the number of rows.
|
||||
*/
|
||||
public int nRows() { return m; }
|
||||
|
||||
/**
|
||||
* @param i
|
||||
* @param j
|
||||
* @return The entry at row i column j.
|
||||
*/
|
||||
public double entry(int i, int j) {
|
||||
return M[i][j];
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the dot product of this matrix with the parameter that. (Return value is this . that)
|
||||
* Recall that the dot product is the typical matrix multiplication.
|
||||
* @param that The matrix to apply this matrix to.
|
||||
* @throws BadDimensionException If this.nCols() != that.nRows() because the dot product is not defined
|
||||
* @return The dot product of this matrix with that.
|
||||
*/
|
||||
public Matrix dot(Matrix that) throws UndefinedMatrixOpException {
|
||||
if (this.nCols() != that.nRows()) {
|
||||
throw new UndefinedMatrixOpException("Dot product not defined", this, that);
|
||||
}
|
||||
|
||||
double[][] result = new double[this.nRows()][that.nCols()];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
for (int j = 0; j < result[i].length; j++) {
|
||||
double entry = 0;
|
||||
for (int k = 0; k < this.nCols(); k++) {
|
||||
entry += this.entry(i, k) * that.entry(k, j);
|
||||
}
|
||||
|
||||
result[i][j] = entry;
|
||||
}
|
||||
}
|
||||
|
||||
return new Matrix(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add this matrix to that and returns the result. (Return value is this + that)
|
||||
* @param that the matrix to add this matrix to.
|
||||
* @throws BadDimensionException If the dimension of the two matrices are not identical.
|
||||
* @return The sum of the this and that.
|
||||
*/
|
||||
public Matrix plus(Matrix that) throws UndefinedMatrixOpException {
|
||||
if (this.nRows() != that.nRows() || this.nCols() != this.nRows()) {
|
||||
throw new UndefinedMatrixOpException("Matrix dimensions are not identical", this, that);
|
||||
}
|
||||
|
||||
double[][] result = new double[this.nRows()][this.nCols()];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
for (int j = 0; j < result[i].length; j++) {
|
||||
result[i][j] = this.entry(i, j) + that.entry(i, j);
|
||||
}
|
||||
}
|
||||
|
||||
return new Matrix(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param theta The rotation angle.
|
||||
* @return The homogeneous rotation matrix for a given value for theta.
|
||||
*/
|
||||
public static Matrix rotationH2D(double theta) {
|
||||
double[][] R = {{Math.cos(theta), -Math.sin(theta), 0}, {Math.sin(theta), Math.cos(theta), 0}, {0, 0, 1}};
|
||||
return new Matrix(R);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param tx The amount to translate in the x direction.
|
||||
* @param ty The amount to translate in the y direction.
|
||||
* @return The matrix representing a translation of tx, ty.
|
||||
*/
|
||||
public static Matrix translationH2D(double tx, double ty) {
|
||||
double[][] T = {{1, 0, tx}, {0, 1, ty}, {0, 0, 1}};
|
||||
return new Matrix(T);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param x The x coordinate
|
||||
* @param y The y coordinate
|
||||
* @return The column matrix representing in homogeneous coordinates the point (x, y).
|
||||
*/
|
||||
public static Matrix vectorH2D(double x, double y) {
|
||||
double[][] V = {{x}, {y}, {1}};
|
||||
return new Matrix(V);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param n The dimension of the matrix. Recall that the identity matrix has 1's for any entry that is in the same row index as its column index, 0's everywhere else.
|
||||
* @return the nxn identity matrix
|
||||
*/
|
||||
public static Matrix identity(int n) {
|
||||
return identity(n, n);
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the mxn identity matrix which has 1's for every entry at the same row and column index and
|
||||
* 0 for all other entries.
|
||||
* @param m
|
||||
* @param n
|
||||
* @return the mxn identity matrix.
|
||||
*/
|
||||
public static Matrix identity(int m, int n) {
|
||||
|
||||
double[][] result = new double[m][n];
|
||||
for (int i = 0; i < m; i++) {
|
||||
for (int j = 0; j < n; j++) {
|
||||
result[i][j] = (i == j) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
return new Matrix(result);
|
||||
}
|
||||
|
||||
/**
|
||||
* A little helpful toString() in case you want to print your matrix to System.out
|
||||
*/
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < m; i++) {
|
||||
for (int j = 0; j < n; j++) {
|
||||
sb.append(M[i][j]);
|
||||
sb.append('\t');
|
||||
}
|
||||
sb.append('\n');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
141
Orbital-Bodies/Orbit.pde
Normal file
141
Orbital-Bodies/Orbit.pde
Normal file
@@ -0,0 +1,141 @@
|
||||
import java.util.*;
|
||||
import java.awt.*;
|
||||
|
||||
Orbiter sun; // The root orbiter
|
||||
int lastMillis;
|
||||
double[][] originM = {{0},{0},{1}};
|
||||
Matrix origin = new Matrix(originM);
|
||||
|
||||
// A few fun parameters
|
||||
boolean clearBackground = true;
|
||||
double speedModifier = 1.0; // Set in some of the scenes to change the speed.
|
||||
|
||||
// One default scene (selected in the setup() function
|
||||
void setupScene1() {
|
||||
|
||||
sun = new Orbiter(null, 0, 0, 0, Orbiter.Type.CIRCLE, Color.yellow);
|
||||
|
||||
Orbiter earth = new Orbiter(sun, 50, 0, 1, Orbiter.Type.CIRCLE, Color.blue);
|
||||
Orbiter moon = new Orbiter(earth, 30, 0, 1, Orbiter.Type.CIRCLE, Color.gray);
|
||||
Orbiter moonSatellite = new Orbiter(moon, 20, 0, 1, Orbiter.Type.CIRCLE, Color.gray);
|
||||
|
||||
Orbiter jupiter = new Orbiter(sun, 200, 0, 0.5, Orbiter.Type.CIRCLE, Color.red);
|
||||
Orbiter jupiterMoon = new Orbiter(jupiter, 75, 0, 2, Orbiter.Type.CIRCLE, Color.green);
|
||||
Orbiter jupiterExplorer = new Orbiter(jupiterMoon, 40, 0, -1, Orbiter.Type.SQUARE, Color.orange);
|
||||
Orbiter jupiterExplorerRobot = new Orbiter(jupiterExplorer, 20, 0, -3, Orbiter.Type.TRIANGLE, Color.magenta);
|
||||
}
|
||||
|
||||
// A second default scene
|
||||
void setupScene2() {
|
||||
speedModifier = 0.25;
|
||||
sun = new Orbiter(null, 0, 0, 0, Orbiter.Type.TRIANGLE, Color.yellow);
|
||||
|
||||
Orbiter earth = new Orbiter(sun, 50, 0, 10, Orbiter.Type.TRIANGLE, Color.blue);
|
||||
Orbiter moon = new Orbiter(earth, 30, 0, 20, Orbiter.Type.TRIANGLE, Color.gray);
|
||||
Orbiter moonSatellite = new Orbiter(moon, 20, 0, 30, Orbiter.Type.TRIANGLE, Color.gray);
|
||||
|
||||
Orbiter jupiter = new Orbiter(sun, 200, 0, 5, Orbiter.Type.TRIANGLE, Color.red);
|
||||
Orbiter jupiterMoon = new Orbiter(jupiter, 75, 0, 2, Orbiter.Type.TRIANGLE, Color.green);
|
||||
Orbiter jupiterExplorer = new Orbiter(jupiterMoon, 40, 0, 8, Orbiter.Type.TRIANGLE, Color.orange);
|
||||
Orbiter jupiterExplorerRobot = new Orbiter(jupiterExplorer, 20, 0, -6, Orbiter.Type.TRIANGLE, Color.magenta);
|
||||
}
|
||||
|
||||
// The setup. You don't need to edit this other than to switch scenes by commenting out
|
||||
// the setupScene1() and uncommenting setupScene2().
|
||||
void setup() {
|
||||
size(800, 800);
|
||||
background(0);
|
||||
setupScene1();
|
||||
//setupScene2(); // Run this one with clearBackground set to false
|
||||
lastMillis = millis();
|
||||
}
|
||||
|
||||
// The draw function
|
||||
// DO NOT EDIT
|
||||
void draw() {
|
||||
if (clearBackground) background(0); // Make the background black.
|
||||
|
||||
int currentMillis = millis(); // Get the current number of milliseconds
|
||||
int elapsedMillis = currentMillis - lastMillis; // Get the number of milliseconds elapsed since last call
|
||||
double timeDelta = elapsedMillis / 1000.0;
|
||||
|
||||
updateOrbiters(timeDelta * speedModifier);
|
||||
pushMatrix();
|
||||
scale(1, -1);
|
||||
translate(width / 2, - height / 2);
|
||||
drawOrbiters();
|
||||
popMatrix();
|
||||
|
||||
lastMillis = currentMillis;
|
||||
}
|
||||
|
||||
void updateOrbiters(double timeDelta) {
|
||||
Queue<Orbiter> queue = new LinkedList<Orbiter>();
|
||||
queue.add(sun);
|
||||
|
||||
while (!queue.isEmpty()) {
|
||||
Orbiter node = queue.remove();
|
||||
node.updateRotation(timeDelta);
|
||||
queue.addAll(node.getChildren());
|
||||
}
|
||||
// TODO
|
||||
// This code should traverse the orbiters (in BFS or DFS, but I used BFS)
|
||||
// order using a stack or a queue (your choice), and call updateRotation
|
||||
// on each one using the timeDelta parameter.
|
||||
//
|
||||
// Recall that Java has a Queue<T> data type and a Stack<T> interface
|
||||
|
||||
}
|
||||
|
||||
void drawOrbiters() {
|
||||
Queue<Orbiter> queue = new LinkedList<Orbiter>();
|
||||
queue.add(sun);
|
||||
|
||||
while (!queue.isEmpty()) {
|
||||
Orbiter node = queue.remove();
|
||||
drawOrbiter(node);
|
||||
queue.addAll(node.getChildren());
|
||||
}
|
||||
|
||||
// TODO
|
||||
// This code should traverse the orbiters (in BFS or DFS order, i used BFS)
|
||||
// and call drawOrbiter on each orbiter.
|
||||
|
||||
}
|
||||
|
||||
// The code for drawing an orbiter. This is called from your drawOrbiters() method
|
||||
// but you should not have to edit it.
|
||||
void drawOrbiter(Orbiter orbiter) {
|
||||
try {
|
||||
Matrix position = orbiter.getMatrix().dot(origin);
|
||||
|
||||
int px = (int) Math.round(position.entry(0,0) / position.entry(2,0));
|
||||
int py = (int) Math.round(position.entry(1,0) / position.entry(2,0));
|
||||
|
||||
// Draw the orbiter
|
||||
noStroke();
|
||||
fill(orbiter.getFillColor().getRed(), orbiter.getFillColor().getGreen(), orbiter.getFillColor().getBlue());
|
||||
switch (orbiter.getType()) {
|
||||
case CIRCLE:
|
||||
ellipse(px, py, 16, 16);
|
||||
break;
|
||||
case SQUARE:
|
||||
rect(px-4, py-4, 8, 8);
|
||||
break;
|
||||
case TRIANGLE:
|
||||
triangle(px, py+3, px-2, py-1, px+2, py-1);
|
||||
break;
|
||||
}
|
||||
noFill();
|
||||
|
||||
// Draw the orbit path
|
||||
if (clearBackground) {
|
||||
stroke(60);
|
||||
for (Orbiter child : orbiter.getChildren()) {
|
||||
int radius = (int) (2*child.getOrbitRadius());
|
||||
ellipse(px, py, radius, radius);
|
||||
}
|
||||
}
|
||||
} catch (UndefinedMatrixOpException umoe) {
|
||||
}
|
||||
}
|
||||
69
Orbital-Bodies/Orbiter.java
Normal file
69
Orbital-Bodies/Orbiter.java
Normal file
@@ -0,0 +1,69 @@
|
||||
import java.awt.Color;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* An Orbiter is an object that orbits some other object, called its parent.
|
||||
* The center of an orbital system is an Orbiter with no parent.
|
||||
* Each Orbiter may have child Oribters that orbit it.
|
||||
*
|
||||
* An Orbiter stores its orbital radius and current orbit angle.
|
||||
*/
|
||||
|
||||
public class Orbiter {
|
||||
|
||||
public enum Type {
|
||||
CIRCLE, SQUARE, TRIANGLE
|
||||
}
|
||||
|
||||
private final double orbitRadius;
|
||||
private final Type type;
|
||||
private final Color fillColor;
|
||||
private double orbitAngle;
|
||||
private double orbitSpeed;
|
||||
|
||||
private final List<Orbiter> children = new LinkedList<Orbiter>();
|
||||
private final Orbiter parent;
|
||||
|
||||
public Orbiter(Orbiter parent, double orbitRadius, double orbitAngle, double orbitSpeed, Type type, Color fillColor) {
|
||||
this.orbitRadius = orbitRadius;
|
||||
this.orbitAngle = orbitAngle;
|
||||
this.type = type;
|
||||
this.fillColor = fillColor;
|
||||
this.parent = parent;
|
||||
this.orbitSpeed = orbitSpeed;
|
||||
if (parent != null) parent.children.add(this);
|
||||
}
|
||||
|
||||
public double getOrbitRadius() { return orbitRadius; }
|
||||
public double getOrbitAngle() { return orbitAngle; }
|
||||
public Color getFillColor() { return fillColor; }
|
||||
public Type getType() { return type; }
|
||||
public Orbiter getParent() { return parent; }
|
||||
public List<Orbiter> getChildren() { return children; }
|
||||
|
||||
/**
|
||||
* Updates the rotation of this orbiter by the amount specified in the deltaAngle parameter.
|
||||
* @param deltaAngle The amount of rotation angle to add the to the current rotation.
|
||||
*/
|
||||
public void updateRotation(double timeDelta) {
|
||||
orbitAngle += (timeDelta * orbitSpeed);
|
||||
}
|
||||
|
||||
public Matrix getMatrix() throws UndefinedMatrixOpException {
|
||||
if (parent == null) {
|
||||
return Matrix.identity(3);
|
||||
}
|
||||
|
||||
Matrix local = Matrix.rotationH2D(orbitAngle).dot(Matrix.translationH2D(orbitRadius, 0));
|
||||
|
||||
return this.parent.getMatrix().dot(local);
|
||||
|
||||
|
||||
// TODO
|
||||
// If this is the root node, then return the 3x3 identity matrix
|
||||
// If this is not the root node, should return the transformation
|
||||
// matrix for this orbiter (see the writeup for an idea of how to
|
||||
// do this). Make sure you've coded the Matrix class first.
|
||||
|
||||
}
|
||||
}
|
||||
14
Orbital-Bodies/UndefinedMatrixOpException.java
Normal file
14
Orbital-Bodies/UndefinedMatrixOpException.java
Normal file
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Thrown when a matrix oepration is applied to matrices of the wrong size.
|
||||
*
|
||||
* You don't need to edit this.
|
||||
*/
|
||||
|
||||
public class UndefinedMatrixOpException extends Exception {
|
||||
|
||||
|
||||
public UndefinedMatrixOpException(String message, Matrix m1, Matrix m2) {
|
||||
super(message + "\nMatrix 1: " + m1 + "\n\nMatrix 2: " + m2);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user