dlg.but.cancel = Cancel
dlg.but.close = Close
-
! General file type names
filetypes.pdf = PDF files (*.pdf)
BasicFrame.SimpleFileFilter1 = All rocket designs (*.ork; *.rkt)
simedtdlg.tab.Launchcond = Launch conditions
simedtdlg.tab.Simopt = Simulation options
simedtdlg.tab.Plotdata = Plot data
+simedtdlg.tab.CustomExpressions = Custom expressions
simedtdlg.tab.Exportdata = Export data
simedtdlg.lbl.Motorcfg = Motor configuration:
simedtdlg.lbl.ttip.Motorcfg = Select the motor configuration to use.
CsvOptionPanel.separator.tab = TAB
+! Custom expression general stuff
+customExpression.Name = Name
+customExpression.Symbol = Symbol
+customExpression.Expression = Expression
+customExpression.Units = Units
+customExpression.Operator = Operator
+customExpression.Description = Description
+
+! Custom expression panel
+customExpressionPanel.but.NewExpression = New expression
+customExpressionPanel.lbl.UpdateNote = You must run the simulation before data will be available for plotting.
+customExpressionPanel.lbl.CalcNote = Expressions will be calculated in the order shown.
+customExpressionPanel.lbl.CustomExpressions = Custom Expressions :
+customExpression.Units.but.ttip.Remove = Remove this expression
+customExpression.Units.but.ttip.Edit = Edit this expression
+customExpression.Units.but.ttip.MoveUp = Move expression up in calculation order
+customExpression.Units.but.ttip.MoveDown = Move expression down in calculation order
+
+! Custom expression builder window
+ExpressionBuilderDialog.title = Expression Builder
+ExpressionBuilderDialog.InsertVariable = Insert Variable
+ExpressionBuilderDialog.InsertOperator = Insert Operator
+ExpressionBuilderDialog.led.ttip.Name = Name must not have already been used
+ExpressionBuilderDialog.led.ttip.Symbol = Symbol must not have already been used
+ExpressionBuilderDialog.led.ttip.Expression = Expression must use only known symbols and operators
+
+! Custom expression variable selector
+CustomVariableSelector.title = Variable Selector
+
+! Custom operator selector
+CustomOperatorSelector.title = Operator Selector
! MotorPlot
MotorPlot.title.Motorplot = Motor plot
MotorPlot.txt.Delays = Delays:
MotorPlot.txt.Comment = Comment:\n
-
-
! Simulation plot panel
simplotpanel.lbl.Presetplotconf = Preset plot configurations:
simplotpanel.lbl.Xaxistype = X axis type:
SimulationPlotPanel.error.noPlotSelected = Please add one or more variables to plot on the Y-axis.
SimulationPlotPanel.error.noPlotSelected.title = Nothing to plot
-
! Component add buttons
compaddbuttons.Bodycompandfinsets = Body components and fin sets
compaddbuttons.Nosecone = Nose cone
edit-paste.png
edit-redo.png
edit-undo.png
+down.png
+pencil.png
+up.png
edit-scale.png (modified from edit-copy.png)
import net.sf.openrocket.rocketcomponent.Configuration;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.simulation.BasicEventSimulationEngine;
+import net.sf.openrocket.simulation.CustomExpression;
import net.sf.openrocket.simulation.FlightData;
import net.sf.openrocket.simulation.RK4SimulationStepper;
import net.sf.openrocket.simulation.SimulationConditions;
private SimulationOptions options;
private ArrayList<String> simulationListeners = new ArrayList<String>();
+ private ArrayList<CustomExpression> customExpressions = new ArrayList<CustomExpression>();
private final Class<? extends SimulationEngine> simulationEngineClass = BasicEventSimulationEngine.class;
private Class<? extends SimulationStepper> simulationStepperClass = RK4SimulationStepper.class;
private Class<? extends AerodynamicCalculator> aerodynamicCalculatorClass = BarrowmanCalculator.class;
private Class<? extends MassCalculator> massCalculatorClass = BasicMassCalculator.class;
-
-
/** Listeners for this object */
private List<EventListener> listeners = new ArrayList<EventListener>();
}
+ public void addCustomExpression(CustomExpression expression){
+ this.status = Simulation.Status.OUTDATED;
+ log.debug("Simulation must be run again to update custom expression.");
+ customExpressions.add(expression);
+ }
+
+ public void removeCustomExpression(CustomExpression expression){
+ customExpressions.remove(expression);
+ }
+
+ public ArrayList<CustomExpression> getCustomExpressions(){
+ return customExpressions;
+ }
+
/**
* Return the rocket associated with this simulation.
}
SimulationConditions simulationConditions = options.toSimulationConditions();
+ simulationConditions.setSimulation(this);
for (SimulationListener l : additionalListeners) {
simulationConditions.getSimulationListenerList().add(l);
}
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
import net.sf.openrocket.rocketcomponent.TubeCoupler;
+import net.sf.openrocket.simulation.CustomExpression;
import net.sf.openrocket.simulation.FlightData;
import net.sf.openrocket.simulation.FlightDataBranch;
import net.sf.openrocket.simulation.FlightDataType;
writeln("<name>" + escapeXML(simulation.getName()) + "</name>");
// TODO: MEDIUM: Other simulators/calculators
+
writeln("<simulator>RK4Simulator</simulator>");
writeln("<calculator>BarrowmanCalculator</calculator>");
- writeln("<conditions>");
- indent++;
+
+ // Write out custom expressions
+ if (!simulation.getCustomExpressions().isEmpty()){
+ writeln("<customexpressions>"); indent++;
+ for (CustomExpression expression : simulation.getCustomExpressions()){
+ writeln("<expression>"); indent++;
+ writeElement("name", expression.getName());
+ writeElement("symbol", expression.getSymbol());
+ writeElement("unit", expression.getUnit());
+ writeElement("expressionstring", expression.getExpressionString());
+ indent--; writeln("</expression>");
+ }
+ indent--; writeln("</customexpressions>");
+ }
+
+ writeln("<conditions>"); indent++;
writeElement("configid", cond.getMotorConfigurationID());
writeElement("launchrodlength", cond.getLaunchRodLength());
writeElement("listener", escapeXML(s));
}
-
// Write basic simulation data
FlightData data = simulation.getSimulatedData();
import net.sf.openrocket.rocketcomponent.Transition;
import net.sf.openrocket.rocketcomponent.TrapezoidFinSet;
import net.sf.openrocket.rocketcomponent.TubeCoupler;
+import net.sf.openrocket.simulation.CustomExpression;
import net.sf.openrocket.simulation.FlightData;
import net.sf.openrocket.simulation.FlightDataBranch;
import net.sf.openrocket.simulation.FlightDataType;
}
class SingleSimulationHandler extends AbstractElementHandler {
+ private static final LogHelper log = Application.getLogger();
+
private final DocumentLoadingContext context;
private final OpenRocketDocument doc;
private SimulationConditionsHandler conditionHandler;
private FlightDataHandler dataHandler;
-
+ private CustomExpressionsHandler customExpressionsHandler;
+
+ private ArrayList<CustomExpression> customExpressions = new ArrayList<CustomExpression>();
private final List<String> listeners = new ArrayList<String>();
public SingleSimulationHandler(OpenRocketDocument doc, DocumentLoadingContext context) {
this.context = context;
}
-
+ public void setCustomExpressions(ArrayList<CustomExpression> expressions){
+ this.customExpressions = expressions;
+ }
@Override
public ElementHandler openElement(String element, HashMap<String, String> attributes,
if (element.equals("name") || element.equals("simulator") ||
element.equals("calculator") || element.equals("listener")) {
return PlainTextHandler.INSTANCE;
+ } else if (element.equals("customexpressions")) {
+ customExpressionsHandler = new CustomExpressionsHandler(this, context);
+ return customExpressionsHandler;
} else if (element.equals("conditions")) {
conditionHandler = new SimulationConditionsHandler(doc.getRocket(), context);
return conditionHandler;
Simulation simulation = new Simulation(doc.getRocket(), status, name,
conditions, listeners, data);
-
+
+ // Note : arraylist implementation in simulation different from standard one
+ for (CustomExpression exp : customExpressions){
+ exp.setSimulation(simulation);
+ if (exp.checkAll())
+ simulation.addCustomExpression(exp);
+ }
+
doc.addSimulation(simulation);
}
}
+class CustomExpressionsHandler extends AbstractElementHandler {
+ private final DocumentLoadingContext context;
+ private final SingleSimulationHandler simHandler;
+ public CustomExpression currentExpression = new CustomExpression();
+ private final ArrayList<CustomExpression> customExpressions = new ArrayList<CustomExpression>();
+
+ public CustomExpressionsHandler(SingleSimulationHandler simHandler, DocumentLoadingContext context) {
+ this.context = context;
+ this.simHandler = simHandler;
+ }
+
+ @Override
+ public ElementHandler openElement(String element,
+ HashMap<String, String> attributes, WarningSet warnings)
+ throws SAXException {
+
+ if (element.equals("expression")){
+ currentExpression = new CustomExpression();
+ }
+
+ return this;
+ }
+ @Override
+ public void closeElement(String element, HashMap<String, String> attributes,
+ String content, WarningSet warnings) {
+
+ if (element.equals("expression"))
+ customExpressions.add(currentExpression);
+
+ if (element.equals("name"))
+ currentExpression.setName(content);
+
+ else if (element.equals("symbol"))
+ currentExpression.setSymbol(content);
+
+ else if (element.equals("unit"))
+ currentExpression.setUnit(content);
+
+ else if (element.equals("expressionstring"))
+ currentExpression.setExpression(content);
+
+ }
+
+ @Override
+ public void endHandler(String element, HashMap<String, String> attributes,
+ String content, WarningSet warnings) {
+ simHandler.setCustomExpressions(customExpressions);
+ }
+}
+
class SimulationConditionsHandler extends AbstractElementHandler {
private final DocumentLoadingContext context;
private SimulationOptions conditions;
String[] split = typeList.split(",");
types = new FlightDataType[split.length];
for (int i = 0; i < split.length; i++) {
- types[i] = FlightDataType.getType(split[i], UnitGroup.UNITS_NONE);
+ types[i] = FlightDataType.getType(split[i], "None ("+split[i]+")", UnitGroup.UNITS_NONE);
+ // TODO: HIGH: Deal with symbols
}
// TODO: LOW: May throw an IllegalArgumentException
--- /dev/null
+package net.sf.openrocket.gui.customexpression;
+
+import java.awt.Color;
+import java.awt.Window;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.Collections;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.SwingUtilities;
+
+import net.miginfocom.swing.MigLayout;
+import net.sf.openrocket.document.Simulation;
+import net.sf.openrocket.gui.components.DescriptionArea;
+import net.sf.openrocket.gui.components.UnitSelector;
+import net.sf.openrocket.gui.customexpression.ExpressionBuilderDialog;
+import net.sf.openrocket.gui.util.Icons;
+import net.sf.openrocket.l10n.Translator;
+import net.sf.openrocket.logging.LogHelper;
+import net.sf.openrocket.simulation.CustomExpression;
+import net.sf.openrocket.startup.Application;
+
+public class CustomExpressionPanel extends JPanel {
+
+ private static final LogHelper log = Application.getLogger();
+ private static final Translator trans = Application.getTranslator();
+
+ private JPanel expressionSelectorPanel;
+ private Simulation simulation;
+
+ public CustomExpressionPanel(final Simulation simulation) {
+ super(new MigLayout("fill"));
+ this.simulation = simulation;
+
+ expressionSelectorPanel = new JPanel(new MigLayout("gapy rel"));
+ JScrollPane scroll = new JScrollPane(expressionSelectorPanel);
+ this.add(scroll, "spany 2, height 10px, wmin 400lp, grow 100, gapright para");
+
+ DescriptionArea desc = new DescriptionArea(trans.get("customExpressionPanel.lbl.UpdateNote")+"\n\n"+trans.get("customExpressionPanel.lbl.CalcNote"), 8, -2f);
+ desc.setViewportBorder(BorderFactory.createEmptyBorder());
+ this.add(desc, "width 1px, growx 1, wrap unrel");
+
+ //// New expression
+ JButton button = new JButton(trans.get("customExpressionPanel.but.NewExpression"));
+ button.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // Open window to configure expression
+ log.debug("Opening window to configure new expression");
+ Window parent = SwingUtilities.getWindowAncestor(CustomExpressionPanel.this);
+ new ExpressionBuilderDialog(parent, simulation).setVisible(true);
+ updateExpressions();
+ }
+ });
+
+ this.add(button, "left");
+
+ updateExpressions();
+ }
+
+ /*
+ * Update the expressionSelectorPanel
+ */
+ private void updateExpressions(){
+
+ expressionSelectorPanel.removeAll();
+ for (CustomExpression expression : simulation.getCustomExpressions()){
+ SingleExpression se = new SingleExpression(expression);
+ expressionSelectorPanel.add(se, "wrap");
+ }
+
+ //TODO: High : Find out why repaint method not working properly here.
+ //expressionSelectorPanel.repaint();
+ expressionSelectorPanel.updateUI(); // Not the correct method to use but works
+
+
+ }
+
+ private void deleteExpression(CustomExpression expression){
+ simulation.getCustomExpressions().remove(expression);
+ }
+
+ /**
+ * Moves an expression up or down in the expression list
+ * @param expression
+ * @param move integer - +1 to move down, -1 to move up
+ */
+ private void moveExpression(CustomExpression expression, int move){
+ ArrayList<CustomExpression> expressions = simulation.getCustomExpressions();
+ int i = expressions.indexOf(expression);
+ if (i+move == expressions.size() || i+move < 0)
+ return;
+ else
+ Collections.swap(expressions, i, i+move);
+ }
+
+
+ /*
+ * A JPanel which configures a single expression
+ */
+ private class SingleExpression extends JPanel {
+
+ // Convenience method to make the labels consistent
+ private JLabel setLabelStyle(JLabel l){
+ l.setBackground(Color.WHITE);
+ l.setOpaque(true);
+ l.setBorder(BorderFactory.createRaisedBevelBorder() );
+ l.setText(" " + l.getText() + " ");
+ return l;
+ }
+
+ private SingleExpression(final CustomExpression expression) {
+ super(new MigLayout("ins 0"));
+ // name: aName symbol: a Unit: m/s
+ //super(new MigLayout("","[::100][:200:400][::100][:100:200][::100][:100:200]",""));
+
+ JLabel nameLabel = new JLabel( trans.get("customExpression.Name")+ " :");
+ JLabel name = new JLabel ( expression.getName() );
+ name = setLabelStyle(name);
+ JLabel symbolLabel = new JLabel( trans.get("customExpression.Symbol")+ " :" );
+ JLabel symbol = new JLabel ( expression.getSymbol());
+ symbol = setLabelStyle(symbol);
+ symbol.setBackground(Color.WHITE);
+
+ JLabel unitLabel = new JLabel( trans.get("customExpression.Units")+ " :");
+ UnitSelector unitSelector = new UnitSelector(expression.getType().getUnitGroup());
+
+ JButton editButton = new JButton(Icons.EDIT);
+ editButton.setToolTipText(trans.get("customExpression.Units.but.ttip.Edit"));
+ editButton.setBorderPainted(false);
+ editButton.addActionListener( new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e){
+ Window parent = SwingUtilities.getWindowAncestor(CustomExpressionPanel.this);
+ expression.editExpression(parent);
+ updateExpressions();
+ }
+ });
+
+ JButton upButton = new JButton(Icons.UP);
+ upButton.setToolTipText(trans.get("customExpression.Units.but.ttip.MoveUp"));
+ upButton.setBorderPainted(false);
+ upButton.addActionListener( new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ moveExpression(expression, -1);
+ updateExpressions();
+ }
+ });
+
+ JButton downButton = new JButton(Icons.DOWN);
+ downButton.setToolTipText(trans.get("customExpression.Units.but.ttip.MoveDown"));
+ downButton.setBorderPainted(false);
+ downButton.addActionListener( new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ moveExpression(expression, 1);
+ updateExpressions();
+ }
+ });
+
+
+ JButton deleteButton = new JButton(Icons.DELETE);
+ //// Remove this expression
+ deleteButton.setToolTipText(trans.get("customExpression.Units.but.ttip.Remove"));
+ deleteButton.setBorderPainted(false);
+ deleteButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ deleteExpression(expression);
+ updateExpressions();
+ }
+ });
+
+ this.add(nameLabel);
+ this.add(name, "width 200:200:400, growx");
+ this.add(new JPanel());
+ this.add(symbolLabel);
+ this.add(symbol, "width :50:200");
+ this.add(new JPanel());
+ this.add(unitLabel);
+ this.add(unitSelector, "width :50:100");
+ this.add(new JPanel(), "growx");
+ this.add(upButton, "right");
+ this.add(downButton, "right");
+ this.add(editButton, "right");
+ this.add(deleteButton, "right");
+ }
+ }
+}
--- /dev/null
+package net.sf.openrocket.gui.customexpression;
+
+import java.awt.Window;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
+
+import javax.swing.ImageIcon;
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.SwingUtilities;
+
+import net.miginfocom.swing.MigLayout;
+import net.sf.openrocket.document.Simulation;
+import net.sf.openrocket.gui.util.Icons;
+import net.sf.openrocket.l10n.Translator;
+import net.sf.openrocket.logging.LogHelper;
+import net.sf.openrocket.simulation.CustomExpression;
+import net.sf.openrocket.startup.Application;
+
+/**
+ * Dialog box for making a custom expression
+ * @author Richard Graham
+ *
+ */
+
+public class ExpressionBuilderDialog extends JDialog {
+
+ private static final Translator trans = Application.getTranslator();
+ private static final LogHelper log = Application.getLogger();
+
+ private static final ImageIcon GreenIcon = Icons.loadImageIcon("pix/spheres/green-16x16.png", "OK");
+ private static final ImageIcon RedIcon = Icons.loadImageIcon("pix/spheres/red-16x16.png", "Bad");
+
+ private CustomExpression expression;
+ private CustomExpression previousExpressionCopy;
+
+ private final Window parentWindow;
+ private final Simulation simulation;
+
+ // Define these check indicators to show if fields are OK
+ private final JLabel nameCheck = new JLabel(RedIcon);
+ private final JLabel expressionCheck = new JLabel(RedIcon);
+ private final JLabel unitCheck = new JLabel(RedIcon);
+ private final JButton okButton = new JButton(trans.get("dlg.but.ok"));
+ private final JTextField expressionField = new JTextField(20);
+
+ public ExpressionBuilderDialog(Window parent, Simulation simulation){
+ this(parent, simulation, new CustomExpression(simulation));
+ }
+
+ public ExpressionBuilderDialog(Window parent, final Simulation simulation, final CustomExpression previousExpression){
+
+ super(parent, trans.get("ExpressionBuilderDialog.title"), JDialog.ModalityType.DOCUMENT_MODAL);
+
+ this.parentWindow = parent;
+ this.simulation = simulation;
+ this.previousExpressionCopy = (CustomExpression) previousExpression.clone();
+ this.expression = previousExpression;
+
+ //// Name box -- Check input when focus changes and transfer focus to next box on enter key
+ JLabel nameLabel = new JLabel(trans.get("customExpression.Name"));
+ final JTextField nameField = new JTextField(20);
+ nameField.setText(expression.getName());
+ nameField.setFocusTraversalKeysEnabled(true);
+ nameField.addFocusListener(new FocusListener() {
+ @Override
+ public void focusGained(FocusEvent e) { }
+
+ @Override
+ public void focusLost(FocusEvent e) {
+ expression.setName(nameField.getText());
+ ExpressionBuilderDialog.this.updateOK();
+ }
+ });
+ nameField.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent arg0) {
+ nameField.transferFocus();
+ }
+ });
+
+ //// Expression box -- for this one we check after each keypress using a keyListener. Enter transfers to next field
+ JLabel expressionLabel = new JLabel(trans.get("customExpression.Expression"));
+ expressionField.setText(expression.getExpressionString());
+ expressionField.addKeyListener(new KeyListener() {
+ @Override
+ public void keyReleased(KeyEvent arg0) {
+ expression.setExpression( expressionField.getText() );
+ ExpressionBuilderDialog.this.updateOK();
+ }
+
+ @Override
+ public void keyPressed(KeyEvent e) {}
+
+ @Override
+ public void keyTyped(KeyEvent e) {}
+ });
+ expressionField.addActionListener(new ActionListener(){
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ expressionField.transferFocus();
+ }
+ });
+
+ //// Units box -- with action listeners checking input after change in focus or enter press
+ JLabel unitLabel = new JLabel(trans.get("customExpression.Units"));
+ final JTextField unitField = new JTextField(5);
+ unitField.setText(expression.getUnit());
+ unitField.addFocusListener(new FocusListener(){
+ @Override
+ public void focusLost(FocusEvent arg0) {
+ expression.setUnit(unitField.getText()) ;
+ ExpressionBuilderDialog.this.updateOK();
+ }
+ @Override
+ public void focusGained(FocusEvent arg0) {}
+ });
+ unitField.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ unitField.transferFocus();
+ }
+ });
+
+ //// Symbol box
+ JLabel symbolLabel = new JLabel(trans.get("customExpression.Symbol"));
+ final JTextField symbolField = new JTextField(5);
+ symbolField.setText(expression.getSymbol());
+ symbolField.addFocusListener(new FocusListener(){
+ @Override
+ public void focusLost(FocusEvent arg0) {
+ expression.setSymbol(symbolField.getText()) ;
+ ExpressionBuilderDialog.this.updateOK();
+ }
+ @Override
+ public void focusGained(FocusEvent arg0) {}
+ });
+ symbolField.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ symbolField.transferFocus();
+ }
+ });
+
+
+ //// Insert variable button
+ final JButton insertVariableButton = new JButton(trans.get("ExpressionBuilderDialog.InsertVariable"));
+ insertVariableButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ log.debug("Opening insert variable window");
+ Window parentWindow = SwingUtilities.getWindowAncestor(ExpressionBuilderDialog.this);
+ new VariableSelector(parentWindow, ExpressionBuilderDialog.this, simulation).setVisible(true);
+ }
+ });
+
+ //// Insert operator button
+ final JButton insertOperatorButton = new JButton(trans.get("ExpressionBuilderDialog.InsertOperator"));
+ insertOperatorButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ log.debug("Opening insert operator window");
+ Window parentWindow = SwingUtilities.getWindowAncestor(ExpressionBuilderDialog.this);
+ new OperatorSelector(parentWindow, ExpressionBuilderDialog.this).setVisible(true);
+ }
+ });
+
+
+ //// OK Button
+ okButton.setEnabled(false);
+ okButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ expression.addToSimulation();
+ ExpressionBuilderDialog.this.dispose();
+ }
+ });
+
+ //// Cancel button
+ final JButton cancelButton = new JButton(trans.get("dlg.but.cancel"));
+ cancelButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ expression.overwrite(previousExpressionCopy);
+ ExpressionBuilderDialog.this.dispose();
+ }
+ });
+
+ //// Set to tips
+ nameCheck.setToolTipText(trans.get("ExpressionBuilderDialog.led.ttip.Name"));
+ unitCheck.setToolTipText(trans.get("ExpressionBuilderDialog.led.ttip.Symbol"));
+ expressionCheck.setToolTipText(trans.get("ExpressionBuilderDialog.led.ttip.Expression"));
+
+ //// Do the layout
+ JPanel mainPanel = new JPanel(new MigLayout());
+ mainPanel.add(nameLabel);
+ mainPanel.add(nameField);
+ mainPanel.add(nameCheck, "wrap, center");
+ mainPanel.add(symbolLabel);
+ mainPanel.add(symbolField, "split 4, growx");
+ mainPanel.add(new JPanel());
+ mainPanel.add(unitLabel, "right");
+ mainPanel.add(unitField, "right, growx");
+ mainPanel.add(unitCheck, "wrap, center");
+ mainPanel.add(expressionLabel);
+ mainPanel.add(expressionField);
+ mainPanel.add(expressionCheck, "wrap, center");
+ mainPanel.add(insertOperatorButton, "span 2, right, split 2");
+ mainPanel.add(insertVariableButton, "right, wrap");
+ mainPanel.add(cancelButton, "span 2, right, width :50:100");
+ mainPanel.add(okButton, "right, width :50:100, wrap");
+
+ this.add(mainPanel);
+ this.validate();
+ this.pack();
+ this.setLocationByPlatform(true);
+ this.updateOK();
+
+ }
+
+ /**
+ * Enable OK button only if all the fields are ok
+ * @param okButton
+ */
+ protected void updateOK() {
+
+ boolean nameOK = expression.checkName();
+ boolean unitOK = expression.checkUnit();
+ boolean symbolOK = expression.checkSymbol();
+ boolean expressionOK = expression.checkExpression();
+
+ if (nameOK) { nameCheck.setIcon(GreenIcon); } else { nameCheck.setIcon(RedIcon); }
+ if (unitOK && symbolOK) { unitCheck.setIcon(GreenIcon); } else { unitCheck.setIcon(RedIcon); }
+ if (expressionOK) { expressionCheck.setIcon(GreenIcon); } else { expressionCheck.setIcon(RedIcon); }
+
+ okButton.setEnabled( nameOK && unitOK && symbolOK && expressionOK );
+ }
+
+ /**
+ * Inserts a string into the expression box at the position of the cursor.
+ * String will be padded with spaces either side
+ * Expression box will be focused after this is called.
+ * For strings containing an ( , cursor will be moved to the point after that, otherwise, cursor will move to the end of the inserted string.
+ * @param str
+ */
+ public void pasteIntoExpression(String str) {
+ int pos = expressionField.getCaretPosition();
+ String current = expressionField.getText();
+ expressionField.setText(current.subSequence(0, pos) + " " + str + " " + current.subSequence(pos, current.length()));
+ expressionField.requestFocus();
+ int bracketPos = str.indexOf("(");
+ if (bracketPos != -1){
+ expressionField.setCaretPosition(pos+2+bracketPos);
+ }
+ else {
+ expressionField.setCaretPosition(pos+2+str.length());
+ }
+ }
+}
--- /dev/null
+package net.sf.openrocket.gui.customexpression;
+
+import java.awt.Window;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import net.miginfocom.swing.MigLayout;
+import net.sf.openrocket.l10n.Translator;
+import net.sf.openrocket.logging.LogHelper;
+import net.sf.openrocket.startup.Application;
+
+public class OperatorSelector extends JDialog {
+
+ private static final Translator trans = Application.getTranslator();
+ private static final LogHelper log = Application.getLogger();
+
+ private final Window parentWindow;
+
+ public OperatorSelector(Window parent, final ExpressionBuilderDialog parentBuilder){
+
+ super(parent, trans.get("CustomOperatorSelector.title"), JDialog.ModalityType.DOCUMENT_MODAL);
+
+ this.parentWindow = parent;
+
+ final JButton insertButton = new JButton(trans.get("ExpressionBuilderDialog.InsertOperator"));
+
+ JPanel mainPanel = new JPanel(new MigLayout());
+
+ //// Table of variables and model
+ final OperatorTableModel tableModel = new OperatorTableModel();
+ final JTable table = new JTable(tableModel);
+
+ table.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
+ int width = table.getColumnModel().getTotalColumnWidth();
+ table.getColumnModel().getColumn(0).setPreferredWidth( (int) (.2 * width));
+ table.getColumnModel().getColumn(1).setPreferredWidth( (int) (.8 * width));
+
+ JScrollPane scrollPane = new JScrollPane(table);
+ table.setFillsViewportHeight(true);
+ table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+ @Override
+ public void valueChanged(ListSelectionEvent e){
+ if (table.getSelectedRowCount() == 1){
+ insertButton.setEnabled(true);
+ }
+ else {
+ insertButton.setEnabled(false);
+ }
+ }
+ });
+
+ mainPanel.add(scrollPane, "wrap");
+
+ //// Cancel button
+ final JButton cancelButton = new JButton(trans.get("dlg.but.cancel"));
+ cancelButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ OperatorSelector.this.dispose();
+ }
+ });
+ mainPanel.add(cancelButton, "right, width :100:200, split 2");
+
+ //// Insert button
+ insertButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ int row = table.getSelectedRow();
+ String str = tableModel.getOperatorAt(row);
+ parentBuilder.pasteIntoExpression(str);
+ OperatorSelector.this.dispose();
+ }
+ });
+ insertButton.setEnabled(false); // disabled by default, only enable when a variable selected
+ mainPanel.add(insertButton, "right, width :100:200, wrap");
+
+ this.add(mainPanel);
+ this.validate();
+ this.pack();
+ this.setLocationByPlatform(true);
+ }
+}
--- /dev/null
+package net.sf.openrocket.gui.customexpression;
+
+import javax.swing.table.AbstractTableModel;
+
+import net.sf.openrocket.l10n.Translator;
+import net.sf.openrocket.simulation.CustomExpression;
+import net.sf.openrocket.startup.Application;
+
+public class OperatorTableModel extends AbstractTableModel {
+
+ private static final Translator trans = Application.getTranslator();
+
+ private static final String[] columnNames = {trans.get("customExpression.Operator"), trans.get("customExpression.Description")};
+
+ private final Object[] operators = CustomExpression.AVAILABLE_OPERATORS.keySet().toArray();
+ private final Object[] descriptions = CustomExpression.AVAILABLE_OPERATORS.values().toArray();
+
+ public OperatorTableModel(){
+
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 2;
+ }
+
+ @Override
+ public int getRowCount() {
+ return CustomExpression.AVAILABLE_OPERATORS.size();
+ }
+
+ @Override
+ public Object getValueAt(int row, int col) {
+ if (col == 0){
+ return operators[row].toString();
+ }
+ else if (col == 1){
+ return descriptions[row].toString();
+ }
+ return null;
+ }
+
+ @Override
+ public String getColumnName(int col) {
+ return columnNames[col];
+ }
+
+ public String getOperatorAt(int row) {
+ return operators[row].toString();
+ }
+
+}
--- /dev/null
+package net.sf.openrocket.gui.customexpression;
+
+import java.awt.Window;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
+
+import net.miginfocom.swing.MigLayout;
+import net.sf.openrocket.document.Simulation;
+import net.sf.openrocket.l10n.Translator;
+import net.sf.openrocket.logging.LogHelper;
+import net.sf.openrocket.startup.Application;
+
+/**
+ * Dialog to select from available custom variables
+ * @author Richard Graham
+ *
+ */
+
+public class VariableSelector extends JDialog {
+
+ private static final Translator trans = Application.getTranslator();
+ private static final LogHelper log = Application.getLogger();
+
+ private final Window parentWindow;
+ private final Simulation simulation;
+
+ public VariableSelector(Window parent, final ExpressionBuilderDialog parentBuilder, final Simulation simulation){
+
+ super(parent, trans.get("CustomVariableSelector.title"), JDialog.ModalityType.DOCUMENT_MODAL);
+
+ this.parentWindow = parent;
+ this.simulation = simulation;
+
+ final JButton insertButton = new JButton(trans.get("ExpressionBuilderDialog.InsertVariable"));
+
+ JPanel mainPanel = new JPanel(new MigLayout());
+
+ //// Table of variables and model
+ final VariableTableModel tableModel = new VariableTableModel(simulation);
+ final JTable table = new JTable(tableModel);
+
+ table.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
+ int width = table.getColumnModel().getTotalColumnWidth();
+ table.getColumnModel().getColumn(0).setPreferredWidth( (int) (.7 * width));
+ table.getColumnModel().getColumn(1).setPreferredWidth( (int) (.15 * width));
+ table.getColumnModel().getColumn(2).setPreferredWidth( (int) (.15 * width));
+
+ JScrollPane scrollPane = new JScrollPane(table);
+ table.setFillsViewportHeight(true);
+ table.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
+ @Override
+ public void valueChanged(ListSelectionEvent e){
+ if (table.getSelectedRowCount() == 1){
+ insertButton.setEnabled(true);
+ }
+ else {
+ insertButton.setEnabled(false);
+ }
+ }
+ });
+
+ mainPanel.add(scrollPane, "wrap");
+
+ //// Cancel button
+ final JButton cancelButton = new JButton(trans.get("dlg.but.cancel"));
+ cancelButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ VariableSelector.this.dispose();
+ }
+ });
+ mainPanel.add(cancelButton, "right, width :100:200, split 2");
+
+ //// Insert button
+ insertButton.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ int row = table.getSelectedRow();
+ String str = tableModel.getSymbolAt(row);
+ parentBuilder.pasteIntoExpression(str);
+ VariableSelector.this.dispose();
+ }
+ });
+ insertButton.setEnabled(false); // disabled by default, only enable when a variable selected
+ mainPanel.add(insertButton, "right, width :100:200, wrap");
+
+ this.add(mainPanel);
+ this.validate();
+ this.pack();
+ this.setLocationByPlatform(true);
+ }
+}
--- /dev/null
+/**
+ *
+ */
+package net.sf.openrocket.gui.customexpression;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+
+import javax.swing.table.AbstractTableModel;
+
+import net.sf.openrocket.document.Simulation;
+import net.sf.openrocket.l10n.Translator;
+import net.sf.openrocket.simulation.CustomExpression;
+import net.sf.openrocket.simulation.FlightDataType;
+import net.sf.openrocket.startup.Application;
+
+/**
+ * @author Richard Graham
+ *
+ */
+public class VariableTableModel extends AbstractTableModel {
+
+ private static final Translator trans = Application.getTranslator();
+
+ private ArrayList<FlightDataType> types = new ArrayList<FlightDataType>();
+ private static final String[] columnNames = {trans.get("customExpression.Name"), trans.get("customExpression.Symbol"), trans.get("customExpression.Units")};
+
+ /*
+ * Table model will be constructed with all the built in variables and any custom variables defined
+ */
+ public VariableTableModel(Simulation sim){
+
+ Collections.addAll(types, FlightDataType.ALL_TYPES);
+
+ for (CustomExpression expression : sim.getCustomExpressions()){
+ types.add(expression.getType());
+ }
+
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 3;
+ }
+
+ @Override
+ public int getRowCount() {
+ return types.size();
+ }
+
+ @Override
+ public Object getValueAt(int row, int col) {
+ if (col == 0)
+ return types.get(row).getName();
+ else if (col == 1)
+ return types.get(row).getSymbol();
+ else if (col == 2)
+ return types.get(row).getUnitGroup().getDefaultUnit().toString();
+
+ return null;
+ }
+
+ @Override
+ public String getColumnName(int col) {
+ return columnNames[col];
+ }
+
+ public String getSymbolAt(int row) {
+ if (row < 0 || row > types.size()){
+ return "";
+ }
+ else {
+ return types.get(row).getSymbol();
+ }
+ }
+}
import net.sf.openrocket.gui.components.SimulationExportPanel;
import net.sf.openrocket.gui.components.UnitSelector;
import net.sf.openrocket.gui.plot.Axis;
+import net.sf.openrocket.gui.customexpression.CustomExpressionPanel;
import net.sf.openrocket.gui.plot.PlotConfiguration;
import net.sf.openrocket.gui.plot.SimulationPlotPanel;
import net.sf.openrocket.gui.util.GUIUtil;
public static final int DEFAULT = -1;
public static final int EDIT = 1;
- public static final int PLOT = 2;
+ public static final int PLOT = 3;
private final Window parentWindow;
tabbedPane.addTab(trans.get("simedtdlg.tab.Launchcond"), flightConditionsTab());
//// Simulation options
tabbedPane.addTab(trans.get("simedtdlg.tab.Simopt"), simulationOptionsTab());
+ //// Custom expressions tab
+ tabbedPane.addTab(trans.get("simedtdlg.tab.CustomExpressions"), customExpressionsTab());
//// Plot data
tabbedPane.addTab(trans.get("simedtdlg.tab.Plotdata"), plotTab());
//// Export data
if (tab == EDIT) {
tabbedPane.setSelectedIndex(0);
} else if (tab == PLOT) {
- tabbedPane.setSelectedIndex(2);
+ tabbedPane.setSelectedIndex(3);
} else {
FlightData data = s.getSimulatedData();
if (data == null || data.getBranchCount() == 0)
}
-
+ private JPanel customExpressionsTab() {
+ return new CustomExpressionPanel(simulation);
+ }
/**
public static final Icon PREFERENCES = loadImageIcon("pix/icons/preferences.png", "Preferences");
public static final Icon DELETE = loadImageIcon("pix/icons/delete.png", "Delete");
+ public static final Icon EDIT = loadImageIcon("pix/icons/pencil.png", "Edit");
+ public static final Icon UP = loadImageIcon("pix/icons/up.png", "Up");
+ public static final Icon DOWN = loadImageIcon("pix/icons/down.png", "Down");
+
static {
log.debug("Icons loaded");
package net.sf.openrocket.simulation;
+import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
}
SimulationListenerHelper.firePostStep(status);
+ // Calculate values for custom expressions
+ FlightDataBranch data = status.getFlightData();
+ ArrayList<CustomExpression> allExpressions = status.getSimulationConditions().getSimulation().getCustomExpressions();
+ for (CustomExpression expression : allExpressions ) {
+ data.setValue(expression.getType(), expression.evaluate(status));
+ }
// Check for NaN values in the simulation status
checkNaN();
--- /dev/null
+package net.sf.openrocket.simulation;
+
+import java.awt.Window;
+import java.util.SortedMap;
+import java.util.TreeMap;
+
+import net.sf.openrocket.document.Simulation;
+import net.sf.openrocket.gui.customexpression.ExpressionBuilderDialog;
+import net.sf.openrocket.logging.LogHelper;
+import net.sf.openrocket.startup.Application;
+import net.sf.openrocket.unit.FixedUnitGroup;
+import net.sf.openrocket.unit.UnitGroup;
+import net.sf.openrocket.util.ArrayList;
+import de.congrace.exp4j.Calculable;
+import de.congrace.exp4j.ExpressionBuilder;
+
+
+/**
+ * Represents a single custom expression
+ * @author Richard Graham
+ *
+ */
+public class CustomExpression implements Cloneable{
+
+ private static final LogHelper log = Application.getLogger();
+
+ private String name, symbol, unit, expression;
+ private ExpressionBuilder builder;
+ private static Simulation sim = null;
+
+ // A map of available operator strings (keys) and description of function (value)
+ public static final SortedMap<String, String> AVAILABLE_OPERATORS = new TreeMap<String, String>() {{
+ put("+" , "Addition");
+ put("-" , "Subtraction");
+ put("*" , "Multiplication");
+ put("/" , "Divison");
+ put("%" , "Modulo");
+ put("^" , "Exponentiation");
+ put("abs()" , "Absolute value");
+ put("ceil()" , "Ceiling (next integer value");
+ put("floor()" , "Floor (previous integer value");
+ put("sqrt()" , "Square root");
+ put("cbrt()" , "Cubic root");
+ put("exp()" , "Euler\'s number raised to the value (e^x)");
+ put("log()" , "Natural logarithm");
+ put("sin()" , "Sine");
+ put("cos()" , "Cosine");
+ put("tan()" , "Tangent");
+ put("asin()" , "Arc sine");
+ put("acos()" , "Arc cosine");
+ put("atan()" , "Arc tangent");
+ put("sinh()" , "Hyerbolic sine");
+ put("cosh()" , "Hyperbolic cosine");
+ put("tanh()" , "Hyperbolic tangent");
+ }};
+
+
+ public CustomExpression(){
+ setName("");
+ setSymbol("");
+ setUnit("");
+ setExpression("");
+ }
+
+ public CustomExpression(Simulation sim){
+ this();
+ setSimulation(sim);
+ }
+
+ public CustomExpression(Simulation sim, String name, String symbol, String unit, String expression) {
+
+ setName(name);
+ setSymbol(symbol);
+ setUnit(unit);
+ setExpression(expression);
+ setSimulation(sim);
+ }
+
+ /*
+ * Opens an ExpressionBuilderDialog for this expression
+ */
+ public void editExpression(Window parent){
+ log.debug("Opening window to edit an existing custom expression");
+ new ExpressionBuilderDialog(parent, sim, this).setVisible(true);
+ }
+
+ /*
+ * Use this to update the simulation this is associated with
+ */
+ public void setSimulation(Simulation sim){
+ CustomExpression.sim = sim;
+ }
+
+ /*
+ * Returns the flight data branch 0 for this simulation, or an empty branch
+ * if no simulated data exists
+ */
+ private FlightDataBranch getBranch() {
+ if ( sim == null || sim.getSimulatedData().getBranch(0) == null) {
+ return new FlightDataBranch();
+ }
+ else {
+ return sim.getSimulatedData().getBranch(0);
+ }
+ }
+
+
+ public void setName(String name){
+ this.name = name;
+ }
+
+ public void setUnit(String unit){
+ this.unit = unit;
+ }
+
+ public void setSymbol(String symbol){
+ this.symbol = symbol;
+ }
+
+ public void setExpression(String expression){
+ this.expression = expression;
+ builder = new ExpressionBuilder(expression);
+ }
+
+ // get a list of all the names of all the available variables
+ private ArrayList<String> getAllNames(){
+ ArrayList<String> names = new ArrayList<String>();
+ for (FlightDataType type : FlightDataType.ALL_TYPES)
+ names.add(type.getName());
+ for (CustomExpression exp : sim.getCustomExpressions() ){
+ if (exp != this)
+ names.add(exp.getName());
+ }
+ return names;
+ }
+
+ // get a list of all the symbols of the available variables ignoring this one
+ private ArrayList<String> getAllSymbols(){
+ ArrayList<String> symbols = new ArrayList<String>();
+ for (FlightDataType type : FlightDataType.ALL_TYPES)
+ symbols.add(type.getSymbol());
+ for (CustomExpression exp : sim.getCustomExpressions() ){
+ if (exp != this)
+ symbols.add(exp.getSymbol());
+ }
+ return symbols;
+ }
+
+ public boolean checkSymbol(){
+ if (symbol.trim().isEmpty())
+ return false;
+
+ // No bad characters
+ for (char c : "0123456789.()[]{}".toCharArray())
+ if (symbol.indexOf(c) != -1 )
+ return false;
+
+ // No operators (ignoring brackets)
+ for (String s : CustomExpression.AVAILABLE_OPERATORS.keySet()){
+ if (symbol.contains(s.replaceAll("\\(|\\)", "")))
+ return false;
+ }
+
+ // No already defined symbols
+ ArrayList<String> symbols = getAllSymbols().clone();
+ if (symbols.contains(symbol.trim())){
+ int index = symbols.indexOf(symbol.trim());
+ log.user("Symbol "+symbol+" already exists, found "+symbols.get(index));
+ return false;
+ }
+
+ return true;
+ }
+
+ public boolean checkName(){
+ if (name.trim().isEmpty())
+ return false;
+
+ ArrayList<String> names = getAllNames().clone();
+ if (names.contains(name.trim())){
+ int index = names.indexOf(name.trim());
+ log.user("Symbol "+symbol+" already exists, found "+names.get(index));
+ return false;
+ }
+
+ return true;
+ }
+
+ // Currently no restrictions on unit
+ public boolean checkUnit(){
+ return true;
+ }
+
+ public boolean checkAll(){
+ return checkUnit() && checkSymbol() && checkName();
+ }
+
+ public String getName(){
+ return name;
+ }
+
+ public String getSymbol(){
+ return symbol;
+ }
+
+ public String getUnit(){
+ return unit;
+ }
+
+ public String getExpressionString(){
+ return expression;
+ }
+
+
+ /*
+ * Check if the current expression is valid
+ */
+ public boolean checkExpression(){
+
+ if (expression.trim().isEmpty()){
+ return false;
+ }
+
+ // Define the available variables as 0
+ for (FlightDataType type : getBranch().getTypes()){
+ builder.withVariable(type.getSymbol(), 0.0);
+ }
+
+ for (String symb : getAllSymbols()){
+ builder.withVariable(symb, 0.0);
+ }
+
+ // Try to build
+ try {
+ builder.build();
+ } catch (Exception e) {
+ log.user("Custom expression invalid : " + e.toString());
+ return false;
+ }
+
+ // Otherwise, all OK
+ return true;
+ }
+
+ /*
+ * Evaluate the expression using the last variable values from the simulation status.
+ * Returns NaN on any error.
+ */
+ public Double evaluate(SimulationStatus status){
+
+ for (FlightDataType type : status.getFlightData().getTypes()){
+ builder.withVariable(type.getSymbol(), status.getFlightData().getLast(type) );
+ }
+
+ Calculable calc;
+ try {
+ calc = builder.build();
+ return new Double(calc.calculate());
+ } catch (Exception e) {
+ log.user("Could not calculate custom expression "+name);
+ return Double.NaN;
+ }
+ }
+
+ /*
+ * Returns the new flight data type corresponding to this calculated data
+ */
+ public FlightDataType getType(){
+ UnitGroup ug = new FixedUnitGroup(unit);
+ return FlightDataType.getType(name, symbol, ug);
+ }
+
+ /*
+ * Add this expression to the simulation if not already added
+ */
+ public void addToSimulation(){
+ if (! sim.getCustomExpressions().contains(this))
+ sim.addCustomExpression( this );
+ }
+
+ /*
+ * Removes this expression from the simulation, replacing it with a given new expression
+ */
+ public void overwrite(CustomExpression newExpression){
+ if (!sim.getCustomExpressions().contains(this))
+ return;
+ else {
+ int index = sim.getCustomExpressions().indexOf(this);
+ sim.getCustomExpressions().set(index, newExpression);
+ }
+ }
+
+ @Override
+ public String toString(){
+ return "Custom expression : "+this.name.toString()+ " " + this.expression.toString();
+ }
+
+ @Override
+ /*
+ * Clone method makes a deep copy of everything except the simulation
+ * @see java.lang.Object#clone()
+ */
+ public Object clone() {
+ try {
+ return super.clone();
+ }
+ catch( CloneNotSupportedException e )
+ {
+ return new CustomExpression( sim ,
+ new String(this.getName()),
+ new String(this.getSymbol()),
+ new String(this.getUnit()),
+ new String(this.getExpressionString()));
+ }
+ }
+
+}
}
}
-
+ /**
+ * Makes an 'empty' flight data branch which has no data but all built in data types are defined.
+ */
+ public FlightDataBranch() {
+ branchName = "Empty branch";
+ for (FlightDataType type : FlightDataType.ALL_TYPES){
+ this.setValue(type, Double.NaN);
+ }
+ this.immute();
+ }
/**
* Adds a new point into the data branch. The value for all types is set to NaN by default.
//// Time
- public static final FlightDataType TYPE_TIME = newType(trans.get("FlightDataType.TYPE_TIME"), UnitGroup.UNITS_FLIGHT_TIME, 1);
-
+ public static final FlightDataType TYPE_TIME = newType(trans.get("FlightDataType.TYPE_TIME"), "t", UnitGroup.UNITS_FLIGHT_TIME, 1);
//// Vertical position and motion
//// Altitude
- public static final FlightDataType TYPE_ALTITUDE = newType(trans.get("FlightDataType.TYPE_ALTITUDE"), UnitGroup.UNITS_DISTANCE, 10);
+ public static final FlightDataType TYPE_ALTITUDE = newType(trans.get("FlightDataType.TYPE_ALTITUDE"), "a", UnitGroup.UNITS_DISTANCE, 10);
//// Vertical velocity
- public static final FlightDataType TYPE_VELOCITY_Z = newType(trans.get("FlightDataType.TYPE_VELOCITY_Z"), UnitGroup.UNITS_VELOCITY, 11);
+ public static final FlightDataType TYPE_VELOCITY_Z = newType(trans.get("FlightDataType.TYPE_VELOCITY_Z"), "Vz", UnitGroup.UNITS_VELOCITY, 11);
//// Vertical acceleration
- public static final FlightDataType TYPE_ACCELERATION_Z = newType(trans.get("FlightDataType.TYPE_ACCELERATION_Z"), UnitGroup.UNITS_ACCELERATION, 12);
+ public static final FlightDataType TYPE_ACCELERATION_Z = newType(trans.get("FlightDataType.TYPE_ACCELERATION_Z"), "Az", UnitGroup.UNITS_ACCELERATION, 12);
//// Total motion
//// Total velocity
- public static final FlightDataType TYPE_VELOCITY_TOTAL = newType(trans.get("FlightDataType.TYPE_VELOCITY_TOTAL"), UnitGroup.UNITS_VELOCITY, 20);
+ public static final FlightDataType TYPE_VELOCITY_TOTAL = newType(trans.get("FlightDataType.TYPE_VELOCITY_TOTAL"), "Vt", UnitGroup.UNITS_VELOCITY, 20);
//// Total acceleration
- public static final FlightDataType TYPE_ACCELERATION_TOTAL = newType(trans.get("FlightDataType.TYPE_ACCELERATION_TOTAL"), UnitGroup.UNITS_ACCELERATION, 21);
+ public static final FlightDataType TYPE_ACCELERATION_TOTAL = newType(trans.get("FlightDataType.TYPE_ACCELERATION_TOTAL"), "At", UnitGroup.UNITS_ACCELERATION, 21);
//// Lateral position and motion
//// Position upwind
- public static final FlightDataType TYPE_POSITION_X = newType(trans.get("FlightDataType.TYPE_POSITION_X"), UnitGroup.UNITS_DISTANCE, 30);
+ public static final FlightDataType TYPE_POSITION_X = newType(trans.get("FlightDataType.TYPE_POSITION_X"), "Px", UnitGroup.UNITS_DISTANCE, 30);
//// Position parallel to wind
- public static final FlightDataType TYPE_POSITION_Y = newType(trans.get("FlightDataType.TYPE_POSITION_Y"), UnitGroup.UNITS_DISTANCE, 31);
+ public static final FlightDataType TYPE_POSITION_Y = newType(trans.get("FlightDataType.TYPE_POSITION_Y"), "Py", UnitGroup.UNITS_DISTANCE, 31);
//// Lateral distance
- public static final FlightDataType TYPE_POSITION_XY = newType(trans.get("FlightDataType.TYPE_POSITION_XY"), UnitGroup.UNITS_DISTANCE, 32);
+ public static final FlightDataType TYPE_POSITION_XY = newType(trans.get("FlightDataType.TYPE_POSITION_XY"), "Pl", UnitGroup.UNITS_DISTANCE, 32);
//// Lateral direction
- public static final FlightDataType TYPE_POSITION_DIRECTION = newType(trans.get("FlightDataType.TYPE_POSITION_DIRECTION"), UnitGroup.UNITS_ANGLE, 33);
+ public static final FlightDataType TYPE_POSITION_DIRECTION = newType(trans.get("FlightDataType.TYPE_POSITION_DIRECTION"), "θl", UnitGroup.UNITS_ANGLE, 33);
//// Lateral velocity
- public static final FlightDataType TYPE_VELOCITY_XY = newType(trans.get("FlightDataType.TYPE_VELOCITY_XY"), UnitGroup.UNITS_VELOCITY, 34);
+ public static final FlightDataType TYPE_VELOCITY_XY = newType(trans.get("FlightDataType.TYPE_VELOCITY_XY"), "Vl", UnitGroup.UNITS_VELOCITY, 34);
//// Lateral acceleration
- public static final FlightDataType TYPE_ACCELERATION_XY = newType(trans.get("FlightDataType.TYPE_ACCELERATION_XY"), UnitGroup.UNITS_ACCELERATION, 35);
+ public static final FlightDataType TYPE_ACCELERATION_XY = newType(trans.get("FlightDataType.TYPE_ACCELERATION_XY"), "Al", UnitGroup.UNITS_ACCELERATION, 35);
//// Latitude
- public static final FlightDataType TYPE_LATITUDE = newType(trans.get("FlightDataType.TYPE_LATITUDE"), UnitGroup.UNITS_ANGLE, 36);
+ public static final FlightDataType TYPE_LATITUDE = newType(trans.get("FlightDataType.TYPE_LATITUDE"), "φ", UnitGroup.UNITS_ANGLE, 36);
//// Longitude
- public static final FlightDataType TYPE_LONGITUDE = newType(trans.get("FlightDataType.TYPE_LONGITUDE"), UnitGroup.UNITS_ANGLE, 37);
+ public static final FlightDataType TYPE_LONGITUDE = newType(trans.get("FlightDataType.TYPE_LONGITUDE"), "λ", UnitGroup.UNITS_ANGLE, 37);
//// Angular motion
//// Angle of attack
- public static final FlightDataType TYPE_AOA = newType(trans.get("FlightDataType.TYPE_AOA"), UnitGroup.UNITS_ANGLE, 40);
+ public static final FlightDataType TYPE_AOA = newType(trans.get("FlightDataType.TYPE_AOA"), "α", UnitGroup.UNITS_ANGLE, 40);
//// Roll rate
- public static final FlightDataType TYPE_ROLL_RATE = newType(trans.get("FlightDataType.TYPE_ROLL_RATE"), UnitGroup.UNITS_ROLL, 41);
+ public static final FlightDataType TYPE_ROLL_RATE = newType(trans.get("FlightDataType.TYPE_ROLL_RATE"), "dΦ", UnitGroup.UNITS_ROLL, 41);
//// Pitch rate
- public static final FlightDataType TYPE_PITCH_RATE = newType(trans.get("FlightDataType.TYPE_PITCH_RATE"), UnitGroup.UNITS_ROLL, 42);
+ public static final FlightDataType TYPE_PITCH_RATE = newType(trans.get("FlightDataType.TYPE_PITCH_RATE"), "dθ", UnitGroup.UNITS_ROLL, 42);
//// Yaw rate
- public static final FlightDataType TYPE_YAW_RATE = newType(trans.get("FlightDataType.TYPE_YAW_RATE"), UnitGroup.UNITS_ROLL, 43);
+ public static final FlightDataType TYPE_YAW_RATE = newType(trans.get("FlightDataType.TYPE_YAW_RATE"), "dΨ", UnitGroup.UNITS_ROLL, 43);
//// Stability information
//// Mass
- public static final FlightDataType TYPE_MASS = newType(trans.get("FlightDataType.TYPE_MASS"), UnitGroup.UNITS_MASS, 50);
+ public static final FlightDataType TYPE_MASS = newType(trans.get("FlightDataType.TYPE_MASS"), "m", UnitGroup.UNITS_MASS, 50);
//// Longitudinal moment of inertia
- public static final FlightDataType TYPE_LONGITUDINAL_INERTIA = newType(trans.get("FlightDataType.TYPE_LONGITUDINAL_INERTIA"), UnitGroup.UNITS_INERTIA, 51);
+ public static final FlightDataType TYPE_LONGITUDINAL_INERTIA = newType(trans.get("FlightDataType.TYPE_LONGITUDINAL_INERTIA"), "Il", UnitGroup.UNITS_INERTIA, 51);
//// Rotational moment of inertia
- public static final FlightDataType TYPE_ROTATIONAL_INERTIA = newType(trans.get("FlightDataType.TYPE_ROTATIONAL_INERTIA"), UnitGroup.UNITS_INERTIA, 52);
+ public static final FlightDataType TYPE_ROTATIONAL_INERTIA = newType(trans.get("FlightDataType.TYPE_ROTATIONAL_INERTIA"), "Ir", UnitGroup.UNITS_INERTIA, 52);
//// CP location
- public static final FlightDataType TYPE_CP_LOCATION = newType(trans.get("FlightDataType.TYPE_CP_LOCATION"), UnitGroup.UNITS_LENGTH, 53);
+ public static final FlightDataType TYPE_CP_LOCATION = newType(trans.get("FlightDataType.TYPE_CP_LOCATION"), "Cp", UnitGroup.UNITS_LENGTH, 53);
//// CG location
- public static final FlightDataType TYPE_CG_LOCATION = newType(trans.get("FlightDataType.TYPE_CG_LOCATION"), UnitGroup.UNITS_LENGTH, 54);
+ public static final FlightDataType TYPE_CG_LOCATION = newType(trans.get("FlightDataType.TYPE_CG_LOCATION"), "Cg", UnitGroup.UNITS_LENGTH, 54);
//// Stability margin calibers
- public static final FlightDataType TYPE_STABILITY = newType(trans.get("FlightDataType.TYPE_STABILITY"), UnitGroup.UNITS_COEFFICIENT, 55);
+ public static final FlightDataType TYPE_STABILITY = newType(trans.get("FlightDataType.TYPE_STABILITY"), "S", UnitGroup.UNITS_COEFFICIENT, 55);
//// Characteristic numbers
//// Mach number
- public static final FlightDataType TYPE_MACH_NUMBER = newType(trans.get("FlightDataType.TYPE_MACH_NUMBER"), UnitGroup.UNITS_COEFFICIENT, 60);
+ public static final FlightDataType TYPE_MACH_NUMBER = newType(trans.get("FlightDataType.TYPE_MACH_NUMBER"), "M", UnitGroup.UNITS_COEFFICIENT, 60);
//// Reynolds number
- public static final FlightDataType TYPE_REYNOLDS_NUMBER = newType(trans.get("FlightDataType.TYPE_REYNOLDS_NUMBER"), UnitGroup.UNITS_COEFFICIENT, 61);
+ public static final FlightDataType TYPE_REYNOLDS_NUMBER = newType(trans.get("FlightDataType.TYPE_REYNOLDS_NUMBER"), "R", UnitGroup.UNITS_COEFFICIENT, 61);
//// Thrust and drag
//// Thrust
- public static final FlightDataType TYPE_THRUST_FORCE = newType(trans.get("FlightDataType.TYPE_THRUST_FORCE"), UnitGroup.UNITS_FORCE, 70);
+ public static final FlightDataType TYPE_THRUST_FORCE = newType(trans.get("FlightDataType.TYPE_THRUST_FORCE"), "Ft", UnitGroup.UNITS_FORCE, 70);
//// Drag force
- public static final FlightDataType TYPE_DRAG_FORCE = newType(trans.get("FlightDataType.TYPE_DRAG_FORCE"), UnitGroup.UNITS_FORCE, 71);
+ public static final FlightDataType TYPE_DRAG_FORCE = newType(trans.get("FlightDataType.TYPE_DRAG_FORCE"), "Fd", UnitGroup.UNITS_FORCE, 71);
//// Drag coefficient
- public static final FlightDataType TYPE_DRAG_COEFF = newType(trans.get("FlightDataType.TYPE_DRAG_COEFF"), UnitGroup.UNITS_COEFFICIENT, 72);
+ public static final FlightDataType TYPE_DRAG_COEFF = newType(trans.get("FlightDataType.TYPE_DRAG_COEFF"), "Cd", UnitGroup.UNITS_COEFFICIENT, 72);
//// Axial drag coefficient
- public static final FlightDataType TYPE_AXIAL_DRAG_COEFF = newType(trans.get("FlightDataType.TYPE_AXIAL_DRAG_COEFF"), UnitGroup.UNITS_COEFFICIENT, 73);
+ public static final FlightDataType TYPE_AXIAL_DRAG_COEFF = newType(trans.get("FlightDataType.TYPE_AXIAL_DRAG_COEFF"), "Cda", UnitGroup.UNITS_COEFFICIENT, 73);
//// Component drag coefficients
//// Friction drag coefficient
- public static final FlightDataType TYPE_FRICTION_DRAG_COEFF = newType(trans.get("FlightDataType.TYPE_FRICTION_DRAG_COEFF"), UnitGroup.UNITS_COEFFICIENT, 80);
+ public static final FlightDataType TYPE_FRICTION_DRAG_COEFF = newType(trans.get("FlightDataType.TYPE_FRICTION_DRAG_COEFF"), "Cdf", UnitGroup.UNITS_COEFFICIENT, 80);
//// Pressure drag coefficient
- public static final FlightDataType TYPE_PRESSURE_DRAG_COEFF = newType(trans.get("FlightDataType.TYPE_PRESSURE_DRAG_COEFF"), UnitGroup.UNITS_COEFFICIENT, 81);
+ public static final FlightDataType TYPE_PRESSURE_DRAG_COEFF = newType(trans.get("FlightDataType.TYPE_PRESSURE_DRAG_COEFF"), "Cdp", UnitGroup.UNITS_COEFFICIENT, 81);
//// Base drag coefficient
- public static final FlightDataType TYPE_BASE_DRAG_COEFF = newType(trans.get("FlightDataType.TYPE_BASE_DRAG_COEFF"), UnitGroup.UNITS_COEFFICIENT, 82);
+ public static final FlightDataType TYPE_BASE_DRAG_COEFF = newType(trans.get("FlightDataType.TYPE_BASE_DRAG_COEFF"), "Cdb", UnitGroup.UNITS_COEFFICIENT, 82);
//// Other coefficients
//// Normal force coefficient
- public static final FlightDataType TYPE_NORMAL_FORCE_COEFF = newType(trans.get("FlightDataType.TYPE_NORMAL_FORCE_COEFF"), UnitGroup.UNITS_COEFFICIENT, 90);
+ public static final FlightDataType TYPE_NORMAL_FORCE_COEFF = newType(trans.get("FlightDataType.TYPE_NORMAL_FORCE_COEFF"), "Cn", UnitGroup.UNITS_COEFFICIENT, 90);
//// Pitch moment coefficient
- public static final FlightDataType TYPE_PITCH_MOMENT_COEFF = newType(trans.get("FlightDataType.TYPE_PITCH_MOMENT_COEFF"), UnitGroup.UNITS_COEFFICIENT, 91);
+ public static final FlightDataType TYPE_PITCH_MOMENT_COEFF = newType(trans.get("FlightDataType.TYPE_PITCH_MOMENT_COEFF"), "Cθ", UnitGroup.UNITS_COEFFICIENT, 91);
//// Yaw moment coefficient
- public static final FlightDataType TYPE_YAW_MOMENT_COEFF = newType(trans.get("FlightDataType.TYPE_YAW_MOMENT_COEFF"), UnitGroup.UNITS_COEFFICIENT, 92);
+ public static final FlightDataType TYPE_YAW_MOMENT_COEFF = newType(trans.get("FlightDataType.TYPE_YAW_MOMENT_COEFF"), "CτΨ", UnitGroup.UNITS_COEFFICIENT, 92);
//// Side force coefficient
- public static final FlightDataType TYPE_SIDE_FORCE_COEFF = newType(trans.get("FlightDataType.TYPE_SIDE_FORCE_COEFF"), UnitGroup.UNITS_COEFFICIENT, 93);
+ public static final FlightDataType TYPE_SIDE_FORCE_COEFF = newType(trans.get("FlightDataType.TYPE_SIDE_FORCE_COEFF"), "Cτs", UnitGroup.UNITS_COEFFICIENT, 93);
//// Roll moment coefficient
- public static final FlightDataType TYPE_ROLL_MOMENT_COEFF = newType(trans.get("FlightDataType.TYPE_ROLL_MOMENT_COEFF"), UnitGroup.UNITS_COEFFICIENT, 94);
+ public static final FlightDataType TYPE_ROLL_MOMENT_COEFF = newType(trans.get("FlightDataType.TYPE_ROLL_MOMENT_COEFF"), "CτΦ", UnitGroup.UNITS_COEFFICIENT, 94);
//// Roll forcing coefficient
- public static final FlightDataType TYPE_ROLL_FORCING_COEFF = newType(trans.get("FlightDataType.TYPE_ROLL_FORCING_COEFF"), UnitGroup.UNITS_COEFFICIENT, 95);
+ public static final FlightDataType TYPE_ROLL_FORCING_COEFF = newType(trans.get("FlightDataType.TYPE_ROLL_FORCING_COEFF"), "CfΦ", UnitGroup.UNITS_COEFFICIENT, 95);
//// Roll damping coefficient
- public static final FlightDataType TYPE_ROLL_DAMPING_COEFF = newType(trans.get("FlightDataType.TYPE_ROLL_DAMPING_COEFF"), UnitGroup.UNITS_COEFFICIENT, 96);
+ public static final FlightDataType TYPE_ROLL_DAMPING_COEFF = newType(trans.get("FlightDataType.TYPE_ROLL_DAMPING_COEFF"), "CζΦ", UnitGroup.UNITS_COEFFICIENT, 96);
//// Pitch damping coefficient
- public static final FlightDataType TYPE_PITCH_DAMPING_MOMENT_COEFF = newType(trans.get("FlightDataType.TYPE_PITCH_DAMPING_MOMENT_COEFF"), UnitGroup.UNITS_COEFFICIENT, 97);
+ public static final FlightDataType TYPE_PITCH_DAMPING_MOMENT_COEFF = newType(trans.get("FlightDataType.TYPE_PITCH_DAMPING_MOMENT_COEFF"), "Cζθ", UnitGroup.UNITS_COEFFICIENT, 97);
//// Yaw damping coefficient
- public static final FlightDataType TYPE_YAW_DAMPING_MOMENT_COEFF = newType(trans.get("FlightDataType.TYPE_YAW_DAMPING_MOMENT_COEFF"), UnitGroup.UNITS_COEFFICIENT, 98);
+ public static final FlightDataType TYPE_YAW_DAMPING_MOMENT_COEFF = newType(trans.get("FlightDataType.TYPE_YAW_DAMPING_MOMENT_COEFF"), "CζΨ", UnitGroup.UNITS_COEFFICIENT, 98);
//// Coriolis acceleration
- public static final FlightDataType TYPE_CORIOLIS_ACCELERATION = newType(trans.get("FlightDataType.TYPE_CORIOLIS_ACCELERATION"), UnitGroup.UNITS_ACCELERATION, 99);
+ public static final FlightDataType TYPE_CORIOLIS_ACCELERATION = newType(trans.get("FlightDataType.TYPE_CORIOLIS_ACCELERATION"), "Ac", UnitGroup.UNITS_ACCELERATION, 99);
//// Reference length + area
//// Reference length
- public static final FlightDataType TYPE_REFERENCE_LENGTH = newType(trans.get("FlightDataType.TYPE_REFERENCE_LENGTH"), UnitGroup.UNITS_LENGTH, 100);
+ public static final FlightDataType TYPE_REFERENCE_LENGTH = newType(trans.get("FlightDataType.TYPE_REFERENCE_LENGTH"), "Lr", UnitGroup.UNITS_LENGTH, 100);
//// Reference area
- public static final FlightDataType TYPE_REFERENCE_AREA = newType(trans.get("FlightDataType.TYPE_REFERENCE_AREA"), UnitGroup.UNITS_AREA, 101);
+ public static final FlightDataType TYPE_REFERENCE_AREA = newType(trans.get("FlightDataType.TYPE_REFERENCE_AREA"), "Ar", UnitGroup.UNITS_AREA, 101);
//// Orientation
//// Vertical orientation (zenith)
- public static final FlightDataType TYPE_ORIENTATION_THETA = newType(trans.get("FlightDataType.TYPE_ORIENTATION_THETA"), UnitGroup.UNITS_ANGLE, 106);
+ public static final FlightDataType TYPE_ORIENTATION_THETA = newType(trans.get("FlightDataType.TYPE_ORIENTATION_THETA"), "Θ", UnitGroup.UNITS_ANGLE, 106);
//// Lateral orientation (azimuth)
- public static final FlightDataType TYPE_ORIENTATION_PHI = newType(trans.get("FlightDataType.TYPE_ORIENTATION_PHI"), UnitGroup.UNITS_ANGLE, 107);
+ public static final FlightDataType TYPE_ORIENTATION_PHI = newType(trans.get("FlightDataType.TYPE_ORIENTATION_PHI"), "Φ", UnitGroup.UNITS_ANGLE, 107);
//// Atmospheric conditions
//// Wind velocity
- public static final FlightDataType TYPE_WIND_VELOCITY = newType(trans.get("FlightDataType.TYPE_WIND_VELOCITY"), UnitGroup.UNITS_VELOCITY, 110);
+ public static final FlightDataType TYPE_WIND_VELOCITY = newType(trans.get("FlightDataType.TYPE_WIND_VELOCITY"), "Vw", UnitGroup.UNITS_VELOCITY, 110);
//// Air temperature
- public static final FlightDataType TYPE_AIR_TEMPERATURE = newType(trans.get("FlightDataType.TYPE_AIR_TEMPERATURE"), UnitGroup.UNITS_TEMPERATURE, 111);
+ public static final FlightDataType TYPE_AIR_TEMPERATURE = newType(trans.get("FlightDataType.TYPE_AIR_TEMPERATURE"), "T", UnitGroup.UNITS_TEMPERATURE, 111);
//// Air pressure
- public static final FlightDataType TYPE_AIR_PRESSURE = newType(trans.get("FlightDataType.TYPE_AIR_PRESSURE"), UnitGroup.UNITS_PRESSURE, 112);
+ public static final FlightDataType TYPE_AIR_PRESSURE = newType(trans.get("FlightDataType.TYPE_AIR_PRESSURE"), "p", UnitGroup.UNITS_PRESSURE, 112);
//// Speed of sound
- public static final FlightDataType TYPE_SPEED_OF_SOUND = newType(trans.get("FlightDataType.TYPE_SPEED_OF_SOUND"), UnitGroup.UNITS_VELOCITY, 113);
+ public static final FlightDataType TYPE_SPEED_OF_SOUND = newType(trans.get("FlightDataType.TYPE_SPEED_OF_SOUND"), "Vs", UnitGroup.UNITS_VELOCITY, 113);
//// Simulation information
//// Simulation time step
- public static final FlightDataType TYPE_TIME_STEP = newType(trans.get("FlightDataType.TYPE_TIME_STEP"), UnitGroup.UNITS_TIME_STEP, 200);
+ public static final FlightDataType TYPE_TIME_STEP = newType(trans.get("FlightDataType.TYPE_TIME_STEP"), "dt", UnitGroup.UNITS_TIME_STEP, 200);
//// Computation time
- public static final FlightDataType TYPE_COMPUTATION_TIME = newType(trans.get("FlightDataType.TYPE_COMPUTATION_TIME"), UnitGroup.UNITS_SHORT_TIME, 201);
-
-
+ public static final FlightDataType TYPE_COMPUTATION_TIME = newType(trans.get("FlightDataType.TYPE_COMPUTATION_TIME"), "tc", UnitGroup.UNITS_SHORT_TIME, 201);
+
+
+ // An array of all the built in types
+ public static final FlightDataType[] ALL_TYPES = {
+ TYPE_ALTITUDE ,
+ TYPE_VELOCITY_Z ,
+ TYPE_ACCELERATION_Z,
+ TYPE_VELOCITY_TOTAL,
+ TYPE_ACCELERATION_TOTAL,
+ TYPE_POSITION_X,
+ TYPE_POSITION_Y,
+ TYPE_POSITION_XY,
+ TYPE_POSITION_DIRECTION,
+ TYPE_VELOCITY_XY,
+ TYPE_ACCELERATION_XY,
+ TYPE_LATITUDE,
+ TYPE_LONGITUDE,
+ TYPE_AOA,
+ TYPE_ROLL_RATE,
+ TYPE_PITCH_RATE,
+ TYPE_YAW_RATE,
+ TYPE_MASS,
+ TYPE_LONGITUDINAL_INERTIA,
+ TYPE_ROTATIONAL_INERTIA,
+ TYPE_CP_LOCATION,
+ TYPE_CG_LOCATION,
+ TYPE_STABILITY,
+ TYPE_MACH_NUMBER,
+ TYPE_REYNOLDS_NUMBER,
+ TYPE_THRUST_FORCE,
+ TYPE_DRAG_FORCE,
+ TYPE_DRAG_COEFF,
+ TYPE_AXIAL_DRAG_COEFF,
+ TYPE_FRICTION_DRAG_COEFF,
+ TYPE_PRESSURE_DRAG_COEFF,
+ TYPE_BASE_DRAG_COEFF,
+ TYPE_NORMAL_FORCE_COEFF,
+ TYPE_PITCH_MOMENT_COEFF,
+ TYPE_YAW_MOMENT_COEFF,
+ TYPE_SIDE_FORCE_COEFF,
+ TYPE_ROLL_MOMENT_COEFF,
+ TYPE_ROLL_FORCING_COEFF,
+ TYPE_ROLL_DAMPING_COEFF,
+ TYPE_PITCH_DAMPING_MOMENT_COEFF,
+ TYPE_YAW_DAMPING_MOMENT_COEFF,
+ TYPE_CORIOLIS_ACCELERATION,
+ TYPE_REFERENCE_LENGTH,
+ TYPE_REFERENCE_AREA,
+ TYPE_ORIENTATION_THETA,
+ TYPE_ORIENTATION_PHI,
+ TYPE_WIND_VELOCITY,
+ TYPE_AIR_TEMPERATURE,
+ TYPE_AIR_PRESSURE,
+ TYPE_SPEED_OF_SOUND,
+ TYPE_TIME_STEP,
+ TYPE_COMPUTATION_TIME
+ };
/**
* Return a {@link FlightDataType} based on a string description. This returns known data types
* @param u the unit group the new type should belong to if a new group is created.
* @return a data type.
*/
- public static synchronized FlightDataType getType(String s, UnitGroup u) {
+ public static synchronized FlightDataType getType(String s, String symbol, UnitGroup u) {
FlightDataType type = EXISTING_TYPES.get(s.toLowerCase(Locale.ENGLISH));
if (type != null) {
return type;
}
- type = newType(s, u, DEFAULT_PRIORITY);
+ type = newType(s, symbol, u, DEFAULT_PRIORITY);
return type;
}
/**
* Used while initializing the class.
*/
- private static synchronized FlightDataType newType(String s, UnitGroup u, int priority) {
- FlightDataType type = new FlightDataType(s, u, priority);
+ private static synchronized FlightDataType newType(String s, String symbol, UnitGroup u, int priority) {
+ FlightDataType type = new FlightDataType(s, symbol, u, priority);
EXISTING_TYPES.put(s.toLowerCase(Locale.ENGLISH), type);
return type;
}
private final String name;
+ private final String symbol;
private final UnitGroup units;
private final int priority;
private final int hashCode;
- private FlightDataType(String typeName, UnitGroup units, int priority) {
+ private FlightDataType(String typeName, String symbol, UnitGroup units, int priority) {
if (typeName == null)
throw new IllegalArgumentException("typeName is null");
if (units == null)
throw new IllegalArgumentException("units is null");
this.name = typeName;
+ this.symbol = symbol;
this.units = units;
this.priority = priority;
this.hashCode = this.name.toLowerCase(Locale.ENGLISH).hashCode();
return name;
}
+ public String getSymbol(){
+ return symbol;
+ }
+
public UnitGroup getUnitGroup() {
return units;
}
import java.util.List;
import net.sf.openrocket.aerodynamics.AerodynamicCalculator;
+import net.sf.openrocket.document.Simulation;
import net.sf.openrocket.masscalc.MassCalculator;
import net.sf.openrocket.models.atmosphere.AtmosphericModel;
import net.sf.openrocket.models.gravity.GravityModel;
private Rocket rocket;
private String motorID = null;
+ private Simulation simulation; // The parent simulation
private double launchRodLength = 1;
this.modID++;
}
-
-
+ public void setSimulation(Simulation sim) {
+ this.simulation = sim;
+ }
+ public Simulation getSimulation(){
+ return this.simulation;
+ }
+
// TODO: HIGH: Make cleaner
public List<SimulationListener> getSimulationListenerList() {
return simulationListeners;
import java.util.EventObject;
import java.util.List;
import java.util.Random;
+import java.util.Set;
import net.sf.openrocket.aerodynamics.BarrowmanCalculator;
+import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.masscalc.BasicMassCalculator;
import net.sf.openrocket.models.atmosphere.AtmosphericModel;
import net.sf.openrocket.models.atmosphere.ExtendedISAModel;
import net.sf.openrocket.models.gravity.WGSGravityModel;
import net.sf.openrocket.models.wind.PinkNoiseWindModel;
import net.sf.openrocket.rocketcomponent.Rocket;
+import net.sf.openrocket.startup.Application;
import net.sf.openrocket.util.BugException;
import net.sf.openrocket.util.ChangeSource;
import net.sf.openrocket.util.GeodeticComputationStrategy;
*/
public class SimulationOptions implements ChangeSource, Cloneable {
+ private static final LogHelper log = Application.getLogger();
+
public static final double MAX_LAUNCH_ROD_ANGLE = Math.PI / 3;
/**
this.rocket = rocket;
}
-
public Rocket getRocket() {
return rocket;
}
private static final String CONTROL_FIN_NAME = "CONTROL";
// Define custom flight data type
- private static final FlightDataType FIN_CANT_TYPE = FlightDataType.getType("Control fin cant",
- UnitGroup.UNITS_ANGLE);
+ private static final FlightDataType FIN_CANT_TYPE = FlightDataType.getType("Control fin cant", "αfc", UnitGroup.UNITS_ANGLE);
// Simulation time at which PID controller is activated
private static final double START_TIME = 0.5;
--- /dev/null
+package net.sf.openrocket.unit;
+
+/*
+ * This class provides a 'dumb' version of UnitGroup
+ * It allows any arbitrary unit to be created. It doesn't store any value and can't be converted into anything else.
+ * This is useful for custom expression units.
+ *
+ * @author Richard Graham
+ */
+
+public class FixedUnitGroup extends UnitGroup {
+
+ String unitString;
+
+ public FixedUnitGroup( String unitString ){
+ this.unitString = unitString;
+ }
+
+ public int getUnitCount(){
+ return 1;
+ }
+
+ public Unit getDefaultUnit(){
+ return new GeneralUnit(1, unitString);
+ }
+
+ public boolean contains(Unit u){
+ return true;
+ }
+
+}