diff --git a/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java b/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java index a5607615e..b6a5488c8 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java +++ b/core/src/net/sf/openrocket/rocketcomponent/AxialStage.java @@ -59,7 +59,7 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC * {@inheritDoc} * not strictly accurate, but this should provide an acceptable estimate for total vehicle size */ - @Override + /* @Override public Collection getComponentBounds() { Collection bounds = new ArrayList(8); Coordinate[] instanceLocations = this.getInstanceLocations(); @@ -72,7 +72,7 @@ public class AxialStage extends ComponentAssembly implements FlightConfigurableC return bounds; } - + */ /** * Check whether the given type can be added to this component. A Stage allows * only BodyComponents to be added. diff --git a/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java b/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java index be4d06a9a..486ee6f52 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java +++ b/core/src/net/sf/openrocket/rocketcomponent/BodyTube.java @@ -10,6 +10,7 @@ import net.sf.openrocket.motor.MotorConfiguration; import net.sf.openrocket.motor.MotorConfigurationSet; import net.sf.openrocket.preset.ComponentPreset; import net.sf.openrocket.startup.Application; +import net.sf.openrocket.util.BoundingBox; import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.MathUtil; @@ -304,44 +305,15 @@ public class BodyTube extends SymmetricComponent implements MotorMount, Coaxial * * Currently the points are simply a rectangular box around the body tube. */ - @Override + /* @Override public Collection getComponentBounds() { - Collection bounds = new ArrayList(8); - double x_min_shape = 0; - double x_max_shape = this.length; - double r_max_shape = getOuterRadius(); + Collection bounds = new ArrayList(2); + + addBoundingBox(bounds, 0, length, 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 * InternalComponents or ExternalComponents, excluding BodyComponents, to be added. diff --git a/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java b/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java index 24468aeb3..3aec4aea7 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java +++ b/core/src/net/sf/openrocket/rocketcomponent/ComponentAssembly.java @@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory; import net.sf.openrocket.rocketcomponent.position.AxialMethod; import net.sf.openrocket.rocketcomponent.position.AxialPositionable; +import net.sf.openrocket.util.BoundingBox; import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.Coordinate; @@ -46,14 +47,6 @@ public abstract class ComponentAssembly extends RocketComponent implements Axia public double getAxialOffset() { return getAxialOffset( this.axialMethod ); } - - /** - * Null method (ComponentAssembly has no bounds of itself). - */ - @Override - public Collection getComponentBounds() { - return Collections.emptyList(); - } /** * Null method (ComponentAssembly has no mass of itself). @@ -107,6 +100,17 @@ public abstract class ComponentAssembly extends RocketComponent implements Axia } 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. diff --git a/core/src/net/sf/openrocket/rocketcomponent/InternalComponent.java b/core/src/net/sf/openrocket/rocketcomponent/InternalComponent.java index f108eddf2..f19304a1c 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/InternalComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/InternalComponent.java @@ -2,6 +2,7 @@ package net.sf.openrocket.rocketcomponent; import net.sf.openrocket.rocketcomponent.position.AxialMethod; 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 @@ -35,6 +36,15 @@ public abstract class InternalComponent extends RocketComponent implements Axial 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. * @return true diff --git a/core/src/net/sf/openrocket/rocketcomponent/LaunchLug.java b/core/src/net/sf/openrocket/rocketcomponent/LaunchLug.java index 0824a3aef..924de3678 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/LaunchLug.java +++ b/core/src/net/sf/openrocket/rocketcomponent/LaunchLug.java @@ -8,6 +8,7 @@ import net.sf.openrocket.preset.ComponentPreset; import net.sf.openrocket.preset.ComponentPreset.Type; import net.sf.openrocket.rocketcomponent.position.*; import net.sf.openrocket.startup.Application; +import net.sf.openrocket.util.BoundingBox; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.MathUtil; @@ -187,12 +188,16 @@ public class LaunchLug extends ExternalComponent implements AnglePositionable, C return length * Math.PI * (MathUtil.pow2(radius) - MathUtil.pow2(radius - thickness)); } - @Override + /* @Override public Collection getComponentBounds() { - ArrayList set = new ArrayList(); - addBound(set, 0, radius); - addBound(set, length, radius); - return set; + ArrayList bounds = new ArrayList(2); + addBoundingBox(bounds, 0, length, radius); + return bounds; + } + */ + @Override + public BoundingBox getBoundingBox() { + return new BoundingBox(0, length, radius); } @Override diff --git a/core/src/net/sf/openrocket/rocketcomponent/MassObject.java b/core/src/net/sf/openrocket/rocketcomponent/MassObject.java index b018919d2..faecf63c4 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/MassObject.java +++ b/core/src/net/sf/openrocket/rocketcomponent/MassObject.java @@ -133,13 +133,13 @@ public abstract class MassObject extends InternalComponent { public final double getRotationalUnitInertia() { return pow2(radius) / 2; } - + /* @Override public final Collection getComponentBounds() { Collection c = new ArrayList(); addBound(c, 0, radius); addBound(c, length, radius); return c; - } + }*/ } diff --git a/core/src/net/sf/openrocket/rocketcomponent/ParallelStage.java b/core/src/net/sf/openrocket/rocketcomponent/ParallelStage.java index daf79abda..0cfd8b071 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/ParallelStage.java +++ b/core/src/net/sf/openrocket/rocketcomponent/ParallelStage.java @@ -44,33 +44,6 @@ public class ParallelStage extends AxialStage implements FlightConfigurableCompo return trans.get("BoosterSet.BoosterSet"); } - // not strictly accurate, but this should provide an acceptable estimate for total vehicle size - @Override - public Collection getComponentBounds() { - Collection bounds = new ArrayList(8); - double x_min = Double.MAX_VALUE; - double x_max = Double.MIN_VALUE; - double r_max = 0; - - 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 * only BodyComponents to be added. diff --git a/core/src/net/sf/openrocket/rocketcomponent/PodSet.java b/core/src/net/sf/openrocket/rocketcomponent/PodSet.java index e22fc51aa..26d3c7f67 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/PodSet.java +++ b/core/src/net/sf/openrocket/rocketcomponent/PodSet.java @@ -46,7 +46,7 @@ public class PodSet extends ComponentAssembly implements RingInstanceable { // not strictly accurate, but this should provide an acceptable estimate for total vehicle size - @Override + /* @Override public Collection getComponentBounds() { Collection bounds = new ArrayList(8); double x_min = Double.MAX_VALUE; @@ -71,6 +71,7 @@ public class PodSet extends ComponentAssembly implements RingInstanceable { return bounds; } + */ /** * Check whether the given type can be added to this component. A Stage allows diff --git a/core/src/net/sf/openrocket/rocketcomponent/RailButton.java b/core/src/net/sf/openrocket/rocketcomponent/RailButton.java index df6ea275a..ff0f619db 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RailButton.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RailButton.java @@ -11,6 +11,7 @@ import net.sf.openrocket.rocketcomponent.position.AnglePositionable; import net.sf.openrocket.rocketcomponent.position.AxialMethod; import net.sf.openrocket.rocketcomponent.position.AxialPositionable; import net.sf.openrocket.startup.Application; +import net.sf.openrocket.util.BoundingBox; import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.MathUtil; @@ -232,6 +233,13 @@ public class RailButton extends ExternalComponent implements AnglePositionable, public Type getPresetType() { 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 public void componentChanged(ComponentChangeEvent e) { @@ -287,7 +295,7 @@ public class RailButton extends ExternalComponent implements AnglePositionable, public String getPatternName(){ return (this.getInstanceCount() + "-Line"); } - + /* @Override public Collection getComponentBounds() { final double r = outerDiameter_m / 2.0; @@ -302,7 +310,7 @@ public class RailButton extends ExternalComponent implements AnglePositionable, set.add(new Coordinate(-r, totalHeight_m, -r)); return set; } - + */ @Override public Coordinate getComponentCG() { // Math.PI and density are assumed constant through calculation, and thus may be factored out. diff --git a/core/src/net/sf/openrocket/rocketcomponent/RingComponent.java b/core/src/net/sf/openrocket/rocketcomponent/RingComponent.java index 5dbf4d5ba..4cf2f7349 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RingComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RingComponent.java @@ -162,13 +162,13 @@ public abstract class RingComponent extends StructuralComponent implements Coaxi fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE); } - @Override + /* @Override public Collection getComponentBounds() { List bounds = new ArrayList(); addBound(bounds, 0, getOuterRadius()); addBound(bounds, length, getOuterRadius()); return bounds; - } + }*/ @Override public Coordinate getComponentCG() { @@ -195,7 +195,6 @@ public abstract class RingComponent extends StructuralComponent implements Coaxi getMaterial().getDensity()) * getInstanceCount(); } - @Override public double getLongitudinalUnitInertia() { return ringLongitudinalUnitInertia(getOuterRadius(), getInnerRadius(), getLength()); diff --git a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java index fc20dc813..1d5794736 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/RocketComponent.java @@ -19,6 +19,7 @@ import net.sf.openrocket.preset.ComponentPreset; import net.sf.openrocket.rocketcomponent.position.AxialMethod; import net.sf.openrocket.rocketcomponent.position.RadiusMethod; import net.sf.openrocket.util.ArrayList; +import net.sf.openrocket.util.BoundingBox; import net.sf.openrocket.util.BugException; import net.sf.openrocket.util.ChangeSource; import net.sf.openrocket.util.Color; @@ -222,14 +223,13 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab /** - * Return a collection of bounding coordinates. The coordinates must be such that - * the component is fully enclosed in their convex hull. + * Return bounding box of component. * * Note: this function gets the bounds only for this component. Subchildren must be called individually. * * @return a collection of coordinates that bound the component. */ - public abstract Collection getComponentBounds(); + public abstract BoundingBox getBoundingBox(); /** * Return true if the component may have an aerodynamic effect on the rocket. @@ -1902,7 +1902,9 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab /** - * 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. + * Helper method to add two points on opposite corners of a box + * around the component centerline. This box will be (x_max - + * x_min) long, and 2*r wide/high. */ protected static final void addBoundingBox(Collection bounds, double x_min, double x_max, double r) { bounds.add(new Coordinate(x_min, -r, -r)); diff --git a/core/src/net/sf/openrocket/rocketcomponent/Sleeve.java b/core/src/net/sf/openrocket/rocketcomponent/Sleeve.java index aafff5422..86a5d9191 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/Sleeve.java +++ b/core/src/net/sf/openrocket/rocketcomponent/Sleeve.java @@ -2,6 +2,7 @@ package net.sf.openrocket.rocketcomponent; import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.startup.Application; +import net.sf.openrocket.util.BoundingBox; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.MathUtil; @@ -82,9 +83,6 @@ public class Sleeve extends RingComponent { thickness = t; fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE); } - - - @Override public void setInnerRadiusAutomatic(boolean auto) { diff --git a/core/src/net/sf/openrocket/rocketcomponent/SymmetricComponent.java b/core/src/net/sf/openrocket/rocketcomponent/SymmetricComponent.java index a530bfe94..5c937f44e 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/SymmetricComponent.java +++ b/core/src/net/sf/openrocket/rocketcomponent/SymmetricComponent.java @@ -8,6 +8,7 @@ import java.util.List; import net.sf.openrocket.preset.ComponentPreset; import net.sf.openrocket.rocketcomponent.position.AxialMethod; +import net.sf.openrocket.util.BoundingBox; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.MathUtil; @@ -138,7 +139,7 @@ public abstract class SymmetricComponent extends BodyComponent implements Radial /** * Adds component bounds at a number of points between 0...length. */ - @Override + /* @Override public Collection getComponentBounds() { List list = new ArrayList(20); for (int n = 0; n <= 5; n++) { @@ -147,10 +148,18 @@ public abstract class SymmetricComponent extends BodyComponent implements Radial addBound(list, x, r); } return list; + }*/ + + /** + * Are there any components whose max diameter isn't at either the + * fore or aft end? I don't know of any. + */ + @Override + public BoundingBox getBoundingBox() { + return new BoundingBox(0, getLength(), + Math.max(getForeRadius(), getAftRadius())); } - - @Override protected void loadFromPreset(ComponentPreset preset) { if ( preset.has(ComponentPreset.THICKNESS) ) { diff --git a/core/src/net/sf/openrocket/rocketcomponent/Transition.java b/core/src/net/sf/openrocket/rocketcomponent/Transition.java index d89f6de69..179a3897d 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/Transition.java +++ b/core/src/net/sf/openrocket/rocketcomponent/Transition.java @@ -10,6 +10,7 @@ import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.preset.ComponentPreset; import net.sf.openrocket.preset.ComponentPreset.Type; import net.sf.openrocket.startup.Application; +import net.sf.openrocket.util.BoundingBox; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.MathUtil; @@ -435,7 +436,7 @@ public class Transition extends SymmetricComponent { - @Override +/* @Override public Collection getComponentBounds() { Collection bounds = super.getComponentBounds(); if (foreShoulderLength > 0.001) @@ -443,6 +444,24 @@ public class Transition extends SymmetricComponent { if (aftShoulderLength > 0.001) addBound(bounds, getLength() + aftShoulderLength, aftShoulderRadius); return bounds; + }*/ + + /** + * 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 + public BoundingBox getBoundingBox() { + return new BoundingBox(-getForeShoulderLength(), + getLength() + getAftShoulderLength(), + Math.max(getForeRadius(), getAftRadius())); } @Override diff --git a/core/src/net/sf/openrocket/rocketcomponent/TubeFinSet.java b/core/src/net/sf/openrocket/rocketcomponent/TubeFinSet.java index aa9ad73ab..85db37d74 100644 --- a/core/src/net/sf/openrocket/rocketcomponent/TubeFinSet.java +++ b/core/src/net/sf/openrocket/rocketcomponent/TubeFinSet.java @@ -10,6 +10,7 @@ import net.sf.openrocket.preset.ComponentPreset.Type; import net.sf.openrocket.rocketcomponent.position.AxialMethod; import net.sf.openrocket.rocketcomponent.position.AxialPositionable; import net.sf.openrocket.startup.Application; +import net.sf.openrocket.util.BoundingBox; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.MathUtil; import net.sf.openrocket.util.Transformation; @@ -305,15 +306,18 @@ public class TubeFinSet extends ExternalComponent implements AxialPositionable { return false; } - @Override + /* @Override public Collection getComponentBounds() { - List bounds = new ArrayList(); - double r = getBodyRadius(); - - addBound(bounds, 0, 2 * (r + outerRadius)); - addBound(bounds, length, 2 * (r + outerRadius)); + List bounds = new ArrayList(2); + + addBoundingBox(bounds, 0, length, outerRadius); return bounds; + }*/ + + @Override + public BoundingBox getBoundingBox() { + return new BoundingBox(0, length, outerRadius); } /** diff --git a/core/src/net/sf/openrocket/util/BoundingBox.java b/core/src/net/sf/openrocket/util/BoundingBox.java index 6d5f46eb8..79220ce2e 100644 --- a/core/src/net/sf/openrocket/util/BoundingBox.java +++ b/core/src/net/sf/openrocket/util/BoundingBox.java @@ -17,6 +17,11 @@ public class BoundingBox { this.min = _min.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() { min = Coordinate.MAX.setWeight( 0.0); diff --git a/swing/src/net/sf/openrocket/gui/figure3d/geometry/ComponentRenderer.java b/swing/src/net/sf/openrocket/gui/figure3d/geometry/ComponentRenderer.java index a0f44b54d..cd8229381 100644 --- a/swing/src/net/sf/openrocket/gui/figure3d/geometry/ComponentRenderer.java +++ b/swing/src/net/sf/openrocket/gui/figure3d/geometry/ComponentRenderer.java @@ -25,6 +25,7 @@ import net.sf.openrocket.rocketcomponent.RocketComponent; import net.sf.openrocket.rocketcomponent.Transition; import net.sf.openrocket.rocketcomponent.Transition.Shape; import net.sf.openrocket.rocketcomponent.TubeFinSet; +import net.sf.openrocket.util.BoundingBox; import net.sf.openrocket.util.Coordinate; import net.sf.openrocket.util.Transformation; @@ -121,12 +122,57 @@ public class ComponentRenderer { } else if ( c instanceof ParallelStage ) { } else if ( c instanceof PodSet ) { } else { - renderOther(gl, c); + renderBoundingBox(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) { gl.glBegin(GL.GL_LINES); for (Coordinate cc : c.getComponentBounds()) { @@ -137,7 +183,7 @@ public class ComponentRenderer { } gl.glEnd(); } - + */ private void renderTransition(GL2 gl, Transition t, Surface which) { if (which == Surface.OUTSIDE || which == Surface.INSIDE) {