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 list.set(list.size() - 1, value);
122 double min = minValues.get(type);
123 double max = maxValues.get(type);
125 if (Double.isNaN(min) || (value < min)) {
126 minValues.put(type, value);
128 if (Double.isNaN(max) || (value > max)) {
129 maxValues.put(type, value);
136 * Return the branch name.
138 public String getBranchName() {
143 * Return the variable types included in this branch. The types are sorted in their
146 public FlightDataType[] getTypes() {
147 FlightDataType[] array = values.keySet().toArray(new FlightDataType[0]);
153 * Return the number of data points in this branch.
155 public int getLength() {
156 for (FlightDataType t : values.keySet()) {
157 return values.get(t).size();
163 * Return an array of values for the specified variable type.
165 * @param type the variable type.
166 * @return a list of the variable values, or <code>null</code> if
167 * the variable type hasn't been added to this branch.
169 public List<Double> get(FlightDataType type) {
170 ArrayList<Double> list = values.get(type);
177 * Return the last value of the specified type in the branch, or NaN if the type is
180 * @param type the parameter type.
181 * @return the last value in this branch, or NaN.
183 public double getLast(FlightDataType type) {
184 ArrayList<Double> list = values.get(type);
185 if (list == null || list.isEmpty())
187 return list.get(list.size() - 1);
191 * Return the minimum value of the specified type in the branch, or NaN if the type
194 * @param type the parameter type.
195 * @return the minimum value in this branch, or NaN.
197 public double getMinimum(FlightDataType type) {
198 Double v = minValues.get(type);
205 * Return the maximum value of the specified type in the branch, or NaN if the type
208 * @param type the parameter type.
209 * @return the maximum value in this branch, or NaN.
211 public double getMaximum(FlightDataType type) {
212 Double v = maxValues.get(type);
220 * Add a flight event to this branch.
222 * @param event the event to add.
223 * @throws IllegalStateException if this branch has been made immutable.
225 public void addEvent(FlightEvent event) {
227 events.add(event.resetSourceAndData());
233 * Return the list of events.
235 * @return the list of events during the flight.
237 public List<FlightEvent> getEvents() {
238 return events.clone();
243 * Make this FlightDataBranch immutable. Any calls to the set methods that would
244 * modify this object will after this call throw an <code>IllegalStateException</code>.
246 public void immute() {
252 * Return whether this branch is still mutable.
254 public boolean isMutable() {
255 return mutable.isMutable();
260 public int getModID() {