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.startup.Application;
8 import net.sf.openrocket.util.Coordinate;
9 import net.sf.openrocket.util.MathUtil;
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);
36 public double getOuterRadius() {
41 public void setOuterRadius(double radius) {
42 if (MathUtil.equals(this.radius, radius))
45 this.thickness = Math.min(this.thickness, this.radius);
46 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
50 public double getInnerRadius() {
51 return radius - thickness;
55 public void setInnerRadius(double innerRadius) {
56 setOuterRadius(innerRadius + thickness);
60 public double getThickness() {
64 public void setThickness(double thickness) {
65 if (MathUtil.equals(this.thickness, thickness))
67 this.thickness = MathUtil.clamp(thickness, 0, radius);
68 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
72 public double getRadialDirection() {
73 return radialDirection;
76 public void setRadialDirection(double direction) {
77 direction = MathUtil.reduce180(direction);
78 if (MathUtil.equals(this.radialDirection, direction))
80 this.radialDirection = direction;
81 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
86 public void setLength(double length) {
87 if (MathUtil.equals(this.length, length))
90 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
98 public void setRelativePosition(RocketComponent.Position position) {
99 super.setRelativePosition(position);
100 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
105 public void setPositionValue(double value) {
106 super.setPositionValue(value);
107 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
113 public Coordinate[] shiftCoordinates(Coordinate[] array) {
114 array = super.shiftCoordinates(array);
116 for (int i = 0; i < array.length; i++) {
117 array[i] = array[i].add(0, shiftY, shiftZ);
125 public void componentChanged(ComponentChangeEvent e) {
126 super.componentChanged(e);
129 * shiftY and shiftZ must be computed here since calculating them
130 * in shiftCoordinates() would cause an infinite loop due to .toRelative
132 RocketComponent body;
135 for (body = this.getParent(); body != null; body = body.getParent()) {
136 if (body instanceof SymmetricComponent)
143 SymmetricComponent s = (SymmetricComponent) body;
145 x1 = this.toRelative(Coordinate.NUL, body)[0].x;
146 x2 = this.toRelative(new Coordinate(length, 0, 0), body)[0].x;
147 x1 = MathUtil.clamp(x1, 0, body.getLength());
148 x2 = MathUtil.clamp(x2, 0, body.getLength());
149 parentRadius = Math.max(s.getRadius(x1), s.getRadius(x2));
152 shiftY = Math.cos(radialDirection) * (parentRadius + radius);
153 shiftZ = Math.sin(radialDirection) * (parentRadius + radius);
155 // System.out.println("Computed shift: y="+shiftY+" z="+shiftZ);
162 public double getComponentVolume() {
163 return length * Math.PI * (MathUtil.pow2(radius) - MathUtil.pow2(radius - thickness));
167 public Collection<Coordinate> getComponentBounds() {
168 ArrayList<Coordinate> set = new ArrayList<Coordinate>();
169 addBound(set, 0, radius);
170 addBound(set, length, radius);
175 public Coordinate getComponentCG() {
176 return new Coordinate(length / 2, 0, 0, getComponentMass());
180 public String getComponentName() {
182 return trans.get("LaunchLug.Launchlug");
186 public double getLongitudinalUnitInertia() {
187 // 1/12 * (3 * (r1^2 + r2^2) + h^2)
188 return (3 * (MathUtil.pow2(getInnerRadius())) + MathUtil.pow2(getOuterRadius()) + MathUtil.pow2(getLength())) / 12;
192 public double getRotationalUnitInertia() {
193 // 1/2 * (r1^2 + r2^2)
194 return (MathUtil.pow2(getInnerRadius()) + MathUtil.pow2(getOuterRadius())) / 2;
198 public boolean allowsChildren() {
203 public boolean isCompatible(Class<? extends RocketComponent> type) {
204 // Allow nothing to be attached to a LaunchLug