Initial commit
[debian/openrocket] / src / net / sf / openrocket / rocketcomponent / TrapezoidFinSet.java
1 package net.sf.openrocket.rocketcomponent;
2
3 import net.sf.openrocket.util.Coordinate;
4
5 /**
6  * A set of trapezoidal fins.  The root and tip chords are perpendicular to the rocket
7  * base line, while the leading and aft edges may be slanted.
8  * 
9  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
10  */
11
12 public class TrapezoidFinSet extends FinSet {
13         public static final double MAX_SWEEP_ANGLE=(89*Math.PI/180.0);
14
15         /*
16          *           sweep   tipChord
17          *           |    |___________
18          *           |   /            |
19          *           |  /             | 
20          *           | /              |  height
21          *            /               |
22          * __________/________________|_____________
23          *                length
24          *              == rootChord
25          */
26         
27         // rootChord == length
28         private double tipChord = 0;
29         private double height = 0;
30         private double sweep = 0;
31         
32         
33         public TrapezoidFinSet() {
34                 this (3, 0.05, 0.05, 0.025, 0.05);
35         }
36         
37         // TODO: HIGH:  height=0 -> CP = NaN
38         public TrapezoidFinSet(int fins, double rootChord, double tipChord, double sweep, 
39                         double height) {
40                 super();
41                 
42                 this.setFinCount(fins);
43                 this.length = rootChord;
44                 this.tipChord = tipChord;
45                 this.sweep = sweep;
46                 this.height = height;
47         }
48         
49         
50         public void setFinShape(double rootChord, double tipChord, double sweep, double height,
51                         double thickness) {
52                 if (this.length==rootChord && this.tipChord==tipChord && this.sweep==sweep &&
53                                 this.height==height && this.thickness==thickness)
54                         return;
55                 this.length=rootChord;
56                 this.tipChord=tipChord;
57                 this.sweep=sweep;
58                 this.height=height;
59                 this.thickness=thickness;
60                 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
61         }
62
63         public double getRootChord() {
64                 return length;
65         }
66         public void setRootChord(double r) {
67                 if (length == r)
68                         return;
69                 length = Math.max(r,0);
70                 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
71         }
72         
73         public double getTipChord() {
74                 return tipChord;
75         }
76         public void setTipChord(double r) {
77                 if (tipChord == r)
78                         return;
79                 tipChord = Math.max(r,0);
80                 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
81         }
82
83         /**
84          * Get the sweep length.
85          */
86         public double getSweep() {
87                 return sweep;
88         }
89         /**
90          * Set the sweep length.
91          */
92         public void setSweep(double r) {
93                 if (sweep == r)
94                         return;
95                 sweep = r;
96                 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
97         }
98         
99         /**
100          * Get the sweep angle.  This is calculated from the true sweep and height, and is not
101          * stored separetely.
102          */
103         public double getSweepAngle() {
104                 if (height == 0) {
105                         if (sweep > 0)
106                                 return Math.PI/2;
107                         if (sweep < 0)
108                                 return -Math.PI/2;
109                         return 0;
110                 }
111                 return Math.atan(sweep/height);
112         }
113         /**
114          * Sets the sweep by the sweep angle.  The sweep is calculated and set by this method,
115          * and the angle itself is not stored.
116          */
117         public void setSweepAngle(double r) {
118                 if (r > MAX_SWEEP_ANGLE)
119                         r = MAX_SWEEP_ANGLE;
120                 if (r < -MAX_SWEEP_ANGLE)
121                         r = -MAX_SWEEP_ANGLE;
122                 double sweep = Math.tan(r) * height;
123                 if (Double.isNaN(sweep) || Double.isInfinite(sweep))
124                         return;
125                 setSweep(sweep);
126         }
127
128         public double getHeight() {
129                 return height;
130         }
131         public void setHeight(double r) {
132                 if (height == r)
133                         return;
134                 height = Math.max(r,0);
135                 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
136         }
137
138         
139
140         /**
141          * Returns the geometry of a trapezoidal fin.
142          */
143         @Override
144         public Coordinate[] getFinPoints() {
145                 Coordinate[] c = new Coordinate[4];
146                 
147                 c[0] = Coordinate.NUL;
148                 c[1] = new Coordinate(sweep,height);
149                 c[2] = new Coordinate(sweep+tipChord,height);
150                 c[3] = new Coordinate(length,0);
151                 
152                 return c;
153         }
154         
155         /**
156          * Returns the span of a trapezoidal fin.
157          */
158         @Override
159         public double getSpan() {
160                 return height;
161         }
162         
163
164         @Override
165         public String getComponentName() {
166                 return "Trapezoidal fin set";
167         }
168
169 }