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