package net.sf.openrocket.simulation; import java.util.ArrayList; import java.util.List; import net.sf.openrocket.aerodynamics.AerodynamicCalculator; import net.sf.openrocket.document.Simulation; import net.sf.openrocket.masscalc.MassCalculator; import net.sf.openrocket.models.atmosphere.AtmosphericModel; import net.sf.openrocket.models.gravity.GravityModel; import net.sf.openrocket.models.wind.WindModel; import net.sf.openrocket.rocketcomponent.Rocket; import net.sf.openrocket.simulation.listeners.SimulationListener; import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.GeodeticComputationStrategy; import net.sf.openrocket.util.Monitorable; import net.sf.openrocket.util.WorldCoordinate; /** * A holder class for the simulation conditions. These include conditions that do not change * during the flight of a rocket, for example launch rod parameters, atmospheric models, * aerodynamic calculators etc. * * @author Sampo Niskanen <sampo.niskanen@iki.fi> */ public class SimulationConditions implements Monitorable, Cloneable { private Rocket rocket; private String motorID = null; private Simulation simulation; // The parent simulation private double launchRodLength = 1; /** Launch rod angle >= 0, radians from vertical */ private double launchRodAngle = 0; /** Launch rod direction, 0 = north */ private double launchRodDirection = 0; // Launch site location (lat, lon, alt) private WorldCoordinate launchSite = new WorldCoordinate(0, 0, 0); // Launch location in simulation coordinates (normally always 0, air-start would override this) private Coordinate launchPosition = Coordinate.NUL; private Coordinate launchVelocity = Coordinate.NUL; private GeodeticComputationStrategy geodeticComputation = GeodeticComputationStrategy.SPHERICAL; private WindModel windModel; private AtmosphericModel atmosphericModel; private GravityModel gravityModel; private AerodynamicCalculator aerodynamicCalculator; private MassCalculator massCalculator; private double timeStep = RK4SimulationStepper.RECOMMENDED_TIME_STEP; private double maximumAngleStep = RK4SimulationStepper.RECOMMENDED_ANGLE_STEP; /* Whether to calculate additional data or only primary simulation figures */ private boolean calculateExtras = true; private List<SimulationListener> simulationListeners = new ArrayList<SimulationListener>(); private int randomSeed = 0; private int modID = 0; private int modIDadd = 0; public AerodynamicCalculator getAerodynamicCalculator() { return aerodynamicCalculator; } public void setAerodynamicCalculator(AerodynamicCalculator aerodynamicCalculator) { if (this.aerodynamicCalculator != null) this.modIDadd += this.aerodynamicCalculator.getModID(); this.modID++; this.aerodynamicCalculator = aerodynamicCalculator; } public MassCalculator getMassCalculator() { return massCalculator; } public void setMassCalculator(MassCalculator massCalculator) { if (this.massCalculator != null) this.modIDadd += this.massCalculator.getModID(); this.modID++; this.massCalculator = massCalculator; } public Rocket getRocket() { return rocket; } public void setRocket(Rocket rocket) { if (this.rocket != null) this.modIDadd += this.rocket.getModID(); this.modID++; this.rocket = rocket; } public String getMotorConfigurationID() { return motorID; } public void setMotorConfigurationID(String motorID) { this.motorID = motorID; this.modID++; } public double getLaunchRodLength() { return launchRodLength; } public void setLaunchRodLength(double launchRodLength) { this.launchRodLength = launchRodLength; this.modID++; } public double getLaunchRodAngle() { return launchRodAngle; } public void setLaunchRodAngle(double launchRodAngle) { this.launchRodAngle = launchRodAngle; this.modID++; } public double getLaunchRodDirection() { return launchRodDirection; } public void setLaunchRodDirection(double launchRodDirection) { this.launchRodDirection = launchRodDirection; this.modID++; } public WorldCoordinate getLaunchSite() { return this.launchSite; } public void setLaunchSite(WorldCoordinate site) { if (this.launchSite.equals(site)) return; this.launchSite = site; this.modID++; } public Coordinate getLaunchPosition() { return launchPosition; } public void setLaunchPosition(Coordinate launchPosition) { if (this.launchPosition.equals(launchPosition)) return; this.launchPosition = launchPosition; this.modID++; } public Coordinate getLaunchVelocity() { return launchVelocity; } public void setLaunchVelocity(Coordinate launchVelocity) { if (this.launchVelocity.equals(launchVelocity)) return; this.launchVelocity = launchVelocity; this.modID++; } public GeodeticComputationStrategy getGeodeticComputation() { return geodeticComputation; } public void setGeodeticComputation(GeodeticComputationStrategy geodeticComputation) { if (this.geodeticComputation == geodeticComputation) return; if (geodeticComputation == null) { throw new IllegalArgumentException("strategy cannot be null"); } this.geodeticComputation = geodeticComputation; this.modID++; } public WindModel getWindModel() { return windModel; } public void setWindModel(WindModel windModel) { if (this.windModel != null) this.modIDadd += this.windModel.getModID(); this.modID++; this.windModel = windModel; } public AtmosphericModel getAtmosphericModel() { return atmosphericModel; } public void setAtmosphericModel(AtmosphericModel atmosphericModel) { if (this.atmosphericModel != null) this.modIDadd += this.atmosphericModel.getModID(); this.modID++; this.atmosphericModel = atmosphericModel; } public GravityModel getGravityModel() { return gravityModel; } public void setGravityModel(GravityModel gravityModel) { //if (this.gravityModel != null) // this.modIDadd += this.gravityModel.getModID(); this.modID++; this.gravityModel = gravityModel; } public double getTimeStep() { return timeStep; } public void setTimeStep(double timeStep) { this.timeStep = timeStep; this.modID++; } public double getMaximumAngleStep() { return maximumAngleStep; } public void setMaximumAngleStep(double maximumAngle) { this.maximumAngleStep = maximumAngle; this.modID++; } public boolean isCalculateExtras() { return calculateExtras; } public void setCalculateExtras(boolean calculateExtras) { this.calculateExtras = calculateExtras; this.modID++; } public int getRandomSeed() { return randomSeed; } public void setRandomSeed(int randomSeed) { this.randomSeed = randomSeed; this.modID++; } public void setSimulation(Simulation sim) { this.simulation = sim; } public Simulation getSimulation() { return this.simulation; } // TODO: HIGH: Make cleaner public List<SimulationListener> getSimulationListenerList() { return simulationListeners; } @Override public int getModID() { //return (modID + modIDadd + rocket.getModID() + windModel.getModID() + atmosphericModel.getModID() + // gravityModel.getModID() + aerodynamicCalculator.getModID() + massCalculator.getModID()); return (modID + modIDadd + rocket.getModID() + windModel.getModID() + atmosphericModel.getModID() + aerodynamicCalculator.getModID() + massCalculator.getModID()); } @Override public SimulationConditions clone() { try { // TODO: HIGH: Deep clone models SimulationConditions clone = (SimulationConditions) super.clone(); clone.simulationListeners = new ArrayList<SimulationListener>(this.simulationListeners.size()); for (SimulationListener listener : this.simulationListeners) { clone.simulationListeners.add(listener.clone()); } return clone; } catch (CloneNotSupportedException e) { throw new BugException(e); } } }