2 * A range expression contains two indexExpressions for the beginning and end time index of a range
5 package net.sf.openrocket.simulation.customexpression;
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;
22 public class RangeExpression extends CustomExpression {
23 private static final LogHelper log = Application.getLogger();
25 private ExpressionBuilder startBuilder, endBuilder;
27 public RangeExpression(OpenRocketDocument doc, String startTime, String endTime, String variableType) {
30 if ("".equals(startTime.trim())){
33 if ("".equals(endTime.trim())){
38 this.setSymbol(variableType);
39 this.setExpressions(startTime, endTime);
40 this.expression = variableType+startTime+endTime; // this is used just for generating the hash
42 log.info("New range expression, "+startTime + " to "+endTime);
46 * Sets the actual expression string for this expression
48 private void setExpressions(String start, String end){
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));
59 public Variable evaluate(SimulationStatus status){
61 Calculable startCalc = buildExpression(startBuilder);
62 Calculable endCalc = buildExpression(endBuilder);
63 if (startCalc == null || endCalc == null){
64 return new Variable("Unknown");
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 ) );
74 // From the given datatype, get the time and function values and make an interpolator
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);
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);
83 // Evaluate the expression to get the start and end of the range
84 double startTime, endTime;
86 startTime = startCalc.calculate().getDoubleValue();
87 startTime = MathUtil.clamp(startTime, 0, Double.MAX_VALUE);
89 endTime = endCalc.calculate().getDoubleValue();
90 endTime = MathUtil.clamp(endTime, 0, time.get(time.size()-1));
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");
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];
102 for (double tval : t){
103 y[i] = interp.getValue( tval );
109 result = new Variable("Unknown");
112 result = new Variable(hash(), y, startTime, step);