1 package net.sf.openrocket.rocketcomponent;
3 import net.sf.openrocket.l10n.Translator;
4 import net.sf.openrocket.startup.Application;
5 import net.sf.openrocket.util.Coordinate;
6 import net.sf.openrocket.util.MathUtil;
8 import java.util.ArrayList;
9 import java.util.Collection;
13 public class LaunchLug extends ExternalComponent implements Coaxial {
15 private static final Translator trans = Application.getTranslator();
17 private double radius;
18 private double thickness;
20 private double radialDirection = 0;
22 /* These are calculated when the component is first attached to any Rocket */
23 private double shiftY, shiftZ;
28 super(Position.MIDDLE);
35 public double getOuterRadius () {
39 public void setOuterRadius (double radius) {
40 if (MathUtil.equals(this.radius, radius))
43 this.thickness = Math.min(this.thickness, this.radius);
44 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
47 public double getInnerRadius() {
48 return radius - thickness;
51 public void setInnerRadius(double innerRadius) {
52 setOuterRadius(innerRadius + thickness);
55 public double getThickness() {
59 public void setThickness(double thickness) {
60 if (MathUtil.equals(this.thickness, thickness))
62 this.thickness = MathUtil.clamp(thickness, 0, radius);
63 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
67 public double getRadialDirection() {
68 return radialDirection;
71 public void setRadialDirection(double direction) {
72 direction = MathUtil.reduce180(direction);
73 if (MathUtil.equals(this.radialDirection, direction))
75 this.radialDirection = direction;
76 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
81 public void setLength(double length) {
82 if (MathUtil.equals(this.length, length))
85 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
93 public void setRelativePosition(RocketComponent.Position position) {
94 super.setRelativePosition(position);
95 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
100 public void setPositionValue(double value) {
101 super.setPositionValue(value);
102 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
108 public Coordinate[] shiftCoordinates(Coordinate[] array) {
109 array = super.shiftCoordinates(array);
111 for (int i = 0; i < array.length; i++) {
112 array[i] = array[i].add(0, shiftY, shiftZ);
120 public void componentChanged(ComponentChangeEvent e) {
121 super.componentChanged(e);
124 * shiftY and shiftZ must be computed here since calculating them
125 * in shiftCoordinates() would cause an infinite loop due to .toRelative
127 RocketComponent body;
130 for (body = this.getParent(); body != null; body = body.getParent()) {
131 if (body instanceof SymmetricComponent)
138 SymmetricComponent s = (SymmetricComponent) body;
140 x1 = this.toRelative(Coordinate.NUL, body)[0].x;
141 x2 = this.toRelative(new Coordinate(length, 0, 0), body)[0].x;
142 x1 = MathUtil.clamp(x1, 0, body.getLength());
143 x2 = MathUtil.clamp(x2, 0, body.getLength());
144 parentRadius = Math.max(s.getRadius(x1), s.getRadius(x2));
147 shiftY = Math.cos(radialDirection) * (parentRadius + radius);
148 shiftZ = Math.sin(radialDirection) * (parentRadius + radius);
150 // System.out.println("Computed shift: y="+shiftY+" z="+shiftZ);
157 public double getComponentVolume() {
158 return length * Math.PI * (MathUtil.pow2(radius) - MathUtil.pow2(radius - thickness));
162 public Collection<Coordinate> getComponentBounds() {
163 ArrayList<Coordinate> set = new ArrayList<Coordinate>();
164 addBound(set, 0, radius);
165 addBound(set, length, radius);
170 public Coordinate getComponentCG() {
171 return new Coordinate(length / 2, 0, 0, getComponentMass());
175 public String getComponentName() {
177 return trans.get("LaunchLug.Launchlug");
181 public double getLongitudinalUnitInertia() {
182 // 1/12 * (3 * (r1^2 + r2^2) + h^2)
183 return (3 * (MathUtil.pow2(getInnerRadius())) + MathUtil.pow2(getOuterRadius()) +
184 MathUtil.pow2(getLength())) / 12;
188 public double getRotationalUnitInertia() {
189 // 1/2 * (r1^2 + r2^2)
190 return (MathUtil.pow2(getInnerRadius()) + MathUtil.pow2(getOuterRadius()))/2;
194 public boolean allowsChildren() {
199 public boolean isCompatible(Class<? extends RocketComponent> type) {
200 // Allow nothing to be attached to a LaunchLug
205 * Accept a visitor to this LaunchLug in the component hierarchy.
207 * @param theVisitor the visitor that will be called back with a reference to this LaunchLug
210 public void accept (final ComponentVisitor theVisitor) {
211 theVisitor.visit(this);