Add decimal places and exponential notation option in sim export

This commit is contained in:
SiboVG 2022-06-11 03:40:10 +02:00
parent 7fada6f88c
commit 34279641c9
7 changed files with 104 additions and 38 deletions

View File

@ -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 = <html>The string used to separate the fields in the exported file.<br>
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

View File

@ -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);

View File

@ -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,7 +83,7 @@ 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;
@ -91,12 +93,27 @@ public class TextUtil {
* 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);
}

View File

@ -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<String> fieldSeparator;
private final JSpinner decimalPlacesSpinner;
private final JCheckBox exponentialNotationCheckbox;
private final JCheckBox[] options;
private final JComboBox<String> 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,7 +68,24 @@ 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");
@ -105,6 +128,14 @@ public class CsvOptionPanel extends JPanel {
return fieldSeparator.getSelectedItem().toString();
}
public int getDecimalPlaces() {
return (Integer) decimalPlacesSpinner.getValue();
}
public boolean isExponentialNotation() {
return exponentialNotationCheckbox.isSelected();
}
public String getCommentCharacter() {
return commentCharacter.getSelectedItem().toString();
}

View File

@ -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));
}

View File

@ -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);
@ -271,8 +273,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));
return true;

View File

@ -23,6 +23,7 @@ import net.sf.openrocket.util.BugException;
public class SaveCSVWorker extends SwingWorker<Void, Void> {
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<Void, Void> {
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<Void, Void> {
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<Void, Void> {
};
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 {
@ -84,7 +90,13 @@ public class SaveCSVWorker extends SwingWorker<Void, Void> {
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<Void, Void> {
* @return <code>true</code> if the save was successful, <code>false</code> 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)) {