From d740e2933c744473d48ec5ad9f21d3fc1e5e5828 Mon Sep 17 00:00:00 2001 From: JoePfeiffer Date: Thu, 21 Sep 2023 20:17:07 -0600 Subject: [PATCH 01/10] Add "inch" units to surface roughness --- core/src/net/sf/openrocket/unit/UnitGroup.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/net/sf/openrocket/unit/UnitGroup.java b/core/src/net/sf/openrocket/unit/UnitGroup.java index 090b5ec49..c79272a64 100644 --- a/core/src/net/sf/openrocket/unit/UnitGroup.java +++ b/core/src/net/sf/openrocket/unit/UnitGroup.java @@ -291,6 +291,7 @@ public class UnitGroup { UNITS_ROUGHNESS = new UnitGroup(); UNITS_ROUGHNESS.addUnit(new GeneralUnit(0.000001, MICRO + "m")); UNITS_ROUGHNESS.addUnit(new GeneralUnit(0.0000254, "mil")); + UNITS_ROUGHNESS.addUnit(new GeneralUnit(0.0254, "in")); UNITS_ROUGHNESS.addUnit(new GeneralUnit(1, "m")); From e4ace36e93200ae76b58988e66106e2ae9e5ddc0 Mon Sep 17 00:00:00 2001 From: Isaac Date: Mon, 13 Nov 2023 00:13:03 +0000 Subject: [PATCH 02/10] [2258] Changed the static text box in the component analysis dialog to a JSpinner. --- .../gui/dialogs/ComponentAnalysisDialog.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java index e91a4af75..288885669 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java @@ -42,6 +42,7 @@ import net.miginfocom.swing.MigLayout; import net.sf.openrocket.aerodynamics.AerodynamicCalculator; import net.sf.openrocket.aerodynamics.AerodynamicForces; import net.sf.openrocket.aerodynamics.FlightConditions; +import net.sf.openrocket.gui.components.*; import net.sf.openrocket.gui.util.UITheme; import net.sf.openrocket.logging.Warning; import net.sf.openrocket.logging.WarningSet; @@ -49,11 +50,6 @@ import net.sf.openrocket.gui.adaptors.Column; import net.sf.openrocket.gui.adaptors.ColumnTable; import net.sf.openrocket.gui.adaptors.ColumnTableModel; import net.sf.openrocket.gui.adaptors.DoubleModel; -import net.sf.openrocket.gui.components.BasicSlider; -import net.sf.openrocket.gui.components.ConfigurationComboBox; -import net.sf.openrocket.gui.components.StageSelector; -import net.sf.openrocket.gui.components.StyledLabel; -import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.gui.scalefigure.RocketPanel; import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.gui.widgets.SelectColorToggleButton; @@ -134,7 +130,9 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe //// Wind direction: panel.add(new JLabel(trans.get("componentanalysisdlg.lbl.winddir")), "width 120lp!"); - panel.add(new UnitSelector(theta, true), "width 50lp!"); + EditableSpinner spinner = new EditableSpinner(theta.getSpinnerModel()); + panel.add(spinner, "growx"); + panel.add(new UnitSelector(theta), "width 50lp!"); BasicSlider slider = new BasicSlider(theta.getSliderModel(0, 2 * Math.PI)); panel.add(slider, "growx, split 2"); //// Worst button @@ -165,17 +163,20 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe ////Angle of attack: panel.add(new JLabel(trans.get("componentanalysisdlg.lbl.angleofattack")), "width 120lp!"); - panel.add(new UnitSelector(aoa, true), "width 50lp!"); + panel.add(new EditableSpinner(aoa.getSpinnerModel()), "growx"); + panel.add(new UnitSelector(aoa), "width 50lp!"); panel.add(new BasicSlider(aoa.getSliderModel(0, Math.PI)), "growx, wrap"); //// Mach number: panel.add(new JLabel(trans.get("componentanalysisdlg.lbl.machnumber")), "width 120lp!"); + panel.add(new EditableSpinner(mach.getSpinnerModel()), "width 120lp!"); panel.add(new UnitSelector(mach, true), "width 50lp!"); panel.add(new BasicSlider(mach.getSliderModel(0, 3)), "growx, wrap"); //// Roll rate: panel.add(new JLabel(trans.get("componentanalysisdlg.lbl.rollrate")), "width 120lp!"); - panel.add(new UnitSelector(roll, true), "width 50lp!"); + panel.add(new EditableSpinner(roll.getSpinnerModel()), "growx"); + panel.add(new UnitSelector(roll), "width 50lp!"); panel.add(new BasicSlider(roll.getSliderModel(-20 * 2 * Math.PI, 20 * 2 * Math.PI)), "growx, wrap"); From 1e0947529c77563d1a320dc365cb0dcdeb01a4fa Mon Sep 17 00:00:00 2001 From: Isaac Date: Mon, 13 Nov 2023 13:53:46 +0000 Subject: [PATCH 03/10] [2258] Changed the size of the spinners and unit selector and removed wildcard imports. --- .../openrocket/gui/dialogs/ComponentAnalysisDialog.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java index 5c6a18484..320c4b43a 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/ComponentAnalysisDialog.java @@ -42,7 +42,6 @@ import net.miginfocom.swing.MigLayout; import net.sf.openrocket.aerodynamics.AerodynamicCalculator; import net.sf.openrocket.aerodynamics.AerodynamicForces; import net.sf.openrocket.aerodynamics.FlightConditions; -import net.sf.openrocket.gui.components.*; import net.sf.openrocket.gui.util.UITheme; import net.sf.openrocket.logging.Warning; import net.sf.openrocket.logging.WarningSet; @@ -50,6 +49,12 @@ import net.sf.openrocket.gui.adaptors.Column; import net.sf.openrocket.gui.adaptors.ColumnTable; import net.sf.openrocket.gui.adaptors.ColumnTableModel; import net.sf.openrocket.gui.adaptors.DoubleModel; +import net.sf.openrocket.gui.components.EditableSpinner; +import net.sf.openrocket.gui.components.BasicSlider; +import net.sf.openrocket.gui.components.ConfigurationComboBox; +import net.sf.openrocket.gui.components.StageSelector; +import net.sf.openrocket.gui.components.StyledLabel; +import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.gui.scalefigure.RocketPanel; import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.gui.widgets.SelectColorToggleButton; @@ -109,7 +114,7 @@ public class ComponentAnalysisDialog extends JDialog implements StateChangeListe JTable table; - JPanel panel = new JPanel(new MigLayout("fill", "[120lp][70lp][]")); + JPanel panel = new JPanel(new MigLayout("fill", "[120lp][70lp][50lp][]")); add(panel); rkt = rocketPanel.getDocument().getRocket(); From 94c2c1ef38e40fd12a6393650a40fc997fa40b34 Mon Sep 17 00:00:00 2001 From: SiboVG Date: Wed, 15 Nov 2023 04:41:31 +0100 Subject: [PATCH 04/10] Major refactor of simulation options UI --- .../simulation/SimulationOptions.java | 32 +- .../SimulationOptionsInterface.java | 77 ++ .../sf/openrocket/startup/Preferences.java | 4 +- .../preferences/LaunchPreferencesPanel.java | 468 +--------- .../simulation/SimulationConditionsPanel.java | 818 +++++++++--------- .../openrocket/gui/util/SwingPreferences.java | 3 +- 6 files changed, 511 insertions(+), 891 deletions(-) create mode 100644 core/src/net/sf/openrocket/simulation/SimulationOptionsInterface.java diff --git a/core/src/net/sf/openrocket/simulation/SimulationOptions.java b/core/src/net/sf/openrocket/simulation/SimulationOptions.java index d11759332..dfcee63c3 100644 --- a/core/src/net/sf/openrocket/simulation/SimulationOptions.java +++ b/core/src/net/sf/openrocket/simulation/SimulationOptions.java @@ -32,7 +32,7 @@ import net.sf.openrocket.util.WorldCoordinate; * * @author Sampo Niskanen */ -public class SimulationOptions implements ChangeSource, Cloneable { +public class SimulationOptions implements ChangeSource, Cloneable, SimulationOptionsInterface { @SuppressWarnings("unused") private static final Logger log = LoggerFactory.getLogger(SimulationOptions.class); @@ -71,7 +71,7 @@ public class SimulationOptions implements ChangeSource, Cloneable { private double launchLongitude = preferences.getLaunchLongitude(); private GeodeticComputationStrategy geodeticComputation = GeodeticComputationStrategy.SPHERICAL; - private boolean useISA = preferences.getISAAtmosphere(); + private boolean useISA = preferences.isISAAtmosphere(); private double launchTemperature = preferences.getLaunchTemperature(); // In Kelvin private double launchPressure = preferences.getLaunchPressure(); // In Pascal @@ -161,34 +161,17 @@ public class SimulationOptions implements ChangeSource, Cloneable { setWindTurbulenceIntensity(windDeviation / windAverage); } - - /** - * Return the wind turbulence intensity (standard deviation / average). - * - * @return the turbulence intensity - */ + public double getWindTurbulenceIntensity() { return windTurbulence; } - - /** - * Set the wind standard deviation to match the given turbulence intensity. - * - * @param intensity the turbulence intensity - */ + public void setWindTurbulenceIntensity(double intensity) { // Does not check equality so that setWindSpeedDeviation can be sure of event firing this.windTurbulence = intensity; fireChangeEvent(); } - - - /** - * Set the wind direction - * - * @param direction the wind direction - */ - + public void setWindDirection(double direction) { direction = MathUtil.reduce2Pi(direction); if (launchIntoWind) { @@ -312,11 +295,12 @@ public class SimulationOptions implements ChangeSource, Cloneable { fireChangeEvent(); } - + + /** * Returns an atmospheric model corresponding to the launch conditions. The * atmospheric models may be shared between different calls. - * + * * @return an AtmosphericModel object. */ private AtmosphericModel getAtmosphericModel() { diff --git a/core/src/net/sf/openrocket/simulation/SimulationOptionsInterface.java b/core/src/net/sf/openrocket/simulation/SimulationOptionsInterface.java new file mode 100644 index 000000000..418c9dad5 --- /dev/null +++ b/core/src/net/sf/openrocket/simulation/SimulationOptionsInterface.java @@ -0,0 +1,77 @@ +package net.sf.openrocket.simulation; + +import net.sf.openrocket.util.ChangeSource; +import net.sf.openrocket.util.GeodeticComputationStrategy; + +public interface SimulationOptionsInterface extends ChangeSource { + double getLaunchRodLength(); + + void setLaunchRodLength(double launchRodLength); + + boolean getLaunchIntoWind(); + + void setLaunchIntoWind(boolean i); + + double getLaunchRodAngle(); + + void setLaunchRodAngle(double launchRodAngle); + + double getLaunchRodDirection(); + + void setLaunchRodDirection(double launchRodDirection); + + double getWindSpeedAverage(); + + void setWindSpeedAverage(double windAverage); + + double getWindSpeedDeviation(); + + void setWindSpeedDeviation(double windDeviation); + + /** + * Return the wind turbulence intensity (standard deviation / average). + * + * @return the turbulence intensity + */ + double getWindTurbulenceIntensity(); + + /** + * Set the wind standard deviation to match the given turbulence intensity. + * + * @param intensity the turbulence intensity + */ + void setWindTurbulenceIntensity(double intensity); + + void setWindDirection(double direction); + + double getWindDirection(); + + double getLaunchAltitude(); + + void setLaunchAltitude(double altitude); + + double getLaunchLatitude(); + + void setLaunchLatitude(double launchLatitude); + + double getLaunchLongitude(); + + void setLaunchLongitude(double launchLongitude); + + GeodeticComputationStrategy getGeodeticComputation(); + + void setGeodeticComputation(GeodeticComputationStrategy geodeticComputation); + + boolean isISAAtmosphere(); + + void setISAAtmosphere(boolean isa); + + double getLaunchTemperature(); + + void setLaunchTemperature(double launchTemperature); + + double getLaunchPressure(); + + void setLaunchPressure(double launchPressure); + +} diff --git a/core/src/net/sf/openrocket/startup/Preferences.java b/core/src/net/sf/openrocket/startup/Preferences.java index 7f46a85a5..2c0011832 100644 --- a/core/src/net/sf/openrocket/startup/Preferences.java +++ b/core/src/net/sf/openrocket/startup/Preferences.java @@ -428,7 +428,7 @@ public abstract class Preferences implements ChangeSource { this.putDouble(LAUNCH_ALTITUDE, altitude); // Update the launch temperature and pressure if using ISA - if (getISAAtmosphere()) { + if (isISAAtmosphere()) { setLaunchTemperature(ISA_ATMOSPHERIC_MODEL.getConditions(getLaunchAltitude()).getTemperature()); setLaunchPressure(ISA_ATMOSPHERIC_MODEL.getConditions(getLaunchAltitude()).getPressure()); } @@ -518,7 +518,7 @@ public abstract class Preferences implements ChangeSource { } - public boolean getISAAtmosphere() { + public boolean isISAAtmosphere() { return this.getBoolean(LAUNCH_USE_ISA, true); } diff --git a/swing/src/net/sf/openrocket/gui/dialogs/preferences/LaunchPreferencesPanel.java b/swing/src/net/sf/openrocket/gui/dialogs/preferences/LaunchPreferencesPanel.java index 50b5d97f7..0443c1b8a 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/preferences/LaunchPreferencesPanel.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/preferences/LaunchPreferencesPanel.java @@ -2,35 +2,13 @@ package net.sf.openrocket.gui.dialogs.preferences; import java.awt.Color; import java.awt.LayoutManager; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.util.EventObject; - -import javax.swing.BorderFactory; -import javax.swing.JCheckBox; import javax.swing.JDialog; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.JPanel; -import javax.swing.JSpinner; -import javax.swing.JTextField; -import javax.swing.event.ChangeEvent; -import javax.swing.event.ChangeListener; import net.miginfocom.swing.MigLayout; -import net.sf.openrocket.gui.SpinnerEditor; -import net.sf.openrocket.gui.adaptors.BooleanModel; -import net.sf.openrocket.gui.adaptors.DoubleModel; -import net.sf.openrocket.gui.components.BasicSlider; import net.sf.openrocket.gui.components.StyledLabel; -import net.sf.openrocket.gui.components.UnitSelector; +import net.sf.openrocket.gui.simulation.SimulationConditionsPanel; import net.sf.openrocket.gui.util.GUIUtil; import net.sf.openrocket.gui.util.UITheme; -import net.sf.openrocket.models.atmosphere.ExtendedISAModel; -import net.sf.openrocket.simulation.SimulationOptions; -import net.sf.openrocket.unit.UnitGroup; -import net.sf.openrocket.util.Chars; -import net.sf.openrocket.util.StateChangeListener; public class LaunchPreferencesPanel extends PreferencesPanel { private static Color darkWarningColor; @@ -55,406 +33,8 @@ public class LaunchPreferencesPanel extends PreferencesPanel { warning.setToolTipText(trans.get("pref.dlg.lbl.launchWarning.ttip")); add(warning, "spanx, growx 0, gapbottom para, wrap"); - JPanel sub; - String tip; - UnitSelector unit; - BasicSlider slider; - DoubleModel m; - DoubleModel temperatureModel; - DoubleModel pressureModel; - JSpinner spin; - - // 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 - sub.setBorder(BorderFactory.createTitledBorder(trans - .get("simedtdlg.lbl.Wind"))); - this.add(sub, "growx, split 2, aligny 0, flowy, gapright para"); - - // Wind average - // Average windspeed: - JLabel label = new JLabel(trans.get("simedtdlg.lbl.Averwindspeed")); - // The average windspeed relative to the ground. - tip = trans.get("simedtdlg.lbl.ttip.Averwindspeed"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(preferences, "WindSpeedAverage", - UnitGroup.UNITS_WINDSPEED, 0); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - addEasterEgg(spin); - sub.add(spin, "w 65lp!"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - slider = new BasicSlider(m.getSliderModel(0, 10.0)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - // Wind std. deviation - // // Standard deviation: - label = new JLabel(trans.get("simedtdlg.lbl.Stddeviation")); - // // The standard deviation of the windspeed.
- // // The windspeed is within twice the standard deviation from the - // average for 95% of the time. - tip = trans.get("simedtdlg.lbl.ttip.Stddeviation"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(preferences, "WindSpeedDeviation", - UnitGroup.UNITS_WINDSPEED, 0); - DoubleModel m2 = new DoubleModel(preferences, "WindSpeedAverage", 0.25, - UnitGroup.UNITS_COEFFICIENT, 0); - - 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(new DoubleModel(0), m2)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - - // Wind turbulence intensity - // // Turbulence intensity: - label = new JLabel(trans.get("simedtdlg.lbl.Turbulenceintensity")); - // // The turbulence intensity is the standard deviation divided - // by the average windspeed.
- // // Typical values range from - // // to - tip = trans.get("simedtdlg.lbl.ttip.Turbulenceintensity1") - + trans.get("simedtdlg.lbl.ttip.Turbulenceintensity2") + " " - + UnitGroup.UNITS_RELATIVE.getDefaultUnit().toStringUnit(0.05) - + " " + trans.get("simedtdlg.lbl.ttip.Turbulenceintensity3") - + " " - + UnitGroup.UNITS_RELATIVE.getDefaultUnit().toStringUnit(0.20) - + "."; - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(preferences, "WindTurbulenceIntensity", - UnitGroup.UNITS_RELATIVE, 0); - - 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"); - - final JLabel intensityLabel = new JLabel( - getIntensityDescription(preferences - .getWindTurbulenceIntensity())); - intensityLabel.setToolTipText(tip); - sub.add(intensityLabel, "w 75lp, wrap"); - m.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - intensityLabel.setText(getIntensityDescription(preferences - .getWindTurbulenceIntensity())); - } - }); - - // 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(preferences, "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"); - - // // Temperature and pressure - sub = new JPanel(new MigLayout("fill, gap rel unrel", - "[grow][75lp!][35lp!][75lp!]", "")); - // // Atmospheric preferences - sub.setBorder(BorderFactory.createTitledBorder(trans - .get("simedtdlg.border.Atmoscond"))); - this.add(sub, "growx, aligny 0, gapright para"); - - BooleanModel isa = new BooleanModel(preferences, "ISAAtmosphere"); - JCheckBox check = new JCheckBox(isa); - // // Use International Standard Atmosphere - check.setText(trans.get("simedtdlg.checkbox.InterStdAtmosphere")); - // // Select to use the International Standard Atmosphere model. - // //
This model has a temperature of - // // and a pressure of - // // at sea level. - check.setToolTipText(trans - .get("simedtdlg.checkbox.ttip.InterStdAtmosphere1") - + " " - + UnitGroup.UNITS_TEMPERATURE - .toStringUnit(ExtendedISAModel.STANDARD_TEMPERATURE) - + " " - + trans.get("simedtdlg.checkbox.ttip.InterStdAtmosphere2") - + " " - + UnitGroup.UNITS_PRESSURE - .toStringUnit(ExtendedISAModel.STANDARD_PRESSURE) - + " " - + trans.get("simedtdlg.checkbox.ttip.InterStdAtmosphere3")); - sub.add(check, "spanx, wrap unrel"); - - // Temperature: - label = new JLabel(trans.get("simedtdlg.lbl.Temperature")); - // // The temperature at the launch site. - tip = trans.get("simedtdlg.lbl.ttip.Temperature"); - label.setToolTipText(tip); - isa.addEnableComponent(label, false); - sub.add(label); - - temperatureModel = new DoubleModel(preferences, "LaunchTemperature", - UnitGroup.UNITS_TEMPERATURE, 0); - - spin = new JSpinner(temperatureModel.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - isa.addEnableComponent(spin, false); - sub.add(spin, "growx"); - - unit = new UnitSelector(temperatureModel); - unit.setToolTipText(tip); - isa.addEnableComponent(unit, false); - sub.add(unit, "growx"); - slider = new BasicSlider(temperatureModel.getSliderModel(253.15, 308.15)); // -20 ... - // 35 - slider.setToolTipText(tip); - isa.addEnableComponent(slider, false); - sub.add(slider, "w 75lp, wrap"); - - // Pressure: - label = new JLabel(trans.get("simedtdlg.lbl.Pressure")); - // // The atmospheric pressure at the launch site. - tip = trans.get("simedtdlg.lbl.ttip.Pressure"); - label.setToolTipText(tip); - isa.addEnableComponent(label, false); - sub.add(label); - - pressureModel = new DoubleModel(preferences, "LaunchPressure", - UnitGroup.UNITS_PRESSURE, 0); - - spin = new JSpinner(pressureModel.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - isa.addEnableComponent(spin, false); - sub.add(spin, "growx"); - - unit = new UnitSelector(pressureModel); - unit.setToolTipText(tip); - isa.addEnableComponent(unit, false); - sub.add(unit, "growx"); - slider = new BasicSlider(pressureModel.getSliderModel(0.950e5, 1.050e5)); - slider.setToolTipText(tip); - isa.addEnableComponent(slider, false); - sub.add(slider, "w 75lp, wrap"); - - isa.addChangeListener(new StateChangeListener() { - @Override - public void stateChanged(EventObject e) { - temperatureModel.stateChanged(e); - pressureModel.stateChanged(e); - } - }); - - - // // Launch site preferences - sub = new JPanel(new MigLayout("fill, gap rel unrel", - "[grow][65lp!][30lp!][75lp!]", "")); - // // Launch site - sub.setBorder(BorderFactory.createTitledBorder(trans - .get("simedtdlg.lbl.Launchsite"))); - this.add(sub, "growx, split 2, aligny 0, flowy"); - - // Latitude: - label = new JLabel(trans.get("simedtdlg.lbl.Latitude")); - // // The launch site latitude affects the gravitational pull of - // Earth.
- // // Positive values are on the Northern hemisphere, negative values on - // the Southern hemisphere. - tip = trans.get("simedtdlg.lbl.ttip.Latitude"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(preferences, "LaunchLatitude", - UnitGroup.UNITS_NONE, -90, 90); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "growx"); - - label = new JLabel(Chars.DEGREE + " " + trans.get("CompassRose.lbl.north")); - label.setToolTipText(tip); - sub.add(label, "growx"); - slider = new BasicSlider(m.getSliderModel(-90, 90)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - // Longitude: - label = new JLabel(trans.get("simedtdlg.lbl.Longitude")); - tip = trans.get("simedtdlg.lbl.ttip.Longitude"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(preferences, "LaunchLongitude", - UnitGroup.UNITS_NONE, -180, 180); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "growx"); - - label = new JLabel(Chars.DEGREE + " " + trans.get("CompassRose.lbl.east")); - label.setToolTipText(tip); - sub.add(label, "growx"); - slider = new BasicSlider(m.getSliderModel(-180, 180)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - // Altitude: - label = new JLabel(trans.get("simedtdlg.lbl.Altitude")); - // // The launch altitude above mean sea level.
- // // This affects the position of the rocket in the atmospheric model. - tip = trans.get("simedtdlg.lbl.ttip.Altitude"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(preferences, "LaunchAltitude", - UnitGroup.UNITS_DISTANCE, 0); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "growx"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - slider = new BasicSlider(m.getSliderModel(0, 250, 1000)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - // // Launch rod - sub = new JPanel(new MigLayout("fill, gap rel unrel", - "[grow][65lp!][30lp!][75lp!]", "")); - // // Launch rod - sub.setBorder(BorderFactory.createTitledBorder(trans - .get("simedtdlg.border.Launchrod"))); - this.add(sub, "growx, aligny 0, wrap"); - - // Length: - label = new JLabel(trans.get("simedtdlg.lbl.Length")); - // // The length of the launch rod. - tip = trans.get("simedtdlg.lbl.ttip.Length"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(preferences, "LaunchRodLength", - UnitGroup.UNITS_LENGTH, 0); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "growx"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - slider = new BasicSlider(m.getSliderModel(0, 1, 5)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - // Keep launch rod parallel to the wind. - - BooleanModel intoWind = new BooleanModel(preferences, "LaunchIntoWind"); - JCheckBox checkWind = new JCheckBox(intoWind); - // // Use International Standard Atmosphere - checkWind.setText(trans.get("simedtdlg.checkbox.Intowind")); - checkWind.setToolTipText(trans.get("simedtdlg.checkbox.ttip.Intowind1") - + trans.get("simedtdlg.checkbox.ttip.Intowind2") - + trans.get("simedtdlg.checkbox.ttip.Intowind3") - + trans.get("simedtdlg.checkbox.ttip.Intowind4")); - sub.add(checkWind, "spanx, wrap unrel"); - - // Angle: - label = new JLabel(trans.get("simedtdlg.lbl.Angle")); - // // The angle of the launch rod from vertical. - tip = trans.get("simedtdlg.lbl.ttip.Angle"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(preferences, "LaunchRodAngle", - UnitGroup.UNITS_ANGLE, -SimulationOptions.MAX_LAUNCH_ROD_ANGLE, - SimulationOptions.MAX_LAUNCH_ROD_ANGLE); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "growx"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - slider = new BasicSlider(m.getSliderModel( - -SimulationOptions.MAX_LAUNCH_ROD_ANGLE, 0, - SimulationOptions.MAX_LAUNCH_ROD_ANGLE)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - // Direction: - JLabel directionLabel = new JLabel(trans.get("simedtdlg.lbl.Direction")); - // // Direction of the launch rod. - tip = trans.get("simedtdlg.lbl.ttip.Direction1") - + UnitGroup.UNITS_ANGLE.toStringUnit(0) + " " - + trans.get("simedtdlg.lbl.ttip.Direction2") + " " - + UnitGroup.UNITS_ANGLE.toStringUnit(2 * Math.PI) + " " - + trans.get("simedtdlg.lbl.ttip.Direction3"); - directionLabel.setToolTipText(tip); - sub.add(directionLabel); - - m = new DoubleModel(preferences, "LaunchRodDirection", 1.0, - UnitGroup.UNITS_ANGLE, 0, 2 * Math.PI); - - JSpinner directionSpin = new JSpinner(m.getSpinnerModel()); - directionSpin.setEditor(new SpinnerEditor(directionSpin)); - directionSpin.setToolTipText(tip); - sub.add(directionSpin, "growx"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - BasicSlider directionSlider = new BasicSlider(m.getSliderModel(0, - 2 * Math.PI)); - directionSlider.setToolTipText(tip); - sub.add(directionSlider, "w 75lp, wrap"); - intoWind.addEnableComponent(directionLabel, false); - intoWind.addEnableComponent(directionSpin, false); - intoWind.addEnableComponent(unit, false); - intoWind.addEnableComponent(directionSlider, false); + // Simulation conditions + SimulationConditionsPanel.addSimulationConditionsPanel(this, preferences); } @@ -467,46 +47,4 @@ public class LaunchPreferencesPanel extends PreferencesPanel { darkWarningColor = GUIUtil.getUITheme().getDarkWarningColor(); } - private String getIntensityDescription(double i) { - if (i < 0.001) - // // None - return trans.get("simedtdlg.IntensityDesc.None"); - if (i < 0.05) - // // Very low - return trans.get("simedtdlg.IntensityDesc.Verylow"); - if (i < 0.10) - // // Low - return trans.get("simedtdlg.IntensityDesc.Low"); - if (i < 0.15) - // // Medium - return trans.get("simedtdlg.IntensityDesc.Medium"); - if (i < 0.20) - // // High - return trans.get("simedtdlg.IntensityDesc.High"); - if (i < 0.25) - // // Very high - return trans.get("simedtdlg.IntensityDesc.Veryhigh"); - // // Extreme - return trans.get("simedtdlg.IntensityDesc.Extreme"); - } - - /** - * Shh, don't tell anyone about this easter-egg. (displays a fun quote when the text of the spinner equals 42) - * @param spinner the magic spinner! - */ - private void addEasterEgg(JSpinner spinner) { - JTextField textField = ((JSpinner.DefaultEditor) spinner.getEditor()).getTextField(); - textField.addKeyListener(new KeyAdapter() { - @Override - public void keyTyped(KeyEvent e) { - String text = textField.getText() + e.getKeyChar(); - if (text.equals("42")) { - JOptionPane.showMessageDialog(LaunchPreferencesPanel.this, - "The answer to the ultimate question of life, the universe, and everything.", - "42", JOptionPane.INFORMATION_MESSAGE); - } - } - }); - } - } diff --git a/swing/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java b/swing/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java index 9d11d2010..7c1252657 100644 --- a/swing/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java +++ b/swing/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java @@ -1,15 +1,20 @@ package net.sf.openrocket.gui.simulation; +import java.awt.Component; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; import java.util.EventObject; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JCheckBox; import javax.swing.JLabel; +import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JSpinner; +import javax.swing.JTextField; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; @@ -24,6 +29,7 @@ import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.models.atmosphere.ExtendedISAModel; import net.sf.openrocket.simulation.DefaultSimulationOptionFactory; import net.sf.openrocket.simulation.SimulationOptions; +import net.sf.openrocket.simulation.SimulationOptionsInterface; import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; import net.sf.openrocket.util.Chars; @@ -38,405 +44,11 @@ public class SimulationConditionsPanel extends JPanel { super(new MigLayout("fill")); final SimulationOptions conditions = simulation.getOptions(); - - JPanel sub; - String tip; - UnitSelector unit; - BasicSlider slider; - DoubleModel m; - JSpinner spin; - DoubleModel temperatureModel; - DoubleModel pressureModel; - - //// 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 - sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.lbl.Wind"))); - this.add(sub, "growx, split 2, aligny 0, flowy, gapright para"); - - - // Wind average - //// Average windspeed: - JLabel label = new JLabel(trans.get("simedtdlg.lbl.Averwindspeed")); - //// The average windspeed relative to the ground. - tip = trans.get("simedtdlg.lbl.ttip.Averwindspeed"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(conditions, "WindSpeedAverage", UnitGroup.UNITS_WINDSPEED, 0); - - 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, 10.0)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - - - // Wind std. deviation - //// Standard deviation: - label = new JLabel(trans.get("simedtdlg.lbl.Stddeviation")); - //// The standard deviation of the windspeed.
- //// The windspeed is within twice the standard deviation from the average for 95% of the time. - tip = trans.get("simedtdlg.lbl.ttip.Stddeviation"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(conditions, "WindSpeedDeviation", UnitGroup.UNITS_WINDSPEED, 0); - DoubleModel m2 = new DoubleModel(conditions, "WindSpeedAverage", 0.25, - UnitGroup.UNITS_COEFFICIENT, 0); - - 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(new DoubleModel(0), m2)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - - - - - // Wind turbulence intensity - //// Turbulence intensity: - label = new JLabel(trans.get("simedtdlg.lbl.Turbulenceintensity")); - //// The turbulence intensity is the standard deviation divided by the average windspeed.
- //// Typical values range from - //// to - tip = trans.get("simedtdlg.lbl.ttip.Turbulenceintensity1") + - trans.get("simedtdlg.lbl.ttip.Turbulenceintensity2") + " " + - UnitGroup.UNITS_RELATIVE.getDefaultUnit().toStringUnit(0.05) + - " " + trans.get("simedtdlg.lbl.ttip.Turbulenceintensity3") + " " + - UnitGroup.UNITS_RELATIVE.getDefaultUnit().toStringUnit(0.20) + "."; - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(conditions, "WindTurbulenceIntensity", UnitGroup.UNITS_RELATIVE, 0); - - 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"); - - final JLabel intensityLabel = new JLabel( - getIntensityDescription(conditions.getWindTurbulenceIntensity())); - intensityLabel.setToolTipText(tip); - sub.add(intensityLabel, "w 75lp, wrap"); - m.addChangeListener(new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - intensityLabel.setText( - getIntensityDescription(conditions.getWindTurbulenceIntensity())); - } - }); - - // 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"); - - - - - //// Temperature and pressure - sub = new JPanel(new MigLayout("fill, gap rel unrel", - "[grow][75lp!][35lp!][75lp!]", "")); - //// Atmospheric conditions - sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.border.Atmoscond"))); - this.add(sub, "growx, aligny 0, gapright para"); - - - BooleanModel isa = new BooleanModel(conditions, "ISAAtmosphere"); - JCheckBox check = new JCheckBox(isa); - //// Use International Standard Atmosphere - check.setText(trans.get("simedtdlg.checkbox.InterStdAtmosphere")); - //// Select to use the International Standard Atmosphere model. - ////
This model has a temperature of - //// and a pressure of - //// at sea level. - check.setToolTipText(trans.get("simedtdlg.checkbox.ttip.InterStdAtmosphere1") + " " + - UnitGroup.UNITS_TEMPERATURE.toStringUnit(ExtendedISAModel.STANDARD_TEMPERATURE) + - " " + trans.get("simedtdlg.checkbox.ttip.InterStdAtmosphere2") + " " + - UnitGroup.UNITS_PRESSURE.toStringUnit(ExtendedISAModel.STANDARD_PRESSURE) + - " " + trans.get("simedtdlg.checkbox.ttip.InterStdAtmosphere3")); - sub.add(check, "spanx, wrap unrel"); - - // Temperature: - label = new JLabel(trans.get("simedtdlg.lbl.Temperature")); - //// The temperature at the launch site. - tip = trans.get("simedtdlg.lbl.ttip.Temperature"); - label.setToolTipText(tip); - isa.addEnableComponent(label, false); - sub.add(label); - temperatureModel = new DoubleModel(conditions, "LaunchTemperature", UnitGroup.UNITS_TEMPERATURE, 0); - - spin = new JSpinner(temperatureModel.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - isa.addEnableComponent(spin, false); - sub.add(spin, "growx"); - - unit = new UnitSelector(temperatureModel); - unit.setToolTipText(tip); - isa.addEnableComponent(unit, false); - sub.add(unit, "growx"); - slider = new BasicSlider(temperatureModel.getSliderModel(253.15, 308.15)); // -20 ... 35 - slider.setToolTipText(tip); - isa.addEnableComponent(slider, false); - sub.add(slider, "w 75lp, wrap"); - - - - // Pressure: - label = new JLabel(trans.get("simedtdlg.lbl.Pressure")); - //// The atmospheric pressure at the launch site. - tip = trans.get("simedtdlg.lbl.ttip.Pressure"); - label.setToolTipText(tip); - isa.addEnableComponent(label, false); - sub.add(label); - - pressureModel = new DoubleModel(conditions, "LaunchPressure", UnitGroup.UNITS_PRESSURE, 0); - - spin = new JSpinner(pressureModel.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - isa.addEnableComponent(spin, false); - sub.add(spin, "growx"); - - unit = new UnitSelector(pressureModel); - unit.setToolTipText(tip); - isa.addEnableComponent(unit, false); - sub.add(unit, "growx"); - slider = new BasicSlider(pressureModel.getSliderModel(0.950e5, 1.050e5)); - slider.setToolTipText(tip); - isa.addEnableComponent(slider, false); - sub.add(slider, "w 75lp, wrap"); + // Simulation conditions settings + addSimulationConditionsPanel(this, conditions); - isa.addChangeListener(new StateChangeListener() { - @Override - public void stateChanged(EventObject e) { - temperatureModel.stateChanged(e); - pressureModel.stateChanged(e); - } - }); - - - - //// Launch site conditions - sub = new JPanel(new MigLayout("fill, gap rel unrel", - "[grow][65lp!][30lp!][75lp!]", "")); - //// Launch site - sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.lbl.Launchsite"))); - this.add(sub, "growx, split 2, aligny 0, flowy"); - - - // Latitude: - label = new JLabel(trans.get("simedtdlg.lbl.Latitude")); - //// The launch site latitude affects the gravitational pull of Earth.
- //// Positive values are on the Northern hemisphere, negative values on the Southern hemisphere. - tip = trans.get("simedtdlg.lbl.ttip.Latitude"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(conditions, "LaunchLatitude", UnitGroup.UNITS_NONE, -90, 90); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "w 65lp!"); - - label = new JLabel(Chars.DEGREE + " N"); - label.setToolTipText(tip); - sub.add(label, "growx"); - slider = new BasicSlider(m.getSliderModel(-90, 90)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - - // Longitude: - label = new JLabel(trans.get("simedtdlg.lbl.Longitude")); - tip = trans.get("simedtdlg.lbl.ttip.Longitude"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(conditions, "LaunchLongitude", UnitGroup.UNITS_NONE, -180, 180); - - spin = new JSpinner(m.getSpinnerModel()); - spin.setEditor(new SpinnerEditor(spin)); - spin.setToolTipText(tip); - sub.add(spin, "w 65lp!"); - - label = new JLabel(Chars.DEGREE + " E"); - label.setToolTipText(tip); - sub.add(label, "growx"); - slider = new BasicSlider(m.getSliderModel(-180, 180)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - - // Altitude: - label = new JLabel(trans.get("simedtdlg.lbl.Altitude")); - //// The launch altitude above mean sea level.
- //// This affects the position of the rocket in the atmospheric model. - tip = trans.get("simedtdlg.lbl.ttip.Altitude"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(conditions, "LaunchAltitude", UnitGroup.UNITS_DISTANCE, 0); - - 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, 250, 1000)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - - - - - //// Launch rod - sub = new JPanel(new MigLayout("fill, gap rel unrel", - "[grow][65lp!][30lp!][75lp!]", "")); - //// Launch rod - sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.border.Launchrod"))); - this.add(sub, "growx, aligny 0, wrap"); - - - // Length: - label = new JLabel(trans.get("simedtdlg.lbl.Length")); - //// The length of the launch rod. - tip = trans.get("simedtdlg.lbl.ttip.Length"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(conditions, "LaunchRodLength", UnitGroup.UNITS_LENGTH, 0); - - 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, 1, 5)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - // Keep launch rod parallel to the wind. - - BooleanModel intoWind = new BooleanModel(conditions, "LaunchIntoWind"); - JCheckBox checkWind = new JCheckBox(intoWind); - //// Use International Standard Atmosphere - checkWind.setText(trans.get("simedtdlg.checkbox.Intowind")); - checkWind.setToolTipText( - trans.get("simedtdlg.checkbox.ttip.Intowind1") + - trans.get("simedtdlg.checkbox.ttip.Intowind2") + - trans.get("simedtdlg.checkbox.ttip.Intowind3") + - trans.get("simedtdlg.checkbox.ttip.Intowind4")); - sub.add(checkWind, "spanx, wrap unrel"); - - - // Angle: - label = new JLabel(trans.get("simedtdlg.lbl.Angle")); - //// The angle of the launch rod from vertical. - tip = trans.get("simedtdlg.lbl.ttip.Angle"); - label.setToolTipText(tip); - sub.add(label); - - m = new DoubleModel(conditions, "LaunchRodAngle", UnitGroup.UNITS_ANGLE, - -SimulationOptions.MAX_LAUNCH_ROD_ANGLE, SimulationOptions.MAX_LAUNCH_ROD_ANGLE); - - 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(-SimulationOptions.MAX_LAUNCH_ROD_ANGLE, 0, - SimulationOptions.MAX_LAUNCH_ROD_ANGLE)); - slider.setToolTipText(tip); - sub.add(slider, "w 75lp, wrap"); - - - - // Direction: - JLabel directionLabel = new JLabel(trans.get("simedtdlg.lbl.Direction")); - //// Direction of the launch rod. - tip = trans.get("simedtdlg.lbl.ttip.Direction1") + - UnitGroup.UNITS_ANGLE.toStringUnit(0) + - " " + trans.get("simedtdlg.lbl.ttip.Direction2") + " " + - UnitGroup.UNITS_ANGLE.toStringUnit(2*Math.PI) + - " " + trans.get("simedtdlg.lbl.ttip.Direction3"); - directionLabel.setToolTipText(tip); - sub.add(directionLabel); - - m = new DoubleModel(conditions, "LaunchRodDirection", 1.0, UnitGroup.UNITS_ANGLE, - 0, 2*Math.PI); - - JSpinner directionSpin = new JSpinner(m.getSpinnerModel()); - directionSpin.setEditor(new SpinnerEditor(directionSpin)); - directionSpin.setToolTipText(tip); - sub.add(directionSpin, "w 65lp!"); - - unit = new UnitSelector(m); - unit.setToolTipText(tip); - sub.add(unit, "growx"); - BasicSlider directionSlider = new BasicSlider(m.getSliderModel(0, 2*Math.PI)); - directionSlider.setToolTipText(tip); - sub.add(directionSlider, "w 75lp, wrap"); - intoWind.addEnableComponent(directionLabel, false); - intoWind.addEnableComponent(directionSpin, false); - intoWind.addEnableComponent(unit, false); - intoWind.addEnableComponent(directionSlider, false); - - - - - JButton restoreDefaults = new SelectColorButton(trans.get("simedtdlg.but.resettodefault")); restoreDefaults.addActionListener(new ActionListener() { @@ -468,8 +80,398 @@ public class SimulationConditionsPanel extends JPanel { this.add(saveDefaults, "gapbottom para, gapright para, right"); } - - private String getIntensityDescription(double i) { + + /** + * Adds the simulation conditions panel to the parent panel. + * @param parent The parent panel. + * @param target The object containing the simulation conditions setters/getters. + */ + public static void addSimulationConditionsPanel(JPanel parent, SimulationOptionsInterface target) { + JPanel sub; + DoubleModel pressureModel; + DoubleModel m; + JSpinner spin; + DoubleModel temperatureModel; + String tip; + BasicSlider slider; + UnitSelector unit; + + //// Wind settings: Average wind speed, turbulence intensity, std. deviation, and direction + sub = new JPanel(new MigLayout("fill, gap rel unrel", + "[grow][75lp!][30lp!][75lp!]", "")); + //// Wind + sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.lbl.Wind"))); + parent.add(sub, "growx, split 2, aligny 0, flowy, gapright para"); + + + // Wind average + //// Average windspeed: + JLabel label = new JLabel(trans.get("simedtdlg.lbl.Averwindspeed")); + //// The average windspeed relative to the ground. + tip = trans.get("simedtdlg.lbl.ttip.Averwindspeed"); + label.setToolTipText(tip); + sub.add(label); + + m = new DoubleModel(target, "WindSpeedAverage", UnitGroup.UNITS_WINDSPEED, 0); + + 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, 10.0)); + slider.setToolTipText(tip); + sub.add(slider, "w 75lp, wrap"); + + + // Wind std. deviation + //// Standard deviation: + label = new JLabel(trans.get("simedtdlg.lbl.Stddeviation")); + //// The standard deviation of the windspeed.
+ //// The windspeed is within twice the standard deviation from the average for 95% of the time. + tip = trans.get("simedtdlg.lbl.ttip.Stddeviation"); + label.setToolTipText(tip); + sub.add(label); + + m = new DoubleModel(target, "WindSpeedDeviation", UnitGroup.UNITS_WINDSPEED, 0); + DoubleModel m2 = new DoubleModel(target, "WindSpeedAverage", 0.25, + UnitGroup.UNITS_COEFFICIENT, 0); + + spin = new JSpinner(m.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + addEasterEgg(spin, parent); + sub.add(spin, "w 65lp!"); + + unit = new UnitSelector(m); + unit.setToolTipText(tip); + sub.add(unit, "growx"); + slider = new BasicSlider(m.getSliderModel(new DoubleModel(0), m2)); + slider.setToolTipText(tip); + sub.add(slider, "w 75lp, wrap"); + + + // Wind turbulence intensity + //// Turbulence intensity: + label = new JLabel(trans.get("simedtdlg.lbl.Turbulenceintensity")); + //// The turbulence intensity is the standard deviation divided by the average windspeed.
+ //// Typical values range from + //// to + tip = trans.get("simedtdlg.lbl.ttip.Turbulenceintensity1") + + trans.get("simedtdlg.lbl.ttip.Turbulenceintensity2") + " " + + UnitGroup.UNITS_RELATIVE.getDefaultUnit().toStringUnit(0.05) + + " " + trans.get("simedtdlg.lbl.ttip.Turbulenceintensity3") + " " + + UnitGroup.UNITS_RELATIVE.getDefaultUnit().toStringUnit(0.20) + "."; + label.setToolTipText(tip); + sub.add(label); + + m = new DoubleModel(target, "WindTurbulenceIntensity", UnitGroup.UNITS_RELATIVE, 0); + + 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"); + + final JLabel intensityLabel = new JLabel( + getIntensityDescription(target.getWindTurbulenceIntensity())); + intensityLabel.setToolTipText(tip); + sub.add(intensityLabel, "w 75lp, wrap"); + m.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + intensityLabel.setText( + getIntensityDescription(target.getWindTurbulenceIntensity())); + } + }); + + // 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(target, "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"); + + + //// Temperature and pressure + sub = new JPanel(new MigLayout("fill, gap rel unrel", + "[grow][85lp!][35lp!][75lp!]", "")); + //// Atmospheric conditions + sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.border.Atmoscond"))); + parent.add(sub, "growx, aligny 0, gapright para"); + + + BooleanModel isa = new BooleanModel(target, "ISAAtmosphere"); + JCheckBox check = new JCheckBox(isa); + //// Use International Standard Atmosphere + check.setText(trans.get("simedtdlg.checkbox.InterStdAtmosphere")); + //// Select to use the International Standard Atmosphere model. + ////
This model has a temperature of + //// and a pressure of + //// at sea level. + check.setToolTipText(trans.get("simedtdlg.checkbox.ttip.InterStdAtmosphere1") + " " + + UnitGroup.UNITS_TEMPERATURE.toStringUnit(ExtendedISAModel.STANDARD_TEMPERATURE) + + " " + trans.get("simedtdlg.checkbox.ttip.InterStdAtmosphere2") + " " + + UnitGroup.UNITS_PRESSURE.toStringUnit(ExtendedISAModel.STANDARD_PRESSURE) + + " " + trans.get("simedtdlg.checkbox.ttip.InterStdAtmosphere3")); + sub.add(check, "spanx, wrap unrel"); + + // Temperature: + label = new JLabel(trans.get("simedtdlg.lbl.Temperature")); + //// The temperature at the launch site. + tip = trans.get("simedtdlg.lbl.ttip.Temperature"); + label.setToolTipText(tip); + isa.addEnableComponent(label, false); + sub.add(label); + + temperatureModel = new DoubleModel(target, "LaunchTemperature", UnitGroup.UNITS_TEMPERATURE, 0); + + spin = new JSpinner(temperatureModel.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + isa.addEnableComponent(spin, false); + sub.add(spin, "growx"); + + unit = new UnitSelector(temperatureModel); + unit.setToolTipText(tip); + isa.addEnableComponent(unit, false); + sub.add(unit, "growx"); + slider = new BasicSlider(temperatureModel.getSliderModel(253.15, 308.15)); // -20 ... 35 + slider.setToolTipText(tip); + isa.addEnableComponent(slider, false); + sub.add(slider, "w 75lp, wrap"); + + + // Pressure: + label = new JLabel(trans.get("simedtdlg.lbl.Pressure")); + //// The atmospheric pressure at the launch site. + tip = trans.get("simedtdlg.lbl.ttip.Pressure"); + label.setToolTipText(tip); + isa.addEnableComponent(label, false); + sub.add(label); + + pressureModel = new DoubleModel(target, "LaunchPressure", UnitGroup.UNITS_PRESSURE, 0); + + spin = new JSpinner(pressureModel.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + isa.addEnableComponent(spin, false); + sub.add(spin, "growx"); + + unit = new UnitSelector(pressureModel); + unit.setToolTipText(tip); + isa.addEnableComponent(unit, false); + sub.add(unit, "growx"); + slider = new BasicSlider(pressureModel.getSliderModel(0.950e5, 1.050e5)); + slider.setToolTipText(tip); + isa.addEnableComponent(slider, false); + sub.add(slider, "w 75lp, wrap"); + + + isa.addChangeListener(new StateChangeListener() { + @Override + public void stateChanged(EventObject e) { + temperatureModel.stateChanged(e); + pressureModel.stateChanged(e); + } + }); + + + //// Launch site conditions + sub = new JPanel(new MigLayout("fill, gap rel unrel", + "[grow][65lp!][30lp!][75lp!]", "")); + //// Launch site + sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.lbl.Launchsite"))); + parent.add(sub, "growx, split 2, aligny 0, flowy"); + + + // Latitude: + label = new JLabel(trans.get("simedtdlg.lbl.Latitude")); + //// The launch site latitude affects the gravitational pull of Earth.
+ //// Positive values are on the Northern hemisphere, negative values on the Southern hemisphere. + tip = trans.get("simedtdlg.lbl.ttip.Latitude"); + label.setToolTipText(tip); + sub.add(label); + + m = new DoubleModel(target, "LaunchLatitude", UnitGroup.UNITS_NONE, -90, 90); + + spin = new JSpinner(m.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + sub.add(spin, "w 65lp!"); + + label = new JLabel(Chars.DEGREE + " N"); + label.setToolTipText(tip); + sub.add(label, "growx"); + slider = new BasicSlider(m.getSliderModel(-90, 90)); + slider.setToolTipText(tip); + sub.add(slider, "w 75lp, wrap"); + + + // Longitude: + label = new JLabel(trans.get("simedtdlg.lbl.Longitude")); + tip = trans.get("simedtdlg.lbl.ttip.Longitude"); + label.setToolTipText(tip); + sub.add(label); + + m = new DoubleModel(target, "LaunchLongitude", UnitGroup.UNITS_NONE, -180, 180); + + spin = new JSpinner(m.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + sub.add(spin, "w 65lp!"); + + label = new JLabel(Chars.DEGREE + " E"); + label.setToolTipText(tip); + sub.add(label, "growx"); + slider = new BasicSlider(m.getSliderModel(-180, 180)); + slider.setToolTipText(tip); + sub.add(slider, "w 75lp, wrap"); + + + // Altitude: + label = new JLabel(trans.get("simedtdlg.lbl.Altitude")); + //// The launch altitude above mean sea level.
+ //// This affects the position of the rocket in the atmospheric model. + tip = trans.get("simedtdlg.lbl.ttip.Altitude"); + label.setToolTipText(tip); + sub.add(label); + + m = new DoubleModel(target, "LaunchAltitude", UnitGroup.UNITS_DISTANCE, 0); + + 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, 250, 1000)); + slider.setToolTipText(tip); + sub.add(slider, "w 75lp, wrap"); + + + //// Launch rod + sub = new JPanel(new MigLayout("fill, gap rel unrel", + "[grow][75lp!][30lp!][75lp!]", "")); + //// Launch rod + sub.setBorder(BorderFactory.createTitledBorder(trans.get("simedtdlg.border.Launchrod"))); + parent.add(sub, "growx, aligny 0, wrap"); + + + // Length: + label = new JLabel(trans.get("simedtdlg.lbl.Length")); + //// The length of the launch rod. + tip = trans.get("simedtdlg.lbl.ttip.Length"); + label.setToolTipText(tip); + sub.add(label); + + m = new DoubleModel(target, "LaunchRodLength", UnitGroup.UNITS_LENGTH, 0); + + spin = new JSpinner(m.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + sub.add(spin, "growx"); + + unit = new UnitSelector(m); + unit.setToolTipText(tip); + sub.add(unit, "growx"); + slider = new BasicSlider(m.getSliderModel(0, 1, 5)); + slider.setToolTipText(tip); + sub.add(slider, "w 75lp, wrap"); + + // Keep launch rod parallel to the wind. + + BooleanModel intoWind = new BooleanModel(target, "LaunchIntoWind"); + JCheckBox checkWind = new JCheckBox(intoWind); + //// Use International Standard Atmosphere + checkWind.setText(trans.get("simedtdlg.checkbox.Intowind")); + checkWind.setToolTipText( + trans.get("simedtdlg.checkbox.ttip.Intowind1") + + trans.get("simedtdlg.checkbox.ttip.Intowind2") + + trans.get("simedtdlg.checkbox.ttip.Intowind3") + + trans.get("simedtdlg.checkbox.ttip.Intowind4")); + sub.add(checkWind, "spanx, wrap unrel"); + + + // Angle: + label = new JLabel(trans.get("simedtdlg.lbl.Angle")); + //// The angle of the launch rod from vertical. + tip = trans.get("simedtdlg.lbl.ttip.Angle"); + label.setToolTipText(tip); + sub.add(label); + + m = new DoubleModel(target, "LaunchRodAngle", UnitGroup.UNITS_ANGLE, + -SimulationOptions.MAX_LAUNCH_ROD_ANGLE, SimulationOptions.MAX_LAUNCH_ROD_ANGLE); + + spin = new JSpinner(m.getSpinnerModel()); + spin.setEditor(new SpinnerEditor(spin)); + spin.setToolTipText(tip); + sub.add(spin, "growx"); + + unit = new UnitSelector(m); + unit.setToolTipText(tip); + sub.add(unit, "growx"); + slider = new BasicSlider(m.getSliderModel(-SimulationOptions.MAX_LAUNCH_ROD_ANGLE, 0, + SimulationOptions.MAX_LAUNCH_ROD_ANGLE)); + slider.setToolTipText(tip); + sub.add(slider, "w 75lp, wrap"); + + + // Direction: + JLabel directionLabel = new JLabel(trans.get("simedtdlg.lbl.Direction")); + //// Direction of the launch rod. + tip = trans.get("simedtdlg.lbl.ttip.Direction1") + + UnitGroup.UNITS_ANGLE.toStringUnit(0) + + " " + trans.get("simedtdlg.lbl.ttip.Direction2") + " " + + UnitGroup.UNITS_ANGLE.toStringUnit(2*Math.PI) + + " " + trans.get("simedtdlg.lbl.ttip.Direction3"); + directionLabel.setToolTipText(tip); + sub.add(directionLabel); + + m = new DoubleModel(target, "LaunchRodDirection", 1.0, UnitGroup.UNITS_ANGLE, + 0, 2*Math.PI); + + JSpinner directionSpin = new JSpinner(m.getSpinnerModel()); + directionSpin.setEditor(new SpinnerEditor(directionSpin)); + directionSpin.setToolTipText(tip); + sub.add(directionSpin, "growx"); + + unit = new UnitSelector(m); + unit.setToolTipText(tip); + sub.add(unit, "growx"); + BasicSlider directionSlider = new BasicSlider(m.getSliderModel(0, 2*Math.PI)); + directionSlider.setToolTipText(tip); + sub.add(directionSlider, "w 75lp, wrap"); + intoWind.addEnableComponent(directionLabel, false); + intoWind.addEnableComponent(directionSpin, false); + intoWind.addEnableComponent(unit, false); + intoWind.addEnableComponent(directionSlider, false); + } + + private static String getIntensityDescription(double i) { if (i < 0.001) //// None return trans.get("simedtdlg.IntensityDesc.None"); @@ -491,5 +493,23 @@ public class SimulationConditionsPanel extends JPanel { //// Extreme return trans.get("simedtdlg.IntensityDesc.Extreme"); } - + + /** + * Shh, don't tell anyone about this easter-egg. (displays a fun quote when the text of the spinner equals 42) + * @param spinner the magic spinner! + */ + private static void addEasterEgg(JSpinner spinner, Component parent) { + JTextField textField = ((JSpinner.DefaultEditor) spinner.getEditor()).getTextField(); + textField.addKeyListener(new KeyAdapter() { + @Override + public void keyTyped(KeyEvent e) { + String text = textField.getText() + e.getKeyChar(); + if (text.equals("42")) { + JOptionPane.showMessageDialog(parent, + "The answer to the ultimate question of life, the universe, and everything.", + "42", JOptionPane.INFORMATION_MESSAGE); + } + } + }); + } } diff --git a/swing/src/net/sf/openrocket/gui/util/SwingPreferences.java b/swing/src/net/sf/openrocket/gui/util/SwingPreferences.java index e544fcd8d..44bdd5736 100644 --- a/swing/src/net/sf/openrocket/gui/util/SwingPreferences.java +++ b/swing/src/net/sf/openrocket/gui/util/SwingPreferences.java @@ -32,6 +32,7 @@ import net.sf.openrocket.rocketcomponent.RailButton; import net.sf.openrocket.rocketcomponent.RecoveryDevice; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.TubeFinSet; +import net.sf.openrocket.simulation.SimulationOptionsInterface; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -50,7 +51,7 @@ import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.BuildProperties; -public class SwingPreferences extends net.sf.openrocket.startup.Preferences { +public class SwingPreferences extends net.sf.openrocket.startup.Preferences implements SimulationOptionsInterface { private static final Logger log = LoggerFactory.getLogger(SwingPreferences.class); private static final String SPLIT_CHARACTER = "|"; From b36950651ee79c517e5b8d0baf5d577cd99fd9fa Mon Sep 17 00:00:00 2001 From: JoePfeiffer Date: Wed, 15 Nov 2023 11:45:40 -0700 Subject: [PATCH 05/10] clean up FlightEventsTest --- .../simulation/FlightEventsTest.java | 106 ++++++++---------- 1 file changed, 49 insertions(+), 57 deletions(-) diff --git a/core/test/net/sf/openrocket/simulation/FlightEventsTest.java b/core/test/net/sf/openrocket/simulation/FlightEventsTest.java index 4c4d55bab..5c6b8c95d 100644 --- a/core/test/net/sf/openrocket/simulation/FlightEventsTest.java +++ b/core/test/net/sf/openrocket/simulation/FlightEventsTest.java @@ -32,6 +32,10 @@ public class FlightEventsTest extends BaseTestCase { @Test public void testSingleStage() throws SimulationException { final Rocket rocket = TestRockets.makeEstesAlphaIII(); + final AxialStage stage = rocket.getStage(0); + final InnerTube motorMountTube = (InnerTube) stage.getChild(1).getChild(2); + final Parachute parachute = (Parachute) stage.getChild(1).getChild(3); + final Simulation sim = new Simulation(rocket); sim.getOptions().setISAAtmosphere(true); sim.getOptions().setTimeStep(0.05); @@ -43,41 +47,24 @@ public class FlightEventsTest extends BaseTestCase { final int branchCount = sim.getSimulatedData().getBranchCount(); assertEquals(" Single stage simulation invalid branch count ", 1, branchCount); - final FlightEvent.Type[] expectedEventTypes = {FlightEvent.Type.LAUNCH, FlightEvent.Type.IGNITION, FlightEvent.Type.LIFTOFF, - FlightEvent.Type.LAUNCHROD, FlightEvent.Type.BURNOUT, FlightEvent.Type.EJECTION_CHARGE, FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT, - FlightEvent.Type.APOGEE, FlightEvent.Type.GROUND_HIT, FlightEvent.Type.SIMULATION_END}; - final double[] expectedEventTimes = {0.0, 0.0, 0.1275, 0.13, 2.0, 2.0, 2.001, 2.48338}; // Ground hit time is too variable, so don't include it - final AxialStage stage = rocket.getStage(0); - final InnerTube motorMountTube = (InnerTube) stage.getChild(1).getChild(2); - final Parachute parachute = (Parachute) stage.getChild(1).getChild(3); - final RocketComponent[] expectedSources = {rocket, motorMountTube, null, null, motorMountTube, - stage, parachute, rocket, null, null}; - - // Test event count - FlightDataBranch branch = sim.getSimulatedData().getBranch(0); - List eventList = branch.getEvents(); - List eventTypes = eventList.stream().map(FlightEvent::getType).collect(Collectors.toList()); - assertEquals(" Single stage simulation invalid number of events ", expectedEventTypes.length, eventTypes.size()); - - // Test that all expected events are present, and in the right order - for (int i = 0; i < expectedEventTypes.length; i++) { - assertSame(" Flight type " + expectedEventTypes[i] + " not found in single stage simulation ", - expectedEventTypes[i], eventTypes.get(i)); - } - - // Test that the event times are correct - for (int i = 0; i < expectedEventTimes.length; i++) { - assertEquals(" Flight type " + expectedEventTypes[i] + " has wrong time ", - expectedEventTimes[i], eventList.get(i).getTime(), EPSILON); - - } - - // Test that the event sources are correct - for (int i = 0; i < expectedSources.length; i++) { - assertEquals(" Flight type " + expectedEventTypes[i] + " has wrong source ", - expectedSources[i], eventList.get(i).getSource()); - } - } + final FlightEvent[] expectedEvents = new FlightEvent[] { + new FlightEvent(FlightEvent.Type.LAUNCH, 0.0, rocket), + new FlightEvent(FlightEvent.Type.IGNITION, 0.0, motorMountTube), + new FlightEvent(FlightEvent.Type.LIFTOFF, 0.1275, null), + new FlightEvent(FlightEvent.Type.LAUNCHROD, 0.13, null), + new FlightEvent(FlightEvent.Type.BURNOUT, 2.0, motorMountTube), + new FlightEvent(FlightEvent.Type.EJECTION_CHARGE, 2.0, stage), + new FlightEvent(FlightEvent.Type.RECOVERY_DEVICE_DEPLOYMENT, 2.001, parachute), + new FlightEvent(FlightEvent.Type.APOGEE, 2.48338, rocket), + new FlightEvent(FlightEvent.Type.GROUND_HIT, 1200, null), + new FlightEvent(FlightEvent.Type.SIMULATION_END, 1200, null) + }; + // final double[] expectedEventTimes = {0.0, 0.0, 0.1275, 0.13, 2.0, 2.0, 2.001, 2.48338}; // Ground hit time is too variable, so don't include it + // final RocketComponent[] expectedSources = {rocket, motorMountTube, null, null, motorMountTube, + // stage, parachute, rocket, null, null}; + + checkEvents(expectedEvents, sim, 0); + } /** * Tests for a multi-stage design. @@ -156,29 +143,34 @@ public class FlightEventsTest extends BaseTestCase { throw new IllegalStateException("Invalid branch number " + b); } - // Test event count - final FlightDataBranch branch = sim.getSimulatedData().getBranch(b); - final FlightEvent[] events = branch.getEvents().toArray(new FlightEvent[0]); - assertEquals(" Multi-stage simulation, branch " + b + " invalid number of events ", expectedEvents.length, events.length); + checkEvents(expectedEvents, sim, b); + } + } - // Test that all expected events are present, in the right order, at the right time, from the right sources - for (int i = 0; i < events.length; i++) { - final FlightEvent expected = expectedEvents[i]; - final FlightEvent actual = events[i]; - assertSame("Branch " + b + " FlightEvent " + i + " type " + expected.getType() + " not found; FlightEvent " + actual.getType() + " found instead", - expected.getType(), actual.getType()); + private void checkEvents(FlightEvent[] expectedEvents, Simulation sim, int branchNo) { - if (1200 != expected.getTime()) { - // Tumbling can have a very large time error, so implement a more course epsilon (otherwise unit tests just keep failing...) - double epsilon = actual.getType() == FlightEvent.Type.TUMBLE || actual.getType() == FlightEvent.Type.APOGEE ? 0.05 : EPSILON; - assertEquals("Branch " + b + " FlightEvent " + i + " type " + expected.getType() + " has wrong time ", - expected.getTime(), actual.getTime(), epsilon); - } + FlightEvent[] actualEvents = sim.getSimulatedData().getBranch(branchNo).getEvents().toArray(new FlightEvent[0]); + + // Test event count + assertEquals("Branch " + branchNo + " invalid number of events ", expectedEvents.length, actualEvents.length); - // Test that the event sources are correct - assertEquals("Branch " + b + " FlightEvent " + i + " type " + expected.getType() + " has wrong source ", - expected.getSource(), actual.getSource()); - } - } - } + // Test that all expected events are present, in the right order, at the right time, from the right sources + for (int i = 0; i < actualEvents.length; i++) { + final FlightEvent expected = expectedEvents[i]; + final FlightEvent actual = actualEvents[i]; + assertSame("Branch " + branchNo + " FlightEvent " + i + " type " + expected.getType() + " not found; FlightEvent " + actual.getType() + " found instead", + expected.getType(), actual.getType()); + + if (1200 != expected.getTime()) { + // event times that are dependent on simulation step time shouldn't be held to tighter bounds than that + double epsilon = actual.getType() == FlightEvent.Type.TUMBLE || actual.getType() == FlightEvent.Type.APOGEE ? sim.getOptions().getTimeStep() : EPSILON; + assertEquals("Branch " + branchNo + " FlightEvent " + i + " type " + expected.getType() + " has wrong time ", + expected.getTime(), actual.getTime(), epsilon); + } + + // Test that the event sources are correct + assertEquals("Branch " + branchNo + " FlightEvent " + i + " type " + expected.getType() + " has wrong source ", + expected.getSource(), actual.getSource()); + } + } } From e5554e0f1de24e0072774e753ed1c583291e7318 Mon Sep 17 00:00:00 2001 From: JoePfeiffer Date: Wed, 15 Nov 2023 11:48:33 -0700 Subject: [PATCH 06/10] oops, left some commented out code in there --- core/test/net/sf/openrocket/simulation/FlightEventsTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/core/test/net/sf/openrocket/simulation/FlightEventsTest.java b/core/test/net/sf/openrocket/simulation/FlightEventsTest.java index 5c6b8c95d..442edb574 100644 --- a/core/test/net/sf/openrocket/simulation/FlightEventsTest.java +++ b/core/test/net/sf/openrocket/simulation/FlightEventsTest.java @@ -59,9 +59,6 @@ public class FlightEventsTest extends BaseTestCase { new FlightEvent(FlightEvent.Type.GROUND_HIT, 1200, null), new FlightEvent(FlightEvent.Type.SIMULATION_END, 1200, null) }; - // final double[] expectedEventTimes = {0.0, 0.0, 0.1275, 0.13, 2.0, 2.0, 2.001, 2.48338}; // Ground hit time is too variable, so don't include it - // final RocketComponent[] expectedSources = {rocket, motorMountTube, null, null, motorMountTube, - // stage, parachute, rocket, null, null}; checkEvents(expectedEvents, sim, 0); } From f481581946d54c90e545336ed0a70397c7b41f97 Mon Sep 17 00:00:00 2001 From: Sibo Van Gool Date: Thu, 16 Nov 2023 16:10:33 +0100 Subject: [PATCH 07/10] Update ChangeLog for OR 23.09 --- ChangeLog | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ChangeLog b/ChangeLog index 3503ef69f..3f0411c66 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,4 +1,8 @@ -2022-02-06 Sibo Van Gool +2023-11-16 Sibo Van Gool + + * Released version 23.09. See Release Notes for changes. + +2023-02-06 Sibo Van Gool * Released version 22.02. See Release Notes of 22.02.beta.01, 22.02.beta.02, 22.02.beta.03, 22.02.beta.04, 22.02.beta.05, and 22.02.RC.01 for changes. From 6c89a3c60118226e562e19625d8fd439854b1246 Mon Sep 17 00:00:00 2001 From: Sibo Van Gool Date: Thu, 16 Nov 2023 16:11:11 +0100 Subject: [PATCH 08/10] Update 23.09 date --- ReleaseNotes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ReleaseNotes.md b/ReleaseNotes.md index 3a3816b5f..c1ecdc267 100644 --- a/ReleaseNotes.md +++ b/ReleaseNotes.md @@ -15,7 +15,7 @@ Release Notes
-OpenRocket 23.09 +OpenRocket 23.09 (2023-11-16) ------------------------ You can find a visual overview of what's new for this release on [our website](https://openrocket.info//downloads.html?vers=23.09#whats-new). From 8ad74c0b27954056c455f52986641f60f64921ea Mon Sep 17 00:00:00 2001 From: SiboVG Date: Wed, 15 Nov 2023 16:06:44 +0100 Subject: [PATCH 09/10] [#2388] Sync wind average speed, standard div & turbulence widgets --- .../simulation/SimulationConditionsPanel.java | 49 ++++++++++++------- 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/swing/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java b/swing/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java index 7c1252657..030c8f058 100644 --- a/swing/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java +++ b/swing/src/net/sf/openrocket/gui/simulation/SimulationConditionsPanel.java @@ -112,17 +112,17 @@ public class SimulationConditionsPanel extends JPanel { label.setToolTipText(tip); sub.add(label); - m = new DoubleModel(target, "WindSpeedAverage", UnitGroup.UNITS_WINDSPEED, 0); + DoubleModel windSpeedAverage = new DoubleModel(target, "WindSpeedAverage", UnitGroup.UNITS_WINDSPEED, 0); - spin = new JSpinner(m.getSpinnerModel()); + spin = new JSpinner(windSpeedAverage.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); spin.setToolTipText(tip); - sub.add(spin, "w 65lp!"); + sub.add(spin, "growx"); - unit = new UnitSelector(m); + unit = new UnitSelector(windSpeedAverage); unit.setToolTipText(tip); sub.add(unit, "growx"); - slider = new BasicSlider(m.getSliderModel(0, 10.0)); + slider = new BasicSlider(windSpeedAverage.getSliderModel(0, 10.0)); slider.setToolTipText(tip); sub.add(slider, "w 75lp, wrap"); @@ -136,23 +136,29 @@ public class SimulationConditionsPanel extends JPanel { label.setToolTipText(tip); sub.add(label); - m = new DoubleModel(target, "WindSpeedDeviation", UnitGroup.UNITS_WINDSPEED, 0); - DoubleModel m2 = new DoubleModel(target, "WindSpeedAverage", 0.25, - UnitGroup.UNITS_COEFFICIENT, 0); + DoubleModel windSpeedDeviation = new DoubleModel(target, "WindSpeedDeviation", UnitGroup.UNITS_WINDSPEED, 0); + DoubleModel m2 = new DoubleModel(target, "WindSpeedAverage", 0.25, UnitGroup.UNITS_COEFFICIENT, 0); - spin = new JSpinner(m.getSpinnerModel()); + spin = new JSpinner(windSpeedDeviation.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); spin.setToolTipText(tip); addEasterEgg(spin, parent); - sub.add(spin, "w 65lp!"); + sub.add(spin, "growx"); - unit = new UnitSelector(m); + unit = new UnitSelector(windSpeedDeviation); unit.setToolTipText(tip); sub.add(unit, "growx"); - slider = new BasicSlider(m.getSliderModel(new DoubleModel(0), m2)); + slider = new BasicSlider(windSpeedDeviation.getSliderModel(new DoubleModel(0), m2)); slider.setToolTipText(tip); sub.add(slider, "w 75lp, wrap"); + windSpeedAverage.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + windSpeedDeviation.stateChanged(e); + } + }); + // Wind turbulence intensity //// Turbulence intensity: @@ -168,14 +174,14 @@ public class SimulationConditionsPanel extends JPanel { label.setToolTipText(tip); sub.add(label); - m = new DoubleModel(target, "WindTurbulenceIntensity", UnitGroup.UNITS_RELATIVE, 0); + DoubleModel windTurbulenceIntensity = new DoubleModel(target, "WindTurbulenceIntensity", UnitGroup.UNITS_RELATIVE, 0); - spin = new JSpinner(m.getSpinnerModel()); + spin = new JSpinner(windTurbulenceIntensity.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); spin.setToolTipText(tip); - sub.add(spin, "w 65lp!"); + sub.add(spin, "growx"); - unit = new UnitSelector(m); + unit = new UnitSelector(windTurbulenceIntensity); unit.setToolTipText(tip); sub.add(unit, "growx"); @@ -183,11 +189,18 @@ public class SimulationConditionsPanel extends JPanel { getIntensityDescription(target.getWindTurbulenceIntensity())); intensityLabel.setToolTipText(tip); sub.add(intensityLabel, "w 75lp, wrap"); - m.addChangeListener(new ChangeListener() { + windTurbulenceIntensity.addChangeListener(new ChangeListener() { @Override public void stateChanged(ChangeEvent e) { intensityLabel.setText( getIntensityDescription(target.getWindTurbulenceIntensity())); + windSpeedDeviation.stateChanged(e); + } + }); + windSpeedDeviation.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + windTurbulenceIntensity.stateChanged(e); } }); @@ -204,7 +217,7 @@ public class SimulationConditionsPanel extends JPanel { spin = new JSpinner(m.getSpinnerModel()); spin.setEditor(new SpinnerEditor(spin)); spin.setToolTipText(tip); - sub.add(spin, "w 65lp!"); + sub.add(spin, "growx"); unit = new UnitSelector(m); unit.setToolTipText(tip); From cdeef020b7b45f65bcdac29fbf51fae301287ffe Mon Sep 17 00:00:00 2001 From: SiboVG Date: Fri, 17 Nov 2023 02:08:19 +0100 Subject: [PATCH 10/10] Set wind turbulence to 0 when average speed is 0 --- core/src/net/sf/openrocket/simulation/SimulationOptions.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/src/net/sf/openrocket/simulation/SimulationOptions.java b/core/src/net/sf/openrocket/simulation/SimulationOptions.java index dfcee63c3..f26f0146d 100644 --- a/core/src/net/sf/openrocket/simulation/SimulationOptions.java +++ b/core/src/net/sf/openrocket/simulation/SimulationOptions.java @@ -146,6 +146,9 @@ public class SimulationOptions implements ChangeSource, Cloneable, SimulationOpt if (MathUtil.equals(this.windAverage, windAverage)) return; this.windAverage = MathUtil.max(windAverage, 0); + if (MathUtil.equals(this.windAverage, 0)) { + setWindTurbulenceIntensity(0); + } fireChangeEvent(); }