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 a711aacc4..5012694a7 100644 --- a/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java +++ b/core/src/net/sf/openrocket/file/openrocket/importt/DocumentConfig.java @@ -21,7 +21,7 @@ import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish; import net.sf.openrocket.rocketcomponent.FinSet; import net.sf.openrocket.rocketcomponent.FreeformFinSet; import net.sf.openrocket.rocketcomponent.InnerTube; -import net.sf.openrocket.rocketcomponent.LaunchButton; +import net.sf.openrocket.rocketcomponent.RailButton; import net.sf.openrocket.rocketcomponent.LaunchLug; import net.sf.openrocket.rocketcomponent.MassComponent; import net.sf.openrocket.rocketcomponent.MassObject; @@ -164,9 +164,9 @@ class DocumentConfig { // LaunchButton setters.put("LaunchButton:instancecount", new IntSetter( - Reflection.findMethod(LaunchButton.class, "setInstanceCount",int.class))); + Reflection.findMethod(RailButton.class, "setInstanceCount",int.class))); setters.put("LaunchButton:instanceseparation", new DoubleSetter( - Reflection.findMethod( LaunchButton.class, "setInstanceSeparation", double.class))); + Reflection.findMethod( RailButton.class, "setInstanceSeparation", double.class))); // LaunchLug setters.put("LaunchLug:instancecount", new IntSetter( diff --git a/core/src/net/sf/openrocket/rocketcomponent/BoosterSet.java b/core/src/net/sf/openrocket/rocketcomponent/BoosterSet.java index 35688662a..5154384b3 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/BoosterSet.java +++ b/core/src/net/sf/openrocket/rocketcomponent/BoosterSet.java @@ -14,7 +14,7 @@ import net.sf.openrocket.util.Coordinate; public class BoosterSet extends AxialStage implements FlightConfigurableComponent, RingInstanceable { private static final Translator trans = Application.getTranslator(); - private static final Logger log = LoggerFactory.getLogger(BoosterSet.class); + //private static final Logger log = LoggerFactory.getLogger(BoosterSet.class); protected int count = 1; @@ -127,7 +127,24 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen @Override public Coordinate[] getInstanceOffsets(){ - return this.shiftCoordinates(new Coordinate[]{Coordinate.ZERO}); + checkState(); + + final double radius = this.radialPosition_m; + final double startAngle = this.angularPosition_rad; + final double angleIncr = this.angularSeparation; + Coordinate center = Coordinate.ZERO; + + double curAngle = startAngle; + Coordinate[] toReturn = new Coordinate[this.count]; + for (int instanceNumber = 0; instanceNumber < this.count; instanceNumber++) { + final double curY = radius * Math.cos(curAngle); + final double curZ = radius * Math.sin(curAngle); + toReturn[instanceNumber] = center.add(0, curY, curZ ); + + curAngle += angleIncr; + } + + return toReturn; } @Override @@ -142,8 +159,12 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen "(assumed reason for getting multiple parent locations into an external stage.)"); } - parentInstances[0] = parentInstances[0].add( this.position); - Coordinate[] toReturn = this.shiftCoordinates(parentInstances); + final Coordinate center = parentInstances[0].add( this.position); + Coordinate[] instanceLocations = this.getInstanceOffsets(); + Coordinate[] toReturn = new Coordinate[ instanceLocations.length]; + for( int i = 0; i < toReturn.length; i++){ + toReturn[i] = center.add( instanceLocations[i]); + } return toReturn; } @@ -185,30 +206,30 @@ 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 +// 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 @@ -216,7 +237,7 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen buffer.append(String.format("%s %-24s (stage: %d)", prefix, this.getName(), this.getStageNumber())); buffer.append(String.format(" (len: %5.3f offset: %4.1f via: %s )\n", this.getLength(), this.getAxialOffset(), this.relativePosition.name())); - Coordinate[] relCoords = this.shiftCoordinates(new Coordinate[] { this.getOffset() }); + Coordinate[] relCoords = this.getInstanceOffsets(); Coordinate[] absCoords = this.getLocations(); for (int instanceNumber = 0; instanceNumber < this.count; instanceNumber++) { Coordinate instanceRelativePosition = relCoords[instanceNumber]; diff --git a/core/src/net/sf/openrocket/rocketcomponent/CenteringRing.java b/core/src/net/sf/openrocket/rocketcomponent/CenteringRing.java index 73a999d0a..d7cf3eb81 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/CenteringRing.java +++ b/core/src/net/sf/openrocket/rocketcomponent/CenteringRing.java @@ -102,16 +102,14 @@ public class CenteringRing extends RadiusRingComponent implements LineInstanceab @Override public Coordinate[] getInstanceOffsets(){ Coordinate[] toReturn = new Coordinate[this.getInstanceCount()]; - toReturn[0] = Coordinate.ZERO; - - for ( int index=1 ; index < this.getInstanceCount(); index++){ - toReturn[index] = new Coordinate(index*this.instanceSeparation,0,0,0); - + for ( int index=0 ; index < this.getInstanceCount(); index++){ + toReturn[index] = this.position.setX( this.position.x + index*this.instanceSeparation ); } return toReturn; } + @Override public int getInstanceCount(){ return this.instanceCount; diff --git a/core/src/net/sf/openrocket/rocketcomponent/ExternalComponent.java b/core/src/net/sf/openrocket/rocketcomponent/ExternalComponent.java index a508c4b6d..441997ef6 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/ExternalComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/ExternalComponent.java @@ -7,6 +7,7 @@ import net.sf.openrocket.material.Material; import net.sf.openrocket.preset.ComponentPreset; import net.sf.openrocket.startup.Application; import net.sf.openrocket.unit.UnitGroup; +import net.sf.openrocket.util.Coordinate; /** * Class of components with well-defined physical appearance and which have an effect on @@ -155,7 +156,6 @@ public abstract class ExternalComponent extends RocketComponent { } } - @Override protected List copyFrom(RocketComponent c) { ExternalComponent src = (ExternalComponent) c; diff --git a/core/src/net/sf/openrocket/rocketcomponent/InnerTube.java b/core/src/net/sf/openrocket/rocketcomponent/InnerTube.java index 570e20c34..63dac0898 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/InnerTube.java +++ b/core/src/net/sf/openrocket/rocketcomponent/InnerTube.java @@ -217,47 +217,73 @@ public class InnerTube extends ThicknessRingComponent implements Clusterable, Ra @Override public Coordinate[] getInstanceOffsets(){ - return this.shiftCoordinates(new Coordinate[]{Coordinate.ZERO}); - } - - @Override - public Coordinate[] getLocations(){ - if (null == this.parent) { - throw new BugException(" Attempted to get absolute position Vector of a Stage without a parent. "); - } - Coordinate[] parentInstances = this.parent.getLocations(); - for( int i=0; i< parentInstances.length; i++){ - parentInstances[i] = parentInstances[i].add( this.position ); - } - Coordinate[] toReturn = this.shiftCoordinates(parentInstances); - - return toReturn; - } - - @Override - protected Coordinate[] shiftCoordinates(Coordinate[] array) { - array = super.shiftCoordinates(array); - - int count = getClusterCount(); - if (count == 1) - return array; + int instanceCount = getClusterCount(); + if (instanceCount == 1) + return super.getInstanceOffsets(); List points = getClusterPoints(); - if (points.size() != count) { - throw new BugException("Inconsistent cluster configuration, cluster count=" + count + - " point count=" + points.size()); + if (points.size() != instanceCount) { + throw new BugException("Inconsistent cluster configuration, cluster count(" + instanceCount + + ") != point count(" + points.size()+")"); } - Coordinate[] newArray = new Coordinate[array.length * count]; - for (int i = 0; i < array.length; i++) { - for (int j = 0; j < count; j++) { - newArray[i * count + j] = array[i].add(points.get(j)); - } + + + Coordinate[] newArray = new Coordinate[ instanceCount]; + for (int instanceNumber = 0; instanceNumber < instanceCount; instanceNumber++) { + newArray[ instanceNumber] = this.position.add( points.get(instanceNumber)); } return newArray; } +// @Override +// public Coordinate[] getLocations(){ +// if (null == this.parent) { +// throw new BugException(" Attempted to get absolute position Vector of a Stage without a parent. "); +// } +// +// final Coordinate center = parentInstances[0].add( this.position); +// Coordinate[] instanceLocations = this.getInstanceOffsets(); +// Coordinate[] toReturn = new Coordinate[ instanceLocations.length]; +// for( int i = 0; i < toReturn.length; i++){ +// toReturn[i] = center.add( instanceLocations[i]); +// } +// +// return toReturn; +// +// Coordinate[] parentInstances = this.parent.getLocations(); +// for( int i=0; i< parentInstances.length; i++){ +// parentInstances[i] = parentInstances[i].add( this.position ); +// } +// Coordinate[] toReturn = this.shiftCoordinates(parentInstances); +// +// return toReturn; +// } + +// @Override +// protected Coordinate[] shiftCoordinates(Coordinate[] array) { +// array = super.shiftCoordinates(array); +// +// int count = getClusterCount(); +// if (count == 1) +// return array; +// +// List points = getClusterPoints(); +// if (points.size() != count) { +// throw new BugException("Inconsistent cluster configuration, cluster count=" + count + +// " point count=" + points.size()); +// } +// Coordinate[] newArray = new Coordinate[array.length * count]; +// for (int i = 0; i < array.length; i++) { +// for (int j = 0; j < count; j++) { +// newArray[i * count + j] = array[i].add(points.get(j)); +// } +// } +// +// return newArray; +// } + //////////////// Motor mount ///////////////// @Override @@ -388,19 +414,19 @@ public class InnerTube extends ThicknessRingComponent implements Clusterable, Ra buffer.append(String.format("%s %-24s (cluster: %s)", prefix, this.getName(), this.getPatternName())); buffer.append(String.format(" (len: %5.3f offset: %4.1f via: %s )\n", this.getLength(), this.getAxialOffset(), this.relativePosition.name())); - Coordinate[] relCoords = this.shiftCoordinates(new Coordinate[] { this.getOffset() }); + Coordinate[] relCoords = this.getInstanceOffsets(); Coordinate[] absCoords = this.getLocations(); FlightConfigurationID curId = this.getRocket().getDefaultConfiguration().getFlightConfigurationID(); - int count = this.getInstanceCount(); + final int intanceCount = this.getInstanceCount(); MotorInstance curInstance = this.motors.get(curId); //if( curInstance.isEmpty() ){ { // print just the tube locations - for (int instanceNumber = 0; instanceNumber < count; instanceNumber++) { + for (int instanceNumber = 0; instanceNumber < intanceCount; instanceNumber++) { Coordinate tubeRelativePosition = relCoords[instanceNumber]; Coordinate tubeAbsolutePosition = absCoords[instanceNumber]; - buffer.append(String.format("%s [%2d/%2d]; %28s; %28s;\n", prefix, instanceNumber, count, + buffer.append(String.format("%s [%2d/%2d]; %28s; %28s;\n", prefix, instanceNumber+1, intanceCount, tubeRelativePosition, tubeAbsolutePosition)); } } @@ -410,15 +436,15 @@ public class InnerTube extends ThicknessRingComponent implements Clusterable, Ra }else{ // curInstance has a motor ... Motor curMotor = curInstance.getMotor(); - double motorOffset = this.getLength() - curMotor.getLength(); + final double motorOffset = this.getLength() - curMotor.getLength(); buffer.append(String.format("%s %-24s Thrust: %f N; (Length: %f); \n", prefix, curMotor.getDesignation(), curMotor.getMaxThrustEstimate(), curMotor.getLength() )); - for (int instanceNumber = 0; instanceNumber < count; instanceNumber++) { + for (int instanceNumber = 0; instanceNumber < intanceCount; instanceNumber++) { Coordinate motorRelativePosition = new Coordinate(motorOffset, 0, 0); Coordinate tubeAbs = absCoords[instanceNumber]; Coordinate motorAbsolutePosition = new Coordinate(tubeAbs.x+motorOffset,tubeAbs.y,tubeAbs.z); - buffer.append(String.format("%s [%2d/%2d]; %28s; %28s;\n", prefix, instanceNumber, count, + buffer.append(String.format("%s [%2d/%2d]; %28s; %28s;\n", prefix, instanceNumber+1, intanceCount, motorRelativePosition, motorAbsolutePosition)); } diff --git a/core/src/net/sf/openrocket/rocketcomponent/LaunchLug.java b/core/src/net/sf/openrocket/rocketcomponent/LaunchLug.java index ca8167d96..9ac710d3d 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/LaunchLug.java +++ b/core/src/net/sf/openrocket/rocketcomponent/LaunchLug.java @@ -20,15 +20,12 @@ public class LaunchLug extends ExternalComponent implements Coaxial, LineInstanc private double thickness; private double radialDirection = 0; + protected double radialDistance = 0; private int instanceCount = 1; private double instanceSeparation = 0; // front-front along the positive rocket axis. i.e. [1,0,0]; - /* These are calculated when the component is first attached to any Rocket */ - private double shiftY, shiftZ; - - public LaunchLug() { super(Position.MIDDLE); radius = 0.01 / 2; @@ -113,6 +110,7 @@ public class LaunchLug extends ExternalComponent implements Coaxial, LineInstanc @Override public void setPositionValue(double value) { + System.err.println(" positioning "+getName()+" to: "+value); super.setPositionValue(value); fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); } @@ -145,25 +143,29 @@ public class LaunchLug extends ExternalComponent implements Coaxial, LineInstanc @Override public Coordinate[] getInstanceOffsets(){ Coordinate[] toReturn = new Coordinate[this.getInstanceCount()]; - toReturn[0] = Coordinate.ZERO; - for ( int index=1 ; index < this.getInstanceCount(); index++){ - toReturn[index] = new Coordinate(index*this.instanceSeparation,0,0,0); + final double xOffset = this.position.x; + final double yOffset = Math.cos(radialDirection) * (radialDistance); + final double zOffset = Math.sin(radialDirection) * (radialDistance); + + for ( int index=0; index < this.getInstanceCount(); index++){ + toReturn[index] = new Coordinate(xOffset + index*this.instanceSeparation, yOffset, zOffset); } return toReturn; } - @Override - protected Coordinate[] shiftCoordinates(Coordinate[] array) { - array = super.shiftCoordinates(array); - - for (int i = 0; i < array.length; i++) { - array[i] = array[i].add(0, shiftY, shiftZ); - } - - return array; - } +// @Override +// protected Coordinate[] shiftCoordinates(Coordinate[] array) { +// array = super.shiftCoordinates(array); +// +// for (int i = 0; i < array.length; i++) { +// array[i] = new Coordinate(xOffset + index*this.instanceSeparation, yOffset, zOffset); +// array[i] = array[i].add(0, shiftY, shiftZ); +// } +// +// return array; +// } @Override @@ -194,10 +196,7 @@ public class LaunchLug extends ExternalComponent implements Coaxial, LineInstanc parentRadius = Math.max(s.getRadius(x1), s.getRadius(x2)); } - shiftY = Math.cos(radialDirection) * (parentRadius + radius); - shiftZ = Math.sin(radialDirection) * (parentRadius + radius); - - // System.out.println("Computed shift: y="+shiftY+" z="+shiftZ); + this.radialDistance = parentRadius + radius; } diff --git a/core/src/net/sf/openrocket/rocketcomponent/MassObject.java b/core/src/net/sf/openrocket/rocketcomponent/MassObject.java index 3ffbe299d..c7c2815f4 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/MassObject.java +++ b/core/src/net/sf/openrocket/rocketcomponent/MassObject.java @@ -109,14 +109,14 @@ public abstract class MassObject extends InternalComponent { /** * Shift the coordinates according to the radial position and direction. */ - @Override - protected - final Coordinate[] shiftCoordinates(Coordinate[] array) { - for (int i = 0; i < array.length; i++) { - array[i] = array[i].add(0, shiftY, shiftZ); - } - return array; - } +// @Override +// protected +// final Coordinate[] shiftCoordinates(Coordinate[] array) { +// for (int i = 0; i < array.length; i++) { +// array[i] = array[i].add(0, shiftY, shiftZ); +// } +// return array; +// } @Override public final Coordinate getComponentCG() { diff --git a/core/src/net/sf/openrocket/rocketcomponent/PodSet.java b/core/src/net/sf/openrocket/rocketcomponent/PodSet.java index f81e3f36f..d7556826d 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/PodSet.java +++ b/core/src/net/sf/openrocket/rocketcomponent/PodSet.java @@ -78,8 +78,26 @@ public class PodSet extends ComponentAssembly implements RingInstanceable { @Override public Coordinate[] getInstanceOffsets(){ - return shiftCoordinates(new Coordinate[]{Coordinate.ZERO}); + checkState(); + + final double radius = this.radialPosition_m; + final double startAngle = this.angularPosition_rad; + final double angleIncr = this.angularSeparation; + Coordinate center = Coordinate.ZERO; + + double curAngle = startAngle; + Coordinate[] toReturn = new Coordinate[this.count]; + for (int instanceNumber = 0; instanceNumber < this.count; instanceNumber++) { + final double curY = radius * Math.cos(curAngle); + final double curZ = radius * Math.sin(curAngle); + toReturn[instanceNumber] = center.add(0, curY, curZ ); + + curAngle += angleIncr; + } + + return toReturn; } + @Override public Coordinate[] getLocations() { @@ -96,7 +114,12 @@ public class PodSet extends ComponentAssembly implements RingInstanceable { "(assumed reason for getting multiple parent locations into an external stage.)"); } - Coordinate[] toReturn = this.shiftCoordinates(parentInstances); + final Coordinate center = parentInstances[0].add( this.position); + Coordinate[] instanceLocations = this.getInstanceOffsets(); + Coordinate[] toReturn = new Coordinate[ instanceLocations.length]; + for( int i = 0; i < toReturn.length; i++){ + toReturn[i] = center.add( instanceLocations[i]); + } return toReturn; } @@ -186,31 +209,6 @@ public class PodSet extends ComponentAssembly implements RingInstanceable { 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; this is not true, and may produce unexpected behavior! "); - } - - double radius = this.radialPosition_m; - double angle0 = this.angularPosition_rad; - double angleIncr = this.angularSeparation; - Coordinate center = this.position; - Coordinate[] toReturn = new Coordinate[this.count]; - Coordinate thisOffset; - double thisAngle = angle0; - for (int instanceNumber = 0; instanceNumber < this.count; instanceNumber++) { - thisOffset = center.add(0, radius * Math.cos(thisAngle), radius * Math.sin(thisAngle)); - - toReturn[instanceNumber] = thisOffset.add(c[0]); - thisAngle += angleIncr; - } - - return toReturn; - } - @Override protected StringBuilder toDebugDetail() { StringBuilder buf = super.toDebugDetail(); diff --git a/core/src/net/sf/openrocket/rocketcomponent/RadiusRingComponent.java b/core/src/net/sf/openrocket/rocketcomponent/RadiusRingComponent.java index 6d0ccb657..8f67e3e09 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RadiusRingComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RadiusRingComponent.java @@ -5,10 +5,7 @@ import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.MathUtil; /** - * An inner component that consists of a hollow cylindrical component. This can be - * an inner tube, tube coupler, centering ring, bulkhead etc. - * - * The properties include the inner and outer radii, length and radial position. + * ??? * * @author Sampo Niskanen */ diff --git a/core/src/net/sf/openrocket/rocketcomponent/LaunchButton.java b/core/src/net/sf/openrocket/rocketcomponent/RailButton.java similarity index 94% rename from core/src/net/sf/openrocket/rocketcomponent/LaunchButton.java rename to core/src/net/sf/openrocket/rocketcomponent/RailButton.java index f11775232..a09958ee8 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/LaunchButton.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RailButton.java @@ -15,7 +15,7 @@ import net.sf.openrocket.util.MathUtil; * @author widget (Daniel Williams) * */ -public abstract class LaunchButton extends ExternalComponent implements LineInstanceable { +public abstract class RailButton extends ExternalComponent implements LineInstanceable { private static final Translator trans = Application.getTranslator(); @@ -32,7 +32,7 @@ public abstract class LaunchButton extends ExternalComponent implements LineInst - public LaunchButton() { + public RailButton() { super(Position.MIDDLE); radius = 0.01 / 2; thickness = 0.001; @@ -154,16 +154,16 @@ public abstract class LaunchButton extends ExternalComponent implements LineInst } - @Override - protected Coordinate[] shiftCoordinates(Coordinate[] array) { - array = super.shiftCoordinates(array); - - for (int i = 0; i < array.length; i++) { - array[i] = array[i].add(0, shiftY, shiftZ); - } - - return array; - } +// @Override +// protected Coordinate[] shiftCoordinates(Coordinate[] array) { +// array = super.shiftCoordinates(array); +// +// for (int i = 0; i < array.length; i++) { +// array[i] = array[i].add(0, shiftY, shiftZ); +// } +// +// return array; +// } @Override diff --git a/core/src/net/sf/openrocket/rocketcomponent/RingComponent.java b/core/src/net/sf/openrocket/rocketcomponent/RingComponent.java index c7e2e6b87..f91811aa8 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RingComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RingComponent.java @@ -171,20 +171,7 @@ public abstract class RingComponent extends StructuralComponent implements Coaxi return ((Clusterable) this).getClusterConfiguration().getClusterCount(); return 1; } - - - /** - * Shift the coordinates according to the radial position and direction. - */ - @Override - protected Coordinate[] shiftCoordinates(Coordinate[] array) { - for (int i = 0; i < array.length; i++) { - array[i] = array[i].add(0, shiftY, shiftZ); - } - return array; - } - - + @Override public Collection getComponentBounds() { List bounds = new ArrayList(); diff --git a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java index e94dc7a7c..0bda63489 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java @@ -276,7 +276,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab * @return indicates if a component is positioned via AFTER */ public boolean isAfter(){ - return (Position.AFTER == this.getRelativePositionMethod()); + return (Position.AFTER == this.relativePosition); } @@ -292,10 +292,10 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab * @return an array of shifted coordinates. The method may modify the contents * of the passed array and return the array itself. */ - protected Coordinate[] shiftCoordinates(Coordinate[] c) { - checkState(); - return c; - } +// protected Coordinate[] shiftCoordinates(Coordinate[] c) { +// checkState(); +// return c; +// } /** @@ -943,12 +943,6 @@ 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; } @@ -997,10 +991,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab setAxialOffset(value); } - public void setAxialOffset(double _value) { - this.setAxialOffset(this.relativePosition, _value); - this.fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); - } protected void setAfter(RocketComponent referenceComponent) { checkState(); @@ -1028,23 +1018,29 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab this.position = new Coordinate(newAxialPosition, this.position.y, this.position.z); } - protected void setAxialOffset(Position positionMethod, double newOffset) { - // if this is the root of a hierarchy, constrain the position to zero. - if (null == this.parent) { - return; - } else if ( this.isAfter()){ - positionMethod = Position.AFTER; - } + public void setAxialOffset(double _value) { + this.setAxialOffset(this.relativePosition, _value); + this.fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE); + } + + protected void setAxialOffset(final Position positionMethod, final double newOffset) { checkState(); - - this.relativePosition = positionMethod; - this.offset = newOffset; - + if ( this.isAfter()){ + relativePosition = Position.AFTER; + }else{ + this.relativePosition = positionMethod; + } + if (null == this.parent) { + // if this is the root of a hierarchy, constrain the position to zero. + this.offset = newOffset; + this.position= Coordinate.ZERO; + return; + } + final double EPSILON = 0.000001; double newAxialPosition = Double.NaN; - double refLength = this.parent.getLength(); - - switch (positionMethod) { + final double refLength = this.parent.getLength(); + switch (this.relativePosition) { case ABSOLUTE: newAxialPosition = newOffset - this.parent.position.x; break; @@ -1062,7 +1058,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab newAxialPosition = (refLength - this.length) + newOffset; break; default: - throw new BugException("Unknown position type: " + positionMethod); + throw new BugException("Unknown position type: " + this.relativePosition); } // snap to zero if less than the threshold 'EPSILON' @@ -1072,7 +1068,19 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab if (Double.NaN == newAxialPosition) { throw new BugException("setAxialOffset is broken -- attempted to update as NaN: " + this.toDebugDetail()); } + this.offset = newOffset; this.position = new Coordinate(newAxialPosition, this.position.y, this.position.z); + +// if( this instanceof CenteringRing ){ +// System.err.println("Moving "+this.getName()+"("+this.getID().substring(0, 8)+") to:"+newOffset+" via:"+positionMethod.name()); +// System.err.println(" new Position = "+this.position); +// if( positionMethod == Position.BOTTOM){ +// StackTraceElement[] stack = Thread.currentThread().getStackTrace(); +// for( int i = 0; i < 12 ; i++){ +// System.err.println( stack[i]); +// } +// } +// } } protected void update() { @@ -1081,12 +1089,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab public Coordinate getOffset() { return this.position; - } - -// public Coordinate[] getOffset() { -// return new Coordinate[]{this.position}; -// } - + } /** * @deprecated kept around as example code. instead use getLocations @@ -1101,17 +1104,50 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab } } + /** + * Returns coordinates of this component's instances in relation to this.parent. + *

+ * For example, the absolute position of any given instance is the parent's position + * plus the instance position returned by this method + *

+ * NOTE: this default implementation simply returns this.position + * NOTE: the length of this array returned always equals this.getInstanceCount() + * + * @param c an array of coordinates to shift. + * @return an array of shifted coordinates. The method may modify the contents + * of the passed array and return the array itself. + */ + // @Override Me ! + public Coordinate[] getInstanceOffsets(){ + return new Coordinate[]{this.position}; + } + public Coordinate[] getLocations() { if (null == this.parent) { // == improperly initialized components OR the root Rocket instance return new Coordinate[] { Coordinate.ZERO }; } else { Coordinate[] parentPositions = this.parent.getLocations(); - int instCount = parentPositions.length; - Coordinate[] thesePositions = new Coordinate[instCount]; + int parentCount = parentPositions.length; - for (int pi = 0; pi < instCount; pi++) { - thesePositions[pi] = parentPositions[pi].add(this.getOffset()); + // override .getInstanceOffsets() in the subclass you want to fix. + Coordinate[] instanceOffsets = this.getInstanceOffsets(); + int instanceCount = instanceOffsets.length; + + // usual case optimization + if((1 == parentCount)&&(1 == instanceCount)){ + return new Coordinate[]{parentPositions[0].add(instanceOffsets[0])}; + } + + int thisCount = instanceCount*parentCount; + Coordinate[] thesePositions = new Coordinate[thisCount]; + for (int pi = 0; pi < parentCount; pi++) { + for( int ii = 0; ii < instanceCount; ii++ ){ +// System.err.println(" #"+pi+", "+ii+" = "+(pi + parentCount*ii)); +// System.err.println(" "+parentPositions[pi]+" + "+instanceOffsets[ii]); + thesePositions[pi + parentCount*ii] = parentPositions[pi].add(instanceOffsets[ii]); +// System.err.println(" ="+thesePositions[pi+parentCount*ii]); + } } return thesePositions; } @@ -1190,15 +1226,15 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab return toReturn; } - protected static final Coordinate[] rebase(final Coordinate toMove[], final Coordinate source, final Coordinate dest) { - final Coordinate delta = source.sub(dest); - Coordinate[] toReturn = new Coordinate[toMove.length]; - for (int coordIndex = 0; coordIndex < toMove.length; coordIndex++) { - toReturn[coordIndex] = toMove[coordIndex].add(delta); - } - - return toReturn; - } +// protected static final Coordinate[] rebase(final Coordinate toMove[], final Coordinate source, final Coordinate dest) { +// final Coordinate delta = source.sub(dest); +// Coordinate[] toReturn = new Coordinate[toMove.length]; +// for (int coordIndex = 0; coordIndex < toMove.length; coordIndex++) { +// toReturn[coordIndex] = toMove[coordIndex].add(delta); +// } +// +// return toReturn; +// } /** @@ -2085,8 +2121,8 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab } public void toDebugTreeNode(final StringBuilder buffer, final String prefix) { - buffer.append(String.format("%s %-24s; %5.3f; %24s; %24s;\n", prefix, this.getName(), this.getLength(), - this.getOffset(), this.getLocations()[0])); + buffer.append(String.format("%-42s; %5.3f; %24s; %24s;\n", prefix+" "+this.getName(), + this.getLength(), this.getOffset(), this.getLocations()[0])); } public void dumpTreeHelper(StringBuilder buffer, final String prefix) { diff --git a/core/src/net/sf/openrocket/util/TestRockets.java b/core/src/net/sf/openrocket/util/TestRockets.java index d8c74e442..8f63b03e6 100644 --- a/core/src/net/sf/openrocket/util/TestRockets.java +++ b/core/src/net/sf/openrocket/util/TestRockets.java @@ -27,6 +27,7 @@ import net.sf.openrocket.rocketcomponent.CenteringRing; import net.sf.openrocket.rocketcomponent.ClusterConfiguration; import net.sf.openrocket.rocketcomponent.DeploymentConfiguration; import net.sf.openrocket.rocketcomponent.DeploymentConfiguration.DeployEvent; +import net.sf.openrocket.rocketcomponent.EngineBlock; import net.sf.openrocket.rocketcomponent.ExternalComponent; import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish; import net.sf.openrocket.rocketcomponent.FinSet.CrossSection; @@ -316,8 +317,9 @@ public class TestRockets { public static final Rocket makeEstesAlphaIII(){ Rocket rocket = new Rocket(); + rocket.setName("Estes Alpha III / Code Verification Rocket"); AxialStage stage = new AxialStage(); - stage.setName("Stage1"); + stage.setName("Stage"); rocket.addChild(stage); double noseconeLength = 0.06985; @@ -325,14 +327,31 @@ public class TestRockets { NoseCone nosecone = new NoseCone(Transition.Shape.ELLIPSOID, noseconeLength, noseconeRadius); nosecone.setAftShoulderLength(0.02479); nosecone.setAftShoulderRadius(0.011811); + nosecone.setName("Nose Cone"); stage.addChild(nosecone); double bodytubeLength = 0.19685; double bodytubeRadius = 0.012395; double bodytubeThickness = 0.00033; BodyTube bodytube = new BodyTube(bodytubeLength, bodytubeRadius, bodytubeThickness); + bodytube.setName("Body Tube"); + stage.addChild(bodytube); + + TrapezoidFinSet finset; { + int finCount = 3; + double finRootChord = .05715; + double finTipChord = .03048; + double finSweep = 0.06985455; + double finHeight = 0.04064; + finset = new TrapezoidFinSet(finCount, finRootChord, finTipChord, finSweep, finHeight); + finset.setThickness( 0.003175); + finset.setRelativePosition(Position.BOTTOM); + finset.setName("3 Fin Set"); + bodytube.addChild(finset); + LaunchLug lug = new LaunchLug(); + lug.setName("Launch Lugs"); lug.setRelativePosition(Position.TOP); lug.setAxialOffset(0.111125); lug.setLength(0.0508); @@ -347,21 +366,40 @@ public class TestRockets { inner.setOuterRadius(0.009347); inner.setThickness(0.00033); inner.setMotorMount(true); + inner.setName("Motor Mount Tube"); bodytube.addChild(inner); - // omit other internal components... this method does not return a flyable version of the Mk 2 - } - stage.addChild(bodytube); + { + // MotorBlock + EngineBlock thrustBlock= new EngineBlock(); + thrustBlock.setRelativePosition(Position.TOP); + thrustBlock.setAxialOffset(0.0); + thrustBlock.setLength(0.005004); + thrustBlock.setOuterRadius(0.0090169); + thrustBlock.setThickness(0.00075); + thrustBlock.setName("Engine Block"); + inner.addChild(thrustBlock); + } - int finCount = 3; - double finRootChord = .05715; - double finTipChord = .03048; - double finSweep = 0.06985455; - double finHeight = 0.04064; - TrapezoidFinSet finset = new TrapezoidFinSet(finCount, finRootChord, finTipChord, finSweep, finHeight); - finset.setThickness( 0.003175); - finset.setRelativePosition(Position.BOTTOM); - bodytube.addChild(finset); + // parachute + Parachute chute = new Parachute(); + chute.setRelativePosition(Position.TOP); + chute.setName("Parachute"); + chute.setAxialOffset(0.028575); + chute.setOverrideMass(0.002041); + chute.setMassOverridden(true); + bodytube.addChild(chute); + + // bulkhead x2 + CenteringRing centerings = new CenteringRing(); + centerings.setName("Centering Rings"); + centerings.setRelativePosition(Position.TOP); + centerings.setAxialOffset(0.1397); + centerings.setLength(0.00635); + centerings.setInstanceCount(2); + centerings.setInstanceSeparation(0.035); + bodytube.addChild(centerings); + } Material material = Application.getPreferences().getDefaultComponentMaterial(null, Material.Type.BULK); nosecone.setMaterial(material); diff --git a/core/test/net/sf/openrocket/rocketcomponent/LaunchLugTest.java b/core/test/net/sf/openrocket/rocketcomponent/LaunchLugTest.java new file mode 100644 index 000000000..6592cf7cb --- /dev/null +++ b/core/test/net/sf/openrocket/rocketcomponent/LaunchLugTest.java @@ -0,0 +1,74 @@ +package net.sf.openrocket.rocketcomponent; + +import static org.junit.Assert.*; + +import net.sf.openrocket.rocketcomponent.RocketComponent.Position; +import net.sf.openrocket.util.Coordinate; +import net.sf.openrocket.util.MathUtil; +import net.sf.openrocket.util.TestRockets; +import net.sf.openrocket.util.BaseTestCase.BaseTestCase; + +import org.junit.Test; + +public class LaunchLugTest extends BaseTestCase { + protected final double EPSILON = MathUtil.EPSILON; + + @Test + public void testLaunchLugLocationZeroAngle() { + Rocket rocket = TestRockets.makeEstesAlphaIII(); + + BodyTube body= (BodyTube)rocket.getChild(0).getChild(1); + LaunchLug lug = (LaunchLug)rocket.getChild(0).getChild(1).getChild(1); + lug.setInstanceSeparation(0.05); + lug.setInstanceCount(2); + + double expX = 0.111125 + body.getLocations()[0].x; + double expR = body.getOuterRadius()+lug.getOuterRadius(); + Coordinate expPos = new Coordinate( expX, expR, 0, 0); + Coordinate actPos[] = lug.getLocations(); + assertEquals(" LaunchLug has the wrong x value: ", expPos.x, actPos[0].x, EPSILON); + assertEquals(" LaunchLug has the wrong y value: ", expPos.y, actPos[0].y, EPSILON); + assertEquals(" LaunchLug has the wrong z value: ", expPos.z, actPos[0].z, EPSILON); + assertEquals(" LaunchLug has the wrong weight: ", 0, actPos[0].weight, EPSILON); + assertEquals(" LaunchLug #1 is in the wrong place: ", expPos, actPos[0]); + + expPos = expPos.setX( expX+0.05 ); + assertEquals(" LaunchLug #2 is in the wrong place: ", expPos, actPos[1]); + } + + @Test + public void testLaunchLugLocationAtAngles() { + Rocket rocket = TestRockets.makeEstesAlphaIII(); + + BodyTube body= (BodyTube)rocket.getChild(0).getChild(1); + LaunchLug lug = (LaunchLug)rocket.getChild(0).getChild(1).getChild(1); + double startAngle = Math.PI/2; + lug.setRadialDirection( startAngle ); + lug.setInstanceSeparation(0.05); + lug.setInstanceCount(2); + System.err.println("..created lug: at : " + lug.getInstanceOffsets()[0]); + System.err.println(" angle: "+startAngle/Math.PI*180+" deg "); + + //String treeDump = rocket.toDebugTree(); + //System.err.println(treeDump); + + + double expX = 0.111125 + body.getLocations()[0].x; + double expR = 0.015376; + double expY = Math.cos(startAngle)*expR ; + double expZ = Math.sin(startAngle)*expR ; + Coordinate expPos = new Coordinate( expX, expY, expZ, 0); + Coordinate actPos[] = lug.getLocations(); + assertEquals(" LaunchLug has the wrong x value: ", expPos.x, actPos[0].x, EPSILON); + assertEquals(" LaunchLug has the wrong y value: ", expPos.y, actPos[0].y, EPSILON); + assertEquals(" LaunchLug has the wrong z value: ", expPos.z, actPos[0].z, EPSILON); + assertEquals(" LaunchLug has the wrong weight: ", 0, actPos[0].weight, EPSILON); + assertEquals(" LaunchLug is in the wrong place: ", expPos, actPos[0]); + + if( 1 < actPos.length){ + expPos = expPos.setX( expX+0.05 ); + assertEquals(" LaunchLug #2 is in the wrong place: ", expPos, actPos[1]); + } + } + +} diff --git a/core/test/net/sf/openrocket/rocketcomponent/RocketTest.java b/core/test/net/sf/openrocket/rocketcomponent/RocketTest.java index 16b5ca5df..177342e9e 100644 --- a/core/test/net/sf/openrocket/rocketcomponent/RocketTest.java +++ b/core/test/net/sf/openrocket/rocketcomponent/RocketTest.java @@ -1,5 +1,15 @@ package net.sf.openrocket.rocketcomponent; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; +import net.sf.openrocket.material.Material; +import net.sf.openrocket.rocketcomponent.RocketComponent.Position; +import net.sf.openrocket.startup.Application; +import net.sf.openrocket.util.Coordinate; +import net.sf.openrocket.util.MathUtil; +import net.sf.openrocket.util.TestRockets; import net.sf.openrocket.util.BaseTestCase.BaseTestCase; import org.junit.Test; @@ -8,16 +18,115 @@ public class RocketTest extends BaseTestCase { @Test public void testCopyFrom() { - Rocket r1 = net.sf.openrocket.util.TestRockets.makeIsoHaisu(); - Rocket r2 = net.sf.openrocket.util.TestRockets.makeBigBlue(); +// Rocket r1 = net.sf.openrocket.util.TestRockets.makeIsoHaisu(); +// Rocket r2 = net.sf.openrocket.util.TestRockets.makeBigBlue(); +// +// Rocket copy = (Rocket) r2.copy(); +// +// ComponentCompare.assertDeepEquality(r2, copy); +// +// r1.copyFrom(copy); +// +// ComponentCompare.assertDeepEquality(r1, r2); + fail("NYI"); + } + + @Test + public void testEstesAlphaIII(){ + final double EPSILON = MathUtil.EPSILON; + Rocket rocket = TestRockets.makeEstesAlphaIII(); + +// String treeDump = rocket.toDebugTree(); +// System.err.println(treeDump); - Rocket copy = (Rocket) r2.copy(); + AxialStage stage= (AxialStage)rocket.getChild(0); - ComponentCompare.assertDeepEquality(r2, copy); + NoseCone nose = (NoseCone)stage.getChild(0); + BodyTube body = (BodyTube)stage.getChild(1); + FinSet fins = (FinSet)body.getChild(0); + LaunchLug lug = (LaunchLug)body.getChild(1); + InnerTube mmt = (InnerTube)body.getChild(2); + EngineBlock block = (EngineBlock)mmt.getChild(0); + Parachute chute = (Parachute)body.getChild(3); + CenteringRing center = (CenteringRing)body.getChild(4); - r1.copyFrom(copy); - ComponentCompare.assertDeepEquality(r1, r2); + RocketComponent cc; + Coordinate expLoc; + Coordinate actLoc; + { + cc = nose; + expLoc = new Coordinate(0,0,0); + actLoc = cc.getLocations()[0]; + assertThat(cc.getName()+" not positioned correctly: ", actLoc, equalTo(expLoc)); + + cc = body; + expLoc = new Coordinate(0.06985,0,0); + actLoc = cc.getLocations()[0]; + assertThat(cc.getName()+" not positioned correctly: ", actLoc, equalTo(expLoc)); + + { + cc = fins; + expLoc = new Coordinate(0.20955,0,0); + actLoc = cc.getLocations()[0]; + assertThat(cc.getName()+" not positioned correctly: ", actLoc, equalTo(expLoc)); + + cc = lug; + expLoc = new Coordinate(0.180975, 0.015376, 0); + actLoc = cc.getLocations()[0]; + assertThat(cc.getName()+" not positioned correctly: ", actLoc, equalTo(expLoc)); + + cc = mmt; + expLoc = new Coordinate(0.2032,0,0); + actLoc = cc.getLocations()[0]; + assertThat(cc.getName()+" not positioned correctly: ", actLoc, equalTo(expLoc)); + { + cc = block; + expLoc = new Coordinate(0.2032,0,0); + actLoc = cc.getLocations()[0]; + assertThat(cc.getName()+" not positioned correctly: ", actLoc, equalTo(expLoc)); + } + + } + + cc = chute; + expLoc = new Coordinate(0.098425,0,0); + actLoc = cc.getLocations()[0]; + assertThat(cc.getName()+" not positioned correctly: ", actLoc, equalTo(expLoc)); + + cc = center; + assertThat(cc.getName()+" not instanced correctly: ", cc.getInstanceCount(), equalTo(2)); + // singleton instances follow different code paths + center.setInstanceCount(1); + expLoc = new Coordinate(0.20955,0,0); + actLoc = cc.getLocations()[0]; + assertEquals(" position x fail: ", expLoc.x, actLoc.x, EPSILON); + assertEquals(" position y fail: ", expLoc.y, actLoc.y, EPSILON); + assertEquals(" position z fail: ", expLoc.z, actLoc.z, EPSILON); + assertThat(cc.getName()+" not positioned correctly: ", actLoc, equalTo(expLoc)); + + cc = center; + center.setInstanceCount(2); + Coordinate actLocs[] = cc.getLocations(); + expLoc = new Coordinate(0.20955,0,0); + actLoc = actLocs[0]; +// assertEquals(" position x fail: ", expLoc.x, actLoc.x, EPSILON); +// assertEquals(" position y fail: ", expLoc.y, actLoc.y, EPSILON); +// assertEquals(" position z fail: ", expLoc.z, actLoc.z, EPSILON); + assertThat(cc.getName()+" not positioned correctly: ", actLoc, equalTo(expLoc)); + { // second instance + expLoc = new Coordinate(0.24455, 0, 0); + actLoc = actLocs[1]; + assertThat(cc.getName()+" not positioned correctly: ", actLoc, equalTo(expLoc)); + } + { // second instance + assertThat(cc.getName()+" not instanced correctly: ", cc.getInstanceCount(), equalTo(2)); + expLoc = new Coordinate(0.24455, 0, 0); + actLoc = actLocs[1]; + assertThat(cc.getName()+" not positioned correctly: ", actLoc, equalTo(expLoc)); + } + + } } }