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;
12 * A set of trapezoidal fins. The root and tip chords are perpendicular to the rocket
13 * base line, while the leading and aft edges may be slanted.
15 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
18 public class TrapezoidFinSet extends FinSet {
19 private static final Translator trans = Application.getTranslator();
21 public static final double MAX_SWEEP_ANGLE = (89 * Math.PI / 180.0);
30 * __________/________________|_____________
35 // rootChord == length
36 private double tipChord = 0;
37 private double height = 0;
38 private double sweep = 0;
41 public TrapezoidFinSet() {
42 this(3, 0.05, 0.05, 0.025, 0.03);
45 // TODO: HIGH: height=0 -> CP = NaN
46 public TrapezoidFinSet(int fins, double rootChord, double tipChord, double sweep,
50 this.setFinCount(fins);
51 this.length = rootChord;
52 this.tipChord = tipChord;
58 public void setFinShape(double rootChord, double tipChord, double sweep, double height,
60 if (this.length == rootChord && this.tipChord == tipChord && this.sweep == sweep &&
61 this.height == height && this.thickness == thickness)
63 this.length = rootChord;
64 this.tipChord = tipChord;
67 this.thickness = thickness;
68 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
71 public double getRootChord() {
75 public void setRootChord(double r) {
78 length = Math.max(r, 0);
79 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
82 public double getTipChord() {
86 public void setTipChord(double r) {
89 tipChord = Math.max(r, 0);
90 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
94 * Get the sweep length.
96 public double getSweep() {
101 * Set the sweep length.
103 public void setSweep(double r) {
107 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
111 * Get the sweep angle. This is calculated from the true sweep and height, and is not
114 public double getSweepAngle() {
122 return Math.atan(sweep / height);
126 * Sets the sweep by the sweep angle. The sweep is calculated and set by this method,
127 * and the angle itself is not stored.
129 public void setSweepAngle(double r) {
130 if (r > MAX_SWEEP_ANGLE)
132 if (r < -MAX_SWEEP_ANGLE)
133 r = -MAX_SWEEP_ANGLE;
134 double sweep = Math.tan(r) * height;
135 if (Double.isNaN(sweep) || Double.isInfinite(sweep))
140 public double getHeight() {
144 public void setHeight(double r) {
147 height = Math.max(r, 0);
148 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
154 * Returns the geometry of a trapezoidal fin.
157 public Coordinate[] getFinPoints() {
158 List<Coordinate> list = new ArrayList<Coordinate>(4);
160 list.add(Coordinate.NUL);
161 list.add(new Coordinate(sweep, height));
162 if (tipChord > 0.0001) {
163 list.add(new Coordinate(sweep + tipChord, height));
165 list.add(new Coordinate(MathUtil.max(length, 0.0001), 0));
167 return list.toArray(new Coordinate[list.size()]);
171 * Returns the span of a trapezoidal fin.
174 public double getSpan() {
180 public String getComponentName() {
181 //// Trapezoidal fin set
182 return trans.get("TrapezoidFinSet.TrapezoidFinSet");