1 package com.billkuker.rocketry.motorsim.visual.workbench;
3 import java.awt.Dimension;
4 import java.awt.FlowLayout;
5 import java.awt.event.ActionEvent;
6 import java.awt.event.ActionListener;
7 import java.beans.PropertyChangeEvent;
8 import java.text.DecimalFormat;
9 import java.text.NumberFormat;
10 import java.util.Collections;
11 import java.util.Vector;
13 import javax.measure.quantity.Pressure;
14 import javax.measure.quantity.Velocity;
15 import javax.measure.quantity.VolumetricDensity;
16 import javax.measure.unit.SI;
17 import javax.swing.ButtonGroup;
18 import javax.swing.JButton;
19 import javax.swing.JFrame;
20 import javax.swing.JPanel;
21 import javax.swing.JRadioButton;
22 import javax.swing.JScrollPane;
23 import javax.swing.JSplitPane;
24 import javax.swing.JTable;
25 import javax.swing.SwingUtilities;
26 import javax.swing.event.ChangeEvent;
27 import javax.swing.event.ChangeListener;
28 import javax.swing.table.AbstractTableModel;
30 import org.jscience.physics.amount.Amount;
32 import com.billkuker.rocketry.motorsim.Fuel;
33 import com.billkuker.rocketry.motorsim.RocketScience;
34 import com.billkuker.rocketry.motorsim.fuel.EditableCombustionProduct;
35 import com.billkuker.rocketry.motorsim.fuel.PiecewiseSaintRobertFuel;
36 import com.billkuker.rocketry.motorsim.fuel.SaintRobertFuel;
37 import com.billkuker.rocketry.motorsim.fuel.SaintRobertFuel.Type;
38 import com.billkuker.rocketry.motorsim.visual.Chart;
39 import com.billkuker.rocketry.motorsim.visual.Editor;
41 public class SRFuelEditor extends JSplitPane {
42 private static final long serialVersionUID = 1L;
44 private static final NumberFormat nf = new DecimalFormat("##########.###");
46 Chart<Pressure, Velocity> burnRate;
48 private class Entry implements Comparable<Entry> {
49 Amount<Pressure> p = Amount.valueOf(0, RocketScience.UnitPreference.getUnitPreference().getPreferredUnit(RocketScience.PSI));
54 public int compareTo(Entry o) {
55 return p.compareTo(o.p);
59 public static class EditablePSRFuel extends PiecewiseSaintRobertFuel {
61 @SuppressWarnings("unchecked")
62 private Amount<VolumetricDensity> idealDensity = (Amount<VolumetricDensity>) Amount
65 private double combustionEfficiency = 1;
66 private double densityRatio = 1;
67 private EditableCombustionProduct cp;
68 private String name = "New Fuel";
70 public EditablePSRFuel(Type t) {
72 cp = new EditableCombustionProduct();
79 public void setType(Type t){
83 public void add(Amount<Pressure> p, final double _a, final double _n) {
88 public Amount<VolumetricDensity> getIdealDensity() {
92 public void setIdealDensity(Amount<VolumetricDensity> idealDensity) {
93 this.idealDensity = idealDensity;
96 public double getCombustionEfficiency() {
97 return combustionEfficiency;
100 public void setCombustionEfficiency(double combustionEfficiency) {
101 this.combustionEfficiency = combustionEfficiency;
104 public double getDensityRatio() {
108 public void setDensityRatio(double densityRatio) {
109 this.densityRatio = densityRatio;
113 public CombustionProduct getCombustionProduct() {
117 public String getName() {
121 public void setName(String name) {
127 final EditablePSRFuel f = new EditablePSRFuel(SaintRobertFuel.Type.SI);
129 private class TM extends AbstractTableModel {
130 private static final long serialVersionUID = 1L;
133 public int getColumnCount() {
138 public int getRowCount() {
139 return entries.size();
143 public String getColumnName(int col) {
148 return "Coefficient (a)";
150 return "Exponent (n)";
156 public Object getValueAt(int rowIndex, int columnIndex) {
157 Entry e = entries.get(rowIndex);
158 switch (columnIndex) {
160 //Format like 100 psi or 4.8 Mpa
161 return nf.format(e.p.doubleValue(e.p.getUnit())) + " " + e.p.getUnit();
170 public boolean isCellEditable(int row, int col) {
174 @SuppressWarnings("unchecked")
175 public void setValueAt(Object value, int row, int col) {
176 Entry e = entries.get(row);
181 e.p = (Amount<Pressure>) Amount.valueOf((String) value);
182 } catch ( Exception ee ){
183 double d = Double.parseDouble((String)value);
184 e.p = (Amount<Pressure>)Amount.valueOf(d, e.p.getUnit());
188 e.a = Double.valueOf((String) value);
191 e.n = Double.valueOf((String) value);
193 } catch (Exception ex) {
194 ex.printStackTrace();
196 Collections.sort(entries);
197 fireTableDataChanged();
198 //f = new EditablePSRFuel(SaintRobertFuel.Type.NONSI);
200 for (Entry en : entries) {
201 f.add(en.p, en.a, en.n);
203 f.firePropertyChange(new PropertyChangeEvent(f,"entries", null, null));
210 public void fireTableDataChanged() {
211 super.fireTableDataChanged();
216 public Fuel getFuel(){
220 private void update() {
221 SwingUtilities.invokeLater(new Runnable() {
225 editTop.setTopComponent(new Editor(f));
226 editTop.setBottomComponent(new Editor(f.getCombustionProduct()));
227 if (burnRate != null)
228 SRFuelEditor.this.remove(burnRate);
230 burnRate = new Chart<Pressure, Velocity>(
231 SI.MEGA(SI.PASCAL), SI.MILLIMETER.divide(SI.SECOND)
232 .asType(Velocity.class), f, "burnRate");
233 } catch (NoSuchMethodException e) {
236 burnRate.setDomain(burnRate.new IntervalDomain(Amount.valueOf(
237 0, SI.MEGA(SI.PASCAL)), Amount.valueOf(11, SI
238 .MEGA(SI.PASCAL)), 50));
239 SRFuelEditor.this.setRightComponent(burnRate);
240 SRFuelEditor.this.revalidate();
245 private Vector<Entry> entries = new Vector<Entry>();
247 JSplitPane editParent;
249 JSplitPane editBottom;
252 public SRFuelEditor() {
253 super(HORIZONTAL_SPLIT);
255 setDividerLocation(.3);
257 final TM tm = new TM();
259 editParent = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
260 editTop = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
261 editBottom = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
263 editParent.setTopComponent(editTop);
264 editParent.setBottomComponent(editBottom);
266 editTop.setTopComponent(new Editor(f));
268 JTable table = new JTable(tm);
269 JScrollPane scrollpane = new JScrollPane(table);
270 scrollpane.setMinimumSize(new Dimension(200, 200));
271 editBottom.setTopComponent(scrollpane);
273 setLeftComponent(editParent);
275 JButton add = new JButton("Add Data");
276 add.addActionListener(new ActionListener() {
278 public void actionPerformed(ActionEvent e) {
279 entries.add(new Entry());
280 tm.fireTableDataChanged();
283 controls = new JPanel();
284 controls.setPreferredSize(new Dimension(200, 50));
285 controls.setLayout(new FlowLayout());
290 final JRadioButton si, nonsi;
291 ButtonGroup type = new ButtonGroup();
292 JPanel radio = new JPanel();
293 radio.add(si = new JRadioButton("SI"));
294 radio.add(nonsi = new JRadioButton("NonSI"));
299 si.setSelected(true);
301 si.addChangeListener(new ChangeListener(){
303 public void stateChanged(ChangeEvent e) {
304 if ( si.isSelected() ){
305 System.err.println("SI");
308 System.err.println("NONSI");
309 f.setType(Type.NONSI);
314 editBottom.setBottomComponent(controls);
317 editParent.setDividerLocation(.5);
318 editTop.setDividerLocation(.5);
319 editBottom.setDividerLocation(.8);
321 editParent.resetToPreferredSizes();
327 public static void main(String args[]) {
328 JFrame f = new JFrame();
329 f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
330 f.setContentPane(new SRFuelEditor());