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