1 package net.sf.openrocket.rocketcomponent;
3 import java.util.ArrayList;
4 import java.util.Collection;
6 import net.sf.openrocket.l10n.Translator;
7 import net.sf.openrocket.preset.ComponentPreset;
8 import net.sf.openrocket.preset.ComponentPreset.Type;
9 import net.sf.openrocket.startup.Application;
10 import net.sf.openrocket.util.Coordinate;
11 import net.sf.openrocket.util.MathUtil;
15 public class LaunchLug extends ExternalComponent implements Coaxial {
17 private static final Translator trans = Application.getTranslator();
19 private double radius;
20 private double thickness;
22 private double radialDirection = 0;
24 /* These are calculated when the component is first attached to any Rocket */
25 private double shiftY, shiftZ;
30 super(Position.MIDDLE);
38 public double getOuterRadius() {
43 public void setOuterRadius(double radius) {
44 if (MathUtil.equals(this.radius, radius))
47 this.thickness = Math.min(this.thickness, this.radius);
49 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
53 public double getInnerRadius() {
54 return radius - thickness;
58 public void setInnerRadius(double innerRadius) {
59 setOuterRadius(innerRadius + thickness);
63 public double getThickness() {
67 public void setThickness(double thickness) {
68 if (MathUtil.equals(this.thickness, thickness))
70 this.thickness = MathUtil.clamp(thickness, 0, radius);
72 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
76 public double getRadialDirection() {
77 return radialDirection;
80 public void setRadialDirection(double direction) {
81 direction = MathUtil.reduce180(direction);
82 if (MathUtil.equals(this.radialDirection, direction))
84 this.radialDirection = direction;
85 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
90 public void setLength(double length) {
91 if (MathUtil.equals(this.length, length))
94 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
102 public void setRelativePosition(RocketComponent.Position position) {
103 super.setRelativePosition(position);
104 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
109 public void setPositionValue(double value) {
110 super.setPositionValue(value);
111 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
117 protected void loadFromPreset(ComponentPreset preset) {
118 if ( preset.has(ComponentPreset.OUTER_DIAMETER) ) {
119 double outerDiameter = preset.get(ComponentPreset.OUTER_DIAMETER);
120 this.radius = outerDiameter/2.0;
121 if ( preset.has(ComponentPreset.INNER_DIAMETER) ) {
122 double innerDiameter = preset.get(ComponentPreset.INNER_DIAMETER);
123 this.thickness = (outerDiameter-innerDiameter) / 2.0;
127 super.loadFromPreset(preset);
129 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
134 public Type getPresetType() {
135 return ComponentPreset.Type.LAUNCH_LUG;
140 public Coordinate[] shiftCoordinates(Coordinate[] array) {
141 array = super.shiftCoordinates(array);
143 for (int i = 0; i < array.length; i++) {
144 array[i] = array[i].add(0, shiftY, shiftZ);
152 public void componentChanged(ComponentChangeEvent e) {
153 super.componentChanged(e);
156 * shiftY and shiftZ must be computed here since calculating them
157 * in shiftCoordinates() would cause an infinite loop due to .toRelative
159 RocketComponent body;
162 for (body = this.getParent(); body != null; body = body.getParent()) {
163 if (body instanceof SymmetricComponent)
170 SymmetricComponent s = (SymmetricComponent) body;
172 x1 = this.toRelative(Coordinate.NUL, body)[0].x;
173 x2 = this.toRelative(new Coordinate(length, 0, 0), body)[0].x;
174 x1 = MathUtil.clamp(x1, 0, body.getLength());
175 x2 = MathUtil.clamp(x2, 0, body.getLength());
176 parentRadius = Math.max(s.getRadius(x1), s.getRadius(x2));
179 shiftY = Math.cos(radialDirection) * (parentRadius + radius);
180 shiftZ = Math.sin(radialDirection) * (parentRadius + radius);
182 // System.out.println("Computed shift: y="+shiftY+" z="+shiftZ);
189 public double getComponentVolume() {
190 return length * Math.PI * (MathUtil.pow2(radius) - MathUtil.pow2(radius - thickness));
194 public Collection<Coordinate> getComponentBounds() {
195 ArrayList<Coordinate> set = new ArrayList<Coordinate>();
196 addBound(set, 0, radius);
197 addBound(set, length, radius);
202 public Coordinate getComponentCG() {
203 return new Coordinate(length / 2, 0, 0, getComponentMass());
207 public String getComponentName() {
209 return trans.get("LaunchLug.Launchlug");
213 public double getLongitudinalUnitInertia() {
214 // 1/12 * (3 * (r1^2 + r2^2) + h^2)
215 return (3 * (MathUtil.pow2(getInnerRadius())) + MathUtil.pow2(getOuterRadius()) + MathUtil.pow2(getLength())) / 12;
219 public double getRotationalUnitInertia() {
220 // 1/2 * (r1^2 + r2^2)
221 return (MathUtil.pow2(getInnerRadius()) + MathUtil.pow2(getOuterRadius())) / 2;
225 public boolean allowsChildren() {
230 public boolean isCompatible(Class<? extends RocketComponent> type) {
231 // Allow nothing to be attached to a LaunchLug