diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties
index 11ccd3456..7bf394c88 100644
--- a/core/resources/l10n/messages.properties
+++ b/core/resources/l10n/messages.properties
@@ -332,6 +332,8 @@ simedtdlg.lbl.Wind = Wind
simedtdlg.lbl.Averwindspeed = Average windspeed:
simedtdlg.lbl.ttip.Averwindspeed = The average windspeed relative to the ground.
simedtdlg.lbl.Stddeviation = Standard deviation:
+simedtdlg.lbl.Winddirection = Wind direction:
+simedtdlg.lbl.ttip.Winddirection = Wind direction, 0-360 degrees.
0 means from the north,
90 is from the east
simedtdlg.lbl.ttip.Stddeviation = The standard deviation of the windspeed.
The windspeed is within twice the standard deviation from the average for 95% of the time.
simedtdlg.lbl.Turbulenceintensity = Turbulence intensity:
simedtdlg.lbl.ttip.Turbulenceintensity1 = The turbulence intensity is the standard deviation divided by the average windspeed.
@@ -1477,8 +1479,8 @@ FlightDataType.TYPE_VELOCITY_Z = Vertical velocity
FlightDataType.TYPE_ACCELERATION_Z = Vertical acceleration
FlightDataType.TYPE_VELOCITY_TOTAL = Total velocity
FlightDataType.TYPE_ACCELERATION_TOTAL = Total acceleration
-FlightDataType.TYPE_POSITION_X = Position upwind
-FlightDataType.TYPE_POSITION_Y = Position parallel to wind
+FlightDataType.TYPE_POSITION_X = Position East-West
+FlightDataType.TYPE_POSITION_Y = Position North-South
FlightDataType.TYPE_POSITION_XY = Lateral distance
FlightDataType.TYPE_POSITION_DIRECTION = Lateral direction
FlightDataType.TYPE_VELOCITY_XY = Lateral velocity
@@ -1536,6 +1538,7 @@ PlotConfiguration.Dragcoef = Drag coefficients vs. Mach number
PlotConfiguration.Rollcharacteristics = Roll characteristics
PlotConfiguration.Angleofattack = Angle of attack and orientation vs. time
PlotConfiguration.Simulationtime = Simulation time step and computation time
+PlotConfiguration.Groundtrack = Ground track
! Warning
Warning.LargeAOA.str1 = Large angle of attack encountered.
diff --git a/core/src/net/sf/openrocket/models/wind/PinkNoiseWindModel.java b/core/src/net/sf/openrocket/models/wind/PinkNoiseWindModel.java
index 960325d5f..e9ee2a7a3 100644
--- a/core/src/net/sf/openrocket/models/wind/PinkNoiseWindModel.java
+++ b/core/src/net/sf/openrocket/models/wind/PinkNoiseWindModel.java
@@ -18,8 +18,8 @@ public class PinkNoiseWindModel implements WindModel {
/** Random value with which to XOR the random seed value */
private static final int SEED_RANDOMIZATION = 0x7343AA03;
-
-
+
+
/** Pink noise alpha parameter. */
private static final double ALPHA = 5.0 / 3.0;
@@ -32,8 +32,9 @@ public class PinkNoiseWindModel implements WindModel {
/** Time difference between random samples. */
private static final double DELTA_T = 0.05;
-
+
private double average = 0;
+ private double direction = Math.PI / 2; // this is an East wind
private double standardDeviation = 0;
private final int seed;
@@ -52,7 +53,7 @@ public class PinkNoiseWindModel implements WindModel {
}
-
+
/**
* Return the average wind speed.
*
@@ -74,8 +75,14 @@ public class PinkNoiseWindModel implements WindModel {
setTurbulenceIntensity(intensity);
}
+ public void setDirection(double direction) {
+ this.direction = direction;
+ }
+
+ public double getDirection() {
+ return this.direction;
+ }
-
/**
* Return the standard deviation from the average wind speed.
*
@@ -120,9 +127,9 @@ public class PinkNoiseWindModel implements WindModel {
}
-
-
-
+
+
+
@Override
public Coordinate getWindVelocity(double time, double altitude) {
if (time < 0) {
@@ -150,8 +157,8 @@ public class PinkNoiseWindModel implements WindModel {
double a = (time - time1) / DELTA_T;
double speed = average + (value1 * (1 - a) + value2 * a) * standardDeviation / STDDEV;
- // TODO: MEDIUM: Make wind direction configurable
- return new Coordinate(speed, 0, 0);
+ return new Coordinate(speed * Math.sin(direction), speed * Math.cos(direction), 0);
+
}
@@ -160,7 +167,7 @@ public class PinkNoiseWindModel implements WindModel {
}
-
+
@Override
public int getModID() {
return (int) (average * 1000 + standardDeviation);
diff --git a/core/src/net/sf/openrocket/simulation/SimulationOptions.java b/core/src/net/sf/openrocket/simulation/SimulationOptions.java
index f32c01407..bb8bfaf82 100644
--- a/core/src/net/sf/openrocket/simulation/SimulationOptions.java
+++ b/core/src/net/sf/openrocket/simulation/SimulationOptions.java
@@ -68,7 +68,7 @@ public class SimulationOptions implements ChangeSource, Cloneable {
private double windAverage = 2.0;
private double windTurbulence = 0.1;
-
+ private double windDirection = Math.PI / 2;
/*
* SimulationOptions maintains the launch site parameters as separate double values,
@@ -211,8 +211,25 @@ public class SimulationOptions implements ChangeSource, Cloneable {
}
+ /**
+ * Set the wind direction
+ *
+ * @param direction the wind direction
+ */
+ public void setWindDirection(double direction) {
+ direction = MathUtil.reduce360(direction);
+ if (MathUtil.equals(this.windDirection, direction))
+ return;
+ this.windDirection = direction;
+ fireChangeEvent();
+
+ }
+ public double getWindDirection() {
+ return this.windDirection;
+
+ }
public double getLaunchAltitude() {
return launchAltitude;
@@ -446,6 +463,7 @@ public class SimulationOptions implements ChangeSource, Cloneable {
this.timeStep = src.timeStep;
this.windAverage = src.windAverage;
this.windTurbulence = src.windTurbulence;
+ this.windDirection = src.windDirection;
this.calculateExtras = src.calculateExtras;
this.randomSeed = src.randomSeed;
@@ -501,6 +519,10 @@ public class SimulationOptions implements ChangeSource, Cloneable {
isChanged = true;
this.windAverage = src.windAverage;
}
+ if (this.windDirection != src.windDirection) {
+ isChanged = true;
+ this.windDirection = src.windDirection;
+ }
if (this.windTurbulence != src.windTurbulence) {
isChanged = true;
this.windTurbulence = src.windTurbulence;
@@ -542,6 +564,7 @@ public class SimulationOptions implements ChangeSource, Cloneable {
MathUtil.equals(this.timeStep, o.timeStep) &&
MathUtil.equals(this.windAverage, o.windAverage) &&
MathUtil.equals(this.windTurbulence, o.windTurbulence) &&
+ MathUtil.equals(this.windDirection, o.windDirection) &&
this.calculateExtras == o.calculateExtras && this.randomSeed == o.randomSeed);
}
@@ -595,6 +618,8 @@ public class SimulationOptions implements ChangeSource, Cloneable {
PinkNoiseWindModel windModel = new PinkNoiseWindModel(randomSeed);
windModel.setAverage(getWindSpeedAverage());
windModel.setStandardDeviation(getWindSpeedDeviation());
+ windModel.setDirection(windDirection);
+
conditions.setWindModel(windModel);
conditions.setAtmosphericModel(getAtmosphericModel());
diff --git a/swing/src/net/sf/openrocket/gui/plot/PlotConfiguration.java b/swing/src/net/sf/openrocket/gui/plot/PlotConfiguration.java
index 8f1f455de..e700c9080 100644
--- a/swing/src/net/sf/openrocket/gui/plot/PlotConfiguration.java
+++ b/swing/src/net/sf/openrocket/gui/plot/PlotConfiguration.java
@@ -67,6 +67,18 @@ public class PlotConfiguration implements Cloneable {
config.setEvent(FlightEvent.Type.TUMBLE, true);
config.setEvent(FlightEvent.Type.EXCEPTION, true);
configs.add(config);
+
+
+ //// Ground track
+ config = new PlotConfiguration(trans.get("PlotConfiguration.Groundtrack"), FlightDataType.TYPE_POSITION_X);
+ config.addPlotDataType(FlightDataType.TYPE_POSITION_Y, 0);
+ config.addPlotDataType(FlightDataType.TYPE_ALTITUDE, 1);
+ config.setEvent(FlightEvent.Type.IGNITION, true);
+ config.setEvent(FlightEvent.Type.BURNOUT, true);
+ config.setEvent(FlightEvent.Type.APOGEE, true);
+ config.setEvent(FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT, true);
+ config.setEvent(FlightEvent.Type.GROUND_HIT, true);
+ configs.add(config);
//// Stability vs. time
config = new PlotConfiguration(trans.get("PlotConfiguration.Stability"));
diff --git a/swing/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java b/swing/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java
index 2839704b1..f21746f4a 100644
--- a/swing/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java
+++ b/swing/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java
@@ -43,7 +43,7 @@ public class SimulationConditionsPanel extends JPanel {
DoubleModel m;
JSpinner spin;
- //// Wind settings: Average wind speed, turbulence intensity, std. deviation
+ //// Wind settings: Average wind speed, turbulence intensity, std. deviation, and direction
sub = new JPanel(new MigLayout("fill, gap rel unrel",
"[grow][65lp!][30lp!][75lp!]", ""));
//// Wind
@@ -100,6 +100,30 @@ public class SimulationConditionsPanel extends JPanel {
slider.setToolTipText(tip);
sub.add(slider, "w 75lp, wrap");
+ // Wind Direction:
+ label = new JLabel(trans.get("simedtdlg.lbl.Winddirection"));
+ //// Direction of the wind. 0 is north
+ tip = trans.get("simedtdlg.lbl.ttip.Winddirection");
+ label.setToolTipText(tip);
+ sub.add(label);
+
+ m = new DoubleModel(conditions, "WindDirection", 1.0, UnitGroup.UNITS_ANGLE,
+ 0, 2*Math.PI);
+
+ spin = new JSpinner(m.getSpinnerModel());
+ spin.setEditor(new SpinnerEditor(spin));
+ spin.setToolTipText(tip);
+ sub.add(spin, "w 65lp!");
+
+ unit = new UnitSelector(m);
+ unit.setToolTipText(tip);
+ sub.add(unit, "growx");
+ slider = new BasicSlider(m.getSliderModel(0, 2*Math.PI));
+ slider.setToolTipText(tip);
+ sub.add(slider, "w 75lp, wrap");
+
+
+
// Wind turbulence intensity
//// Turbulence intensity: