[Bugfix] Fixed Core Positioning Code
- Launch Lugs correctly position themselves (used to default to the centerline of the rocket) added LaunchLugTest class - Booster Sets automatically adjust radial distance - based on own, and others' body radius. - Refactored shiftCoordinates(...) => getInstanceLocations()
This commit is contained in:
parent
afe56365f4
commit
ec5a3119c5
@ -21,7 +21,7 @@ import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
|
|||||||
import net.sf.openrocket.rocketcomponent.FinSet;
|
import net.sf.openrocket.rocketcomponent.FinSet;
|
||||||
import net.sf.openrocket.rocketcomponent.FreeformFinSet;
|
import net.sf.openrocket.rocketcomponent.FreeformFinSet;
|
||||||
import net.sf.openrocket.rocketcomponent.InnerTube;
|
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.LaunchLug;
|
||||||
import net.sf.openrocket.rocketcomponent.MassComponent;
|
import net.sf.openrocket.rocketcomponent.MassComponent;
|
||||||
import net.sf.openrocket.rocketcomponent.MassObject;
|
import net.sf.openrocket.rocketcomponent.MassObject;
|
||||||
@ -164,9 +164,9 @@ class DocumentConfig {
|
|||||||
|
|
||||||
// LaunchButton
|
// LaunchButton
|
||||||
setters.put("LaunchButton:instancecount", new IntSetter(
|
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(
|
setters.put("LaunchButton:instanceseparation", new DoubleSetter(
|
||||||
Reflection.findMethod( LaunchButton.class, "setInstanceSeparation", double.class)));
|
Reflection.findMethod( RailButton.class, "setInstanceSeparation", double.class)));
|
||||||
|
|
||||||
// LaunchLug
|
// LaunchLug
|
||||||
setters.put("LaunchLug:instancecount", new IntSetter(
|
setters.put("LaunchLug:instancecount", new IntSetter(
|
||||||
|
@ -14,7 +14,7 @@ import net.sf.openrocket.util.Coordinate;
|
|||||||
public class BoosterSet extends AxialStage implements FlightConfigurableComponent, RingInstanceable {
|
public class BoosterSet extends AxialStage implements FlightConfigurableComponent, RingInstanceable {
|
||||||
|
|
||||||
private static final Translator trans = Application.getTranslator();
|
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;
|
protected int count = 1;
|
||||||
|
|
||||||
@ -127,7 +127,24 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Coordinate[] getInstanceOffsets(){
|
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
|
@Override
|
||||||
@ -142,8 +159,12 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen
|
|||||||
"(assumed reason for getting multiple parent locations into an external stage.)");
|
"(assumed reason for getting multiple parent locations into an external stage.)");
|
||||||
}
|
}
|
||||||
|
|
||||||
parentInstances[0] = parentInstances[0].add( this.position);
|
final Coordinate center = parentInstances[0].add( this.position);
|
||||||
Coordinate[] toReturn = this.shiftCoordinates(parentInstances);
|
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;
|
return toReturn;
|
||||||
}
|
}
|
||||||
@ -185,30 +206,30 @@ public class BoosterSet extends AxialStage implements FlightConfigurableComponen
|
|||||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// @Override
|
||||||
protected Coordinate[] shiftCoordinates(Coordinate[] c) {
|
// protected Coordinate[] shiftCoordinates(Coordinate[] c) {
|
||||||
checkState();
|
// checkState();
|
||||||
|
//
|
||||||
if (1 < c.length) {
|
// if (1 < c.length) {
|
||||||
throw new BugException("implementation of 'shiftCoordinates' assumes the coordinate array has len == 1; The length here is "+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 radius = this.radialPosition_m;
|
||||||
double angle0 = this.angularPosition_rad;
|
// double angle0 = this.angularPosition_rad;
|
||||||
double angleIncr = this.angularSeparation;
|
// double angleIncr = this.angularSeparation;
|
||||||
Coordinate center = c[0];
|
// Coordinate center = c[0];
|
||||||
Coordinate[] toReturn = new Coordinate[this.count];
|
// Coordinate[] toReturn = new Coordinate[this.count];
|
||||||
//Coordinate thisOffset;
|
// //Coordinate thisOffset;
|
||||||
double thisAngle = angle0;
|
// double thisAngle = angle0;
|
||||||
for (int instanceNumber = 0; instanceNumber < this.count; instanceNumber++) {
|
// for (int instanceNumber = 0; instanceNumber < this.count; instanceNumber++) {
|
||||||
toReturn[instanceNumber] = center.add(0, radius * Math.cos(thisAngle), radius * Math.sin(thisAngle));
|
// toReturn[instanceNumber] = center.add(0, radius * Math.cos(thisAngle), radius * Math.sin(thisAngle));
|
||||||
|
//
|
||||||
thisAngle += angleIncr;
|
// thisAngle += angleIncr;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return toReturn;
|
// return toReturn;
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@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("%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()));
|
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();
|
Coordinate[] absCoords = this.getLocations();
|
||||||
for (int instanceNumber = 0; instanceNumber < this.count; instanceNumber++) {
|
for (int instanceNumber = 0; instanceNumber < this.count; instanceNumber++) {
|
||||||
Coordinate instanceRelativePosition = relCoords[instanceNumber];
|
Coordinate instanceRelativePosition = relCoords[instanceNumber];
|
||||||
|
@ -102,16 +102,14 @@ public class CenteringRing extends RadiusRingComponent implements LineInstanceab
|
|||||||
@Override
|
@Override
|
||||||
public Coordinate[] getInstanceOffsets(){
|
public Coordinate[] getInstanceOffsets(){
|
||||||
Coordinate[] toReturn = new Coordinate[this.getInstanceCount()];
|
Coordinate[] toReturn = new Coordinate[this.getInstanceCount()];
|
||||||
toReturn[0] = Coordinate.ZERO;
|
for ( int index=0 ; index < this.getInstanceCount(); index++){
|
||||||
|
toReturn[index] = this.position.setX( this.position.x + index*this.instanceSeparation );
|
||||||
for ( int index=1 ; index < this.getInstanceCount(); index++){
|
|
||||||
toReturn[index] = new Coordinate(index*this.instanceSeparation,0,0,0);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getInstanceCount(){
|
public int getInstanceCount(){
|
||||||
return this.instanceCount;
|
return this.instanceCount;
|
||||||
|
@ -7,6 +7,7 @@ import net.sf.openrocket.material.Material;
|
|||||||
import net.sf.openrocket.preset.ComponentPreset;
|
import net.sf.openrocket.preset.ComponentPreset;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.unit.UnitGroup;
|
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
|
* 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
|
@Override
|
||||||
protected List<RocketComponent> copyFrom(RocketComponent c) {
|
protected List<RocketComponent> copyFrom(RocketComponent c) {
|
||||||
ExternalComponent src = (ExternalComponent) c;
|
ExternalComponent src = (ExternalComponent) c;
|
||||||
|
@ -217,47 +217,73 @@ public class InnerTube extends ThicknessRingComponent implements Clusterable, Ra
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Coordinate[] getInstanceOffsets(){
|
public Coordinate[] getInstanceOffsets(){
|
||||||
return this.shiftCoordinates(new Coordinate[]{Coordinate.ZERO});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
int instanceCount = getClusterCount();
|
||||||
public Coordinate[] getLocations(){
|
if (instanceCount == 1)
|
||||||
if (null == this.parent) {
|
return super.getInstanceOffsets();
|
||||||
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;
|
|
||||||
|
|
||||||
List<Coordinate> points = getClusterPoints();
|
List<Coordinate> points = getClusterPoints();
|
||||||
if (points.size() != count) {
|
if (points.size() != instanceCount) {
|
||||||
throw new BugException("Inconsistent cluster configuration, cluster count=" + count +
|
throw new BugException("Inconsistent cluster configuration, cluster count(" + instanceCount +
|
||||||
" point count=" + points.size());
|
") != 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++) {
|
Coordinate[] newArray = new Coordinate[ instanceCount];
|
||||||
newArray[i * count + j] = array[i].add(points.get(j));
|
for (int instanceNumber = 0; instanceNumber < instanceCount; instanceNumber++) {
|
||||||
}
|
newArray[ instanceNumber] = this.position.add( points.get(instanceNumber));
|
||||||
}
|
}
|
||||||
|
|
||||||
return newArray;
|
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<Coordinate> 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 /////////////////
|
//////////////// Motor mount /////////////////
|
||||||
|
|
||||||
@Override
|
@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("%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()));
|
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();
|
Coordinate[] absCoords = this.getLocations();
|
||||||
FlightConfigurationID curId = this.getRocket().getDefaultConfiguration().getFlightConfigurationID();
|
FlightConfigurationID curId = this.getRocket().getDefaultConfiguration().getFlightConfigurationID();
|
||||||
int count = this.getInstanceCount();
|
final int intanceCount = this.getInstanceCount();
|
||||||
MotorInstance curInstance = this.motors.get(curId);
|
MotorInstance curInstance = this.motors.get(curId);
|
||||||
//if( curInstance.isEmpty() ){
|
//if( curInstance.isEmpty() ){
|
||||||
{
|
{
|
||||||
// print just the tube locations
|
// print just the tube locations
|
||||||
|
|
||||||
for (int instanceNumber = 0; instanceNumber < count; instanceNumber++) {
|
for (int instanceNumber = 0; instanceNumber < intanceCount; instanceNumber++) {
|
||||||
Coordinate tubeRelativePosition = relCoords[instanceNumber];
|
Coordinate tubeRelativePosition = relCoords[instanceNumber];
|
||||||
Coordinate tubeAbsolutePosition = absCoords[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));
|
tubeRelativePosition, tubeAbsolutePosition));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -410,15 +436,15 @@ public class InnerTube extends ThicknessRingComponent implements Clusterable, Ra
|
|||||||
}else{
|
}else{
|
||||||
// curInstance has a motor ...
|
// curInstance has a motor ...
|
||||||
Motor curMotor = curInstance.getMotor();
|
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",
|
buffer.append(String.format("%s %-24s Thrust: %f N; (Length: %f); \n",
|
||||||
prefix, curMotor.getDesignation(), curMotor.getMaxThrustEstimate(), curMotor.getLength() ));
|
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 motorRelativePosition = new Coordinate(motorOffset, 0, 0);
|
||||||
Coordinate tubeAbs = absCoords[instanceNumber];
|
Coordinate tubeAbs = absCoords[instanceNumber];
|
||||||
Coordinate motorAbsolutePosition = new Coordinate(tubeAbs.x+motorOffset,tubeAbs.y,tubeAbs.z);
|
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));
|
motorRelativePosition, motorAbsolutePosition));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,14 +20,11 @@ public class LaunchLug extends ExternalComponent implements Coaxial, LineInstanc
|
|||||||
private double thickness;
|
private double thickness;
|
||||||
|
|
||||||
private double radialDirection = 0;
|
private double radialDirection = 0;
|
||||||
|
protected double radialDistance = 0;
|
||||||
|
|
||||||
private int instanceCount = 1;
|
private int instanceCount = 1;
|
||||||
private double instanceSeparation = 0; // front-front along the positive rocket axis. i.e. [1,0,0];
|
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() {
|
public LaunchLug() {
|
||||||
super(Position.MIDDLE);
|
super(Position.MIDDLE);
|
||||||
@ -113,6 +110,7 @@ public class LaunchLug extends ExternalComponent implements Coaxial, LineInstanc
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPositionValue(double value) {
|
public void setPositionValue(double value) {
|
||||||
|
System.err.println(" positioning "+getName()+" to: "+value);
|
||||||
super.setPositionValue(value);
|
super.setPositionValue(value);
|
||||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||||
}
|
}
|
||||||
@ -145,25 +143,29 @@ public class LaunchLug extends ExternalComponent implements Coaxial, LineInstanc
|
|||||||
@Override
|
@Override
|
||||||
public Coordinate[] getInstanceOffsets(){
|
public Coordinate[] getInstanceOffsets(){
|
||||||
Coordinate[] toReturn = new Coordinate[this.getInstanceCount()];
|
Coordinate[] toReturn = new Coordinate[this.getInstanceCount()];
|
||||||
toReturn[0] = Coordinate.ZERO;
|
|
||||||
|
|
||||||
for ( int index=1 ; index < this.getInstanceCount(); index++){
|
final double xOffset = this.position.x;
|
||||||
toReturn[index] = new Coordinate(index*this.instanceSeparation,0,0,0);
|
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;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
// @Override
|
||||||
protected Coordinate[] shiftCoordinates(Coordinate[] array) {
|
// protected Coordinate[] shiftCoordinates(Coordinate[] array) {
|
||||||
array = super.shiftCoordinates(array);
|
// array = super.shiftCoordinates(array);
|
||||||
|
//
|
||||||
for (int i = 0; i < array.length; i++) {
|
// for (int i = 0; i < array.length; i++) {
|
||||||
array[i] = array[i].add(0, shiftY, shiftZ);
|
// array[i] = new Coordinate(xOffset + index*this.instanceSeparation, yOffset, zOffset);
|
||||||
}
|
// array[i] = array[i].add(0, shiftY, shiftZ);
|
||||||
|
// }
|
||||||
return array;
|
//
|
||||||
}
|
// return array;
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -194,10 +196,7 @@ public class LaunchLug extends ExternalComponent implements Coaxial, LineInstanc
|
|||||||
parentRadius = Math.max(s.getRadius(x1), s.getRadius(x2));
|
parentRadius = Math.max(s.getRadius(x1), s.getRadius(x2));
|
||||||
}
|
}
|
||||||
|
|
||||||
shiftY = Math.cos(radialDirection) * (parentRadius + radius);
|
this.radialDistance = parentRadius + radius;
|
||||||
shiftZ = Math.sin(radialDirection) * (parentRadius + radius);
|
|
||||||
|
|
||||||
// System.out.println("Computed shift: y="+shiftY+" z="+shiftZ);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -109,14 +109,14 @@ public abstract class MassObject extends InternalComponent {
|
|||||||
/**
|
/**
|
||||||
* Shift the coordinates according to the radial position and direction.
|
* Shift the coordinates according to the radial position and direction.
|
||||||
*/
|
*/
|
||||||
@Override
|
// @Override
|
||||||
protected
|
// protected
|
||||||
final Coordinate[] shiftCoordinates(Coordinate[] array) {
|
// final Coordinate[] shiftCoordinates(Coordinate[] array) {
|
||||||
for (int i = 0; i < array.length; i++) {
|
// for (int i = 0; i < array.length; i++) {
|
||||||
array[i] = array[i].add(0, shiftY, shiftZ);
|
// array[i] = array[i].add(0, shiftY, shiftZ);
|
||||||
}
|
// }
|
||||||
return array;
|
// return array;
|
||||||
}
|
// }
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Coordinate getComponentCG() {
|
public final Coordinate getComponentCG() {
|
||||||
|
@ -78,9 +78,27 @@ public class PodSet extends ComponentAssembly implements RingInstanceable {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Coordinate[] getInstanceOffsets(){
|
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
|
@Override
|
||||||
public Coordinate[] getLocations() {
|
public Coordinate[] getLocations() {
|
||||||
if (null == this.parent) {
|
if (null == this.parent) {
|
||||||
@ -96,7 +114,12 @@ public class PodSet extends ComponentAssembly implements RingInstanceable {
|
|||||||
"(assumed reason for getting multiple parent locations into an external stage.)");
|
"(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;
|
return toReturn;
|
||||||
}
|
}
|
||||||
@ -186,31 +209,6 @@ public class PodSet extends ComponentAssembly implements RingInstanceable {
|
|||||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
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
|
@Override
|
||||||
protected StringBuilder toDebugDetail() {
|
protected StringBuilder toDebugDetail() {
|
||||||
StringBuilder buf = super.toDebugDetail();
|
StringBuilder buf = super.toDebugDetail();
|
||||||
|
@ -5,10 +5,7 @@ import net.sf.openrocket.util.Coordinate;
|
|||||||
import net.sf.openrocket.util.MathUtil;
|
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 <sampo.niskanen@iki.fi>
|
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
||||||
*/
|
*/
|
||||||
|
@ -15,7 +15,7 @@ import net.sf.openrocket.util.MathUtil;
|
|||||||
* @author widget (Daniel Williams)
|
* @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();
|
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);
|
super(Position.MIDDLE);
|
||||||
radius = 0.01 / 2;
|
radius = 0.01 / 2;
|
||||||
thickness = 0.001;
|
thickness = 0.001;
|
||||||
@ -154,16 +154,16 @@ public abstract class LaunchButton extends ExternalComponent implements LineInst
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
// @Override
|
||||||
protected Coordinate[] shiftCoordinates(Coordinate[] array) {
|
// protected Coordinate[] shiftCoordinates(Coordinate[] array) {
|
||||||
array = super.shiftCoordinates(array);
|
// array = super.shiftCoordinates(array);
|
||||||
|
//
|
||||||
for (int i = 0; i < array.length; i++) {
|
// for (int i = 0; i < array.length; i++) {
|
||||||
array[i] = array[i].add(0, shiftY, shiftZ);
|
// array[i] = array[i].add(0, shiftY, shiftZ);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return array;
|
// return array;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
@ -172,19 +172,6 @@ public abstract class RingComponent extends StructuralComponent implements Coaxi
|
|||||||
return 1;
|
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
|
@Override
|
||||||
public Collection<Coordinate> getComponentBounds() {
|
public Collection<Coordinate> getComponentBounds() {
|
||||||
List<Coordinate> bounds = new ArrayList<Coordinate>();
|
List<Coordinate> bounds = new ArrayList<Coordinate>();
|
||||||
|
@ -276,7 +276,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
* @return indicates if a component is positioned via AFTER
|
* @return indicates if a component is positioned via AFTER
|
||||||
*/
|
*/
|
||||||
public boolean isAfter(){
|
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
|
* @return an array of shifted coordinates. The method may modify the contents
|
||||||
* of the passed array and return the array itself.
|
* of the passed array and return the array itself.
|
||||||
*/
|
*/
|
||||||
protected Coordinate[] shiftCoordinates(Coordinate[] c) {
|
// protected Coordinate[] shiftCoordinates(Coordinate[] c) {
|
||||||
checkState();
|
// checkState();
|
||||||
return c;
|
// return c;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -943,12 +943,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
throw new BugException("Unknown position type: " + thePosition);
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -997,10 +991,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
setAxialOffset(value);
|
setAxialOffset(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAxialOffset(double _value) {
|
|
||||||
this.setAxialOffset(this.relativePosition, _value);
|
|
||||||
this.fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void setAfter(RocketComponent referenceComponent) {
|
protected void setAfter(RocketComponent referenceComponent) {
|
||||||
checkState();
|
checkState();
|
||||||
@ -1028,23 +1018,29 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
this.position = new Coordinate(newAxialPosition, this.position.y, this.position.z);
|
this.position = new Coordinate(newAxialPosition, this.position.y, this.position.z);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setAxialOffset(Position positionMethod, double newOffset) {
|
public void setAxialOffset(double _value) {
|
||||||
// if this is the root of a hierarchy, constrain the position to zero.
|
this.setAxialOffset(this.relativePosition, _value);
|
||||||
if (null == this.parent) {
|
this.fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||||
return;
|
}
|
||||||
} else if ( this.isAfter()){
|
|
||||||
positionMethod = Position.AFTER;
|
|
||||||
}
|
|
||||||
checkState();
|
|
||||||
|
|
||||||
this.relativePosition = positionMethod;
|
protected void setAxialOffset(final Position positionMethod, final double newOffset) {
|
||||||
this.offset = newOffset;
|
checkState();
|
||||||
|
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;
|
final double EPSILON = 0.000001;
|
||||||
double newAxialPosition = Double.NaN;
|
double newAxialPosition = Double.NaN;
|
||||||
double refLength = this.parent.getLength();
|
final double refLength = this.parent.getLength();
|
||||||
|
switch (this.relativePosition) {
|
||||||
switch (positionMethod) {
|
|
||||||
case ABSOLUTE:
|
case ABSOLUTE:
|
||||||
newAxialPosition = newOffset - this.parent.position.x;
|
newAxialPosition = newOffset - this.parent.position.x;
|
||||||
break;
|
break;
|
||||||
@ -1062,7 +1058,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
newAxialPosition = (refLength - this.length) + newOffset;
|
newAxialPosition = (refLength - this.length) + newOffset;
|
||||||
break;
|
break;
|
||||||
default:
|
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'
|
// 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) {
|
if (Double.NaN == newAxialPosition) {
|
||||||
throw new BugException("setAxialOffset is broken -- attempted to update as NaN: " + this.toDebugDetail());
|
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);
|
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() {
|
protected void update() {
|
||||||
@ -1083,11 +1091,6 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
return this.position;
|
return this.position;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public Coordinate[] getOffset() {
|
|
||||||
// return new Coordinate[]{this.position};
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated kept around as example code. instead use getLocations
|
* @deprecated kept around as example code. instead use getLocations
|
||||||
* @return
|
* @return
|
||||||
@ -1101,17 +1104,50 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns coordinates of this component's instances in relation to this.parent.
|
||||||
|
* <p>
|
||||||
|
* For example, the absolute position of any given instance is the parent's position
|
||||||
|
* plus the instance position returned by this method
|
||||||
|
* <p>
|
||||||
|
* 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() {
|
public Coordinate[] getLocations() {
|
||||||
if (null == this.parent) {
|
if (null == this.parent) {
|
||||||
// == improperly initialized components OR the root Rocket instance
|
// == improperly initialized components OR the root Rocket instance
|
||||||
return new Coordinate[] { Coordinate.ZERO };
|
return new Coordinate[] { Coordinate.ZERO };
|
||||||
} else {
|
} else {
|
||||||
Coordinate[] parentPositions = this.parent.getLocations();
|
Coordinate[] parentPositions = this.parent.getLocations();
|
||||||
int instCount = parentPositions.length;
|
int parentCount = parentPositions.length;
|
||||||
Coordinate[] thesePositions = new Coordinate[instCount];
|
|
||||||
|
|
||||||
for (int pi = 0; pi < instCount; pi++) {
|
// override <instance>.getInstanceOffsets() in the subclass you want to fix.
|
||||||
thesePositions[pi] = parentPositions[pi].add(this.getOffset());
|
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;
|
return thesePositions;
|
||||||
}
|
}
|
||||||
@ -1190,15 +1226,15 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static final Coordinate[] rebase(final Coordinate toMove[], final Coordinate source, final Coordinate dest) {
|
// protected static final Coordinate[] rebase(final Coordinate toMove[], final Coordinate source, final Coordinate dest) {
|
||||||
final Coordinate delta = source.sub(dest);
|
// final Coordinate delta = source.sub(dest);
|
||||||
Coordinate[] toReturn = new Coordinate[toMove.length];
|
// Coordinate[] toReturn = new Coordinate[toMove.length];
|
||||||
for (int coordIndex = 0; coordIndex < toMove.length; coordIndex++) {
|
// for (int coordIndex = 0; coordIndex < toMove.length; coordIndex++) {
|
||||||
toReturn[coordIndex] = toMove[coordIndex].add(delta);
|
// toReturn[coordIndex] = toMove[coordIndex].add(delta);
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
return toReturn;
|
// return toReturn;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2085,8 +2121,8 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void toDebugTreeNode(final StringBuilder buffer, final String prefix) {
|
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(),
|
buffer.append(String.format("%-42s; %5.3f; %24s; %24s;\n", prefix+" "+this.getName(),
|
||||||
this.getOffset(), this.getLocations()[0]));
|
this.getLength(), this.getOffset(), this.getLocations()[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dumpTreeHelper(StringBuilder buffer, final String prefix) {
|
public void dumpTreeHelper(StringBuilder buffer, final String prefix) {
|
||||||
|
@ -27,6 +27,7 @@ import net.sf.openrocket.rocketcomponent.CenteringRing;
|
|||||||
import net.sf.openrocket.rocketcomponent.ClusterConfiguration;
|
import net.sf.openrocket.rocketcomponent.ClusterConfiguration;
|
||||||
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
|
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration;
|
||||||
import net.sf.openrocket.rocketcomponent.DeploymentConfiguration.DeployEvent;
|
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;
|
||||||
import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
|
import net.sf.openrocket.rocketcomponent.ExternalComponent.Finish;
|
||||||
import net.sf.openrocket.rocketcomponent.FinSet.CrossSection;
|
import net.sf.openrocket.rocketcomponent.FinSet.CrossSection;
|
||||||
@ -316,8 +317,9 @@ public class TestRockets {
|
|||||||
public static final Rocket makeEstesAlphaIII(){
|
public static final Rocket makeEstesAlphaIII(){
|
||||||
|
|
||||||
Rocket rocket = new Rocket();
|
Rocket rocket = new Rocket();
|
||||||
|
rocket.setName("Estes Alpha III / Code Verification Rocket");
|
||||||
AxialStage stage = new AxialStage();
|
AxialStage stage = new AxialStage();
|
||||||
stage.setName("Stage1");
|
stage.setName("Stage");
|
||||||
rocket.addChild(stage);
|
rocket.addChild(stage);
|
||||||
|
|
||||||
double noseconeLength = 0.06985;
|
double noseconeLength = 0.06985;
|
||||||
@ -325,14 +327,31 @@ public class TestRockets {
|
|||||||
NoseCone nosecone = new NoseCone(Transition.Shape.ELLIPSOID, noseconeLength, noseconeRadius);
|
NoseCone nosecone = new NoseCone(Transition.Shape.ELLIPSOID, noseconeLength, noseconeRadius);
|
||||||
nosecone.setAftShoulderLength(0.02479);
|
nosecone.setAftShoulderLength(0.02479);
|
||||||
nosecone.setAftShoulderRadius(0.011811);
|
nosecone.setAftShoulderRadius(0.011811);
|
||||||
|
nosecone.setName("Nose Cone");
|
||||||
stage.addChild(nosecone);
|
stage.addChild(nosecone);
|
||||||
|
|
||||||
double bodytubeLength = 0.19685;
|
double bodytubeLength = 0.19685;
|
||||||
double bodytubeRadius = 0.012395;
|
double bodytubeRadius = 0.012395;
|
||||||
double bodytubeThickness = 0.00033;
|
double bodytubeThickness = 0.00033;
|
||||||
BodyTube bodytube = new BodyTube(bodytubeLength, bodytubeRadius, bodytubeThickness);
|
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();
|
LaunchLug lug = new LaunchLug();
|
||||||
|
lug.setName("Launch Lugs");
|
||||||
lug.setRelativePosition(Position.TOP);
|
lug.setRelativePosition(Position.TOP);
|
||||||
lug.setAxialOffset(0.111125);
|
lug.setAxialOffset(0.111125);
|
||||||
lug.setLength(0.0508);
|
lug.setLength(0.0508);
|
||||||
@ -347,21 +366,40 @@ public class TestRockets {
|
|||||||
inner.setOuterRadius(0.009347);
|
inner.setOuterRadius(0.009347);
|
||||||
inner.setThickness(0.00033);
|
inner.setThickness(0.00033);
|
||||||
inner.setMotorMount(true);
|
inner.setMotorMount(true);
|
||||||
|
inner.setName("Motor Mount Tube");
|
||||||
bodytube.addChild(inner);
|
bodytube.addChild(inner);
|
||||||
|
|
||||||
// omit other internal components... this method does not return a flyable version of the Mk 2
|
{
|
||||||
}
|
// MotorBlock
|
||||||
stage.addChild(bodytube);
|
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;
|
// parachute
|
||||||
double finRootChord = .05715;
|
Parachute chute = new Parachute();
|
||||||
double finTipChord = .03048;
|
chute.setRelativePosition(Position.TOP);
|
||||||
double finSweep = 0.06985455;
|
chute.setName("Parachute");
|
||||||
double finHeight = 0.04064;
|
chute.setAxialOffset(0.028575);
|
||||||
TrapezoidFinSet finset = new TrapezoidFinSet(finCount, finRootChord, finTipChord, finSweep, finHeight);
|
chute.setOverrideMass(0.002041);
|
||||||
finset.setThickness( 0.003175);
|
chute.setMassOverridden(true);
|
||||||
finset.setRelativePosition(Position.BOTTOM);
|
bodytube.addChild(chute);
|
||||||
bodytube.addChild(finset);
|
|
||||||
|
// 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);
|
Material material = Application.getPreferences().getDefaultComponentMaterial(null, Material.Type.BULK);
|
||||||
nosecone.setMaterial(material);
|
nosecone.setMaterial(material);
|
||||||
|
@ -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]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,15 @@
|
|||||||
package net.sf.openrocket.rocketcomponent;
|
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 net.sf.openrocket.util.BaseTestCase.BaseTestCase;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
@ -8,16 +18,115 @@ public class RocketTest extends BaseTestCase {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCopyFrom() {
|
public void testCopyFrom() {
|
||||||
Rocket r1 = net.sf.openrocket.util.TestRockets.makeIsoHaisu();
|
// Rocket r1 = net.sf.openrocket.util.TestRockets.makeIsoHaisu();
|
||||||
Rocket r2 = net.sf.openrocket.util.TestRockets.makeBigBlue();
|
// 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");
|
||||||
|
}
|
||||||
|
|
||||||
Rocket copy = (Rocket) r2.copy();
|
@Test
|
||||||
|
public void testEstesAlphaIII(){
|
||||||
|
final double EPSILON = MathUtil.EPSILON;
|
||||||
|
Rocket rocket = TestRockets.makeEstesAlphaIII();
|
||||||
|
|
||||||
ComponentCompare.assertDeepEquality(r2, copy);
|
// String treeDump = rocket.toDebugTree();
|
||||||
|
// System.err.println(treeDump);
|
||||||
|
|
||||||
r1.copyFrom(copy);
|
AxialStage stage= (AxialStage)rocket.getChild(0);
|
||||||
|
|
||||||
ComponentCompare.assertDeepEquality(r1, r2);
|
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);
|
||||||
|
|
||||||
|
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user