bug fixes
This commit is contained in:
parent
50e8b972a3
commit
ceac736133
11
ChangeLog
11
ChangeLog
@ -1,3 +1,14 @@
|
|||||||
|
2011-08-25 Sampo Niskanen
|
||||||
|
|
||||||
|
* [BUG] Ignore synthetic methods in logging traces
|
||||||
|
* [BUG] Ignore JRE bug #6826104
|
||||||
|
|
||||||
|
2011-08-24 Sampo Niskanen
|
||||||
|
|
||||||
|
* [BUG] NPE in SimulationOptions.equals
|
||||||
|
* [BUG] Exception in plotting optimization path
|
||||||
|
* [BUG] Exception in saving optimization path
|
||||||
|
|
||||||
2011-08-17 Justin Seitz
|
2011-08-17 Justin Seitz
|
||||||
|
|
||||||
* Added Blue tube to materials database.
|
* Added Blue tube to materials database.
|
||||||
|
|||||||
@ -606,8 +606,11 @@ public class GeneralOptimizationDialog extends JDialog {
|
|||||||
@Override
|
@Override
|
||||||
public void actionPerformed(ActionEvent e) {
|
public void actionPerformed(ActionEvent e) {
|
||||||
log.user("Plotting optimization path, dimensionality=" + selectedModifiers.size());
|
log.user("Plotting optimization path, dimensionality=" + selectedModifiers.size());
|
||||||
OptimizationPlotDialog dialog = new OptimizationPlotDialog(optimizationPath, evaluationHistory,
|
OptimizationPlotDialog dialog = new OptimizationPlotDialog(
|
||||||
selectedModifiers, getSelectedParameter(),
|
Collections.unmodifiableList(optimizationPath),
|
||||||
|
Collections.unmodifiableMap(evaluationHistory),
|
||||||
|
Collections.unmodifiableList(selectedModifiers),
|
||||||
|
getSelectedParameter(),
|
||||||
UnitGroup.stabilityUnits(getSelectedSimulation().getRocket()),
|
UnitGroup.stabilityUnits(getSelectedSimulation().getRocket()),
|
||||||
GeneralOptimizationDialog.this);
|
GeneralOptimizationDialog.this);
|
||||||
dialog.setVisible(true);
|
dialog.setVisible(true);
|
||||||
@ -803,6 +806,7 @@ public class GeneralOptimizationDialog extends JDialog {
|
|||||||
});
|
});
|
||||||
timer.setRepeats(false);
|
timer.setRepeats(false);
|
||||||
timer.start();
|
timer.start();
|
||||||
|
updateComponents();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -1125,16 +1129,21 @@ public class GeneralOptimizationDialog extends JDialog {
|
|||||||
* Update the enabled status of all components in the dialog.
|
* Update the enabled status of all components in the dialog.
|
||||||
*/
|
*/
|
||||||
private void updateComponents() {
|
private void updateComponents() {
|
||||||
|
boolean state;
|
||||||
|
|
||||||
if (updating) {
|
if (updating) {
|
||||||
|
log.debug("Ignoring updateComponents");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.debug("Running updateComponents()");
|
||||||
|
|
||||||
updating = true;
|
updating = true;
|
||||||
|
|
||||||
|
|
||||||
// First enable all components if optimization not running
|
// First enable all components if optimization not running
|
||||||
if (!running) {
|
if (!running) {
|
||||||
|
log.debug("Initially enabling all components");
|
||||||
for (JComponent c : disableComponents) {
|
for (JComponent c : disableComponents) {
|
||||||
c.setEnabled(true);
|
c.setEnabled(true);
|
||||||
}
|
}
|
||||||
@ -1143,46 +1152,56 @@ public class GeneralOptimizationDialog extends JDialog {
|
|||||||
|
|
||||||
// "Add" button
|
// "Add" button
|
||||||
SimulationModifier mod = getSelectedAvailableModifier();
|
SimulationModifier mod = getSelectedAvailableModifier();
|
||||||
if (mod != null && !selectedModifiers.contains(mod)) {
|
state = (mod != null && !selectedModifiers.contains(mod));
|
||||||
addButton.setEnabled(true);
|
log.debug("addButton enabled: " + state);
|
||||||
} else {
|
addButton.setEnabled(state);
|
||||||
addButton.setEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// "Remove" button
|
// "Remove" button
|
||||||
removeButton.setEnabled(selectedModifierTable.getSelectedRow() >= 0);
|
state = (selectedModifierTable.getSelectedRow() >= 0);
|
||||||
|
log.debug("removeButton enabled: " + state);
|
||||||
|
removeButton.setEnabled(state);
|
||||||
|
|
||||||
// "Remove all" button
|
// "Remove all" button
|
||||||
removeAllButton.setEnabled(!selectedModifiers.isEmpty());
|
state = (!selectedModifiers.isEmpty());
|
||||||
|
log.debug("removeAllButton enabled: " + state);
|
||||||
|
removeAllButton.setEnabled(state);
|
||||||
|
|
||||||
|
|
||||||
// Optimization goal
|
// Optimization goal
|
||||||
String selected = (String) optimizationGoalCombo.getSelectedItem();
|
String selected = (String) optimizationGoalCombo.getSelectedItem();
|
||||||
if (GOAL_SEEK.equals(selected)) {
|
state = GOAL_SEEK.equals(selected);
|
||||||
optimizationGoalSpinner.setVisible(true);
|
log.debug("optimizationGoalSpinner & UnitSelector enabled: " + state);
|
||||||
optimizationGoalUnitSelector.setVisible(true);
|
optimizationGoalSpinner.setVisible(state);
|
||||||
} else {
|
optimizationGoalUnitSelector.setVisible(state);
|
||||||
optimizationGoalSpinner.setVisible(false);
|
|
||||||
optimizationGoalUnitSelector.setVisible(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Minimum/maximum stability options
|
// Minimum/maximum stability options
|
||||||
minimumStabilitySpinner.setEnabled(minimumStabilitySelected.isSelected());
|
state = minimumStabilitySelected.isSelected();
|
||||||
minimumStabilityUnitSelector.setEnabled(minimumStabilitySelected.isSelected());
|
log.debug("minimumStabilitySpinner & UnitSelector enabled: " + state);
|
||||||
maximumStabilitySpinner.setEnabled(maximumStabilitySelected.isSelected());
|
minimumStabilitySpinner.setEnabled(state);
|
||||||
maximumStabilityUnitSelector.setEnabled(maximumStabilitySelected.isSelected());
|
minimumStabilityUnitSelector.setEnabled(state);
|
||||||
|
|
||||||
|
state = maximumStabilitySelected.isSelected();
|
||||||
|
log.debug("maximumStabilitySpimmer & UnitSelector enabled: " + state);
|
||||||
|
maximumStabilitySpinner.setEnabled(state);
|
||||||
|
maximumStabilityUnitSelector.setEnabled(state);
|
||||||
|
|
||||||
|
|
||||||
// Plot button (enabled if path exists and dimensionality is 1 or 2)
|
// Plot button (enabled if path exists and dimensionality is 1 or 2)
|
||||||
plotButton.setEnabled(!optimizationPath.isEmpty() && (selectedModifiers.size() == 1 || selectedModifiers.size() == 2));
|
state = (!optimizationPath.isEmpty() && (selectedModifiers.size() == 1 || selectedModifiers.size() == 2));
|
||||||
|
log.debug("plotButton enabled: " + state + " optimizationPath.isEmpty=" + optimizationPath.isEmpty() +
|
||||||
|
" selectedModifiers.size=" + selectedModifiers.size());
|
||||||
|
plotButton.setEnabled(state);
|
||||||
|
|
||||||
// Save button (enabled if path exists)
|
// Save button (enabled if path exists)
|
||||||
saveButton.setEnabled(!optimizationPath.isEmpty());
|
state = (!evaluationHistory.isEmpty());
|
||||||
|
log.debug("saveButton enabled: " + state);
|
||||||
|
saveButton.setEnabled(state);
|
||||||
|
|
||||||
|
|
||||||
// Last disable all components if optimization is running
|
// Last disable all components if optimization is running
|
||||||
if (running) {
|
if (running) {
|
||||||
|
log.debug("Disabling all components because optimization is running");
|
||||||
for (JComponent c : disableComponents) {
|
for (JComponent c : disableComponents) {
|
||||||
c.setEnabled(false);
|
c.setEnabled(false);
|
||||||
}
|
}
|
||||||
@ -1445,6 +1464,12 @@ public class GeneralOptimizationDialog extends JDialog {
|
|||||||
@Override
|
@Override
|
||||||
public void setValueAt(Object value, int row, int column) {
|
public void setValueAt(Object value, int row, int column) {
|
||||||
|
|
||||||
|
if (row >= selectedModifiers.size()) {
|
||||||
|
throw new BugException("setValueAt with invalid row: value=" + value + " row=" + row + " column=" + column +
|
||||||
|
" selectedModifiers.size=" + selectedModifiers.size() + " selectedModifiers=" + selectedModifiers +
|
||||||
|
" selectedModifierTable.getRowCount=" + selectedModifierTable.getRowCount());
|
||||||
|
}
|
||||||
|
|
||||||
switch (column) {
|
switch (column) {
|
||||||
case PARAMETER:
|
case PARAMETER:
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -162,7 +162,12 @@ public class OptimizationPlotDialog extends JDialog {
|
|||||||
double x1 = xUnit.toUnit(modX.getMinValue());
|
double x1 = xUnit.toUnit(modX.getMinValue());
|
||||||
double x2 = xUnit.toUnit(modX.getMaxValue());
|
double x2 = xUnit.toUnit(modX.getMaxValue());
|
||||||
|
|
||||||
chart.getXYPlot().getDomainAxis().setRange(x1, x2);
|
if (x1 < x2 - 0.0001) {
|
||||||
|
log.debug("Setting 1D plot domain axis x1=" + x1 + " x2=" + x2);
|
||||||
|
chart.getXYPlot().getDomainAxis().setRange(x1, x2);
|
||||||
|
} else {
|
||||||
|
log.warn("1D plot domain singular x1=" + x1 + " x2=" + x2 + ", not setting");
|
||||||
|
}
|
||||||
|
|
||||||
// Add lines to show optimization limits
|
// Add lines to show optimization limits
|
||||||
XYLineAnnotation line = new XYLineAnnotation(x1, -1e19, x1, 1e19);
|
XYLineAnnotation line = new XYLineAnnotation(x1, -1e19, x1, 1e19);
|
||||||
@ -296,8 +301,19 @@ public class OptimizationPlotDialog extends JDialog {
|
|||||||
double y1 = yUnit.toUnit(modY.getMinValue());
|
double y1 = yUnit.toUnit(modY.getMinValue());
|
||||||
double y2 = yUnit.toUnit(modY.getMaxValue());
|
double y2 = yUnit.toUnit(modY.getMaxValue());
|
||||||
|
|
||||||
chart.getXYPlot().getDomainAxis().setRange(x1, x2);
|
if (x1 < x2 - 0.0001) {
|
||||||
chart.getXYPlot().getRangeAxis().setRange(y1, y2);
|
log.debug("Setting 2D plot domain axis to x1=" + x1 + " x2=" + x2);
|
||||||
|
chart.getXYPlot().getDomainAxis().setRange(x1, x2);
|
||||||
|
} else {
|
||||||
|
log.warn("2D plot has singular domain axis: x1=" + x1 + " x2=" + x2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (y1 < y2 - 0.0001) {
|
||||||
|
log.debug("Setting 2D plot range axis to y1=" + y1 + " y2=" + y2);
|
||||||
|
chart.getXYPlot().getRangeAxis().setRange(y1, y2);
|
||||||
|
} else {
|
||||||
|
log.warn("2D plot has singular range axis: y1=" + y1 + " y2=" + y2);
|
||||||
|
}
|
||||||
|
|
||||||
XYBoxAnnotation box = new XYBoxAnnotation(x1, y1, x2, y2);
|
XYBoxAnnotation box = new XYBoxAnnotation(x1, y1, x2, y2);
|
||||||
chart.getXYPlot().addAnnotation(box);
|
chart.getXYPlot().addAnnotation(box);
|
||||||
@ -308,6 +324,15 @@ public class OptimizationPlotDialog extends JDialog {
|
|||||||
text.setTextAnchor(TextAnchor.BASELINE_LEFT);
|
text.setTextAnchor(TextAnchor.BASELINE_LEFT);
|
||||||
chart.getXYPlot().addAnnotation(text);
|
chart.getXYPlot().addAnnotation(text);
|
||||||
|
|
||||||
|
|
||||||
|
if (min < max - 0.0001) {
|
||||||
|
log.debug("Setting gradient scale range to min=" + min + " max=" + max);
|
||||||
|
} else {
|
||||||
|
log.warn("2D plot has singular gradient scale, resetting to (0,1): min=" + min + " max=" + max);
|
||||||
|
min = 0;
|
||||||
|
max = 1;
|
||||||
|
}
|
||||||
|
|
||||||
PaintScale paintScale = new GradientScale(min, max);
|
PaintScale paintScale = new GradientScale(min, max);
|
||||||
|
|
||||||
XYShapeRenderer shapeRenderer = new XYShapeRenderer();
|
XYShapeRenderer shapeRenderer = new XYShapeRenderer();
|
||||||
|
|||||||
@ -301,6 +301,29 @@ public class ExceptionHandler implements Thread.UncaughtExceptionHandler {
|
|||||||
|
|
||||||
// NOTE: Calling method logs the entire throwable, so log only message here
|
// NOTE: Calling method logs the entire throwable, so log only message here
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Detect and ignore bug 6826104 in Sun JRE.
|
||||||
|
*/
|
||||||
|
if (t instanceof NullPointerException) {
|
||||||
|
StackTraceElement[] trace = t.getStackTrace();
|
||||||
|
|
||||||
|
if (trace.length > 3 &&
|
||||||
|
trace[0].getClassName().equals("sun.awt.X11.XWindowPeer") &&
|
||||||
|
trace[0].getMethodName().equals("restoreTransientFor") &&
|
||||||
|
|
||||||
|
trace[1].getClassName().equals("sun.awt.X11.XWindowPeer") &&
|
||||||
|
trace[1].getMethodName().equals("removeFromTransientFors") &&
|
||||||
|
|
||||||
|
trace[2].getClassName().equals("sun.awt.X11.XWindowPeer") &&
|
||||||
|
trace[2].getMethodName().equals("setModalBlocked")) {
|
||||||
|
log.warn("Ignoring Sun JRE bug (6826104): http://bugs.sun.com/view_bug.do?bug_id=6826104" + t);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Detect and ignore bug 6828938 in Sun JRE 1.6.0_14 - 1.6.0_16.
|
* Detect and ignore bug 6828938 in Sun JRE 1.6.0_14 - 1.6.0_16.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -1,6 +1,35 @@
|
|||||||
package net.sf.openrocket.gui.scalefigure;
|
package net.sf.openrocket.gui.scalefigure;
|
||||||
|
|
||||||
|
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.Font;
|
||||||
|
import java.awt.Point;
|
||||||
|
import java.awt.event.ActionEvent;
|
||||||
|
import java.awt.event.InputEvent;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.concurrent.Executors;
|
||||||
|
import java.util.concurrent.ThreadFactory;
|
||||||
|
|
||||||
|
import javax.swing.AbstractAction;
|
||||||
|
import javax.swing.Action;
|
||||||
|
import javax.swing.JComboBox;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JSlider;
|
||||||
|
import javax.swing.JToggleButton;
|
||||||
|
import javax.swing.JViewport;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.event.ChangeEvent;
|
||||||
|
import javax.swing.event.ChangeListener;
|
||||||
|
import javax.swing.event.TreeSelectionEvent;
|
||||||
|
import javax.swing.event.TreeSelectionListener;
|
||||||
|
import javax.swing.tree.TreePath;
|
||||||
|
import javax.swing.tree.TreeSelectionModel;
|
||||||
|
|
||||||
import net.miginfocom.swing.MigLayout;
|
import net.miginfocom.swing.MigLayout;
|
||||||
import net.sf.openrocket.aerodynamics.AerodynamicCalculator;
|
import net.sf.openrocket.aerodynamics.AerodynamicCalculator;
|
||||||
import net.sf.openrocket.aerodynamics.BarrowmanCalculator;
|
import net.sf.openrocket.aerodynamics.BarrowmanCalculator;
|
||||||
@ -40,34 +69,6 @@ import net.sf.openrocket.util.Coordinate;
|
|||||||
import net.sf.openrocket.util.MathUtil;
|
import net.sf.openrocket.util.MathUtil;
|
||||||
import net.sf.openrocket.util.Prefs;
|
import net.sf.openrocket.util.Prefs;
|
||||||
|
|
||||||
import javax.swing.AbstractAction;
|
|
||||||
import javax.swing.Action;
|
|
||||||
import javax.swing.JComboBox;
|
|
||||||
import javax.swing.JLabel;
|
|
||||||
import javax.swing.JPanel;
|
|
||||||
import javax.swing.JSlider;
|
|
||||||
import javax.swing.JToggleButton;
|
|
||||||
import javax.swing.JViewport;
|
|
||||||
import javax.swing.SwingUtilities;
|
|
||||||
import javax.swing.event.ChangeEvent;
|
|
||||||
import javax.swing.event.ChangeListener;
|
|
||||||
import javax.swing.event.TreeSelectionEvent;
|
|
||||||
import javax.swing.event.TreeSelectionListener;
|
|
||||||
import javax.swing.tree.TreePath;
|
|
||||||
import javax.swing.tree.TreeSelectionModel;
|
|
||||||
import java.awt.Dimension;
|
|
||||||
import java.awt.Font;
|
|
||||||
import java.awt.Point;
|
|
||||||
import java.awt.event.ActionEvent;
|
|
||||||
import java.awt.event.InputEvent;
|
|
||||||
import java.awt.event.MouseEvent;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.ThreadFactory;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A JPanel that contains a RocketFigure and buttons to manipulate the figure.
|
* A JPanel that contains a RocketFigure and buttons to manipulate the figure.
|
||||||
*
|
*
|
||||||
@ -241,12 +242,13 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
|
|||||||
add(new BasicSlider(theta.getSliderModel(0, 2 * Math.PI), JSlider.VERTICAL, true),
|
add(new BasicSlider(theta.getSliderModel(0, 2 * Math.PI), JSlider.VERTICAL, true),
|
||||||
"ax 50%, wrap, width " + (d.width + 6) + "px:null:null, growy");
|
"ax 50%, wrap, width " + (d.width + 6) + "px:null:null, growy");
|
||||||
|
|
||||||
|
|
||||||
//// <html>Click to select Shift+click to select other Double-click to edit Click+drag to move
|
//// <html>Click to select Shift+click to select other Double-click to edit Click+drag to move
|
||||||
infoMessage = new JLabel(trans.get("RocketPanel.lbl.infoMessage"));
|
infoMessage = new JLabel(trans.get("RocketPanel.lbl.infoMessage"));
|
||||||
infoMessage.setFont(new Font("Sans Serif", Font.PLAIN, 9));
|
infoMessage.setFont(new Font("Sans Serif", Font.PLAIN, 9));
|
||||||
add(infoMessage, "skip, span, gapleft 25, wrap");
|
add(infoMessage, "skip, span, gapleft 25, wrap");
|
||||||
|
|
||||||
|
|
||||||
addExtras();
|
addExtras();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -263,35 +265,35 @@ public class RocketPanel extends JPanel implements TreeSelectionListener, Change
|
|||||||
public Configuration getConfiguration() {
|
public Configuration getConfiguration() {
|
||||||
return configuration;
|
return configuration;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the center of pressure figure element.
|
* Get the center of pressure figure element.
|
||||||
*
|
*
|
||||||
* @return center of pressure info
|
* @return center of pressure info
|
||||||
*/
|
*/
|
||||||
public Caret getExtraCP () {
|
public Caret getExtraCP() {
|
||||||
return extraCP;
|
return extraCP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the center of gravity figure element.
|
* Get the center of gravity figure element.
|
||||||
*
|
*
|
||||||
* @return center of gravity info
|
* @return center of gravity info
|
||||||
*/
|
*/
|
||||||
public Caret getExtraCG () {
|
public Caret getExtraCG() {
|
||||||
return extraCG;
|
return extraCG;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the extra text figure element.
|
* Get the extra text figure element.
|
||||||
*
|
*
|
||||||
* @return extra text that contains info about the rocket design
|
* @return extra text that contains info about the rocket design
|
||||||
*/
|
*/
|
||||||
public RocketInfo getExtraText () {
|
public RocketInfo getExtraText() {
|
||||||
return extraText;
|
return extraText;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setSelectionModel(TreeSelectionModel m) {
|
public void setSelectionModel(TreeSelectionModel m) {
|
||||||
if (selectionModel != null) {
|
if (selectionModel != null) {
|
||||||
selectionModel.removeTreeSelectionListener(this);
|
selectionModel.removeTreeSelectionListener(this);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -95,31 +95,33 @@ public class TraceException extends Exception {
|
|||||||
StackTraceElement[] elements = this.getStackTrace();
|
StackTraceElement[] elements = this.getStackTrace();
|
||||||
|
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
if (minLevel < elements.length) {
|
sb.append('(');
|
||||||
|
|
||||||
sb.append("(");
|
if (elements == null || elements.length == 0) {
|
||||||
sb.append(toString(elements[minLevel]));
|
sb.append("no stack trace");
|
||||||
for (int i = minLevel + 1; i <= maxLevel; i++) {
|
|
||||||
if (i < elements.length) {
|
|
||||||
sb.append(' ').append(toString(elements[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sb.append(')');
|
|
||||||
|
|
||||||
} else if (elements.length == 0) {
|
|
||||||
|
|
||||||
sb.append("(no stack trace)");
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
sb.append('(');
|
int levelCount = 0;
|
||||||
sb.append(toString(elements[0]));
|
int position = minLevel;
|
||||||
for (int i = 1; i < elements.length; i++) {
|
while (levelCount <= (maxLevel - minLevel) && position < elements.length) {
|
||||||
sb.append(' ').append(toString(elements[i]));
|
|
||||||
|
// Ignore synthetic "access$0" methods generated by the JRE
|
||||||
|
if (elements[position].getMethodName().contains("$")) {
|
||||||
|
position++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (levelCount > 0) {
|
||||||
|
sb.append(' ');
|
||||||
|
}
|
||||||
|
sb.append(toString(elements[position]));
|
||||||
|
levelCount++;
|
||||||
|
position++;
|
||||||
}
|
}
|
||||||
sb.append(" level=").append(minLevel).append(')');
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
sb.append(')');
|
||||||
|
|
||||||
message = sb.toString();
|
message = sb.toString();
|
||||||
}
|
}
|
||||||
return message;
|
return message;
|
||||||
|
|||||||
@ -15,7 +15,7 @@ import net.sf.openrocket.util.MathUtil;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class Material implements Comparable<Material> {
|
public abstract class Material implements Comparable<Material> {
|
||||||
|
|
||||||
public enum Type {
|
public enum Type {
|
||||||
LINE("Line", UnitGroup.UNITS_DENSITY_LINE),
|
LINE("Line", UnitGroup.UNITS_DENSITY_LINE),
|
||||||
SURFACE("Surface", UnitGroup.UNITS_DENSITY_SURFACE),
|
SURFACE("Surface", UnitGroup.UNITS_DENSITY_SURFACE),
|
||||||
@ -23,13 +23,16 @@ public abstract class Material implements Comparable<Material> {
|
|||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final UnitGroup units;
|
private final UnitGroup units;
|
||||||
|
|
||||||
private Type(String name, UnitGroup units) {
|
private Type(String name, UnitGroup units) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.units = units;
|
this.units = units;
|
||||||
}
|
}
|
||||||
|
|
||||||
public UnitGroup getUnitGroup() {
|
public UnitGroup getUnitGroup() {
|
||||||
return units;
|
return units;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return name;
|
return name;
|
||||||
@ -43,7 +46,7 @@ public abstract class Material implements Comparable<Material> {
|
|||||||
public Line(String name, double density, boolean userDefined) {
|
public Line(String name, double density, boolean userDefined) {
|
||||||
super(name, density, userDefined);
|
super(name, density, userDefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return Type.LINE;
|
return Type.LINE;
|
||||||
@ -71,7 +74,7 @@ public abstract class Material implements Comparable<Material> {
|
|||||||
public Bulk(String name, double density, boolean userDefined) {
|
public Bulk(String name, double density, boolean userDefined) {
|
||||||
super(name, density, userDefined);
|
super(name, density, userDefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type getType() {
|
public Type getType() {
|
||||||
return Type.BULK;
|
return Type.BULK;
|
||||||
@ -79,7 +82,7 @@ public abstract class Material implements Comparable<Material> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private final String name;
|
private final String name;
|
||||||
private final double density;
|
private final double density;
|
||||||
private final boolean userDefined;
|
private final boolean userDefined;
|
||||||
@ -92,7 +95,7 @@ public abstract class Material implements Comparable<Material> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public double getDensity() {
|
public double getDensity() {
|
||||||
return density;
|
return density;
|
||||||
}
|
}
|
||||||
@ -116,7 +119,7 @@ public abstract class Material implements Comparable<Material> {
|
|||||||
return this.getName(this.getType().getUnitGroup().getDefaultUnit());
|
return this.getName(this.getType().getUnitGroup().getDefaultUnit());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compares this object to another object. Material objects are equal if and only if
|
* Compares this object to another object. Material objects are equal if and only if
|
||||||
* their types, names and densities are identical.
|
* their types, names and densities are identical.
|
||||||
@ -127,30 +130,30 @@ public abstract class Material implements Comparable<Material> {
|
|||||||
return false;
|
return false;
|
||||||
if (this.getClass() != o.getClass())
|
if (this.getClass() != o.getClass())
|
||||||
return false;
|
return false;
|
||||||
Material m = (Material)o;
|
Material m = (Material) o;
|
||||||
return ((m.name.equals(this.name)) &&
|
return ((m.name.equals(this.name)) && MathUtil.equals(m.density, this.density));
|
||||||
MathUtil.equals(m.density, this.density));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A hashCode() method giving a hash code compatible with the equals() method.
|
* A hashCode() method giving a hash code compatible with the equals() method.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return name.hashCode() + (int)(density*1000);
|
return name.hashCode() + (int) (density * 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Order the materials according to their name, secondarily according to density.
|
* Order the materials according to their name, secondarily according to density.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public int compareTo(Material o) {
|
public int compareTo(Material o) {
|
||||||
int c = this.name.compareTo(o.name);
|
int c = this.name.compareTo(o.name);
|
||||||
if (c != 0) {
|
if (c != 0) {
|
||||||
return c;
|
return c;
|
||||||
} else {
|
} else {
|
||||||
return (int)((this.density - o.density)*1000);
|
return (int) ((this.density - o.density) * 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -158,7 +161,7 @@ public abstract class Material implements Comparable<Material> {
|
|||||||
/**
|
/**
|
||||||
* Return a new material of the specified type.
|
* Return a new material of the specified type.
|
||||||
*/
|
*/
|
||||||
public static Material newMaterial(Type type, String name, double density,
|
public static Material newMaterial(Type type, String name, double density,
|
||||||
boolean userDefined) {
|
boolean userDefined) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case LINE:
|
case LINE:
|
||||||
@ -171,7 +174,7 @@ public abstract class Material implements Comparable<Material> {
|
|||||||
return new Material.Bulk(name, density, userDefined);
|
return new Material.Bulk(name, density, userDefined);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Unknown material type: "+type);
|
throw new IllegalArgumentException("Unknown material type: " + type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -193,10 +196,10 @@ public abstract class Material implements Comparable<Material> {
|
|||||||
if (str == null)
|
if (str == null)
|
||||||
throw new IllegalArgumentException("Material string is null");
|
throw new IllegalArgumentException("Material string is null");
|
||||||
|
|
||||||
String[] split = str.split("\\|",3);
|
String[] split = str.split("\\|", 3);
|
||||||
if (split.length < 3)
|
if (split.length < 3)
|
||||||
throw new IllegalArgumentException("Illegal material string: "+str);
|
throw new IllegalArgumentException("Illegal material string: " + str);
|
||||||
|
|
||||||
Type type = null;
|
Type type = null;
|
||||||
String name;
|
String name;
|
||||||
double density;
|
double density;
|
||||||
@ -204,15 +207,15 @@ public abstract class Material implements Comparable<Material> {
|
|||||||
try {
|
try {
|
||||||
type = Type.valueOf(split[0]);
|
type = Type.valueOf(split[0]);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new IllegalArgumentException("Illegal material string: "+str, e);
|
throw new IllegalArgumentException("Illegal material string: " + str, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
name = split[1];
|
name = split[1];
|
||||||
|
|
||||||
try {
|
try {
|
||||||
density = Double.parseDouble(split[2]);
|
density = Double.parseDouble(split[2]);
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new IllegalArgumentException("Illegal material string: "+str, e);
|
throw new IllegalArgumentException("Illegal material string: " + str, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -226,8 +229,8 @@ public abstract class Material implements Comparable<Material> {
|
|||||||
return new Material.Line(name, density, userDefined);
|
return new Material.Line(name, density, userDefined);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new IllegalArgumentException("Illegal material string: "+str);
|
throw new IllegalArgumentException("Illegal material string: " + str);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,26 +7,31 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
|
|||||||
* A model for a preset component.
|
* A model for a preset component.
|
||||||
* <p>
|
* <p>
|
||||||
* A preset component contains a component class type, manufacturer information,
|
* A preset component contains a component class type, manufacturer information,
|
||||||
* part information, and getter methods for various properties of the component.
|
* part information, and a method that returns a prototype of the preset component.
|
||||||
*
|
*
|
||||||
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
|
||||||
*/
|
*/
|
||||||
public abstract class RocketComponentPreset {
|
public abstract class ComponentPreset {
|
||||||
|
|
||||||
private final Class<? extends RocketComponent> componentClass;
|
|
||||||
private final Manufacturer manufacturer;
|
private final Manufacturer manufacturer;
|
||||||
private final String partName;
|
|
||||||
private final String partNo;
|
private final String partNo;
|
||||||
private final String partDescription;
|
private final String partDescription;
|
||||||
|
private final RocketComponent prototype;
|
||||||
|
|
||||||
|
|
||||||
public RocketComponentPreset(Class<? extends RocketComponent> componentClass, Manufacturer manufacturer,
|
public ComponentPreset(Manufacturer manufacturer, String partNo, String partDescription,
|
||||||
String partName, String partNo, String partDescription) {
|
RocketComponent prototype) {
|
||||||
this.componentClass = componentClass;
|
|
||||||
this.manufacturer = manufacturer;
|
this.manufacturer = manufacturer;
|
||||||
this.partName = partName;
|
|
||||||
this.partNo = partNo;
|
this.partNo = partNo;
|
||||||
this.partDescription = partDescription;
|
this.partDescription = partDescription;
|
||||||
|
this.prototype = prototype.copy();
|
||||||
|
|
||||||
|
if (prototype.getParent() != null) {
|
||||||
|
throw new IllegalArgumentException("Prototype component cannot have a parent");
|
||||||
|
}
|
||||||
|
if (prototype.getChildCount() > 0) {
|
||||||
|
throw new IllegalArgumentException("Prototype component cannot have children");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -34,7 +39,7 @@ public abstract class RocketComponentPreset {
|
|||||||
* Return the component class that this preset defines.
|
* Return the component class that this preset defines.
|
||||||
*/
|
*/
|
||||||
public Class<? extends RocketComponent> getComponentClass() {
|
public Class<? extends RocketComponent> getComponentClass() {
|
||||||
return componentClass;
|
return prototype.getClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -44,13 +49,6 @@ public abstract class RocketComponentPreset {
|
|||||||
return manufacturer;
|
return manufacturer;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the part name. This is a short, human-readable name of the part.
|
|
||||||
*/
|
|
||||||
public String getPartName() {
|
|
||||||
return partName;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the part number. This is the part identifier (e.g. "BT-50").
|
* Return the part number. This is the part identifier (e.g. "BT-50").
|
||||||
*/
|
*/
|
||||||
@ -65,4 +63,11 @@ public abstract class RocketComponentPreset {
|
|||||||
return partDescription;
|
return partDescription;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a prototype component. This component may be modified freely.
|
||||||
|
*/
|
||||||
|
public RocketComponent getPrototype() {
|
||||||
|
return prototype.copy();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -1,29 +0,0 @@
|
|||||||
package net.sf.openrocket.preset;
|
|
||||||
|
|
||||||
import net.sf.openrocket.motor.Manufacturer;
|
|
||||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
|
||||||
|
|
||||||
public class ExternalComponentPreset extends RocketComponentPreset {
|
|
||||||
|
|
||||||
private final double mass;
|
|
||||||
private final String materialName;
|
|
||||||
|
|
||||||
public ExternalComponentPreset(Class<? extends RocketComponent> componentClass, Manufacturer manufacturer, String partName,
|
|
||||||
String partNo, String partDescription, double mass, String materialName) {
|
|
||||||
super(componentClass, manufacturer, partName, partNo, partDescription);
|
|
||||||
|
|
||||||
this.materialName = materialName;
|
|
||||||
this.mass = mass;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public String getMaterialName() {
|
|
||||||
return materialName;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public double getMass() {
|
|
||||||
return mass;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package net.sf.openrocket.rocketcomponent;
|
package net.sf.openrocket.rocketcomponent;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to represent a body object. The object can be described as a function of
|
* Class to represent a body object. The object can be described as a function of
|
||||||
* the cylindrical coordinates x and angle theta as r = f(x,theta). The component
|
* the cylindrical coordinates x and angle theta as r = f(x,theta). The component
|
||||||
@ -13,7 +14,7 @@ package net.sf.openrocket.rocketcomponent;
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class BodyComponent extends ExternalComponent {
|
public abstract class BodyComponent extends ExternalComponent {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default constructor. Sets the relative position to POSITION_RELATIVE_AFTER,
|
* Default constructor. Sets the relative position to POSITION_RELATIVE_AFTER,
|
||||||
* i.e. body components come after one another.
|
* i.e. body components come after one another.
|
||||||
@ -21,8 +22,8 @@ public abstract class BodyComponent extends ExternalComponent {
|
|||||||
public BodyComponent() {
|
public BodyComponent() {
|
||||||
super(RocketComponent.Position.AFTER);
|
super(RocketComponent.Position.AFTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the outer radius of the component at cylindrical coordinate (x,theta).
|
* Get the outer radius of the component at cylindrical coordinate (x,theta).
|
||||||
*
|
*
|
||||||
@ -33,8 +34,8 @@ public abstract class BodyComponent extends ExternalComponent {
|
|||||||
* @return Distance to the outer edge of the object
|
* @return Distance to the outer edge of the object
|
||||||
*/
|
*/
|
||||||
public abstract double getRadius(double x, double theta);
|
public abstract double getRadius(double x, double theta);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the inner radius of the component at cylindrical coordinate (x,theta).
|
* Get the inner radius of the component at cylindrical coordinate (x,theta).
|
||||||
*
|
*
|
||||||
@ -45,11 +46,23 @@ public abstract class BodyComponent extends ExternalComponent {
|
|||||||
* @return Distance to the inner edge of the object
|
* @return Distance to the inner edge of the object
|
||||||
*/
|
*/
|
||||||
public abstract double getInnerRadius(double x, double theta);
|
public abstract double getInnerRadius(double x, double theta);
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void loadFromPreset(RocketComponent preset) {
|
||||||
|
BodyComponent c = (BodyComponent) preset;
|
||||||
|
this.setLength(c.getLength());
|
||||||
|
|
||||||
|
super.loadFromPreset(preset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the length of the body component.
|
* Sets the length of the body component.
|
||||||
|
* <p>
|
||||||
|
* Note: This should be overridden by the subcomponents which need to call
|
||||||
|
* clearPreset(). (BodyTube allows changing length without resetting the preset.)
|
||||||
*/
|
*/
|
||||||
public void setLength(double length) {
|
public void setLength(double length) {
|
||||||
if (this.length == length)
|
if (this.length == length)
|
||||||
@ -57,10 +70,10 @@ public abstract class BodyComponent extends ExternalComponent {
|
|||||||
this.length = Math.max(length, 0);
|
this.length = Math.max(length, 0);
|
||||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean allowsChildren() {
|
public boolean allowsChildren() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -108,6 +108,7 @@ public class BodyTube extends SymmetricComponent implements MotorMount, Coaxial
|
|||||||
if (this.thickness > this.outerRadius)
|
if (this.thickness > this.outerRadius)
|
||||||
this.thickness = this.outerRadius;
|
this.thickness = this.outerRadius;
|
||||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||||
|
clearPreset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -128,6 +129,16 @@ public class BodyTube extends SymmetricComponent implements MotorMount, Coaxial
|
|||||||
|
|
||||||
autoRadius = auto;
|
autoRadius = auto;
|
||||||
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
fireComponentChangeEvent(ComponentChangeEvent.BOTH_CHANGE);
|
||||||
|
clearPreset();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void loadFromPreset(RocketComponent preset) {
|
||||||
|
BodyTube c = (BodyTube) preset;
|
||||||
|
this.setOuterRadius(c.getOuterRadius());
|
||||||
|
|
||||||
|
super.loadFromPreset(preset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,6 @@ import java.util.List;
|
|||||||
import net.sf.openrocket.l10n.Translator;
|
import net.sf.openrocket.l10n.Translator;
|
||||||
import net.sf.openrocket.material.Material;
|
import net.sf.openrocket.material.Material;
|
||||||
import net.sf.openrocket.material.Material.Type;
|
import net.sf.openrocket.material.Material.Type;
|
||||||
import net.sf.openrocket.preset.ExternalComponentPreset;
|
|
||||||
import net.sf.openrocket.preset.RocketComponentPreset;
|
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.unit.UnitGroup;
|
import net.sf.openrocket.unit.UnitGroup;
|
||||||
import net.sf.openrocket.util.Prefs;
|
import net.sf.openrocket.util.Prefs;
|
||||||
@ -116,6 +114,7 @@ public abstract class ExternalComponent extends RocketComponent {
|
|||||||
material = mat;
|
material = mat;
|
||||||
clearPreset();
|
clearPreset();
|
||||||
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
||||||
|
clearPreset();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Finish getFinish() {
|
public Finish getFinish() {
|
||||||
@ -131,22 +130,26 @@ public abstract class ExternalComponent extends RocketComponent {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void loadFromPreset(RocketComponentPreset preset) {
|
protected void loadFromPreset(RocketComponent preset) {
|
||||||
super.loadFromPreset(preset);
|
super.loadFromPreset(preset);
|
||||||
|
|
||||||
ExternalComponentPreset p = (ExternalComponentPreset) preset;
|
// Surface finish is left unchanged
|
||||||
String materialName = p.getMaterialName();
|
|
||||||
double mass = p.getMass();
|
|
||||||
|
|
||||||
double volume = getComponentVolume();
|
ExternalComponent c = (ExternalComponent) preset;
|
||||||
double density;
|
|
||||||
if (volume > 0.00001) {
|
Material mat = c.getMaterial();
|
||||||
density = mass / volume;
|
if (c.isMassOverridden()) {
|
||||||
} else {
|
double mass = c.getOverrideMass();
|
||||||
density = 1000;
|
double volume = getComponentVolume();
|
||||||
|
double density;
|
||||||
|
if (volume > 0.00001) {
|
||||||
|
density = mass / volume;
|
||||||
|
} else {
|
||||||
|
density = 1000;
|
||||||
|
}
|
||||||
|
mat = Material.newMaterial(Type.BULK, mat.getName(), density, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
Material mat = Material.newMaterial(Type.BULK, materialName, density, true);
|
|
||||||
setMaterial(mat);
|
setMaterial(mat);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,7 @@ import javax.swing.event.ChangeListener;
|
|||||||
|
|
||||||
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.preset.RocketComponentPreset;
|
import net.sf.openrocket.preset.ComponentPreset;
|
||||||
import net.sf.openrocket.startup.Application;
|
import net.sf.openrocket.startup.Application;
|
||||||
import net.sf.openrocket.util.ArrayList;
|
import net.sf.openrocket.util.ArrayList;
|
||||||
import net.sf.openrocket.util.BugException;
|
import net.sf.openrocket.util.BugException;
|
||||||
@ -125,7 +125,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
private String id = null;
|
private String id = null;
|
||||||
|
|
||||||
// Preset component this component is based upon
|
// Preset component this component is based upon
|
||||||
private RocketComponentPreset presetComponent = null;
|
private ComponentPreset presetComponent = null;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -669,7 +669,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
*
|
*
|
||||||
* @return the preset component, or <code>null</code> if this is not based on a preset.
|
* @return the preset component, or <code>null</code> if this is not based on a preset.
|
||||||
*/
|
*/
|
||||||
public final RocketComponentPreset getPresetComponent() {
|
public final ComponentPreset getPresetComponent() {
|
||||||
return presetComponent;
|
return presetComponent;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -679,7 +679,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
*
|
*
|
||||||
* @param preset the preset component to load, or <code>null</code> to clear the preset.
|
* @param preset the preset component to load, or <code>null</code> to clear the preset.
|
||||||
*/
|
*/
|
||||||
public final void loadPreset(RocketComponentPreset preset) {
|
public final void loadPreset(ComponentPreset preset) {
|
||||||
if (presetComponent == preset) {
|
if (presetComponent == preset) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -707,7 +707,7 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
rocket.freeze();
|
rocket.freeze();
|
||||||
}
|
}
|
||||||
|
|
||||||
loadFromPreset(preset);
|
loadFromPreset(preset.getPrototype());
|
||||||
|
|
||||||
this.presetComponent = preset;
|
this.presetComponent = preset;
|
||||||
fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
|
fireComponentChangeEvent(ComponentChangeEvent.NONFUNCTIONAL_CHANGE);
|
||||||
@ -726,10 +726,13 @@ public abstract class RocketComponent implements ChangeSource, Cloneable, Iterab
|
|||||||
* <p>
|
* <p>
|
||||||
* This method should fire the appropriate events related to the changes. The rocket
|
* This method should fire the appropriate events related to the changes. The rocket
|
||||||
* is frozen by the caller, so the events will be automatically combined.
|
* is frozen by the caller, so the events will be automatically combined.
|
||||||
|
* <p>
|
||||||
|
* This method must FIRST perform the preset loading and THEN call super.loadFromPreset().
|
||||||
|
* This is because mass setting requires the dimensions to be set beforehand.
|
||||||
*
|
*
|
||||||
* @param preset the preset to load from
|
* @param preset the preset to load from
|
||||||
*/
|
*/
|
||||||
protected void loadFromPreset(RocketComponentPreset preset) {
|
protected void loadFromPreset(RocketComponent preset) {
|
||||||
// No-op
|
// No-op
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -103,6 +103,7 @@ public abstract class SymmetricComponent extends BodyComponent implements Radial
|
|||||||
this.thickness = MathUtil.clamp(thickness, 0, Math.max(getForeRadius(), getAftRadius()));
|
this.thickness = MathUtil.clamp(thickness, 0, Math.max(getForeRadius(), getAftRadius()));
|
||||||
filled = false;
|
filled = false;
|
||||||
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
||||||
|
clearPreset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -124,6 +125,7 @@ public abstract class SymmetricComponent extends BodyComponent implements Radial
|
|||||||
return;
|
return;
|
||||||
this.filled = filled;
|
this.filled = filled;
|
||||||
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
fireComponentChangeEvent(ComponentChangeEvent.MASS_CHANGE);
|
||||||
|
clearPreset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -143,6 +145,18 @@ public abstract class SymmetricComponent extends BodyComponent implements Radial
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void loadFromPreset(RocketComponent preset) {
|
||||||
|
SymmetricComponent c = (SymmetricComponent) preset;
|
||||||
|
this.setThickness(c.getThickness());
|
||||||
|
this.setFilled(c.isFilled());
|
||||||
|
|
||||||
|
super.loadFromPreset(preset);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate volume of the component by integrating over the length of the component.
|
* Calculate volume of the component by integrating over the length of the component.
|
||||||
* The method caches the result, so subsequent calls are instant. Subclasses may
|
* The method caches the result, so subsequent calls are instant. Subclasses may
|
||||||
@ -368,7 +382,7 @@ public abstract class SymmetricComponent extends BodyComponent implements Radial
|
|||||||
longitudinalInertia = 0;
|
longitudinalInertia = 0;
|
||||||
rotationalInertia = 0;
|
rotationalInertia = 0;
|
||||||
|
|
||||||
double volume = 0;
|
double vol = 0;
|
||||||
|
|
||||||
for (int n = 1; n <= DIVISIONS; n++) {
|
for (int n = 1; n <= DIVISIONS; n++) {
|
||||||
/*
|
/*
|
||||||
@ -399,20 +413,20 @@ public abstract class SymmetricComponent extends BodyComponent implements Radial
|
|||||||
longitudinalInertia += dV * ((3 * (pow2(outer) + pow2(inner)) + pow2(l)) / 12
|
longitudinalInertia += dV * ((3 * (pow2(outer) + pow2(inner)) + pow2(l)) / 12
|
||||||
+ pow2(x + l / 2));
|
+ pow2(x + l / 2));
|
||||||
|
|
||||||
volume += dV;
|
vol += dV;
|
||||||
|
|
||||||
// Update for next iteration
|
// Update for next iteration
|
||||||
r1 = r2;
|
r1 = r2;
|
||||||
x += l;
|
x += l;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MathUtil.equals(volume, 0)) {
|
if (MathUtil.equals(vol, 0)) {
|
||||||
integrateInertiaSurface();
|
integrateInertiaSurface();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rotationalInertia /= volume;
|
rotationalInertia /= vol;
|
||||||
longitudinalInertia /= volume;
|
longitudinalInertia /= vol;
|
||||||
|
|
||||||
// Shift longitudinal inertia to CG
|
// Shift longitudinal inertia to CG
|
||||||
longitudinalInertia = Math.max(longitudinalInertia - pow2(getComponentCG().x), 0);
|
longitudinalInertia = Math.max(longitudinalInertia - pow2(getComponentCG().x), 0);
|
||||||
|
|||||||
@ -17,6 +17,7 @@ import net.sf.openrocket.rocketcomponent.Rocket;
|
|||||||
import net.sf.openrocket.util.BugException;
|
import net.sf.openrocket.util.BugException;
|
||||||
import net.sf.openrocket.util.ChangeSource;
|
import net.sf.openrocket.util.ChangeSource;
|
||||||
import net.sf.openrocket.util.MathUtil;
|
import net.sf.openrocket.util.MathUtil;
|
||||||
|
import net.sf.openrocket.util.Utils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class holding simulation options in basic parameter form and which functions
|
* A class holding simulation options in basic parameter form and which functions
|
||||||
@ -415,7 +416,7 @@ public class SimulationOptions implements ChangeSource, Cloneable {
|
|||||||
return false;
|
return false;
|
||||||
SimulationOptions o = (SimulationOptions) other;
|
SimulationOptions o = (SimulationOptions) other;
|
||||||
return ((this.rocket == o.rocket) &&
|
return ((this.rocket == o.rocket) &&
|
||||||
this.motorID.equals(o.motorID) &&
|
Utils.equals(this.motorID, o.motorID) &&
|
||||||
MathUtil.equals(this.launchAltitude, o.launchAltitude) &&
|
MathUtil.equals(this.launchAltitude, o.launchAltitude) &&
|
||||||
MathUtil.equals(this.launchLatitude, o.launchLatitude) &&
|
MathUtil.equals(this.launchLatitude, o.launchLatitude) &&
|
||||||
MathUtil.equals(this.launchPressure, o.launchPressure) &&
|
MathUtil.equals(this.launchPressure, o.launchPressure) &&
|
||||||
|
|||||||
89
test/net/sf/openrocket/logging/TraceExceptionTest.java
Normal file
89
test/net/sf/openrocket/logging/TraceExceptionTest.java
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
package net.sf.openrocket.logging;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class TraceExceptionTest {
|
||||||
|
|
||||||
|
private TraceException getViaAccess() {
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The SubClass test bases on the fact that getViaAccess method is defined on a row number < 20
|
||||||
|
* and the return statement is on a row number > 20.
|
||||||
|
*
|
||||||
|
* The JRE sometimes adds an additional "access$NNN" method call between the calls with the
|
||||||
|
* row number equal to the method definition line.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
return new TraceException(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testBasic() {
|
||||||
|
TraceException trace = new TraceException();
|
||||||
|
assertMatch("\\(TraceExceptionTest.java:[2-9][0-9]\\)", trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testOneLevelUp() {
|
||||||
|
// @formatter:off - these need to be on the same line number
|
||||||
|
TraceException trace = getOneLevelUp(); TraceException ref = new TraceException();
|
||||||
|
// @formatter:on
|
||||||
|
assertEquals(ref.getMessage(), trace.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
private TraceException getOneLevelUp() {
|
||||||
|
return new TraceException(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTwoLevels() {
|
||||||
|
TraceException trace = getTwoLevels();
|
||||||
|
assertMatch("\\(TraceExceptionTest.java:[2-9][0-9] TraceExceptionTest.java:[2-9][0-9]\\)", trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
private TraceException getTwoLevels() {
|
||||||
|
return new TraceException(0, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testViaSubclass() {
|
||||||
|
/*
|
||||||
|
* This tests that TraceException.getMessage ignores the synthetic "access$0" method calls.
|
||||||
|
*/
|
||||||
|
|
||||||
|
TraceException trace = new SubClass().getTrace();
|
||||||
|
assertMatch("\\(TraceExceptionTest.java:[2-9][0-9] TraceExceptionTest.java:[2-9][0-9]\\)", trace);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SubClass {
|
||||||
|
private TraceException getTrace() {
|
||||||
|
return getViaAccess();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private void assertMatch(String regex, TraceException trace) {
|
||||||
|
boolean match = trace.getMessage().matches(regex);
|
||||||
|
if (!match) {
|
||||||
|
trace.printStackTrace();
|
||||||
|
assertTrue("Was: " + trace.getMessage(), match);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user