1 package net.sf.openrocket.simulation;
3 import java.util.ArrayList;
4 import java.util.Arrays;
5 import java.util.HashMap;
6 import java.util.LinkedHashMap;
10 import net.sf.openrocket.util.Monitorable;
11 import net.sf.openrocket.util.Mutable;
14 * A single branch of flight data. The data is ordered based on some variable, typically time.
15 * It also contains flight events that have occurred during simulation.
17 * After instantiating a FlightDataBranch data and new variable types can be added to the branch.
18 * A new data point (a value for each variable defined) is created using {@link #addPoint()} after
19 * which the value for each variable type can be set using {@link #setValue(FlightDataType, double)}.
20 * Each variable type does NOT have to be set, unset values will default to NaN. New variable types
21 * not defined in the constructor can be added using {@link #setValue(FlightDataType, double)}, they
22 * will be created and all previous values will be set to NaN.
24 * After populating a FlightDataBranch object it can be made immutable by calling {@link #immute()}.
26 * @author Sampo Niskanen <sampo.niskanen@iki.fi>
28 public class FlightDataBranch implements Monitorable {
30 /** The name of this flight data branch. */
31 private final String branchName;
33 private final Map<FlightDataType, ArrayList<Double>> values =
34 new LinkedHashMap<FlightDataType, ArrayList<Double>>();
36 private final Map<FlightDataType, Double> maxValues = new HashMap<FlightDataType, Double>();
37 private final Map<FlightDataType, Double> minValues = new HashMap<FlightDataType, Double>();
40 private final ArrayList<FlightEvent> events = new ArrayList<FlightEvent>();
42 private Mutable mutable = new Mutable();
44 private int modID = 0;
47 * Sole constructor. Defines the name of the FlightDataBranch and at least one variable type.
49 * @param name the name of this FlightDataBranch.
50 * @param types data types to include (must include at least one type).
52 public FlightDataBranch(String name, FlightDataType... types) {
53 if (types.length == 0) {
54 throw new IllegalArgumentException("Must specify at least one data type.");
57 this.branchName = name;
59 for (FlightDataType t : types) {
60 if (values.containsKey(t)) {
61 throw new IllegalArgumentException("Value type " + t + " specified multiple " +
62 "times in constructor.");
65 values.put(t, new ArrayList<Double>());
66 minValues.put(t, Double.NaN);
67 maxValues.put(t, Double.NaN);
74 * Adds a new point into the data branch. The value for all types is set to NaN by default.
76 * @throws IllegalStateException if this object has been made immutable.
78 public void addPoint() {
81 for (FlightDataType t : values.keySet()) {
82 values.get(t).add(Double.NaN);
89 * Set the value for a specific data type at the latest point. New variable types can be
90 * added to the FlightDataBranch transparently.
92 * @param type the variable to set.
93 * @param value the value to set.
94 * @throws IllegalStateException if this object has been made immutable.
96 public void setValue(FlightDataType type, double value) {
99 ArrayList<Double> list = values.get(type);
102 list = new ArrayList<Double>();
104 for (int i = 0; i < n; i++) {
105 list.add(Double.NaN);
107 values.put(type, list);
108 minValues.put(type, value);
109 maxValues.put(type, value);
112 list.set(list.size() - 1, value);
113 double min = minValues.get(type);
114 double max = maxValues.get(type);
116 if (Double.isNaN(min) || (value < min)) {
117 minValues.put(type, value);
119 if (Double.isNaN(max) || (value > max)) {
120 maxValues.put(type, value);
127 * Return the branch name.
129 public String getBranchName() {
134 * Return the variable types included in this branch. The types are sorted in their
137 public FlightDataType[] getTypes() {
138 FlightDataType[] array = values.keySet().toArray(new FlightDataType[0]);
144 * Return the number of data points in this branch.
146 public int getLength() {
147 for (FlightDataType t : values.keySet()) {
148 return values.get(t).size();
154 * Return an array of values for the specified variable type.
156 * @param type the variable type.
157 * @return a list of the variable values, or <code>null</code> if
158 * the variable type hasn't been added to this branch.
160 @SuppressWarnings("unchecked")
161 public List<Double> get(FlightDataType type) {
162 ArrayList<Double> list = values.get(type);
165 return (List<Double>) list.clone();
169 * Return the last value of the specified type in the branch, or NaN if the type is
172 * @param type the parameter type.
173 * @return the last value in this branch, or NaN.
175 public double getLast(FlightDataType type) {
176 ArrayList<Double> list = values.get(type);
177 if (list == null || list.isEmpty())
179 return list.get(list.size() - 1);
183 * Return the minimum value of the specified type in the branch, or NaN if the type
186 * @param type the parameter type.
187 * @return the minimum value in this branch, or NaN.
189 public double getMinimum(FlightDataType type) {
190 Double v = minValues.get(type);
197 * Return the maximum value of the specified type in the branch, or NaN if the type
200 * @param type the parameter type.
201 * @return the maximum value in this branch, or NaN.
203 public double getMaximum(FlightDataType type) {
204 Double v = maxValues.get(type);
212 * Add a flight event to this branch.
214 * @param event the event to add.
215 * @throws IllegalStateException if this branch has been made immutable.
217 public void addEvent(FlightEvent event) {
219 events.add(event.resetSourceAndData());
225 * Return the list of events.
227 * @return the list of events during the flight.
229 @SuppressWarnings("unchecked")
230 public List<FlightEvent> getEvents() {
231 return (List<FlightEvent>) events.clone();
236 * Make this FlightDataBranch immutable. Any calls to the set methods that would
237 * modify this object will after this call throw an <code>IllegalStateException</code>.
239 public void immute() {
245 * Return whether this branch is still mutable.
247 public boolean isMutable() {
248 return mutable.isMutable();
253 public int getModID() {