1 package com.billkuker.rocketry.motorsim.visual;
\r
3 import java.awt.BasicStroke;
\r
4 import java.awt.BorderLayout;
\r
5 import java.awt.Color;
\r
6 import java.awt.Component;
\r
7 import java.awt.Dimension;
\r
8 import java.awt.Graphics;
\r
9 import java.awt.Graphics2D;
\r
10 import java.awt.Rectangle;
\r
11 import java.awt.geom.AffineTransform;
\r
12 import java.beans.PropertyChangeEvent;
\r
13 import java.beans.PropertyChangeListener;
\r
14 import java.text.NumberFormat;
\r
16 import javax.measure.quantity.Area;
\r
17 import javax.measure.quantity.Length;
\r
18 import javax.measure.quantity.Volume;
\r
19 import javax.measure.unit.SI;
\r
20 import javax.swing.JFrame;
\r
21 import javax.swing.JLabel;
\r
22 import javax.swing.JPanel;
\r
23 import javax.swing.JSlider;
\r
24 import javax.swing.JSplitPane;
\r
25 import javax.swing.WindowConstants;
\r
26 import javax.swing.event.ChangeEvent;
\r
27 import javax.swing.event.ChangeListener;
\r
29 import org.jscience.physics.amount.Amount;
\r
31 import com.billkuker.rocketry.motorsim.ChangeListening;
\r
32 import com.billkuker.rocketry.motorsim.Grain;
\r
34 public class GrainPanel extends JPanel {
\r
35 private static final long serialVersionUID = 1L;
\r
36 private Amount<Length> displayedRegression = Amount.valueOf(0, SI.MILLIMETER);
\r
37 private JLabel l = new JLabel();
\r
38 private Chart<Length,Area> area;
\r
39 Chart<Length, Volume> volume;
\r
41 private Grain grain;
\r
43 public GrainPanel(Grain g){
\r
44 super(new BorderLayout());
\r
48 if ( g instanceof ChangeListening.Subject ){
\r
49 ((ChangeListening.Subject)g).addPropertyChangeListener(new PropertyChangeListener(){
\r
50 public void propertyChange(PropertyChangeEvent evt) {
\r
52 area.setDomain(area.new IntervalDomain(Amount.valueOf(0, SI.MILLIMETER), grain.webThickness()));
\r
53 volume.setDomain(volume.new IntervalDomain(Amount.valueOf(0, SI.MILLIMETER), grain.webThickness()));
\r
61 area = new Chart<Length, Area>(
\r
63 SI.MILLIMETER.pow(2).asType(Area.class),
\r
66 area.setDomain(area.new IntervalDomain(Amount.valueOf(0, SI.MILLIMETER), grain.webThickness()));
\r
68 volume = new Chart<Length, Volume>(
\r
70 SI.MILLIMETER.pow(3).asType(Volume.class),
\r
73 volume.setDomain(volume.new IntervalDomain(Amount.valueOf(0, SI.MILLIMETER), grain.webThickness()));
\r
75 area.setMaximumSize(new Dimension(200,100));
\r
76 volume.setMaximumSize(new Dimension(200,100));
\r
79 } catch (ClassCastException e) {
\r
80 // TODO Auto-generated catch block
\r
81 e.printStackTrace();
\r
82 } catch (NoSuchMethodException e) {
\r
83 // TODO Auto-generated catch block
\r
84 e.printStackTrace();
\r
96 protected void addComponents(
\r
97 Component crossSection,
\r
104 JSplitPane v = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
\r
105 JSplitPane h = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
\r
107 JPanel graphics = new JPanel(new BorderLayout());
\r
108 graphics.add(crossSection, BorderLayout.CENTER);
\r
109 graphics.add(label, BorderLayout.NORTH);
\r
110 graphics.add(slider, BorderLayout.SOUTH);
\r
112 v.setTopComponent(h);
\r
113 v.setBottomComponent(area);
\r
114 h.setLeftComponent(graphics);
\r
115 h.setRightComponent(volume);
\r
118 h.resetToPreferredSizes();
\r
119 v.resetToPreferredSizes();
\r
123 public void setDisplayedRegression( Amount<Length> r ){
\r
124 displayedRegression = r;
\r
126 NumberFormat nf = NumberFormat.getInstance();
\r
127 nf.setMaximumFractionDigits(2);
\r
128 l.setText("Regression: " + nf.format(displayedRegression.doubleValue(SI.MILLIMETER)) + "mm");
\r
130 area.mark(displayedRegression);
\r
131 volume.mark(displayedRegression);
\r
136 private class XC extends JPanel{
\r
137 private static final long serialVersionUID = 1L;
\r
139 public XC(Grain g){
\r
141 java.awt.geom.Area unburnt = grain.getSideView(Amount.valueOf(0, SI.MILLIMETER));
\r
143 Rectangle bounds = unburnt.getBounds();
\r
144 double max = bounds.getWidth();
\r
145 if ( bounds.getHeight() > max )
\r
146 max = bounds.getHeight();
\r
147 int w = (int)(bounds.getWidth() * 200.0 / max);
\r
151 Dimension sz = new Dimension(240+w, 250);
\r
152 setMinimumSize(sz);
\r
153 setPreferredSize(sz);
\r
154 setMaximumSize(sz);
\r
156 public void paint(Graphics g){
\r
158 Graphics2D g2d = (Graphics2D)g;
\r
159 g2d.translate(10, 30);
\r
161 grain.draw(g2d, displayedRegression );
\r
165 AffineTransform t = g2d.getTransform();
\r
166 java.awt.geom.Area unburnt = grain.getCrossSection(Amount.valueOf(0, SI.MILLIMETER));
\r
168 Rectangle bounds = unburnt.getBounds();
\r
169 g2d.scale(200 / bounds.getWidth(), 200 / bounds.getHeight());
\r
170 g2d.translate(-bounds.getX(), -bounds.getY());
\r
172 //Draw the fuel that is left
\r
173 java.awt.geom.Area burning = grain.getCrossSection(displayedRegression);
\r
174 g2d.setColor(Color.RED);
\r
176 //Draw the fuel that is left
\r
177 java.awt.geom.Area left = grain.getCrossSection(displayedRegression.plus(grain.webThickness().divide(30)));
\r
178 g2d.setColor(Color.GRAY);
\r
180 //Draw the outline of the unburnt grain
\r
181 g2d.setStroke(new BasicStroke(1.0f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND));
\r
182 g2d.setColor(Color.BLACK);
\r
185 g2d.setTransform(t);
\r
188 AffineTransform t = g2d.getTransform();
\r
189 java.awt.geom.Area unburnt = grain.getSideView(Amount.valueOf(0, SI.MILLIMETER));
\r
191 Rectangle bounds = unburnt.getBounds();
\r
192 g2d.translate(220, 0);
\r
194 double max = bounds.getWidth();
\r
195 if ( bounds.getHeight() > max )
\r
196 max = bounds.getHeight();
\r
198 g2d.scale(200 / max, 200 / max);
\r
199 g2d.translate(-bounds.getX(), -bounds.getY());
\r
201 //Draw the fuel that is left
\r
202 java.awt.geom.Area burning = grain.getSideView(displayedRegression);
\r
203 g2d.setColor(Color.RED);
\r
205 //Draw the fuel that is left
\r
206 java.awt.geom.Area left = grain.getSideView(displayedRegression.plus(grain.webThickness().divide(30)));
\r
207 g2d.setColor(Color.GRAY);
\r
209 //Draw the outline of the unburnt grain
\r
210 g2d.setColor(Color.BLACK);
\r
213 g2d.setTransform(t);
\r
219 private class SL extends JSlider implements ChangeListener{
\r
220 private static final long serialVersionUID = 1L;
\r
221 private static final int STEPS = 60;
\r
223 addChangeListener(this);
\r
229 public void stateChanged(ChangeEvent e) {
\r
230 double r = ((SL)e.getSource()).getValue();
\r
232 setDisplayedRegression(grain.webThickness().divide(STEPS).times(r));
\r
236 public void showAsWindow(){
\r
237 JFrame f = new JFrame();
\r
238 f.setTitle(grain.getClass().getName());
\r
239 f.setSize(1024,600);
\r
240 f.setContentPane(this);
\r
241 f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
\r
242 f.setVisible(true);
\r