Display computer motor class in motor selection dialog

This commit is contained in:
Sampo Niskanen 2012-02-19 18:41:04 +00:00
parent 02fbe90a32
commit 216ba1dd00
3 changed files with 166 additions and 62 deletions

View File

@ -1,3 +1,7 @@
2012-02-19 Sampo Niskanen
* Display computed motor class
2012-02-16 Sampo Niskanen 2012-02-16 Sampo Niskanen
* [BUG] Freeze when dropping component on child component * [BUG] Freeze when dropping component on child component

View File

@ -0,0 +1,89 @@
package net.sf.openrocket.gui.dialogs.motor.thrustcurve;
import net.sf.openrocket.unit.UnitGroup;
import net.sf.openrocket.util.BugException;
/**
* NAR approved motor classes (http://www.nar.org/NARmotors.html).
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public enum MotorClass {
A18("1/8A", 0, 0.3125),
A14("1/4A", 0.3125, 0.625),
A12("1/2A", 0.625, 1.25),
A("A", 1.25, 2.5),
B("B", 2.5, 5),
C("C", 5, 10),
D("D", 10, 20),
E("E", 20, 40),
F("F", 40, 80),
G("G", 80, 160),
H("H", 160, 320),
I("I", 320, 640),
J("J", 640, 1280),
K("K", 1280, 2560),
L("L", 2560, 5120),
M("M", 5120, 10240),
N("N", 10240, 20480),
O("O", 20480, 40960),
OVER("> O", 40960, Double.MAX_VALUE) {
@Override
public String getDescription(double impulse) {
return "Over O";
}
@Override
public String getClassDescription() {
return "Over O-class (over " + UnitGroup.UNITS_IMPULSE.toStringUnit(40960) + ")";
}
};
private final String className;
private final double min;
private final double max;
private MotorClass(String className, double min, double max) {
this.className = className;
this.min = min;
this.max = max;
}
public String getDescription(double impulse) {
double percent = (impulse - min) / (max - min) * 100;
if (percent < 1) {
// 0% looks stupid
percent = 1;
}
return String.format("%d%% %s", Math.round(percent), className);
}
public String getClassDescription() {
return "Class " + className + " (" + UnitGroup.UNITS_IMPULSE.toStringUnit(min) + " - " + UnitGroup.UNITS_IMPULSE.toStringUnit(max) + ")";
}
/**
* Find the appropriate motor class for the provided impulse.
*/
public static MotorClass getMotorClass(double impulse) {
double epsilon = 0.0000001;
// Round large values so 640.1 Ns (which is displayed as 640 Ns) is counted as I-class
if (impulse >= 100) {
impulse = Math.rint(impulse);
}
for (MotorClass m : MotorClass.values()) {
if (impulse <= m.max + epsilon) {
return m;
}
}
throw new BugException("Could not find motor class for impulse " + impulse);
}
}

View File

@ -54,7 +54,6 @@ import net.sf.openrocket.gui.util.SwingPreferences;
import net.sf.openrocket.l10n.Translator; import net.sf.openrocket.l10n.Translator;
import net.sf.openrocket.logging.LogHelper; import net.sf.openrocket.logging.LogHelper;
import net.sf.openrocket.motor.Motor; import net.sf.openrocket.motor.Motor;
import net.sf.openrocket.motor.MotorDigest;
import net.sf.openrocket.motor.ThrustCurveMotor; import net.sf.openrocket.motor.ThrustCurveMotor;
import net.sf.openrocket.startup.Application; import net.sf.openrocket.startup.Application;
import net.sf.openrocket.unit.UnitGroup; import net.sf.openrocket.unit.UnitGroup;
@ -75,19 +74,19 @@ import org.jfree.data.xy.XYSeriesCollection;
public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelector { public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelector {
private static final LogHelper log = Application.getLogger(); private static final LogHelper log = Application.getLogger();
private static final Translator trans = Application.getTranslator(); private static final Translator trans = Application.getTranslator();
private static final double MOTOR_SIMILARITY_THRESHOLD = 0.95; private static final double MOTOR_SIMILARITY_THRESHOLD = 0.95;
private static final int SHOW_ALL = 0; private static final int SHOW_ALL = 0;
private static final int SHOW_SMALLER = 1; private static final int SHOW_SMALLER = 1;
private static final int SHOW_EXACT = 2; private static final int SHOW_EXACT = 2;
private static final String[] SHOW_DESCRIPTIONS = { private static final String[] SHOW_DESCRIPTIONS = {
//// Show all motors //// Show all motors
trans.get("TCMotorSelPan.SHOW_DESCRIPTIONS.desc1"), trans.get("TCMotorSelPan.SHOW_DESCRIPTIONS.desc1"),
//// Show motors with diameter less than that of the motor mount //// Show motors with diameter less than that of the motor mount
trans.get("TCMotorSelPan.SHOW_DESCRIPTIONS.desc2"), trans.get("TCMotorSelPan.SHOW_DESCRIPTIONS.desc2"),
//// Show motors with diameter equal to that of the motor mount //// Show motors with diameter equal to that of the motor mount
trans.get("TCMotorSelPan.SHOW_DESCRIPTIONS.desc3") trans.get("TCMotorSelPan.SHOW_DESCRIPTIONS.desc3")
}; };
private static final int SHOW_MAX = 2; private static final int SHOW_MAX = 2;
@ -101,14 +100,14 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
private static final ThrustCurveMotorComparator MOTOR_COMPARATOR = new ThrustCurveMotorComparator(); private static final ThrustCurveMotorComparator MOTOR_COMPARATOR = new ThrustCurveMotorComparator();
private final List<ThrustCurveMotorSet> database; private final List<ThrustCurveMotorSet> database;
private final double diameter; private final double diameter;
private CloseableDialog dialog = null; private CloseableDialog dialog = null;
private final ThrustCurveMotorDatabaseModel model; private final ThrustCurveMotorDatabaseModel model;
private final JTable table; private final JTable table;
private final TableRowSorter<TableModel> sorter; private final TableRowSorter<TableModel> sorter;
@ -118,12 +117,13 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
private final JTextField searchField; private final JTextField searchField;
private String[] searchTerms = new String[0]; private String[] searchTerms = new String[0];
private final JLabel curveSelectionLabel; private final JLabel curveSelectionLabel;
private final JComboBox curveSelectionBox; private final JComboBox curveSelectionBox;
private final DefaultComboBoxModel curveSelectionModel; private final DefaultComboBoxModel curveSelectionModel;
private final JLabel totalImpulseLabel; private final JLabel totalImpulseLabel;
private final JLabel classificationLabel;
private final JLabel avgThrustLabel; private final JLabel avgThrustLabel;
private final JLabel maxThrustLabel; private final JLabel maxThrustLabel;
private final JLabel burnTimeLabel; private final JLabel burnTimeLabel;
@ -159,7 +159,7 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
this.diameter = diameter; this.diameter = diameter;
// Construct the database (adding the current motor if not in the db already) // Construct the database (adding the current motor if not in the db already)
List<ThrustCurveMotorSet> db; List<ThrustCurveMotorSet> db;
// TODO - ugly blind cast. // TODO - ugly blind cast.
@ -185,8 +185,8 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
} }
database = db; database = db;
//// GUI //// GUI
JPanel panel; JPanel panel;
@ -195,8 +195,8 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
panel = new JPanel(new MigLayout("fill")); panel = new JPanel(new MigLayout("fill"));
this.add(panel, "grow"); this.add(panel, "grow");
// Selection label // Selection label
//// Select rocket motor: //// Select rocket motor:
label = new StyledLabel(trans.get("TCMotorSelPan.lbl.Selrocketmotor"), Style.BOLD); label = new StyledLabel(trans.get("TCMotorSelPan.lbl.Selrocketmotor"), Style.BOLD);
@ -246,12 +246,12 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
}); });
panel.add(hideSimilarBox, "gapleft para, spanx, growx, wrap para"); panel.add(hideSimilarBox, "gapleft para, spanx, growx, wrap para");
// Motor selection table // Motor selection table
model = new ThrustCurveMotorDatabaseModel(database); model = new ThrustCurveMotorDatabaseModel(database);
table = new JTable(model); table = new JTable(model);
// Set comparators and widths // Set comparators and widths
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
sorter = new TableRowSorter<TableModel>(model); sorter = new TableRowSorter<TableModel>(model);
@ -290,22 +290,22 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
} }
}); });
JScrollPane scrollpane = new JScrollPane(); JScrollPane scrollpane = new JScrollPane();
scrollpane.setViewportView(table); scrollpane.setViewportView(table);
panel.add(scrollpane, "grow, width :500:, height :300:, spanx, wrap para"); panel.add(scrollpane, "grow, width :500:, height :300:, spanx, wrap para");
// Motor mount diameter label // Motor mount diameter label
//// Motor mount diameter: //// Motor mount diameter:
label = new StyledLabel(trans.get("TCMotorSelPan.lbl.Motormountdia")+ " " + label = new StyledLabel(trans.get("TCMotorSelPan.lbl.Motormountdia") + " " +
UnitGroup.UNITS_MOTOR_DIMENSIONS.getDefaultUnit().toStringUnit(diameter)); UnitGroup.UNITS_MOTOR_DIMENSIONS.getDefaultUnit().toStringUnit(diameter));
panel.add(label, "gapright 30lp, spanx, split"); panel.add(label, "gapright 30lp, spanx, split");
// Search field // Search field
//// Search: //// Search:
label = new StyledLabel(trans.get("TCMotorSelPan.lbl.Search")); label = new StyledLabel(trans.get("TCMotorSelPan.lbl.Search"));
@ -345,15 +345,15 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
}); });
panel.add(searchField, "growx, wrap"); panel.add(searchField, "growx, wrap");
// Vertical split // Vertical split
this.add(panel, "grow"); this.add(panel, "grow");
this.add(new JSeparator(JSeparator.VERTICAL), "growy, gap para para"); this.add(new JSeparator(JSeparator.VERTICAL), "growy, gap para para");
panel = new JPanel(new MigLayout("fill")); panel = new JPanel(new MigLayout("fill"));
// Thrust curve selection // Thrust curve selection
//// Select thrust curve: //// Select thrust curve:
curveSelectionLabel = new JLabel(trans.get("TCMotorSelPan.lbl.Selectthrustcurve")); curveSelectionLabel = new JLabel(trans.get("TCMotorSelPan.lbl.Selectthrustcurve"));
@ -373,10 +373,10 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
}); });
panel.add(curveSelectionBox, "growx, wrap para"); panel.add(curveSelectionBox, "growx, wrap para");
// Ejection charge delay: // Ejection charge delay:
panel.add(new JLabel(trans.get("TCMotorSelPan.lbl.Ejectionchargedelay"))); panel.add(new JLabel(trans.get("TCMotorSelPan.lbl.Ejectionchargedelay")));
@ -404,16 +404,20 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
panel.add(new StyledLabel(trans.get("TCMotorSelPan.lbl.NumberofsecondsorNone"), -3), "skip, wrap para"); panel.add(new StyledLabel(trans.get("TCMotorSelPan.lbl.NumberofsecondsorNone"), -3), "skip, wrap para");
setDelays(false); setDelays(false);
panel.add(new JSeparator(), "spanx, growx, wrap para"); panel.add(new JSeparator(), "spanx, growx, wrap para");
// Thrust curve info // Thrust curve info
//// Total impulse: //// Total impulse:
panel.add(new JLabel(trans.get("TCMotorSelPan.lbl.Totalimpulse"))); panel.add(new JLabel(trans.get("TCMotorSelPan.lbl.Totalimpulse")));
totalImpulseLabel = new JLabel(); totalImpulseLabel = new JLabel();
panel.add(totalImpulseLabel, "wrap"); panel.add(totalImpulseLabel, "split");
classificationLabel = new JLabel();
classificationLabel.setEnabled(false); // Gray
// classificationLabel.setForeground(Color.GRAY);
panel.add(classificationLabel, "gapleft unrel, wrap");
//// Avg. thrust: //// Avg. thrust:
panel.add(new JLabel(trans.get("TCMotorSelPan.lbl.Avgthrust"))); panel.add(new JLabel(trans.get("TCMotorSelPan.lbl.Avgthrust")));
@ -454,7 +458,7 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
digestLabel = null; digestLabel = null;
} }
comment = new JTextArea(5, 5); comment = new JTextArea(5, 5);
GUIUtil.changeFontSize(comment, -2); GUIUtil.changeFontSize(comment, -2);
withCommentFont = comment.getFont(); withCommentFont = comment.getFont();
@ -465,9 +469,9 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
scrollpane = new JScrollPane(comment); scrollpane = new JScrollPane(comment);
panel.add(scrollpane, "spanx, growx, wrap para"); panel.add(scrollpane, "spanx, growx, wrap para");
// Thrust curve plot // Thrust curve plot
chart = ChartFactory.createXYLineChart( chart = ChartFactory.createXYLineChart(
null, // title null, // title
@ -480,7 +484,7 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
false // urls false // urls
); );
// Add the data and formatting to the plot // Add the data and formatting to the plot
XYPlot plot = chart.getXYPlot(); XYPlot plot = chart.getXYPlot();
@ -533,20 +537,20 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
zoomIcon.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); zoomIcon.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
layer.add(zoomIcon, (Integer) 1); layer.add(zoomIcon, (Integer) 1);
panel.add(layer, "width 300:300:, height 180:180:, grow, spanx"); panel.add(layer, "width 300:300:, height 180:180:, grow, spanx");
this.add(panel, "grow"); this.add(panel, "grow");
// Sets the filter: // Sets the filter:
int showMode = Application.getPreferences().getChoice(net.sf.openrocket.startup.Preferences.MOTOR_DIAMETER_FILTER, SHOW_MAX, SHOW_EXACT); int showMode = Application.getPreferences().getChoice(net.sf.openrocket.startup.Preferences.MOTOR_DIAMETER_FILTER, SHOW_MAX, SHOW_EXACT);
filterComboBox.setSelectedIndex(showMode); filterComboBox.setSelectedIndex(showMode);
// Update the panel data // Update the panel data
updateData(); updateData();
selectedDelay = delay; selectedDelay = delay;
@ -599,7 +603,7 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
} }
private void changeLabelFont(ValueAxis axis, float size) { private void changeLabelFont(ValueAxis axis, float size) {
Font font = axis.getTickLabelFont(); Font font = axis.getTickLabelFont();
font = font.deriveFont(font.getSize2D() + size); font = font.deriveFont(font.getSize2D() + size);
@ -638,6 +642,9 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
curveSelectionBox.setEnabled(false); curveSelectionBox.setEnabled(false);
curveSelectionLabel.setEnabled(false); curveSelectionLabel.setEnabled(false);
totalImpulseLabel.setText(""); totalImpulseLabel.setText("");
totalImpulseLabel.setToolTipText(null);
classificationLabel.setText("");
classificationLabel.setToolTipText(null);
avgThrustLabel.setText(""); avgThrustLabel.setText("");
maxThrustLabel.setText(""); maxThrustLabel.setText("");
burnTimeLabel.setText(""); burnTimeLabel.setText("");
@ -652,12 +659,12 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
return; return;
} }
// Check which thrust curves to display // Check which thrust curves to display
List<ThrustCurveMotor> motors = getFilteredCurves(); List<ThrustCurveMotor> motors = getFilteredCurves();
final int index = motors.indexOf(selectedMotor); final int index = motors.indexOf(selectedMotor);
// Update the thrust curve selection box // Update the thrust curve selection box
curveSelectionModel.removeAllElements(); curveSelectionModel.removeAllElements();
for (int i = 0; i < motors.size(); i++) { for (int i = 0; i < motors.size(); i++) {
@ -673,10 +680,15 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
curveSelectionLabel.setEnabled(false); curveSelectionLabel.setEnabled(false);
} }
// Update thrust curve data // Update thrust curve data
totalImpulseLabel.setText(UnitGroup.UNITS_IMPULSE.getDefaultUnit().toStringUnit( double impulse = selectedMotor.getTotalImpulseEstimate();
selectedMotor.getTotalImpulseEstimate())); MotorClass mc = MotorClass.getMotorClass(impulse);
totalImpulseLabel.setText(UnitGroup.UNITS_IMPULSE.getDefaultUnit().toStringUnit(impulse));
classificationLabel.setText("(" + mc.getDescription(impulse) + ")");
totalImpulseLabel.setToolTipText(mc.getClassDescription());
classificationLabel.setToolTipText(mc.getClassDescription());
avgThrustLabel.setText(UnitGroup.UNITS_FORCE.getDefaultUnit().toStringUnit( avgThrustLabel.setText(UnitGroup.UNITS_FORCE.getDefaultUnit().toStringUnit(
selectedMotor.getAverageThrustEstimate())); selectedMotor.getAverageThrustEstimate()));
maxThrustLabel.setText(UnitGroup.UNITS_FORCE.getDefaultUnit().toStringUnit( maxThrustLabel.setText(UnitGroup.UNITS_FORCE.getDefaultUnit().toStringUnit(
@ -694,7 +706,7 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
setComment(selectedMotor.getDescription()); setComment(selectedMotor.getDescription());
// Update the plot // Update the plot
XYPlot plot = chart.getXYPlot(); XYPlot plot = chart.getXYPlot();
@ -721,7 +733,6 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
plot.setDataset(dataset); plot.setDataset(dataset);
} }
private List<ThrustCurveMotor> getFilteredCurves() { private List<ThrustCurveMotor> getFilteredCurves() {
List<ThrustCurveMotor> motors = selectedMotorSet.getMotors(); List<ThrustCurveMotor> motors = selectedMotorSet.getMotors();
if (hideSimilarBox.isSelected()) { if (hideSimilarBox.isSelected()) {
@ -797,7 +808,7 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
} }
/** /**
* Select the default motor from this ThrustCurveMotorSet. This uses primarily motors * Select the default motor from this ThrustCurveMotorSet. This uses primarily motors
* that the user has previously used, and secondarily a heuristic method of selecting which * that the user has previously used, and secondarily a heuristic method of selecting which
@ -814,7 +825,7 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
return set.getMotors().get(0); return set.getMotors().get(0);
} }
// Find which motor has been used the most recently // Find which motor has been used the most recently
List<ThrustCurveMotor> list = set.getMotors(); List<ThrustCurveMotor> list = set.getMotors();
Preferences prefs = ((SwingPreferences) Application.getPreferences()).getNode(net.sf.openrocket.startup.Preferences.PREFERRED_THRUST_CURVE_MOTOR_NODE); Preferences prefs = ((SwingPreferences) Application.getPreferences()).getNode(net.sf.openrocket.startup.Preferences.PREFERRED_THRUST_CURVE_MOTOR_NODE);
@ -867,7 +878,7 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
} }
if (!Double.isNaN(closest)) { if (!Double.isNaN(closest)) {
selectedDelay = closest; selectedDelay = closest;
//// None //// None
delayBox.setSelectedItem(ThrustCurveMotor.getDelayString(closest, trans.get("TCMotorSelPan.delayBox.None"))); delayBox.setSelectedItem(ThrustCurveMotor.getDelayString(closest, trans.get("TCMotorSelPan.delayBox.None")));
} else { } else {
delayBox.setSelectedItem("None"); delayBox.setSelectedItem("None");
@ -876,7 +887,7 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
} else { } else {
selectedDelay = currentDelay; selectedDelay = currentDelay;
//// None //// None
delayBox.setSelectedItem(ThrustCurveMotor.getDelayString(currentDelay, trans.get("TCMotorSelPan.delayBox.None"))); delayBox.setSelectedItem(ThrustCurveMotor.getDelayString(currentDelay, trans.get("TCMotorSelPan.delayBox.None")));
} }
@ -885,11 +896,11 @@ public class ThrustCurveMotorSelectionPanel extends JPanel implements MotorSelec
} }
////////////////////// //////////////////////
private class CurveSelectionRenderer implements ListCellRenderer { private class CurveSelectionRenderer implements ListCellRenderer {
private final ListCellRenderer renderer; private final ListCellRenderer renderer;