1 package net.sf.openrocket.rocketcomponent;
3 import java.util.ArrayList;
4 import java.util.Collection;
7 import net.sf.openrocket.util.Coordinate;
8 import net.sf.openrocket.util.MathUtil;
12 * An inner component that consists of a hollow cylindrical component. This can be
13 * an inner tube, tube coupler, centering ring, bulkhead etc.
15 * The properties include the inner and outer radii, length and radial position.
17 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
19 public abstract class RingComponent extends StructuralComponent {
21 protected boolean outerRadiusAutomatic = false;
22 protected boolean innerRadiusAutomatic = false;
25 private double radialDirection = 0;
26 private double radialPosition = 0;
28 private double shiftY = 0;
29 private double shiftZ = 0;
34 public abstract double getOuterRadius();
35 public abstract void setOuterRadius(double r);
37 public abstract double getInnerRadius();
38 public abstract void setInnerRadius(double r);
40 public abstract double getThickness();
41 public abstract void setThickness(double thickness);
44 public final boolean isOuterRadiusAutomatic() {
45 return outerRadiusAutomatic;
48 protected void setOuterRadiusAutomatic(boolean auto) {
49 if (auto == outerRadiusAutomatic)
51 outerRadiusAutomatic = auto;
52 fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
56 public final boolean isInnerRadiusAutomatic() {
57 return innerRadiusAutomatic;
60 protected void setInnerRadiusAutomatic(boolean auto) {
61 if (auto == innerRadiusAutomatic)
63 innerRadiusAutomatic = auto;
64 fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
70 public final void setLength(double length) {
71 double l = Math.max(length,0);
76 fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
81 * Return the radial direction of displacement of the component. Direction 0
82 * is equivalent to the Y-direction.
84 * @return the radial direction.
86 public double getRadialDirection() {
87 return radialDirection;
91 * Set the radial direction of displacement of the component. Direction 0
92 * is equivalent to the Y-direction.
94 * @param dir the radial direction.
96 public void setRadialDirection(double dir) {
97 dir = MathUtil.reduce180(dir);
98 if (radialDirection == dir)
100 radialDirection = dir;
101 shiftY = radialPosition * Math.cos(radialDirection);
102 shiftZ = radialPosition * Math.sin(radialDirection);
103 fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
110 * Return the radial position of the component. The position is the distance
111 * of the center of the component from the center of the parent component.
113 * @return the radial position.
115 public double getRadialPosition() {
116 return radialPosition;
120 * Set the radial position of the component. The position is the distance
121 * of the center of the component from the center of the parent component.
123 * @param pos the radial position.
125 public void setRadialPosition(double pos) {
126 pos = Math.max(pos, 0);
127 if (radialPosition == pos)
129 radialPosition = pos;
130 shiftY = radialPosition * Math.cos(radialDirection);
131 shiftZ = radialPosition * Math.sin(radialDirection);
132 fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
136 public double getRadialShiftY() {
140 public double getRadialShiftZ() {
144 public void setRadialShift(double y, double z) {
145 radialPosition = Math.hypot(y, z);
146 radialDirection = Math.atan2(z, y);
148 // Re-calculate to ensure consistency
149 shiftY = radialPosition * Math.cos(radialDirection);
150 shiftZ = radialPosition * Math.sin(radialDirection);
151 assert(MathUtil.equals(y, shiftY));
152 assert(MathUtil.equals(z, shiftZ));
154 fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
159 * Return the number of times the component is multiplied.
161 public int getClusterCount() {
162 if (this instanceof Clusterable)
163 return ((Clusterable)this).getClusterConfiguration().getClusterCount();
169 * Shift the coordinates according to the radial position and direction.
172 public Coordinate[] shiftCoordinates(Coordinate[] array) {
173 for (int i=0; i < array.length; i++) {
174 array[i] = array[i].add(0, shiftY, shiftZ);
181 public Collection<Coordinate> getComponentBounds() {
182 List<Coordinate> bounds = new ArrayList<Coordinate>();
183 addBound(bounds,0,getOuterRadius());
184 addBound(bounds,length,getOuterRadius());
191 public Coordinate getComponentCG() {
192 return new Coordinate(length/2, 0, 0, getComponentMass());
196 public double getComponentMass() {
197 return ringMass(getOuterRadius(), getInnerRadius(), getLength(),
198 getMaterial().getDensity()) * getClusterCount();
203 public double getLongitudalUnitInertia() {
204 return ringLongitudalUnitInertia(getOuterRadius(), getInnerRadius(), getLength());
208 public double getRotationalUnitInertia() {
209 return ringRotationalUnitInertia(getOuterRadius(), getInnerRadius());