diff --git a/core/resources/l10n/messages.properties b/core/resources/l10n/messages.properties
index 95b8960d0..99a6ee242 100644
--- a/core/resources/l10n/messages.properties
+++ b/core/resources/l10n/messages.properties
@@ -552,10 +552,14 @@ SimExpPan.border.Vartoexport = Variables to export
SimExpPan.border.Stage = Stage to export
SimExpPan.but.Selectall = Select all
SimExpPan.but.Selectnone = Select none
-SimExpPan.border.Fieldsep = Field separator
+SimExpPan.border.StorageSettings = Storage settings
SimExpPan.lbl.Fieldsepstr = Field separator string:
SimExpPan.lbl.longA1 = The string used to separate the fields in the exported file.
SimExpPan.lbl.longA2 = Use ',' for a Comma Separated Values (CSV) file.
+SimExpPan.lbl.DecimalPlaces = Decimal places:
+SimExpPan.lbl.DecimalPlaces.ttip = The number of decimal places to use for the variables in the exported file.
+SimExpPan.lbl.ExponentialNotation = Use exponential notation
+SimExpPan.lbl.ExponentialNotation.ttip = Whether to use exponential notation for the variables (e.g. 1.5e-4) or not (e.g. 0.00015).
SimExpPan.checkbox.Includesimudesc = Include simulation description
SimExpPan.checkbox.ttip.Includesimudesc = Include a comment at the beginning of the file describing the simulation.
SimExpPan.border.Comments = Comments
diff --git a/core/src/net/sf/openrocket/file/CSVExport.java b/core/src/net/sf/openrocket/file/CSVExport.java
index 7d66dfe42..042ae77c0 100644
--- a/core/src/net/sf/openrocket/file/CSVExport.java
+++ b/core/src/net/sf/openrocket/file/CSVExport.java
@@ -29,6 +29,8 @@ public class CSVExport {
* @param fields the fields to export (in appropriate order).
* @param units the units of the fields.
* @param fieldSeparator the field separator string.
+ * @param decimalPlaces the number of decimal places to use.
+ * @param isExponentialNotation whether to use exponential notation.
* @param commentStarter the comment starting character(s).
* @param simulationComments whether to output general simulation comments.
* @param fieldComments whether to output field comments.
@@ -37,8 +39,9 @@ public class CSVExport {
*/
public static void exportCSV(OutputStream stream, Simulation simulation,
FlightDataBranch branch, FlightDataType[] fields, Unit[] units,
- String fieldSeparator, String commentStarter, boolean simulationComments,
- boolean fieldComments, boolean eventComments) throws IOException {
+ String fieldSeparator, int decimalPlaces, boolean isExponentialNotation,
+ String commentStarter, boolean simulationComments, boolean fieldComments,
+ boolean eventComments) throws IOException {
if (fields.length != units.length) {
throw new IllegalArgumentException("fields and units lengths must be equal " +
@@ -71,7 +74,7 @@ public class CSVExport {
writer.println();
}
- writeData(writer, branch, fields, units, fieldSeparator,
+ writeData(writer, branch, fields, units, fieldSeparator, decimalPlaces, isExponentialNotation,
eventComments, commentStarter);
@@ -87,8 +90,8 @@ public class CSVExport {
}
private static void writeData(PrintWriter writer, FlightDataBranch branch,
- FlightDataType[] fields, Unit[] units, String fieldSeparator, boolean eventComments,
- String commentStarter) {
+ FlightDataType[] fields, Unit[] units, String fieldSeparator, int decimalPlaces, boolean isExponentialNotation,
+ boolean eventComments, String commentStarter) {
// Number of data points
int n = branch.getLength();
@@ -132,12 +135,7 @@ public class CSVExport {
// Store CSV line
for (int i = 0; i < fields.length; i++) {
double value = fieldValues.get(i).get(pos);
- // The latitude and longitude fields need a bit more accurate formatting
- if (fields[i] == FlightDataType.TYPE_LATITUDE || fields[i] == FlightDataType.TYPE_LONGITUDE) {
- writer.print(TextUtil.doubleToString(units[i].toUnit(value), 5));
- } else {
- writer.print(TextUtil.doubleToString(units[i].toUnit(value)));
- }
+ writer.print(TextUtil.doubleToString(units[i].toUnit(value), decimalPlaces, isExponentialNotation));
if (i < fields.length - 1) {
writer.print(fieldSeparator);
diff --git a/core/src/net/sf/openrocket/util/TextUtil.java b/core/src/net/sf/openrocket/util/TextUtil.java
index ffed25a90..c39affaba 100644
--- a/core/src/net/sf/openrocket/util/TextUtil.java
+++ b/core/src/net/sf/openrocket/util/TextUtil.java
@@ -47,9 +47,11 @@ public class TextUtil {
* 5 digits of precision.
*
* @param d the value to present.
+ * @param decimalPlaces the number of decimal places to save the value with.
+ * @param isExponentialNotation if true, the value is presented in exponential notation.
* @return a representation with suitable precision.
*/
- public static final String doubleToString(double d, int decimalPlaces) {
+ public static String doubleToString(double d, int decimalPlaces, boolean isExponentialNotation) {
// Check for special cases
if (MathUtil.equals(d, 0))
return "0";
@@ -68,7 +70,7 @@ public class TextUtil {
double abs = Math.abs(d);
// Small and large values always in exponential notation
- if (abs < 0.001 || abs >= 100000000) {
+ if (isExponentialNotation && (abs < 0.001 || abs >= 100000000)) {
return sign + exponentialFormat(abs);
}
@@ -81,22 +83,37 @@ public class TextUtil {
dec = decimalFormat(abs, decimalPlaces);
}
- if (dec.length() <= exp.length())
+ if (dec.length() <= exp.length() || !isExponentialNotation)
return sign + dec;
else
return sign + exp;
}
+
+ /**
+ * Return a string of the double value with suitable precision for storage.
+ * The string is the shortest representation of the value including at least
+ * 5 digits of precision.
+ * Saves with exponential notation by default.
+ *
+ * @param d the value to present.
+ * @param decimalPlaces the number of decimal places to save the value with.
+ * @return a representation with suitable precision.
+ */
+ public static String doubleToString(double d, int decimalPlaces) {
+ return doubleToString(d, decimalPlaces, true);
+ }
/**
* Return a string of the double value with suitable precision for storage.
* The string is the shortest representation of the value including at least
* 5 digits of precision.
+ * Saves with exponential notation by default & decimal places based on the value's size.
*
* @param d the value to present.
* @return a representation with suitable precision.
*/
- public static final String doubleToString(double d) {
- return doubleToString(d, -1);
+ public static String doubleToString(double d) {
+ return doubleToString(d, -1, true);
}
diff --git a/swing/src/net/sf/openrocket/gui/components/CsvOptionPanel.java b/swing/src/net/sf/openrocket/gui/components/CsvOptionPanel.java
index 5a121d9ad..631992d44 100644
--- a/swing/src/net/sf/openrocket/gui/components/CsvOptionPanel.java
+++ b/swing/src/net/sf/openrocket/gui/components/CsvOptionPanel.java
@@ -5,6 +5,9 @@ import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
+import javax.swing.JSpinner;
+import javax.swing.SpinnerModel;
+import javax.swing.SpinnerNumberModel;
import net.miginfocom.swing.MigLayout;
import net.sf.openrocket.l10n.Translator;
@@ -27,6 +30,8 @@ public class CsvOptionPanel extends JPanel {
private final String baseClassName;
private final JComboBox fieldSeparator;
+ private final JSpinner decimalPlacesSpinner;
+ private final JCheckBox exponentialNotationCheckbox;
private final JCheckBox[] options;
private final JComboBox commentCharacter;
@@ -48,10 +53,11 @@ public class CsvOptionPanel extends JPanel {
// TODO: HIGH: Rename the translation keys
- // Field separator panel
+ // Storage settings panel
panel = new JPanel(new MigLayout("fill"));
- panel.setBorder(BorderFactory.createTitledBorder(trans.get("SimExpPan.border.Fieldsep")));
-
+ panel.setBorder(BorderFactory.createTitledBorder(trans.get("SimExpPan.border.StorageSettings")));
+
+ //// Field separation
label = new JLabel(trans.get("SimExpPan.lbl.Fieldsepstr"));
tip = trans.get("SimExpPan.lbl.longA1") +
trans.get("SimExpPan.lbl.longA2");
@@ -62,8 +68,25 @@ public class CsvOptionPanel extends JPanel {
fieldSeparator.setEditable(true);
fieldSeparator.setSelectedItem(Application.getPreferences().getString(Preferences.EXPORT_FIELD_SEPARATOR, ","));
fieldSeparator.setToolTipText(tip);
- panel.add(fieldSeparator, "growx");
-
+ panel.add(fieldSeparator, "growx, wrap");
+
+ //// Decimal places
+ label = new JLabel(trans.get("SimExpPan.lbl.DecimalPlaces"));
+ label.setToolTipText(trans.get("SimExpPan.lbl.DecimalPlaces.ttip"));
+ panel.add(label, "gapright unrel");
+
+ SpinnerModel dpModel = new SpinnerNumberModel(3, 0, 15, 1);
+ decimalPlacesSpinner = new JSpinner(dpModel);
+ decimalPlacesSpinner.setToolTipText(trans.get("SimExpPan.lbl.DecimalPlaces.ttip"));
+ panel.add(decimalPlacesSpinner, "growx, wrap");
+ // TODO: preferences + action
+
+ //// Exponential notation
+ exponentialNotationCheckbox = new JCheckBox(trans.get("SimExpPan.lbl.ExponentialNotation"));
+ exponentialNotationCheckbox.setToolTipText(trans.get("SimExpPan.lbl.ExponentialNotation.ttip"));
+ panel.add(exponentialNotationCheckbox);
+ // TODO: preferences + action
+
this.add(panel, "growx, wrap unrel");
@@ -104,6 +127,14 @@ public class CsvOptionPanel extends JPanel {
public String getFieldSeparator() {
return fieldSeparator.getSelectedItem().toString();
}
+
+ public int getDecimalPlaces() {
+ return (Integer) decimalPlacesSpinner.getValue();
+ }
+
+ public boolean isExponentialNotation() {
+ return exponentialNotationCheckbox.isSelected();
+ }
public String getCommentCharacter() {
return commentCharacter.getSelectedItem().toString();
diff --git a/swing/src/net/sf/openrocket/gui/components/SimulationExportPanel.java b/swing/src/net/sf/openrocket/gui/components/SimulationExportPanel.java
index 4d2c54bff..9ad4e3820 100644
--- a/swing/src/net/sf/openrocket/gui/components/SimulationExportPanel.java
+++ b/swing/src/net/sf/openrocket/gui/components/SimulationExportPanel.java
@@ -212,6 +212,8 @@ public class SimulationExportPanel extends JPanel {
String commentChar = csvOptions.getCommentCharacter();
String fieldSep = csvOptions.getFieldSeparator();
+ int decimalPlaces = csvOptions.getDecimalPlaces();
+ boolean isExponentialNotation = csvOptions.isExponentialNotation();
boolean simulationComment = csvOptions.getSelectionOption(OPTION_SIMULATION_COMMENTS);
boolean fieldComment = csvOptions.getSelectionOption(OPTION_FIELD_DESCRIPTIONS);
boolean eventComment = csvOptions.getSelectionOption(OPTION_FLIGHT_EVENTS);
@@ -245,8 +247,8 @@ public class SimulationExportPanel extends JPanel {
}
- SaveCSVWorker.export(file, simulation, branch, fieldTypes, fieldUnits, fieldSep,
- commentChar, simulationComment, fieldComment, eventComment,
+ SaveCSVWorker.export(file, simulation, branch, fieldTypes, fieldUnits, fieldSep, decimalPlaces,
+ isExponentialNotation, commentChar, simulationComment, fieldComment, eventComment,
SwingUtilities.getWindowAncestor(this));
}
diff --git a/swing/src/net/sf/openrocket/gui/simulation/SimulationExportPanel.java b/swing/src/net/sf/openrocket/gui/simulation/SimulationExportPanel.java
index f6236b5aa..ad6172ffb 100644
--- a/swing/src/net/sf/openrocket/gui/simulation/SimulationExportPanel.java
+++ b/swing/src/net/sf/openrocket/gui/simulation/SimulationExportPanel.java
@@ -238,6 +238,8 @@ public class SimulationExportPanel extends JPanel {
String commentChar = csvOptions.getCommentCharacter();
String fieldSep = csvOptions.getFieldSeparator();
+ int decimalPlaces = csvOptions.getDecimalPlaces();
+ boolean isExponentialNotation = csvOptions.isExponentialNotation();
boolean simulationComment = csvOptions.getSelectionOption(OPTION_SIMULATION_COMMENTS);
boolean fieldComment = csvOptions.getSelectionOption(OPTION_FIELD_DESCRIPTIONS);
boolean eventComment = csvOptions.getSelectionOption(OPTION_FLIGHT_EVENTS);
@@ -269,10 +271,10 @@ public class SimulationExportPanel extends JPanel {
} else if (fieldSep.equals(TAB)) {
fieldSep = "\t";
}
-
-
- SaveCSVWorker.export(file, simulation, branch, fieldTypes, fieldUnits, fieldSep,
- commentChar, simulationComment, fieldComment, eventComment,
+
+
+ SaveCSVWorker.export(file, simulation, branch, fieldTypes, fieldUnits, fieldSep, decimalPlaces,
+ isExponentialNotation, commentChar, simulationComment, fieldComment, eventComment,
SwingUtilities.getWindowAncestor(this));
return true;
diff --git a/swing/src/net/sf/openrocket/gui/util/SaveCSVWorker.java b/swing/src/net/sf/openrocket/gui/util/SaveCSVWorker.java
index 342d2c17d..06c1e4944 100644
--- a/swing/src/net/sf/openrocket/gui/util/SaveCSVWorker.java
+++ b/swing/src/net/sf/openrocket/gui/util/SaveCSVWorker.java
@@ -23,6 +23,7 @@ import net.sf.openrocket.util.BugException;
public class SaveCSVWorker extends SwingWorker {
private static final int BYTES_PER_FIELD_PER_POINT = 7;
+ private static final int DEFAULT_DECIMAL_PLACES = 3;
private final File file;
private final Simulation simulation;
@@ -30,6 +31,8 @@ public class SaveCSVWorker extends SwingWorker {
private final FlightDataType[] fields;
private final Unit[] units;
private final String fieldSeparator;
+ private final int decimalPlaces;
+ private final boolean isExponentialNotation;
private final String commentStarter;
private final boolean simulationComments;
private final boolean fieldComments;
@@ -37,14 +40,17 @@ public class SaveCSVWorker extends SwingWorker {
public SaveCSVWorker(File file, Simulation simulation, FlightDataBranch branch,
- FlightDataType[] fields, Unit[] units, String fieldSeparator, String commentStarter,
- boolean simulationComments, boolean fieldComments, boolean eventComments) {
+ FlightDataType[] fields, Unit[] units, String fieldSeparator, int decimalPlaces,
+ boolean isExponentialNotation, String commentStarter, boolean simulationComments,
+ boolean fieldComments, boolean eventComments) {
this.file = file;
this.simulation = simulation;
this.branch = branch;
this.fields = fields;
this.units = units;
this.fieldSeparator = fieldSeparator;
+ this.decimalPlaces = decimalPlaces;
+ this.isExponentialNotation = isExponentialNotation;
this.commentStarter = commentStarter;
this.simulationComments = simulationComments;
this.fieldComments = fieldComments;
@@ -72,7 +78,7 @@ public class SaveCSVWorker extends SwingWorker {
};
try {
- CSVExport.exportCSV(os, simulation, branch, fields, units, fieldSeparator,
+ CSVExport.exportCSV(os, simulation, branch, fields, units, fieldSeparator, decimalPlaces, isExponentialNotation,
commentStarter, simulationComments, fieldComments, eventComments);
} finally {
try {
@@ -83,8 +89,14 @@ public class SaveCSVWorker extends SwingWorker {
}
return null;
}
-
-
+
+ public static boolean export(File file, Simulation simulation, FlightDataBranch branch,
+ FlightDataType[] fields, Unit[] units, String fieldSeparator,
+ String commentStarter, boolean simulationComments,
+ boolean fieldComments, boolean eventComments, Window parent) {
+ return export(file, simulation, branch, fields, units, fieldSeparator, DEFAULT_DECIMAL_PLACES, true,
+ commentStarter, simulationComments, fieldComments, eventComments, parent);
+ }
/**
* Exports a CSV file using a progress dialog if necessary.
@@ -92,14 +104,14 @@ public class SaveCSVWorker extends SwingWorker {
* @return true
if the save was successful, false
otherwise.
*/
public static boolean export(File file, Simulation simulation, FlightDataBranch branch,
- FlightDataType[] fields, Unit[] units, String fieldSeparator, String commentStarter,
- boolean simulationComments, boolean fieldComments, boolean eventComments,
- Window parent) {
+ FlightDataType[] fields, Unit[] units, String fieldSeparator, int decimalPlaces,
+ boolean isExponentialNotation, String commentStarter, boolean simulationComments,
+ boolean fieldComments, boolean eventComments, Window parent) {
SaveCSVWorker worker = new SaveCSVWorker(file, simulation, branch, fields, units,
- fieldSeparator, commentStarter, simulationComments, fieldComments,
- eventComments);
+ fieldSeparator, decimalPlaces, isExponentialNotation, commentStarter, simulationComments,
+ fieldComments, eventComments);
if (!SwingWorkerDialog.runWorker(parent, "Exporting flight data",
"Writing " + file.getName() + "...", worker)) {