Merge pull request #1240 from SiboVG/issue-1128

[fixes #1128] Fix SimulationPlot range with boosters dataset
This commit is contained in:
Joe Pfeiffer 2022-03-11 09:48:58 -07:00 committed by GitHub
commit 7d643f4787
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 48 additions and 47 deletions

View File

@ -137,6 +137,10 @@ public class FlightData {
public FlightDataBranch getBranch(int n) { public FlightDataBranch getBranch(int n) {
return branches.get(n); return branches.get(n);
} }
public List<FlightDataBranch> getBranches() {
return branches;
}

View File

@ -1,5 +1,6 @@
package net.sf.openrocket.gui.plot; package net.sf.openrocket.gui.plot;
import java.util.Collections;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@ -37,7 +38,7 @@ public class PlotConfiguration implements Cloneable {
config.setEvent(FlightEvent.Type.STAGE_SEPARATION, true); config.setEvent(FlightEvent.Type.STAGE_SEPARATION, true);
config.setEvent(FlightEvent.Type.GROUND_HIT, true); config.setEvent(FlightEvent.Type.GROUND_HIT, true);
config.setEvent(FlightEvent.Type.TUMBLE, true); config.setEvent(FlightEvent.Type.TUMBLE, true);
config.setEvent(FlightEvent.Type.EXCEPTION, true); config.setEvent(FlightEvent.Type.EXCEPTION, true);
configs.add(config); configs.add(config);
//// Total motion vs. time //// Total motion vs. time
@ -52,7 +53,7 @@ public class PlotConfiguration implements Cloneable {
config.setEvent(FlightEvent.Type.STAGE_SEPARATION, true); config.setEvent(FlightEvent.Type.STAGE_SEPARATION, true);
config.setEvent(FlightEvent.Type.GROUND_HIT, true); config.setEvent(FlightEvent.Type.GROUND_HIT, true);
config.setEvent(FlightEvent.Type.TUMBLE, true); config.setEvent(FlightEvent.Type.TUMBLE, true);
config.setEvent(FlightEvent.Type.EXCEPTION, true); config.setEvent(FlightEvent.Type.EXCEPTION, true);
configs.add(config); configs.add(config);
//// Flight side profile //// Flight side profile
@ -65,7 +66,7 @@ public class PlotConfiguration implements Cloneable {
config.setEvent(FlightEvent.Type.STAGE_SEPARATION, true); config.setEvent(FlightEvent.Type.STAGE_SEPARATION, true);
config.setEvent(FlightEvent.Type.GROUND_HIT, true); config.setEvent(FlightEvent.Type.GROUND_HIT, true);
config.setEvent(FlightEvent.Type.TUMBLE, true); config.setEvent(FlightEvent.Type.TUMBLE, true);
config.setEvent(FlightEvent.Type.EXCEPTION, true); config.setEvent(FlightEvent.Type.EXCEPTION, true);
configs.add(config); configs.add(config);
@ -92,7 +93,7 @@ public class PlotConfiguration implements Cloneable {
config.setEvent(FlightEvent.Type.STAGE_SEPARATION, true); config.setEvent(FlightEvent.Type.STAGE_SEPARATION, true);
config.setEvent(FlightEvent.Type.GROUND_HIT, true); config.setEvent(FlightEvent.Type.GROUND_HIT, true);
config.setEvent(FlightEvent.Type.TUMBLE, true); config.setEvent(FlightEvent.Type.TUMBLE, true);
config.setEvent(FlightEvent.Type.EXCEPTION, true); config.setEvent(FlightEvent.Type.EXCEPTION, true);
configs.add(config); configs.add(config);
//// Drag coefficients vs. Mach number //// Drag coefficients vs. Mach number
@ -102,7 +103,7 @@ public class PlotConfiguration implements Cloneable {
config.addPlotDataType(FlightDataType.TYPE_FRICTION_DRAG_COEFF, 0); config.addPlotDataType(FlightDataType.TYPE_FRICTION_DRAG_COEFF, 0);
config.addPlotDataType(FlightDataType.TYPE_BASE_DRAG_COEFF, 0); config.addPlotDataType(FlightDataType.TYPE_BASE_DRAG_COEFF, 0);
config.addPlotDataType(FlightDataType.TYPE_PRESSURE_DRAG_COEFF, 0); config.addPlotDataType(FlightDataType.TYPE_PRESSURE_DRAG_COEFF, 0);
config.setEvent(FlightEvent.Type.EXCEPTION, true); config.setEvent(FlightEvent.Type.EXCEPTION, true);
configs.add(config); configs.add(config);
//// Roll characteristics //// Roll characteristics
@ -119,7 +120,7 @@ public class PlotConfiguration implements Cloneable {
config.setEvent(FlightEvent.Type.STAGE_SEPARATION, true); config.setEvent(FlightEvent.Type.STAGE_SEPARATION, true);
config.setEvent(FlightEvent.Type.GROUND_HIT, true); config.setEvent(FlightEvent.Type.GROUND_HIT, true);
config.setEvent(FlightEvent.Type.TUMBLE, true); config.setEvent(FlightEvent.Type.TUMBLE, true);
config.setEvent(FlightEvent.Type.EXCEPTION, true); config.setEvent(FlightEvent.Type.EXCEPTION, true);
configs.add(config); configs.add(config);
//// Angle of attack and orientation vs. time //// Angle of attack and orientation vs. time
@ -134,7 +135,7 @@ public class PlotConfiguration implements Cloneable {
config.setEvent(FlightEvent.Type.STAGE_SEPARATION, true); config.setEvent(FlightEvent.Type.STAGE_SEPARATION, true);
config.setEvent(FlightEvent.Type.GROUND_HIT, true); config.setEvent(FlightEvent.Type.GROUND_HIT, true);
config.setEvent(FlightEvent.Type.TUMBLE, true); config.setEvent(FlightEvent.Type.TUMBLE, true);
config.setEvent(FlightEvent.Type.EXCEPTION, true); config.setEvent(FlightEvent.Type.EXCEPTION, true);
configs.add(config); configs.add(config);
//// Simulation time step and computation time //// Simulation time step and computation time
@ -148,7 +149,7 @@ public class PlotConfiguration implements Cloneable {
config.setEvent(FlightEvent.Type.STAGE_SEPARATION, true); config.setEvent(FlightEvent.Type.STAGE_SEPARATION, true);
config.setEvent(FlightEvent.Type.GROUND_HIT, true); config.setEvent(FlightEvent.Type.GROUND_HIT, true);
config.setEvent(FlightEvent.Type.TUMBLE, true); config.setEvent(FlightEvent.Type.TUMBLE, true);
config.setEvent(FlightEvent.Type.EXCEPTION, true); config.setEvent(FlightEvent.Type.EXCEPTION, true);
configs.add(config); configs.add(config);
DEFAULT_CONFIGURATIONS = configs.toArray(new PlotConfiguration[0]); DEFAULT_CONFIGURATIONS = configs.toArray(new PlotConfiguration[0]);
@ -424,19 +425,19 @@ public class PlotConfiguration implements Cloneable {
return new Pair<PlotConfiguration, Double>(best, bestValue); return new Pair<PlotConfiguration, Double>(best, bestValue);
} }
protected void fitAxes(FlightDataBranch data) {
this.fitAxes(Collections.singletonList(data));
}
/** /**
* Fit the axes to hold the provided data. All of the plotDataAxis elements must * Fit the axes to hold the provided data. All of the plotDataAxis elements must
* be non-negative. * be non-negative.
* <p> * <p>
* NOTE: This method assumes that only two axes are used. * NOTE: This method assumes that only two axes are used.
*/ */
protected void fitAxes(FlightDataBranch data) { public void fitAxes(List<FlightDataBranch> data) {
// Reset axes // Reset axes
for (Axis a : allAxes) { for (Axis a : allAxes) {
a.reset(); a.reset();
@ -453,13 +454,18 @@ public class PlotConfiguration implements Cloneable {
} }
Axis axis = allAxes.get(index); Axis axis = allAxes.get(index);
double min = unit.toUnit(data.getMinimum(type)); double min = unit.toUnit(data.get(0).getMinimum(type));
double max = unit.toUnit(data.getMaximum(type)); double max = unit.toUnit(data.get(0).getMaximum(type));
for (int j = 1; j < data.size(); j++) {
min = Math.min(min, unit.toUnit(data.get(j).getMinimum(type)));
max = Math.max(max, unit.toUnit(data.get(j).getMaximum(type)));
}
axis.addBound(min); axis.addBound(min);
axis.addBound(max); axis.addBound(max);
} }
// Ensure non-zero (or NaN) range, add a few percent range, include zero if it is close // Ensure non-zero (or NaN) range, add a few percent range, include zero if it is close
for (Axis a : allAxes) { for (Axis a : allAxes) {
if (MathUtil.equals(a.getMinValue(), a.getMaxValue())) { if (MathUtil.equals(a.getMinValue(), a.getMaxValue())) {
@ -491,41 +497,28 @@ public class PlotConfiguration implements Cloneable {
//// Compute common zero //// Compute common zero
// TODO: MEDIUM: This algorithm may require tweaking
double min1 = left.getMinValue(); double min1 = left.getMinValue();
double max1 = left.getMaxValue(); double max1 = left.getMaxValue();
double min2 = right.getMinValue(); double min2 = right.getMinValue();
double max2 = right.getMaxValue(); double max2 = right.getMaxValue();
// Calculate and round scaling factor // Get the zero locations, scaled down to a value from 0 to 1 (0 = bottom of y axis, 1 = top)
double scale = Math.max(left.getRangeLength(), right.getRangeLength()) / double zeroLoc1 = -min1 / left.getRangeLength();
Math.min(left.getRangeLength(), right.getRangeLength()); double zeroLoc2 = -min2 / right.getRangeLength();
//System.out.println("Scale: " + scale); // Scale the right axis
if (zeroLoc1 > zeroLoc2) {
scale = roundScale(scale); min2 = -max2 * (zeroLoc1 / (1 - zeroLoc1));
if (right.getRangeLength() > left.getRangeLength()) { } else {
scale = 1 / scale; max2 = min2 * (-1 / zeroLoc1 + 1);
} }
//System.out.println("Rounded scale: " + scale);
// Scale right axis, enlarge axes if necessary and scale back
min2 *= scale;
max2 *= scale;
min1 = Math.min(min1, min2);
min2 = min1;
max1 = Math.max(max1, max2);
max2 = max1;
min2 /= scale;
max2 /= scale;
// Apply scale // Apply scale
left.addBound(min1); left.addBound(min1);
left.addBound(max1); left.addBound(max1);
right.addBound(min2); right.addBound(min2);
right.addBound(max2); right.addBound(max2);
} }

View File

@ -25,6 +25,7 @@ import net.sf.openrocket.simulation.FlightDataType;
import net.sf.openrocket.simulation.FlightEvent; import net.sf.openrocket.simulation.FlightEvent;
import net.sf.openrocket.unit.Unit; import net.sf.openrocket.unit.Unit;
import net.sf.openrocket.unit.UnitGroup; import net.sf.openrocket.unit.UnitGroup;
import net.sf.openrocket.util.Coordinate;
import net.sf.openrocket.util.LinearInterpolator; import net.sf.openrocket.util.LinearInterpolator;
import net.sf.openrocket.utils.DecimalFormatter; import net.sf.openrocket.utils.DecimalFormatter;
@ -48,7 +49,6 @@ import org.jfree.chart.renderer.xy.XYLineAndShapeRenderer;
import org.jfree.chart.title.LegendTitle; import org.jfree.chart.title.LegendTitle;
import org.jfree.chart.title.TextTitle; import org.jfree.chart.title.TextTitle;
import org.jfree.data.Range; import org.jfree.data.Range;
import org.jfree.data.xy.XYDataItem;
import org.jfree.data.xy.XYDataset; import org.jfree.data.xy.XYDataset;
import org.jfree.data.xy.XYSeries; import org.jfree.data.xy.XYSeries;
import org.jfree.data.xy.XYSeriesCollection; import org.jfree.data.xy.XYSeriesCollection;
@ -134,7 +134,11 @@ public class SimulationPlot {
// Fill the auto-selections based on first branch selected. // Fill the auto-selections based on first branch selected.
FlightDataBranch mainBranch = simulation.getSimulatedData().getBranch(0); FlightDataBranch mainBranch = simulation.getSimulatedData().getBranch(0);
this.filled = config.fillAutoAxes(mainBranch); this.filled = config.fillAutoAxes(mainBranch);
List<Axis> axes = filled.getAllAxes();
// Compute the axes based on the min and max value of all branches
PlotConfiguration plotConfig = filled.clone();
plotConfig.fitAxes(simulation.getSimulatedData().getBranches());
List<Axis> minMaxAxes = plotConfig.getAllAxes();
// Create the data series for both axes // Create the data series for both axes
XYSeriesCollection[] data = new XYSeriesCollection[2]; XYSeriesCollection[] data = new XYSeriesCollection[2];
@ -250,11 +254,11 @@ public class SimulationPlot {
// Check whether axis has any data // Check whether axis has any data
if (data[axisno].getSeriesCount() > 0) { if (data[axisno].getSeriesCount() > 0) {
// Create and set axis // Create and set axis
double min = axes.get(axisno).getMinValue(); double min = minMaxAxes.get(axisno).getMinValue();
double max = axes.get(axisno).getMaxValue(); double max = minMaxAxes.get(axisno).getMaxValue();
NumberAxis axis = new PresetNumberAxis(min, max); NumberAxis axis = new PresetNumberAxis(min, max);
axis.setLabel(axisLabel[axisno]); axis.setLabel(axisLabel[axisno]);
// axis.setRange(axes.get(i).getMinValue(), axes.get(i).getMaxValue());
plot.setRangeAxis(axisno, axis); plot.setRangeAxis(axisno, axis);
axis.setLabelFont(new Font("Dialog", Font.BOLD, 14)); axis.setLabelFont(new Font("Dialog", Font.BOLD, 14));