--- /dev/null
+import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
+
+public class MotorSim {
+
+ public static void main(String args[]) throws Exception {
+
+ try {
+ System.setProperty("apple.laf.useScreenMenuBar", "true");
+ System.setProperty(
+ "com.apple.mrj.application.apple.menu.about.name",
+ "MotorSim");
+ UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+ } catch (Exception e1) {
+ e1.printStackTrace();
+ }
+ SwingUtilities.invokeLater(new Runnable(){
+ @Override
+ public void run() {
+ new com.billkuker.rocketry.motorsim.visual.workbench.MotorWorkbench().setVisible(true);
+ }
+ });
+
+ }
+
+}
+++ /dev/null
-import javax.swing.SwingUtilities;
-import javax.swing.UIManager;
-
-public class MotorWorkbench {
-
- public static void main(String args[]) throws Exception {
-
- try {
- System.setProperty("apple.laf.useScreenMenuBar", "true");
- System.setProperty(
- "com.apple.mrj.application.apple.menu.about.name",
- "MotorWorkbench");
- UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
- } catch (Exception e1) {
- e1.printStackTrace();
- }
- SwingUtilities.invokeLater(new Runnable(){
- @Override
- public void run() {
- new com.billkuker.rocketry.motorsim.visual.workbench.MotorWorkbench().setVisible(true);
- }
- });
-
- }
-
-}
--- /dev/null
+package com.billkuker.rocketry.motorsim.visual.workbench;
+
+import com.billkuker.rocketry.motorsim.Burn;
+
+public interface BurnWatcher {
+ public void replace( Burn oldBurn, Burn newBurn);
+}
import java.beans.PropertyChangeListener;\r
import java.beans.PropertyVetoException;\r
import java.io.IOException;\r
+import java.util.Vector;\r
\r
import javax.measure.quantity.Pressure;\r
import javax.measure.quantity.Velocity;\r
Motor motor;\r
GrainEditor grainEditor;\r
BurnTab bt;\r
+ Burn burn;\r
+ \r
+ private Vector<BurnWatcher> burnWatchers = new Vector<BurnWatcher>();\r
\r
private static final int XML_TAB = 0;\r
private static final int CASING_TAB = 1;\r
remove(bar);\r
add(bp, BorderLayout.CENTER);\r
\r
+ for( BurnWatcher bw : burnWatchers )\r
+ bw.replace(burn, b);\r
+ burn = b;\r
+ \r
revalidate();\r
}\r
});\r
if (o instanceof Fuel || o instanceof Fuel.CombustionProduct)\r
setSelectedIndex(FUEL_TAB);\r
}\r
+ \r
+ public void addBurnWatcher(BurnWatcher bw){\r
+ burnWatchers.add(bw);\r
+ }\r
\r
@Deprecated\r
public void showAsWindow() {\r
private JTree tree;\r
private JTabbedPane motors;\r
private WorkbenchTreeModel tm;\r
+ private MultiBurnChart mb;\r
+ private JFrame allBurns;\r
\r
private HashMap<MotorEditor, File> e2f = new HashMap<MotorEditor, File>();\r
private HashMap<File, MotorEditor> f2e = new HashMap<File, MotorEditor>();\r
private HashMap<Motor, MotorEditor> m2e = new HashMap<Motor, MotorEditor>();\r
\r
public MotorWorkbench() {\r
- setTitle("MotorWorkbench");\r
+ setTitle("MotorSim 1.0 RC1");\r
addMenu();\r
setSize(1024, 768);\r
top = new JPanel(new BorderLayout());\r
setContentPane(top);\r
-\r
+ \r
+ mb = new MultiBurnChart();\r
+ allBurns = new JFrame();\r
+ allBurns.setSize(800, 600);\r
+ setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE);\r
+ allBurns.add(mb);\r
+ allBurns.setVisible(true);\r
+ \r
motors = new JTabbedPane();\r
\r
tree = new JTree(tm = new WorkbenchTreeModel());\r
// split.setResizeWeight(.25);\r
top.add(split, BorderLayout.CENTER);\r
\r
- setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);\r
+ setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);\r
setVisible(true);\r
\r
}\r
f2e.remove(e2f.get(e));\r
e2f.remove(e);\r
m2e.remove(e.getMotor());\r
+ mb.removeBurn(e.burn);\r
}\r
});\r
}\r
public void addMotor(Motor m, File f) {\r
tm.addMotor(m);\r
MotorEditor e = new MotorEditor(m);\r
+ e.addBurnWatcher(mb);\r
String title;\r
if (f == null) {\r
title = "New Motor";\r
\r
@Override\r
public void valueChanged(TreeSelectionEvent e) {\r
+ if ( e.getPath().getLastPathComponent() == tm.getRoot() ){\r
+ allBurns.setVisible(true);\r
+ allBurns.toFront();\r
+ }\r
+ \r
Motor m = getMotor(e.getPath());\r
\r
if ( m == null )\r
.getLastPathComponent()).getUserObject();\r
m2e.get(m).focusOnObject(o);\r
}\r
+ \r
+\r
}\r
\r
private Motor getMotor(TreePath p) {\r
--- /dev/null
+package com.billkuker.rocketry.motorsim.visual.workbench;
+
+import java.awt.BorderLayout;
+import java.util.HashMap;
+
+import javax.measure.quantity.Duration;
+import javax.measure.quantity.Force;
+import javax.measure.unit.SI;
+import javax.measure.unit.Unit;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.WindowConstants;
+import javax.swing.plaf.multi.MultiButtonUI;
+
+import org.jfree.chart.ChartFactory;
+import org.jfree.chart.ChartPanel;
+import org.jfree.chart.JFreeChart;
+import org.jfree.chart.plot.PlotOrientation;
+import org.jfree.data.xy.XYSeries;
+import org.jfree.data.xy.XYSeriesCollection;
+import org.jscience.physics.amount.Amount;
+
+import com.billkuker.rocketry.motorsim.Burn;
+import com.billkuker.rocketry.motorsim.ConvergentDivergentNozzle;
+import com.billkuker.rocketry.motorsim.Motor;
+import com.billkuker.rocketry.motorsim.RocketScience;
+import com.billkuker.rocketry.motorsim.grain.MultiGrain;
+
+public class MultiBurnChart extends JPanel implements BurnWatcher {
+
+ private XYSeriesCollection dataset = new XYSeriesCollection();
+
+ private HashMap<Burn, XYSeries> burnToSeries = new HashMap<Burn, XYSeries>();
+ private Unit<Duration> time;
+ private Unit<Force> force;
+
+ @SuppressWarnings("unchecked")
+ public MultiBurnChart() {
+ this.setLayout(new BorderLayout());
+ time = RocketScience.UnitPreference.preference
+ .getPreferredUnit(SI.SECOND);
+ force = RocketScience.UnitPreference.preference
+ .getPreferredUnit(SI.NEWTON);
+ JFreeChart chart = ChartFactory.createXYLineChart(
+ "Burns", // Title
+ time.toString(), // x-axis Label
+ force.toString(), // y-axis Label
+ dataset, PlotOrientation.VERTICAL, // Plot Orientation
+ true, // Show Legend
+ true, // Use tool tips
+ false // Configure chart to generate URLs?
+ );
+ add(new ChartPanel(chart));
+ }
+
+ public void addBurn(Burn b) {
+ XYSeries s = createSeries(b);
+ burnToSeries.put(b, s);
+ dataset.addSeries(s);
+ }
+
+ private XYSeries createSeries(Burn b) {
+ XYSeries s = new XYSeries(b.getMotor().getName());
+ Amount<Force> low = Amount.valueOf(1, SI.NEWTON);
+ for( Burn.Interval i : b.getData().values() ){
+ s.add(i.time.doubleValue(time), i.thrust.doubleValue(force));
+ }
+ return s;
+ }
+
+ public void removeBurn(Burn b) {
+ XYSeries s = burnToSeries.get(b);
+ if (s == null)
+ return;
+ dataset.removeSeries(s);
+ }
+
+ public static void main(String args[]) throws Exception{
+ MultiBurnChart c = new MultiBurnChart();
+
+ JFrame f = new JFrame();
+ f.setSize(1024, 768);
+ f.setContentPane(c);
+ f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
+ f.setVisible(true);
+
+ Motor m = MotorEditor.defaultMotor();
+ Burn b = new Burn(m);
+ c.addBurn(b);
+
+ m.setName("Motor2");
+ ((ConvergentDivergentNozzle)m.getNozzle()).setThroatDiameter(Amount.valueOf(3, SI.MILLIMETER));
+ c.addBurn(new Burn(m));
+
+ Thread.sleep(5000);
+
+ c.removeBurn(b);
+
+ }
+
+ @Override
+ public void replace(Burn oldBurn, Burn newBurn) {
+ removeBurn(oldBurn);
+ addBurn(newBurn);
+ }
+}
if (part instanceof Motor) {
setText(((Motor) part).getName());
+ } else if ( part instanceof String ) {
+ setText((String)part);
} else if ( part == null ) {
setText("");
} else {
}
public WorkbenchTreeModel() {
- super(new DefaultMutableTreeNode(), true);
+ super(new DefaultMutableTreeNode("All Motors"), true);
}
@Override