diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties
index 7c0b8385e..d41dd4841 100644
--- a/core/resources/l10n/messages.properties
+++ b/core/resources/l10n/messages.properties
@@ -894,6 +894,7 @@ StageConfig.tab.Separation.ttip = Stage separation options
StageConfig.separation.lbl.title = Select when this stage separates:
StageConfig.separation.lbl.plus = plus
StageConfig.separation.lbl.seconds = seconds
+StageConfig.parallel.autoradius = Enable Automatic Positioning
StageConfig.parallel.radius = Radial Distance
StageConfig.parallel.angle = Angle
StageConfig.parallel.count = Number of Copies
diff --git a/core/src/net/sf/openrocket/file/openrocket/OpenRocketSaver.java b/core/src/net/sf/openrocket/file/openrocket/OpenRocketSaver.java
index 27a4361fb..508e3e274 100644
--- a/core/src/net/sf/openrocket/file/openrocket/OpenRocketSaver.java
+++ b/core/src/net/sf/openrocket/file/openrocket/OpenRocketSaver.java
@@ -19,7 +19,7 @@ import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.document.StorageOptions;
import net.sf.openrocket.file.RocketSaver;
import net.sf.openrocket.rocketcomponent.AxialStage;
-import net.sf.openrocket.rocketcomponent.BoosterSet;
+import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration.DeployEvent;
import net.sf.openrocket.rocketcomponent.FinSet;
import net.sf.openrocket.rocketcomponent.FlightConfigurableComponent;
@@ -259,7 +259,7 @@ public class OpenRocketSaver extends RocketSaver {
/////////////////
// Search the rocket for any Boosters or Pods (version 1.8)
for (RocketComponent c : document.getRocket()) {
- if ((c instanceof BoosterSet) || (c instanceof PodSet)) {
+ if ((c instanceof ParallelStage) || (c instanceof PodSet)) {
return FILE_VERSION_DIVISOR + 8;
}
}
diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java b/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java
index 5012694a7..44701df23 100644
--- a/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java
+++ b/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java
@@ -9,7 +9,7 @@ import net.sf.openrocket.preset.ComponentPreset;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.BodyComponent;
import net.sf.openrocket.rocketcomponent.BodyTube;
-import net.sf.openrocket.rocketcomponent.BoosterSet;
+import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.Bulkhead;
import net.sf.openrocket.rocketcomponent.CenteringRing;
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
@@ -90,7 +90,7 @@ class DocumentConfig {
// Other
constructors.put("stage", AxialStage.class.getConstructor(new Class>[0]));
- constructors.put("boosterset", BoosterSet.class.getConstructor(new Class>[0]));
+ constructors.put("boosterset", ParallelStage.class.getConstructor(new Class>[0]));
constructors.put("podset", PodSet.class.getConstructor(new Class>[0]));
} catch (NoSuchMethodException e) {
@@ -150,11 +150,11 @@ class DocumentConfig {
// BoosterSet
setters.put("BoosterSet:instancecount", new IntSetter(
- Reflection.findMethod(BoosterSet.class, "setInstanceCount",int.class)));
+ Reflection.findMethod(ParallelStage.class, "setInstanceCount",int.class)));
setters.put("BoosterSet:radialoffset", new DoubleSetter(
- Reflection.findMethod(BoosterSet.class, "setRadialOffset", double.class)));
+ Reflection.findMethod(ParallelStage.class, "setRadialOffset", double.class)));
setters.put("BoosterSet:angleoffset", new DoubleSetter(
- Reflection.findMethod(BoosterSet.class, "setAngularOffset", double.class)));
+ Reflection.findMethod(ParallelStage.class, "setAngularOffset", double.class)));
// SymmetricComponent
setters.put("SymmetricComponent:thickness", new DoubleSetter(
diff --git a/core/src/net/sf/openrocket/file/openrocket/importt/PositionSetter.java b/core/src/net/sf/openrocket/file/openrocket/importt/PositionSetter.java
index 0a206cafb..a9c470824 100644
--- a/core/src/net/sf/openrocket/file/openrocket/importt/PositionSetter.java
+++ b/core/src/net/sf/openrocket/file/openrocket/importt/PositionSetter.java
@@ -4,7 +4,7 @@ import java.util.HashMap;
import net.sf.openrocket.aerodynamics.Warning;
import net.sf.openrocket.aerodynamics.WarningSet;
-import net.sf.openrocket.rocketcomponent.BoosterSet;
+import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.FinSet;
import net.sf.openrocket.rocketcomponent.InternalComponent;
import net.sf.openrocket.rocketcomponent.LaunchLug;
@@ -46,8 +46,8 @@ class PositionSetter implements Setter {
} else if (c instanceof TubeFinSet) {
((TubeFinSet) c).setRelativePosition(type);
c.setAxialOffset(pos);
- } else if (c instanceof BoosterSet) {
- ((BoosterSet) c).setRelativePositionMethod(type);
+ } else if (c instanceof ParallelStage) {
+ ((ParallelStage) c).setRelativePositionMethod(type);
c.setAxialOffset(pos);
} else if (c instanceof PodSet) {
((PodSet) c).setRelativePositionMethod(type);
diff --git a/core/src/net/sf/openrocket/file/openrocket/savers/AxialStageSaver.java b/core/src/net/sf/openrocket/file/openrocket/savers/AxialStageSaver.java
index 013ad6636..b3115c749 100644
--- a/core/src/net/sf/openrocket/file/openrocket/savers/AxialStageSaver.java
+++ b/core/src/net/sf/openrocket/file/openrocket/savers/AxialStageSaver.java
@@ -5,7 +5,7 @@ import java.util.List;
import java.util.Locale;
import net.sf.openrocket.rocketcomponent.AxialStage;
-import net.sf.openrocket.rocketcomponent.BoosterSet;
+import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.FlightConfigurationID;
import net.sf.openrocket.rocketcomponent.Rocket;
@@ -28,7 +28,7 @@ public class AxialStageSaver extends ComponentAssemblySaver {
list.add("");
}
} else {
- if (c instanceof BoosterSet) {
+ if (c instanceof ParallelStage) {
list.add("");
instance.addParams(c, list);
list.add("");
diff --git a/core/src/net/sf/openrocket/file/openrocket/savers/ComponentAssemblySaver.java b/core/src/net/sf/openrocket/file/openrocket/savers/ComponentAssemblySaver.java
index ef624e2c4..c9facdc38 100644
--- a/core/src/net/sf/openrocket/file/openrocket/savers/ComponentAssemblySaver.java
+++ b/core/src/net/sf/openrocket/file/openrocket/savers/ComponentAssemblySaver.java
@@ -4,7 +4,7 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
-import net.sf.openrocket.rocketcomponent.BoosterSet;
+import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.ComponentAssembly;
import net.sf.openrocket.rocketcomponent.Instanceable;
import net.sf.openrocket.rocketcomponent.PodSet;
@@ -24,7 +24,7 @@ public class ComponentAssemblySaver extends RocketComponentSaver {
list.add("");
instance.addParams(c, list);
list.add("");
- } else if (c instanceof BoosterSet) {
+ } else if (c instanceof ParallelStage) {
list.add("");
instance.addParams(c, list);
list.add("");
diff --git a/core/src/net/sf/openrocket/masscalc/MassCalculator.java b/core/src/net/sf/openrocket/masscalc/MassCalculator.java
index 98bb13198..86ab2af3c 100644
--- a/core/src/net/sf/openrocket/masscalc/MassCalculator.java
+++ b/core/src/net/sf/openrocket/masscalc/MassCalculator.java
@@ -13,7 +13,7 @@ import net.sf.openrocket.motor.MotorInstanceConfiguration;
import net.sf.openrocket.motor.MotorInstanceId;
import net.sf.openrocket.motor.ThrustCurveMotor;
import net.sf.openrocket.rocketcomponent.AxialStage;
-import net.sf.openrocket.rocketcomponent.BoosterSet;
+import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.ComponentAssembly;
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.Instanceable;
@@ -345,7 +345,7 @@ public class MassCalculator implements Monitorable {
MassData childrenData = MassData.ZERO_DATA;
// Combine data for subcomponents
for (RocketComponent child : component.getChildren()) {
- if( child instanceof BoosterSet ){
+ if( child instanceof ParallelStage ){
// this stage will be tallied separately... skip.
continue;
}
@@ -401,7 +401,7 @@ public class MassCalculator implements Monitorable {
// move to parent's reference point
resultantData = resultantData.move( component.getOffset() );
- if( component instanceof BoosterSet ){
+ if( component instanceof ParallelStage ){
// hacky correction for the fact Booster Stages aren't direct subchildren to the rocket
resultantData = resultantData.move( component.getParent().getOffset() );
}
diff --git a/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java b/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java
index 918fb196f..5288ce692 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java
@@ -63,7 +63,7 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC
*/
@Override
public boolean isCompatible(Class extends RocketComponent> type) {
- if (BoosterSet.class.isAssignableFrom(type)) {
+ if (ParallelStage.class.isAssignableFrom(type)) {
return true;
} else if (PodSet.class.isAssignableFrom(type)) {
return true;
diff --git a/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java b/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java
index 043aeef54..f12d270e8 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java
@@ -81,6 +81,22 @@ public abstract class ComponentAssembly extends RocketComponent {
return 0;
}
+ public double getOuterRadius(){
+ double outerRadius=0;
+ for( RocketComponent comp : children ){
+ double thisRadius=0;
+ if( comp instanceof BodyTube ){
+ thisRadius = ((BodyTube)comp).getOuterRadius();
+ }else if( comp instanceof Transition ){
+ Transition trans = (Transition)comp;
+ thisRadius = Math.max( trans.getForeRadius(), trans.getAftRadius());
+ }
+
+ outerRadius = Math.max( outerRadius, thisRadius);
+ }
+ return outerRadius;
+ }
+
/**
* Components have no aerodynamic effect, so return false.
*/
@@ -113,7 +129,7 @@ public abstract class ComponentAssembly extends RocketComponent {
if (null == this.parent) {
throw new NullPointerException(" a Stage requires a parent before any positioning! ");
}
- if ((this instanceof BoosterSet ) || ( this instanceof PodSet )){
+ if ((this instanceof ParallelStage ) || ( this instanceof PodSet )){
if (Position.AFTER == _newPosition) {
log.warn("Stages (or Pods) cannot be relative to other stages via AFTER! Ignoring.");
super.setRelativePosition(Position.TOP);
diff --git a/core/src/net/sf/openrocket/rocketcomponent/BoosterSet.java b/core/src/net/sf/openrocket/rocketcomponent/ParallelStage.java
similarity index 85%
rename from core/src/net/sf/openrocket/rocketcomponent/BoosterSet.java
rename to core/src/net/sf/openrocket/rocketcomponent/ParallelStage.java
index 5154384b3..02a36fdfe 100644
--- a/core/src/net/sf/openrocket/rocketcomponent/BoosterSet.java
+++ b/core/src/net/sf/openrocket/rocketcomponent/ParallelStage.java
@@ -11,7 +11,7 @@ import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.Coordinate;
-public class BoosterSet extends AxialStage implements FlightConfigurableComponent, RingInstanceable {
+public class ParallelStage extends AxialStage implements FlightConfigurableComponent, RingInstanceable {
private static final Translator trans = Application.getTranslator();
//private static final Logger log = LoggerFactory.getLogger(BoosterSet.class);
@@ -20,15 +20,16 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen
protected double angularSeparation = Math.PI;
protected double angularPosition_rad = 0;
+ protected boolean autoRadialPosition = true;
protected double radialPosition_m = 0;
- public BoosterSet() {
+ public ParallelStage() {
this.count = 2;
this.relativePosition = Position.BOTTOM;
this.angularSeparation = Math.PI * 2 / this.count;
}
- public BoosterSet( final int _count ){
+ public ParallelStage( final int _count ){
this();
this.count = _count;
@@ -88,7 +89,7 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen
@Override
protected RocketComponent copyWithOriginalID() {
- BoosterSet copy = (BoosterSet) (super.copyWithOriginalID());
+ ParallelStage copy = (ParallelStage) (super.copyWithOriginalID());
return copy;
}
@@ -192,6 +193,15 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen
return this.getAxialOffset();
}
+ public boolean getAutoRadialOffset(){
+ return this.autoRadialPosition;
+ }
+
+ public void setAutoRadialOffset( final boolean enabled ){
+ this.autoRadialPosition = enabled;
+ fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
+ }
+
@Override
public void setRadialOffset(final double radius) {
mutex.verify();
@@ -206,32 +216,6 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
}
-// @Override
-// protected Coordinate[] shiftCoordinates(Coordinate[] c) {
-// checkState();
-//
-// if (1 < c.length) {
-// throw new BugException("implementation of 'shiftCoordinates' assumes the coordinate array has len == 1; The length here is "+c.length+"! ");
-// }
-//
-// double radius = this.radialPosition_m;
-// double angle0 = this.angularPosition_rad;
-// double angleIncr = this.angularSeparation;
-// Coordinate center = c[0];
-// Coordinate[] toReturn = new Coordinate[this.count];
-// //Coordinate thisOffset;
-// double thisAngle = angle0;
-// for (int instanceNumber = 0; instanceNumber < this.count; instanceNumber++) {
-// toReturn[instanceNumber] = center.add(0, radius * Math.cos(thisAngle), radius * Math.sin(thisAngle));
-//
-// thisAngle += angleIncr;
-// }
-//
-// return toReturn;
-// }
-//
-
-
@Override
public void toDebugTreeNode(final StringBuilder buffer, final String prefix) {
buffer.append(String.format("%s %-24s (stage: %d)", prefix, this.getName(), this.getStageNumber()));
@@ -248,5 +232,20 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen
}
+ @Override
+ protected void update() {
+ super.update();
+
+ if( this.autoRadialPosition ){
+ AxialStage parentStage = (AxialStage)this.parent;
+ if( null == parentStage ){
+ this.radialPosition_m = this.getOuterRadius();
+ }else{
+ this.radialPosition_m = this.getOuterRadius() + parentStage.getOuterRadius();
+ }
+ }
+ }
+
+
}
diff --git a/core/src/net/sf/openrocket/util/TestRockets.java b/core/src/net/sf/openrocket/util/TestRockets.java
index 8f63b03e6..73d8ba3c8 100644
--- a/core/src/net/sf/openrocket/util/TestRockets.java
+++ b/core/src/net/sf/openrocket/util/TestRockets.java
@@ -21,7 +21,7 @@ import net.sf.openrocket.preset.InvalidComponentPresetException;
import net.sf.openrocket.preset.TypedPropertyMap;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.BodyTube;
-import net.sf.openrocket.rocketcomponent.BoosterSet;
+import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.Bulkhead;
import net.sf.openrocket.rocketcomponent.CenteringRing;
import net.sf.openrocket.rocketcomponent.ClusterConfiguration;
@@ -829,7 +829,7 @@ public class TestRockets {
// ====== Booster Stage Set ======
// ====== ====== ====== ======
- BoosterSet boosterStage = new BoosterSet();
+ ParallelStage boosterStage = new ParallelStage();
boosterStage.setName("Booster Stage");
coreStage.addChild( boosterStage);
boosterStage.setRelativePositionMethod(Position.BOTTOM);
diff --git a/core/test/net/sf/openrocket/masscalc/MassCalculatorTest.java b/core/test/net/sf/openrocket/masscalc/MassCalculatorTest.java
index 2e55fc9b4..74382d111 100644
--- a/core/test/net/sf/openrocket/masscalc/MassCalculatorTest.java
+++ b/core/test/net/sf/openrocket/masscalc/MassCalculatorTest.java
@@ -8,7 +8,7 @@ import org.junit.Test;
import net.sf.openrocket.masscalc.MassCalculator.MassCalcType;
import net.sf.openrocket.motor.MotorInstance;
-import net.sf.openrocket.rocketcomponent.BoosterSet;
+import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.FlightConfiguration;
import net.sf.openrocket.rocketcomponent.FlightConfigurationID;
import net.sf.openrocket.rocketcomponent.InnerTube;
@@ -119,7 +119,7 @@ public class MassCalculatorTest extends BaseTestCase {
// ====== Booster Set Stage ======
// ====== ====== ======
- BoosterSet boosters = (BoosterSet) rkt.getChild(1).getChild(1);
+ ParallelStage boosters = (ParallelStage) rkt.getChild(1).getChild(1);
{
expMass = 0.01530561538;
cc= boosters.getChild(0);
@@ -232,7 +232,7 @@ public class MassCalculatorTest extends BaseTestCase {
// ====== Booster Set Stage ======
// ====== ====== ======
- BoosterSet boosters = (BoosterSet) rkt.getChild(1).getChild(1);
+ ParallelStage boosters = (ParallelStage) rkt.getChild(1).getChild(1);
{
cc= boosters.getChild(0);
expInertia = 5.20107e-6;
@@ -264,7 +264,7 @@ public class MassCalculatorTest extends BaseTestCase {
Rocket rocket = TestRockets.makeFalcon9Heavy();
rocket.setName("TestRocket."+Thread.currentThread().getStackTrace()[1].getMethodName());
- BoosterSet boosters = (BoosterSet) rocket.getChild(1).getChild(1);
+ ParallelStage boosters = (ParallelStage) rocket.getChild(1).getChild(1);
int boostNum = boosters.getStageNumber();
rocket.getDefaultConfiguration().setAllStages(false);
@@ -293,7 +293,7 @@ public class MassCalculatorTest extends BaseTestCase {
Rocket rocket = TestRockets.makeFalcon9Heavy();
rocket.setName("TestRocket."+Thread.currentThread().getStackTrace()[1].getMethodName());
- BoosterSet boosters = (BoosterSet) rocket.getChild(1).getChild(1);
+ ParallelStage boosters = (ParallelStage) rocket.getChild(1).getChild(1);
int boostNum = boosters.getStageNumber();
rocket.getDefaultConfiguration().setAllStages(false);
rocket.getDefaultConfiguration().setOnlyStage( boostNum);
@@ -339,7 +339,7 @@ public class MassCalculatorTest extends BaseTestCase {
rocket.setName("TestRocket."+Thread.currentThread().getStackTrace()[1].getMethodName());
FlightConfiguration defaultConfig = rocket.getDefaultConfiguration();
- BoosterSet boosters = (BoosterSet) rocket.getChild(1).getChild(1);
+ ParallelStage boosters = (ParallelStage) rocket.getChild(1).getChild(1);
int boostNum = boosters.getStageNumber();
rocket.getDefaultConfiguration().setAllStages(false);
@@ -365,7 +365,7 @@ public class MassCalculatorTest extends BaseTestCase {
FlightConfiguration defaultConfig = rocket.getDefaultConfiguration();
rocket.setName("TestRocket."+Thread.currentThread().getStackTrace()[1].getMethodName());
- BoosterSet boosters = (BoosterSet) rocket.getChild(1).getChild(1);
+ ParallelStage boosters = (ParallelStage) rocket.getChild(1).getChild(1);
int boostNum = boosters.getStageNumber();
rocket.getDefaultConfiguration().setAllStages(false);
@@ -393,7 +393,7 @@ public class MassCalculatorTest extends BaseTestCase {
FlightConfiguration config = rocket.getDefaultConfiguration();
rocket.setName("TestRocket."+Thread.currentThread().getStackTrace()[1].getMethodName());
- BoosterSet boosters = (BoosterSet) rocket.getChild(1).getChild(1);
+ ParallelStage boosters = (ParallelStage) rocket.getChild(1).getChild(1);
int boostNum = boosters.getStageNumber();
config.setAllStages(false);
config.setOnlyStage( boostNum);
@@ -444,7 +444,7 @@ public class MassCalculatorTest extends BaseTestCase {
FlightConfiguration config = rocket.getDefaultConfiguration();
rocket.setName("TestRocket."+Thread.currentThread().getStackTrace()[1].getMethodName());
- BoosterSet boosters = (BoosterSet) rocket.getChild(1).getChild(1);
+ ParallelStage boosters = (ParallelStage) rocket.getChild(1).getChild(1);
int boostNum = boosters.getStageNumber();
config.setAllStages(false);
config.setOnlyStage( boostNum);
diff --git a/core/test/net/sf/openrocket/rocketcomponent/BoosterSetTest.java b/core/test/net/sf/openrocket/rocketcomponent/BoosterSetTest.java
index 3ba03ed49..042ab61ee 100644
--- a/core/test/net/sf/openrocket/rocketcomponent/BoosterSetTest.java
+++ b/core/test/net/sf/openrocket/rocketcomponent/BoosterSetTest.java
@@ -23,7 +23,7 @@ public class BoosterSetTest extends BaseTestCase {
}
public Rocket createTestRocket() {
- double tubeRadius = 1;
+ double tubeRadius = 1.2;
// setup
Rocket rocket = new Rocket();
rocket.setName("Rocket");
@@ -53,28 +53,29 @@ public class BoosterSetTest extends BaseTestCase {
return rocket;
}
- public BoosterSet createBooster() {
+ public ParallelStage createBooster() {
double tubeRadius = 0.8;
- BoosterSet booster = new BoosterSet();
- booster.setName("Booster Stage");
+ ParallelStage strapon = new ParallelStage();
+ strapon.setName("Booster Stage");
+ strapon.setAutoRadialOffset(true);
RocketComponent boosterNose = new NoseCone(Transition.Shape.CONICAL, 2.0, tubeRadius);
boosterNose.setName("Booster Nosecone");
- booster.addChild(boosterNose);
+ strapon.addChild(boosterNose);
RocketComponent boosterBody = new BodyTube(2.0, tubeRadius, 0.01);
boosterBody.setName("Booster Body ");
- booster.addChild(boosterBody);
+ strapon.addChild(boosterBody);
Transition boosterTail = new Transition();
boosterTail.setName("Booster Tail");
boosterTail.setForeRadius(1.0);
boosterTail.setAftRadius(0.5);
boosterTail.setLength(1.0);
- booster.addChild(boosterTail);
+ strapon.addChild(boosterTail);
- booster.setInstanceCount(3);
- booster.setRadialOffset(1.8);
+ strapon.setInstanceCount(3);
+ strapon.setRadialOffset(1.8);
- return booster;
+ return strapon;
}
/* From OpenRocket Technical Documentation
@@ -104,7 +105,7 @@ public class BoosterSetTest extends BaseTestCase {
}
@Test
- public void testAddSustainerStage() {
+ public void testCreateSustainer() {
RocketComponent rocket = createTestRocket();
// Sustainer Stage
@@ -200,7 +201,7 @@ public class BoosterSetTest extends BaseTestCase {
assertEquals(" createTestRocket failed:\n" + rocketTree + " core Fins abs X: ", expectedX, resultantX, EPSILON);
}
-
+
@Test
public void testSetStagePosition_topOfStack() {
// setup
@@ -233,15 +234,17 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
- BoosterSet set0 = createBooster();
+ ParallelStage set0 = createBooster();
core.addChild(set0);
double targetOffset = 0;
set0.setAxialOffset(Position.BOTTOM, targetOffset);
// vv function under test
+ set0.setAutoRadialOffset(true);
set0.setInstanceCount(2);
set0.setRadialOffset(4.0);
set0.setAngularOffset(Math.PI / 2);
+
// ^^ function under test
String treeDump = rocket.toDebugTree();
@@ -262,6 +265,49 @@ public class BoosterSetTest extends BaseTestCase {
assertEquals(" 'setAngularOffset(double)' failed:\n" + treeDump + " angular offset: ", expectedAngularOffset, angularOffset, EPSILON);
}
+
+ @Test
+ public void testAddStraponAuto() {
+ // setup
+ RocketComponent rocket = createTestRocket();
+ AxialStage core = (AxialStage) rocket.getChild(1);
+ ParallelStage strapons = createBooster();
+ core.addChild( strapons);
+
+ double targetXOffset = +1.0;
+ strapons.setAxialOffset(Position.BOTTOM, targetXOffset);
+ double targetRadialOffset = 0.01;
+ // vv function under test
+ strapons.setRadialOffset(targetRadialOffset);
+ strapons.setAutoRadialOffset(true);
+ // ^^ function under test
+ String treeDump = rocket.toDebugTree();
+
+ double expectedRadialOffset = core.getOuterRadius() + strapons.getOuterRadius();
+ double actualRadialOffset = strapons.getRadialOffset();
+ assertEquals(" 'setAutoRadialOffset()' failed:\n" + treeDump , expectedRadialOffset, actualRadialOffset, EPSILON);
+
+// Coordinate[] instanceAbsoluteCoords = set0.getLocations();
+// // Coordinate[] instanceRelativeCoords = new Coordinate[] { componentAbsolutePosition };
+// // instanceRelativeCoords = boosterSet.shiftCoordinates(instanceRelativeCoords);
+//
+// int inst = 0;
+// Coordinate expectedPosition0 = new Coordinate(expectedX, radius * Math.cos(angle * inst), radius * Math.sin(angle * inst));
+// Coordinate resultantPosition0 = instanceAbsoluteCoords[inst];
+// assertEquals(" 'setAngularOffset(double)' failed:\n" + treeDump + " angular offset: ", resultantPosition0, equalTo(expectedPosition0));
+//
+// inst = 1;
+// Coordinate expectedPosition1 = new Coordinate(expectedX, radius * Math.cos(angle * inst), radius * Math.sin(angle * inst));
+// Coordinate resultantPosition1 = instanceAbsoluteCoords[inst];
+// assertThat(treeDump + "\n>> Failed to generate Parallel Stage instances correctly: ", resultantPosition1, equalTo(expectedPosition1));
+//
+// inst = 2;
+// Coordinate expectedPosition2 = new Coordinate(expectedX, radius * Math.cos(angle * inst), radius * Math.sin(angle * inst));
+// Coordinate resultantPosition2 = instanceAbsoluteCoords[inst];
+// assertThat(treeDump + "\n>> Failed to generate Parallel Stage instances correctly: ", resultantPosition2, equalTo(expectedPosition2));
+//
+ }
+
// because even though this is an "outside" stage, it's relative to itself -- i.e. an error.
// also an error with a well-defined failure result (i.e. just failover to AFTER placement as the first stage of a rocket.
@Test
@@ -269,7 +315,7 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
- BoosterSet set0 = createBooster();
+ ParallelStage set0 = createBooster();
core.addChild(set0);
double targetOffset = 0;
@@ -314,7 +360,7 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
- BoosterSet booster = createBooster();
+ ParallelStage booster = createBooster();
core.addChild(booster);
double targetX = +17.0;
@@ -376,7 +422,7 @@ public class BoosterSetTest extends BaseTestCase {
public void testSetStagePosition_outsideTOP() {
Rocket rocket = this.createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
- BoosterSet booster = createBooster();
+ ParallelStage booster = createBooster();
core.addChild(booster);
double targetOffset = +2.0;
@@ -406,7 +452,7 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
- BoosterSet booster = createBooster();
+ ParallelStage booster = createBooster();
core.addChild(booster);
// when 'external' the stage should be freely movable
@@ -436,7 +482,7 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
- BoosterSet booster = createBooster();
+ ParallelStage booster = createBooster();
core.addChild(booster);
// vv function under test
@@ -465,7 +511,7 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
- BoosterSet booster = createBooster();
+ ParallelStage booster = createBooster();
core.addChild(booster);
double targetOffset = +4.50;
@@ -489,7 +535,7 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
- BoosterSet booster = createBooster();
+ ParallelStage booster = createBooster();
core.addChild(booster);
double targetOffset = +4.50;
@@ -513,7 +559,7 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
- BoosterSet booster = createBooster();
+ ParallelStage booster = createBooster();
core.addChild(booster);
double targetOffset = +4.50;
@@ -538,7 +584,7 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
- BoosterSet booster = createBooster();
+ ParallelStage booster = createBooster();
core.addChild(booster);
@@ -563,7 +609,7 @@ public class BoosterSetTest extends BaseTestCase {
// setup
RocketComponent rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
- BoosterSet booster = createBooster();
+ ParallelStage booster = createBooster();
core.addChild(booster);
double targetOffset = +4.50;
@@ -587,7 +633,7 @@ public class BoosterSetTest extends BaseTestCase {
Rocket rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
- BoosterSet booster = new BoosterSet();
+ ParallelStage booster = new ParallelStage();
booster.setName("Booster Stage");
core.addChild(booster);
final double targetOffset = +2.50;
@@ -623,10 +669,10 @@ public class BoosterSetTest extends BaseTestCase {
public void testStageInitializationMethodValueOrder() {
Rocket rocket = createTestRocket();
AxialStage core = (AxialStage) rocket.getChild(1);
- BoosterSet boosterA = createBooster();
+ ParallelStage boosterA = createBooster();
boosterA.setName("Booster A Stage");
core.addChild(boosterA);
- BoosterSet boosterB = createBooster();
+ ParallelStage boosterB = createBooster();
boosterB.setName("Booster B Stage");
core.addChild(boosterB);
@@ -653,11 +699,11 @@ public class BoosterSetTest extends BaseTestCase {
Rocket rocket = createTestRocket();
AxialStage sustainer = (AxialStage) rocket.getChild(0);
AxialStage core = (AxialStage) rocket.getChild(1);
- BoosterSet boosterA = createBooster();
+ ParallelStage boosterA = createBooster();
boosterA.setName("Booster A Stage");
core.addChild(boosterA);
boosterA.setAxialOffset(Position.BOTTOM, 0.0);
- BoosterSet boosterB = createBooster();
+ ParallelStage boosterB = createBooster();
boosterB.setName("Booster B Stage");
core.addChild(boosterB);
boosterB.setAxialOffset(Position.BOTTOM, 0);
@@ -691,7 +737,7 @@ public class BoosterSetTest extends BaseTestCase {
actualStageCount = rocket.getDefaultConfiguration().getStageCount();
assertEquals(" Stage tracking error: removed booster A, but configuration not updated: " + treedump, expectedStageCount, actualStageCount);
- BoosterSet boosterC = createBooster();
+ ParallelStage boosterC = createBooster();
boosterC.setName("Booster C Stage");
core.addChild(boosterC);
boosterC.setAxialOffset(Position.BOTTOM, 0);
diff --git a/swing/src/net/sf/openrocket/gui/configdialog/ComponentAssemblyConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/ComponentAssemblyConfig.java
index ac3ce259e..7d54fbb09 100644
--- a/swing/src/net/sf/openrocket/gui/configdialog/ComponentAssemblyConfig.java
+++ b/swing/src/net/sf/openrocket/gui/configdialog/ComponentAssemblyConfig.java
@@ -27,82 +27,6 @@ public class ComponentAssemblyConfig extends RocketComponentConfig {
public ComponentAssemblyConfig(OpenRocketDocument document, RocketComponent component) {
super(document, component);
- // For DEBUG purposes
- if( component instanceof AxialStage ){
- System.err.println(" Dumping AxialStage tree info for devel / debugging.");
- System.err.println(component.toDebugTree());
- }
-
- // only stages which are actually off-centerline will get the dialog here:
- if(( component instanceof ComponentAssembly )&&( 1 < component.getInstanceCount() )){
- tabbedPane.insertTab( trans.get("RocketCompCfg.tab.Parallel"), null, parallelTab( (ComponentAssembly) component ), trans.get("RocketCompCfg.tab.ParallelComment"), 1);
- }
- }
-
- private JPanel parallelTab( final ComponentAssembly assembly ){
- JPanel motherPanel = new JPanel( new MigLayout("fill"));
-
- // set radial distance
- JLabel radiusLabel = new JLabel(trans.get("StageConfig.parallel.radius"));
- motherPanel.add( radiusLabel , "align left");
- DoubleModel radiusModel = new DoubleModel( assembly, "RadialOffset", UnitGroup.UNITS_LENGTH, 0);
- //radiusModel.setCurrentUnit( UnitGroup.UNITS_LENGTH.getUnit("cm"));
- JSpinner radiusSpinner = new JSpinner( radiusModel.getSpinnerModel());
- radiusSpinner.setEditor(new SpinnerEditor(radiusSpinner ));
- motherPanel.add(radiusSpinner , "growx 1, align right");
- UnitSelector radiusUnitSelector = new UnitSelector(radiusModel);
- motherPanel.add(radiusUnitSelector, "growx 1, wrap");
-
- // set location angle around the primary stage
- JLabel angleLabel = new JLabel(trans.get("StageConfig.parallel.angle"));
- motherPanel.add( angleLabel, "align left");
- DoubleModel angleModel = new DoubleModel( assembly, "AngularOffset", 1.0, UnitGroup.UNITS_ANGLE, 0.0, Math.PI*2);
- angleModel.setCurrentUnit( UnitGroup.UNITS_ANGLE.getUnit("rad"));
- JSpinner angleSpinner = new JSpinner(angleModel.getSpinnerModel());
- angleSpinner.setEditor(new SpinnerEditor(angleSpinner));
- motherPanel.add(angleSpinner, "growx 1");
- UnitSelector angleUnitSelector = new UnitSelector(angleModel);
- motherPanel.add( angleUnitSelector, "growx 1, wrap");
-
- // set multiplicity
- JLabel countLabel = new JLabel(trans.get("StageConfig.parallel.count"));
- motherPanel.add( countLabel, "align left");
-
- IntegerModel countModel = new IntegerModel( assembly, "InstanceCount", 2);
- JSpinner countSpinner = new JSpinner(countModel.getSpinnerModel());
- countSpinner.setEditor(new SpinnerEditor(countSpinner));
- motherPanel.add(countSpinner, "growx 1, wrap");
-
- // setPositions relative to parent component
- JLabel positionLabel = new JLabel(trans.get("LaunchLugCfg.lbl.Posrelativeto"));
- motherPanel.add( positionLabel);
-
- // EnumModel(ChangeSource source, String valueName, Enum[] values) {
- ComboBoxModel relativePositionMethodModel = new EnumModel(component, "RelativePositionMethod",
- new RocketComponent.Position[] {
- RocketComponent.Position.TOP,
- RocketComponent.Position.MIDDLE,
- RocketComponent.Position.BOTTOM,
- RocketComponent.Position.ABSOLUTE
- });
- JComboBox> positionMethodCombo = new JComboBox( relativePositionMethodModel );
- motherPanel.add(positionMethodCombo, "spanx 2, growx, wrap");
-
- // relative offset labels
- JLabel positionPlusLabel = new JLabel(trans.get("StageConfig.parallel.offset"));
- motherPanel.add( positionPlusLabel );
- DoubleModel axialOffsetModel = new DoubleModel( assembly, "AxialOffset", UnitGroup.UNITS_LENGTH);
- axialOffsetModel.setCurrentUnit(UnitGroup.UNITS_LENGTH.getUnit("cm"));
- JSpinner axPosSpin= new JSpinner( axialOffsetModel.getSpinnerModel());
- axPosSpin.setEditor(new SpinnerEditor(axPosSpin));
- motherPanel.add(axPosSpin, "growx");
- UnitSelector axialOffsetUnitSelector = new UnitSelector(axialOffsetModel);
- motherPanel.add(axialOffsetUnitSelector, "growx 1, wrap");
-
- // For DEBUG purposes
- //System.err.println(assembly.getRocket().toDebugTree());
-
- return motherPanel;
}
}
diff --git a/swing/src/net/sf/openrocket/gui/configdialog/ParallelStageConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/ParallelStageConfig.java
new file mode 100644
index 000000000..21286436d
--- /dev/null
+++ b/swing/src/net/sf/openrocket/gui/configdialog/ParallelStageConfig.java
@@ -0,0 +1,118 @@
+package net.sf.openrocket.gui.configdialog;
+
+import javax.swing.ComboBoxModel;
+import javax.swing.JCheckBox;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSpinner;
+
+import net.miginfocom.swing.MigLayout;
+import net.sf.openrocket.document.OpenRocketDocument;
+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.adaptors.EnumModel;
+import net.sf.openrocket.gui.adaptors.IntegerModel;
+import net.sf.openrocket.gui.components.UnitSelector;
+import net.sf.openrocket.l10n.Translator;
+import net.sf.openrocket.rocketcomponent.AxialStage;
+import net.sf.openrocket.rocketcomponent.ParallelStage;
+import net.sf.openrocket.rocketcomponent.ComponentAssembly;
+import net.sf.openrocket.rocketcomponent.RocketComponent;
+import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.unit.UnitGroup;
+import net.sf.openrocket.util.ChangeSource;
+
+public class ParallelStageConfig extends RocketComponentConfig {
+ private static final long serialVersionUID = -944969957186522471L;
+ private static final Translator trans = Application.getTranslator();
+
+ public ParallelStageConfig(OpenRocketDocument document, RocketComponent component) {
+ super(document, component);
+
+ // For DEBUG purposes
+ if( component instanceof AxialStage ){
+ System.err.println(" Dumping AxialStage tree info for devel / debugging.");
+ System.err.println(component.toDebugTree());
+ }
+
+ // only stages which are actually off-centerline will get the dialog here:
+ tabbedPane.insertTab( trans.get("RocketCompCfg.tab.Parallel"), null, parallelTab( (ParallelStage)component ), trans.get("RocketCompCfg.tab.ParallelComment"), 1);
+ }
+
+ private JPanel parallelTab( final ParallelStage boosters ){
+ JPanel motherPanel = new JPanel( new MigLayout("fill"));
+
+ // auto radial distance
+ BooleanModel autoRadOffsModel = new BooleanModel( boosters, "AutoRadialOffset");
+ JCheckBox autoRadCheckBox = new JCheckBox( autoRadOffsModel );
+ autoRadCheckBox.setText( trans.get("StageConfig.parallel.autoradius"));
+ motherPanel.add( autoRadCheckBox, "align left, wrap");
+ // set radial distance
+ JLabel radiusLabel = new JLabel(trans.get("StageConfig.parallel.radius"));
+ motherPanel.add( radiusLabel , "align left");
+ autoRadOffsModel.addEnableComponent(radiusLabel, false);
+ DoubleModel radiusModel = new DoubleModel( boosters, "RadialOffset", UnitGroup.UNITS_LENGTH, 0);
+ //radiusModel.setCurrentUnit( UnitGroup.UNITS_LENGTH.getUnit("cm"));
+ JSpinner radiusSpinner = new JSpinner( radiusModel.getSpinnerModel());
+ radiusSpinner.setEditor(new SpinnerEditor(radiusSpinner ));
+ motherPanel.add(radiusSpinner , "growx 1, align right");
+ autoRadOffsModel.addEnableComponent(radiusSpinner, false);
+ UnitSelector radiusUnitSelector = new UnitSelector(radiusModel);
+ motherPanel.add(radiusUnitSelector, "growx 1, wrap");
+ autoRadOffsModel.addEnableComponent(radiusUnitSelector, false);
+
+ // set location angle around the primary stage
+ JLabel angleLabel = new JLabel(trans.get("StageConfig.parallel.angle"));
+ motherPanel.add( angleLabel, "align left");
+ DoubleModel angleModel = new DoubleModel( boosters, "AngularOffset", 1.0, UnitGroup.UNITS_ANGLE, 0.0, Math.PI*2);
+ angleModel.setCurrentUnit( UnitGroup.UNITS_ANGLE.getUnit("rad"));
+ JSpinner angleSpinner = new JSpinner(angleModel.getSpinnerModel());
+ angleSpinner.setEditor(new SpinnerEditor(angleSpinner));
+ motherPanel.add(angleSpinner, "growx 1");
+ UnitSelector angleUnitSelector = new UnitSelector(angleModel);
+ motherPanel.add( angleUnitSelector, "growx 1, wrap");
+
+ // set multiplicity
+ JLabel countLabel = new JLabel(trans.get("StageConfig.parallel.count"));
+ motherPanel.add( countLabel, "align left");
+
+ IntegerModel countModel = new IntegerModel( boosters, "InstanceCount", 2);
+ JSpinner countSpinner = new JSpinner(countModel.getSpinnerModel());
+ countSpinner.setEditor(new SpinnerEditor(countSpinner));
+ motherPanel.add(countSpinner, "growx 1, wrap");
+
+ // setPositions relative to parent component
+ JLabel positionLabel = new JLabel(trans.get("LaunchLugCfg.lbl.Posrelativeto"));
+ motherPanel.add( positionLabel);
+
+ // EnumModel(ChangeSource source, String valueName, Enum[] values) {
+ ComboBoxModel relativePositionMethodModel = new EnumModel(component, "RelativePositionMethod",
+ new RocketComponent.Position[] {
+ RocketComponent.Position.TOP,
+ RocketComponent.Position.MIDDLE,
+ RocketComponent.Position.BOTTOM,
+ RocketComponent.Position.ABSOLUTE
+ });
+ JComboBox> positionMethodCombo = new JComboBox( relativePositionMethodModel );
+ motherPanel.add(positionMethodCombo, "spanx 2, growx, wrap");
+
+ // relative offset labels
+ JLabel positionPlusLabel = new JLabel(trans.get("StageConfig.parallel.offset"));
+ motherPanel.add( positionPlusLabel );
+ DoubleModel axialOffsetModel = new DoubleModel( boosters, "AxialOffset", UnitGroup.UNITS_LENGTH);
+ axialOffsetModel.setCurrentUnit(UnitGroup.UNITS_LENGTH.getUnit("cm"));
+ JSpinner axPosSpin= new JSpinner( axialOffsetModel.getSpinnerModel());
+ axPosSpin.setEditor(new SpinnerEditor(axPosSpin));
+ motherPanel.add(axPosSpin, "growx");
+ UnitSelector axialOffsetUnitSelector = new UnitSelector(axialOffsetModel);
+ motherPanel.add(axialOffsetUnitSelector, "growx 1, wrap");
+
+ // For DEBUG purposes
+ //System.err.println(assembly.getRocket().toDebugTree());
+
+ return motherPanel;
+ }
+
+}
diff --git a/swing/src/net/sf/openrocket/gui/configdialog/PodSetConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/PodSetConfig.java
new file mode 100644
index 000000000..664912e02
--- /dev/null
+++ b/swing/src/net/sf/openrocket/gui/configdialog/PodSetConfig.java
@@ -0,0 +1,100 @@
+package net.sf.openrocket.gui.configdialog;
+
+import javax.swing.ComboBoxModel;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JSpinner;
+
+import net.miginfocom.swing.MigLayout;
+import net.sf.openrocket.document.OpenRocketDocument;
+import net.sf.openrocket.gui.SpinnerEditor;
+import net.sf.openrocket.gui.adaptors.DoubleModel;
+import net.sf.openrocket.gui.adaptors.EnumModel;
+import net.sf.openrocket.gui.adaptors.IntegerModel;
+import net.sf.openrocket.gui.components.UnitSelector;
+import net.sf.openrocket.l10n.Translator;
+import net.sf.openrocket.rocketcomponent.AxialStage;
+import net.sf.openrocket.rocketcomponent.ComponentAssembly;
+import net.sf.openrocket.rocketcomponent.RocketComponent;
+import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.unit.UnitGroup;
+
+public class PodSetConfig extends RocketComponentConfig {
+ private static final long serialVersionUID = -944969957186522471L;
+ private static final Translator trans = Application.getTranslator();
+
+ public PodSetConfig(OpenRocketDocument document, RocketComponent component) {
+ super(document, component);
+
+ // only stages which are actually off-centerline will get the dialog here:
+ tabbedPane.insertTab( trans.get("RocketCompCfg.tab.Parallel"), null, parallelTab( (ComponentAssembly) component ), trans.get("RocketCompCfg.tab.ParallelComment"), 1);
+ }
+
+ private JPanel parallelTab( final ComponentAssembly assembly ){
+ JPanel motherPanel = new JPanel( new MigLayout("fill"));
+
+ // set radial distance
+ JLabel radiusLabel = new JLabel(trans.get("StageConfig.parallel.radius"));
+ motherPanel.add( radiusLabel , "align left");
+ DoubleModel radiusModel = new DoubleModel( assembly, "RadialOffset", UnitGroup.UNITS_LENGTH, 0);
+ //radiusModel.setCurrentUnit( UnitGroup.UNITS_LENGTH.getUnit("cm"));
+ JSpinner radiusSpinner = new JSpinner( radiusModel.getSpinnerModel());
+ radiusSpinner.setEditor(new SpinnerEditor(radiusSpinner ));
+ motherPanel.add(radiusSpinner , "growx 1, align right");
+ UnitSelector radiusUnitSelector = new UnitSelector(radiusModel);
+ motherPanel.add(radiusUnitSelector, "growx 1, wrap");
+
+ // set location angle around the primary stage
+ JLabel angleLabel = new JLabel(trans.get("StageConfig.parallel.angle"));
+ motherPanel.add( angleLabel, "align left");
+ DoubleModel angleModel = new DoubleModel( assembly, "AngularOffset", 1.0, UnitGroup.UNITS_ANGLE, 0.0, Math.PI*2);
+ angleModel.setCurrentUnit( UnitGroup.UNITS_ANGLE.getUnit("rad"));
+ JSpinner angleSpinner = new JSpinner(angleModel.getSpinnerModel());
+ angleSpinner.setEditor(new SpinnerEditor(angleSpinner));
+ motherPanel.add(angleSpinner, "growx 1");
+ UnitSelector angleUnitSelector = new UnitSelector(angleModel);
+ motherPanel.add( angleUnitSelector, "growx 1, wrap");
+
+ // set multiplicity
+ JLabel countLabel = new JLabel(trans.get("StageConfig.parallel.count"));
+ motherPanel.add( countLabel, "align left");
+
+ IntegerModel countModel = new IntegerModel( assembly, "InstanceCount", 2);
+ JSpinner countSpinner = new JSpinner(countModel.getSpinnerModel());
+ countSpinner.setEditor(new SpinnerEditor(countSpinner));
+ motherPanel.add(countSpinner, "growx 1, wrap");
+
+ // setPositions relative to parent component
+ JLabel positionLabel = new JLabel(trans.get("LaunchLugCfg.lbl.Posrelativeto"));
+ motherPanel.add( positionLabel);
+
+ // EnumModel(ChangeSource source, String valueName, Enum[] values) {
+ ComboBoxModel relativePositionMethodModel = new EnumModel(component, "RelativePositionMethod",
+ new RocketComponent.Position[] {
+ RocketComponent.Position.TOP,
+ RocketComponent.Position.MIDDLE,
+ RocketComponent.Position.BOTTOM,
+ RocketComponent.Position.ABSOLUTE
+ });
+ JComboBox> positionMethodCombo = new JComboBox( relativePositionMethodModel );
+ motherPanel.add(positionMethodCombo, "spanx 2, growx, wrap");
+
+ // relative offset labels
+ JLabel positionPlusLabel = new JLabel(trans.get("StageConfig.parallel.offset"));
+ motherPanel.add( positionPlusLabel );
+ DoubleModel axialOffsetModel = new DoubleModel( assembly, "AxialOffset", UnitGroup.UNITS_LENGTH);
+ axialOffsetModel.setCurrentUnit(UnitGroup.UNITS_LENGTH.getUnit("cm"));
+ JSpinner axPosSpin= new JSpinner( axialOffsetModel.getSpinnerModel());
+ axPosSpin.setEditor(new SpinnerEditor(axPosSpin));
+ motherPanel.add(axPosSpin, "growx");
+ UnitSelector axialOffsetUnitSelector = new UnitSelector(axialOffsetModel);
+ motherPanel.add(axialOffsetUnitSelector, "growx 1, wrap");
+
+ // For DEBUG purposes
+ //System.err.println(assembly.getRocket().toDebugTree());
+
+ return motherPanel;
+ }
+
+}
diff --git a/swing/src/net/sf/openrocket/gui/main/ComponentAddButtons.java b/swing/src/net/sf/openrocket/gui/main/ComponentAddButtons.java
index ea3e2fa6f..05381aa71 100644
--- a/swing/src/net/sf/openrocket/gui/main/ComponentAddButtons.java
+++ b/swing/src/net/sf/openrocket/gui/main/ComponentAddButtons.java
@@ -34,7 +34,7 @@ import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.Markers;
import net.sf.openrocket.rocketcomponent.BodyComponent;
import net.sf.openrocket.rocketcomponent.BodyTube;
-import net.sf.openrocket.rocketcomponent.BoosterSet;
+import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.Bulkhead;
import net.sf.openrocket.rocketcomponent.CenteringRing;
import net.sf.openrocket.rocketcomponent.EllipticalFinSet;
@@ -167,7 +167,7 @@ public class ComponentAddButtons extends JPanel implements Scrollable {
//// Component Assembly Components:
ComponentButton[] buttonsToAdd = {
new ComponentButton(AxialStage.class, trans.get("RocketActions.NewStageAct.Newstage")),
- new ComponentButton(BoosterSet.class, trans.get("compaddbuttons.newBooster.lbl")),
+ new ComponentButton(ParallelStage.class, trans.get("compaddbuttons.newBooster.lbl")),
new ComponentButton(PodSet.class, trans.get("compaddbuttons.newPods.lbl"))};
addButtonGroup(row, buttonsToAdd);
diff --git a/swing/src/net/sf/openrocket/gui/main/ComponentIcons.java b/swing/src/net/sf/openrocket/gui/main/ComponentIcons.java
index 0d846fd8d..0874c54fa 100644
--- a/swing/src/net/sf/openrocket/gui/main/ComponentIcons.java
+++ b/swing/src/net/sf/openrocket/gui/main/ComponentIcons.java
@@ -12,7 +12,7 @@ import javax.swing.ImageIcon;
import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.rocketcomponent.AxialStage;
import net.sf.openrocket.rocketcomponent.BodyTube;
-import net.sf.openrocket.rocketcomponent.BoosterSet;
+import net.sf.openrocket.rocketcomponent.ParallelStage;
import net.sf.openrocket.rocketcomponent.Bulkhead;
import net.sf.openrocket.rocketcomponent.CenteringRing;
import net.sf.openrocket.rocketcomponent.EllipticalFinSet;
@@ -86,7 +86,7 @@ public class ComponentIcons {
load("stage", trans.get("ComponentIcons.Stage"),
AxialStage.class);
load("boosters", trans.get("ComponentIcons.Boosters"),
- BoosterSet.class);
+ ParallelStage.class);
load("pods", trans.get("ComponentIcons.Pods"),
PodSet.class);
// // Mass components