1 package com.billkuker.rocketry.motorsim.grain;
\r
3 import java.awt.BorderLayout;
\r
4 import java.awt.Color;
\r
5 import java.awt.Dimension;
\r
6 import java.awt.Graphics;
\r
7 import java.awt.Graphics2D;
\r
8 import java.awt.Rectangle;
\r
9 import java.awt.geom.AffineTransform;
\r
10 import java.text.NumberFormat;
\r
12 import javax.measure.quantity.Area;
\r
13 import javax.measure.quantity.Length;
\r
14 import javax.measure.quantity.Volume;
\r
15 import javax.measure.unit.SI;
\r
16 import javax.swing.JFrame;
\r
17 import javax.swing.JLabel;
\r
18 import javax.swing.JPanel;
\r
19 import javax.swing.JSlider;
\r
20 import javax.swing.JSplitPane;
\r
21 import javax.swing.event.ChangeEvent;
\r
22 import javax.swing.event.ChangeListener;
\r
24 import org.jscience.physics.amount.Amount;
\r
26 import com.billkuker.rocketry.motorsim.Grain;
\r
27 import com.billkuker.rocketry.motorsim.visual.Chart;
\r
29 public class GrainPanel extends JPanel {
\r
30 private static final long serialVersionUID = 1L;
\r
31 private Amount<Length> displayedRegression = Amount.valueOf(0, SI.MILLIMETER);
\r
32 private JLabel l = new JLabel();
\r
33 private Chart<Length,Area> area;
\r
34 Chart<Length, Volume> volume;
\r
37 private Grain grain;
\r
39 public GrainPanel(Grain g){
\r
40 super(new BorderLayout());
\r
46 area = new Chart<Length, Area>(
\r
48 SI.MILLIMETER.pow(2).asType(Area.class),
\r
51 area.setDomain(area.new IntervalDomain(Amount.valueOf(0, SI.MILLIMETER), grain.webThickness()));
\r
53 volume = new Chart<Length, Volume>(
\r
55 SI.MILLIMETER.pow(3).asType(Volume.class),
\r
58 volume.setDomain(volume.new IntervalDomain(Amount.valueOf(0, SI.MILLIMETER), grain.webThickness()));
\r
60 area.setMaximumSize(new Dimension(200,100));
\r
61 volume.setMaximumSize(new Dimension(200,100));
\r
64 } catch (ClassCastException e) {
\r
65 // TODO Auto-generated catch block
\r
66 e.printStackTrace();
\r
67 } catch (NoSuchMethodException e) {
\r
68 // TODO Auto-generated catch block
\r
69 e.printStackTrace();
\r
73 JSplitPane charts = new JSplitPane(JSplitPane.VERTICAL_SPLIT, area, volume);
\r
74 charts.setDividerLocation(.5);
\r
75 charts.setResizeWeight(.5);
\r
77 JPanel left = new JPanel(new BorderLayout());
\r
79 if ( grain instanceof Grain.Graphical){
\r
80 add(xc = new XC((Grain.Graphical)grain), BorderLayout.CENTER);
\r
83 left.add(l, BorderLayout.NORTH);
\r
84 left.add( sl = new SL(), BorderLayout.SOUTH);
\r
86 add(new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, left, charts));
\r
90 public void setDisplayedRegression( Amount<Length> r ){
\r
91 displayedRegression = r;
\r
93 NumberFormat nf = NumberFormat.getInstance();
\r
94 nf.setMaximumFractionDigits(2);
\r
95 l.setText("Regression: " + nf.format(displayedRegression.doubleValue(SI.MILLIMETER)) + "mm");
\r
97 area.mark(displayedRegression);
\r
98 volume.mark(displayedRegression);
\r
103 private class XC extends JPanel{
\r
104 private static final long serialVersionUID = 1L;
\r
105 Grain.Graphical grain;
\r
106 public XC(Grain.Graphical g){
\r
107 setMinimumSize(new Dimension(440,250));
\r
110 public void paint(Graphics g){
\r
112 Graphics2D g2d = (Graphics2D)g;
\r
113 g2d.translate(10, 30);
\r
115 grain.draw(g2d, displayedRegression );
\r
119 AffineTransform t = g2d.getTransform();
\r
120 java.awt.geom.Area unburnt = grain.getCrossSection(Amount.valueOf(0, SI.MILLIMETER));
\r
122 Rectangle bounds = unburnt.getBounds();
\r
123 g2d.scale(200 / bounds.getWidth(), 200 / bounds.getHeight());
\r
124 g2d.translate(-bounds.getX(), -bounds.getY());
\r
126 //Draw the fuel that is left
\r
127 java.awt.geom.Area burning = grain.getCrossSection(displayedRegression);
\r
128 g2d.setColor(Color.RED);
\r
130 //Draw the fuel that is left
\r
131 java.awt.geom.Area left = grain.getCrossSection(displayedRegression.plus(grain.webThickness().divide(30)));
\r
132 g2d.setColor(Color.GRAY);
\r
134 //Draw the outline of the unburnt grain
\r
135 g2d.setColor(Color.BLACK);
\r
138 g2d.setTransform(t);
\r
141 AffineTransform t = g2d.getTransform();
\r
142 java.awt.geom.Area unburnt = grain.getSideView(Amount.valueOf(0, SI.MILLIMETER));
\r
144 Rectangle bounds = unburnt.getBounds();
\r
145 g2d.translate(220, 0);
\r
147 double max = bounds.getWidth();
\r
148 if ( bounds.getHeight() > max )
\r
149 max = bounds.getHeight();
\r
151 g2d.scale(200 / max, 200 / max);
\r
152 g2d.translate(-bounds.getX(), -bounds.getY());
\r
154 //Draw the fuel that is left
\r
155 java.awt.geom.Area burning = grain.getSideView(displayedRegression);
\r
156 g2d.setColor(Color.RED);
\r
158 //Draw the fuel that is left
\r
159 java.awt.geom.Area left = grain.getSideView(displayedRegression.plus(grain.webThickness().divide(30)));
\r
160 g2d.setColor(Color.GRAY);
\r
162 //Draw the outline of the unburnt grain
\r
163 g2d.setColor(Color.BLACK);
\r
166 g2d.setTransform(t);
\r
172 private class SL extends JSlider implements ChangeListener{
\r
173 private static final long serialVersionUID = 1L;
\r
174 private static final int STEPS = 60;
\r
176 addChangeListener(this);
\r
183 public void stateChanged(ChangeEvent e) {
\r
184 double r = ((SL)e.getSource()).getValue();
\r
186 setDisplayedRegression(grain.webThickness().divide(STEPS).times(r));
\r
190 public void show(){
\r
191 JFrame f = new JFrame();
\r
192 f.setSize(1024,600);
\r
193 f.setContentPane(this);
\r
194 f.setDefaultCloseOperation(f.DISPOSE_ON_CLOSE);
\r
195 f.setVisible(true);
\r