1 package net.sf.openrocket.simulation;
3 import java.util.Arrays;
4 import java.util.HashMap;
5 import java.util.LinkedHashMap;
9 import net.sf.openrocket.util.ArrayList;
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);
72 * Makes an 'empty' flight data branch which has no data but all built in data types are defined.
74 public FlightDataBranch() {
75 branchName = "Empty branch";
76 for (FlightDataType type : FlightDataType.ALL_TYPES){
77 this.setValue(type, Double.NaN);
83 * Adds a new point into the data branch. The value for all types is set to NaN by default.
85 * @throws IllegalStateException if this object has been made immutable.
87 public void addPoint() {
90 for (FlightDataType t : values.keySet()) {
91 values.get(t).add(Double.NaN);
98 * Set the value for a specific data type at the latest point. New variable types can be
99 * added to the FlightDataBranch transparently.
101 * @param type the variable to set.
102 * @param value the value to set.
103 * @throws IllegalStateException if this object has been made immutable.
105 public void setValue(FlightDataType type, double value) {
108 ArrayList<Double> list = values.get(type);
111 list = new ArrayList<Double>();
113 for (int i = 0; i < n; i++) {
114 list.add(Double.NaN);
116 values.put(type, list);
117 minValues.put(type, value);
118 maxValues.put(type, value);
121 if (list.size() > 0){
122 list.set(list.size() - 1, value);
125 double min = minValues.get(type);
126 double max = maxValues.get(type);
128 if (Double.isNaN(min) || (value < min)) {
129 minValues.put(type, value);
131 if (Double.isNaN(max) || (value > max)) {
132 maxValues.put(type, value);
139 * Return the branch name.
141 public String getBranchName() {
146 * Return the variable types included in this branch. The types are sorted in their
149 public FlightDataType[] getTypes() {
150 FlightDataType[] array = values.keySet().toArray(new FlightDataType[0]);
156 * Return the number of data points in this branch.
158 public int getLength() {
159 for (FlightDataType t : values.keySet()) {
160 return values.get(t).size();
166 * Return an array of values for the specified variable type.
168 * @param type the variable type.
169 * @return a list of the variable values, or <code>null</code> if
170 * the variable type hasn't been added to this branch.
172 public List<Double> get(FlightDataType type) {
173 ArrayList<Double> list = values.get(type);
180 * Return the last value of the specified type in the branch, or NaN if the type is
183 * @param type the parameter type.
184 * @return the last value in this branch, or NaN.
186 public double getLast(FlightDataType type) {
187 ArrayList<Double> list = values.get(type);
188 if (list == null || list.isEmpty())
190 return list.get(list.size() - 1);
194 * Return the minimum value of the specified type in the branch, or NaN if the type
197 * @param type the parameter type.
198 * @return the minimum value in this branch, or NaN.
200 public double getMinimum(FlightDataType type) {
201 Double v = minValues.get(type);
208 * Return the maximum value of the specified type in the branch, or NaN if the type
211 * @param type the parameter type.
212 * @return the maximum value in this branch, or NaN.
214 public double getMaximum(FlightDataType type) {
215 Double v = maxValues.get(type);
223 * Add a flight event to this branch.
225 * @param event the event to add.
226 * @throws IllegalStateException if this branch has been made immutable.
228 public void addEvent(FlightEvent event) {
230 events.add(event.resetSourceAndData());
236 * Return the list of events.
238 * @return the list of events during the flight.
240 public List<FlightEvent> getEvents() {
241 return events.clone();
246 * Make this FlightDataBranch immutable. Any calls to the set methods that would
247 * modify this object will after this call throw an <code>IllegalStateException</code>.
249 public void immute() {
255 * Return whether this branch is still mutable.
257 public boolean isMutable() {
258 return mutable.isMutable();
263 public int getModID() {