October 2016 Revision
parent
8926fbae33
commit
50dba493ff
@ -1,2 +1,2 @@
|
||||
java -jar simulator.jar
|
||||
java -jar simulator.jar > log.txt
|
||||
pause
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,10 +1,33 @@
|
||||
package com.verictas.pos.simulator;
|
||||
|
||||
public class SimulatorConfig {
|
||||
// The amount of rounds and the time step
|
||||
public static int rounds = 525960;
|
||||
public static double time = 60; // in seconds
|
||||
/**
|
||||
* Time settings
|
||||
*/
|
||||
|
||||
// Set the skipLines integer to skip lines (for example: every 5th line is written) in the output file (for smaller files), if this is set to 1, it has no effect and all lines will be written.
|
||||
public static int skipLines = 5;
|
||||
public static int rounds = 526100 * 35 * 60; // Amount of rounds to run the simulator for
|
||||
public static double time = 1; // Time steps in seconds
|
||||
|
||||
/**
|
||||
* Object settings
|
||||
*/
|
||||
|
||||
public static String sunName = "Sun"; // The name of the sun to calculate values TO
|
||||
public static String[] objectNames = { "Earth" }; // The name of the object(s) your want to calculate the values OF
|
||||
|
||||
/**
|
||||
* Ascending & descending node detection
|
||||
*/
|
||||
|
||||
public static double z = -22439680.6; // Reference z height for the used system in meters
|
||||
public static double zThreshold = 100; // Threshold value to specify the maximum value (in meters) the z difference can be to be considered close to the reference plane (To eliminate all bending points that are to far away from the z-axis to count as nodes)
|
||||
|
||||
/**
|
||||
* Output preferences
|
||||
*/
|
||||
|
||||
public static String outputUnit = "AU"; // Preferred output unit preference (AU => AU/day, m => m/s)
|
||||
public static int outputNumbers = 0; // Preferred way of outputting numbers: (0 => comma for decimals, dot in large numbers OR 1 => comma for large numbers, dot with decimals)
|
||||
public static int skipLines = 2629743; // Set the skipLines integer to skip lines (for example: every 5th line is written) in the output file (for smaller files), if this is set to 1, it has no effect and all lines will be written.
|
||||
public static boolean skipUnnecessary = true; // Skip the unnecessary objects in the export
|
||||
}
|
||||
|
@ -0,0 +1,14 @@
|
||||
package com.verictas.pos.simulator.mathUtils;
|
||||
|
||||
import javax.vecmath.Vector3d;
|
||||
|
||||
public class AOP {
|
||||
/**
|
||||
* Helper class for calculating the argument of periapsis
|
||||
*/
|
||||
public static double calculate(Vector3d ascendingNode, Vector3d perihelion, Vector3d aphelion) {
|
||||
Vector3d eccentricity = new Vector3d(0,0,0);
|
||||
eccentricity.sub(perihelion, aphelion);
|
||||
return ascendingNode.angle(eccentricity);
|
||||
}
|
||||
}
|
@ -0,0 +1,184 @@
|
||||
package com.verictas.pos.simulator.processor;
|
||||
|
||||
import com.verictas.pos.simulator.Object;
|
||||
import com.verictas.pos.simulator.SimulatorConfig;
|
||||
import com.verictas.pos.simulator.mathUtils.AU;
|
||||
|
||||
import javax.vecmath.Vector3d;
|
||||
|
||||
public class ObjectProcessor {
|
||||
public Vector3d aphelion;
|
||||
public Vector3d perihelion;
|
||||
public double aphelionDistance = -1;
|
||||
public double perihelionDistance = -1;
|
||||
|
||||
public Object thisObject;
|
||||
public Object referenceObject;
|
||||
|
||||
public Vector3d startingPosition;
|
||||
public double lastStartDistance = -1;
|
||||
public double beforeLastStartDistance = -1;
|
||||
|
||||
public Vector3d ascendingNode;
|
||||
public Vector3d descendingNode;
|
||||
|
||||
public double zAxisDistance = -1;
|
||||
public double pastzAxisDistance = -1;
|
||||
public Vector3d lastPos;
|
||||
|
||||
public void setStartingPosition(Vector3d position) {
|
||||
this.startingPosition = position;
|
||||
}
|
||||
|
||||
public void setObjectData(Object object) {
|
||||
this.thisObject = object;
|
||||
}
|
||||
|
||||
public void setReferenceObjectData(Object object) {
|
||||
this.referenceObject = object;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the aphelion & perihelion
|
||||
*/
|
||||
public void processAphelionAndPerihelion() {
|
||||
double sunDistance = this.thisObject.getDistance(this.referenceObject).length();
|
||||
|
||||
/**
|
||||
* Set the defaults
|
||||
*/
|
||||
|
||||
if (this.aphelionDistance == -1) {
|
||||
this.aphelionDistance = sunDistance;
|
||||
}
|
||||
|
||||
if (this.perihelionDistance == -1) {
|
||||
this.perihelionDistance = sunDistance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the aphelion or perihelion should be changed
|
||||
*/
|
||||
|
||||
if (sunDistance > aphelionDistance) {
|
||||
this.aphelion = this.thisObject.position;
|
||||
this.aphelionDistance = sunDistance;
|
||||
}
|
||||
|
||||
if (sunDistance < perihelionDistance) {
|
||||
this.perihelion = this.thisObject.position;
|
||||
this.perihelionDistance = sunDistance;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the ascending node
|
||||
*/
|
||||
|
||||
public void processNodes() {
|
||||
double zAxisDistance = Math.abs(this.thisObject.position.getZ() - SimulatorConfig.z);
|
||||
|
||||
if (this.pastzAxisDistance == -1) {
|
||||
this.pastzAxisDistance = zAxisDistance;
|
||||
}
|
||||
|
||||
if (this.pastzAxisDistance != -1 && this.zAxisDistance == -1) {
|
||||
this.zAxisDistance = zAxisDistance;
|
||||
}
|
||||
|
||||
if (this.zAxisDistance != -1 && this.pastzAxisDistance != 1) {
|
||||
if ((this.pastzAxisDistance > this.zAxisDistance && zAxisDistance > this.zAxisDistance) && (this.zAxisDistance < SimulatorConfig.zThreshold)) {
|
||||
if (SimulatorConfig.outputUnit.equals("AU")) {
|
||||
System.out.println("INFO:: Found a node within the threshold at " + AU.convertFromMeter(this.lastPos) + " (in AU) for object " + this.thisObject.name + "!");
|
||||
} else {
|
||||
System.out.println("INFO:: Found a node within the threshold at " + this.lastPos + " (in m) for object " + this.thisObject.name + "!");
|
||||
}
|
||||
|
||||
if ((this.lastPos.getZ() - this.thisObject.position.getZ()) < 0) {
|
||||
if (SimulatorConfig.z < 0) {
|
||||
// The reference plane is in negative z, so you have gone up!
|
||||
this.ascendingNode = this.lastPos;
|
||||
System.out.println("INFO:: Detected node as: ASCENDING NODE!");
|
||||
} else {
|
||||
// The reference plane is in positive z, so you have gone down!
|
||||
this.descendingNode = this.lastPos;
|
||||
System.out.println("INFO:: Detected node as: DESCENDING NODE!");
|
||||
}
|
||||
} else {
|
||||
if (SimulatorConfig.z < 0) {
|
||||
// The reference plane is in negative z, so you have gone down!
|
||||
this.descendingNode = this.lastPos;
|
||||
System.out.println("INFO:: Detected node as: DESCENDING NODE!");
|
||||
} else {
|
||||
// The reference plane is in positive z, so you have gone up!
|
||||
this.ascendingNode = this.lastPos;
|
||||
System.out.println("INFO:: Detected node as: ASCENDING NODE!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.pastzAxisDistance = this.zAxisDistance;
|
||||
this.zAxisDistance = zAxisDistance;
|
||||
}
|
||||
|
||||
this.lastPos = this.thisObject.position;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the round check
|
||||
*/
|
||||
public boolean processRoundCheck() {
|
||||
double startDistance = this.thisObject.getDistance(this.startingPosition).length();
|
||||
boolean fullRotation = false;
|
||||
|
||||
/**
|
||||
* Check if all are set and shuffle!
|
||||
*/
|
||||
|
||||
if (beforeLastStartDistance != -1 && lastStartDistance != -1) {
|
||||
// Ready to go!
|
||||
if (beforeLastStartDistance > lastStartDistance && startDistance > lastStartDistance) {
|
||||
// Last point was the closest to the starting position overall!
|
||||
fullRotation = true;
|
||||
System.out.println("INFO:: Object " + this.thisObject.name + " has made a full rotation last round.");
|
||||
}
|
||||
|
||||
beforeLastStartDistance = lastStartDistance;
|
||||
lastStartDistance = startDistance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if 1st distance is set and 2nd isn't set
|
||||
*/
|
||||
|
||||
if (beforeLastStartDistance != -1 && lastStartDistance == -1) {
|
||||
lastStartDistance = startDistance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the 1st distance isn't set
|
||||
*/
|
||||
if (beforeLastStartDistance == -1) {
|
||||
beforeLastStartDistance = startDistance;
|
||||
}
|
||||
|
||||
if(fullRotation) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
aphelionDistance = -1;
|
||||
perihelionDistance = -1;
|
||||
lastStartDistance = -1;
|
||||
beforeLastStartDistance = -1;
|
||||
aphelion = null;
|
||||
perihelion = null;
|
||||
ascendingNode = null;
|
||||
descendingNode = null;
|
||||
zAxisDistance = -1;
|
||||
lastPos = null;
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
package com.verictas.pos.simulator.processor;
|
||||
|
||||
public class ProcessingException extends Exception {
|
||||
public ProcessingException() { super(); }
|
||||
public ProcessingException(String message) { super(message); }
|
||||
public ProcessingException(String message, Throwable cause) { super(message, cause); }
|
||||
public ProcessingException(Throwable cause) { super(cause); }
|
||||
}
|
@ -0,0 +1,150 @@
|
||||
package com.verictas.pos.simulator.processor;
|
||||
|
||||
import com.verictas.pos.simulator.Object;
|
||||
import com.verictas.pos.simulator.SimulatorConfig;
|
||||
import com.verictas.pos.simulator.dataWriter.DataWriter;
|
||||
import com.verictas.pos.simulator.dataWriter.WritingException;
|
||||
import com.verictas.pos.simulator.mathUtils.AOP;
|
||||
import com.verictas.pos.simulator.mathUtils.AU;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class Processor {
|
||||
private DataWriter writer;
|
||||
public HashMap<String, Object> initialObjectValues = new HashMap<>();
|
||||
public HashMap<String, ObjectProcessor> objects = new HashMap<>();
|
||||
|
||||
public Processor(Object[] objects) throws ProcessingException, WritingException {
|
||||
/**
|
||||
* Initialize DataWriter
|
||||
*/
|
||||
this.writer = new DataWriter();
|
||||
|
||||
/**
|
||||
* Store the initial values of all the objects in memory (and to a file) for later use
|
||||
*/
|
||||
this.initialObjectValues = objectArrayToHashMap(objects);
|
||||
|
||||
// Write initial values to file
|
||||
this.write(initialObjectValues);
|
||||
|
||||
/**
|
||||
* Create the object processing array
|
||||
*/
|
||||
for (Object object : initialObjectValues.values()) {
|
||||
this.objects.put(object.name, new ObjectProcessor());
|
||||
this.objects.get(object.name).setStartingPosition(object.position);
|
||||
}
|
||||
}
|
||||
|
||||
public void process(Object[] objectArray) throws ProcessingException, WritingException {
|
||||
HashMap<String, Object> objects = objectArrayToHashMap(objectArray);
|
||||
|
||||
/**
|
||||
* Only do the processing for the asked planet(s)
|
||||
*/
|
||||
for(String objectName : SimulatorConfig.objectNames) {
|
||||
ObjectProcessor object = this.objects.get(objectName);
|
||||
|
||||
object.setObjectData(objects.get(objectName));
|
||||
object.setReferenceObjectData(objects.get(SimulatorConfig.sunName));
|
||||
|
||||
// Check if the object has gone round last round
|
||||
|
||||
boolean round = object.processRoundCheck();
|
||||
if (round) {
|
||||
// Object has gone full circle last round!
|
||||
System.out.println("\n\n============== ROTATION DATA: " + objectName.toUpperCase() + " =============");
|
||||
System.out.println("Current position (AU): " + AU.convertFromMeter(objects.get(objectName).position));
|
||||
System.out.println("Current position (m): " + objects.get(objectName).position + "\n");
|
||||
|
||||
if (object.ascendingNode != null) {
|
||||
System.out.println("Ascending node (AU): " + AU.convertFromMeter(object.ascendingNode));
|
||||
System.out.println("Ascending node (m): " + object.ascendingNode + "\n");
|
||||
} else {
|
||||
if (object.descendingNode != null) {
|
||||
System.out.println("WARNING:: Ascending node not found. Because a descending node was found, you can assume the current position is the ascending node (or it is between the starting position and the current.\n");
|
||||
} else {
|
||||
System.out.println("WARNING:: Ascending node not found. Have you set the reference plane height correctly?\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (object.descendingNode != null) {
|
||||
System.out.println("Descending node (AU): " + AU.convertFromMeter(object.descendingNode));
|
||||
System.out.println("Descending node (m): " + object.descendingNode + "\n");
|
||||
} else {
|
||||
if (object.ascendingNode != null) {
|
||||
System.out.println("WARNING:: Descending node not found. Because a ascending node was found, you can assume the current position is the descending node (or it is between the starting position and the current).\n");
|
||||
} else {
|
||||
System.out.println("WARNING:: Descending node not found. Have you set the reference plane height correctly?\n");
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Position during apastron (AU): " + AU.convertFromMeter(object.aphelion));
|
||||
System.out.println("Position during apastron (m): " + object.aphelion);
|
||||
System.out.println("Distance from (the) " + SimulatorConfig.sunName + " during apastron in m: " + object.aphelionDistance + "\n");
|
||||
System.out.println("Position during periastron (AU): " + AU.convertFromMeter(object.perihelion));
|
||||
System.out.println("Position during periastron (m): " + object.perihelion);
|
||||
System.out.println("Distance from (the) " + SimulatorConfig.sunName + " during periastron in m: " + object.perihelionDistance + "\n");
|
||||
|
||||
if (object.ascendingNode != null) {
|
||||
System.out.println("Argument of periapsis (range: 0 - PI): " + AOP.calculate(object.ascendingNode, object.perihelion, object.aphelion) + " rad");
|
||||
System.out.println("Argument of periapsis: " + Math.toDegrees(AOP.calculate(object.ascendingNode, object.perihelion, object.aphelion)) + " degrees");
|
||||
} else {
|
||||
if (object.descendingNode != null) {
|
||||
System.out.println("WARNING:: Ascending node not found. The argument is calculated with the current position as ascending node).\n");
|
||||
System.out.println("Argument of periapsis (range: 0 - PI): " + AOP.calculate(objects.get(objectName).position, object.perihelion, object.aphelion) + " rad");
|
||||
System.out.println("Argument of periapsis: " + Math.toDegrees(AOP.calculate(objects.get(objectName).position, object.perihelion, object.aphelion)) + " degrees");
|
||||
}
|
||||
System.out.println("ERROR:: Can't calculate the argument of periapsis because the ascending node is missing.");
|
||||
}
|
||||
|
||||
System.out.println("=======================================================================================\n\n");
|
||||
|
||||
object.reset();
|
||||
|
||||
// Reset starting position
|
||||
this.objects.get(objectName).setStartingPosition(objects.get(objectName).position);
|
||||
}
|
||||
|
||||
// Process values for this round
|
||||
object.processAphelionAndPerihelion();
|
||||
object.processNodes();
|
||||
|
||||
this.objects.put(objectName, object);
|
||||
}
|
||||
|
||||
this.write(objects);
|
||||
}
|
||||
|
||||
private void write(HashMap<String, Object> objects) throws ProcessingException, WritingException {
|
||||
if (SimulatorConfig.skipUnnecessary) {
|
||||
for (String name : SimulatorConfig.objectNames) {
|
||||
this.writer.write(objects.get(name), objects.get(SimulatorConfig.sunName));
|
||||
}
|
||||
} else {
|
||||
for (Object object : objects.values()) {
|
||||
this.writer.write(object, objects.get(SimulatorConfig.sunName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private HashMap<String, Object> objectArrayToHashMap(Object[] objects) {
|
||||
// Create the return map
|
||||
HashMap<String, Object> objectMap = new HashMap<>();
|
||||
|
||||
for(int i = 0; i < objects.length; i++) {
|
||||
objectMap.put(objects[i].name, objects[i]);
|
||||
}
|
||||
|
||||
return objectMap;
|
||||
}
|
||||
|
||||
public void close() throws ProcessingException {
|
||||
try {
|
||||
this.writer.save();
|
||||
} catch(WritingException e) {
|
||||
throw new ProcessingException("An error occurred during creation of the file writer: " + e.toString());
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue