6ee32df1f6626df0e1f632be0e65a8fa795c8b53
[sw/motorsim] / gui / com / billkuker / rocketry / motorsim / visual / BurnPanel.java
1 package com.billkuker.rocketry.motorsim.visual;\r
2 \r
3 import java.awt.BorderLayout;\r
4 import java.awt.Color;\r
5 import java.awt.Dimension;\r
6 import java.text.NumberFormat;\r
7 \r
8 import javax.measure.quantity.Duration;\r
9 import javax.measure.quantity.Force;\r
10 import javax.measure.quantity.Pressure;\r
11 import javax.measure.quantity.Velocity;\r
12 import javax.measure.unit.SI;\r
13 import javax.swing.JFrame;\r
14 import javax.swing.JPanel;\r
15 import javax.swing.JSlider;\r
16 import javax.swing.JSplitPane;\r
17 import javax.swing.WindowConstants;\r
18 import javax.swing.event.ChangeEvent;\r
19 import javax.swing.event.ChangeListener;\r
20 \r
21 import org.jscience.physics.amount.Amount;\r
22 \r
23 import com.billkuker.rocketry.motorsim.Burn;\r
24 import com.billkuker.rocketry.motorsim.BurnSummary;\r
25 \r
26 public class BurnPanel extends JPanel {\r
27         private static final long serialVersionUID = 1L;\r
28         private Burn burn;\r
29         Chart<Duration, Pressure> pressure;\r
30         Chart<Duration, Force> thrust;\r
31         Chart<Pressure, Velocity> burnRate;\r
32         GrainPanel grain;\r
33         Amount<Duration> displayedTime = Amount.valueOf(0, SI.SECOND);\r
34         \r
35         private static final Color RED = new Color(196, 0, 0);\r
36         private static final Color GREEN = new Color(0, 196, 0);\r
37         private static final Color ORANGE = new Color(160, 96, 0);\r
38         \r
39         public BurnPanel(Burn b){\r
40                 super( new BorderLayout() );\r
41                 burn = b;\r
42                 \r
43                 try {\r
44                         pressure = new Chart<Duration, Pressure>(\r
45                                         SI.SECOND,\r
46                                         SI.MEGA(SI.PASCAL),\r
47                                         b,\r
48                                         "pressure");\r
49                         pressure.setDomain(burn.getData().keySet());\r
50                         \r
51                         thrust = new Chart<Duration, Force>(\r
52                                         SI.SECOND,\r
53                                         SI.NEWTON,\r
54                                         b,\r
55                                         "thrust");\r
56                         thrust.setDomain(burn.getData().keySet());\r
57                         \r
58                         burnRate = new Chart<Pressure, Velocity>(\r
59                                         SI.MEGA(SI.PASCAL),\r
60                                         SI.METERS_PER_SECOND,\r
61                                         burn.getMotor().getFuel(),\r
62                                         "burnRate");\r
63                         burnRate.setDomain(\r
64                                         burnRate.new IntervalDomain(\r
65                                                         Amount.valueOf(0, SI.MEGA(SI.PASCAL)),\r
66                                                         Amount.valueOf(11, SI.MEGA(SI.PASCAL)),\r
67                                                         20\r
68                                                         ));\r
69                         \r
70                         \r
71                         JSplitPane tp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, thrust, pressure);\r
72                         tp.setDividerLocation(.5);\r
73                         tp.setResizeWeight(.5);\r
74                         \r
75                         grain = new GrainPanel(burn.getMotor().getGrain()){\r
76                                 private static final long serialVersionUID = 1L;\r
77                                 @Override protected void addComponents(java.awt.Component crossSection, java.awt.Component slider, java.awt.Component label, java.awt.Component area, java.awt.Component volume) {\r
78                                         JSplitPane h = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, crossSection, area); \r
79                                         add(h, BorderLayout.CENTER);\r
80                                         h.resetToPreferredSizes();\r
81                                 };\r
82                         };\r
83                         \r
84                         JSplitPane grains = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, grain, burnRate);\r
85                         grains.setDividerLocation(.5);\r
86                         grains.setResizeWeight(.5);\r
87                         \r
88                         JSplitPane main = new JSplitPane(JSplitPane.VERTICAL_SPLIT, grains, tp);\r
89                         Dimension minimumSize = new Dimension(800, 200);\r
90                         grains.setMinimumSize(minimumSize);\r
91                         tp.setMinimumSize(minimumSize);\r
92                         main.setDividerLocation(.5);\r
93                         main.setResizeWeight(.5);\r
94                         \r
95                         add( main, BorderLayout.CENTER );\r
96                         \r
97                         add( new SL(), BorderLayout.SOUTH);\r
98                         \r
99                         BurnSummary bi = new BurnSummary(burn);\r
100                         SummaryPanel text = new SummaryPanel(burn);\r
101                         text.setBurnSummary(bi);\r
102                         add(text, BorderLayout.NORTH);\r
103                         \r
104                         {\r
105 \r
106                                 //Color in the Burst marker\r
107                                 Color saftyColor;\r
108                                 if ( bi.getSaftyFactor() == null ){\r
109                                         saftyColor = Color.BLACK;\r
110                                 } else {\r
111                                         double d = bi.getSaftyFactor();\r
112                                         if ( d >= 1.5 ){\r
113                                                 saftyColor = GREEN;\r
114                                         } else if ( d > 1 ){\r
115                                                 saftyColor = ORANGE;\r
116                                         } else {\r
117                                                 saftyColor = RED;\r
118                                         }\r
119                                 }\r
120                                 Amount<Pressure> burst = b.getMotor().getChamber().getBurstPressure();\r
121                                 if ( burst != null ){\r
122                                         pressure.addRangeMarker(burst, "Burst", saftyColor);\r
123                                 }\r
124                                 \r
125                                 //Add some additional Markers\r
126                                 thrust.addRangeMarker(bi.maxThrust(), "Max", Color.BLACK);\r
127                                 thrust.addRangeMarker(bi.averageThrust(), "Average", Color.BLACK);\r
128                                 pressure.addRangeMarker(bi.maxPressure(), "Max", Color.BLACK);\r
129                                 burnRate.addDomainMarker(bi.maxPressure(), "Max", RED);\r
130                                 \r
131 \r
132                         }\r
133                         \r
134                         \r
135                 } catch (NoSuchMethodException e){\r
136                         throw new Error(e);\r
137                 }\r
138                 \r
139 \r
140         }\r
141         \r
142         private class SL extends JSlider implements ChangeListener{\r
143                 private static final long serialVersionUID = 1L;\r
144                 private static final int STEPS = 80;\r
145                 public SL(){\r
146                         addChangeListener(this);\r
147                         setMinimum(0);\r
148                         setMaximum(STEPS);\r
149                         setValue(0);\r
150                 }\r
151                 \r
152                 public void stateChanged(ChangeEvent e) {\r
153                         double t = ((SL)e.getSource()).getValue();\r
154                         displayedTime = burn.burnTime().divide(STEPS).times(t);\r
155                         \r
156                         //Find the nearest key in the data set\r
157                         displayedTime =burn.getData().tailMap(displayedTime).firstKey();\r
158                         \r
159                         NumberFormat nf = NumberFormat.getInstance();\r
160                         nf.setMaximumFractionDigits(2);\r
161                         \r
162                         pressure.mark(displayedTime);\r
163                         thrust.mark(displayedTime);\r
164                         \r
165                         grain.setDisplayedRegression(burn.getData().get(displayedTime).regression);\r
166                         \r
167                         burnRate.mark(burn.getData().get(displayedTime).chamberPressure);\r
168                         \r
169                         \r
170                         /*\r
171                         double r = ((SL)e.getSource()).getValue();\r
172                         displayedRegression = grain.webThickness().divide(STEPS).times(r);\r
173                         NumberFormat nf = NumberFormat.getInstance();\r
174                         nf.setMaximumFractionDigits(2);\r
175                         l.setText("Regression: " + nf.format(displayedRegression.doubleValue(SI.MILLIMETER)) + "mm");\r
176                         area.mark(displayedRegression);\r
177                         volume.mark(displayedRegression);\r
178                         if ( xc != null )\r
179                                 xc.repaint();\r
180                         */\r
181                 }\r
182         }\r
183         \r
184         public void showAsWindow(){\r
185                 JFrame f = new JFrame();\r
186                 f.setTitle(burn.getMotor().getName());\r
187                 f.setSize(1280,720);\r
188                 f.setLocation(0, 0);\r
189                 f.setContentPane(this);\r
190                 f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);\r
191                 f.setVisible(true);\r
192         }\r
193 }\r