use multithreading to complete this please include comments
use multithreading to complete this, please include comments if at all possible
For this problem you will need to create a GUI that allows a user to see a planet orbiting around a star. You will need to use the Java Swing components, as well as the ExecutorService so that your application is multithreaded.Solution
You can use this code to complete your application:-
Create file SolarSystem.java
compile it by javac -Xlint SolarSystem.java
Run java SolarSystem
import java.awt.*;
import java.awt.geom.*;
import javax.swing.*;
import javax.swing.event.*;
import java.util.*;
import java.awt.event.*;
import java.io.*;
/**
* This class is used to make the spatial coordinates more transparent.
*/
class Coord {
/**
* X represents the horizontal dimension which is measured from LHS
* of GUI. Y represents the vertical dimension which is measured
* from top of GUI.
*/
public static final byte X = 1, Y = 0;
}
/**
* Main entry into program. Creates GUI and repaints it in infinite loop.
*/
public class SolarSystem {
/**
* The time increment for numerical integration of differential equations
* governing motion in the solar system.
*/
private static double dt = 0.001;
/**
* Default constructor.
*/
public SolarSystem() { }
/**
* Main entry point into program. User may input number of planets
* on command line.
*/
public static void main(String[] arguments) {
SkyFrame skyFrame;
int numOfPlanets = 9;
if (arguments.length == 0)
skyFrame = new SkyFrame(numOfPlanets, dt);
else {
if (arguments[0].equals(\"h\")) {
System.exit(1);
skyFrame = new SkyFrame(0, 0);
}
try {
numOfPlanets = Integer.parseInt(arguments[0]);
numOfPlanets = (int)Math.abs(numOfPlanets);
skyFrame = new SkyFrame(numOfPlanets, 0);
}
catch(Exception e) {
System.err.println(e.toString());
System.exit(0);
skyFrame = new SkyFrame(0, 0);
}
}
while (true) {
skyFrame.getPanel().repaint();
}
}
/**
* The method getColor is used by the sattelites of the solar system
* to get their color.
*/
public static Color getColor(int i) {
Color color;
int j = i%8;
switch(j) {
case 0 : color = Color.red;
break;
case 1: color = Color.blue;
break;
case 2 : color = Color.green;
break;
case 3 : color = Color.pink;
break;
case 4: color = Color.orange;
break;
case 5: color = Color.cyan;
break;
case 6 : color = Color.magenta;
break;
case 7 : color = Color.lightGray;
break;
default : color = Color.gray;
}
return color;
}
}
/**
* Class Stars defines a group of stars that are displayed at random
* locations. The stars are yellow circles that change diameter to simulate
* twinlking.
*/
class Stars {
/**
* Coordinates of the stars relative to the Sun\'s position.
*/
private double[] xPos, yPos;
/**
* Initial diameter of the stars.
*/
private double diameter = 5;
/**
* Number of stars.
*/
private int numOfStars;
/**
* The Sun at the center of the solar system.
*/
private Sun sun;
public Stars(int mNumOfStars,
double maxRadius,
double minRadius,
Sun mSun) {
numOfStars = (int)Math.abs(mNumOfStars);
xPos = new double[numOfStars];
yPos = new double[numOfStars];
maxRadius = Math.abs(maxRadius);
minRadius = Math.abs(minRadius);
sun = mSun;
if (minRadius == 0)
minRadius += sun.getDiameter();
//
// Chose positions for each star at random between max and min radius.
//
for (int i = 0; i < numOfStars; ++i) {
xPos[i] = (float)Math.random()*maxRadius;
float yMin = xPos[i] > minRadius ?
0 :
(float)Math.sqrt(minRadius*minRadius - xPos[i]*xPos[i]);
float yMax = (float)Math.sqrt(maxRadius*maxRadius -
xPos[i]*xPos[i]);
yPos[i] = (float)Math.random()*(yMax - yMin) + yMin;
if (Math.random() > 0.5)
xPos[i]*= -1;
if (Math.random() > 0.5)
yPos[i]*= -1;
}
}
/**
* The method draw displays the stars.
*/
public void draw(Graphics2D comp2D) {
comp2D.setColor(Color.yellow);
//
// Make stars twinkle by chosing random diameter for each star.
//
for (int i = 0; i < numOfStars; ++i) {
double actualDia = diameter*Math.random();
Ellipse2D.Double starShape =
new Ellipse2D.Double(xPos[i]/
SkyFrame.getScaleFactor() +
sun.getAbsPos(Coord.X),
yPos[i]/SkyFrame.getScaleFactor() +
sun.getAbsPos(Coord.Y),
actualDia,
actualDia);
comp2D.fill(starShape);
}
}
}
/**
* The interface host defines the interface needed for an object to serve
* as a host about which a satellite may orbit.
*/
interface Host {
/**
* The method getAbsPos calculates the absolute position of the
* Host. This is the position used to display the Host
* and is taken with respect to the upper left corner of the display.
*/
public double getAbsPos(byte mAxis);
/**
* The method getMass returns the mass of the Host in arbitrary
* units.
*/
public double getMass();
}
/**
* The abstract class Satellite defines satellites that orbit about a Sun.
*/
abstract class Satellite implements Host{
/**
* The x and y coordinates of the Satellite\'s position.
*/
protected double xPos, yPos;
/**
* The x and y components of the Satellite\'s velocity.
*/
protected double xVel = 0, yVel = 0;
/**
* The x and y components of the Satellite\'s acceleration.
*/
protected double xAcc = 0, yAcc = 0, dt;
/**
* The diameter of the Satellite.
*/
protected double diameter;
/**
* The mass of the Satellite (arb. units).
*/
protected double mass;
/**
* The color of the Satellite
*/
protected final Color color;
/**
* The Host about which the Satellite orbits.
*/
protected Host host;
/**
* Constructor for Satellite objects.
*/
public Satellite(double mDt,
double mDiameter,
double mRadius,
Color mColor,
double mMass,
Host mHost){
dt = mDt;
diameter = mDiameter;
mass = mMass;
color = mColor;
host = mHost;
//
// The satellite\'s coordinates (xPos, yPos) relative to the
// coordinates of the host satellite.
//
xPos = Math.random()*mRadius;
yPos = Math.sqrt(mRadius*mRadius - xPos*xPos);
//
// Choose at random from the four Cartesian quadrants for the
// intial position.
//
if (probOneHalf())
xPos*= -1;
if (probOneHalf())
yPos*= -1;
}
/**
* The method probOneHalf returns true with probability 1/2, otherwise
* returns false.
*/
protected boolean probOneHalf() {
return Math.random() > 0.5;
}
/**
* The method getAbsPos calculates the absolute position of the
* Satellite. This is the position used to display the Satellite
*/
public double getAbsPos(byte mAxis) {
if (mAxis == Coord.X)
return xPos/SkyFrame.getScaleFactor() + host.getAbsPos(mAxis);
else
return yPos/SkyFrame.getScaleFactor() + host.getAbsPos(mAxis);
}
/**
* The getRelPosScaled calculate the relative position of the Satellite
* scaled by the scale factor of the SkyFrame.
*/
protected double getRelPosScaled(byte mAxis) {
if (mAxis == Coord.X)
return xPos/SkyFrame.getScaleFactor();
else
return yPos/SkyFrame.getScaleFactor();
}
/**
* The method getRelPosUnscaled calculates the relative position of
* the Satellite without scaling.
*/
protected double getRelPosUnscaled(byte mAxis) {
if (mAxis == Coord.X)
return xPos;
else
return yPos;
}
/**
* The method getTheta returns the angular position of the Satellite.
*/
public double getTheta() {
double theta = Math.atan(yPos/xPos);
if (xPos < 0)
theta = Math.PI + theta;
else if (xPos > 0 && yPos < 0)
theta = 2*Math.PI + theta;
return theta;
}
/**
* The method getVel calculates a Cartesian component of the Satellite\'s
*/
public double getVel(byte mAxis) {
if (mAxis == Coord.X)
return xVel;
else
return yVel;
}
/**
* The method getAcc calculates a Cartesian component of the Satellite\'s
*/
public double getAcc(byte mAxis) {
if (mAxis == Coord.X)
return xAcc;
else
return yAcc;
}
/**
* The abstract method translate calculates the displacement of the
* Satellite as a function of time and updates the Satellite\'s
* coordinates xPos and yPos.
*/
public abstract void translate();
/**
* The method getDiameter returns the Satellite\'s diameter.
*/
public double getDiameter() {
return diameter;
}
/**
* The method getColor returns the Satellite\'s color.
*/
public Color getColor() {
return color;
}
/**
* The method getMass returns the Satellite\'s mass (arb. units).
*/
public double getMass() {
return mass;
}
/**
* The method draw displays the Satellite.
*/
public void draw(Graphics2D comp2D) {
double zoomedDiameter = diameter/SkyFrame.getScaleFactor();
Ellipse2D.Double form =
new Ellipse2D.Double((int)(getAbsPos(Coord.X) - zoomedDiameter/2),
(int)(getAbsPos(Coord.Y) - zoomedDiameter/2),
(int)zoomedDiameter,
(int)zoomedDiameter);
comp2D.setColor(color);
comp2D.fill(form);
}
}
/**
* Class Planet extends Satellite @see Satellite and implements the planets
* that revolve about the Sun @see Sun. A Planet is given an initial
* position and velocity and follows Newton\'s laws of motion.
*/
class Planet extends Satellite {
/**
* An array of int\'s used to indicate the previous positions of the planet.
* Used to plot the trajectory of the planet. The array is filled and
* the index of the current position is tracked.
*/
private int[] prevXPos, prevYPos;
/**
* Used to index into the position arrays to indicate the current position
* of the planet.
*/
private int currPosition = 0;
/**
* Counts the number of transaltions the Planet undergoes.
*/
private int count = 0;
/**
* Determines the number of translations between which the position of
* the Planet is recorded.
*/
private int recordPosition = 5;
/**
* Indicates when we must loop back to the beginning of the previous
* position array
*/
private boolean looped = false;
/**
* The maximum number of previous positions that are recorded.
*/
private final int maxPrevPositions = 128;
/**
* Total energy of the planet.
*/
private final double TE;
/**
* The actual number of moons orbiting around the planet.
*/
private final byte numOfMoons;
/**
* The maximum number of moons that may orbit around the planet.
*/
private final byte maxNumOfMoons = 4;
/**
* The array of moons that orbit around the planet.
*/
private Moon[] moon;
/**
* The panel in which the planet is displayed.
*/
private SkyPanel hostPanel;
public Planet(double mDt,
double mDiameter,
double mRadius,
Color mColor,
double mMass,
SkyPanel mHostPanel,
Host mHost ){
super(mDt, mDiameter, mRadius, mColor, mMass, mHost);
hostPanel = mHostPanel;
prevXPos = new int[maxPrevPositions];
prevYPos = new int[maxPrevPositions];
for (int i = 0; i < maxPrevPositions; ++i)
prevXPos[i] = prevYPos[i] = 0;
numOfMoons = (byte)(Math.random()*maxNumOfMoons);
if (numOfMoons > 0) {
moon = new Moon[numOfMoons];
for (int i = 0; i < numOfMoons; ++i)
moon[i] = new Moon(dt, // Time increment for calculating motion.
Math.random()*6 + 3, // Moon\'s diameter.
diameter*(1 + 0.2*Math.random()),// Radius of orbit.
this); // Host about which moon orbits.
}
double distToHost = Math.sqrt(getRelPosUnscaled(Coord.X)*
getRelPosUnscaled(Coord.X) +
getRelPosUnscaled(Coord.Y)*
getRelPosUnscaled(Coord.Y));
//
// For calculating the force due to gravity, we set the universal
// gravitational constant to one (or incorporate it into the sun\'s
// mass).
//
double forceDueToGravity = host.getMass()*mass/
(distToHost*distToHost);
double theta = getTheta();
//
// The following formula for the velocity ensures that the
// planet\'s initial motion about the sun is circular.
//
yVel = Math.sqrt(host.getMass()/distToHost)*
Math.sin(theta + Math.PI/2);
xVel = Math.sqrt(host.getMass()/distToHost)*
Math.cos(theta + Math.PI/2);
xAcc = forceDueToGravity*Math.cos(theta + Math.PI)/mass;
yAcc = forceDueToGravity*Math.sin(theta + Math.PI)/mass;
//
// Record the initial total energy of planet.
//
TE = mass*(xVel*xVel + yVel*yVel)/2 +
mass*Math.sqrt(xAcc*xAcc + yAcc*yAcc)*distToHost;
}
/**
* The method translate calculates the motion of the planet by numerically
* integrating Newton\'s laws of motion.
*/
public void translate() {
double force, distToHost, theta;
for (int i = 0; i < 1/dt; ++i) {
distToHost = Math.sqrt(getRelPosUnscaled(Coord.X) *
getRelPosUnscaled(Coord.X) +
getRelPosUnscaled(Coord.Y) *
getRelPosUnscaled(Coord.Y));
force = mass*host.getMass()/(distToHost*distToHost);
theta = getTheta();
//
// Calculate new acceleration.
//
xAcc = force*Math.cos(theta + Math.PI)/mass;
yAcc = force*Math.sin(theta + Math.PI)/mass;
//
// Calculate new position using the original velocity.
//
xPos+= xVel*dt + dt*dt*xAcc/2;
yPos+= yVel*dt + dt*dt*yAcc/2;
//
// Calculate new velocity.
//
xVel+= xAcc*dt;
yVel+= yAcc*dt;
if (hostPanel.showPos())
recordPosition();
//
// Translate the moons orbiting around the planet.
//
for (int j = 0; j < numOfMoons; ++j)
moon[j].translate();
}
}
/**
* The method recordPosition records the current position of the planet
* in the arrays prevXPos and prevYPos.
*/
private void recordPosition() {
if (++count > (int)(recordPosition/dt)) {
count = 0;
if (currPosition == maxPrevPositions) {
currPosition = 0;
looped = true;
}
prevXPos[currPosition] = (int)getRelPosUnscaled(Coord.X);
prevYPos[currPosition++] = (int)getRelPosUnscaled(Coord.Y);
}
}
/**
* The method getKE returns the kinetic energy of the planet in arbitrary
* units.
*/
public double getKE() {
return mass*(xVel*xVel + yVel*yVel)/2;
}
/**
* The method getPE returns the potential energy of the planet in arbitrary
* units.
*/
public double getPE() {
return mass*Math.sqrt(xAcc*xAcc + yAcc*yAcc)*
Math.sqrt(xPos*xPos + yPos*yPos);
}
/**
* The method getTE returns the total energy of the planet in arbitrary
* units.
*/
public double getTE() {
return TE;
}
/**
* The method draw displays the Planet in scaled units of pixels.
*/
public void draw(Graphics2D comp2D) {
double zoomedDiameter = diameter/SkyFrame.getScaleFactor();
//
// Draw the night-time semi-circle of the planet.
//
comp2D.setColor(Color.darkGray);
comp2D.fill(semiCircle(getAbsPos(Coord.X),
getAbsPos(Coord.Y),
zoomedDiameter,
getTheta() + 3*Math.PI/2));
//
// Draw the day-time semi-circle of the planet.
//
comp2D.setColor(color);
comp2D.fill(semiCircle(getAbsPos(Coord.X),
getAbsPos(Coord.Y),
zoomedDiameter,
getTheta() + Math.PI/2 ));
//
// Show previous positions of the planet if requested by hostPanel.
//
if (hostPanel.showPos())
drawPrevPositions(comp2D);
//
// Draw the moons orbiting around the planet.
//
for (int i = 0; i < numOfMoons; ++i)
moon[i].draw(comp2D);
}
/**
* The method drawPrevPositions draws the previous positions of the planet
* by placing dots to indicate it\'s path.
* @param comp2D The Graphics2D object used for the display.
*/
private void drawPrevPositions(Graphics2D comp2D) {
int end;
int x, y;
if (looped)
end = maxPrevPositions;
else
end = currPosition;
for (int i = 0; i < end; ++i) {
x = prevXPos[i]/SkyFrame.getScaleFactor() +
(int)host.getAbsPos(Coord.X);
y = prevYPos[i]/SkyFrame.getScaleFactor() +
(int)host.getAbsPos(Coord.Y);
comp2D.fill( new Ellipse2D.Float(x, y, 1, 1));
}
}
/**
* The method erasePrevPostions removes the dots indicating the previous
* position of the planet from the screen.
*/
public void erasePrevPositions() {
looped = false;
currPosition = 0;
count = 0;
}
/**
* The method semiCircle is used to draw a day-time and night-time
* semi-circle of the planet with respect to the Host about which
* the planet orbits.
*/
private Area semiCircle(double x, double y, double dia, double theta) {
double xp = x - dia/2;
double yp = y - dia/2;
Ellipse2D.Double circle = new Ellipse2D.Double(xp, yp, dia, dia);
Rectangle2D.Double rect = new Rectangle2D.Double(xp, yp, dia, dia/2);
Area semiCircleArea = new Area(circle);
Area rectArea = new Area(rect);
semiCircleArea.subtract(rectArea);
semiCircleArea.transform(AffineTransform.
getRotateInstance(theta, x, y));
return semiCircleArea;
}
}
/**
* The class Moon defines a moon which executes pure circular motion about
* it\'s host, so the formulas for calculating position are simplified compared
* to those used for calculating planetary motion about the sun.
*/
class Moon extends Satellite {
/**
* Constructor.
*/
public Moon(double mDt,
double mDiameter,
double mRadius,
Host mHost)
{
super(mDt, mDiameter, mRadius, Color.lightGray, (double)1, mHost);
}
/**
* The method translate calculates the motion of the moon. Since moons
* are only allowed to undergo circular motion, the calculation is
* simplified compared to planetary motion.
*/
public void translate() {
double r, theta;
//
// Find radial position of moon.
//
r = Math.sqrt(getRelPosUnscaled(Coord.X)*getRelPosUnscaled(Coord.X) +
getRelPosUnscaled(Coord.Y)*getRelPosUnscaled(Coord.Y));
//
// Calculate new angular position which is old old angular position
// plus speed multiplied by delta t. The number 1000 is an arbitrary
// number chosen to give the moons a convenient angular speed of orbit
// (it is not related to any othe part of the program).
//
theta = getTheta() + Math.sqrt(1000*host.getMass()/(r*r*r))*dt;
//
// Convert angular position to Cartesian coordiantes.
//
xPos = r*Math.cos(theta);
yPos = r*Math.sin(theta);
}
}
/**
* The class Sun extends Satellite @see Satellite and defines the origin
* about which all planets orbit in the solar system. It is yellow and
* has rays of random length eminatting from it.
*/
class Sun extends Satellite {
public Sun(double mDiameter,
double mMass,
double mXPos,
double mYPos) {
super((double)1,
mDiameter,
(double)0,
Color.yellow,
mMass,
(Host)null);
xPos = mXPos;
yPos = mYPos;
}
/**
* The method getAbsPos returns the absolute position of the Sun in pixels.
*/
public double getAbsPos(byte mAxis) {
if (mAxis == Coord.X)
return xPos;
else
return yPos;
}
/**
* The methos setMass allows the user to set the mass of the sun in order
* to observe the effects on planetary motion. The mass is measured in
* arbitray units.
*/
public void setMass(double newMass) {
diameter*=newMass/mass;
mass = newMass;
}
/**
* The method draw displays the Sun in scaled units of pixels.
* Sun.
*/
public void draw(Graphics2D comp2D) {
super.draw(comp2D);
BasicStroke pen = new BasicStroke(2F);
comp2D.setStroke(pen);
double xf, yf;
double zoomedDiameter = diameter/SkyFrame.getScaleFactor();
//
// Draw rays of sun.
//
for (int i = 0; i < 10; ++i) {
if (probOneHalf())
xf = xPos+ Math.random()*zoomedDiameter*1.5;
else
xf = xPos - Math.random()*zoomedDiameter*1.5;
if (probOneHalf())
yf = yPos + Math.random()*zoomedDiameter*1.5;
else
yf = yPos - Math.random()*zoomedDiameter*1.5;
Line2D.Double ray = new Line2D.Double(xPos,
yPos,
xf,
yf);
}
}
public void translate() {} // Sun does not move.
}












