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);
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 public List<Double> get(FlightDataType type) {
161 ArrayList<Double> list = values.get(type);
168 * Return the last value of the specified type in the branch, or NaN if the type is
171 * @param type the parameter type.
172 * @return the last value in this branch, or NaN.
174 public double getLast(FlightDataType type) {
175 ArrayList<Double> list = values.get(type);
176 if (list == null || list.isEmpty())
178 return list.get(list.size() - 1);
182 * Return the minimum value of the specified type in the branch, or NaN if the type
185 * @param type the parameter type.
186 * @return the minimum value in this branch, or NaN.
188 public double getMinimum(FlightDataType type) {
189 Double v = minValues.get(type);
196 * Return the maximum value of the specified type in the branch, or NaN if the type
199 * @param type the parameter type.
200 * @return the maximum value in this branch, or NaN.
202 public double getMaximum(FlightDataType type) {
203 Double v = maxValues.get(type);
211 * Add a flight event to this branch.
213 * @param event the event to add.
214 * @throws IllegalStateException if this branch has been made immutable.
216 public void addEvent(FlightEvent event) {
218 events.add(event.resetSourceAndData());
224 * Return the list of events.
226 * @return the list of events during the flight.
228 public List<FlightEvent> getEvents() {
229 return events.clone();
234 * Make this FlightDataBranch immutable. Any calls to the set methods that would
235 * modify this object will after this call throw an <code>IllegalStateException</code>.
237 public void immute() {
243 * Return whether this branch is still mutable.
245 public boolean isMutable() {
246 return mutable.isMutable();
251 public int getModID() {