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;
13 * A MassObject is an internal component that can a specific weight, but not necessarily a strictly bound shape. It is
14 * represented as a homogeneous cylinder and drawn in the rocket figure with rounded corners.
16 * Subclasses of this class need only implement the {@link #getComponentMass()}, {@link #getComponentName()} and {@link
17 * #isCompatible(RocketComponent)} methods.
19 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
21 public abstract class MassObject extends InternalComponent {
23 private double radius;
25 private double radialPosition;
26 private double radialDirection;
28 private double shiftY = 0;
29 private double shiftZ = 0;
36 public MassObject(double length, double radius) {
42 this.setRelativePosition(Position.TOP);
43 this.setPositionValue(0.0);
47 public void setLength(double length) {
48 length = Math.max(length, 0);
49 if (MathUtil.equals(this.length, length)) {
53 fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
57 public final double getRadius() {
62 public final void setRadius(double radius) {
63 radius = Math.max(radius, 0);
64 if (MathUtil.equals(this.radius, radius)) {
68 fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
73 public final double getRadialPosition() {
74 return radialPosition;
77 public final void setRadialPosition(double radialPosition) {
78 radialPosition = Math.max(radialPosition, 0);
79 if (MathUtil.equals(this.radialPosition, radialPosition)) {
82 this.radialPosition = radialPosition;
83 shiftY = radialPosition * Math.cos(radialDirection);
84 shiftZ = radialPosition * Math.sin(radialDirection);
85 fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
88 public final double getRadialDirection() {
89 return radialDirection;
92 public final void setRadialDirection(double radialDirection) {
93 radialDirection = MathUtil.reduce180(radialDirection);
94 if (MathUtil.equals(this.radialDirection, radialDirection)) {
97 this.radialDirection = radialDirection;
98 shiftY = radialPosition * Math.cos(radialDirection);
99 shiftZ = radialPosition * Math.sin(radialDirection);
100 fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
105 * Shift the coordinates according to the radial position and direction.
108 public final Coordinate[] shiftCoordinates(Coordinate[] array) {
109 for (int i = 0; i < array.length; i++) {
110 array[i] = array[i].add(0, shiftY, shiftZ);
116 public final Coordinate getComponentCG() {
117 return new Coordinate(length / 2, shiftY, shiftZ, getComponentMass());
121 public final double getLongitudinalUnitInertia() {
122 return (3 * pow2(radius) + pow2(length)) / 12;
126 public final double getRotationalUnitInertia() {
127 return pow2(radius) / 2;
131 public final Collection<Coordinate> getComponentBounds() {
132 Collection<Coordinate> c = new ArrayList<Coordinate>();
133 addBound(c, 0, radius);
134 addBound(c, length, radius);