lose embedded source jars from upstream branch
[debian/openrocket] / core / src / net / sf / openrocket / rocketcomponent / InnerTube.java
1 package net.sf.openrocket.rocketcomponent;
2
3 import java.util.ArrayList;
4 import java.util.HashMap;
5 import java.util.List;
6
7 import net.sf.openrocket.l10n.Translator;
8 import net.sf.openrocket.motor.Motor;
9 import net.sf.openrocket.startup.Application;
10 import net.sf.openrocket.util.BugException;
11 import net.sf.openrocket.util.Coordinate;
12 import net.sf.openrocket.util.MathUtil;
13
14
15 /**
16  * This class defines an inner tube that can be used as a motor mount.  The component
17  * may also be clustered.
18  *
19  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
20  */
21 public class InnerTube extends ThicknessRingComponent
22                 implements Clusterable, RadialParent, MotorMount {
23         private static final Translator trans = Application.getTranslator();
24         
25         private ClusterConfiguration cluster = ClusterConfiguration.SINGLE;
26         private double clusterScale = 1.0;
27         private double clusterRotation = 0.0;
28         
29
30         private boolean motorMount = false;
31         private HashMap<String, Double> ejectionDelays = new HashMap<String, Double>();
32         private HashMap<String, Motor> motors = new HashMap<String, Motor>();
33         private IgnitionEvent ignitionEvent = IgnitionEvent.AUTOMATIC;
34         private double ignitionDelay = 0;
35         private double overhang = 0;
36         
37         
38         /**
39          * Main constructor.
40          */
41         public InnerTube() {
42                 // A-C motor size:
43                 this.setOuterRadius(0.019 / 2);
44                 this.setInnerRadius(0.018 / 2);
45                 this.setLength(0.070);
46         }
47         
48         
49         @Override
50         public double getInnerRadius(double x) {
51                 return getInnerRadius();
52         }
53         
54         
55         @Override
56         public double getOuterRadius(double x) {
57                 return getOuterRadius();
58         }
59         
60         
61         @Override
62         public String getComponentName() {
63                 //// Inner Tube
64                 return trans.get("InnerTube.InnerTube");
65         }
66         
67         @Override
68         public boolean allowsChildren() {
69                 return true;
70         }
71         
72         /**
73          * Allow all InternalComponents to be added to this component.
74          */
75         @Override
76         public boolean isCompatible(Class<? extends RocketComponent> type) {
77                 return InternalComponent.class.isAssignableFrom(type);
78         }
79         
80         
81
82         /////////////  Cluster methods  //////////////
83         
84         /**
85          * Get the current cluster configuration.
86          * @return  The current cluster configuration.
87          */
88         @Override
89         public ClusterConfiguration getClusterConfiguration() {
90                 return cluster;
91         }
92         
93         /**
94          * Set the current cluster configuration.
95          * @param cluster  The cluster configuration.
96          */
97         @Override
98         public void setClusterConfiguration(ClusterConfiguration cluster) {
99                 this.cluster = cluster;
100                 fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
101         }
102         
103         /**
104          * Return the number of tubes in the cluster.
105          * @return Number of tubes in the current cluster.
106          */
107         @Override
108         public int getClusterCount() {
109                 return cluster.getClusterCount();
110         }
111         
112         /**
113          * Get the cluster scaling.  A value of 1.0 indicates that the tubes are packed
114          * touching each other, larger values separate the tubes and smaller values
115          * pack inside each other.
116          */
117         public double getClusterScale() {
118                 return clusterScale;
119         }
120         
121         /**
122          * Set the cluster scaling.
123          * @see #getClusterScale()
124          */
125         public void setClusterScale(double scale) {
126                 scale = Math.max(scale, 0);
127                 if (MathUtil.equals(clusterScale, scale))
128                         return;
129                 clusterScale = scale;
130                 fireComponentChangeEvent(new ComponentChangeEvent(this, ComponentChangeEvent.MASS_CHANGE));
131         }
132         
133         
134
135         /**
136          * @return the clusterRotation
137          */
138         public double getClusterRotation() {
139                 return clusterRotation;
140         }
141         
142         
143         /**
144          * @param rotation the clusterRotation to set
145          */
146         public void setClusterRotation(double rotation) {
147                 rotation = MathUtil.reduce180(rotation);
148                 if (clusterRotation == rotation)
149                         return;
150                 this.clusterRotation = rotation;
151                 fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
152         }
153         
154         
155         /**
156          * Return the distance between the closest two cluster inner tube center points.
157          * This is equivalent to the cluster scale multiplied by the tube diameter.
158          */
159         @Override
160         public double getClusterSeparation() {
161                 return 2 * getOuterRadius() * clusterScale;
162         }
163         
164         
165         public List<Coordinate> getClusterPoints() {
166                 List<Coordinate> list = new ArrayList<Coordinate>(getClusterCount());
167                 List<Double> points = cluster.getPoints(clusterRotation - getRadialDirection());
168                 double separation = getClusterSeparation();
169                 for (int i = 0; i < points.size() / 2; i++) {
170                         list.add(new Coordinate(0, points.get(2 * i) * separation, points.get(2 * i + 1) * separation));
171                 }
172                 return list;
173         }
174         
175         
176         @Override
177         public Coordinate[] shiftCoordinates(Coordinate[] array) {
178                 array = super.shiftCoordinates(array);
179                 
180                 int count = getClusterCount();
181                 if (count == 1)
182                         return array;
183                 
184                 List<Coordinate> points = getClusterPoints();
185                 if (points.size() != count) {
186                         throw new BugException("Inconsistent cluster configuration, cluster count=" + count +
187                                         " point count=" + points.size());
188                 }
189                 Coordinate[] newArray = new Coordinate[array.length * count];
190                 for (int i = 0; i < array.length; i++) {
191                         for (int j = 0; j < count; j++) {
192                                 newArray[i * count + j] = array[i].add(points.get(j));
193                         }
194                 }
195                 
196                 return newArray;
197         }
198         
199         
200
201
202         ////////////////  Motor mount  /////////////////
203         
204         @Override
205         public boolean isMotorMount() {
206                 return motorMount;
207         }
208         
209         @Override
210         public void setMotorMount(boolean mount) {
211                 if (motorMount == mount)
212                         return;
213                 motorMount = mount;
214                 fireComponentChangeEvent(ComponentChangeEvent.MOTOR_CHANGE);
215         }
216         
217         @Override
218         public Motor getMotor(String id) {
219                 if (id == null)
220                         return null;
221                 
222                 // Check whether the id is valid for the current rocket
223                 RocketComponent root = this.getRoot();
224                 if (!(root instanceof Rocket))
225                         return null;
226                 if (!((Rocket) root).isMotorConfigurationID(id))
227                         return null;
228                 
229                 return motors.get(id);
230         }
231         
232         @Override
233         public void setMotor(String id, Motor motor) {
234                 if (id == null) {
235                         if (motor != null) {
236                                 throw new IllegalArgumentException("Cannot set non-null motor for id null");
237                         }
238                 }
239                 Motor current = motors.get(id);
240                 if ((motor == null && current == null) ||
241                                 (motor != null && motor.equals(current)))
242                         return;
243                 motors.put(id, motor);
244                 fireComponentChangeEvent(ComponentChangeEvent.MOTOR_CHANGE);
245         }
246         
247         @Override
248         public double getMotorDelay(String id) {
249                 Double delay = ejectionDelays.get(id);
250                 if (delay == null)
251                         return Motor.PLUGGED;
252                 return delay;
253         }
254         
255         @Override
256         public void setMotorDelay(String id, double delay) {
257                 ejectionDelays.put(id, delay);
258                 fireComponentChangeEvent(ComponentChangeEvent.MOTOR_CHANGE);
259         }
260         
261         @Deprecated
262         @Override
263         public int getMotorCount() {
264                 return getClusterCount();
265         }
266         
267         @Override
268         public double getMotorMountDiameter() {
269                 return getInnerRadius() * 2;
270         }
271         
272         @Override
273         public IgnitionEvent getIgnitionEvent() {
274                 return ignitionEvent;
275         }
276         
277         @Override
278         public void setIgnitionEvent(IgnitionEvent event) {
279                 if (ignitionEvent == event)
280                         return;
281                 ignitionEvent = event;
282                 fireComponentChangeEvent(ComponentChangeEvent.EVENT_CHANGE);
283         }
284         
285         
286         @Override
287         public double getIgnitionDelay() {
288                 return ignitionDelay;
289         }
290         
291         @Override
292         public void setIgnitionDelay(double delay) {
293                 if (MathUtil.equals(delay, ignitionDelay))
294                         return;
295                 ignitionDelay = delay;
296                 fireComponentChangeEvent(ComponentChangeEvent.EVENT_CHANGE);
297         }
298         
299         
300         @Override
301         public double getMotorOverhang() {
302                 return overhang;
303         }
304         
305         @Override
306         public void setMotorOverhang(double overhang) {
307                 if (MathUtil.equals(this.overhang, overhang))
308                         return;
309                 this.overhang = overhang;
310                 fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
311         }
312         
313         
314         @Override
315         public Coordinate getMotorPosition(String id) {
316                 Motor motor = motors.get(id);
317                 if (motor == null) {
318                         throw new IllegalArgumentException("No motor with id " + id + " defined.");
319                 }
320                 
321                 return new Coordinate(this.getLength() - motor.getLength() + this.getMotorOverhang());
322         }
323         
324         /*
325          * (non-Javadoc)
326          * Copy the motor and ejection delay HashMaps.
327          *
328          * @see rocketcomponent.RocketComponent#copy()
329          */
330         @SuppressWarnings("unchecked")
331         @Override
332         protected RocketComponent copyWithOriginalID() {
333                 RocketComponent c = super.copyWithOriginalID();
334                 ((InnerTube) c).motors = (HashMap<String, Motor>) motors.clone();
335                 ((InnerTube) c).ejectionDelays = (HashMap<String, Double>) ejectionDelays.clone();
336                 return c;
337         }
338         
339 }