Revert PR#543 -- Change causes a stack overflow while during simulation of certain rockets.
Revert "Fix 525" -- PR causes Stack Overflow when simulating other rockets.
This commit is contained in:
commit
da5dcca83d
@ -2,6 +2,7 @@ package net.sf.openrocket.aerodynamics;
|
|||||||
|
|
||||||
import static net.sf.openrocket.util.MathUtil.pow2;
|
import static net.sf.openrocket.util.MathUtil.pow2;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
@ -22,7 +23,6 @@ import net.sf.openrocket.rocketcomponent.InstanceMap;
|
|||||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.rocketcomponent.SymmetricComponent;
|
import net.sf.openrocket.rocketcomponent.SymmetricComponent;
|
||||||
import net.sf.openrocket.util.ArrayList;
|
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.MathUtil;
|
import net.sf.openrocket.util.MathUtil;
|
||||||
import net.sf.openrocket.util.PolyInterpolator;
|
import net.sf.openrocket.util.PolyInterpolator;
|
||||||
@ -96,6 +96,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
|
|||||||
// Calculate non-axial force data
|
// Calculate non-axial force data
|
||||||
AerodynamicForces total = calculateNonAxialForces(configuration, conditions, map, warnings);
|
AerodynamicForces total = calculateNonAxialForces(configuration, conditions, map, warnings);
|
||||||
|
|
||||||
|
|
||||||
// Calculate friction data
|
// Calculate friction data
|
||||||
total.setFrictionCD(calculateFrictionDrag(configuration, conditions, map, warnings));
|
total.setFrictionCD(calculateFrictionDrag(configuration, conditions, map, warnings));
|
||||||
total.setPressureCD(calculatePressureDrag(configuration, conditions, map, warnings));
|
total.setPressureCD(calculatePressureDrag(configuration, conditions, map, warnings));
|
||||||
@ -173,6 +174,7 @@ public class BarrowmanCalculator extends AbstractAerodynamicCalculator {
|
|||||||
if (calcMap == null)
|
if (calcMap == null)
|
||||||
buildCalcMap(configuration);
|
buildCalcMap(configuration);
|
||||||
|
|
||||||
|
|
||||||
if( ! isContinuous( configuration.getRocket() ) ){
|
if( ! isContinuous( configuration.getRocket() ) ){
|
||||||
warnings.add( Warning.DIAMETER_DISCONTINUITY);
|
warnings.add( Warning.DIAMETER_DISCONTINUITY);
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,24 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC
|
|||||||
separations.reset(fcid);
|
separations.reset(fcid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@inheritDoc}
|
||||||
|
* not strictly accurate, but this should provide an acceptable estimate for total vehicle size
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Collection<Coordinate> getComponentBounds() {
|
||||||
|
Collection<Coordinate> bounds = new ArrayList<Coordinate>(8);
|
||||||
|
Coordinate[] instanceLocations = this.getInstanceLocations();
|
||||||
|
double x_min = instanceLocations[0].x;
|
||||||
|
double x_max = x_min + this.length;
|
||||||
|
double r_max = 0;
|
||||||
|
|
||||||
|
addBound(bounds, x_min, r_max);
|
||||||
|
addBound(bounds, x_max, r_max);
|
||||||
|
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether the given type can be added to this component. A Stage allows
|
* Check whether the given type can be added to this component. A Stage allows
|
||||||
* only BodyComponents to be added.
|
* only BodyComponents to be added.
|
||||||
|
@ -10,7 +10,6 @@ import net.sf.openrocket.motor.MotorConfiguration;
|
|||||||
import net.sf.openrocket.motor.MotorConfigurationSet;
|
import net.sf.openrocket.motor.MotorConfigurationSet;
|
||||||
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.util.BoundingBox;
|
|
||||||
import net.sf.openrocket.util.BugException;
|
import net.sf.openrocket.util.BugException;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.MathUtil;
|
import net.sf.openrocket.util.MathUtil;
|
||||||
@ -297,7 +296,52 @@ public class BodyTube extends SymmetricComponent implements MotorMount, Coaxial
|
|||||||
private static double getFilledVolume(double r, double l) {
|
private static double getFilledVolume(double r, double l) {
|
||||||
return Math.PI * r * r * l;
|
return Math.PI * r * r * l;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds bounding coordinates to the given set. The body tube will fit within the
|
||||||
|
* convex hull of the points.
|
||||||
|
*
|
||||||
|
* Currently the points are simply a rectangular box around the body tube.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Collection<Coordinate> getComponentBounds() {
|
||||||
|
Collection<Coordinate> bounds = new ArrayList<Coordinate>(8);
|
||||||
|
double x_min_shape = 0;
|
||||||
|
double x_max_shape = this.length;
|
||||||
|
double r_max_shape = getOuterRadius();
|
||||||
|
|
||||||
|
Coordinate[] locs = this.getLocations();
|
||||||
|
// not strictly accurate, but this should provide an acceptable estimate for total vehicle size
|
||||||
|
double x_min_inst = Double.MAX_VALUE;
|
||||||
|
double x_max_inst = Double.MIN_VALUE;
|
||||||
|
double r_max_inst = 0.0;
|
||||||
|
|
||||||
|
// refactor: get component inherent bounds
|
||||||
|
for (Coordinate cur : locs) {
|
||||||
|
double x_cur = cur.x;
|
||||||
|
double r_cur = MathUtil.hypot(cur.y, cur.z);
|
||||||
|
if (x_min_inst > x_cur) {
|
||||||
|
x_min_inst = x_cur;
|
||||||
|
}
|
||||||
|
if (x_max_inst < x_cur) {
|
||||||
|
x_max_inst = x_cur;
|
||||||
|
}
|
||||||
|
if (r_cur > r_max_inst) {
|
||||||
|
r_max_inst = r_cur;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// combine the position bounds with the inherent shape bounds
|
||||||
|
double x_min = x_min_shape + x_min_inst;
|
||||||
|
double x_max = x_max_shape + x_max_inst;
|
||||||
|
double r_max = r_max_shape + r_max_inst;
|
||||||
|
|
||||||
|
addBoundingBox(bounds, x_min, x_max, r_max);
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether the given type can be added to this component. BodyTubes allow any
|
* Check whether the given type can be added to this component. BodyTubes allow any
|
||||||
* InternalComponents or ExternalComponents, excluding BodyComponents, to be added.
|
* InternalComponents or ExternalComponents, excluding BodyComponents, to be added.
|
||||||
|
@ -9,7 +9,6 @@ import org.slf4j.LoggerFactory;
|
|||||||
|
|
||||||
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
||||||
import net.sf.openrocket.rocketcomponent.position.AxialPositionable;
|
import net.sf.openrocket.rocketcomponent.position.AxialPositionable;
|
||||||
import net.sf.openrocket.util.BoundingBox;
|
|
||||||
import net.sf.openrocket.util.BugException;
|
import net.sf.openrocket.util.BugException;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
|
|
||||||
@ -47,6 +46,14 @@ public abstract class ComponentAssembly extends RocketComponent implements Axia
|
|||||||
public double getAxialOffset() {
|
public double getAxialOffset() {
|
||||||
return getAxialOffset( this.axialMethod );
|
return getAxialOffset( this.axialMethod );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Null method (ComponentAssembly has no bounds of itself).
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Collection<Coordinate> getComponentBounds() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Null method (ComponentAssembly has no mass of itself).
|
* Null method (ComponentAssembly has no mass of itself).
|
||||||
@ -100,17 +107,6 @@ public abstract class ComponentAssembly extends RocketComponent implements Axia
|
|||||||
}
|
}
|
||||||
return outerRadius;
|
return outerRadius;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* We'll find the bounding box of a component by iterating an
|
|
||||||
* InstanceMap, not by performing a treewalk of the component.
|
|
||||||
* So, anything subclassed from a ComponentAssembly will just
|
|
||||||
* return an empty bounding box
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public BoundingBox getBoundingBox() {
|
|
||||||
return new BoundingBox();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Components have no aerodynamic effect, so return false.
|
* Components have no aerodynamic effect, so return false.
|
||||||
|
@ -709,16 +709,53 @@ public abstract class FinSet extends ExternalComponent implements RingInstanceab
|
|||||||
BoundingBox singleFinBounds= new BoundingBox().update(getFinPoints());
|
BoundingBox singleFinBounds= new BoundingBox().update(getFinPoints());
|
||||||
final double finLength = singleFinBounds.max.x;
|
final double finLength = singleFinBounds.max.x;
|
||||||
final double finHeight = singleFinBounds.max.y;
|
final double finHeight = singleFinBounds.max.y;
|
||||||
|
|
||||||
/*
|
|
||||||
BoundingBox compBox = new BoundingBox().update(getComponentLocations());
|
BoundingBox compBox = new BoundingBox().update(getComponentLocations());
|
||||||
|
|
||||||
BoundingBox finSetBox = new BoundingBox( compBox.min.sub( 0, finHeight, finHeight ),
|
BoundingBox finSetBox = new BoundingBox( compBox.min.sub( 0, finHeight, finHeight ),
|
||||||
compBox.max.add( finLength, finHeight, finHeight ));
|
compBox.max.add( finLength, finHeight, finHeight ));
|
||||||
return finSetBox;
|
return finSetBox;
|
||||||
*/
|
}
|
||||||
|
|
||||||
return new BoundingBox(0.0, finLength, finHeight);
|
/**
|
||||||
|
* Adds bounding coordinates to the given set. The body tube will fit within the
|
||||||
|
* convex hull of the points.
|
||||||
|
*
|
||||||
|
* Currently the points are simply a rectangular box around the body tube.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Collection<Coordinate> getComponentBounds() {
|
||||||
|
Collection<Coordinate> bounds = new ArrayList<Coordinate>(8);
|
||||||
|
|
||||||
|
// should simply return this component's bounds in this component's body frame.
|
||||||
|
|
||||||
|
double x_min = Double.MAX_VALUE;
|
||||||
|
double x_max = Double.MIN_VALUE;
|
||||||
|
double r_max = 0.0;
|
||||||
|
|
||||||
|
for (Coordinate point : getFinPoints()) {
|
||||||
|
double hypot = MathUtil.hypot(point.y, point.z);
|
||||||
|
double x_cur = point.x;
|
||||||
|
if (x_min > x_cur) {
|
||||||
|
x_min = x_cur;
|
||||||
|
}
|
||||||
|
if (x_max < x_cur) {
|
||||||
|
x_max = x_cur;
|
||||||
|
}
|
||||||
|
if (r_max < hypot) {
|
||||||
|
r_max = hypot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Coordinate location = this.getLocations()[0];
|
||||||
|
x_max += location.x;
|
||||||
|
|
||||||
|
if( parent instanceof SymmetricComponent){
|
||||||
|
r_max += ((SymmetricComponent)parent).getRadius(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
addBoundingBox(bounds, x_min, x_max, r_max);
|
||||||
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -63,7 +63,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
final protected HashMap<MotorConfigurationId, MotorConfiguration> motors = new HashMap<MotorConfigurationId, MotorConfiguration>();
|
final protected HashMap<MotorConfigurationId, MotorConfiguration> motors = new HashMap<MotorConfigurationId, MotorConfiguration>();
|
||||||
|
|
||||||
private int boundsModID = -1;
|
private int boundsModID = -1;
|
||||||
private BoundingBox cachedBoundingBox = new BoundingBox();
|
private BoundingBox cachedBounds = new BoundingBox();
|
||||||
private double cachedLength = -1;
|
private double cachedLength = -1;
|
||||||
|
|
||||||
private int refLengthModID = -1;
|
private int refLengthModID = -1;
|
||||||
@ -501,6 +501,18 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
return isComponentActive( (RocketComponent) c);
|
return isComponentActive( (RocketComponent) c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the bounds of the current configuration. The bounds are cached.
|
||||||
|
*
|
||||||
|
* @return a <code>Collection</code> containing coordinates bounding the rocket.
|
||||||
|
*
|
||||||
|
* @deprecated Migrate to <FlightConfiguration>.getBoundingBox(), when practical.
|
||||||
|
*/
|
||||||
|
@Deprecated
|
||||||
|
public Collection<Coordinate> getBounds() {
|
||||||
|
return getBoundingBox().toCollection();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the bounding box of the current configuration.
|
* Return the bounding box of the current configuration.
|
||||||
*
|
*
|
||||||
@ -508,34 +520,22 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
*/
|
*/
|
||||||
public BoundingBox getBoundingBox() {
|
public BoundingBox getBoundingBox() {
|
||||||
if (rocket.getModID() != boundsModID) {
|
if (rocket.getModID() != boundsModID) {
|
||||||
calculateBoundingBox();
|
calculateBounds();
|
||||||
}
|
}
|
||||||
return cachedBoundingBox;
|
return cachedBounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void calculateBoundingBox(){
|
private void calculateBounds(){
|
||||||
BoundingBox bounds = new BoundingBox();
|
BoundingBox bounds = new BoundingBox();
|
||||||
|
|
||||||
// iterate through all components
|
for (RocketComponent component : this.getActiveComponents()) {
|
||||||
final InstanceMap imap = this.getActiveInstances();
|
BoundingBox componentBounds = new BoundingBox().update(component.getComponentBounds());
|
||||||
for(Map.Entry<RocketComponent, ArrayList<InstanceContext>> entry: imap.entrySet() ) {
|
bounds.update( componentBounds );
|
||||||
final RocketComponent comp = entry.getKey();
|
|
||||||
if (this.isComponentActive(comp)) {
|
|
||||||
|
|
||||||
// iterate across all componenent instances
|
|
||||||
final ArrayList<InstanceContext> contextList = entry.getValue();
|
|
||||||
|
|
||||||
for(InstanceContext context: contextList ) {
|
|
||||||
BoundingBox instanceBox = new BoundingBox(context.transform.transform(comp.getBoundingBox().min),
|
|
||||||
context.transform.transform(comp.getBoundingBox().max));
|
|
||||||
bounds.update(instanceBox);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
boundsModID = rocket.getModID();
|
boundsModID = rocket.getModID();
|
||||||
cachedLength = bounds.span().x;
|
cachedLength = bounds.span().x;
|
||||||
cachedBoundingBox.update( bounds );
|
cachedBounds.update( bounds );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -546,7 +546,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
*/
|
*/
|
||||||
public double getLength() {
|
public double getLength() {
|
||||||
if (rocket.getModID() != boundsModID) {
|
if (rocket.getModID() != boundsModID) {
|
||||||
calculateBoundingBox();
|
calculateBounds();
|
||||||
}
|
}
|
||||||
return cachedLength;
|
return cachedLength;
|
||||||
}
|
}
|
||||||
@ -567,7 +567,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
FlightConfiguration clone = new FlightConfiguration( this.rocket, this.fcid );
|
FlightConfiguration clone = new FlightConfiguration( this.rocket, this.fcid );
|
||||||
clone.setName(configurationName);
|
clone.setName(configurationName);
|
||||||
|
|
||||||
clone.cachedBoundingBox = this.cachedBoundingBox.clone();
|
clone.cachedBounds = this.cachedBounds.clone();
|
||||||
clone.modID = this.modID;
|
clone.modID = this.modID;
|
||||||
clone.boundsModID = -1;
|
clone.boundsModID = -1;
|
||||||
clone.refLengthModID = -1;
|
clone.refLengthModID = -1;
|
||||||
@ -594,7 +594,7 @@ public class FlightConfiguration implements FlightConfigurableParameter<FlightCo
|
|||||||
cloneMotor.getMount().setMotorConfig(cloneMotor, copyId);
|
cloneMotor.getMount().setMotorConfig(cloneMotor, copyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
copy.cachedBoundingBox = this.cachedBoundingBox.clone();
|
copy.cachedBounds = this.cachedBounds.clone();
|
||||||
copy.modID = this.modID;
|
copy.modID = this.modID;
|
||||||
copy.boundsModID = -1;
|
copy.boundsModID = -1;
|
||||||
copy.refLengthModID = -1;
|
copy.refLengthModID = -1;
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package net.sf.openrocket.rocketcomponent;
|
package net.sf.openrocket.rocketcomponent;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import net.sf.openrocket.util.ArrayList;
|
|
||||||
import net.sf.openrocket.util.Transformation;
|
import net.sf.openrocket.util.Transformation;
|
||||||
|
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ package net.sf.openrocket.rocketcomponent;
|
|||||||
|
|
||||||
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
||||||
import net.sf.openrocket.rocketcomponent.position.AxialPositionable;
|
import net.sf.openrocket.rocketcomponent.position.AxialPositionable;
|
||||||
import net.sf.openrocket.util.BoundingBox;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A component internal to the rocket. Internal components have no effect on the
|
* A component internal to the rocket. Internal components have no effect on the
|
||||||
@ -36,15 +35,6 @@ public abstract class InternalComponent extends RocketComponent implements Axial
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* An internal component can't extend beyond the bounding box established by external components
|
|
||||||
* Return an empty bounding box to simplify methods calling us.
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public BoundingBox getBoundingBox() {
|
|
||||||
return new BoundingBox();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is massive.
|
* Is massive.
|
||||||
* @return <code>true</code>
|
* @return <code>true</code>
|
||||||
|
@ -8,7 +8,6 @@ import net.sf.openrocket.preset.ComponentPreset;
|
|||||||
import net.sf.openrocket.preset.ComponentPreset.Type;
|
import net.sf.openrocket.preset.ComponentPreset.Type;
|
||||||
import net.sf.openrocket.rocketcomponent.position.*;
|
import net.sf.openrocket.rocketcomponent.position.*;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.util.BoundingBox;
|
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.MathUtil;
|
import net.sf.openrocket.util.MathUtil;
|
||||||
|
|
||||||
@ -187,10 +186,13 @@ public class LaunchLug extends ExternalComponent implements AnglePositionable, C
|
|||||||
public double getComponentVolume() {
|
public double getComponentVolume() {
|
||||||
return length * Math.PI * (MathUtil.pow2(radius) - MathUtil.pow2(radius - thickness));
|
return length * Math.PI * (MathUtil.pow2(radius) - MathUtil.pow2(radius - thickness));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BoundingBox getBoundingBox() {
|
public Collection<Coordinate> getComponentBounds() {
|
||||||
return new BoundingBox(0, length, radius);
|
ArrayList<Coordinate> set = new ArrayList<Coordinate>();
|
||||||
|
addBound(set, 0, radius);
|
||||||
|
addBound(set, length, radius);
|
||||||
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -133,4 +133,13 @@ public abstract class MassObject extends InternalComponent {
|
|||||||
public final double getRotationalUnitInertia() {
|
public final double getRotationalUnitInertia() {
|
||||||
return pow2(radius) / 2;
|
return pow2(radius) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public final Collection<Coordinate> getComponentBounds() {
|
||||||
|
Collection<Coordinate> c = new ArrayList<Coordinate>();
|
||||||
|
addBound(c, 0, radius);
|
||||||
|
addBound(c, length, radius);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,33 @@ public class ParallelStage extends AxialStage implements FlightConfigurableCompo
|
|||||||
return trans.get("BoosterSet.BoosterSet");
|
return trans.get("BoosterSet.BoosterSet");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// not strictly accurate, but this should provide an acceptable estimate for total vehicle size
|
||||||
|
@Override
|
||||||
|
public Collection<Coordinate> getComponentBounds() {
|
||||||
|
Collection<Coordinate> bounds = new ArrayList<Coordinate>(8);
|
||||||
|
double x_min = Double.MAX_VALUE;
|
||||||
|
double x_max = Double.MIN_VALUE;
|
||||||
|
double r_max = 0;
|
||||||
|
|
||||||
|
Coordinate[] instanceLocations = this.getComponentLocations();
|
||||||
|
|
||||||
|
for (Coordinate currentInstanceLocation : instanceLocations) {
|
||||||
|
if (x_min > (currentInstanceLocation.x)) {
|
||||||
|
x_min = currentInstanceLocation.x;
|
||||||
|
}
|
||||||
|
if (x_max < (currentInstanceLocation.x + this.length)) {
|
||||||
|
x_max = currentInstanceLocation.x + this.length;
|
||||||
|
}
|
||||||
|
if (r_max < (this.getRadiusOffset())) {
|
||||||
|
r_max = this.getRadiusOffset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addBound(bounds, x_min, r_max);
|
||||||
|
addBound(bounds, x_max, r_max);
|
||||||
|
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether the given type can be added to this component. A Stage allows
|
* Check whether the given type can be added to this component. A Stage allows
|
||||||
* only BodyComponents to be added.
|
* only BodyComponents to be added.
|
||||||
|
@ -45,6 +45,33 @@ public class PodSet extends ComponentAssembly implements RingInstanceable {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// not strictly accurate, but this should provide an acceptable estimate for total vehicle size
|
||||||
|
@Override
|
||||||
|
public Collection<Coordinate> getComponentBounds() {
|
||||||
|
Collection<Coordinate> bounds = new ArrayList<Coordinate>(8);
|
||||||
|
double x_min = Double.MAX_VALUE;
|
||||||
|
double x_max = Double.MIN_VALUE;
|
||||||
|
double r_max = 0;
|
||||||
|
|
||||||
|
Coordinate[] instanceLocations = this.getComponentLocations();
|
||||||
|
|
||||||
|
for (Coordinate currentInstanceLocation : instanceLocations) {
|
||||||
|
if (x_min > (currentInstanceLocation.x)) {
|
||||||
|
x_min = currentInstanceLocation.x;
|
||||||
|
}
|
||||||
|
if (x_max < (currentInstanceLocation.x + this.length)) {
|
||||||
|
x_max = currentInstanceLocation.x + this.length;
|
||||||
|
}
|
||||||
|
if (r_max < (this.getRadiusOffset())) {
|
||||||
|
r_max = this.getRadiusOffset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addBound(bounds, x_min, r_max);
|
||||||
|
addBound(bounds, x_max, r_max);
|
||||||
|
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether the given type can be added to this component. A Stage allows
|
* Check whether the given type can be added to this component. A Stage allows
|
||||||
* only BodyComponents to be added.
|
* only BodyComponents to be added.
|
||||||
|
@ -11,7 +11,6 @@ import net.sf.openrocket.rocketcomponent.position.AnglePositionable;
|
|||||||
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
||||||
import net.sf.openrocket.rocketcomponent.position.AxialPositionable;
|
import net.sf.openrocket.rocketcomponent.position.AxialPositionable;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.util.BoundingBox;
|
|
||||||
import net.sf.openrocket.util.BugException;
|
import net.sf.openrocket.util.BugException;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.MathUtil;
|
import net.sf.openrocket.util.MathUtil;
|
||||||
@ -233,13 +232,6 @@ public class RailButton extends ExternalComponent implements AnglePositionable,
|
|||||||
public Type getPresetType() {
|
public Type getPresetType() {
|
||||||
return ComponentPreset.Type.RAIL_BUTTON;
|
return ComponentPreset.Type.RAIL_BUTTON;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public BoundingBox getBoundingBox() {
|
|
||||||
final double r = outerDiameter_m / 2.0;
|
|
||||||
return new BoundingBox(new Coordinate(-r, -r, 0),
|
|
||||||
new Coordinate(r, r, totalHeight_m));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void componentChanged(ComponentChangeEvent e) {
|
public void componentChanged(ComponentChangeEvent e) {
|
||||||
@ -295,6 +287,21 @@ public class RailButton extends ExternalComponent implements AnglePositionable,
|
|||||||
public String getPatternName(){
|
public String getPatternName(){
|
||||||
return (this.getInstanceCount() + "-Line");
|
return (this.getInstanceCount() + "-Line");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Coordinate> getComponentBounds() {
|
||||||
|
final double r = outerDiameter_m / 2.0;
|
||||||
|
ArrayList<Coordinate> set = new ArrayList<Coordinate>();
|
||||||
|
set.add(new Coordinate(r, totalHeight_m, r));
|
||||||
|
set.add(new Coordinate(r, totalHeight_m, -r));
|
||||||
|
set.add(new Coordinate(r, 0, r));
|
||||||
|
set.add(new Coordinate(r, 0, -r));
|
||||||
|
set.add(new Coordinate(-r, 0, r));
|
||||||
|
set.add(new Coordinate(-r, 0, -r));
|
||||||
|
set.add(new Coordinate(-r, totalHeight_m, r));
|
||||||
|
set.add(new Coordinate(-r, totalHeight_m, -r));
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Coordinate getComponentCG() {
|
public Coordinate getComponentCG() {
|
||||||
|
@ -162,6 +162,14 @@ public abstract class RingComponent extends StructuralComponent implements Coaxi
|
|||||||
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<Coordinate> getComponentBounds() {
|
||||||
|
List<Coordinate> bounds = new ArrayList<Coordinate>();
|
||||||
|
addBound(bounds, 0, getOuterRadius());
|
||||||
|
addBound(bounds, length, getOuterRadius());
|
||||||
|
return bounds;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Coordinate getComponentCG() {
|
public Coordinate getComponentCG() {
|
||||||
Coordinate cg = Coordinate.ZERO;
|
Coordinate cg = Coordinate.ZERO;
|
||||||
@ -187,6 +195,7 @@ public abstract class RingComponent extends StructuralComponent implements Coaxi
|
|||||||
getMaterial().getDensity()) * getInstanceCount();
|
getMaterial().getDensity()) * getInstanceCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public double getLongitudinalUnitInertia() {
|
public double getLongitudinalUnitInertia() {
|
||||||
return ringLongitudinalUnitInertia(getOuterRadius(), getInnerRadius(), getLength());
|
return ringLongitudinalUnitInertia(getOuterRadius(), getInnerRadius(), getLength());
|
||||||
|
@ -19,7 +19,6 @@ import net.sf.openrocket.preset.ComponentPreset;
|
|||||||
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
||||||
import net.sf.openrocket.rocketcomponent.position.RadiusMethod;
|
import net.sf.openrocket.rocketcomponent.position.RadiusMethod;
|
||||||
import net.sf.openrocket.util.ArrayList;
|
import net.sf.openrocket.util.ArrayList;
|
||||||
import net.sf.openrocket.util.BoundingBox;
|
|
||||||
import net.sf.openrocket.util.BugException;
|
import net.sf.openrocket.util.BugException;
|
||||||
import net.sf.openrocket.util.ChangeSource;
|
import net.sf.openrocket.util.ChangeSource;
|
||||||
import net.sf.openrocket.util.Color;
|
import net.sf.openrocket.util.Color;
|
||||||
@ -223,13 +222,14 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return bounding box of component.
|
* Return a collection of bounding coordinates. The coordinates must be such that
|
||||||
|
* the component is fully enclosed in their convex hull.
|
||||||
*
|
*
|
||||||
* Note: this function gets the bounds only for this component. Subchildren must be called individually.
|
* Note: this function gets the bounds only for this component. Subchildren must be called individually.
|
||||||
*
|
*
|
||||||
* @return a collection of coordinates that bound the component.
|
* @return a collection of coordinates that bound the component.
|
||||||
*/
|
*/
|
||||||
public abstract BoundingBox getBoundingBox();
|
public abstract Collection<Coordinate> getComponentBounds();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return true if the component may have an aerodynamic effect on the rocket.
|
* Return true if the component may have an aerodynamic effect on the rocket.
|
||||||
@ -1902,9 +1902,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper method to add two points on opposite corners of a box
|
* Helper method to add two points on opposite corners of a box around the rocket centerline. This box will be (x_max - x_min) long, and 2*r wide/high.
|
||||||
* around the component centerline. This box will be (x_max -
|
|
||||||
* x_min) long, and 2*r wide/high.
|
|
||||||
*/
|
*/
|
||||||
protected static final void addBoundingBox(Collection<Coordinate> bounds, double x_min, double x_max, double r) {
|
protected static final void addBoundingBox(Collection<Coordinate> bounds, double x_min, double x_max, double r) {
|
||||||
bounds.add(new Coordinate(x_min, -r, -r));
|
bounds.add(new Coordinate(x_min, -r, -r));
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
// this class is only used by the Android application
|
|
||||||
package net.sf.openrocket.rocketcomponent;
|
package net.sf.openrocket.rocketcomponent;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@ -8,6 +7,20 @@ import net.sf.openrocket.util.Coordinate;
|
|||||||
public abstract class RocketUtils {
|
public abstract class RocketUtils {
|
||||||
|
|
||||||
public static double getLength(Rocket rocket) {
|
public static double getLength(Rocket rocket) {
|
||||||
return rocket.getSelectedConfiguration().getLength();
|
double length = 0;
|
||||||
|
Collection<Coordinate> bounds = rocket.getSelectedConfiguration().getBounds();
|
||||||
|
if (!bounds.isEmpty()) {
|
||||||
|
double minX = Double.POSITIVE_INFINITY, maxX = Double.NEGATIVE_INFINITY;
|
||||||
|
for (Coordinate c : bounds) {
|
||||||
|
if (c.x < minX)
|
||||||
|
minX = c.x;
|
||||||
|
if (c.x > maxX)
|
||||||
|
maxX = c.x;
|
||||||
|
}
|
||||||
|
length = maxX - minX;
|
||||||
|
}
|
||||||
|
return length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package net.sf.openrocket.rocketcomponent;
|
|||||||
|
|
||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.util.BoundingBox;
|
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.MathUtil;
|
import net.sf.openrocket.util.MathUtil;
|
||||||
|
|
||||||
@ -83,6 +82,9 @@ public class Sleeve extends RingComponent {
|
|||||||
thickness = t;
|
thickness = t;
|
||||||
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setInnerRadiusAutomatic(boolean auto) {
|
public void setInnerRadiusAutomatic(boolean auto) {
|
||||||
|
@ -8,7 +8,6 @@ import java.util.List;
|
|||||||
|
|
||||||
import net.sf.openrocket.preset.ComponentPreset;
|
import net.sf.openrocket.preset.ComponentPreset;
|
||||||
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
||||||
import net.sf.openrocket.util.BoundingBox;
|
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.MathUtil;
|
import net.sf.openrocket.util.MathUtil;
|
||||||
|
|
||||||
@ -134,17 +133,24 @@ public abstract class SymmetricComponent extends BodyComponent implements Radial
|
|||||||
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
||||||
clearPreset();
|
clearPreset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Are there any components whose max diameter isn't at either the
|
* Adds component bounds at a number of points between 0...length.
|
||||||
* fore or aft end? I don't know of any.
|
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public BoundingBox getBoundingBox() {
|
public Collection<Coordinate> getComponentBounds() {
|
||||||
return new BoundingBox(0, getLength(),
|
List<Coordinate> list = new ArrayList<Coordinate>(20);
|
||||||
Math.max(getForeRadius(), getAftRadius()));
|
for (int n = 0; n <= 5; n++) {
|
||||||
|
double x = n * length / 5;
|
||||||
|
double r = getRadius(x);
|
||||||
|
addBound(list, x, r);
|
||||||
|
}
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void loadFromPreset(ComponentPreset preset) {
|
protected void loadFromPreset(ComponentPreset preset) {
|
||||||
if ( preset.has(ComponentPreset.THICKNESS) ) {
|
if ( preset.has(ComponentPreset.THICKNESS) ) {
|
||||||
|
@ -10,7 +10,6 @@ import net.sf.openrocket.l10n.Translator;
|
|||||||
import net.sf.openrocket.preset.ComponentPreset;
|
import net.sf.openrocket.preset.ComponentPreset;
|
||||||
import net.sf.openrocket.preset.ComponentPreset.Type;
|
import net.sf.openrocket.preset.ComponentPreset.Type;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.util.BoundingBox;
|
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.MathUtil;
|
import net.sf.openrocket.util.MathUtil;
|
||||||
|
|
||||||
@ -434,22 +433,16 @@ public class Transition extends SymmetricComponent {
|
|||||||
return Math.max(getRadius(x) - thickness, 0);
|
return Math.max(getRadius(x) - thickness, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* bounding box of transition
|
|
||||||
*
|
|
||||||
* It's tempting to ignore the shoulders (if any) on the grounds
|
|
||||||
* that they will be covered by the fore and aft body tubes, but
|
|
||||||
* including them won't cause any errors
|
|
||||||
*
|
|
||||||
* we will assume the maximum radius will occur at either the fore
|
|
||||||
* or aft end -- this is true for the transitions that are
|
|
||||||
* currently allowed, but could conceivably change in the future
|
|
||||||
*/
|
|
||||||
@Override
|
@Override
|
||||||
public BoundingBox getBoundingBox() {
|
public Collection<Coordinate> getComponentBounds() {
|
||||||
return new BoundingBox(-getForeShoulderLength(),
|
Collection<Coordinate> bounds = super.getComponentBounds();
|
||||||
getLength() + getAftShoulderLength(),
|
if (foreShoulderLength > 0.001)
|
||||||
Math.max(getForeRadius(), getAftRadius()));
|
addBound(bounds, -foreShoulderLength, foreShoulderRadius);
|
||||||
|
if (aftShoulderLength > 0.001)
|
||||||
|
addBound(bounds, getLength() + aftShoulderLength, aftShoulderRadius);
|
||||||
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -10,7 +10,6 @@ import net.sf.openrocket.preset.ComponentPreset.Type;
|
|||||||
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
import net.sf.openrocket.rocketcomponent.position.AxialMethod;
|
||||||
import net.sf.openrocket.rocketcomponent.position.AxialPositionable;
|
import net.sf.openrocket.rocketcomponent.position.AxialPositionable;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.util.BoundingBox;
|
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.MathUtil;
|
import net.sf.openrocket.util.MathUtil;
|
||||||
import net.sf.openrocket.util.Transformation;
|
import net.sf.openrocket.util.Transformation;
|
||||||
@ -305,10 +304,16 @@ public class TubeFinSet extends ExternalComponent implements AxialPositionable {
|
|||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BoundingBox getBoundingBox() {
|
public Collection<Coordinate> getComponentBounds() {
|
||||||
return new BoundingBox(0, length, outerRadius);
|
List<Coordinate> bounds = new ArrayList<Coordinate>();
|
||||||
|
double r = getBodyRadius();
|
||||||
|
|
||||||
|
addBound(bounds, 0, 2 * (r + outerRadius));
|
||||||
|
addBound(bounds, length, 2 * (r + outerRadius));
|
||||||
|
|
||||||
|
return bounds;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -130,7 +130,11 @@ public class SimulationStatus implements Monitorable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!Double.isNaN(lugPosition)) {
|
if (!Double.isNaN(lugPosition)) {
|
||||||
double maxX = this.configuration.getBoundingBox().max.x;
|
double maxX = 0;
|
||||||
|
for (Coordinate c : this.configuration.getBounds()) {
|
||||||
|
if (c.x > maxX)
|
||||||
|
maxX = c.x;
|
||||||
|
}
|
||||||
if (maxX >= lugPosition) {
|
if (maxX >= lugPosition) {
|
||||||
length = Math.max(0, length - (maxX - lugPosition));
|
length = Math.max(0, length - (maxX - lugPosition));
|
||||||
}
|
}
|
||||||
|
@ -17,11 +17,6 @@ public class BoundingBox {
|
|||||||
this.min = _min.clone();
|
this.min = _min.clone();
|
||||||
this.max = _max.clone();
|
this.max = _max.clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
public BoundingBox(double xmin, double xmax, double rad) {
|
|
||||||
min = new Coordinate(xmin, -rad, -rad);
|
|
||||||
max = new Coordinate(xmax, rad, rad);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
min = Coordinate.MAX.setWeight( 0.0);
|
min = Coordinate.MAX.setWeight( 0.0);
|
||||||
@ -118,14 +113,8 @@ public class BoundingBox {
|
|||||||
update_z_max(other.max.z);
|
update_z_max(other.max.z);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Coordinate span() {
|
public Coordinate span() { return max.sub( min ); }
|
||||||
Coordinate tmp = max.sub( min );
|
|
||||||
return new Coordinate(Math.max(tmp.x, 0.0),
|
|
||||||
Math.max(tmp.y, 0.0),
|
|
||||||
Math.max(tmp.z, 0.0),
|
|
||||||
Math.max(tmp.weight, 0.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
public Coordinate[] toArray() {
|
public Coordinate[] toArray() {
|
||||||
return new Coordinate[] { this.min, this.max };
|
return new Coordinate[] { this.min, this.max };
|
||||||
|
1
openrocket.log
Normal file
1
openrocket.log
Normal file
@ -0,0 +1 @@
|
|||||||
|
Error: Unable to access jarfile OpenRocket.jar
|
@ -49,7 +49,6 @@ import net.sf.openrocket.rocketcomponent.Rocket;
|
|||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.startup.Preferences;
|
import net.sf.openrocket.startup.Preferences;
|
||||||
import net.sf.openrocket.util.BoundingBox;
|
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.MathUtil;
|
import net.sf.openrocket.util.MathUtil;
|
||||||
|
|
||||||
@ -469,21 +468,64 @@ public class RocketFigure3d extends JPanel implements GLEventListener {
|
|||||||
redrawExtras = true;
|
redrawExtras = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private static class Bounds {
|
||||||
|
double xMin, xMax, xSize;
|
||||||
|
double yMin, yMax, ySize;
|
||||||
|
double zMin, zMax, zSize;
|
||||||
|
double rMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bounds cachedBounds = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the bounds for the current configuration
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Bounds calculateBounds() {
|
||||||
|
if (cachedBounds != null) {
|
||||||
|
return cachedBounds;
|
||||||
|
} else {
|
||||||
|
final Bounds b = new Bounds();
|
||||||
|
final FlightConfiguration configuration = rkt.getSelectedConfiguration();
|
||||||
|
final Collection<Coordinate> bounds = configuration.getBounds();
|
||||||
|
for (Coordinate c : bounds) {
|
||||||
|
b.xMax = Math.max(b.xMax, c.x);
|
||||||
|
b.xMin = Math.min(b.xMin, c.x);
|
||||||
|
|
||||||
|
b.yMax = Math.max(b.yMax, c.y);
|
||||||
|
b.yMin = Math.min(b.yMin, c.y);
|
||||||
|
|
||||||
|
b.zMax = Math.max(b.zMax, c.z);
|
||||||
|
b.zMin = Math.min(b.zMin, c.z);
|
||||||
|
|
||||||
|
double r = MathUtil.hypot(c.y, c.z);
|
||||||
|
b.rMax = Math.max(b.rMax, r);
|
||||||
|
}
|
||||||
|
b.xSize = b.xMax - b.xMin;
|
||||||
|
b.ySize = b.yMax - b.yMin;
|
||||||
|
b.zSize = b.zMax - b.zMin;
|
||||||
|
cachedBounds = b;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void setupView(final GL2 gl, final GLU glu) {
|
private void setupView(final GL2 gl, final GLU glu) {
|
||||||
gl.glLoadIdentity();
|
gl.glLoadIdentity();
|
||||||
|
|
||||||
gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_POSITION,
|
gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_POSITION,
|
||||||
lightPosition, 0);
|
lightPosition, 0);
|
||||||
|
|
||||||
// Get the bounding box
|
// Get the bounds
|
||||||
final BoundingBox b = rkt.getSelectedConfiguration().getBoundingBox();
|
final Bounds b = calculateBounds();
|
||||||
|
|
||||||
// Calculate the distance needed to fit the bounds in both the X and Y
|
// Calculate the distance needed to fit the bounds in both the X and Y
|
||||||
// direction
|
// direction
|
||||||
// Add 10% for space around it.
|
// Add 10% for space around it.
|
||||||
final double dX = (b.max.x * 1.2 / 2.0)
|
final double dX = (b.xSize * 1.2 / 2.0)
|
||||||
/ Math.tan(Math.toRadians(fovX / 2.0));
|
/ Math.tan(Math.toRadians(fovX / 2.0));
|
||||||
final double dY = (b.max.y * 2.0 * 1.2 / 2.0)
|
final double dY = (b.rMax * 2.0 * 1.2 / 2.0)
|
||||||
/ Math.tan(Math.toRadians(fovY / 2.0));
|
/ Math.tan(Math.toRadians(fovY / 2.0));
|
||||||
|
|
||||||
// Move back the greater of the 2 distances
|
// Move back the greater of the 2 distances
|
||||||
@ -493,8 +535,7 @@ public class RocketFigure3d extends JPanel implements GLEventListener {
|
|||||||
gl.glRotated(roll * (180.0 / Math.PI), 1, 0, 0);
|
gl.glRotated(roll * (180.0 / Math.PI), 1, 0, 0);
|
||||||
|
|
||||||
// Center the rocket in the view.
|
// Center the rocket in the view.
|
||||||
// gl.glTranslated(-b.xMin - b.xSize / 2.0, 0, 0);
|
gl.glTranslated(-b.xMin - b.xSize / 2.0, 0, 0);
|
||||||
gl.glTranslated((b.min.x - b.max.x) / 2.0, 0, 0);
|
|
||||||
|
|
||||||
//Change to LEFT Handed coordinates
|
//Change to LEFT Handed coordinates
|
||||||
gl.glScaled(1, 1, -1);
|
gl.glScaled(1, 1, -1);
|
||||||
@ -513,6 +554,7 @@ public class RocketFigure3d extends JPanel implements GLEventListener {
|
|||||||
*/
|
*/
|
||||||
public void updateFigure() {
|
public void updateFigure() {
|
||||||
log.debug("3D Figure Updated");
|
log.debug("3D Figure Updated");
|
||||||
|
cachedBounds = null;
|
||||||
if (canvas != null) {
|
if (canvas != null) {
|
||||||
((GLAutoDrawable) canvas).invoke(true, new GLRunnable() {
|
((GLAutoDrawable) canvas).invoke(true, new GLRunnable() {
|
||||||
@Override
|
@Override
|
||||||
|
@ -2,6 +2,7 @@ package net.sf.openrocket.gui.figure3d;
|
|||||||
|
|
||||||
import java.awt.Point;
|
import java.awt.Point;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -27,7 +28,6 @@ import net.sf.openrocket.rocketcomponent.InstanceContext;
|
|||||||
import net.sf.openrocket.rocketcomponent.InstanceMap;
|
import net.sf.openrocket.rocketcomponent.InstanceMap;
|
||||||
import net.sf.openrocket.rocketcomponent.MotorMount;
|
import net.sf.openrocket.rocketcomponent.MotorMount;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.util.ArrayList;
|
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.Transformation;
|
import net.sf.openrocket.util.Transformation;
|
||||||
|
|
||||||
|
@ -25,7 +25,6 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
|
|||||||
import net.sf.openrocket.rocketcomponent.Transition;
|
import net.sf.openrocket.rocketcomponent.Transition;
|
||||||
import net.sf.openrocket.rocketcomponent.Transition.Shape;
|
import net.sf.openrocket.rocketcomponent.Transition.Shape;
|
||||||
import net.sf.openrocket.rocketcomponent.TubeFinSet;
|
import net.sf.openrocket.rocketcomponent.TubeFinSet;
|
||||||
import net.sf.openrocket.util.BoundingBox;
|
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.Transformation;
|
import net.sf.openrocket.util.Transformation;
|
||||||
|
|
||||||
@ -122,57 +121,12 @@ public class ComponentRenderer {
|
|||||||
} else if ( c instanceof ParallelStage ) {
|
} else if ( c instanceof ParallelStage ) {
|
||||||
} else if ( c instanceof PodSet ) {
|
} else if ( c instanceof PodSet ) {
|
||||||
} else {
|
} else {
|
||||||
renderBoundingBox(gl, c);
|
renderOther(gl, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* If I don't have a method to render an object, I'll render its bounding box
|
|
||||||
*/
|
|
||||||
private void renderBoundingBox(GL2 gl, RocketComponent c) {
|
|
||||||
BoundingBox box = c.getBoundingBox();
|
|
||||||
|
|
||||||
// rectangle at forward end
|
|
||||||
gl.glBegin(GL.GL_LINES);
|
|
||||||
gl.glVertex3d(box.min.x, box.min.y, box.min.z);
|
|
||||||
gl.glVertex3d(box.min.x, box.max.y, box.min.z);
|
|
||||||
gl.glVertex3d(box.min.x, box.max.y, box.max.z);
|
|
||||||
gl.glVertex3d(box.min.x, box.max.x, box.min.z);
|
|
||||||
gl.glEnd();
|
|
||||||
|
|
||||||
// rectangle at aft end
|
|
||||||
gl.glBegin(GL.GL_LINES);
|
|
||||||
gl.glVertex3d(box.max.x, box.min.y, box.min.z);
|
|
||||||
gl.glVertex3d(box.max.x, box.max.y, box.min.z);
|
|
||||||
gl.glVertex3d(box.max.x, box.max.y, box.max.z);
|
|
||||||
gl.glVertex3d(box.max.x, box.max.x, box.min.z);
|
|
||||||
gl.glEnd();
|
|
||||||
|
|
||||||
// connect forward and aft rectangles
|
|
||||||
gl.glBegin(GL.GL_LINES);
|
|
||||||
gl.glVertex3d(box.min.x, box.min.y, box.min.z);
|
|
||||||
gl.glVertex3d(box.max.x, box.min.y, box.min.z);
|
|
||||||
gl.glEnd();
|
|
||||||
|
|
||||||
gl.glBegin(GL.GL_LINES);
|
|
||||||
gl.glVertex3d(box.min.x, box.max.y, box.min.z);
|
|
||||||
gl.glVertex3d(box.max.x, box.max.y, box.min.z);
|
|
||||||
gl.glEnd();
|
|
||||||
|
|
||||||
gl.glBegin(GL.GL_LINES);
|
|
||||||
gl.glVertex3d(box.min.x, box.min.y, box.max.z);
|
|
||||||
gl.glVertex3d(box.max.x, box.min.y, box.max.z);
|
|
||||||
gl.glEnd();
|
|
||||||
|
|
||||||
gl.glBegin(GL.GL_LINES);
|
|
||||||
gl.glVertex3d(box.min.x, box.max.y, box.max.z);
|
|
||||||
gl.glVertex3d(box.max.x, box.max.y, box.max.z);
|
|
||||||
gl.glEnd();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
private void renderOther(GL2 gl, RocketComponent c) {
|
private void renderOther(GL2 gl, RocketComponent c) {
|
||||||
gl.glBegin(GL.GL_LINES);
|
gl.glBegin(GL.GL_LINES);
|
||||||
for (Coordinate cc : c.getComponentBounds()) {
|
for (Coordinate cc : c.getComponentBounds()) {
|
||||||
@ -183,7 +137,7 @@ public class ComponentRenderer {
|
|||||||
}
|
}
|
||||||
gl.glEnd();
|
gl.glEnd();
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
private void renderTransition(GL2 gl, Transition t, Surface which) {
|
private void renderTransition(GL2 gl, Transition t, Surface which) {
|
||||||
|
|
||||||
if (which == Surface.OUTSIDE || which == Surface.INSIDE) {
|
if (which == Surface.OUTSIDE || which == Surface.INSIDE) {
|
||||||
|
@ -52,7 +52,6 @@ import net.sf.openrocket.rocketcomponent.MotorMount;
|
|||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.startup.Preferences;
|
import net.sf.openrocket.startup.Preferences;
|
||||||
import net.sf.openrocket.util.BoundingBox;
|
|
||||||
import net.sf.openrocket.util.Color;
|
import net.sf.openrocket.util.Color;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.MathUtil;
|
import net.sf.openrocket.util.MathUtil;
|
||||||
@ -93,6 +92,7 @@ public class PhotoPanel extends JPanel implements GLEventListener {
|
|||||||
@Override
|
@Override
|
||||||
public boolean run(final GLAutoDrawable drawable) {
|
public boolean run(final GLAutoDrawable drawable) {
|
||||||
PhotoPanel.this.configuration = doc.getSelectedConfiguration();
|
PhotoPanel.this.configuration = doc.getSelectedConfiguration();
|
||||||
|
cachedBounds = null;
|
||||||
rr = new RealisticRenderer(doc);
|
rr = new RealisticRenderer(doc);
|
||||||
rr.init(drawable);
|
rr.init(drawable);
|
||||||
|
|
||||||
@ -246,11 +246,11 @@ public class PhotoPanel extends JPanel implements GLEventListener {
|
|||||||
draw(drawable, 0);
|
draw(drawable, 0);
|
||||||
|
|
||||||
if (p.isMotionBlurred()) {
|
if (p.isMotionBlurred()) {
|
||||||
BoundingBox b = configuration.getBoundingBox();
|
Bounds b = calculateBounds();
|
||||||
|
|
||||||
float m = .6f;
|
float m = .6f;
|
||||||
int c = 10;
|
int c = 10;
|
||||||
float d = (float) (b.max.x - b.min.x) / 25.0f;
|
float d = (float) b.xSize / 25.0f;
|
||||||
|
|
||||||
gl.glAccum(GL2.GL_LOAD, m);
|
gl.glAccum(GL2.GL_LOAD, m);
|
||||||
|
|
||||||
@ -391,11 +391,11 @@ public class PhotoPanel extends JPanel implements GLEventListener {
|
|||||||
gl.glLightfv(GLLightingFunc.GL_LIGHT2, GLLightingFunc.GL_SPECULAR,
|
gl.glLightfv(GLLightingFunc.GL_LIGHT2, GLLightingFunc.GL_SPECULAR,
|
||||||
new float[] { color[0], color[1], color[2], 1 }, 0);
|
new float[] { color[0], color[1], color[2], 1 }, 0);
|
||||||
|
|
||||||
BoundingBox b = configuration.getBoundingBox();
|
Bounds b = calculateBounds();
|
||||||
gl.glLightf(GLLightingFunc.GL_LIGHT2,
|
gl.glLightf(GLLightingFunc.GL_LIGHT2,
|
||||||
GLLightingFunc.GL_QUADRATIC_ATTENUATION, 20f);
|
GLLightingFunc.GL_QUADRATIC_ATTENUATION, 20f);
|
||||||
gl.glLightfv(GLLightingFunc.GL_LIGHT2, GLLightingFunc.GL_POSITION,
|
gl.glLightfv(GLLightingFunc.GL_LIGHT2, GLLightingFunc.GL_POSITION,
|
||||||
new float[] { (float) (b.max.x + .1f), 0, 0, 1 }, 0);
|
new float[] { (float) (b.xMax + .1f), 0, 0, 1 }, 0);
|
||||||
gl.glEnable(GLLightingFunc.GL_LIGHT2);
|
gl.glEnable(GLLightingFunc.GL_LIGHT2);
|
||||||
} else {
|
} else {
|
||||||
gl.glDisable(GLLightingFunc.GL_LIGHT2);
|
gl.glDisable(GLLightingFunc.GL_LIGHT2);
|
||||||
@ -478,14 +478,56 @@ public class PhotoPanel extends JPanel implements GLEventListener {
|
|||||||
ratio = (double) w / (double) h;
|
ratio = (double) w / (double) h;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
private static class Bounds {
|
||||||
|
double xMin, xMax, xSize;
|
||||||
|
double yMin, yMax, ySize;
|
||||||
|
double zMin, zMax, zSize;
|
||||||
|
double rMax;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Bounds cachedBounds = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the bounds for the current configuration
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
private Bounds calculateBounds() {
|
||||||
|
if (cachedBounds != null) {
|
||||||
|
return cachedBounds;
|
||||||
|
} else {
|
||||||
|
final Bounds b = new Bounds();
|
||||||
|
final Collection<Coordinate> bounds = configuration.getBounds();
|
||||||
|
for (Coordinate c : bounds) {
|
||||||
|
b.xMax = Math.max(b.xMax, c.x);
|
||||||
|
b.xMin = Math.min(b.xMin, c.x);
|
||||||
|
|
||||||
|
b.yMax = Math.max(b.yMax, c.y);
|
||||||
|
b.yMin = Math.min(b.yMin, c.y);
|
||||||
|
|
||||||
|
b.zMax = Math.max(b.zMax, c.z);
|
||||||
|
b.zMin = Math.min(b.zMin, c.z);
|
||||||
|
|
||||||
|
double r = MathUtil.hypot(c.y, c.z);
|
||||||
|
b.rMax = Math.max(b.rMax, r);
|
||||||
|
}
|
||||||
|
b.xSize = b.xMax - b.xMin;
|
||||||
|
b.ySize = b.yMax - b.yMin;
|
||||||
|
b.zSize = b.zMax - b.zMin;
|
||||||
|
cachedBounds = b;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void setupModel(final GL2 gl) {
|
private void setupModel(final GL2 gl) {
|
||||||
|
// Get the bounds
|
||||||
|
final Bounds b = calculateBounds();
|
||||||
gl.glRotated(-p.getPitch() * (180.0 / Math.PI), 0, 0, 1);
|
gl.glRotated(-p.getPitch() * (180.0 / Math.PI), 0, 0, 1);
|
||||||
gl.glRotated(p.getYaw() * (180.0 / Math.PI), 0, 1, 0);
|
gl.glRotated(p.getYaw() * (180.0 / Math.PI), 0, 1, 0);
|
||||||
gl.glRotated(p.getRoll() * (180.0 / Math.PI), 1, 0, 0);
|
gl.glRotated(p.getRoll() * (180.0 / Math.PI), 1, 0, 0);
|
||||||
|
|
||||||
// Center the rocket in the view.
|
// Center the rocket in the view.
|
||||||
final BoundingBox b = configuration.getBoundingBox();
|
gl.glTranslated(-b.xMin - b.xSize / 2.0, 0, 0);
|
||||||
gl.glTranslated((b.min.x - b.max.x) / 2.0, 0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,10 @@ public class RocketInfo implements FigureElement {
|
|||||||
private float line = 0;
|
private float line = 0;
|
||||||
private float x1, x2, y1, y2;
|
private float x1, x2, y1, y2;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public RocketInfo(FlightConfiguration configuration) {
|
public RocketInfo(FlightConfiguration configuration) {
|
||||||
this.configuration = configuration;
|
this.configuration = configuration;
|
||||||
this.stabilityUnits = UnitGroup.stabilityUnits(configuration);
|
this.stabilityUnits = UnitGroup.stabilityUnits(configuration);
|
||||||
|
@ -14,6 +14,7 @@ import java.awt.geom.Ellipse2D;
|
|||||||
import java.awt.geom.NoninvertibleTransformException;
|
import java.awt.geom.NoninvertibleTransformException;
|
||||||
import java.awt.geom.Point2D;
|
import java.awt.geom.Point2D;
|
||||||
import java.awt.geom.Rectangle2D;
|
import java.awt.geom.Rectangle2D;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
@ -33,7 +34,6 @@ import net.sf.openrocket.rocketcomponent.MotorMount;
|
|||||||
import net.sf.openrocket.rocketcomponent.Rocket;
|
import net.sf.openrocket.rocketcomponent.Rocket;
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.util.ArrayList;
|
|
||||||
import net.sf.openrocket.util.BoundingBox;
|
import net.sf.openrocket.util.BoundingBox;
|
||||||
import net.sf.openrocket.util.BugException;
|
import net.sf.openrocket.util.BugException;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
|
@ -67,12 +67,12 @@ import net.sf.openrocket.simulation.listeners.SimulationListener;
|
|||||||
import net.sf.openrocket.simulation.listeners.system.ApogeeEndListener;
|
import net.sf.openrocket.simulation.listeners.system.ApogeeEndListener;
|
||||||
import net.sf.openrocket.simulation.listeners.system.InterruptListener;
|
import net.sf.openrocket.simulation.listeners.system.InterruptListener;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
|
import net.sf.openrocket.unit.UnitGroup;
|
||||||
import net.sf.openrocket.util.ChangeSource;
|
import net.sf.openrocket.util.ChangeSource;
|
||||||
import net.sf.openrocket.util.Chars;
|
import net.sf.openrocket.util.Chars;
|
||||||
import net.sf.openrocket.util.Coordinate;
|
import net.sf.openrocket.util.Coordinate;
|
||||||
import net.sf.openrocket.util.MathUtil;
|
import net.sf.openrocket.util.MathUtil;
|
||||||
import net.sf.openrocket.util.StateChangeListener;
|
import net.sf.openrocket.util.StateChangeListener;
|
||||||
import net.sf.openrocket.unit.UnitGroup;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -607,7 +607,18 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
|
|||||||
figure3d.setCP(cp);
|
figure3d.setCP(cp);
|
||||||
|
|
||||||
// Length bound is assumed to be tight
|
// Length bound is assumed to be tight
|
||||||
double length = curConfig.getLength();
|
double length = 0;
|
||||||
|
Collection<Coordinate> bounds = curConfig.getBounds();
|
||||||
|
if (!bounds.isEmpty()) {
|
||||||
|
double minX = Double.POSITIVE_INFINITY, maxX = Double.NEGATIVE_INFINITY;
|
||||||
|
for (Coordinate c : bounds) {
|
||||||
|
if (c.x < minX)
|
||||||
|
minX = c.x;
|
||||||
|
if (c.x > maxX)
|
||||||
|
maxX = c.x;
|
||||||
|
}
|
||||||
|
length = maxX - minX;
|
||||||
|
}
|
||||||
|
|
||||||
double diameter = Double.NaN;
|
double diameter = Double.NaN;
|
||||||
for (RocketComponent c : curConfig.getCoreComponents()) {
|
for (RocketComponent c : curConfig.getCoreComponents()) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user