<classpathentry kind="lib" path="/home/sampo/Projects/OpenRocket/lib/miglayout15-swing.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/JCommon 1.0.16"/>
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/JFreeChart 1.0.13"/>
- <classpathentry kind="lib" path="lib-test/hamcrest-core-1.1.jar"/>
- <classpathentry kind="lib" path="lib-test/hamcrest-library-1.1.jar"/>
- <classpathentry kind="lib" path="lib-test/jmock-2.5.1.jar"/>
- <classpathentry kind="lib" path="lib-test/jmock-junit4-2.5.1.jar"/>
<classpathentry kind="lib" path="lib-extra/RXTXcomm.jar"/>
<classpathentry kind="lib" path="lib-test/junit-4.7.jar"/>
<classpathentry kind="output" path="bin"/>
+2009-10-10 Sampo Niskanen
+
+ * Removed non-ASCII characters from source code files
+ * Created Chars class for non-ASCII characters
+ * Added styrofoam materials
+
2009-10-04 Sampo Niskanen
* [BUG] Fixed too high configuration dialogs
Bugs:
-- Simulation plot dialog forces dialog one button row too high (All/None)
- Unit tests fail from ant script
Maybe:
-- Windows executable wrapper (launch4j)
- Inform user about software updates
Postponed:
+- Windows executable wrapper (launch4j)
- Allow only one instance of OpenRocket running (RMI communication)
- Only schedule rocket figure update instead of each time updating it
- Reading (writing) .RKT format
- JTree text is cropped unnecessarily
- Allow editing user-defined materials
- [BUG] All configuration dialogs too high
+- Simulation plot dialog forces dialog one button row too high (All/None)
<fileset dir="." includes="*">
<type type="file"/>
</fileset>
- <fileset dir="." includes="datafiles/ lib/ pix/ src/ test/"/>
+ <fileset dir="." includes="datafiles/ lib/ lib-test/ pix/ src/ test/"/>
</copy>
<zip destfile="${dist.src}" basedir="${build.dir}" includes="${pkgname}/"/>
<delete dir="${build.dir}/${pkgname}"/>
<!-- DIST-BIN -->
- <target name="dist-bin" depends="checktodo,clean,unittest,jar">
+ <target name="dist-bin" depends="check,clean,unittest,jar">
<move file="${jar.file}" tofile="${dist.bin}"/>
</target>
</target>
+ <!-- CHECK -->
+ <target name="check" depends="checktodo,checkascii"/>
+
<!-- CHECK TODOs -->
<target name="checktodo">
<tempfile property="todo.file" prefix="checktodo-"/>
<fileset dir="${src.dir}">
<include name="**/*.java"/>
</fileset>
+ <fileset dir="${src-test.dir}">
+ <include name="**/*.java"/>
+ </fileset>
<filterchain>
<linecontainsregexp>
<regexp pattern="TODO:.*CRITICAL"/>
</target>
+ <!-- CHECK TODOs -->
+ <target name="checkascii">
+ <tempfile property="ascii.file" prefix="checkascii-"/>
+ <echo>Checking project for non-ASCII characters.</echo>
+ <concat destfile="${ascii.file}">
+ <fileset dir="${src.dir}">
+ <include name="**/*.java"/>
+ </fileset>
+ <fileset dir="${src-test.dir}">
+ <include name="**/*.java"/>
+ </fileset>
+ <filterchain>
+ <linecontainsregexp>
+ <regexp pattern="\P{ASCII}"/>
+ </linecontainsregexp>
+ </filterchain>
+ </concat>
+ <loadfile srcfile="${ascii.file}" property="nonascii"/>
+ <delete file="${ascii.file}"/>
+ <fail if="nonascii">Non-ASCII characters exist in project:
+${nonascii}</fail>
+ <echo>No non-ASCII characters in project.</echo>
+ </target>
+
+
<!-- Unit tests -->
<target name="unittest" description="Execute unit tests" depends="build">
<echo>Building unit tests</echo>
<echo>Running unit tests</echo>
<mkdir dir="tmp/rawtestoutput"/>
- <junit printsummary="true" failureproperty="junit.failure">
+ <junit fork="yes" forkmode="once" printsummary="true" failureproperty="junit.failure">
<classpath>
<path refid="test-classpath"/>
<path location="${basedir}"/>
<batchtest todir="tmp/rawtestoutput">
<fileset dir="${build-test.dir}">
<include name="**/*Test*.class" />
+ <exclude name="**/*$*.class" />
<exclude name="Test.class" />
</fileset>
<formatter type="xml"/>
<fileset dir="tmp/rawtestoutput"/>
<report todir="tmp/test-reports"/>
</junitreport>
- <fail if="junit.failure" message="Unit test(s) failed. See reports!"/>
+ <fail if="junit.failure" message="Unit test(s) failed. See report in ${basedir}/tmp/test-reports/index.html"/>
+ <echo>
+ Unit tests passed successfully.
+ </echo>
</target>
</project>
\ No newline at end of file
BULK_MATERIAL.add(new Material.Bulk("Cardboard", 680, false));
BULK_MATERIAL.add(new Material.Bulk("Carbon fiber", 1780, false));
BULK_MATERIAL.add(new Material.Bulk("Cork", 240, false));
- BULK_MATERIAL.add(new Material.Bulk("Depron", 40, false));
+ BULK_MATERIAL.add(new Material.Bulk("Depron (XPS)", 40, false));
BULK_MATERIAL.add(new Material.Bulk("Fiberglass", 1850, false));
BULK_MATERIAL.add(new Material.Bulk("Kraft phenolic",950, false));
BULK_MATERIAL.add(new Material.Bulk("Maple", 755, false));
BULK_MATERIAL.add(new Material.Bulk("Polystyrene", 1050, false));
BULK_MATERIAL.add(new Material.Bulk("PVC", 1390, false));
BULK_MATERIAL.add(new Material.Bulk("Spruce", 450, false));
- // TODO: CRITICAL: Add styrofoam
+ BULK_MATERIAL.add(new Material.Bulk("Styrofoam generic (EPS)", 20, false));
+ BULK_MATERIAL.add(new Material.Bulk("Styrofoam / Blue Foam (XPS)", 32, false));
BULK_MATERIAL.add(new Material.Bulk("Quantum tubing",1050, false));
SURFACE_MATERIAL.add(new Material.Surface("Ripstop nylon", 0.067, false));
private final JEditorPane editorPane;
+
public DescriptionArea(int rows) {
- this(rows, -1);
+ this("", rows, -1);
}
-
public DescriptionArea(int rows, float size) {
+ this("", rows, size);
+ }
+
+ public DescriptionArea(String text, int rows, float size) {
super(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
this.setPreferredSize(dim);
this.setViewportView(editorPane);
+ this.setText(text);
}
public void setText(String txt) {
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.gui.components.StyledLabel;
import net.sf.openrocket.gui.components.URLLabel;
+import net.sf.openrocket.util.Chars;
import net.sf.openrocket.util.GUIUtil;
import net.sf.openrocket.util.Icons;
import net.sf.openrocket.util.Prefs;
panel.add(new StyledLabel(" ", -1), "ax 50%, growy, wrap para");
}
- panel.add(new StyledLabel("Copyright \u00A9 2007-2009 Sampo Niskanen"),
+ panel.add(new StyledLabel("Copyright " + Chars.COPY +" 2007-2009 Sampo Niskanen"),
"ax 50%, growy, wrap para");
panel.add(new URLLabel(OPENROCKET_URL), "ax 50%, growy, wrap para");
package net.sf.openrocket.gui.dialogs;
import static net.sf.openrocket.unit.Unit.NOUNIT2;
+import static net.sf.openrocket.util.Chars.ALPHA;
import java.awt.Color;
import java.awt.Component;
import net.sf.openrocket.gui.adaptors.DoubleModel;
import net.sf.openrocket.gui.adaptors.MotorConfigurationModel;
import net.sf.openrocket.gui.components.BasicSlider;
-import net.sf.openrocket.gui.components.StyledLabel;
import net.sf.openrocket.gui.components.StageSelector;
+import net.sf.openrocket.gui.components.StyledLabel;
import net.sf.openrocket.gui.components.UnitSelector;
import net.sf.openrocket.gui.scalefigure.RocketPanel;
import net.sf.openrocket.rocketcomponent.Configuration;
return unit.toString(cpData.get(row).cp.x);
}
},
- new Column("<html>C<sub>N<sub>\u03b1</sub></sub>") {
+ new Column("<html>C<sub>N<sub>"+ALPHA+"</sub></sub>") {
@Override public Object getValueAt(int row) {
return NOUNIT2.toString(cpData.get(row).cp.weight);
}
import net.sf.openrocket.rocketcomponent.MotorMount;
import net.sf.openrocket.rocketcomponent.Rocket;
import net.sf.openrocket.rocketcomponent.RocketComponent;
+import net.sf.openrocket.util.Chars;
import net.sf.openrocket.util.GUIUtil;
public class EditMotorConfigurationDialog extends JDialog {
String str = motor.getDesignation(mount.getMotorDelay(id));
int count = mount.getMotorCount();
if (count > 1) {
- str = "" + count + "\u00d7 " + str;
+ str = "" + count + Chars.TIMES + " " + str;
}
return str;
}
String name = mount.toString();
int count = mount.getMotorCount();
if (count > 1) {
- name = name + " (\u00d7" + count + ")";
+ name = name + " (" + Chars.TIMES + count + ")";
}
return name;
}
-
}
-
-
-
}
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.communication.UpdateInfo;
import net.sf.openrocket.gui.components.URLLabel;
+import net.sf.openrocket.util.Chars;
import net.sf.openrocket.util.ComparablePair;
import net.sf.openrocket.util.GUIUtil;
import net.sf.openrocket.util.Icons;
if (count >= 4 && n != updates.get(i).getU())
break;
n = updates.get(i).getU();
- panel.add(new JLabel(" \u2022 " + updates.get(i).getV()), "wrap 0px");
+ panel.add(new JLabel(" " + Chars.BULLET + " " + updates.get(i).getV()),
+ "wrap 0px");
count++;
}
}
import javax.swing.AbstractListModel;
import javax.swing.ComboBoxModel;
import javax.swing.JButton;
+import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
+import javax.swing.JOptionPane;
import javax.swing.JPanel;
+import javax.swing.JProgressBar;
import javax.swing.JTabbedPane;
+import javax.swing.Timer;
import net.miginfocom.swing.MigLayout;
+import net.sf.openrocket.communication.UpdateInfo;
+import net.sf.openrocket.communication.UpdateInfoRetriever;
import net.sf.openrocket.gui.components.StyledLabel;
+import net.sf.openrocket.gui.dialogs.UpdateInfoDialog;
import net.sf.openrocket.unit.Unit;
import net.sf.openrocket.unit.UnitGroup;
import net.sf.openrocket.util.GUIUtil;
tabbedPane.addTab("Units", null, unitsPane(), "Default units");
tabbedPane.addTab("Materials", null, new MaterialEditPanel(), "Custom materials");
- tabbedPane.addTab("Confirmation", null, confirmationPane(), "Confirmation dialog settings");
+ tabbedPane.addTab("Options", null, optionsPane(), "Miscellaneous options");
JButton close = new JButton("Close");
}
- private JPanel confirmationPane() {
- JPanel panel = new JPanel(new MigLayout("fill"));
+ private JPanel optionsPane() {
+ JPanel panel = new JPanel(new MigLayout("fillx, ins 30lp n n n"));
- panel.add(new JLabel("Position to insert new body components:"));
+
+ panel.add(new JLabel("Position to insert new body components:"), "gapright para");
panel.add(new JComboBox(new PrefChoiseSelector(Prefs.BODY_COMPONENT_INSERT_POSITION_KEY,
- "Always ask", "Insert in middle", "Add to end")), "wrap para, sg combos");
+ "Always ask", "Insert in middle", "Add to end")), "wrap para, growx, sg combos");
panel.add(new JLabel("Confirm deletion of simulations:"));
panel.add(new JComboBox(new PrefBooleanSelector(Prefs.CONFIRM_DELETE_SIMULATION,
- "Delete", "Confirm", true)), "wrap para, sg combos");
+ "Delete", "Confirm", true)), "wrap 40lp, growx, sg combos");
+
+
+ final JCheckBox softwareUpdateBox = new JCheckBox("Check for software updates");
+ softwareUpdateBox.setSelected(Prefs.getCheckUpdates());
+ softwareUpdateBox.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ Prefs.setCheckUpdates(softwareUpdateBox.isSelected());
+ }
+ });
+ panel.add(softwareUpdateBox);
+
+ JButton button = new JButton("Check now");
+ button.setToolTipText("Check for software updates now");
+ button.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ checkForUpdates();
+ }
+ });
+ panel.add(button, "right, wrap");
+
return panel;
}
}
+ private void checkForUpdates() {
+ final UpdateInfoRetriever retriever = new UpdateInfoRetriever();
+ retriever.start();
+
+
+ // Progress dialog
+ final JDialog dialog = new JDialog(this, ModalityType.APPLICATION_MODAL);
+ JPanel panel = new JPanel(new MigLayout());
+
+ panel.add(new JLabel("Checking for updates..."), "wrap");
+
+ JProgressBar bar = new JProgressBar();
+ bar.setIndeterminate(true);
+ panel.add(bar, "growx, wrap para");
+
+ JButton cancel = new JButton("Cancel");
+ cancel.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ dialog.dispose();
+ }
+ });
+ panel.add(cancel, "right");
+ dialog.add(panel);
+
+ GUIUtil.setDisposableDialogOptions(dialog, cancel);
+
+
+ // Timer to monitor progress
+ final Timer timer = new Timer(100, null);
+ final long startTime = System.currentTimeMillis();
+
+ ActionListener listener = new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (!retriever.isRunning() || startTime+10000 < System.currentTimeMillis()) {
+ timer.stop();
+ dialog.dispose();
+ }
+ }
+ };
+ timer.addActionListener(listener);
+ timer.start();
+
+
+ // Wait for action
+ dialog.setVisible(true);
+
+
+ // Check result
+ UpdateInfo info = retriever.getUpdateInfo();
+ if (info == null) {
+ JOptionPane.showMessageDialog(this,
+ "An error occurred while communicating with the server.",
+ "Unable to retrieve update information", JOptionPane.WARNING_MESSAGE, null);
+ } else if (info.getLatestVersion() == null ||
+ info.getLatestVersion().equals("") ||
+ Prefs.getVersion().equalsIgnoreCase(info.getLatestVersion())) {
+ JOptionPane.showMessageDialog(this,
+ "You are running the latest version of OpenRocket.",
+ "No updates available", JOptionPane.INFORMATION_MESSAGE, null);
+ } else {
+ new UpdateInfoDialog(info).setVisible(true);
+ }
+
+ }
+
//////// Singleton implementation ////////
package net.sf.openrocket.gui.figureelements;
+import static net.sf.openrocket.util.Chars.*;
+
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import net.sf.openrocket.util.Prefs;
-
/**
* A <code>FigureElement</code> that draws text at different positions in the figure
* with general data about the rocket.
at = "at M="+UnitGroup.UNITS_COEFFICIENT.getDefaultUnit().toStringUnit(mach);
if (!Double.isNaN(aoa)) {
- at += " \u03b1=" + UnitGroup.UNITS_ANGLE.getDefaultUnit().toStringUnit(aoa);
+ at += " "+ALPHA+"=" + UnitGroup.UNITS_ANGLE.getDefaultUnit().toStringUnit(aoa);
}
if (!Double.isNaN(theta)) {
- at += " \u0398=" + UnitGroup.UNITS_ANGLE.getDefaultUnit().toStringUnit(theta);
+ at += " "+THETA+"=" + UnitGroup.UNITS_ANGLE.getDefaultUnit().toStringUnit(theta);
}
GlyphVector cgValue = createText(
public void actionPerformed(ActionEvent e) {
if (!updateInfo.isRunning()) {
timer.stop();
+
+ String current = Prefs.getVersion();
+ String last = Prefs.getString(Prefs.LAST_UPDATE, "");
UpdateInfo info = updateInfo.getUpdateInfo();
- if (info != null && !Prefs.getVersion().equals(info.getLatestVersion())) {
+ if (info != null && info.getLatestVersion() != null &&
+ !current.equals(info.getLatestVersion()) &&
+ !last.equals(info.getLatestVersion())) {
+ Prefs.putString(Prefs.LAST_UPDATE, info.getLatestVersion());
new UpdateInfoDialog(info).setVisible(true);
}
}
import net.sf.openrocket.gui.components.UnitSelector;
import net.sf.openrocket.gui.plot.Axis;
import net.sf.openrocket.gui.plot.PlotConfiguration;
-import net.sf.openrocket.gui.plot.PlotPanel;
+import net.sf.openrocket.gui.plot.SimulationPlotPanel;
import net.sf.openrocket.rocketcomponent.Configuration;
import net.sf.openrocket.simulation.FlightData;
import net.sf.openrocket.simulation.FlightDataBranch;
import net.sf.openrocket.simulation.listeners.CSVSaveListener;
import net.sf.openrocket.unit.Unit;
import net.sf.openrocket.unit.UnitGroup;
+import net.sf.openrocket.util.Chars;
import net.sf.openrocket.util.GUIUtil;
import net.sf.openrocket.util.Icons;
import net.sf.openrocket.util.Prefs;
spin.setToolTipText(tip);
sub.add(spin,"w 65lp!");
- label = new JLabel("\u00b0 N");
+ label = new JLabel(Chars.DEGREE + " N");
label.setToolTipText(tip);
sub.add(label,"growx");
slider = new BasicSlider(m.getSliderModel(-90, 90));
if (true)
- return new PlotPanel(simulation);
+ return new SimulationPlotPanel(simulation);
JPanel panel = new JPanel(new MigLayout("fill"));
+++ /dev/null
-package net.sf.openrocket.gui.plot;
-
-import java.awt.event.ActionEvent;
-import java.awt.event.ActionListener;
-import java.awt.event.ItemEvent;
-import java.awt.event.ItemListener;
-import java.util.Arrays;
-import java.util.EnumSet;
-
-import javax.swing.JButton;
-import javax.swing.JComboBox;
-import javax.swing.JLabel;
-import javax.swing.JOptionPane;
-import javax.swing.JPanel;
-import javax.swing.JScrollPane;
-import javax.swing.JTable;
-import javax.swing.SwingUtilities;
-import javax.swing.table.AbstractTableModel;
-import javax.swing.table.TableColumn;
-import javax.swing.table.TableColumnModel;
-
-import net.miginfocom.swing.MigLayout;
-import net.sf.openrocket.document.Simulation;
-import net.sf.openrocket.gui.components.StyledLabel;
-import net.sf.openrocket.gui.components.UnitSelector;
-import net.sf.openrocket.simulation.FlightDataBranch;
-import net.sf.openrocket.simulation.FlightEvent;
-import net.sf.openrocket.simulation.FlightDataBranch.Type;
-import net.sf.openrocket.unit.Unit;
-import net.sf.openrocket.util.GUIUtil;
-import net.sf.openrocket.util.Icons;
-import net.sf.openrocket.util.Pair;
-
-public class PlotPanel extends JPanel {
-
- // TODO: LOW: Should these be somewhere else?
- public static final int AUTO = -1;
- public static final int LEFT = 0;
- public static final int RIGHT = 1;
-
- public static final String AUTO_NAME = "Auto";
- public static final String LEFT_NAME = "Left";
- public static final String RIGHT_NAME = "Right";
-
- private static final String CUSTOM = "Custom";
-
- /** The "Custom" configuration - not to be used for anything other than the title. */
- private static final PlotConfiguration CUSTOM_CONFIGURATION;
- static {
- CUSTOM_CONFIGURATION = new PlotConfiguration(CUSTOM);
- }
-
- /** The array of presets for the combo box. */
- private static final PlotConfiguration[] PRESET_ARRAY;
- static {
- PRESET_ARRAY = Arrays.copyOf(PlotConfiguration.DEFAULT_CONFIGURATIONS,
- PlotConfiguration.DEFAULT_CONFIGURATIONS.length + 1);
- PRESET_ARRAY[PRESET_ARRAY.length-1] = CUSTOM_CONFIGURATION;
- }
-
-
-
- /** The current default configuration, set each time a plot is made. */
- private static PlotConfiguration defaultConfiguration =
- PlotConfiguration.DEFAULT_CONFIGURATIONS[0].resetUnits();
-
-
- private final Simulation simulation;
- private final FlightDataBranch.Type[] types;
- private PlotConfiguration configuration;
-
-
- private JComboBox configurationSelector;
-
- private JComboBox domainTypeSelector;
- private UnitSelector domainUnitSelector;
-
- private JPanel typeSelectorPanel;
- private FlightEventTableModel eventTableModel;
-
-
- private int modifying = 0;
-
-
- public PlotPanel(final Simulation simulation) {
- super(new MigLayout("fill"));
-
- this.simulation = simulation;
- if (simulation.getSimulatedData() == null ||
- simulation.getSimulatedData().getBranchCount()==0) {
- throw new IllegalArgumentException("Simulation contains no data.");
- }
- FlightDataBranch branch = simulation.getSimulatedData().getBranch(0);
- types = branch.getTypes();
-
- // TODO: LOW: Revert to custom if data type is not available.
- configuration = defaultConfiguration.clone();
-
-
- //// Configuration selector
-
- // Setup the combo box
- configurationSelector = new JComboBox(PRESET_ARRAY);
- for (PlotConfiguration config: PRESET_ARRAY) {
- if (config.getName().equals(configuration.getName())) {
- configurationSelector.setSelectedItem(config);
- }
- }
- configurationSelector.addItemListener(new ItemListener() {
- @Override
- public void itemStateChanged(ItemEvent e) {
- if (modifying > 0)
- return;
- PlotConfiguration conf = (PlotConfiguration)configurationSelector.getSelectedItem();
- if (conf == CUSTOM_CONFIGURATION)
- return;
- modifying++;
- configuration = conf.clone().resetUnits();
- updatePlots();
- modifying--;
- }
- });
- this.add(new JLabel("Preset plot configurations: "), "spanx, split");
- this.add(configurationSelector,"growx, wrap 30lp");
-
-
-
- //// X axis
-
-
- this.add(new JLabel("X axis type:"), "spanx, split");
- domainTypeSelector = new JComboBox(types);
- domainTypeSelector.setSelectedItem(configuration.getDomainAxisType());
- domainTypeSelector.addItemListener(new ItemListener() {
- @Override
- public void itemStateChanged(ItemEvent e) {
- if (modifying > 0)
- return;
- FlightDataBranch.Type type = (Type) domainTypeSelector.getSelectedItem();
- configuration.setDomainAxisType(type);
- domainUnitSelector.setUnitGroup(type.getUnitGroup());
- domainUnitSelector.setSelectedUnit(configuration.getDomainAxisUnit());
- setToCustom();
- }
- });
- this.add(domainTypeSelector, "gapright para");
-
-
- this.add(new JLabel("Unit:"));
- domainUnitSelector = new UnitSelector(configuration.getDomainAxisType().getUnitGroup());
- domainUnitSelector.setSelectedUnit(configuration.getDomainAxisUnit());
- domainUnitSelector.addItemListener(new ItemListener() {
- @Override
- public void itemStateChanged(ItemEvent e) {
- if (modifying > 0)
- return;
- configuration.setDomainAxisUnit(domainUnitSelector.getSelectedUnit());
- }
- });
- this.add(domainUnitSelector, "width 40lp, gapright para");
-
-
- StyledLabel desc = new StyledLabel("<html><p>The data will be plotted in time order " +
- "even if the X axis type is not time.", -2);
- this.add(desc, "width :0px:, growx, wrap para");
-
-
-
- //// Y axis selector panel
-
- this.add(new JLabel("Y axis types:"));
-
- this.add(new JLabel("Flight events:"), "wrap rel");
-
- typeSelectorPanel = new JPanel(new MigLayout("gapy rel"));
- JScrollPane scroll = new JScrollPane(typeSelectorPanel);
- this.add(scroll, "spany 2, height 10px, grow 100, gapright para");
-
-
- //// Flight events
- eventTableModel = new FlightEventTableModel();
- JTable table = new JTable(eventTableModel);
- table.setTableHeader(null);
- table.setShowVerticalLines(false);
- table.setRowSelectionAllowed(false);
- table.setColumnSelectionAllowed(false);
-
- TableColumnModel columnModel = table.getColumnModel();
- TableColumn col0 = columnModel.getColumn(0);
- int w = table.getRowHeight() + 2;
- col0.setMinWidth(w);
- col0.setPreferredWidth(w);
- col0.setMaxWidth(w);
- table.addMouseListener(new GUIUtil.BooleanTableClickListener(table));
- this.add(new JScrollPane(table), "height 1px, width 200lp, grow 1, wrap rel");
-
-
- //// All + None buttons
- JButton button = new JButton("All");
- button.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- for (FlightEvent.Type t: FlightEvent.Type.values())
- configuration.setEvent(t, true);
- eventTableModel.fireTableDataChanged();
- }
- });
- this.add(button, "split 2, gapleft para, gapright para, growx, sizegroup buttons");
-
- button = new JButton("None");
- button.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- for (FlightEvent.Type t: FlightEvent.Type.values())
- configuration.setEvent(t, false);
- eventTableModel.fireTableDataChanged();
- }
- });
- this.add(button, "gapleft para, gapright para, growx, sizegroup buttons, wrap para");
-
-
-
-
- button = new JButton("New Y axis plot type");
- button.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- if (configuration.getTypeCount() >= 15) {
- JOptionPane.showMessageDialog(PlotPanel.this,
- "A maximum of 15 plots is allowed.", "Cannot add plot",
- JOptionPane.ERROR_MESSAGE);
- return;
- }
-
- // Select new type smartly
- FlightDataBranch.Type type = null;
- for (FlightDataBranch.Type t:
- simulation.getSimulatedData().getBranch(0).getTypes()) {
-
- boolean used = false;
- if (configuration.getDomainAxisType().equals(t)) {
- used = true;
- } else {
- for (int i=0; i < configuration.getTypeCount(); i++) {
- if (configuration.getType(i).equals(t)) {
- used = true;
- break;
- }
- }
- }
-
- if (!used) {
- type = t;
- break;
- }
- }
- if (type == null) {
- type = simulation.getSimulatedData().getBranch(0).getTypes()[0];
- }
-
- // Add new type
- configuration.addPlotDataType(type);
- setToCustom();
- updatePlots();
- }
- });
- this.add(button, "spanx, split");
-
-
- this.add(new JPanel(), "growx");
-
- button = new JButton("Plot flight");
- button.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- defaultConfiguration = configuration.clone();
- PlotDialog.showPlot(SwingUtilities.getWindowAncestor(PlotPanel.this),
- simulation, configuration);
- }
- });
- this.add(button, "right");
-
-
- updatePlots();
- }
-
-
- private void setToCustom() {
- modifying++;
- configuration.setName(CUSTOM);
- configurationSelector.setSelectedItem(CUSTOM_CONFIGURATION);
- modifying--;
- }
-
-
- private void updatePlots() {
- domainTypeSelector.setSelectedItem(configuration.getDomainAxisType());
- domainUnitSelector.setUnitGroup(configuration.getDomainAxisType().getUnitGroup());
- domainUnitSelector.setSelectedUnit(configuration.getDomainAxisUnit());
-
- typeSelectorPanel.removeAll();
- for (int i=0; i < configuration.getTypeCount(); i++) {
- FlightDataBranch.Type type = configuration.getType(i);
- Unit unit = configuration.getUnit(i);
- int axis = configuration.getAxis(i);
-
- typeSelectorPanel.add(new PlotTypeSelector(i, type, unit, axis), "wrap");
- }
-
- typeSelectorPanel.repaint();
-
- eventTableModel.fireTableDataChanged();
- }
-
-
-
-
- /**
- * A JPanel which configures a single plot of a PlotConfiguration.
- */
- private class PlotTypeSelector extends JPanel {
- private final String[] POSITIONS = { AUTO_NAME, LEFT_NAME, RIGHT_NAME };
-
- private final int index;
- private JComboBox typeSelector;
- private UnitSelector unitSelector;
- private JComboBox axisSelector;
-
-
- public PlotTypeSelector(int index, FlightDataBranch.Type type) {
- this (index, type, null, -1);
- }
-
- public PlotTypeSelector(int plotIndex, FlightDataBranch.Type type, Unit unit, int position) {
- super(new MigLayout("ins 0"));
-
- this.index = plotIndex;
-
- typeSelector = new JComboBox(types);
- typeSelector.setSelectedItem(type);
- typeSelector.addItemListener(new ItemListener() {
- @Override
- public void itemStateChanged(ItemEvent e) {
- if (modifying > 0)
- return;
- FlightDataBranch.Type type = (Type) typeSelector.getSelectedItem();
- configuration.setPlotDataType(index, type);
- unitSelector.setUnitGroup(type.getUnitGroup());
- unitSelector.setSelectedUnit(configuration.getUnit(index));
- setToCustom();
- }
- });
- this.add(typeSelector, "gapright para");
-
- this.add(new JLabel("Unit:"));
- unitSelector = new UnitSelector(type.getUnitGroup());
- if (unit != null)
- unitSelector.setSelectedUnit(unit);
- unitSelector.addItemListener(new ItemListener() {
- @Override
- public void itemStateChanged(ItemEvent e) {
- if (modifying > 0)
- return;
- Unit unit = (Unit) unitSelector.getSelectedUnit();
- configuration.setPlotDataUnit(index, unit);
- }
- });
- this.add(unitSelector, "width 40lp, gapright para");
-
- this.add(new JLabel("Axis:"));
- axisSelector = new JComboBox(POSITIONS);
- if (position == LEFT)
- axisSelector.setSelectedIndex(1);
- else if (position == RIGHT)
- axisSelector.setSelectedIndex(2);
- else
- axisSelector.setSelectedIndex(0);
- axisSelector.addItemListener(new ItemListener() {
- @Override
- public void itemStateChanged(ItemEvent e) {
- if (modifying > 0)
- return;
- int axis = axisSelector.getSelectedIndex() - 1;
- configuration.setPlotDataAxis(index, axis);
- }
- });
- this.add(axisSelector);
-
-
- JButton button = new JButton(Icons.DELETE);
- button.setToolTipText("Remove this plot");
- button.setBorderPainted(false);
- button.addActionListener(new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent e) {
- configuration.removePlotDataType(index);
- setToCustom();
- updatePlots();
- }
- });
- this.add(button, "gapright 0");
- }
- }
-
-
-
- private class FlightEventTableModel extends AbstractTableModel {
- private final FlightEvent.Type[] eventTypes;
-
- public FlightEventTableModel() {
- EnumSet<FlightEvent.Type> set = EnumSet.noneOf(FlightEvent.Type.class);
- for (int i=0; i < simulation.getSimulatedData().getBranchCount(); i++) {
- for (Pair<Double,FlightEvent> e:
- simulation.getSimulatedData().getBranch(i).getEvents()) {
- set.add(e.getV().getType());
- }
- }
- set.remove(FlightEvent.Type.ALTITUDE);
- int count = set.size();
-
- eventTypes = new FlightEvent.Type[count];
- int pos = 0;
- for (FlightEvent.Type t: FlightEvent.Type.values()) {
- if (set.contains(t)) {
- eventTypes[pos] = t;
- pos++;
- }
- }
- }
-
- @Override
- public int getColumnCount() {
- return 2;
- }
-
- @Override
- public int getRowCount() {
- return eventTypes.length;
- }
-
- @Override
- public Class<?> getColumnClass(int column) {
- switch (column) {
- case 0:
- return Boolean.class;
-
- case 1:
- return String.class;
-
- default:
- throw new IndexOutOfBoundsException("column="+column);
- }
- }
-
- @Override
- public Object getValueAt(int row, int column) {
- switch (column) {
- case 0:
- return new Boolean(configuration.isEventActive(eventTypes[row]));
-
- case 1:
- return eventTypes[row].toString();
-
- default:
- throw new IndexOutOfBoundsException("column="+column);
- }
- }
-
- @Override
- public boolean isCellEditable(int row, int column) {
- return column == 0;
- }
-
- @Override
- public void setValueAt(Object value, int row, int column) {
- if (column != 0 || !(value instanceof Boolean)) {
- throw new IllegalArgumentException("column="+column+", value="+value);
- }
-
- configuration.setEvent(eventTypes[row], (Boolean)value);
- this.fireTableCellUpdated(row, column);
- }
- }
-}
--- /dev/null
+package net.sf.openrocket.gui.plot;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.ItemEvent;
+import java.awt.event.ItemListener;
+import java.util.Arrays;
+import java.util.EnumSet;
+
+import javax.swing.BorderFactory;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.JTable;
+import javax.swing.SwingUtilities;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableColumn;
+import javax.swing.table.TableColumnModel;
+
+import net.miginfocom.swing.MigLayout;
+import net.sf.openrocket.document.Simulation;
+import net.sf.openrocket.gui.components.DescriptionArea;
+import net.sf.openrocket.gui.components.UnitSelector;
+import net.sf.openrocket.simulation.FlightDataBranch;
+import net.sf.openrocket.simulation.FlightEvent;
+import net.sf.openrocket.simulation.FlightDataBranch.Type;
+import net.sf.openrocket.unit.Unit;
+import net.sf.openrocket.util.GUIUtil;
+import net.sf.openrocket.util.Icons;
+import net.sf.openrocket.util.Pair;
+
+public class SimulationPlotPanel extends JPanel {
+
+ // TODO: LOW: Should these be somewhere else?
+ public static final int AUTO = -1;
+ public static final int LEFT = 0;
+ public static final int RIGHT = 1;
+
+ public static final String AUTO_NAME = "Auto";
+ public static final String LEFT_NAME = "Left";
+ public static final String RIGHT_NAME = "Right";
+
+ private static final String CUSTOM = "Custom";
+
+ /** The "Custom" configuration - not to be used for anything other than the title. */
+ private static final PlotConfiguration CUSTOM_CONFIGURATION;
+ static {
+ CUSTOM_CONFIGURATION = new PlotConfiguration(CUSTOM);
+ }
+
+ /** The array of presets for the combo box. */
+ private static final PlotConfiguration[] PRESET_ARRAY;
+ static {
+ PRESET_ARRAY = Arrays.copyOf(PlotConfiguration.DEFAULT_CONFIGURATIONS,
+ PlotConfiguration.DEFAULT_CONFIGURATIONS.length + 1);
+ PRESET_ARRAY[PRESET_ARRAY.length-1] = CUSTOM_CONFIGURATION;
+ }
+
+
+
+ /** The current default configuration, set each time a plot is made. */
+ private static PlotConfiguration defaultConfiguration =
+ PlotConfiguration.DEFAULT_CONFIGURATIONS[0].resetUnits();
+
+
+ private final Simulation simulation;
+ private final FlightDataBranch.Type[] types;
+ private PlotConfiguration configuration;
+
+
+ private JComboBox configurationSelector;
+
+ private JComboBox domainTypeSelector;
+ private UnitSelector domainUnitSelector;
+
+ private JPanel typeSelectorPanel;
+ private FlightEventTableModel eventTableModel;
+
+
+ private int modifying = 0;
+
+
+ public SimulationPlotPanel(final Simulation simulation) {
+ super(new MigLayout("fill"));
+
+ this.simulation = simulation;
+ if (simulation.getSimulatedData() == null ||
+ simulation.getSimulatedData().getBranchCount()==0) {
+ throw new IllegalArgumentException("Simulation contains no data.");
+ }
+ FlightDataBranch branch = simulation.getSimulatedData().getBranch(0);
+ types = branch.getTypes();
+
+ // TODO: LOW: Revert to custom if data type is not available.
+ configuration = defaultConfiguration.clone();
+
+
+ //// Configuration selector
+
+ // Setup the combo box
+ configurationSelector = new JComboBox(PRESET_ARRAY);
+ for (PlotConfiguration config: PRESET_ARRAY) {
+ if (config.getName().equals(configuration.getName())) {
+ configurationSelector.setSelectedItem(config);
+ }
+ }
+ configurationSelector.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ if (modifying > 0)
+ return;
+ PlotConfiguration conf = (PlotConfiguration)configurationSelector.getSelectedItem();
+ if (conf == CUSTOM_CONFIGURATION)
+ return;
+ modifying++;
+ configuration = conf.clone().resetUnits();
+ updatePlots();
+ modifying--;
+ }
+ });
+ this.add(new JLabel("Preset plot configurations: "), "spanx, split");
+ this.add(configurationSelector,"growx, wrap 20lp");
+
+
+
+ //// X axis
+
+
+ this.add(new JLabel("X axis type:"), "spanx, split");
+ domainTypeSelector = new JComboBox(types);
+ domainTypeSelector.setSelectedItem(configuration.getDomainAxisType());
+ domainTypeSelector.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ if (modifying > 0)
+ return;
+ FlightDataBranch.Type type = (Type) domainTypeSelector.getSelectedItem();
+ configuration.setDomainAxisType(type);
+ domainUnitSelector.setUnitGroup(type.getUnitGroup());
+ domainUnitSelector.setSelectedUnit(configuration.getDomainAxisUnit());
+ setToCustom();
+ }
+ });
+ this.add(domainTypeSelector, "gapright para");
+
+
+ this.add(new JLabel("Unit:"));
+ domainUnitSelector = new UnitSelector(configuration.getDomainAxisType().getUnitGroup());
+ domainUnitSelector.setSelectedUnit(configuration.getDomainAxisUnit());
+ domainUnitSelector.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ if (modifying > 0)
+ return;
+ configuration.setDomainAxisUnit(domainUnitSelector.getSelectedUnit());
+ }
+ });
+ this.add(domainUnitSelector, "width 40lp, gapright para");
+
+
+ DescriptionArea desc = new DescriptionArea("The data will be plotted in time order " +
+ "even if the X axis type is not time.", 2, -2f);
+ desc.setViewportBorder(BorderFactory.createEmptyBorder());
+ this.add(desc, "width 1px, growx 1, wrap unrel");
+
+
+
+ //// Y axis selector panel
+
+ this.add(new JLabel("Y axis types:"));
+
+ this.add(new JLabel("Flight events:"), "wrap rel");
+
+ typeSelectorPanel = new JPanel(new MigLayout("gapy rel"));
+ JScrollPane scroll = new JScrollPane(typeSelectorPanel);
+ this.add(scroll, "spany 2, height 10px, grow 100, gapright para");
+
+
+ //// Flight events
+ eventTableModel = new FlightEventTableModel();
+ JTable table = new JTable(eventTableModel);
+ table.setTableHeader(null);
+ table.setShowVerticalLines(false);
+ table.setRowSelectionAllowed(false);
+ table.setColumnSelectionAllowed(false);
+
+ TableColumnModel columnModel = table.getColumnModel();
+ TableColumn col0 = columnModel.getColumn(0);
+ int w = table.getRowHeight() + 2;
+ col0.setMinWidth(w);
+ col0.setPreferredWidth(w);
+ col0.setMaxWidth(w);
+ table.addMouseListener(new GUIUtil.BooleanTableClickListener(table));
+ this.add(new JScrollPane(table), "height 10px, width 200lp, grow 1, wrap rel");
+
+
+ //// All + None buttons
+ JButton button = new JButton("All");
+ button.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ for (FlightEvent.Type t: FlightEvent.Type.values())
+ configuration.setEvent(t, true);
+ eventTableModel.fireTableDataChanged();
+ }
+ });
+ this.add(button, "split 2, gapleft para, gapright para, growx, sizegroup buttons");
+
+ button = new JButton("None");
+ button.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ for (FlightEvent.Type t: FlightEvent.Type.values())
+ configuration.setEvent(t, false);
+ eventTableModel.fireTableDataChanged();
+ }
+ });
+ this.add(button, "gapleft para, gapright para, growx, sizegroup buttons, wrap para");
+
+
+
+
+ button = new JButton("New Y axis plot type");
+ button.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (configuration.getTypeCount() >= 15) {
+ JOptionPane.showMessageDialog(SimulationPlotPanel.this,
+ "A maximum of 15 plots is allowed.", "Cannot add plot",
+ JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+
+ // Select new type smartly
+ FlightDataBranch.Type type = null;
+ for (FlightDataBranch.Type t:
+ simulation.getSimulatedData().getBranch(0).getTypes()) {
+
+ boolean used = false;
+ if (configuration.getDomainAxisType().equals(t)) {
+ used = true;
+ } else {
+ for (int i=0; i < configuration.getTypeCount(); i++) {
+ if (configuration.getType(i).equals(t)) {
+ used = true;
+ break;
+ }
+ }
+ }
+
+ if (!used) {
+ type = t;
+ break;
+ }
+ }
+ if (type == null) {
+ type = simulation.getSimulatedData().getBranch(0).getTypes()[0];
+ }
+
+ // Add new type
+ configuration.addPlotDataType(type);
+ setToCustom();
+ updatePlots();
+ }
+ });
+ this.add(button, "spanx, split");
+
+
+ this.add(new JPanel(), "growx");
+
+ button = new JButton("Plot flight");
+ button.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ defaultConfiguration = configuration.clone();
+ PlotDialog.showPlot(SwingUtilities.getWindowAncestor(SimulationPlotPanel.this),
+ simulation, configuration);
+ }
+ });
+ this.add(button, "right");
+
+
+ updatePlots();
+ }
+
+
+ private void setToCustom() {
+ modifying++;
+ configuration.setName(CUSTOM);
+ configurationSelector.setSelectedItem(CUSTOM_CONFIGURATION);
+ modifying--;
+ }
+
+
+ private void updatePlots() {
+ domainTypeSelector.setSelectedItem(configuration.getDomainAxisType());
+ domainUnitSelector.setUnitGroup(configuration.getDomainAxisType().getUnitGroup());
+ domainUnitSelector.setSelectedUnit(configuration.getDomainAxisUnit());
+
+ typeSelectorPanel.removeAll();
+ for (int i=0; i < configuration.getTypeCount(); i++) {
+ FlightDataBranch.Type type = configuration.getType(i);
+ Unit unit = configuration.getUnit(i);
+ int axis = configuration.getAxis(i);
+
+ typeSelectorPanel.add(new PlotTypeSelector(i, type, unit, axis), "wrap");
+ }
+
+ typeSelectorPanel.repaint();
+
+ eventTableModel.fireTableDataChanged();
+ }
+
+
+
+
+ /**
+ * A JPanel which configures a single plot of a PlotConfiguration.
+ */
+ private class PlotTypeSelector extends JPanel {
+ private final String[] POSITIONS = { AUTO_NAME, LEFT_NAME, RIGHT_NAME };
+
+ private final int index;
+ private JComboBox typeSelector;
+ private UnitSelector unitSelector;
+ private JComboBox axisSelector;
+
+
+ public PlotTypeSelector(int index, FlightDataBranch.Type type) {
+ this (index, type, null, -1);
+ }
+
+ public PlotTypeSelector(int plotIndex, FlightDataBranch.Type type, Unit unit, int position) {
+ super(new MigLayout("ins 0"));
+
+ this.index = plotIndex;
+
+ typeSelector = new JComboBox(types);
+ typeSelector.setSelectedItem(type);
+ typeSelector.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ if (modifying > 0)
+ return;
+ FlightDataBranch.Type type = (Type) typeSelector.getSelectedItem();
+ configuration.setPlotDataType(index, type);
+ unitSelector.setUnitGroup(type.getUnitGroup());
+ unitSelector.setSelectedUnit(configuration.getUnit(index));
+ setToCustom();
+ }
+ });
+ this.add(typeSelector, "gapright para");
+
+ this.add(new JLabel("Unit:"));
+ unitSelector = new UnitSelector(type.getUnitGroup());
+ if (unit != null)
+ unitSelector.setSelectedUnit(unit);
+ unitSelector.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ if (modifying > 0)
+ return;
+ Unit unit = (Unit) unitSelector.getSelectedUnit();
+ configuration.setPlotDataUnit(index, unit);
+ }
+ });
+ this.add(unitSelector, "width 40lp, gapright para");
+
+ this.add(new JLabel("Axis:"));
+ axisSelector = new JComboBox(POSITIONS);
+ if (position == LEFT)
+ axisSelector.setSelectedIndex(1);
+ else if (position == RIGHT)
+ axisSelector.setSelectedIndex(2);
+ else
+ axisSelector.setSelectedIndex(0);
+ axisSelector.addItemListener(new ItemListener() {
+ @Override
+ public void itemStateChanged(ItemEvent e) {
+ if (modifying > 0)
+ return;
+ int axis = axisSelector.getSelectedIndex() - 1;
+ configuration.setPlotDataAxis(index, axis);
+ }
+ });
+ this.add(axisSelector);
+
+
+ JButton button = new JButton(Icons.DELETE);
+ button.setToolTipText("Remove this plot");
+ button.setBorderPainted(false);
+ button.addActionListener(new ActionListener() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ configuration.removePlotDataType(index);
+ setToCustom();
+ updatePlots();
+ }
+ });
+ this.add(button, "gapright 0");
+ }
+ }
+
+
+
+ private class FlightEventTableModel extends AbstractTableModel {
+ private final FlightEvent.Type[] eventTypes;
+
+ public FlightEventTableModel() {
+ EnumSet<FlightEvent.Type> set = EnumSet.noneOf(FlightEvent.Type.class);
+ for (int i=0; i < simulation.getSimulatedData().getBranchCount(); i++) {
+ for (Pair<Double,FlightEvent> e:
+ simulation.getSimulatedData().getBranch(i).getEvents()) {
+ set.add(e.getV().getType());
+ }
+ }
+ set.remove(FlightEvent.Type.ALTITUDE);
+ int count = set.size();
+
+ eventTypes = new FlightEvent.Type[count];
+ int pos = 0;
+ for (FlightEvent.Type t: FlightEvent.Type.values()) {
+ if (set.contains(t)) {
+ eventTypes[pos] = t;
+ pos++;
+ }
+ }
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 2;
+ }
+
+ @Override
+ public int getRowCount() {
+ return eventTypes.length;
+ }
+
+ @Override
+ public Class<?> getColumnClass(int column) {
+ switch (column) {
+ case 0:
+ return Boolean.class;
+
+ case 1:
+ return String.class;
+
+ default:
+ throw new IndexOutOfBoundsException("column="+column);
+ }
+ }
+
+ @Override
+ public Object getValueAt(int row, int column) {
+ switch (column) {
+ case 0:
+ return new Boolean(configuration.isEventActive(eventTypes[row]));
+
+ case 1:
+ return eventTypes[row].toString();
+
+ default:
+ throw new IndexOutOfBoundsException("column="+column);
+ }
+ }
+
+ @Override
+ public boolean isCellEditable(int row, int column) {
+ return column == 0;
+ }
+
+ @Override
+ public void setValueAt(Object value, int row, int column) {
+ if (column != 0 || !(value instanceof Boolean)) {
+ throw new IllegalArgumentException("column="+column+", value="+value);
+ }
+
+ configuration.setEvent(eventTypes[row], (Boolean)value);
+ this.fireTableCellUpdated(row, column);
+ }
+ }
+}
import net.sf.openrocket.simulation.listeners.InterruptListener;
import net.sf.openrocket.unit.UnitGroup;
import net.sf.openrocket.util.ChangeSource;
+import net.sf.openrocket.util.Chars;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.MathUtil;
import net.sf.openrocket.util.Prefs;
// Add rotation slider
// Minimum size to fit "360deg"
- JLabel l = new JLabel("360\u00b0");
+ JLabel l = new JLabel("360" + Chars.DEGREE);
Dimension d = l.getPreferredSize();
add(new BasicSlider(theta.getSliderModel(0,2*Math.PI),JSlider.VERTICAL,true),
import javax.swing.event.EventListenerList;
import net.sf.openrocket.motor.Motor;
+import net.sf.openrocket.util.Chars;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.MathUtil;
if (previous != null) {
String s = "";
if (count > 1) {
- s = "" + count + "\u00d7" + previous;
+ s = "" + count + Chars.TIMES + previous;
} else {
s = previous;
}
if (previous != null) {
String s = "";
if (count > 1) {
- s = "" + count + "\u00d7" + previous;
+ s = "" + count + Chars.TIMES + previous;
} else {
s = previous;
}
package net.sf.openrocket.rocketcomponent;
-import static java.lang.Math.sin;
-import static java.lang.Math.sqrt;
-import static net.sf.openrocket.util.MathUtil.pow2;
-import static net.sf.openrocket.util.MathUtil.pow3;
+import static java.lang.Math.*;
+import static net.sf.openrocket.util.Chars.*;
+import static net.sf.openrocket.util.MathUtil.*;
import java.util.Collection;
"<i>Radius</i> × (<i>x</i> / <i>Length</i>)" +
"<sup><i>k</i></sup> "+
"where <i>k</i> is the shape parameter. For <i>k</i>=0.5 this is a "+
- "<b>½-power</b> or <b>parabolic</b> nose cone, for <i>k</i>=0.75 a "+
- "<b>¾-power</b>, and for <i>k</i>=1 a <b>conical</b> nose cone.",
+ "<b>" + FRAC12 +"-power</b> or <b>parabolic</b> nose cone, for <i>k</i>=0.75 a "+
+ "<b>" + FRAC34 +"-power</b>, and for <i>k</i>=1 a <b>conical</b> nose cone.",
"A power series transition has a profile of "+
"<i>Radius</i> × (<i>x</i> / <i>Length</i>)" +
"<sup><i>k</i></sup> "+
"where <i>k</i> is the shape parameter. For <i>k</i>=0.5 the transition is "+
- "<b>½-power</b> or <b>parabolic</b>, for <i>k</i>=0.75 a <b>¾-power</b>, and for " +
- "<i>k</i>=1 <b>conical</b>.",true) {
+ "<b>" + FRAC12 + "-power</b> or <b>parabolic</b>, for <i>k</i>=0.75 a " +
+ "<b>" + FRAC34 + "-power</b>, and for <i>k</i>=1 <b>conical</b>.",true) {
@Override
public boolean usesParameter() { // Range 0...1
return true;
import java.text.DecimalFormat;
+import net.sf.openrocket.util.Chars;
+
public class DegreeUnit extends GeneralUnit {
public DegreeUnit() {
- super(Math.PI/180.0,"\u00b0");
+ super(Math.PI/180.0, ""+Chars.DEGREE);
}
@Override
import java.text.DecimalFormat;
+import net.sf.openrocket.util.Chars;
+
public abstract class Unit {
/** No unit with 2 digit precision */
- public static final Unit NOUNIT2 = new GeneralUnit(1,"\u200b", 2); // zero-width space
+ public static final Unit NOUNIT2 = new GeneralUnit(1,""+Chars.ZWSP, 2);
protected final double multiplier; // meters = units * multiplier
protected final String unit;
package net.sf.openrocket.unit;
+import static net.sf.openrocket.util.Chars.*;
import static net.sf.openrocket.util.MathUtil.pow2;
import java.util.ArrayList;
UNITS_DISTANCE.addUnit(new GeneralUnit(1609.344,"mi"));
UNITS_AREA = new UnitGroup();
- UNITS_AREA.addUnit(new GeneralUnit(pow2(0.001),"mm\u00b2"));
- UNITS_AREA.addUnit(new GeneralUnit(pow2(0.01),"cm\u00b2"));
- UNITS_AREA.addUnit(new GeneralUnit(1,"m\u00b2"));
- UNITS_AREA.addUnit(new GeneralUnit(pow2(0.0254),"in\u00b2"));
- UNITS_AREA.addUnit(new GeneralUnit(pow2(0.3048),"ft\u00b2"));
+ UNITS_AREA.addUnit(new GeneralUnit(pow2(0.001),"mm" + SQUARED));
+ UNITS_AREA.addUnit(new GeneralUnit(pow2(0.01),"cm" + SQUARED));
+ UNITS_AREA.addUnit(new GeneralUnit(1,"m" + SQUARED));
+ UNITS_AREA.addUnit(new GeneralUnit(pow2(0.0254),"in" + SQUARED));
+ UNITS_AREA.addUnit(new GeneralUnit(pow2(0.3048),"ft" + SQUARED));
UNITS_AREA.setDefaultUnit(1);
UNITS_VELOCITY.addUnit(new GeneralUnit(0.44704, "mph"));
UNITS_ACCELERATION = new UnitGroup();
- UNITS_ACCELERATION.addUnit(new GeneralUnit(1, "m/s\u00b2"));
- UNITS_ACCELERATION.addUnit(new GeneralUnit(0.3048, "ft/s\u00b2"));
+ UNITS_ACCELERATION.addUnit(new GeneralUnit(1, "m/s" + SQUARED));
+ UNITS_ACCELERATION.addUnit(new GeneralUnit(0.3048, "ft/s" + SQUARED));
UNITS_MASS = new UnitGroup();
UNITS_ANGLE.addUnit(new FixedPrecisionUnit("rad",0.01));
UNITS_DENSITY_BULK = new UnitGroup();
- UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1000,"g/cm\u00b3"));
- UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1,"kg/m\u00b3"));
- UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1729.99404,"oz/in\u00b3"));
- UNITS_DENSITY_BULK.addUnit(new GeneralUnit(16.0184634,"lb/ft\u00b3"));
+ UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1000,"g/cm" + CUBED));
+ UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1,"kg/m" + CUBED));
+ UNITS_DENSITY_BULK.addUnit(new GeneralUnit(1729.99404,"oz/in" + CUBED));
+ UNITS_DENSITY_BULK.addUnit(new GeneralUnit(16.0184634,"lb/ft" + CUBED));
UNITS_DENSITY_SURFACE = new UnitGroup();
- UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(10,"g/cm\u00b2"));
- UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(0.001,"g/m\u00b2"));
- UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(1,"kg/m\u00b2"));
- UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(43.9418487,"oz/in\u00b2"));
- UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(0.305151727,"oz/ft\u00b2"));
- UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(4.88242764,"lb/ft\u00b2"));
+ UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(10,"g/cm" + SQUARED));
+ UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(0.001,"g/m" + SQUARED));
+ UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(1,"kg/m" + SQUARED));
+ UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(43.9418487,"oz/in" + SQUARED));
+ UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(0.305151727,"oz/ft" + SQUARED));
+ UNITS_DENSITY_SURFACE.addUnit(new GeneralUnit(4.88242764,"lb/ft" + SQUARED));
UNITS_DENSITY_SURFACE.setDefaultUnit(1);
UNITS_DENSITY_LINE = new UnitGroup();
UNITS_IMPULSE = new UnitGroup();
UNITS_IMPULSE.addUnit(new GeneralUnit(1,"Ns"));
- UNITS_IMPULSE.addUnit(new GeneralUnit(4.44822162, "lbf\u00b7s"));
+ UNITS_IMPULSE.addUnit(new GeneralUnit(4.44822162, "lbf"+DOT+"s"));
UNITS_TIME_STEP = new UnitGroup();
UNITS_TIME_STEP.addUnit(new FixedPrecisionUnit("ms", 1, 0.001));
UNITS_TEMPERATURE = new UnitGroup();
UNITS_TEMPERATURE.addUnit(new FixedPrecisionUnit("K", 1));
- UNITS_TEMPERATURE.addUnit(new TemperatureUnit(1, 273.15, "\u00b0C"));
- UNITS_TEMPERATURE.addUnit(new TemperatureUnit(5.0/9.0, 459.67, "\u00b0F"));
+ UNITS_TEMPERATURE.addUnit(new TemperatureUnit(1, 273.15, DEGREE+"C"));
+ UNITS_TEMPERATURE.addUnit(new TemperatureUnit(5.0/9.0, 459.67, DEGREE+"F"));
UNITS_TEMPERATURE.setDefaultUnit(1);
UNITS_PRESSURE = new UnitGroup();
UNITS_PRESSURE.addUnit(new GeneralUnit(1, "Pa"));
UNITS_RELATIVE = new UnitGroup();
- UNITS_RELATIVE.addUnit(new FixedPrecisionUnit("\u200b", 0.01));
+ UNITS_RELATIVE.addUnit(new FixedPrecisionUnit(""+ZWSP, 0.01, 1.0));
UNITS_RELATIVE.addUnit(new FixedPrecisionUnit("%", 1, 0.01));
+ UNITS_RELATIVE.addUnit(new FixedPrecisionUnit(""+PERMILLE, 1, 0.001));
UNITS_RELATIVE.setDefaultUnit(1);
UNITS_ROUGHNESS = new UnitGroup();
- UNITS_ROUGHNESS.addUnit(new GeneralUnit(0.000001, "\u03bcm"));
+ UNITS_ROUGHNESS.addUnit(new GeneralUnit(0.000001, MICRO+"m"));
UNITS_ROUGHNESS.addUnit(new GeneralUnit(0.0000254, "mil"));
UNITS_COEFFICIENT = new UnitGroup();
- UNITS_COEFFICIENT.addUnit(new FixedPrecisionUnit("\u200b", 0.01)); // zero-width space
+ UNITS_COEFFICIENT.addUnit(new FixedPrecisionUnit(""+ZWSP, 0.01)); // zero-width space
HashMap<String,UnitGroup> map = new HashMap<String,UnitGroup>();
UNITS_LENGTH.setDefaultUnit("cm");
UNITS_MOTOR_DIMENSIONS.setDefaultUnit("mm");
UNITS_DISTANCE.setDefaultUnit("m");
- UNITS_AREA.setDefaultUnit("cm\u00b2");
+ UNITS_AREA.setDefaultUnit("cm"+SQUARED);
UNITS_STABILITY.setDefaultUnit("cal");
UNITS_VELOCITY.setDefaultUnit("m/s");
- UNITS_ACCELERATION.setDefaultUnit("m/s\u00b2");
+ UNITS_ACCELERATION.setDefaultUnit("m/s"+SQUARED);
UNITS_MASS.setDefaultUnit("g");
- UNITS_ANGLE.setDefaultUnit(0);
- UNITS_DENSITY_BULK.setDefaultUnit("g/cm\u00b3");
- UNITS_DENSITY_SURFACE.setDefaultUnit("g/m\u00b2");
+ UNITS_ANGLE.setDefaultUnit(""+DEGREE);
+ UNITS_DENSITY_BULK.setDefaultUnit("g/cm"+CUBED);
+ UNITS_DENSITY_SURFACE.setDefaultUnit("g/m"+SQUARED);
UNITS_DENSITY_LINE.setDefaultUnit("g/m");
UNITS_FORCE.setDefaultUnit("N");
UNITS_IMPULSE.setDefaultUnit("Ns");
UNITS_TIME_STEP.setDefaultUnit("s");
UNITS_FLIGHT_TIME.setDefaultUnit("s");
UNITS_ROLL.setDefaultUnit("r/s");
- UNITS_TEMPERATURE.setDefaultUnit(1);
+ UNITS_TEMPERATURE.setDefaultUnit(DEGREE+"C");
UNITS_PRESSURE.setDefaultUnit("mbar");
UNITS_RELATIVE.setDefaultUnit("%");
- UNITS_ROUGHNESS.setDefaultUnit("\u03bcm");
+ UNITS_ROUGHNESS.setDefaultUnit(MICRO+"m");
}
public static void setDefaultImperialUnits() {
UNITS_LENGTH.setDefaultUnit("in");
UNITS_MOTOR_DIMENSIONS.setDefaultUnit("in");
UNITS_DISTANCE.setDefaultUnit("ft");
- UNITS_AREA.setDefaultUnit("in\u00b2");
+ UNITS_AREA.setDefaultUnit("in"+SQUARED);
UNITS_STABILITY.setDefaultUnit("cal");
UNITS_VELOCITY.setDefaultUnit("ft/s");
- UNITS_ACCELERATION.setDefaultUnit("ft/s\u00b2");
+ UNITS_ACCELERATION.setDefaultUnit("ft/s"+SQUARED);
UNITS_MASS.setDefaultUnit("oz");
- UNITS_ANGLE.setDefaultUnit(0);
- UNITS_DENSITY_BULK.setDefaultUnit("oz/in\u00b3");
- UNITS_DENSITY_SURFACE.setDefaultUnit("oz/ft\u00b2");
+ UNITS_ANGLE.setDefaultUnit(""+DEGREE);
+ UNITS_DENSITY_BULK.setDefaultUnit("oz/in"+CUBED);
+ UNITS_DENSITY_SURFACE.setDefaultUnit("oz/ft"+SQUARED);
UNITS_DENSITY_LINE.setDefaultUnit("oz/ft");
UNITS_FORCE.setDefaultUnit("N");
UNITS_IMPULSE.setDefaultUnit("Ns");
UNITS_TIME_STEP.setDefaultUnit("s");
UNITS_FLIGHT_TIME.setDefaultUnit("s");
UNITS_ROLL.setDefaultUnit("r/s");
- UNITS_TEMPERATURE.setDefaultUnit(2);
+ UNITS_TEMPERATURE.setDefaultUnit(DEGREE+"F");
UNITS_PRESSURE.setDefaultUnit("mbar");
UNITS_RELATIVE.setDefaultUnit("%");
UNITS_ROUGHNESS.setDefaultUnit("mil");
}
/**
- * Set the default unit based on the unit name. Does nothing if the name
- * does not match any of the units.
+ * Set the default unit based on the unit name. Throws an exception if a
+ * unit with the provided name is not available.
*
- * @param name the unit name (<code>null</code> ok).
- * @return <code>true</code> if the the default was set,
- * <code>false</code> if a matching unit was not found.
+ * @param name the unit name.
+ * @throws IllegalArgumentException if the corresponding unit is not found in the group.
*/
- public boolean setDefaultUnit(String name) {
- if (name == null)
- return false;
-
+ public void setDefaultUnit(String name) throws IllegalArgumentException {
for (int i=0; i < units.size(); i++) {
- if (name.equals(units.get(i).getUnit())) {
+ if (units.get(i).getUnit().equals(name)) {
setDefaultUnit(i);
- return true;
+ return;
}
}
- return false;
+ throw new IllegalArgumentException("name="+name);
}
--- /dev/null
+package net.sf.openrocket.util;
+
+/**
+ * A class defining various non-ASCII characters for easier use.
+ *
+ * @author Sampo Niskanen <sampo.niskanen@iki.fi>
+ */
+public class Chars {
+
+ /** The fraction 1/2 */
+ public static final char FRAC12 = '\u00BD';
+ /** The fraction 1/4 */
+ public static final char FRAC14 = '\u00BC';
+ /** The fraction 3/4 */
+ public static final char FRAC34 = '\u00BE';
+
+ /** Degree sign */
+ public static final char DEGREE = '\u00B0';
+
+ /** Squared, superscript 2 */
+ public static final char SQUARED = '\u00B2';
+ /** Cubed, superscript 3 */
+ public static final char CUBED = '\u00B3';
+
+ /** Per mille sign */
+ public static final char PERMILLE = '\u2030';
+
+ /** Middle dot, multiplication */
+ public static final char DOT = '\u00B7';
+ /** Multiplication sign, cross */
+ public static final char TIMES = '\u00D7';
+
+ /** No-break space */
+ public static final char NBSP = '\u00A0';
+ /** Zero-width space */
+ public static final char ZWSP = '\u200B';
+
+ /** Micro sign (Greek letter mu) */
+ public static final char MICRO = '\u00B5';
+
+ /** Alpha */
+ public static final char ALPHA = '\u03b1';
+ /** Theta */
+ public static final char THETA = '\u0398';
+
+ /** Copyright symbol */
+ public static final char COPY = '\u00A9';
+ /** A centered bullet */
+ public static final char BULLET = '\u2022';
+}
* A thread-safe <code>ProgressMonitor</code>. This class may be instantiated
* and the method {@link #setProgress(int)} called safely from any thread.
* <p>
- * Why the FSCK&!¤#&%¤ isn't the default API version thread-safe?!?!
+ * Why the FSCK&!#&% isn't the default API version thread-safe?!?!
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
return v;
}
+
+ /**
+ * Compare both components of the Pair to another object.
+ * The pair is equal iff both items are equal (or null).
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public boolean equals(Object other) {
+ if (!(other instanceof Pair))
+ return false;
+ Object otherU = ((Pair)other).getU();
+ Object otherV = ((Pair)other).getV();
+
+ if (otherU == null) {
+ if (this.u != null)
+ return false;
+ } else {
+ if (!otherU.equals(this.u))
+ return false;
+ }
+
+ if (otherV == null) {
+ if (this.v != null)
+ return false;
+ } else {
+ if (!otherV.equals(this.v))
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ return ((u != null) ? u.hashCode() : 0) + ((v != null) ? v.hashCode() : 0);
+ }
+
}
*/
public static final String NODENAME = (DEBUG?"OpenRocket-debug":"OpenRocket");
-
-
- private static final String BUILD_VERSION;
- private static final String BUILD_SOURCE;
+
public static final String DEFAULT_BUILD_SOURCE = "default";
- private static final boolean DEFAULT_CHECK_UPDATES;
+
- static {
- try {
- InputStream is = ClassLoader.getSystemResourceAsStream("build.properties");
- if (is == null) {
- throw new MissingResourceException(
- "build.properties not found, distribution built wrong" +
- " path:"+System.getProperty("java.class.path"),
- "build.properties", "build.version");
- }
-
- Properties props = new Properties();
- props.load(is);
- is.close();
-
- BUILD_VERSION = props.getProperty("build.version");
- if (BUILD_VERSION == null) {
+ /*
+ * Load property file only when necessary.
+ */
+ private static class BuildPropertyHolder {
+
+ public static final String BUILD_VERSION;
+ public static final String BUILD_SOURCE;
+ public static final boolean DEFAULT_CHECK_UPDATES;
+
+ static {
+ try {
+ InputStream is = ClassLoader.getSystemResourceAsStream("build.properties");
+ if (is == null) {
+ throw new MissingResourceException(
+ "build.properties not found, distribution built wrong" +
+ " classpath:"+System.getProperty("java.class.path"),
+ "build.properties", "build.version");
+ }
+
+ Properties props = new Properties();
+ props.load(is);
+ is.close();
+
+ String version = props.getProperty("build.version");
+ if (version == null) {
+ throw new MissingResourceException(
+ "build.version not found in property file",
+ "build.properties", "build.version");
+ }
+ BUILD_VERSION = version.trim();
+
+ BUILD_SOURCE = props.getProperty("build.source");
+ if (BUILD_SOURCE == null) {
+ throw new MissingResourceException(
+ "build.source not found in property file",
+ "build.properties", "build.source");
+ }
+
+ String value = props.getProperty("build.checkupdates");
+ if (value != null)
+ DEFAULT_CHECK_UPDATES = Boolean.parseBoolean(value);
+ else
+ DEFAULT_CHECK_UPDATES = true;
+
+ } catch (IOException e) {
throw new MissingResourceException(
- "build.version not found in property file",
+ "Error reading build.properties",
"build.properties", "build.version");
}
-
- BUILD_SOURCE = props.getProperty("build.source");
-
- String value = props.getProperty("build.checkupdates");
- if (value != null)
- DEFAULT_CHECK_UPDATES = Boolean.parseBoolean(value);
- else
- DEFAULT_CHECK_UPDATES = true;
-
- } catch (IOException e) {
- throw new MissingResourceException(
- "Error reading build.properties",
- "build.properties", "build.version");
}
}
-
public static final String BODY_COMPONENT_INSERT_POSITION_KEY = "BodyComponentInsertPosition";
public static final String PLOT_SHOW_POINTS = "ShowPlotPoints";
private static final String CHECK_UPDATES = "CheckUpdates";
+ public static final String LAST_UPDATE = "LastUpdateVersion";
/**
* Node to this application's preferences.
public static String getVersion() {
- return BUILD_VERSION;
+ return BuildPropertyHolder.BUILD_VERSION;
}
public static String getBuildSource() {
- return BUILD_SOURCE;
+ return BuildPropertyHolder.BUILD_SOURCE;
}
public static boolean getCheckUpdates() {
- return PREFNODE.getBoolean(CHECK_UPDATES, DEFAULT_CHECK_UPDATES);
+ return PREFNODE.getBoolean(CHECK_UPDATES, BuildPropertyHolder.DEFAULT_CHECK_UPDATES);
}
public static void setCheckUpdates(boolean check) {
if (group == null)
continue;
- group.setDefaultUnit(prefs.get(key, null));
+ try {
+ group.setDefaultUnit(prefs.get(key, null));
+ } catch (IllegalArgumentException ignore) { }
}
} catch (BackingStoreException e) {
assertTrue(m1.matches("a/"));
assertTrue(m1.matches("a/rcs"));
assertTrue(m1.matches("a/rms"));
- assertTrue(m1.matches("aerotech ...-/%¤#_!"));
+ assertTrue(m1.matches("aerotech ...-/%#_!"));
assertTrue(m1.matches(" .isp/"));
assertFalse(m1.matches("aero/tech"));
assertCoordinateEquals(new Coordinate(2,4,6,8), y.multiply(2));
- assertEquals(1+2+3, y.dot(x));
- assertEquals(1+2+3, x.dot(y));
- assertEquals(1+2+3, Coordinate.dot(x,y));
- assertEquals(x.dot(x), x.length2());
- assertEquals(y.dot(y), y.length2());
+ assertEquals(1+2+3, y.dot(x), EPS);
+ assertEquals(1+2+3, x.dot(y), EPS);
+ assertEquals(1+2+3, Coordinate.dot(x,y), EPS);
+ assertEquals(x.dot(x), x.length2(), EPS);
+ assertEquals(y.dot(y), y.length2(), EPS);
assertEquals(Math.sqrt(1+4+9), y.length(), EPS);
assertEquals(1, y.normalize().length(), EPS);
assertEquals(PI*PI*PI, MathUtil.pow3(PI), EPS);
assertEquals(PI*PI*PI*PI, MathUtil.pow4(PI), EPS);
- assertEquals(1.0, MathUtil.clamp(0.9999, 1.0, 2.0));
- assertEquals(1.23, MathUtil.clamp(1.23, 1.0, 2.0));
- assertEquals(2.0, MathUtil.clamp(2 + EPS/100, 1.0, 2.0));
+ assertEquals(1.0, MathUtil.clamp(0.9999, 1.0, 2.0), 0);
+ assertEquals(1.23, MathUtil.clamp(1.23, 1.0, 2.0), 0);
+ assertEquals(2.0, MathUtil.clamp(2 + EPS/100, 1.0, 2.0), 0);
- assertEquals(1.0f, MathUtil.clamp(0.9999f, 1.0f, 2.0f));
- assertEquals(1.23f, MathUtil.clamp(1.23f, 1.0f, 2.0f));
- assertEquals(2.0f, MathUtil.clamp(2.0001f, 1.0f, 2.0f));
+ assertEquals(1.0f, MathUtil.clamp(0.9999f, 1.0f, 2.0f), 0);
+ assertEquals(1.23f, MathUtil.clamp(1.23f, 1.0f, 2.0f), 0);
+ assertEquals(2.0f, MathUtil.clamp(2.0001f, 1.0f, 2.0f), 0);
assertEquals(1, MathUtil.clamp(-3, 1, 5));
assertEquals(3, MathUtil.clamp(3, 1, 5));
assertEquals(5, MathUtil.clamp(6, 1, 5));
- assertEquals(-1.0, MathUtil.sign(Double.NEGATIVE_INFINITY));
- assertEquals(-1.0, MathUtil.sign(-100));
- assertEquals(-1.0, MathUtil.sign(Math.nextAfter(0.0, -1.0)));
- assertEquals( 1.0, MathUtil.sign(Math.nextUp(0.0)));
- assertEquals( 1.0, MathUtil.sign(100));
- assertEquals( 1.0, MathUtil.sign(Double.POSITIVE_INFINITY));
+ assertEquals(-1.0, MathUtil.sign(Double.NEGATIVE_INFINITY), EPS);
+ assertEquals(-1.0, MathUtil.sign(-100), EPS);
+ assertEquals(-1.0, MathUtil.sign(Math.nextAfter(0.0, -1.0)), EPS);
+ assertEquals( 1.0, MathUtil.sign(Math.nextUp(0.0)), EPS);
+ assertEquals( 1.0, MathUtil.sign(100), EPS);
+ assertEquals( 1.0, MathUtil.sign(Double.POSITIVE_INFINITY), EPS);
}
@Test
@Test
public void minmaxTest() {
- assertEquals(1.0, MathUtil.min(1.0, Math.nextUp(1.0)));
- assertEquals(1.0, MathUtil.min(1.0, Double.POSITIVE_INFINITY));
- assertEquals(1.0, MathUtil.min(NaN, 1.0));
- assertEquals(1.0, MathUtil.min(1.0, NaN));
- assertEquals(NaN, MathUtil.min(NaN, NaN));
+ assertEquals(1.0, MathUtil.min(1.0, Math.nextUp(1.0)), 0);
+ assertEquals(1.0, MathUtil.min(1.0, Double.POSITIVE_INFINITY), 0);
+ assertEquals(1.0, MathUtil.min(NaN, 1.0), 0);
+ assertEquals(1.0, MathUtil.min(1.0, NaN), 0);
+ assertEquals(NaN, MathUtil.min(NaN, NaN), 0);
- assertEquals(Math.nextUp(1.0), MathUtil.max(1.0, Math.nextUp(1.0)));
- assertEquals(Double.POSITIVE_INFINITY, MathUtil.max(1.0, Double.POSITIVE_INFINITY));
- assertEquals(1.0, MathUtil.max(NaN, 1.0));
- assertEquals(1.0, MathUtil.max(1.0, NaN));
- assertEquals(NaN, MathUtil.max(NaN, NaN));
+ assertEquals(Math.nextUp(1.0), MathUtil.max(1.0, Math.nextUp(1.0)), 0);
+ assertEquals(Double.POSITIVE_INFINITY, MathUtil.max(1.0, Double.POSITIVE_INFINITY), 0);
+ assertEquals(1.0, MathUtil.max(NaN, 1.0), 0);
+ assertEquals(1.0, MathUtil.max(1.0, NaN), 0);
+ assertEquals(NaN, MathUtil.max(NaN, NaN), 0);
- assertEquals(1.0, MathUtil.min(1.0, 2.0, 3.0));
- assertEquals(1.0, MathUtil.min(1.0, NaN, NaN));
- assertEquals(1.0, MathUtil.min(NaN, 1.0, NaN));
- assertEquals(1.0, MathUtil.min(NaN, NaN, 1.0));
- assertEquals(1.0, MathUtil.min(2.0, NaN, 1.0));
- assertEquals(1.0, MathUtil.min(1.0, 2.0, NaN));
- assertEquals(1.0, MathUtil.min(NaN, 2.0, 1.0));
+ assertEquals(1.0, MathUtil.min(1.0, 2.0, 3.0), 0);
+ assertEquals(1.0, MathUtil.min(1.0, NaN, NaN), 0);
+ assertEquals(1.0, MathUtil.min(NaN, 1.0, NaN), 0);
+ assertEquals(1.0, MathUtil.min(NaN, NaN, 1.0), 0);
+ assertEquals(1.0, MathUtil.min(2.0, NaN, 1.0), 0);
+ assertEquals(1.0, MathUtil.min(1.0, 2.0, NaN), 0);
+ assertEquals(1.0, MathUtil.min(NaN, 2.0, 1.0), 0);
- assertEquals(3.0, MathUtil.max(1.0, 3.0, 2.0));
- assertEquals(1.0, MathUtil.max(1.0, NaN, NaN));
- assertEquals(1.0, MathUtil.max(NaN, 1.0, NaN));
- assertEquals(1.0, MathUtil.max(NaN, NaN, 1.0));
- assertEquals(2.0, MathUtil.max(2.0, NaN, 1.0));
- assertEquals(2.0, MathUtil.max(1.0, 2.0, NaN));
- assertEquals(2.0, MathUtil.max(NaN, 2.0, 1.0));
+ assertEquals(3.0, MathUtil.max(1.0, 3.0, 2.0), 0);
+ assertEquals(1.0, MathUtil.max(1.0, NaN, NaN), 0);
+ assertEquals(1.0, MathUtil.max(NaN, 1.0, NaN), 0);
+ assertEquals(1.0, MathUtil.max(NaN, NaN, 1.0), 0);
+ assertEquals(2.0, MathUtil.max(2.0, NaN, 1.0), 0);
+ assertEquals(2.0, MathUtil.max(1.0, 2.0, NaN), 0);
+ assertEquals(2.0, MathUtil.max(NaN, 2.0, 1.0), 0);
}
@Test