1 package net.sf.openrocket.rocketcomponent;
3 import static net.sf.openrocket.util.MathUtil.pow2;
5 import java.util.ArrayList;
6 import java.util.Collection;
8 import net.sf.openrocket.util.Coordinate;
9 import net.sf.openrocket.util.MathUtil;
14 * A MassObject is an internal component that can a specific weight, but not
15 * necessarily a strictly bound shape. It is represented as a homogeneous
16 * cylinder and drawn in the rocket figure with rounded corners.
18 * Subclasses of this class need only implement the {@link #getComponentMass()},
19 * {@link #getComponentName()} and {@link #isCompatible(RocketComponent)}
22 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
24 public abstract class MassObject extends InternalComponent {
26 private double radius;
28 private double radialPosition;
29 private double radialDirection;
31 private double shiftY = 0;
32 private double shiftZ = 0;
39 public MassObject(double length, double radius) {
45 this.setRelativePosition(Position.TOP);
46 this.setPositionValue(0.0);
52 public void setLength(double length) {
53 length = Math.max(length, 0);
54 if (MathUtil.equals(this.length, length))
57 fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
62 public final double getRadius() {
67 public final void setRadius(double radius) {
68 radius = Math.max(radius, 0);
69 if (MathUtil.equals(this.radius, radius))
72 fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
77 public final double getRadialPosition() {
78 return radialPosition;
81 public final void setRadialPosition(double radialPosition) {
82 radialPosition = Math.max(radialPosition, 0);
83 if (MathUtil.equals(this.radialPosition, radialPosition))
85 this.radialPosition = radialPosition;
86 shiftY = radialPosition * Math.cos(radialDirection);
87 shiftZ = radialPosition * Math.sin(radialDirection);
88 fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
91 public final double getRadialDirection() {
92 return radialDirection;
95 public final void setRadialDirection(double radialDirection) {
96 radialDirection = MathUtil.reduce180(radialDirection);
97 if (MathUtil.equals(this.radialDirection, radialDirection))
99 this.radialDirection = radialDirection;
100 shiftY = radialPosition * Math.cos(radialDirection);
101 shiftZ = radialPosition * Math.sin(radialDirection);
102 fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
109 * Shift the coordinates according to the radial position and direction.
112 public final Coordinate[] shiftCoordinates(Coordinate[] array) {
113 for (int i=0; i < array.length; i++) {
114 array[i] = array[i].add(0, shiftY, shiftZ);
120 public final Coordinate getComponentCG() {
121 return new Coordinate(length/2, shiftY, shiftZ, getComponentMass());
125 public final double getLongitudalUnitInertia() {
126 return (3*pow2(radius) + pow2(length)) / 12;
130 public final double getRotationalUnitInertia() {
131 return pow2(radius) / 2;
135 public final Collection<Coordinate> getComponentBounds() {
136 Collection<Coordinate> c = new ArrayList<Coordinate>();
137 addBound(c, 0, radius);
138 addBound(c, length, radius);