diff --git a/core/resources/build.properties b/core/resources/build.properties index 0c5d05e93..89a2ebdfd 100644 --- a/core/resources/build.properties +++ b/core/resources/build.properties @@ -1,6 +1,6 @@ # The OpenRocket build version -build.version=20-08-alpha-14 +build.version=20-08-alpha-15 # The source of the package. When building a package for a specific diff --git a/core/src/net/sf/openrocket/document/Simulation.java b/core/src/net/sf/openrocket/document/Simulation.java index 30b4d02c7..23e3ea620 100644 --- a/core/src/net/sf/openrocket/document/Simulation.java +++ b/core/src/net/sf/openrocket/document/Simulation.java @@ -164,7 +164,12 @@ public class Simulation implements ChangeSource, Cloneable { } } - + + public FlightConfiguration getActiveConfiguration() { + mutex.verify(); + return rocket.getFlightConfiguration(this.configId); + } + /** * Return the rocket associated with this simulation. * @@ -185,7 +190,7 @@ public class Simulation implements ChangeSource, Cloneable { /** * Set the motor configuration ID. If this id does not yet exist, it will be created. * - * @param id the configuration to set. + * @param fcid the configuration to set. */ public void setFlightConfigurationId(FlightConfigurationId fcid) { if ( null == fcid ){ @@ -487,25 +492,29 @@ public class Simulation implements ChangeSource, Cloneable { /** * Create a duplicate of this simulation with the specified rocket. The new * simulation is in non-simulated state. + * This methods performs + * synchronization on the simulation for thread protection. + *

+ * Note: This method is package-private for unit testing purposes. * * @param newRocket the rocket for the new simulation. - * @return a new simulation with the same conditions and properties. + * @return a new deep copy of the simulation and rocket with the same conditions and properties. */ public Simulation duplicateSimulation(Rocket newRocket) { mutex.lock("duplicateSimulation"); try { - Simulation copy = new Simulation(newRocket); - - copy.name = this.name; - copy.options.copyFrom(this.options); - copy.simulatedConfigurationDescription = this.simulatedConfigurationDescription; + final Simulation newSim = new Simulation(newRocket); + newSim.name = this.name; + newSim.configId = this.configId; + newSim.options.copyFrom(this.options); + newSim.simulatedConfigurationDescription = this.simulatedConfigurationDescription; for (SimulationExtension c : this.simulationExtensions) { - copy.simulationExtensions.add(c.clone()); + newSim.simulationExtensions.add(c.clone()); } - copy.simulationStepperClass = this.simulationStepperClass; - copy.aerodynamicCalculatorClass = this.aerodynamicCalculatorClass; + newSim.simulationStepperClass = this.simulationStepperClass; + newSim.aerodynamicCalculatorClass = this.aerodynamicCalculatorClass; - return copy; + return newSim; } finally { mutex.unlock("duplicateSimulation"); } diff --git a/core/src/net/sf/openrocket/optimization/rocketoptimization/RocketOptimizationFunction.java b/core/src/net/sf/openrocket/optimization/rocketoptimization/RocketOptimizationFunction.java index cfaed6580..ddc47d19a 100644 --- a/core/src/net/sf/openrocket/optimization/rocketoptimization/RocketOptimizationFunction.java +++ b/core/src/net/sf/openrocket/optimization/rocketoptimization/RocketOptimizationFunction.java @@ -38,7 +38,7 @@ public class RocketOptimizationFunction implements Function { private final SimulationModifier[] modifiers; - private final List listeners = new ArrayList(); + private final List listeners = new ArrayList<>(); /** @@ -83,12 +83,12 @@ public class RocketOptimizationFunction implements Function { modifiers.length + " simulation modifiers"); } - Simulation simulation = newSimulationInstance(baseSimulation); + final Simulation simulation = newSimulationInstance(baseSimulation); + for (int i = 0; i < modifiers.length; i++) { modifiers[i].modify(simulation, p[i]); } - // Check whether the point is within the simulation domain Pair d = domain.getDistanceToDomain(simulation); double distance = d.getU(); @@ -106,7 +106,6 @@ public class RocketOptimizationFunction implements Function { return goalValue; } - // Compute the optimization value parameterValue = parameter.computeValue(simulation); goalValue = goal.getMinimizationParameter(parameterValue); @@ -118,35 +117,25 @@ public class RocketOptimizationFunction implements Function { goalValue = Double.MAX_VALUE; } - log.trace("Parameter value at point " + point + " is " + parameterValue + ", goal function value=" + goalValue); - - fireEvent(simulation, point, referenceValue, new Value(parameterValue, parameter.getUnitGroup().getDefaultUnit()), - goalValue); + fireEvent( simulation, point, referenceValue, + new Value(parameterValue, parameter.getUnitGroup().getDefaultUnit()), + goalValue); return goalValue; } - - - /** - * Returns a new deep copy of the simulation and rocket. This methods performs - * synchronization on the simulation for thread protection. + * Returns a new deep copy of the simulation and rocket. *

* Note: This method is package-private for unit testing purposes. - * - * @return a new deep copy of the simulation and rocket + * + * @return a new deep copy of the simulation and rocket */ Simulation newSimulationInstance(Simulation simulation) { - synchronized (baseSimulation) { - Rocket newRocket = simulation.getRocket().copyWithOriginalID(); - Simulation newSimulation = simulation.duplicateSimulation(newRocket); - return newSimulation; - } + return simulation.duplicateSimulation(simulation.getRocket().copyWithOriginalID()); } - /** * Add a listener to this function. The listener will be notified each time the * function is successfully evaluated. diff --git a/core/src/net/sf/openrocket/optimization/rocketoptimization/domains/StabilityDomain.java b/core/src/net/sf/openrocket/optimization/rocketoptimization/domains/StabilityDomain.java index e33f8189e..eab1c431d 100644 --- a/core/src/net/sf/openrocket/optimization/rocketoptimization/domains/StabilityDomain.java +++ b/core/src/net/sf/openrocket/optimization/rocketoptimization/domains/StabilityDomain.java @@ -63,7 +63,7 @@ public class StabilityDomain implements SimulationDomain { */ AerodynamicCalculator aerodynamicCalculator = new BarrowmanCalculator(); - FlightConfiguration configuration = simulation.getRocket().getSelectedConfiguration(); + FlightConfiguration configuration = simulation.getActiveConfiguration(); FlightConditions conditions = new FlightConditions(configuration); conditions.setMach(Application.getPreferences().getDefaultMach()); conditions.setAOA(0); diff --git a/core/src/net/sf/openrocket/optimization/rocketoptimization/modifiers/FlightConfigurationModifier.java b/core/src/net/sf/openrocket/optimization/rocketoptimization/modifiers/FlightConfigurationModifier.java index da19f9d50..4ca45b337 100644 --- a/core/src/net/sf/openrocket/optimization/rocketoptimization/modifiers/FlightConfigurationModifier.java +++ b/core/src/net/sf/openrocket/optimization/rocketoptimization/modifiers/FlightConfigurationModifier.java @@ -70,8 +70,8 @@ public class FlightConfigurationModifier configs = (FlightConfigurableParameterSet) configGetter.invoke(c); - return configs.get(simulation.getRocket().getSelectedConfiguration().getFlightConfigurationID()); + FlightConfigurableParameterSet configSet = (FlightConfigurableParameterSet) configGetter.invoke(c); + return configSet.get(simulation.getFlightConfigurationId()); } } diff --git a/core/src/net/sf/openrocket/optimization/rocketoptimization/modifiers/GenericComponentModifier.java b/core/src/net/sf/openrocket/optimization/rocketoptimization/modifiers/GenericComponentModifier.java index bd80889a8..7970139ff 100644 --- a/core/src/net/sf/openrocket/optimization/rocketoptimization/modifiers/GenericComponentModifier.java +++ b/core/src/net/sf/openrocket/optimization/rocketoptimization/modifiers/GenericComponentModifier.java @@ -39,7 +39,8 @@ public class GenericComponentModifier extends GenericModifier { @Override protected RocketComponent getModifiedObject(Simulation simulation) throws OptimizationException { - RocketComponent c = simulation.getRocket().findComponent(componentId); + final RocketComponent c = simulation.getRocket().findComponent(componentId); + if (c == null) { throw new OptimizationException("Could not find component of type " + componentClass.getSimpleName() + " with correct ID"); diff --git a/core/src/net/sf/openrocket/optimization/rocketoptimization/parameters/StabilityParameter.java b/core/src/net/sf/openrocket/optimization/rocketoptimization/parameters/StabilityParameter.java index 08b67cbd3..cec642f00 100644 --- a/core/src/net/sf/openrocket/optimization/rocketoptimization/parameters/StabilityParameter.java +++ b/core/src/net/sf/openrocket/optimization/rocketoptimization/parameters/StabilityParameter.java @@ -44,57 +44,47 @@ public class StabilityParameter implements OptimizableParameter { @Override public double computeValue(Simulation simulation) throws OptimizationException { - Coordinate cp, cg; - double cpx, cgx; - double stability; - log.debug("Calculating stability of simulation, absolute=" + absolute); - + /* * These are instantiated each time because this class must be thread-safe. * Caching would in any case be inefficient since the rocket changes all the time. */ - AerodynamicCalculator aerodynamicCalculator = new BarrowmanCalculator(); - - FlightConfiguration configuration = simulation.getRocket().getSelectedConfiguration(); - FlightConditions conditions = new FlightConditions(configuration); + final AerodynamicCalculator aerodynamicCalculator = new BarrowmanCalculator(); + final FlightConfiguration configuration = simulation.getActiveConfiguration(); + final FlightConditions conditions = new FlightConditions(configuration); conditions.setMach(Application.getPreferences().getDefaultMach()); conditions.setAOA(0); conditions.setRollRate(0); - cp = aerodynamicCalculator.getWorstCP(configuration, conditions, null); - // worst case CM is also - cg = MassCalculator.calculateLaunch(configuration).getCM(); - + final Coordinate cp = aerodynamicCalculator.getWorstCP(configuration, conditions, null); + // the launch CM is the worst case CM + final Coordinate cg = MassCalculator.calculateLaunch(configuration).getCM(); + + double cpx = Double.NaN; if (cp.weight > 0.000001) cpx = cp.x; - else - cpx = Double.NaN; - + + double cgx = Double.NaN; if (cg.weight > 0.000001) cgx = cg.x; - else - cgx = Double.NaN; - // Calculate the reference (absolute or relative) - stability = cpx - cgx; - - if (!absolute) { + final double stability_absolute = cpx - cgx; + + if (absolute) { + return stability_absolute; + } else { double diameter = 0; - for (RocketComponent c : configuration.getActiveComponents()) { + for (RocketComponent c : configuration.getActiveInstances().keySet()) { if (c instanceof SymmetricComponent) { - double d1 = ((SymmetricComponent) c).getForeRadius() * 2; - double d2 = ((SymmetricComponent) c).getAftRadius() * 2; + final double d1 = ((SymmetricComponent) c).getForeRadius() * 2; + final double d2 = ((SymmetricComponent) c).getAftRadius() * 2; diameter = MathUtil.max(diameter, d1, d2); } } - stability = stability / diameter; + return stability_absolute / diameter; } - - log.debug("Resulting stability is " + stability + ", absolute=" + absolute); - - return stability; } @Override diff --git a/core/src/net/sf/openrocket/optimization/services/DefaultSimulationModifierService.java b/core/src/net/sf/openrocket/optimization/services/DefaultSimulationModifierService.java index ca2446b83..47a122811 100644 --- a/core/src/net/sf/openrocket/optimization/services/DefaultSimulationModifierService.java +++ b/core/src/net/sf/openrocket/optimization/services/DefaultSimulationModifierService.java @@ -215,7 +215,7 @@ public class DefaultSimulationModifierService implements SimulationModifierServi trans.get("optimization.modifier.internalcomponent.position"), trans.get("optimization.modifier.internalcomponent.position.desc"), c, UnitGroup.UNITS_LENGTH, - 1.0, c.getClass(), c.getID(), "AxialMethod"); + 1.0, c.getClass(), c.getID(), "AxialOffset"); mod.setMinValue(0); mod.setMaxValue(parent.getLength()); modifiers.add(mod); @@ -229,7 +229,7 @@ public class DefaultSimulationModifierService implements SimulationModifierServi trans.get("optimization.modifier.finset.position"), trans.get("optimization.modifier.finset.position.desc"), c, UnitGroup.UNITS_LENGTH, - 1.0, c.getClass(), c.getID(), "AxialMethod"); + 1.0, c.getClass(), c.getID(), "AxialOffset"); mod.setMinValue(0); mod.setMaxValue(parent.getLength()); modifiers.add(mod); @@ -243,7 +243,7 @@ public class DefaultSimulationModifierService implements SimulationModifierServi trans.get("optimization.modifier.launchlug.position"), trans.get("optimization.modifier.launchlug.position.desc"), c, UnitGroup.UNITS_LENGTH, - 1.0, c.getClass(), c.getID(), "AxialMethod"); + 1.0, c.getClass(), c.getID(), "AxialOffset"); mod.setMinValue(0); mod.setMaxValue(parent.getLength()); modifiers.add(mod); @@ -260,7 +260,7 @@ public class DefaultSimulationModifierService implements SimulationModifierServi 1.0, c.getClass(), c.getID(), - "DeploymentConfiguration", + "DeploymentConfigurations", DeploymentConfiguration.class, "DeployDelay"); @@ -276,7 +276,7 @@ public class DefaultSimulationModifierService implements SimulationModifierServi 1.0, c.getClass(), c.getID(), - "DeploymentConfiguration", + "DeploymentConfigurations", DeploymentConfiguration.class, "DeployAltitude") { diff --git a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java index a579e3902..e857f667c 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java +++ b/core/src/net/sf/openrocket/rocketcomponent/FlightConfiguration.java @@ -71,7 +71,16 @@ public class FlightConfiguration implements FlightConfigurableParameterRocket. + * + * @param rocket the rocket + */ + public FlightConfiguration(final Rocket rocket) { + this(rocket, FlightConfigurationId.DEFAULT_VALUE_FCID); + } + /** * Create a new configuration with the specified Rocket. * diff --git a/core/src/net/sf/openrocket/rocketcomponent/RecoveryDevice.java b/core/src/net/sf/openrocket/rocketcomponent/RecoveryDevice.java index 7de46329c..a0e783a70 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RecoveryDevice.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RecoveryDevice.java @@ -84,7 +84,7 @@ public abstract class RecoveryDevice extends MassObject implements FlightConfigu clearPreset(); fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE); } - + public FlightConfigurableParameterSet getDeploymentConfigurations() { return deploymentConfigurations; } diff --git a/core/src/net/sf/openrocket/rocketcomponent/Rocket.java b/core/src/net/sf/openrocket/rocketcomponent/Rocket.java index 8cde7c7ad..1be373b40 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/Rocket.java +++ b/core/src/net/sf/openrocket/rocketcomponent/Rocket.java @@ -79,7 +79,7 @@ public class Rocket extends ComponentAssembly { functionalModID = modID; // must be after the hashmaps :P - FlightConfiguration defaultConfig = new FlightConfiguration(this, FlightConfigurationId.DEFAULT_VALUE_FCID); + final FlightConfiguration defaultConfig = new FlightConfiguration(this, FlightConfigurationId.DEFAULT_VALUE_FCID); configSet = new FlightConfigurableParameterSet<>( defaultConfig ); this.selectedConfiguration = defaultConfig; } @@ -330,15 +330,26 @@ public class Rocket extends ComponentAssembly { */ @Override public Rocket copyWithOriginalID() { - Rocket copy = (Rocket) super.copyWithOriginalID(); - + final Rocket copyRocket = (Rocket) super.copyWithOriginalID(); + // Rocket copy is cloned, so non-trivial members must be cloned as well: - copy.stageMap = new HashMap(); - copy.configSet = new FlightConfigurableParameterSet( this.configSet ); - copy.selectedConfiguration = copy.configSet.get( this.getSelectedConfiguration().getId()); - copy.listenerList = new HashSet(); + copyRocket.stageMap = new HashMap<>(); + for( Map.Entry entry : this.stageMap.entrySet()){ + final AxialStage stage = (AxialStage)copyRocket.findComponent(entry.getValue().getID()); + copyRocket.stageMap.put(entry.getKey(), stage); + } + + // these flight configurations need to reference the _new_ Rocket copy + // the default value needs to be explicitly set, because it has different semantics + copyRocket.configSet = new FlightConfigurableParameterSet<>(new FlightConfiguration(copyRocket)); + for (FlightConfigurationId key : this.configSet.getIds()) { + copyRocket.configSet.set(key, new FlightConfiguration(copyRocket, key)); + } + + copyRocket.selectedConfiguration = copyRocket.configSet.get( this.getSelectedConfiguration().getId()); + copyRocket.listenerList = new HashSet<>(); - return copy; + return copyRocket; } public int getFlightConfigurationCount() { @@ -376,8 +387,13 @@ public class Rocket extends ComponentAssembly { this.functionalModID = r.functionalModID; this.refType = r.refType; this.customReferenceLength = r.customReferenceLength; - this.configSet = new FlightConfigurableParameterSet( r.configSet ); - + + // these flight configurations need to reference the _this_ Rocket: + this.configSet.setDefault(new FlightConfiguration(this)); + for (FlightConfigurationId key : r.configSet.map.keySet()) { + this.configSet.set(key, new FlightConfiguration(this, key)); + } + this.perfectFinish = r.perfectFinish; this.checkComponentStructure(); diff --git a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java index 8a2fdfcee..269ec1813 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java @@ -1627,7 +1627,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab checkState(); Iterator iter = this.iterator(true); while (iter.hasNext()) { - RocketComponent c = iter.next(); + final RocketComponent c = iter.next(); if (c.getID().equals(idToFind)) return c; } diff --git a/swing/src/net/sf/openrocket/gui/dialogs/optimization/GeneralOptimizationDialog.java b/swing/src/net/sf/openrocket/gui/dialogs/optimization/GeneralOptimizationDialog.java index 14cda1d8d..1377c5a32 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/optimization/GeneralOptimizationDialog.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/optimization/GeneralOptimizationDialog.java @@ -39,10 +39,7 @@ import javax.swing.JToggleButton; import javax.swing.ListSelectionModel; import javax.swing.Timer; import javax.swing.border.TitledBorder; -import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; -import javax.swing.event.ListSelectionEvent; -import javax.swing.event.ListSelectionListener; import javax.swing.event.TreeSelectionEvent; import javax.swing.event.TreeSelectionListener; import javax.swing.table.AbstractTableModel; @@ -51,6 +48,9 @@ import javax.swing.table.TableColumnModel; import javax.swing.tree.DefaultMutableTreeNode; import javax.swing.tree.TreePath; +import net.sf.openrocket.optimization.rocketoptimization.modifiers.GenericComponentModifier; +import net.sf.openrocket.rocketcomponent.FinSet; +import net.sf.openrocket.rocketcomponent.FlightConfiguration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -118,12 +118,11 @@ public class GeneralOptimizationDialog extends JDialog { private static final String START_TEXT = trans.get("btn.start"); private static final String STOP_TEXT = trans.get("btn.stop"); - private RocketDescriptor descriptor = Application.getInjector().getInstance(RocketDescriptor.class); + private final RocketDescriptor descriptor = Application.getInjector().getInstance(RocketDescriptor.class); - private final List optimizationParameters = new ArrayList(); - private final Map> simulationModifiers = - new HashMap>(); + private final List optimizationParameters = new ArrayList<>(); + private final Map> simulationModifiers = new HashMap<>(); private final OpenRocketDocument baseDocument; @@ -138,7 +137,7 @@ public class GeneralOptimizationDialog extends JDialog { private final DescriptionArea selectedModifierDescription; private final SimulationModifierTree availableModifierTree; - private final JComboBox simulationSelectionCombo; + private final JComboBox> simulationSelectionCombo; private final JComboBox> optimizationParameterCombo; private final JComboBox optimizationGoalCombo; @@ -146,8 +145,8 @@ public class GeneralOptimizationDialog extends JDialog { private final UnitSelector optimizationGoalUnitSelector; private final DoubleModel optimizationSeekValue; - private DoubleModel minimumStability; - private DoubleModel maximumStability; + private final DoubleModel minimumStability; + private final DoubleModel maximumStability; private final JCheckBox minimumStabilitySelected; private final JSpinner minimumStabilitySpinner; private final UnitSelector minimumStabilityUnitSelector; @@ -165,14 +164,10 @@ public class GeneralOptimizationDialog extends JDialog { private final JButton plotButton; private final JButton saveButton; - private final JButton applyButton; - private final JButton resetButton; - private final JButton closeButton; - - private final List selectedModifiers = new ArrayList(); + private final List selectedModifiers = new ArrayList<>(); /** List of components to disable while optimization is running */ - private final List disableComponents = new ArrayList(); + private final List disableComponents = new ArrayList<>(); /** Whether optimization is currently running or not */ private boolean running = false; @@ -185,8 +180,8 @@ public class GeneralOptimizationDialog extends JDialog { private int evaluationCount = 0; private double stepSize = 0; - private final Map evaluationHistory = new LinkedHashMap(); - private final List optimizationPath = new LinkedList(); + private final Map evaluationHistory = new LinkedHashMap<>(); + private final List optimizationPath = new LinkedList<>(); private boolean updating = false; @@ -212,21 +207,10 @@ public class GeneralOptimizationDialog extends JDialog { JPanel panel = new JPanel(new MigLayout("fill")); - ChangeListener clearHistoryChangeListener = new ChangeListener() { - @Override - public void stateChanged(ChangeEvent e) { - clearHistory(); - } - }; - ActionListener clearHistoryActionListener = new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - clearHistory(); - } - }; + ChangeListener clearHistoryChangeListener = e -> clearHistory(); + ActionListener clearHistoryActionListener = e -> clearHistory(); // // Selected modifiers table - selectedModifierTableModel = new ParameterSelectionTableModel(); selectedModifierTable = new JTable(selectedModifierTableModel); selectedModifierTable.setDefaultRenderer(Double.class, new DoubleCellRenderer()); @@ -249,15 +233,11 @@ public class GeneralOptimizationDialog extends JDialog { return selectedModifiers.get(row).getUnitGroup(); } }); - + selectedModifierTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); + disableComponents.add(selectedModifierTable); - selectedModifierTable.getSelectionModel().addListSelectionListener(new ListSelectionListener() { - @Override - public void valueChanged(ListSelectionEvent e) { - updateComponents(); - } - }); + selectedModifierTable.getSelectionModel().addListSelectionListener(e -> updateComponents()); // Set column widths TableColumnModel columnModel = selectedModifierTable.getColumnModel(); @@ -281,16 +261,16 @@ public class GeneralOptimizationDialog extends JDialog { addButton = new JButton(Chars.LEFT_ARROW + " " + trans.get("btn.add") + " "); addButton.setToolTipText(trans.get("btn.add.ttip")); - addButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - SimulationModifier mod = getSelectedAvailableModifier(); - if (mod != null) { - addModifier(mod); - clearHistory(); - } else { - log.error("Attempting to add simulation modifier when none is selected"); - } + addButton.addActionListener(e -> { + SimulationModifier mod = getSelectedAvailableModifier(); + if (mod != null) { + addModifier(mod); + clearHistory(); + } else { + log.error("Attempting to add simulation modifier when none is selected"); + } + if (selectedModifierTable.isEditing()) { + selectedModifierTable.getCellEditor().stopCellEditing(); } }); disableComponents.add(addButton); @@ -298,17 +278,19 @@ public class GeneralOptimizationDialog extends JDialog { removeButton = new JButton(" " + trans.get("btn.remove") + " " + Chars.RIGHT_ARROW); removeButton.setToolTipText(trans.get("btn.remove.ttip")); - removeButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - SimulationModifier mod = getSelectedModifier(); - if (mod == null) { - log.error("Attempting to remove simulation modifier when none is selected"); - return; - } - removeModifier(mod); - clearHistory(); + removeButton.addActionListener(e -> { + SimulationModifier mod = getSelectedModifier(); + if (mod == null) { + log.error("Attempting to remove simulation modifier when none is selected"); + return; } + + if (selectedModifierTable.isEditing()) { + selectedModifierTable.getCellEditor().stopCellEditing(); + } + + removeModifier(mod); + clearHistory(); }); disableComponents.add(removeButton); sub.add(removeButton, "wrap para*2, sg button"); @@ -378,7 +360,7 @@ public class GeneralOptimizationDialog extends JDialog { disableComponents.add(label); sub.add(label, ""); - simulationSelectionCombo = new JComboBox(); + simulationSelectionCombo = new JComboBox<>(); simulationSelectionCombo.setToolTipText(tip); populateSimulations(); simulationSelectionCombo.addActionListener(clearHistoryActionListener); @@ -392,7 +374,7 @@ public class GeneralOptimizationDialog extends JDialog { disableComponents.add(label); sub.add(label, ""); - optimizationParameterCombo = new JComboBox>(); + optimizationParameterCombo = new JComboBox<>(); optimizationParameterCombo.setToolTipText(tip); populateParameters(); optimizationParameterCombo.addActionListener(clearHistoryActionListener); @@ -406,7 +388,7 @@ public class GeneralOptimizationDialog extends JDialog { disableComponents.add(label); sub.add(label, ""); - optimizationGoalCombo = new JComboBox(new String[] { GOAL_MAXIMIZE, GOAL_MINIMIZE, GOAL_SEEK }); + optimizationGoalCombo = new JComboBox<>(new String[] { GOAL_MAXIMIZE, GOAL_MINIMIZE, GOAL_SEEK }); optimizationGoalCombo.setToolTipText(tip); optimizationGoalCombo.setEditable(false); optimizationGoalCombo.addActionListener(clearHistoryActionListener); @@ -450,12 +432,7 @@ public class GeneralOptimizationDialog extends JDialog { minimumStabilitySelected = new JCheckBox(trans.get("lbl.requireMinStability")); minimumStabilitySelected.setSelected(true); minimumStabilitySelected.setToolTipText(tip); - minimumStabilitySelected.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - updateComponents(); - } - }); + minimumStabilitySelected.addActionListener(e -> updateComponents()); disableComponents.add(minimumStabilitySelected); sub.add(minimumStabilitySelected); @@ -551,51 +528,42 @@ public class GeneralOptimizationDialog extends JDialog { // // Start/Stop button startButton = new JToggleButton(START_TEXT); - startButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - if (updating) { - log.debug("Updating, ignoring event"); - return; - } - if (running) { - log.info(Markers.USER_MARKER, "Stopping optimization"); - stopOptimization(); - } else { - log.info(Markers.USER_MARKER, "Starting optimization"); - startOptimization(); - } + startButton.addActionListener(e -> { + if (updating) { + log.debug("Updating, ignoring event"); + return; + } + if (running) { + log.info(Markers.USER_MARKER, "Stopping optimization"); + stopOptimization(); + } else { + log.info(Markers.USER_MARKER, "Starting optimization"); + startOptimization(); } }); sub.add(startButton, "span, growx, wrap para*2"); plotButton = new JButton(trans.get("btn.plotPath")); plotButton.setToolTipText(trans.get("btn.plotPath.ttip")); - plotButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - log.info(Markers.USER_MARKER, "Plotting optimization path, dimensionality=" + selectedModifiers.size()); - OptimizationPlotDialog dialog = new OptimizationPlotDialog( - Collections.unmodifiableList(optimizationPath), - Collections.unmodifiableMap(evaluationHistory), - Collections.unmodifiableList(selectedModifiers), - getSelectedParameter(), - UnitGroup.stabilityUnits(getSelectedSimulation().getRocket()), - GeneralOptimizationDialog.this); - dialog.setVisible(true); - } + plotButton.addActionListener(e -> { + log.info(Markers.USER_MARKER, "Plotting optimization path, dimensionality=" + selectedModifiers.size()); + OptimizationPlotDialog dialog = new OptimizationPlotDialog( + Collections.unmodifiableList(optimizationPath), + Collections.unmodifiableMap(evaluationHistory), + Collections.unmodifiableList(selectedModifiers), + getSelectedParameter(), + UnitGroup.stabilityUnits(getSelectedSimulation().getRocket()), + GeneralOptimizationDialog.this); + dialog.setVisible(true); }); disableComponents.add(plotButton); sub.add(plotButton, "span, growx, wrap"); saveButton = new JButton(trans.get("btn.save")); saveButton.setToolTipText(trans.get("btn.save.ttip")); - saveButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - log.info(Markers.USER_MARKER, "User selected save path"); - savePath(); - } + saveButton.addActionListener(e -> { + log.info(Markers.USER_MARKER, "User selected save path"); + savePath(); }); disableComponents.add(saveButton); sub.add(saveButton, "span, growx"); @@ -603,32 +571,25 @@ public class GeneralOptimizationDialog extends JDialog { panel.add(sub, "wrap para*2"); // // Bottom buttons - - applyButton = new JButton(trans.get("btn.apply")); + final JButton applyButton = new JButton(trans.get("btn.apply")); applyButton.setToolTipText(trans.get("btn.apply.ttip")); - applyButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - log.info(Markers.USER_MARKER, "Applying optimization changes"); - applyDesign(); - } + applyButton.addActionListener(e -> { + log.info(Markers.USER_MARKER, "Applying optimization changes"); + applyDesign(); }); disableComponents.add(applyButton); panel.add(applyButton, "span, split, gapright para, right"); - - resetButton = new JButton(trans.get("btn.reset")); + + final JButton resetButton = new JButton(trans.get("btn.reset")); resetButton.setToolTipText(trans.get("btn.reset.ttip")); - resetButton.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - log.info(Markers.USER_MARKER, "Resetting optimization design"); - resetDesign(); - } + resetButton.addActionListener(e -> { + log.info(Markers.USER_MARKER, "Resetting optimization design"); + resetDesign(); }); disableComponents.add(resetButton); panel.add(resetButton, "gapright para, right"); - - closeButton = new JButton(trans.get("btn.close")); + + final JButton closeButton = new JButton(trans.get("btn.close")); closeButton.setToolTipText(trans.get("btn.close.ttip")); closeButton.addActionListener(new ActionListener() { @Override @@ -644,6 +605,12 @@ public class GeneralOptimizationDialog extends JDialog { clearHistory(); updateComponents(); GUIUtil.setDisposableDialogOptions(this, null); + + // seem like a reasonable defaults + this.setSize(1200, 600); + // System.err.println("OptimizationDialog.size: " + this.getSize()); + this.setLocation(100, 100); + // System.err.println("OptimizationDialog.location: " + this.getLocation()); } private void startOptimization() { @@ -671,13 +638,9 @@ public class GeneralOptimizationDialog extends JDialog { updating = false; - // Create a copy of the simulation (we're going to modify the original in the current thread) - Simulation simulation = getSelectedSimulation(); - Rocket rocketCopy = simulation.getRocket().copyWithOriginalID(); - simulation = simulation.duplicateSimulation(rocketCopy); - - OptimizableParameter parameter = getSelectedParameter(); - + // Create a copy of the simulation (we'll modify the copy here) + final Simulation simulation = getSelectedSimulation(); + final OptimizableParameter parameter = getSelectedParameter(); OptimizationGoal goal; String value = (String) optimizationGoalCombo.getSelectedItem(); if (GOAL_MAXIMIZE.equals(value)) { @@ -735,11 +698,8 @@ public class GeneralOptimizationDialog extends JDialog { } SimulationModifier[] modifiers = selectedModifiers.toArray(new SimulationModifier[0]); - - // Check for DeploymentAltitude modifier, if it's there, we want to make certain the DeploymentEvent - // is ALTITUDE: + for (SimulationModifier mod : modifiers) { - try { mod.initialize(simulation); } catch (OptimizationException ex) { @@ -822,8 +782,8 @@ public class GeneralOptimizationDialog extends JDialog { try { selectedModifiers.get(i).modify(sim, newPoint.get(i)); } catch (OptimizationException e) { - throw new BugException("Simulation modifier failed to modify the base simulation " + - "modifier=" + selectedModifiers.get(i), e); + throw new BugException( "Simulation modifier failed to modify the base simulation " + + "modifier=" + selectedModifiers.get(i), e); } } figure.updateFigure(); @@ -899,6 +859,8 @@ public class GeneralOptimizationDialog extends JDialog { src.removeChild(0); dest.addChild(c); } + + figure.repaint(); } finally { dest.thaw(); @@ -915,7 +877,7 @@ public class GeneralOptimizationDialog extends JDialog { loadSimulationModifiers(); // Replace selected modifiers with corresponding new modifiers - List newSelected = new ArrayList(); + List newSelected = new ArrayList<>(); for (SimulationModifier original : selectedModifiers) { List newModifiers = simulationModifiers.get(original.getRelatedObject()); if (newModifiers != null) { @@ -951,34 +913,14 @@ public class GeneralOptimizationDialog extends JDialog { current = selection.toString(); } - List> simulations = new ArrayList>(); - Rocket rocket = documentCopy.getRocket(); - - for (Simulation s : documentCopy.getSimulations()) { - //FlightConfigurationID id = s.getConfiguration().getFlightConfigurationID(); - FlightConfigurationId id = new FlightConfigurationId( "stub id value - General Optimizer"); - - String name = createSimulationName(s.getName(), descriptor.format(rocket, id)); - simulations.add(new Named(s, name)); + List> simulations = new ArrayList<>(); + for (Simulation s : documentCopy.getSimulations()){ + final FlightConfiguration config = s.getActiveConfiguration(); + final String optionName = createSimulationName(s.getName(), config.getName() ); + simulations.add(new Named<>(s, optionName)); } - for (FlightConfigurationId curId: rocket.getIds() ){ - if ( curId== null) { - // this is now *extremely* unlikely - throw new NullPointerException(" flightconfiguration has a null id... bug."); - } - - Simulation sim = new Simulation(rocket); - String name = createSimulationName(trans.get("basicSimulationName"), descriptor.format(rocket, curId)); - simulations.add(new Named(sim, name)); - } - - Simulation sim = new Simulation(rocket); - String name = createSimulationName(trans.get("noSimulationName"), descriptor.format(rocket, null)); - simulations.add(new Named(sim, name)); - - - simulationSelectionCombo.setModel(new DefaultComboBoxModel((String[])simulations.toArray())); + simulationSelectionCombo.setModel(new DefaultComboBoxModel<>(new Vector<>(simulations))); simulationSelectionCombo.setSelectedIndex(0); if (current != null) { for (int i = 0; i < simulations.size(); i++) { @@ -1000,12 +942,12 @@ public class GeneralOptimizationDialog extends JDialog { current = trans.get("MaximumAltitudeParameter.name"); } - Vector> parameters = new Vector>(); + Vector> parameters = new Vector<>(); for (OptimizableParameter p : optimizationParameters) { - parameters.add(new Named(p, p.getName())); + parameters.add(new Named<>(p, p.getName())); } - optimizationParameterCombo.setModel(new DefaultComboBoxModel>( parameters )); + optimizationParameterCombo.setModel(new DefaultComboBoxModel<>( parameters )); for (int i = 0; i < parameters.size(); i++) { if (parameters.get(i).toString().equals(current)) { @@ -1029,13 +971,8 @@ public class GeneralOptimizationDialog extends JDialog { if (optimizationParameters.isEmpty()) { throw new BugException("No rocket optimization parameters found, distribution built wrong."); } - - Collections.sort(optimizationParameters, new Comparator() { - @Override - public int compare(OptimizableParameter o1, OptimizableParameter o2) { - return o1.getName().compareTo(o2.getName()); - } - }); + + optimizationParameters.sort(Comparator.comparing(OptimizableParameter::getName)); } private void loadSimulationModifiers() { @@ -1045,7 +982,7 @@ public class GeneralOptimizationDialog extends JDialog { Object key = m.getRelatedObject(); List list = simulationModifiers.get(key); if (list == null) { - list = new ArrayList(); + list = new ArrayList<>(); simulationModifiers.put(key, list); } list.add(m); @@ -1053,12 +990,7 @@ public class GeneralOptimizationDialog extends JDialog { for (Object key : simulationModifiers.keySet()) { List list = simulationModifiers.get(key); - Collections.sort(list, new Comparator() { - @Override - public int compare(SimulationModifier o1, SimulationModifier o2) { - return o1.getName().compareTo(o2.getName()); - } - }); + list.sort((o1, o2) -> o1.getName().compareTo(o2.getName())); } } @@ -1228,9 +1160,9 @@ public class GeneralOptimizationDialog extends JDialog { for (FunctionEvaluationData data : evaluationHistory.values()) { Value[] state = data.getState(); - - for (int i = 0; i < state.length; i++) { - writer.write(TextUtil.doubleToString(state[i].getUnitValue())); + + for (Value value : state) { + writer.write(TextUtil.doubleToString(value.getUnitValue())); writer.write(fieldSeparator); } @@ -1277,16 +1209,18 @@ public class GeneralOptimizationDialog extends JDialog { */ @SuppressWarnings("unchecked") private Simulation getSelectedSimulation() { - /* This is to debug a NPE where the returned selected item is null. */ Object item = simulationSelectionCombo.getSelectedItem(); + + /* This is to debug a NPE where the returned selected item is null. */ if (item == null) { - String s = "Selected simulation is null:"; - s = s + " item count=" + simulationSelectionCombo.getItemCount(); + StringBuilder s = new StringBuilder("Selected simulation is null:"); + s.append(" item count=").append(simulationSelectionCombo.getItemCount()); for (int i = 0; i < simulationSelectionCombo.getItemCount(); i++) { - s = s + " [" + i + "]=" + simulationSelectionCombo.getItemAt(i); + s.append(" [").append(i).append("]=").append(simulationSelectionCombo.getItemAt(i)); } - throw new BugException(s); + throw new BugException(s.toString()); } + return ((Named) item).get(); } diff --git a/swing/src/net/sf/openrocket/gui/dialogs/optimization/OptimizationWorker.java b/swing/src/net/sf/openrocket/gui/dialogs/optimization/OptimizationWorker.java index fce171a95..2ec25ea26 100644 --- a/swing/src/net/sf/openrocket/gui/dialogs/optimization/OptimizationWorker.java +++ b/swing/src/net/sf/openrocket/gui/dialogs/optimization/OptimizationWorker.java @@ -61,12 +61,9 @@ public abstract class OptimizationWorker extends Thread implements OptimizationC private final SimulationModifier[] modifiers; private final ParallelFunctionCache cache; - - private final LinkedBlockingQueue evaluationQueue = - new LinkedBlockingQueue(); - private final LinkedBlockingQueue stepQueue = - new LinkedBlockingQueue(); + private final LinkedBlockingQueue evaluationQueue = new LinkedBlockingQueue<>(); + private final LinkedBlockingQueue stepQueue = new LinkedBlockingQueue<>(); private volatile long lastPurge = 0; private OptimizationException optimizationException = null; @@ -115,13 +112,10 @@ public abstract class OptimizationWorker extends Thread implements OptimizationC } catch (OptimizationException e) { this.optimizationException = e; } finally { - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - lastPurge = System.currentTimeMillis() + 24L * 3600L * 1000L; - processQueue(); - done(optimizationException); - } + SwingUtilities.invokeLater(() -> { + lastPurge = System.currentTimeMillis() + 24L * 3600L * 1000L; + processQueue(); + done(optimizationException); }); } } @@ -157,7 +151,6 @@ public abstract class OptimizationWorker extends Thread implements OptimizationC /** * Publishes data to the listeners. The queue is purged every PURGE_TIMEOUT milliseconds. * - * @param data the data to publish to the listeners */ private synchronized void publish(FunctionEvaluationData evaluation, OptimizationStepData step) { @@ -172,12 +165,7 @@ public abstract class OptimizationWorker extends Thread implements OptimizationC long now = System.currentTimeMillis(); if (lastPurge + PURGE_TIMEOUT <= now) { lastPurge = now; - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - processQueue(); - } - }); + SwingUtilities.invokeLater(this::processQueue); } } @@ -193,14 +181,14 @@ public abstract class OptimizationWorker extends Thread implements OptimizationC } - List evaluations = new ArrayList(); + List evaluations = new ArrayList<>(); evaluationQueue.drainTo(evaluations); if (!evaluations.isEmpty()) { functionEvaluated(evaluations); } - List steps = new ArrayList(); + List steps = new ArrayList<>(); stepQueue.drainTo(steps); if (!steps.isEmpty()) { optimizationStepTaken(steps); diff --git a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java index 2ab3e0c2f..2987ded5a 100644 --- a/swing/src/net/sf/openrocket/gui/main/BasicFrame.java +++ b/swing/src/net/sf/openrocket/gui/main/BasicFrame.java @@ -708,18 +708,17 @@ public class BasicFrame extends JFrame { }); menu.add(item); -// TODO: reimplement this dialog -// //// Optimize -// item = new JMenuItem(trans.get("main.menu.analyze.optimization"), KeyEvent.VK_O); -// item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.analyze.optimization.desc")); -// item.addActionListener(new ActionListener() { -// @Override -// public void actionPerformed(ActionEvent e) { -// log.info(Markers.USER_MARKER, "Rocket optimization selected"); -// new GeneralOptimizationDialog(document, BasicFrame.this).setVisible(true); -// } -// }); -// menu.add(item); + //// Optimize + item = new JMenuItem(trans.get("main.menu.analyze.optimization"), KeyEvent.VK_O); + item.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.analyze.optimization.desc")); + item.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + log.info(Markers.USER_MARKER, "Rocket optimization selected"); + new GeneralOptimizationDialog(document, BasicFrame.this).setVisible(true); + } + }); + menu.add(item); //// Custom expressions item = new JMenuItem(trans.get("main.menu.analyze.customExpressions"), KeyEvent.VK_E); diff --git a/swing/src/net/sf/openrocket/gui/simulation/SimulationEditDialog.java b/swing/src/net/sf/openrocket/gui/simulation/SimulationEditDialog.java index a57ae77bb..b6defbea0 100644 --- a/swing/src/net/sf/openrocket/gui/simulation/SimulationEditDialog.java +++ b/swing/src/net/sf/openrocket/gui/simulation/SimulationEditDialog.java @@ -148,7 +148,9 @@ public class SimulationEditDialog extends JDialog { panel.add(label, "growx 0, gapright para"); final Rocket rkt = document.getRocket(); + final FlightConfiguration config = rkt.getFlightConfiguration(simulationList[0].getFlightConfigurationId()); final ConfigurationComboBox configComboBox = new ConfigurationComboBox(rkt); + configComboBox.setSelectedItem(config); //// Select the motor configuration to use. configComboBox.setToolTipText(trans.get("simedtdlg.combo.ttip.Flightcfg")); diff --git a/swing/src/net/sf/openrocket/gui/simulation/SimulationRunDialog.java b/swing/src/net/sf/openrocket/gui/simulation/SimulationRunDialog.java index 077112d8c..5fb8402a7 100644 --- a/swing/src/net/sf/openrocket/gui/simulation/SimulationRunDialog.java +++ b/swing/src/net/sf/openrocket/gui/simulation/SimulationRunDialog.java @@ -292,7 +292,7 @@ public class SimulationRunDialog extends JDialog { double otherBurn = 0; - FlightConfiguration config = simulation.getRocket().getSelectedConfiguration(); + FlightConfiguration config = simulation.getActiveConfiguration(); Collection activeMotors = config.getActiveMotors(); for (MotorConfiguration curInstance : activeMotors) {