]> git.gag.com Git - debian/openrocket/blob - src/net/sf/openrocket/gui/figureelements/RocketInfo.java
f573e182b2d3e93d1d0d4fcfd9c2db9664ca9277
[debian/openrocket] / src / net / sf / openrocket / gui / figureelements / RocketInfo.java
1 package net.sf.openrocket.gui.figureelements;
2
3 import static net.sf.openrocket.util.Chars.*;
4
5 import java.awt.Color;
6 import java.awt.Font;
7 import java.awt.Graphics2D;
8 import java.awt.Rectangle;
9 import java.awt.font.GlyphVector;
10 import java.awt.geom.Rectangle2D;
11
12 import net.sf.openrocket.aerodynamics.Warning;
13 import net.sf.openrocket.aerodynamics.WarningSet;
14 import net.sf.openrocket.rocketcomponent.Configuration;
15 import net.sf.openrocket.simulation.FlightData;
16 import net.sf.openrocket.unit.UnitGroup;
17 import net.sf.openrocket.util.MathUtil;
18 import net.sf.openrocket.util.Prefs;
19
20
21 /**
22  * A <code>FigureElement</code> that draws text at different positions in the figure
23  * with general data about the rocket.
24  * 
25  * @author Sampo Niskanen <sampo.niskanen@iki.fi>
26  */
27 public class RocketInfo implements FigureElement {
28         
29         // Margin around the figure edges, pixels
30         private static final int MARGIN = 8;
31
32         // Font to use
33         private static final Font FONT = new Font(Font.SANS_SERIF, Font.PLAIN, 11);
34         private static final Font SMALLFONT = new Font(Font.SANS_SERIF, Font.PLAIN, 9);
35
36         
37         private final Caret cpCaret = new CPCaret(0,0);
38         private final Caret cgCaret = new CGCaret(0,0);
39         
40         private final Configuration configuration;
41         private final UnitGroup stabilityUnits;
42         
43         private double cg = 0, cp = 0;
44         private double length = 0, diameter = 0;
45         private double mass = 0;
46         private double aoa = Double.NaN, theta = Double.NaN, mach = Prefs.getDefaultMach();
47         
48         private WarningSet warnings = null;
49         
50         private boolean calculatingData = false;
51         private FlightData flightData = null;
52         
53         private Graphics2D g2 = null;
54         private float line = 0;
55         private float x1, x2, y1, y2;
56         
57         
58         
59         
60         
61         public RocketInfo(Configuration configuration) {
62                 this.configuration = configuration;
63                 this.stabilityUnits = UnitGroup.stabilityUnits(configuration);
64         }
65         
66         
67         @Override
68         public void paint(Graphics2D g2, double scale) {
69                 throw new UnsupportedOperationException("paint() must be called with coordinates");
70         }
71
72         @Override
73         public void paint(Graphics2D g2, double scale, Rectangle visible) {
74                 this.g2 = g2;
75                 this.line = FONT.getLineMetrics("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
76                                 g2.getFontRenderContext()).getHeight();
77                 
78                 x1 = visible.x + MARGIN;
79                 x2 = visible.x + visible.width - MARGIN;
80                 y1 = visible.y + line ;
81                 y2 = visible.y + visible.height - MARGIN;
82
83                 drawMainInfo();
84                 drawStabilityInfo();
85                 drawWarnings();
86                 drawFlightInformation();
87         }
88         
89         
90         public void setCG(double cg) {
91                 this.cg = cg;
92         }
93         
94         public void setCP(double cp) {
95                 this.cp = cp;
96         }
97         
98         public void setLength(double length) {
99                 this.length = length;
100         }
101         
102         public void setDiameter(double diameter) {
103                 this.diameter = diameter;
104         }
105         
106         public void setMass(double mass) {
107                 this.mass = mass;
108         }
109         
110         public void setWarnings(WarningSet warnings) {
111                 this.warnings = warnings.clone();
112         }
113         
114         public void setAOA(double aoa) {
115                 this.aoa = aoa;
116         }
117         
118         public void setTheta(double theta) {
119                 this.theta = theta;
120         }
121         
122         public void setMach(double mach) {
123                 this.mach = mach;
124         }
125         
126         
127         public void setFlightData(FlightData data) {
128                 this.flightData = data;
129         }
130         
131         public void setCalculatingData(boolean calc) {
132                 this.calculatingData = calc;
133         }
134         
135         
136         
137         
138         private void drawMainInfo() {
139                 GlyphVector name = createText(configuration.getRocket().getName());
140                 GlyphVector lengthLine = createText(
141                                 "Length " + UnitGroup.UNITS_LENGTH.getDefaultUnit().toStringUnit(length) +
142                                 ", max. diameter " + 
143                                 UnitGroup.UNITS_LENGTH.getDefaultUnit().toStringUnit(diameter));
144                 
145                 String massText;
146                 if (configuration.hasMotors())
147                         massText = "Mass with motors ";
148                 else
149                         massText = "Mass with no motors ";
150                 
151                 massText += UnitGroup.UNITS_MASS.getDefaultUnit().toStringUnit(mass);
152                 
153                 GlyphVector massLine = createText(massText);
154
155                 
156                 g2.setColor(Color.BLACK);
157
158                 g2.drawGlyphVector(name, x1, y1);
159                 g2.drawGlyphVector(lengthLine, x1, y1+line);
160                 g2.drawGlyphVector(massLine, x1, y1+2*line);
161
162         }
163         
164         
165         private void drawStabilityInfo() {
166                 String at;
167                 
168                 at = "at M="+UnitGroup.UNITS_COEFFICIENT.getDefaultUnit().toStringUnit(mach);
169                 if (!Double.isNaN(aoa)) {
170                         at += " "+ALPHA+"=" + UnitGroup.UNITS_ANGLE.getDefaultUnit().toStringUnit(aoa);
171                 }
172                 if (!Double.isNaN(theta)) {
173                         at += " "+THETA+"=" + UnitGroup.UNITS_ANGLE.getDefaultUnit().toStringUnit(theta);
174                 }
175                 
176                 GlyphVector cgValue = createText(
177                                 UnitGroup.UNITS_LENGTH.getDefaultUnit().toStringUnit(cg));
178                 GlyphVector cpValue = createText(
179                                 UnitGroup.UNITS_LENGTH.getDefaultUnit().toStringUnit(cp));
180                 GlyphVector stabValue = createText(
181                                 stabilityUnits.getDefaultUnit().toStringUnit(cp-cg));
182                                 
183                 GlyphVector cgText = createText("CG:  ");
184                 GlyphVector cpText = createText("CP:  ");
185                 GlyphVector stabText = createText("Stability:  ");
186                 GlyphVector atText = createSmallText(at);
187
188                 Rectangle2D cgRect = cgValue.getVisualBounds();
189                 Rectangle2D cpRect = cpValue.getVisualBounds();
190                 Rectangle2D cgTextRect = cgText.getVisualBounds();
191                 Rectangle2D cpTextRect = cpText.getVisualBounds();
192                 Rectangle2D stabRect = stabValue.getVisualBounds();
193                 Rectangle2D stabTextRect = stabText.getVisualBounds();
194                 Rectangle2D atTextRect = atText.getVisualBounds();
195                 
196                 double unitWidth = MathUtil.max(cpRect.getWidth(), cgRect.getWidth(),
197                                 stabRect.getWidth());
198                 double textWidth = Math.max(cpTextRect.getWidth(), cgTextRect.getWidth());
199                 
200
201                 g2.setColor(Color.BLACK);
202
203                 g2.drawGlyphVector(stabValue, (float)(x2-stabRect.getWidth()), y1);
204                 g2.drawGlyphVector(cgValue, (float)(x2-cgRect.getWidth()), y1+line);
205                 g2.drawGlyphVector(cpValue, (float)(x2-cpRect.getWidth()), y1+2*line);
206
207                 g2.drawGlyphVector(stabText, (float)(x2-unitWidth-stabTextRect.getWidth()), y1);
208                 g2.drawGlyphVector(cgText, (float)(x2-unitWidth-cgTextRect.getWidth()), y1+line);
209                 g2.drawGlyphVector(cpText, (float)(x2-unitWidth-cpTextRect.getWidth()), y1+2*line);
210                                 
211                 cgCaret.setPosition(x2 - unitWidth - textWidth - 10, y1+line-0.3*line);
212                 cgCaret.paint(g2, 1.7);
213
214                 cpCaret.setPosition(x2 - unitWidth - textWidth - 10, y1+2*line-0.3*line);
215                 cpCaret.paint(g2, 1.7);
216                 
217                 float atPos;
218                 if (unitWidth + textWidth + 10 > atTextRect.getWidth()) {
219                         atPos = (float)(x2-(unitWidth+textWidth+10+atTextRect.getWidth())/2);
220                 } else {
221                         atPos = (float)(x2 - atTextRect.getWidth());
222                 }
223                 
224                 g2.setColor(Color.GRAY);
225                 g2.drawGlyphVector(atText, atPos, y1 + 3*line);
226
227         }
228
229         
230         private void drawWarnings() {
231                 if (warnings == null || warnings.isEmpty())
232                         return;
233                 
234                 GlyphVector[] texts = new GlyphVector[warnings.size()+1];
235                 double max = 0;
236                 
237                 texts[0] = createText("Warning:");
238                 int i=1;
239                 for (Warning w: warnings) {
240                         texts[i] = createText(w.toString());
241                         i++;
242                 }
243                 
244                 for (GlyphVector v: texts) {
245                         Rectangle2D rect = v.getVisualBounds();
246                         if (rect.getWidth() > max)
247                                 max = rect.getWidth();
248                 }
249                 
250
251                 float y = y2 - line * warnings.size();
252                 g2.setColor(new Color(255,0,0,130));
253
254                 for (GlyphVector v: texts) {
255                         Rectangle2D rect = v.getVisualBounds();
256                         g2.drawGlyphVector(v, (float)(x2 - max/2 - rect.getWidth()/2), y);
257                         y += line;
258                 }
259         }
260         
261         
262         private void drawFlightInformation() {
263                 double height = drawFlightData();
264                 
265                 if (calculatingData) {
266                         GlyphVector calculating = createText("Calculating...");
267                         g2.setColor(Color.BLACK);
268                         g2.drawGlyphVector(calculating, x1, (float)(y2-height));
269                 }
270         }
271         
272         
273         private double drawFlightData() {
274                 if (flightData == null)
275                         return 0;
276                 
277                 double width=0;
278                 
279                 GlyphVector apogee = createText("Apogee: ");
280                 GlyphVector maxVelocity = createText("Max. velocity: ");
281                 GlyphVector maxAcceleration = createText("Max. acceleration: ");
282
283                 GlyphVector apogeeValue, velocityValue, accelerationValue;
284                 if (!Double.isNaN(flightData.getMaxAltitude())) {
285                         apogeeValue = createText(
286                                         UnitGroup.UNITS_DISTANCE.toStringUnit(flightData.getMaxAltitude()));
287                 } else {
288                         apogeeValue = createText("N/A");
289                 }
290                 if (!Double.isNaN(flightData.getMaxVelocity())) {
291                         velocityValue = createText(
292                                         UnitGroup.UNITS_VELOCITY.toStringUnit(flightData.getMaxVelocity()) +
293                                         "  (Mach " + 
294                                         UnitGroup.UNITS_COEFFICIENT.toString(flightData.getMaxMachNumber()) + ")");
295                 } else {
296                         velocityValue = createText("N/A");
297                 }
298                 if (!Double.isNaN(flightData.getMaxAcceleration())) {
299                         accelerationValue = createText(
300                                         UnitGroup.UNITS_ACCELERATION.toStringUnit(flightData.getMaxAcceleration()));
301                 } else {
302                         accelerationValue = createText("N/A");
303                 }
304                 
305                 Rectangle2D rect;
306                 rect = apogee.getVisualBounds();
307                 width = MathUtil.max(width, rect.getWidth());
308                 
309                 rect = maxVelocity.getVisualBounds();
310                 width = MathUtil.max(width, rect.getWidth());
311                 
312                 rect = maxAcceleration.getVisualBounds();
313                 width = MathUtil.max(width, rect.getWidth());
314                 
315                 width += 5;
316
317                 if (!calculatingData) 
318                         g2.setColor(new Color(0,0,127));
319                 else
320                         g2.setColor(new Color(0,0,127,127));
321
322                 
323                 g2.drawGlyphVector(apogee, (float)x1, (float)(y2-2*line));
324                 g2.drawGlyphVector(maxVelocity, (float)x1, (float)(y2-line));
325                 g2.drawGlyphVector(maxAcceleration, (float)x1, (float)(y2));
326
327                 g2.drawGlyphVector(apogeeValue, (float)(x1+width), (float)(y2-2*line));
328                 g2.drawGlyphVector(velocityValue, (float)(x1+width), (float)(y2-line));
329                 g2.drawGlyphVector(accelerationValue, (float)(x1+width), (float)(y2));
330                 
331                 return 3*line;
332         }
333         
334         
335         
336         private GlyphVector createText(String text) {
337                 return FONT.createGlyphVector(g2.getFontRenderContext(), text);
338         }
339
340         private GlyphVector createSmallText(String text) {
341                 return SMALLFONT.createGlyphVector(g2.getFontRenderContext(), text);
342         }
343
344 }