- Implemented a DampingMoment simulation listener example
[debian/openrocket] / core / src / net / sf / openrocket / simulation / customexpression / RangeExpression.java
1 /*
2  * A range expression contains two indexExpressions for the beginning and end time index of a range
3  */
4
5 package net.sf.openrocket.simulation.customexpression;
6
7 import java.util.List;
8
9 import de.congrace.exp4j.Calculable;
10 import de.congrace.exp4j.ExpressionBuilder;
11 import de.congrace.exp4j.Variable;
12 import net.sf.openrocket.document.OpenRocketDocument;
13 import net.sf.openrocket.logging.LogHelper;
14 import net.sf.openrocket.simulation.customexpression.CustomExpression;
15 import net.sf.openrocket.simulation.FlightDataType;
16 import net.sf.openrocket.simulation.SimulationStatus;
17 import net.sf.openrocket.startup.Application;
18 import net.sf.openrocket.util.ArrayUtils;
19 import net.sf.openrocket.util.LinearInterpolator;
20 import net.sf.openrocket.util.MathUtil;
21
22 public class RangeExpression extends CustomExpression {
23         private static final LogHelper log = Application.getLogger();
24
25         private ExpressionBuilder startBuilder, endBuilder;
26         
27         public RangeExpression(OpenRocketDocument doc, String startTime, String endTime, String variableType) {
28                 super(doc);
29                 
30                 if ("".equals(startTime.trim())){
31                         startTime = "0";
32                 }
33                 if ("".equals(endTime.trim())){
34                         endTime = "t";
35                 }
36                 
37                 this.setName("");
38                 this.setSymbol(variableType);
39                 this.setExpressions(startTime, endTime);
40                 this.expression = variableType+startTime+endTime; // this is used just for generating the hash
41                 
42                 log.info("New range expression, "+startTime + " to "+endTime);
43         }
44         
45         /*
46          * Sets the actual expression string for this expression
47          */
48         private void setExpressions(String start, String end){
49                 
50                 startBuilder = new ExpressionBuilder(start);
51                 endBuilder = new ExpressionBuilder(end);
52                 for (String n : getAllSymbols()){
53                         startBuilder.withVariable(new Variable(n));
54                         endBuilder.withVariable(new Variable(n));
55                 }
56         }
57         
58         @Override
59         public Variable evaluate(SimulationStatus status){
60                 
61                 Calculable startCalc = buildExpression(startBuilder);
62                 Calculable endCalc = buildExpression(endBuilder);
63                 if (startCalc == null || endCalc == null){
64                         return new Variable("Unknown");
65                 }
66                 
67                 // Set the variables in the start and end calculators
68                 for (FlightDataType type : status.getFlightData().getTypes()){
69                         double value = status.getFlightData().getLast(type); 
70                         startCalc.setVariable( new Variable(type.getSymbol(), value ) );
71                         endCalc.setVariable( new Variable(type.getSymbol(), value ) );
72                 }               
73                 
74                 // From the given datatype, get the time and function values and make an interpolator
75
76                 //Note: must get in a way that flight data system will figure out units. Otherwise there will be a type conflict when we get the new data.
77                 FlightDataType type = FlightDataType.getType(null, getSymbol(), null);
78                 
79                 List<Double> data = status.getFlightData().get(type);
80                 List<Double> time = status.getFlightData().get(FlightDataType.TYPE_TIME);
81                 LinearInterpolator interp = new LinearInterpolator(time, data); 
82                 
83                 // Evaluate the expression to get the start and end of the range
84                 double startTime, endTime;
85                 try{
86                         startTime = startCalc.calculate().getDoubleValue();
87                         startTime = MathUtil.clamp(startTime, 0, Double.MAX_VALUE);
88                         
89                         endTime = endCalc.calculate().getDoubleValue();
90                         endTime = MathUtil.clamp(endTime, 0, time.get(time.size()-1));
91                 }
92                 catch (java.util.EmptyStackException e){
93                         log.user("Unable to calculate time index for range expression "+getSymbol()+" due to empty stack exception");
94                         return new Variable("Unknown");
95                 }
96                 
97                 // generate an array representing the range
98                 double step = status.getSimulationConditions().getSimulation().getOptions().getTimeStep();
99                 double[] t = ArrayUtils.range(startTime, endTime,  step);
100                 double[] y = new double[t.length]; 
101                 int i = 0;
102                 for (double tval : t){
103                         y[i] = interp.getValue( tval );
104                         i++;
105                 }
106                                 
107                 Variable result;
108                 if (y.length == 0){
109                         result = new Variable("Unknown");
110                 }
111                 else {
112                         result = new Variable(hash(), y, startTime, step);
113                 }
114                 
115                 return result;
116         }
117 }