diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties index 9f467d0b4..da1358bf1 100644 --- a/core/resources/l10n/messages.properties +++ b/core/resources/l10n/messages.properties @@ -896,7 +896,7 @@ StageConfig.separation.lbl.plus = plus StageConfig.separation.lbl.seconds = seconds StageConfig.parallel.radius = Radial Distance StageConfig.parallel.angle = Angle -StageConfig.parallel.count = Number of Boosters +StageConfig.parallel.count = Number of Copies StageConfig.parallel.offset = Offset Value !EllipticalFinSetConfig 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 bc7744246..0a206cafb 100644 --- a/core/src/net/sf/openrocket/file/openrocket/importt/PositionSetter.java +++ b/core/src/net/sf/openrocket/file/openrocket/importt/PositionSetter.java @@ -4,12 +4,13 @@ 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.FinSet; import net.sf.openrocket.rocketcomponent.InternalComponent; import net.sf.openrocket.rocketcomponent.LaunchLug; +import net.sf.openrocket.rocketcomponent.PodSet; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.RocketComponent.Position; -import net.sf.openrocket.rocketcomponent.AxialStage; import net.sf.openrocket.rocketcomponent.TubeFinSet; class PositionSetter implements Setter { @@ -45,8 +46,11 @@ class PositionSetter implements Setter { } else if (c instanceof TubeFinSet) { ((TubeFinSet) c).setRelativePosition(type); c.setAxialOffset(pos); - } else if (c instanceof AxialStage) { - ((AxialStage) c).setRelativePositionMethod(type); + } else if (c instanceof BoosterSet) { + ((BoosterSet) c).setRelativePositionMethod(type); + c.setAxialOffset(pos); + } else if (c instanceof PodSet) { + ((PodSet) c).setRelativePositionMethod(type); c.setAxialOffset(pos); } else { warnings.add(Warning.FILE_INVALID_PARAMETER); diff --git a/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java b/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java index 494fee744..0821bbf66 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java +++ b/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java @@ -2,7 +2,6 @@ package net.sf.openrocket.rocketcomponent; import java.util.ArrayList; import java.util.Collection; -import java.util.Iterator; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.startup.Application; @@ -94,12 +93,6 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC return copy; } - - public void setRelativePositionMethod(final Position _newPosition) { - // Axial Stages are restricted to .AFTER, and cannot be changed. - return; - } - @Override public double getPositionValue() { mutex.verify(); @@ -134,24 +127,6 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC return this.stageNumber; } - @Override - public double getAxialOffset() { - double returnValue = super.asPositionValue(this.relativePosition); - - if (0.000001 > Math.abs(returnValue)) { - returnValue = 0.0; - } - - return returnValue; - } - - @Override - public void setAxialOffset(final double _pos) { - this.updateBounds(); - super.setAxialOffset(this.relativePosition, _pos); - fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); - } - @Override public Coordinate[] shiftCoordinates(Coordinate[] c) { checkState(); @@ -172,67 +147,6 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC return buf; } - @Override - public void toDebugTreeNode(final StringBuilder buffer, final String prefix) { - - String thisLabel = this.getName() + " (" + this.getStageNumber() + ")"; - - buffer.append(String.format("%s %-24s %5.3f", prefix, thisLabel, this.getLength())); - buffer.append(String.format(" %24s %24s\n", this.getOffset(), this.getLocation()[0])); - - } - - @Override - public void updateBounds() { - // currently only updates the length - this.length = 0; - Iterator childIterator = this.getChildren().iterator(); - while (childIterator.hasNext()) { - RocketComponent curChild = childIterator.next(); - if (curChild.isCenterline()) { - this.length += curChild.getLength(); - } - } - - } - - @Override - protected void update() { - if (null == this.parent) { - return; - } - - this.updateBounds(); - // stages which are directly children of the rocket are inline, and positioned - int childNumber = this.parent.getChildPosition(this); - if (0 == childNumber) { - this.setAfter(this.parent); - } else { - RocketComponent prevStage = this.parent.getChild(childNumber - 1); - this.setAfter(prevStage); - } - - // updates the internal 'previousComponent' field. - this.updateChildSequence(); - - return; - } - - protected void updateChildSequence() { - Iterator childIterator = this.getChildren().iterator(); - RocketComponent prevComp = null; - while (childIterator.hasNext()) { - RocketComponent curChild = childIterator.next(); - if (curChild.isCenterline()) { - //curChild.previousComponent = prevComp; - curChild.setAfter(prevComp); - prevComp = curChild; - // } else { - // curChild.previousComponent = null; - } - } - } - } diff --git a/core/src/net/sf/openrocket/rocketcomponent/BoosterSet.java b/core/src/net/sf/openrocket/rocketcomponent/BoosterSet.java index 7773d4d4f..b9fd4f33d 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/BoosterSet.java +++ b/core/src/net/sf/openrocket/rocketcomponent/BoosterSet.java @@ -2,7 +2,6 @@ package net.sf.openrocket.rocketcomponent; import java.util.ArrayList; import java.util.Collection; -import java.util.Iterator; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.startup.Application; @@ -19,15 +18,9 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen private FlightConfigurationImpl separationConfigurations; - private double angularPosition_rad = 0; - private double radialPosition_m = 0; - - private int count = 2; - private double angularSeparation = Math.PI; - public BoosterSet() { + this.count = 2; this.relativePosition = Position.BOTTOM; - } @Override @@ -40,7 +33,6 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen @Override public Collection getComponentBounds() { Collection bounds = new ArrayList(8); - final double WAG_FACTOR = 1.1; double x_min = Double.MAX_VALUE; double x_max = Double.MIN_VALUE; double r_max = 0; @@ -54,8 +46,8 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen if (x_max < (currentInstanceLocation.x + this.length)) { x_max = currentInstanceLocation.x + this.length; } - if (r_max < (this.getRadialOffset() * WAG_FACTOR)) { - r_max = this.getRadialOffset() * WAG_FACTOR; + if (r_max < (this.getRadialOffset())) { + r_max = this.getRadialOffset(); } } addBound(bounds, x_min, r_max); @@ -120,47 +112,6 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen return false; } - @Override - public int getInstanceCount() { - return this.count; - } - - @Override - public void setInstanceCount(final int _count) { - mutex.verify(); - if (_count < 2) { - // there must be at least one instance.... - return; - } - - this.count = _count; - this.angularSeparation = Math.PI * 2 / this.count; - fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); - } - - @Override - public double getAngularOffset() { - return this.angularPosition_rad; - } - - @Override - public void setAngularOffset(final double angle_rad) { - this.angularPosition_rad = angle_rad; - fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); - } - - @Override - public double getRadialOffset() { - return this.radialPosition_m; - } - - @Override - public void setRadialOffset(final double radius) { - // log.error(" set radial position for: " + this.getName() + " to: " + this.radialPosition_m + " ... in meters?"); - this.radialPosition_m = radius; - fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); - } - @Override public void setRelativePositionMethod(final Position _newPosition) { if (null == this.parent) { @@ -205,31 +156,6 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen return this.stageNumber; } - @Override - public double getAxialOffset() { - double returnValue = Double.NaN; - - if ((this.isCenterline() && (Position.AFTER != this.relativePosition))) { - // remember the implicit (this instanceof Stage) - throw new BugException("found a Stage on centerline, but not positioned as AFTER. Please fix this! " + this.getName() + " is " + this.getRelativePosition().name()); - } else { - returnValue = super.asPositionValue(this.relativePosition); - } - - if (0.000001 > Math.abs(returnValue)) { - returnValue = 0.0; - } - - return returnValue; - } - - @Override - public void setAxialOffset(final double _pos) { - this.updateBounds(); - super.setAxialOffset(this.relativePosition, _pos); - fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); - } - @Override public Coordinate[] shiftCoordinates(Coordinate[] c) { checkState(); @@ -259,70 +185,4 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen return toReturn; } - @Override - protected StringBuilder toDebugDetail() { - StringBuilder buf = super.toDebugDetail(); - // if (-1 == this.getRelativeToStage()) { - // System.err.println(" >>refStageName: " + null + "\n"); - // } else { - // Stage refStage = (Stage) this.parent; - // System.err.println(" >>refStageName: " + refStage.getName() + "\n"); - // System.err.println(" ..refCenterX: " + refStage.position.x + "\n"); - // System.err.println(" ..refLength: " + refStage.getLength() + "\n"); - // } - return buf; - } - - @Override - public void toDebugTreeNode(final StringBuilder buffer, final String prefix) { - - String thisLabel = this.getName() + " (" + this.getStageNumber() + ")"; - - buffer.append(String.format("%s %-24s %5.3f", prefix, thisLabel, this.getLength())); - - if (this.isCenterline()) { - buffer.append(String.format(" %24s %24s\n", this.getOffset(), this.getLocation()[0])); - } else { - buffer.append(String.format(" %4.1f via: %s \n", this.getAxialOffset(), this.relativePosition.name())); - Coordinate[] relCoords = this.shiftCoordinates(new Coordinate[] { Coordinate.ZERO }); - Coordinate[] absCoords = this.getLocation(); - - for (int instanceNumber = 0; instanceNumber < this.count; instanceNumber++) { - Coordinate instanceRelativePosition = relCoords[instanceNumber]; - Coordinate instanceAbsolutePosition = absCoords[instanceNumber]; - buffer.append(String.format("%s [instance %2d of %2d] %32s %32s\n", prefix, instanceNumber, count, - instanceRelativePosition, instanceAbsolutePosition)); - } - } - - } - - @Override - public void updateBounds() { - // currently only updates the length - this.length = 0; - Iterator childIterator = this.getChildren().iterator(); - while (childIterator.hasNext()) { - RocketComponent curChild = childIterator.next(); - this.length += curChild.getLength(); - } - - } - - @Override - protected void update() { - if (null == this.parent) { - return; - } - - this.updateBounds(); - // because if parent is instanceof Stage, that means 'this' is positioned externally - super.update(); - - // updates the internal 'previousComponent' field. - this.updateChildSequence(); - - return; - } - } diff --git a/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java b/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java index de5b78d26..9d7c139ea 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java +++ b/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java @@ -2,9 +2,13 @@ package net.sf.openrocket.rocketcomponent; import java.util.Collection; import java.util.Collections; +import java.util.Iterator; import net.sf.openrocket.util.Coordinate; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** @@ -16,7 +20,14 @@ import net.sf.openrocket.util.Coordinate; * @author Sampo Niskanen */ public abstract class ComponentAssembly extends RocketComponent { - + private static final Logger log = LoggerFactory.getLogger(ComponentAssembly.class); + + protected double angularPosition_rad = 0; + protected double radialPosition_m = 0; + + protected int count = 1; + protected double angularSeparation = Math.PI; + /** * Sets the position of the components to POSITION_RELATIVE_AFTER. * (Should have no effect.) @@ -25,14 +36,31 @@ public abstract class ComponentAssembly extends RocketComponent { super(RocketComponent.Position.AFTER); } + + @Override + public int getInstanceCount() { + return this.count; + } + + public double getAngularOffset() { + return this.angularPosition_rad; + } + + + @Override + public double getAxialOffset() { + return super.asPositionValue(this.relativePosition); + } + + /** * Null method (ComponentAssembly has no bounds of itself). */ @Override - public Collection getComponentBounds() { + public Collection getComponentBounds() { return Collections.emptyList(); } - + /** * Null method (ComponentAssembly has no mass of itself). */ @@ -40,7 +68,7 @@ public abstract class ComponentAssembly extends RocketComponent { public Coordinate getComponentCG() { return Coordinate.NUL; } - + /** * Null method (ComponentAssembly has no mass of itself). */ @@ -49,6 +77,11 @@ public abstract class ComponentAssembly extends RocketComponent { return 0; } + public double getRadialOffset() { + return this.radialPosition_m; + } + + /** * Null method (ComponentAssembly has no mass of itself). */ @@ -57,6 +90,11 @@ public abstract class ComponentAssembly extends RocketComponent { return 0; } + @Override + public boolean getOverrideSubcomponents() { + return true; + } + /** * Null method (ComponentAssembly has no mass of itself). */ @@ -81,12 +119,69 @@ public abstract class ComponentAssembly extends RocketComponent { public boolean isMassive() { return false; } - - @Override - public boolean getOverrideSubcomponents() { - return true; + + + public void setAngularOffset(final double angle_rad) { + if (this.isCenterline()) { + return; + } + + this.angularPosition_rad = angle_rad; + fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); } - + + @Override + public void setAxialOffset(final double _pos) { + this.updateBounds(); + // System.err.println("updating axial position for boosters: " + this.getName() + " ( " + this.getComponentName() + ")"); + // System.err.println(" requesting offset: " + _pos + " via: " + this.relativePosition.name()); + super.setAxialOffset(this.relativePosition, _pos); + // System.err.println(" resultant offset: " + this.position.x + " via: " + this.relativePosition.name()); + fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); + } + + public void setInstanceCount(final int _count) { + mutex.verify(); + if (this.isCenterline()) { + return; + } + + if (_count < 2) { + // there must be at least one instance.... + return; + } + + this.count = _count; + this.angularSeparation = Math.PI * 2 / this.count; + fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); + } + + public void setRadialOffset(final double radius) { + if (false == this.isCenterline()) { + this.radialPosition_m = radius; + fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); + } + } + + public void setRelativePositionMethod(final Position _newPosition) { + if (null == this.parent) { + throw new NullPointerException(" a Stage requires a parent before any positioning! "); + } + if (this.isCenterline()) { + // Centerline stages must be set via AFTER-- regardless of what was requested: + super.setRelativePosition(Position.AFTER); + } else if (this.parent instanceof PodSet) { + if (Position.AFTER == _newPosition) { + log.warn("Stages cannot be relative to other stages via AFTER! Ignoring."); + super.setRelativePosition(Position.TOP); + } else { + super.setRelativePosition(_newPosition); + } + } + fireComponentChangeEvent(ComponentChangeEvent.AERODYNAMIC_CHANGE); + } + + @Override public void setOverrideSubcomponents(boolean override) { // No-op @@ -97,4 +192,83 @@ public abstract class ComponentAssembly extends RocketComponent { return false; } + + @Override + public void toDebugTreeNode(final StringBuilder buffer, final String prefix) { + + String thisLabel = this.getName() + " (" + this.getStageNumber() + ")"; + + buffer.append(String.format("%s %-24s %5.3f", prefix, thisLabel, this.getLength())); + + if (this.isCenterline()) { + buffer.append(String.format(" %24s %24s\n", this.getOffset(), this.getLocation()[0])); + } else { + buffer.append(String.format(" (offset: %4.1f via: %s )\n", this.getAxialOffset(), this.relativePosition.name())); + Coordinate[] relCoords = this.shiftCoordinates(new Coordinate[] { Coordinate.ZERO }); + Coordinate[] absCoords = this.getLocation(); + + for (int instanceNumber = 0; instanceNumber < this.count; instanceNumber++) { + Coordinate instanceRelativePosition = relCoords[instanceNumber]; + Coordinate instanceAbsolutePosition = absCoords[instanceNumber]; + buffer.append(String.format("%s [instance %2d of %2d] %32s %32s\n", prefix, instanceNumber, count, + instanceRelativePosition, instanceAbsolutePosition)); + } + } + + } + + @Override + protected void update() { + if (null == this.parent) { + return; + } + + this.updateBounds(); + if (this.isCenterline()) { + // stages which are directly children of the rocket are inline, and positioned + int childNumber = this.parent.getChildPosition(this); + if (0 == childNumber) { + this.setAfter(this.parent); + } else { + RocketComponent prevStage = this.parent.getChild(childNumber - 1); + this.setAfter(prevStage); + } + } else { + // this path is for 'external' assemblies: pods and boosters + super.update(); + } + + this.updateChildSequence(); + + return; + } + + + @Override + public void updateBounds() { + // currently only updates the length + this.length = 0; + Iterator childIterator = this.getChildren().iterator(); + while (childIterator.hasNext()) { + RocketComponent curChild = childIterator.next(); + if (curChild.isCenterline()) { + this.length += curChild.getLength(); + } + } + + } + + protected void updateChildSequence() { + Iterator childIterator = this.getChildren().iterator(); + RocketComponent prevComp = null; + while (childIterator.hasNext()) { + RocketComponent curChild = childIterator.next(); + if (curChild.isCenterline()) { + curChild.setAfter(prevComp); + prevComp = curChild; + } + } + } + + } diff --git a/core/src/net/sf/openrocket/rocketcomponent/PodSet.java b/core/src/net/sf/openrocket/rocketcomponent/PodSet.java index 101915754..a9bb3a293 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/PodSet.java +++ b/core/src/net/sf/openrocket/rocketcomponent/PodSet.java @@ -2,7 +2,6 @@ package net.sf.openrocket.rocketcomponent; import java.util.ArrayList; import java.util.Collection; -import java.util.Iterator; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.startup.Application; @@ -17,15 +16,8 @@ public class PodSet extends ComponentAssembly implements OutsideComponent { private static final Translator trans = Application.getTranslator(); private static final Logger log = LoggerFactory.getLogger(PodSet.class); - private boolean centerline = true; - private double angularPosition_rad = 0; - private double radialPosition_m = 0; - - private int count = 2; - private double angularSeparation = Math.PI; - - public PodSet() { + this.count = 2; this.relativePosition = Position.BOTTOM; } @@ -45,7 +37,6 @@ public class PodSet extends ComponentAssembly implements OutsideComponent { @Override public Collection getComponentBounds() { Collection bounds = new ArrayList(8); - double x_min = Double.MAX_VALUE; double x_max = Double.MIN_VALUE; double r_max = 0; @@ -120,82 +111,6 @@ public class PodSet extends ComponentAssembly implements OutsideComponent { return false; } - @Override - public int getInstanceCount() { - return this.count; - } - - @Override - public void setInstanceCount(final int _count) { - mutex.verify(); - if (this.centerline) { - return; - } - if (_count < 2) { - // there must be at least one instance.... - return; - } - - this.count = _count; - this.angularSeparation = Math.PI * 2 / this.count; - fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); - } - - @Override - public double getAngularOffset() { - if (this.centerline) { - return 0.; - } else { - return this.angularPosition_rad; - } - } - - @Override - public void setAngularOffset(final double angle_rad) { - if (this.centerline) { - return; - } - - this.angularPosition_rad = angle_rad; - fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); - } - - @Override - public double getRadialOffset() { - if (this.centerline) { - return 0.; - } else { - return this.radialPosition_m; - } - } - - @Override - public void setRadialOffset(final double radius) { - // log.error(" set radial position for: " + this.getName() + " to: " + this.radialPosition_m + " ... in meters?"); - if (false == this.centerline) { - this.radialPosition_m = radius; - fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); - } - } - - public void setRelativePositionMethod(final Position _newPosition) { - if (null == this.parent) { - throw new NullPointerException(" a Stage requires a parent before any positioning! "); - } - if (this.isCenterline()) { - // Centerline stages must be set via AFTER-- regardless of what was requested: - super.setRelativePosition(Position.AFTER); - } else if (this.parent instanceof PodSet) { - if (Position.AFTER == _newPosition) { - log.warn("Stages cannot be relative to other stages via AFTER! Ignoring."); - super.setRelativePosition(Position.TOP); - } else { - super.setRelativePosition(_newPosition); - } - } - fireComponentChangeEvent(ComponentChangeEvent.AERODYNAMIC_CHANGE); - } - @Override public double getPositionValue() { mutex.verify(); @@ -203,13 +118,6 @@ public class PodSet extends ComponentAssembly implements OutsideComponent { return this.getAxialOffset(); } - /* - * @deprecated remove when the file is fixed.... - */ - public void setRelativeToStage(final int _relToStage) { - // no-op - } - /** * Stages may be positioned relative to other stages. In that case, this will set the stage number * against which this stage is positioned. @@ -244,13 +152,6 @@ public class PodSet extends ComponentAssembly implements OutsideComponent { return returnValue; } - @Override - public void setAxialOffset(final double _pos) { - this.updateBounds(); - super.setAxialOffset(this.relativePosition, _pos); - fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); - } - @Override public Coordinate[] shiftCoordinates(Coordinate[] c) { checkState(); @@ -290,68 +191,4 @@ public class PodSet extends ComponentAssembly implements OutsideComponent { return buf; } - @Override - public void toDebugTreeNode(final StringBuilder buffer, final String prefix) { - - String thisLabel = this.getName() + " (" + this.getStageNumber() + ")"; - - buffer.append(String.format("%s %-24s %5.3f", prefix, thisLabel, this.getLength())); - - buffer.append(String.format(" %4.1f via: %s \n", this.getAxialOffset(), this.relativePosition.name())); - Coordinate[] relCoords = this.shiftCoordinates(new Coordinate[] { Coordinate.ZERO }); - Coordinate[] absCoords = this.getLocation(); - - for (int instanceNumber = 0; instanceNumber < this.count; instanceNumber++) { - Coordinate instanceRelativePosition = relCoords[instanceNumber]; - Coordinate instanceAbsolutePosition = absCoords[instanceNumber]; - buffer.append(String.format("%s [instance %2d of %2d] %32s %32s\n", prefix, instanceNumber, count, - instanceRelativePosition, instanceAbsolutePosition)); - } - - } - - @Override - public void updateBounds() { - // currently only updates the length - this.length = 0; - Iterator childIterator = this.getChildren().iterator(); - while (childIterator.hasNext()) { - RocketComponent curChild = childIterator.next(); - this.length += curChild.getLength(); - } - - } - - @Override - protected void update() { - if (null == this.parent) { - return; - } - - this.updateBounds(); - this.updateBounds(); - // because if parent is instanceof Stage, that means 'this' is positioned externally - super.update(); - - // updates the internal 'previousComponent' field. - this.updateChildSequence(); - - return; - } - - protected void updateChildSequence() { - Iterator childIterator = this.getChildren().iterator(); - RocketComponent prevComp = null; - while (childIterator.hasNext()) { - RocketComponent curChild = childIterator.next(); - //curChild.previousComponent = prevComp; - curChild.setAfter(prevComp); - prevComp = curChild; - // } else { - // curChild.previousComponent = null; - - } - - } - } diff --git a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java index 6b634cfd0..f10de19e8 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java @@ -884,7 +884,12 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab * * @param position the relative positioning. */ - protected void setRelativePosition(RocketComponent.Position position) { + protected void setRelativePosition(final RocketComponent.Position position) { + if (position == this.relativePosition) { + // no change. + return; + } + // this variable does not change the internal representation // the relativePosition (method) is just the lens through which external code may view this component's position. this.relativePosition = position; @@ -901,7 +906,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab */ public double asPositionValue(Position thePosition) { if (null == this.parent) { - return 0.0; + return Double.NaN; } double thisX = this.position.x; @@ -914,9 +919,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab break; case ABSOLUTE: Coordinate[] insts = this.getLocation(); - if (1 < insts.length) { - return Double.NaN; - } result = insts[0].x; break; case TOP: @@ -932,6 +934,12 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab throw new BugException("Unknown position type: " + thePosition); } + // if ((this instanceof BoosterSet) && (Position.ABSOLUTE == thePosition)) { + // System.err.println("Fetching position Value for: " + this.getName() + " ( " + this.getClass().getSimpleName() + ")"); + // System.err.println(" polling offset set to: " + this.position.x + " via: " + this.relativePosition.name()); + // System.err.println(" resultant offset: " + result + " via: " + thePosition.name()); + // } + // return result; } @@ -1033,7 +1041,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab this.relativePosition = positionMethod; this.offset = newOffset; - + final double EPSILON = 0.000001; double newAxialPosition = Double.NaN; double refLength = this.parent.getLength(); @@ -1058,6 +1066,10 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab throw new BugException("Unknown position type: " + positionMethod); } + // snap to zero if less than the threshold 'EPSILON' + if (EPSILON > Math.abs(newAxialPosition)) { + newAxialPosition = 0.0; + } if (Double.NaN == newAxialPosition) { throw new BugException("setAxialOffset is broken -- attempted to update as NaN: " + this.toDebugDetail()); } @@ -1167,7 +1179,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab //final Coordinate sourceLoc = this.getLocation()[0]; final Coordinate[] destLocs = dest.getLocation(); Coordinate[] toReturn = new Coordinate[destLocs.length]; - for (int coordIndex = 0; coordIndex < dest.getInstanceCount(); coordIndex++) { + for (int coordIndex = 0; coordIndex < destLocs.length; coordIndex++) { toReturn[coordIndex] = this.getLocation()[0].add(c).sub(destLocs[coordIndex]); } @@ -2061,14 +2073,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab buf.append(" offset: " + this.offset + " via: " + this.relativePosition.name() + " => " + this.getAxialOffset() + "\n"); buf.append(" thisCenterX: " + this.position.x + "\n"); buf.append(" this length: " + this.length + "\n"); - // if (null == this.previousComponent) { - // buf.append(" ..prevComponent: " + null + "\n"); - // } else { - // RocketComponent refComp = this.previousComponent; - // buf.append(" >>prevCompName: " + refComp.getName() + "\n"); - // buf.append(" ..prevCenterX: " + refComp.position.x + "\n"); - // buf.append(" ..prevLength: " + refComp.getLength() + "\n"); - // } return buf; } @@ -2076,7 +2080,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab public String toDebugTree() { StringBuilder buffer = new StringBuilder(); buffer.append("\n ====== ====== ====== ====== ====== ====== ====== ====== ====== ====== ====== ======\n"); - buffer.append(" [Name] [Length] [Rel Pos] [Abs Pos] \n"); + buffer.append(" [Name] [Length] [Rel Pos] [Abs Pos] \n"); this.dumpTreeHelper(buffer, ""); return buffer.toString(); } diff --git a/core/test/net/sf/openrocket/rocketcomponent/BoosterSetTest.java b/core/test/net/sf/openrocket/rocketcomponent/BoosterSetTest.java index 07f404f4f..84d3c0b15 100644 --- a/core/test/net/sf/openrocket/rocketcomponent/BoosterSetTest.java +++ b/core/test/net/sf/openrocket/rocketcomponent/BoosterSetTest.java @@ -313,7 +313,7 @@ public class BoosterSetTest extends BaseTestCase { // setup RocketComponent rocket = createTestRocket(); AxialStage core = (AxialStage) rocket.getChild(1); - AxialStage booster = createBooster(); + BoosterSet booster = createBooster(); core.addChild(booster); double targetX = +17.0; @@ -375,7 +375,7 @@ public class BoosterSetTest extends BaseTestCase { public void testSetStagePosition_outsideTOP() { Rocket rocket = this.createTestRocket(); AxialStage core = (AxialStage) rocket.getChild(1); - AxialStage booster = createBooster(); + BoosterSet booster = createBooster(); core.addChild(booster); double targetOffset = +2.0; @@ -405,7 +405,7 @@ public class BoosterSetTest extends BaseTestCase { // setup RocketComponent rocket = createTestRocket(); AxialStage core = (AxialStage) rocket.getChild(1); - AxialStage booster = createBooster(); + BoosterSet booster = createBooster(); core.addChild(booster); // when 'external' the stage should be freely movable @@ -435,7 +435,7 @@ public class BoosterSetTest extends BaseTestCase { // setup RocketComponent rocket = createTestRocket(); AxialStage core = (AxialStage) rocket.getChild(1); - AxialStage booster = createBooster(); + BoosterSet booster = createBooster(); core.addChild(booster); // vv function under test @@ -464,7 +464,7 @@ public class BoosterSetTest extends BaseTestCase { // setup RocketComponent rocket = createTestRocket(); AxialStage core = (AxialStage) rocket.getChild(1); - AxialStage booster = createBooster(); + BoosterSet booster = createBooster(); core.addChild(booster); double targetOffset = +4.50; @@ -488,7 +488,7 @@ public class BoosterSetTest extends BaseTestCase { // setup RocketComponent rocket = createTestRocket(); AxialStage core = (AxialStage) rocket.getChild(1); - AxialStage booster = createBooster(); + BoosterSet booster = createBooster(); core.addChild(booster); double targetOffset = +4.50; @@ -512,7 +512,7 @@ public class BoosterSetTest extends BaseTestCase { // setup RocketComponent rocket = createTestRocket(); AxialStage core = (AxialStage) rocket.getChild(1); - AxialStage booster = createBooster(); + BoosterSet booster = createBooster(); core.addChild(booster); double targetOffset = +4.50; @@ -537,7 +537,7 @@ public class BoosterSetTest extends BaseTestCase { // setup RocketComponent rocket = createTestRocket(); AxialStage core = (AxialStage) rocket.getChild(1); - AxialStage booster = createBooster(); + BoosterSet booster = createBooster(); core.addChild(booster); @@ -562,7 +562,7 @@ public class BoosterSetTest extends BaseTestCase { // setup RocketComponent rocket = createTestRocket(); AxialStage core = (AxialStage) rocket.getChild(1); - AxialStage booster = createBooster(); + BoosterSet booster = createBooster(); core.addChild(booster); double targetOffset = +4.50; @@ -586,7 +586,7 @@ public class BoosterSetTest extends BaseTestCase { Rocket rocket = createTestRocket(); AxialStage core = (AxialStage) rocket.getChild(1); - AxialStage booster = new AxialStage(); + BoosterSet booster = new BoosterSet(); booster.setName("Booster Stage"); core.addChild(booster); final double targetOffset = +2.50; @@ -622,10 +622,10 @@ public class BoosterSetTest extends BaseTestCase { public void testStageInitializationMethodValueOrder() { Rocket rocket = createTestRocket(); AxialStage core = (AxialStage) rocket.getChild(1); - AxialStage boosterA = createBooster(); + BoosterSet boosterA = createBooster(); boosterA.setName("Booster A Stage"); core.addChild(boosterA); - AxialStage boosterB = createBooster(); + BoosterSet boosterB = createBooster(); boosterB.setName("Booster B Stage"); core.addChild(boosterB); @@ -653,11 +653,11 @@ public class BoosterSetTest extends BaseTestCase { Rocket rocket = createTestRocket(); AxialStage sustainer = (AxialStage) rocket.getChild(0); AxialStage core = (AxialStage) rocket.getChild(1); - AxialStage boosterA = createBooster(); + BoosterSet boosterA = createBooster(); boosterA.setName("Booster A Stage"); core.addChild(boosterA); boosterA.setAxialOffset(Position.BOTTOM, 0.0); - AxialStage boosterB = createBooster(); + BoosterSet boosterB = createBooster(); boosterB.setName("Booster B Stage"); core.addChild(boosterB); boosterB.setAxialOffset(Position.BOTTOM, 0); diff --git a/swing/src/net/sf/openrocket/gui/configdialog/AxialStageConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/AxialStageConfig.java index 0064620cc..6d289c398 100644 --- a/swing/src/net/sf/openrocket/gui/configdialog/AxialStageConfig.java +++ b/swing/src/net/sf/openrocket/gui/configdialog/AxialStageConfig.java @@ -1,6 +1,5 @@ package net.sf.openrocket.gui.configdialog; -import javax.swing.ComboBoxModel; import javax.swing.JComboBox; import javax.swing.JLabel; import javax.swing.JPanel; @@ -10,18 +9,15 @@ 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.StyledLabel; -import net.sf.openrocket.gui.components.UnitSelector; import net.sf.openrocket.gui.components.StyledLabel.Style; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.AxialStage; import net.sf.openrocket.rocketcomponent.StageSeparationConfiguration; import net.sf.openrocket.startup.Application; -import net.sf.openrocket.unit.UnitGroup; -public class AxialStageConfig extends RocketComponentConfig { +public class AxialStageConfig extends ComponentAssemblyConfig { private static final long serialVersionUID = -944969957186522471L; private static final Translator trans = Application.getTranslator(); @@ -35,78 +31,8 @@ public class AxialStageConfig extends RocketComponentConfig { trans.get("StageConfig.tab.Separation.ttip"), 1); } - System.err.println(" building Stage Config Dialogue for: "+component.getName()+" type: "+component.getComponentName()); - // only stages which are actually off-centerline will get the dialog here: - if( ! component.isCenterline()){ - tabbedPane.insertTab( trans.get("RocketCompCfg.tab.Parallel"), null, parallelTab( (AxialStage) component ), trans.get("RocketCompCfg.tab.ParallelComment"), 2); - } } - private JPanel parallelTab( final AxialStage stage ){ - 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( stage, "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( stage, "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( stage, "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(component, "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(stage.getRocket().toDebugTree()); - - return motherPanel; - } private JPanel separationTab(AxialStage stage) { JPanel panel = new JPanel(new MigLayout("fill")); @@ -115,7 +41,7 @@ public class AxialStageConfig extends RocketComponentConfig { panel.add(new StyledLabel(trans.get("StageConfig.separation.lbl.title") + " " + CommonStrings.dagger, Style.BOLD), "spanx, wrap rel"); StageSeparationConfiguration config = stage.getStageSeparationConfiguration().getDefault(); - JComboBox combo = new JComboBox(new EnumModel(config, "SeparationEvent")); + JComboBox combo = new JComboBox(new EnumModel(config, "SeparationEvent")); panel.add(combo, ""); // ... and delay diff --git a/swing/src/net/sf/openrocket/gui/configdialog/ComponentAssemblyConfig.java b/swing/src/net/sf/openrocket/gui/configdialog/ComponentAssemblyConfig.java new file mode 100644 index 000000000..269187b59 --- /dev/null +++ b/swing/src/net/sf/openrocket/gui/configdialog/ComponentAssemblyConfig.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.ComponentAssembly; +import net.sf.openrocket.rocketcomponent.RocketComponent; +import net.sf.openrocket.startup.Application; +import net.sf.openrocket.unit.UnitGroup; + +public class ComponentAssemblyConfig extends RocketComponentConfig { + private static final long serialVersionUID = -944969957186522471L; + private static final Translator trans = Application.getTranslator(); + + public ComponentAssemblyConfig(OpenRocketDocument document, RocketComponent component) { + super(document, component); + + // only stages which are actually off-centerline will get the dialog here: + if(( component instanceof ComponentAssembly )&&( ! component.isCenterline() )){ + tabbedPane.insertTab( trans.get("RocketCompCfg.tab.Parallel"), null, parallelTab( (ComponentAssembly) component ), trans.get("RocketCompCfg.tab.ParallelComment"), 2); + } + } + + 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(stage.getRocket().toDebugTree()); + + return motherPanel; + } + +} diff --git a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java index 358419aed..3f7da1fa6 100644 --- a/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java +++ b/swing/src/net/sf/openrocket/gui/scalefigure/RocketFigure.java @@ -23,16 +23,11 @@ import net.sf.openrocket.gui.figureelements.FigureElement; import net.sf.openrocket.gui.util.ColorConversion; import net.sf.openrocket.gui.util.SwingPreferences; import net.sf.openrocket.motor.Motor; -import net.sf.openrocket.rocketcomponent.BodyTube; -import net.sf.openrocket.rocketcomponent.ClusterConfiguration; +import net.sf.openrocket.rocketcomponent.ComponentAssembly; import net.sf.openrocket.rocketcomponent.Configuration; -import net.sf.openrocket.rocketcomponent.FlightConfiguration; -import net.sf.openrocket.rocketcomponent.InnerTube; -import net.sf.openrocket.rocketcomponent.MotorConfiguration; import net.sf.openrocket.rocketcomponent.MotorMount; import net.sf.openrocket.rocketcomponent.Rocket; import net.sf.openrocket.rocketcomponent.RocketComponent; -import net.sf.openrocket.rocketcomponent.AxialStage; import net.sf.openrocket.gui.rocketfigure.RocketComponentShape; import net.sf.openrocket.gui.scalefigure.RocketPanel; import net.sf.openrocket.startup.Application; @@ -453,7 +448,7 @@ public class RocketFigure extends AbstractScaleFigure { // generate shapes: if( comp instanceof Rocket){ // no-op. no shapes - }else if( comp instanceof AxialStage ){ + }else if( comp instanceof ComponentAssembly ){ // no-op; no shapes here, either. }else{ // get all shapes for this component, add to return list.