I18 changes
[debian/openrocket] / src / net / sf / openrocket / rocketcomponent / RecoveryDevice.java
1 package net.sf.openrocket.rocketcomponent;
2
3 import net.sf.openrocket.l10n.Translator;
4 import net.sf.openrocket.material.Material;
5 import net.sf.openrocket.simulation.FlightEvent;
6 import net.sf.openrocket.startup.Application;
7 import net.sf.openrocket.util.MathUtil;
8 import net.sf.openrocket.util.Pair;
9 import net.sf.openrocket.util.Prefs;
10
11
12 /**
13  * RecoveryDevice is a class representing devices that slow down descent.
14  * Recovery devices report that they have no aerodynamic effect, since they
15  * are within the rocket during ascent.
16  * <p>
17  * A recovery device includes a surface material of which it is made of.
18  * The mass of the component is calculated based on the material and the
19  * area of the device from {@link #getArea()}.  {@link #getComponentMass()}
20  * may be overridden if additional mass needs to be included.
21  * 
22  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
23  */
24 public abstract class RecoveryDevice extends MassObject {
25         private static final Translator trans = Application.getTranslator();
26
27         public static enum DeployEvent {
28                 //// Launch (plus NN seconds)
29                 LAUNCH(trans.get("RecoveryDevice.DeployEvent.LAUNCH")) {
30                         @Override
31                         public boolean isActivationEvent(FlightEvent e, RocketComponent source) {
32                                 return e.getType() == FlightEvent.Type.LAUNCH;
33                         }
34                 },
35                 //// First ejection charge of this stage
36                 EJECTION(trans.get("RecoveryDevice.DeployEvent.EJECTION")) {
37                         @Override
38                         public boolean isActivationEvent(FlightEvent e, RocketComponent source) {
39                                 if (e.getType() != FlightEvent.Type.EJECTION_CHARGE)
40                                         return false;
41                                 RocketComponent charge = e.getSource();
42                                 return charge.getStageNumber() == source.getStageNumber();
43                         }
44                 },
45                 //// Apogee
46                 APOGEE(trans.get("RecoveryDevice.DeployEvent.APOGEE")) {
47                         @Override
48                         public boolean isActivationEvent(FlightEvent e, RocketComponent source) {
49                                 return e.getType() == FlightEvent.Type.APOGEE;
50                         }
51                 },
52                 //// Specific altitude during descent
53                 ALTITUDE(trans.get("RecoveryDevice.DeployEvent.ALTITUDE")) {
54                         @SuppressWarnings("unchecked")
55                         @Override
56                         public boolean isActivationEvent(FlightEvent e, RocketComponent source) {
57                                 if (e.getType() != FlightEvent.Type.ALTITUDE)
58                                         return false;
59
60                                 double alt = ((RecoveryDevice)source).getDeployAltitude();
61                                 Pair<Double,Double> altitude = (Pair<Double,Double>)e.getData();
62                                 
63                                 return (altitude.getU() >= alt) && (altitude.getV() <= alt);
64                         }
65                 },
66                 //// Never
67                 NEVER(trans.get("RecoveryDevice.DeployEvent.NEVER")) {
68                         @Override
69                         public boolean isActivationEvent(FlightEvent e, RocketComponent source) {
70                                 return false;
71                         }
72                 }
73                 ;
74                 
75                 private final String description;
76                 
77                 DeployEvent(String description) {
78                         this.description = description;
79                 }
80                 
81                 public abstract boolean isActivationEvent(FlightEvent e, RocketComponent source);
82                 
83                 @Override
84                 public String toString() {
85                         return description;
86                 }
87
88         }
89         
90         
91         private DeployEvent deployEvent = DeployEvent.EJECTION;
92         private double deployAltitude = 200;
93         private double deployDelay = 0;
94         
95         private double cd = Parachute.DEFAULT_CD;
96         private boolean cdAutomatic = true;
97         
98         
99         private Material.Surface material;
100
101         
102         public RecoveryDevice() {
103                 this(Prefs.getDefaultComponentMaterial(RecoveryDevice.class, Material.Type.SURFACE));
104         }
105         
106         public RecoveryDevice(Material material) {
107                 super();
108                 setMaterial(material);
109         }
110
111         public RecoveryDevice(double length, double radius, Material material) {
112                 super(length, radius);
113                 setMaterial(material);
114         }
115         
116         
117
118         
119         public abstract double getArea();
120         
121         public abstract double getComponentCD(double mach);
122
123         
124         
125         public double getCD() {
126                 return getCD(0);
127         }
128         
129         public double getCD(double mach) {
130                 if (cdAutomatic)
131                         cd = getComponentCD(mach);
132                 return cd;
133         }
134
135         public void setCD(double cd) {
136                 if (MathUtil.equals(this.cd, cd) && !isCDAutomatic())
137                         return;
138                 this.cd = cd;
139                 this.cdAutomatic = false;
140                 fireComponentChangeEvent(ComponentChangeEvent.AERODYNAMIC_CHANGE);
141         }
142
143         
144         public boolean isCDAutomatic() {
145                 return cdAutomatic;
146         }
147         
148         public void setCDAutomatic(boolean auto) {
149                 if (cdAutomatic == auto)
150                         return;
151                 this.cdAutomatic = auto;
152                 fireComponentChangeEvent(ComponentChangeEvent.AERODYNAMIC_CHANGE);
153         }
154         
155         
156         
157         public final Material getMaterial() {
158                 return material;
159         }
160         
161         public final void setMaterial(Material mat) {
162                 if (!(mat instanceof Material.Surface)) {
163                         throw new IllegalArgumentException("Attempted to set non-surface material "+mat);
164                 }
165                 if (mat.equals(material))
166                         return;
167                 this.material = (Material.Surface)mat;
168                 fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
169         }
170         
171         
172         
173         
174         public DeployEvent getDeployEvent() {
175                 return deployEvent;
176         }
177
178         public void setDeployEvent(DeployEvent deployEvent) {
179                 if (this.deployEvent == deployEvent)
180                         return;
181                 this.deployEvent = deployEvent;
182                 fireComponentChangeEvent(ComponentChangeEvent.EVENT_CHANGE);
183         }
184         
185
186         public double getDeployAltitude() {
187                 return deployAltitude;
188         }
189
190         public void setDeployAltitude(double deployAltitude) {
191                 if (MathUtil.equals(this.deployAltitude, deployAltitude))
192                         return;
193                 this.deployAltitude = deployAltitude;
194                 if (getDeployEvent() == DeployEvent.ALTITUDE)
195                         fireComponentChangeEvent(ComponentChangeEvent.EVENT_CHANGE);
196                 else
197                         fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
198         }
199         
200         
201         public double getDeployDelay() {
202                 return deployDelay;
203         }
204         
205         public void setDeployDelay(double delay) {
206                 delay = MathUtil.max(delay, 0);
207                 if (MathUtil.equals(this.deployDelay, delay))
208                         return;
209                 this.deployDelay = delay;
210                 fireComponentChangeEvent(ComponentChangeEvent.EVENT_CHANGE);
211         }
212         
213         
214
215         @Override
216         public double getComponentMass() {
217                 return getArea() * getMaterial().getDensity();
218         }
219
220 }