Add SIM_WARN events to plots.
Note that this required a lot of rewrite to the code adding event icons
This commit is contained in:
parent
67f6aa191a
commit
38a3772eb0
@ -184,6 +184,13 @@ public class FlightEvent implements Comparable<FlightEvent> {
|
|||||||
return this.type.ordinal() - o.type.ordinal();
|
return this.type.ordinal() - o.type.ordinal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean equals(FlightEvent o) {
|
||||||
|
if ((this.type == Type.SIM_WARN) && (o.type == Type.SIM_WARN))
|
||||||
|
return ((Warning)(this.data)).equals((Warning)(o.data));
|
||||||
|
|
||||||
|
return this.equals(0);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "FlightEvent[type=" + type.name() + ",time=" + time + ",source=" + source + ",data=" + String.valueOf(data) + "]";
|
return "FlightEvent[type=" + type.name() + ",time=" + time + ",source=" + source + ",data=" + String.valueOf(data) + "]";
|
||||||
|
@ -101,8 +101,8 @@ public abstract class Plot<T extends DataType, B extends DataBranch<T>, C extend
|
|||||||
|
|
||||||
// Create the data series for both axes
|
// Create the data series for both axes
|
||||||
this.data = new XYSeriesCollection[2];
|
this.data = new XYSeriesCollection[2];
|
||||||
this.data[0] = new XYSeriesCollection();
|
this.data[Util.PlotAxisSelection.LEFT.getValue()] = new XYSeriesCollection();
|
||||||
this.data[1] = new XYSeriesCollection();
|
this.data[Util.PlotAxisSelection.RIGHT.getValue()] = new XYSeriesCollection();
|
||||||
|
|
||||||
// Fill the auto-selections based on first branch selected.
|
// Fill the auto-selections based on first branch selected.
|
||||||
this.filledConfig = config.fillAutoAxes(mainBranch);
|
this.filledConfig = config.fillAutoAxes(mainBranch);
|
||||||
@ -278,7 +278,7 @@ public abstract class Plot<T extends DataType, B extends DataBranch<T>, C extend
|
|||||||
protected List<XYSeries> createSeriesForType(int dataIndex, int startIndex, T type, Unit unit, B branch,
|
protected List<XYSeries> createSeriesForType(int dataIndex, int startIndex, T type, Unit unit, B branch,
|
||||||
int branchIdx, String branchName, String baseName) {
|
int branchIdx, String branchName, String baseName) {
|
||||||
// Default implementation for regular DataBranch
|
// Default implementation for regular DataBranch
|
||||||
MetadataXYSeries series = new MetadataXYSeries(startIndex, false, true, branchIdx, unit.getUnit(), branchName, baseName);
|
MetadataXYSeries series = new MetadataXYSeries(startIndex, false, true, branchIdx, dataIndex, unit.getUnit(), branchName, baseName);
|
||||||
|
|
||||||
List<Double> plotx = branch.get(filledConfig.getDomainAxisType());
|
List<Double> plotx = branch.get(filledConfig.getDomainAxisType());
|
||||||
List<Double> ploty = branch.get(type);
|
List<Double> ploty = branch.get(type);
|
||||||
@ -327,7 +327,7 @@ public abstract class Plot<T extends DataType, B extends DataBranch<T>, C extend
|
|||||||
return formatSampleTooltip(dataName, dataX, unitX, 0, "", sampleIdx, false);
|
return formatSampleTooltip(dataName, dataX, unitX, 0, "", sampleIdx, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getOrdinalEnding(int n) {
|
protected String getOrdinalEnding(int n) {
|
||||||
if (n % 100 == 11 || n % 100 == 12 || n % 100 == 13) return "th";
|
if (n % 100 == 11 || n % 100 == 12 || n % 100 == 13) return "th";
|
||||||
return switch (n % 10) {
|
return switch (n % 10) {
|
||||||
case 1 -> "st";
|
case 1 -> "st";
|
||||||
@ -540,20 +540,27 @@ public abstract class Plot<T extends DataType, B extends DataBranch<T>, C extend
|
|||||||
|
|
||||||
protected static class MetadataXYSeries extends XYSeries {
|
protected static class MetadataXYSeries extends XYSeries {
|
||||||
private final int branchIdx;
|
private final int branchIdx;
|
||||||
|
private final int dataIdx;
|
||||||
private final String unit;
|
private final String unit;
|
||||||
private final String branchName;
|
private final String branchName;
|
||||||
private String baseName;
|
private String baseName;
|
||||||
|
|
||||||
public MetadataXYSeries(Comparable key, boolean autoSort, boolean allowDuplicateXValues, int branchIdx, String unit,
|
public MetadataXYSeries(Comparable key, boolean autoSort, boolean allowDuplicateXValues, int branchIdx, int dataIdx, String unit,
|
||||||
String branchName, String baseName) {
|
String branchName, String baseName) {
|
||||||
super(key, autoSort, allowDuplicateXValues);
|
super(key, autoSort, allowDuplicateXValues);
|
||||||
this.branchIdx = branchIdx;
|
this.branchIdx = branchIdx;
|
||||||
|
this.dataIdx = dataIdx;
|
||||||
this.unit = unit;
|
this.unit = unit;
|
||||||
this.branchName = branchName;
|
this.branchName = branchName;
|
||||||
this.baseName = baseName;
|
this.baseName = baseName;
|
||||||
updateDescription();
|
updateDescription();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public MetadataXYSeries(Comparable key, boolean autoSort, boolean allowDuplicateXValues, int branchIdx, String unit,
|
||||||
|
String branchName, String baseName) {
|
||||||
|
this(key, autoSort, allowDuplicateXValues, branchIdx, -1, unit, branchName, baseName);
|
||||||
|
}
|
||||||
|
|
||||||
public String getUnit() {
|
public String getUnit() {
|
||||||
return unit;
|
return unit;
|
||||||
}
|
}
|
||||||
@ -562,6 +569,10 @@ public abstract class Plot<T extends DataType, B extends DataBranch<T>, C extend
|
|||||||
return branchIdx;
|
return branchIdx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getDataIdx() {
|
||||||
|
return dataIdx;
|
||||||
|
}
|
||||||
|
|
||||||
public String getBranchName() {
|
public String getBranchName() {
|
||||||
return branchName;
|
return branchName;
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import java.awt.Font;
|
|||||||
import java.awt.Image;
|
import java.awt.Image;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
import java.text.DecimalFormat;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
@ -13,11 +14,13 @@ import java.util.Set;
|
|||||||
|
|
||||||
import info.openrocket.core.document.Simulation;
|
import info.openrocket.core.document.Simulation;
|
||||||
import info.openrocket.core.logging.SimulationAbort;
|
import info.openrocket.core.logging.SimulationAbort;
|
||||||
|
import info.openrocket.core.logging.Warning;
|
||||||
import info.openrocket.core.simulation.FlightDataBranch;
|
import info.openrocket.core.simulation.FlightDataBranch;
|
||||||
import info.openrocket.core.simulation.FlightDataType;
|
import info.openrocket.core.simulation.FlightDataType;
|
||||||
import info.openrocket.core.simulation.FlightEvent;
|
import info.openrocket.core.simulation.FlightEvent;
|
||||||
import info.openrocket.core.preferences.ApplicationPreferences;
|
import info.openrocket.core.preferences.ApplicationPreferences;
|
||||||
import info.openrocket.core.util.LinearInterpolator;
|
import info.openrocket.core.util.LinearInterpolator;
|
||||||
|
import info.openrocket.swing.utils.DecimalFormatter;
|
||||||
|
|
||||||
import org.jfree.chart.annotations.XYImageAnnotation;
|
import org.jfree.chart.annotations.XYImageAnnotation;
|
||||||
import org.jfree.chart.annotations.XYTitleAnnotation;
|
import org.jfree.chart.annotations.XYTitleAnnotation;
|
||||||
@ -31,6 +34,8 @@ import org.jfree.chart.ui.VerticalAlignment;
|
|||||||
import org.jfree.chart.ui.RectangleAnchor;
|
import org.jfree.chart.ui.RectangleAnchor;
|
||||||
import org.jfree.chart.ui.RectangleEdge;
|
import org.jfree.chart.ui.RectangleEdge;
|
||||||
import org.jfree.chart.ui.RectangleInsets;
|
import org.jfree.chart.ui.RectangleInsets;
|
||||||
|
import org.jfree.data.xy.XYSeries;
|
||||||
|
import org.jfree.data.xy.XYSeriesCollection;
|
||||||
|
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class SimulationPlot extends Plot<FlightDataType, FlightDataBranch, SimulationPlotConfiguration> {
|
public class SimulationPlot extends Plot<FlightDataType, FlightDataBranch, SimulationPlotConfiguration> {
|
||||||
@ -106,32 +111,30 @@ public class SimulationPlot extends Plot<FlightDataType, FlightDataBranch, Simul
|
|||||||
plot.clearAnnotations();
|
plot.clearAnnotations();
|
||||||
|
|
||||||
// Store flight event information
|
// Store flight event information
|
||||||
List<Double> eventTimes = new ArrayList<>();
|
|
||||||
List<String> eventLabels = new ArrayList<>();
|
|
||||||
List<Color> eventColors = new ArrayList<>();
|
List<Color> eventColors = new ArrayList<>();
|
||||||
List<Image> eventImages = new ArrayList<>();
|
List<Image> eventImages = new ArrayList<>();
|
||||||
|
List<Set<FlightEvent>> eventSets = new ArrayList<>();
|
||||||
|
|
||||||
// Plot the markers
|
// Plot the markers
|
||||||
if (config.getDomainAxisType() == FlightDataType.TYPE_TIME && !preferences.getBoolean(ApplicationPreferences.MARKER_STYLE_ICON, false)) {
|
if (config.getDomainAxisType() == FlightDataType.TYPE_TIME && !preferences.getBoolean(ApplicationPreferences.MARKER_STYLE_ICON, false)) {
|
||||||
fillEventLists(branch, eventTimes, eventLabels, eventColors, eventImages);
|
fillEventLists(branch, eventColors, eventImages, eventSets);
|
||||||
plotVerticalLineMarkers(plot, eventTimes, eventLabels, eventColors);
|
plotVerticalLineMarkers(plot, eventColors, eventSets);
|
||||||
|
|
||||||
} else { // Other domains are plotted as image annotations
|
} else { // Other domains are plotted as image annotations
|
||||||
if (branch == -1) {
|
if (branch == -1) {
|
||||||
// For icon markers, we need to do the plotting separately, otherwise you can have icon markers from e.g.
|
// For icon markers, we need to do the plotting separately, otherwise you can have icon markers from e.g.
|
||||||
// branch 1 be plotted on branch 0
|
// branch 1 be plotted on branch 0
|
||||||
for (int b = 0; b < simulation.getSimulatedData().getBranchCount(); b++) {
|
for (int b = 0; b < simulation.getSimulatedData().getBranchCount(); b++) {
|
||||||
fillEventLists(b, eventTimes, eventLabels, eventColors, eventImages);
|
fillEventLists(b, eventColors, eventImages, eventSets);
|
||||||
dataBranch = simulation.getSimulatedData().getBranch(b);
|
dataBranch = simulation.getSimulatedData().getBranch(b);
|
||||||
plotIconMarkers(plot, dataBranch, eventTimes, eventLabels, eventImages);
|
plotIconMarkers(plot, simulation, b, eventImages, eventSets);
|
||||||
eventTimes.clear();
|
eventSets = new ArrayList<>();
|
||||||
eventLabels.clear();
|
|
||||||
eventColors.clear();
|
eventColors.clear();
|
||||||
eventImages.clear();
|
eventImages.clear();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fillEventLists(branch, eventTimes, eventLabels, eventColors, eventImages);
|
fillEventLists(branch, eventColors, eventImages, eventSets);
|
||||||
plotIconMarkers(plot, dataBranch, eventTimes, eventLabels, eventImages);
|
plotIconMarkers(plot, simulation, branch, eventImages, eventSets);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,72 +163,86 @@ public class SimulationPlot extends Plot<FlightDataType, FlightDataBranch, Simul
|
|||||||
newBranchName.append(" + ").append(allBranches.get(i).getName());
|
newBranchName.append(" + ").append(allBranches.get(i).getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return newBranchName + ": " + ser.getBaseName();
|
return newBranchName + ": " + ser.getBaseName();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void fillEventLists(int branch, List<Double> eventTimes, List<String> eventLabels,
|
private void fillEventLists(int branch,
|
||||||
List<Color> eventColors, List<Image> eventImages) {
|
List<Color> eventColors, List<Image> eventImages, List<Set<FlightEvent>> eventSets) {
|
||||||
|
Set<FlightEvent> eventSet = new HashSet<>();
|
||||||
Set<FlightEvent.Type> typeSet = new HashSet<>();
|
Set<FlightEvent.Type> typeSet = new HashSet<>();
|
||||||
double prevTime = -100;
|
double prevTime = -100;
|
||||||
String text = null;
|
|
||||||
Color color = null;
|
Color color = null;
|
||||||
Image image = null;
|
Image image = null;
|
||||||
int maxOrdinal = -1;
|
int maxOrdinal = -1;
|
||||||
|
|
||||||
for (EventDisplayInfo info : eventList) {
|
for (EventDisplayInfo info : eventList) {
|
||||||
if (branch >= 0 && branch != info.stage) {
|
if (branch >= 0 && branch != info.stage) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
double t = info.time;
|
double t = info.time;
|
||||||
FlightEvent.Type type = info.event.getType();
|
FlightEvent event = info.event;
|
||||||
|
FlightEvent.Type type = event.getType();
|
||||||
|
|
||||||
if (Math.abs(t - prevTime) <= 0.05) {
|
if (Math.abs(t - prevTime) <= 0.05) {
|
||||||
if (!typeSet.contains(type)) {
|
if (!typeSet.contains(type)) {
|
||||||
text = text + ", " + type.toString();
|
|
||||||
if (type.ordinal() > maxOrdinal) {
|
if (type.ordinal() > maxOrdinal) {
|
||||||
color = EventGraphics.getEventColor(info.event);
|
color = EventGraphics.getEventColor(event);
|
||||||
image = EventGraphics.getEventImage(info.event);
|
image = EventGraphics.getEventImage(event);
|
||||||
maxOrdinal = type.ordinal();
|
maxOrdinal = type.ordinal();
|
||||||
}
|
}
|
||||||
typeSet.add(type);
|
typeSet.add(type);
|
||||||
|
eventSet.add(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if (text != null) {
|
if (!eventSet.isEmpty()) {
|
||||||
eventTimes.add(prevTime);
|
|
||||||
eventLabels.add(text);
|
|
||||||
eventColors.add(color);
|
eventColors.add(color);
|
||||||
eventImages.add(image);
|
eventImages.add(image);
|
||||||
|
eventSets.add(eventSet);
|
||||||
}
|
}
|
||||||
prevTime = t;
|
prevTime = t;
|
||||||
text = type.toString();
|
color = EventGraphics.getEventColor(event);
|
||||||
color = EventGraphics.getEventColor(info.event);
|
image = EventGraphics.getEventImage(event);
|
||||||
image = EventGraphics.getEventImage(info.event);
|
|
||||||
typeSet.clear();
|
typeSet.clear();
|
||||||
typeSet.add(type);
|
typeSet.add(type);
|
||||||
|
eventSet = new HashSet<>();
|
||||||
|
eventSet.add(event);
|
||||||
maxOrdinal = type.ordinal();
|
maxOrdinal = type.ordinal();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (text != null) {
|
if (!eventSet.isEmpty()) {
|
||||||
eventTimes.add(prevTime);
|
|
||||||
eventLabels.add(text);
|
|
||||||
eventColors.add(color);
|
eventColors.add(color);
|
||||||
eventImages.add(image);
|
eventImages.add(image);
|
||||||
|
eventSets.add(eventSet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void plotVerticalLineMarkers(XYPlot plot, List<Double> eventTimes, List<String> eventLabels, List<Color> eventColors) {
|
private static String constructEventLabels(Set<FlightEvent> events) {
|
||||||
|
String text = "";
|
||||||
|
|
||||||
|
for (FlightEvent event : events) {
|
||||||
|
if (text != "") {
|
||||||
|
text += ", ";
|
||||||
|
}
|
||||||
|
text += event.getType().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void plotVerticalLineMarkers(XYPlot plot, List<Color> eventColors, List<Set<FlightEvent>> eventSets) {
|
||||||
double markerWidth = 0.01 * plot.getDomainAxis().getUpperBound();
|
double markerWidth = 0.01 * plot.getDomainAxis().getUpperBound();
|
||||||
|
|
||||||
// Domain time is plotted as vertical lines
|
// Domain time is plotted as vertical lines
|
||||||
for (int i = 0; i < eventTimes.size(); i++) {
|
for (int i = 0; i < eventSets.size(); i++) {
|
||||||
double t = eventTimes.get(i);
|
Set<FlightEvent> events = eventSets.get(i);
|
||||||
String event = eventLabels.get(i);
|
double t = ((FlightEvent)events.toArray()[0]).getTime();
|
||||||
|
String eventLabel = constructEventLabels(events);
|
||||||
Color color = eventColors.get(i);
|
Color color = eventColors.get(i);
|
||||||
|
|
||||||
ValueMarker m = new ValueMarker(t);
|
ValueMarker m = new ValueMarker(t);
|
||||||
m.setLabel(event);
|
m.setLabel(eventLabel);
|
||||||
m.setPaint(color);
|
m.setPaint(color);
|
||||||
m.setLabelPaint(color);
|
m.setLabelPaint(color);
|
||||||
m.setAlpha(0.7f);
|
m.setAlpha(0.7f);
|
||||||
@ -238,40 +255,60 @@ public class SimulationPlot extends Plot<FlightDataType, FlightDataBranch, Simul
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void plotIconMarkers(XYPlot plot, FlightDataBranch dataBranch, List<Double> eventTimes,
|
private void plotIconMarkers(XYPlot plot, Simulation simulation, int branch, List<Image> eventImages, List<Set<FlightEvent>> eventSets) {
|
||||||
List<String> eventLabels, List<Image> eventImages) {
|
|
||||||
|
FlightDataBranch dataBranch = simulation.getSimulatedData().getBranch(branch);
|
||||||
|
|
||||||
List<Double> time = dataBranch.get(FlightDataType.TYPE_TIME);
|
List<Double> time = dataBranch.get(FlightDataType.TYPE_TIME);
|
||||||
List<Double> domain = dataBranch.get(config.getDomainAxisType());
|
List<Double> domain = dataBranch.get(config.getDomainAxisType());
|
||||||
|
|
||||||
LinearInterpolator domainInterpolator = new LinearInterpolator(time, domain);
|
LinearInterpolator domainInterpolator = new LinearInterpolator(time, domain);
|
||||||
|
String xName = config.getDomainAxisType().getName();
|
||||||
|
|
||||||
for (int i = 0; i < eventTimes.size(); i++) {
|
List<Axis> minMaxAxes = filledConfig.getAllAxes();
|
||||||
double t = eventTimes.get(i);
|
|
||||||
|
for (int axisno = 0; axisno < data.length; axisno++) {
|
||||||
|
// Image annotations are drawn using the data space defined by the left axis, so
|
||||||
|
// the position of annotations on the right axis need to be mapped to the left axis
|
||||||
|
// dataspace.
|
||||||
|
|
||||||
|
double minLeft = minMaxAxes.get(0).getMinValue();
|
||||||
|
double maxLeft = minMaxAxes.get(0).getMaxValue();
|
||||||
|
|
||||||
|
double minThis = minMaxAxes.get(axisno).getMinValue();
|
||||||
|
double maxThis = minMaxAxes.get(axisno).getMaxValue();
|
||||||
|
|
||||||
|
double slope = (maxLeft - minLeft)/(maxThis - minThis);
|
||||||
|
double intercept = (maxThis * minLeft - maxLeft * minThis)/(maxThis - minThis);
|
||||||
|
|
||||||
|
XYSeriesCollection collection = data[axisno];
|
||||||
|
for (XYSeries series : (List<XYSeries>)(collection.getSeries())) {
|
||||||
|
Plot.MetadataXYSeries metaSeries = (Plot.MetadataXYSeries) series;
|
||||||
|
|
||||||
|
if (metaSeries.getBranchIdx() != branch) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
int dataTypeIdx = metaSeries.getDataIdx();
|
||||||
|
FlightDataType type = config.getType(dataTypeIdx);
|
||||||
|
String yName = type.toString();
|
||||||
|
List<Double> range = dataBranch.get(type);
|
||||||
|
LinearInterpolator rangeInterpolator = new LinearInterpolator(time, range);
|
||||||
|
|
||||||
|
for (int i = 0; i < eventSets.size(); i++) {
|
||||||
|
Set<FlightEvent> events = eventSets.get(i);
|
||||||
|
double t = ((FlightEvent)events.toArray()[0]).getTime();
|
||||||
Image image = eventImages.get(i);
|
Image image = eventImages.get(i);
|
||||||
|
|
||||||
if (image == null) {
|
if (image == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
double xcoord = domainInterpolator.getValue(t);
|
double xcoord = domainInterpolator.getValue(t);
|
||||||
|
|
||||||
for (int index = 0; index < config.getDataCount(); index++) {
|
|
||||||
FlightDataType type = config.getType(index);
|
|
||||||
List<Double> range = dataBranch.get(type);
|
|
||||||
|
|
||||||
LinearInterpolator rangeInterpolator = new LinearInterpolator(time, range);
|
|
||||||
// Image annotations are not supported on the right-side axis
|
|
||||||
// TODO: LOW: Can this be achieved by JFreeChart?
|
|
||||||
if (filledConfig.getAxis(index) != Util.PlotAxisSelection.LEFT.getValue()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
double ycoord = rangeInterpolator.getValue(t);
|
double ycoord = rangeInterpolator.getValue(t);
|
||||||
if (!Double.isNaN(ycoord)) {
|
|
||||||
// Convert units
|
|
||||||
xcoord = config.getDomainAxisUnit().toUnit(xcoord);
|
|
||||||
ycoord = config.getUnit(index).toUnit(ycoord);
|
|
||||||
|
|
||||||
|
xcoord = config.getDomainAxisUnit().toUnit(xcoord);
|
||||||
|
ycoord = config.getUnit(dataTypeIdx).toUnit(ycoord);
|
||||||
|
|
||||||
|
if (!Double.isNaN(ycoord)) {
|
||||||
// Get the sample index of the flight event. Because this can be an interpolation between two samples,
|
// Get the sample index of the flight event. Because this can be an interpolation between two samples,
|
||||||
// take the closest sample.
|
// take the closest sample.
|
||||||
final int sampleIdx;
|
final int sampleIdx;
|
||||||
@ -279,16 +316,71 @@ public class SimulationPlot extends Plot<FlightDataType, FlightDataBranch, Simul
|
|||||||
.min(Comparator.comparingDouble(sample -> Math.abs(sample - t)));
|
.min(Comparator.comparingDouble(sample -> Math.abs(sample - t)));
|
||||||
sampleIdx = closestSample.map(time::indexOf).orElse(-1);
|
sampleIdx = closestSample.map(time::indexOf).orElse(-1);
|
||||||
|
|
||||||
String tooltipText = formatSampleTooltip(eventLabels.get(i), xcoord, config.getDomainAxisUnit().getUnit(), sampleIdx) ;
|
// Convert units
|
||||||
|
String unitY = metaSeries.getUnit();
|
||||||
|
String unitX = config.getDomainAxisUnit().getUnit();
|
||||||
|
|
||||||
|
|
||||||
|
String tooltipText = formatEventTooltip(getNameBasedOnIdxAndSeries(metaSeries, sampleIdx), events,
|
||||||
|
xName, xcoord, unitX,
|
||||||
|
yName, ycoord, unitY,
|
||||||
|
sampleIdx) ;
|
||||||
|
double yloc = slope * ycoord + intercept;
|
||||||
XYImageAnnotation annotation =
|
XYImageAnnotation annotation =
|
||||||
new XYImageAnnotation(xcoord, ycoord, image, RectangleAnchor.CENTER);
|
new XYImageAnnotation(xcoord, yloc, image, RectangleAnchor.CENTER);
|
||||||
annotation.setToolTipText(tooltipText);
|
annotation.setToolTipText(tooltipText);
|
||||||
plot.addAnnotation(annotation);
|
plot.addAnnotation(annotation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String formatEventTooltip(String dataName, Set<FlightEvent> events, String xName, double dataX, String unitX, String yName, double dataY, String unitY, int sampleIdx) {
|
||||||
|
String ord_end = getOrdinalEnding(sampleIdx);
|
||||||
|
|
||||||
|
DecimalFormat df_y = DecimalFormatter.df(dataY, 2, false);
|
||||||
|
DecimalFormat df_x = DecimalFormatter.df(dataX, 2, false);
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
|
||||||
|
// start tooltip
|
||||||
|
sb.append("<html>");
|
||||||
|
|
||||||
|
// Branchname(s)
|
||||||
|
sb.append(String.format("<b><i>%s</i></b><br>", dataName));
|
||||||
|
|
||||||
|
// Any events?
|
||||||
|
if ((null != events) && (events.size() != 0)) {
|
||||||
|
// Pass through and collect any warnings
|
||||||
|
for (FlightEvent event : events) {
|
||||||
|
if (event.getType() == FlightEvent.Type.SIM_WARN) {
|
||||||
|
sb.append("<b><i>Warning: " + ((Warning) event.getData()).toString() + "</b></i><br>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now pass through and collect the other events
|
||||||
|
String eventStr = "";
|
||||||
|
for (FlightEvent event : events) {
|
||||||
|
if (event.getType() != FlightEvent.Type.SIM_WARN) {
|
||||||
|
if (eventStr != "") {
|
||||||
|
eventStr = eventStr + ", ";
|
||||||
|
}
|
||||||
|
eventStr = eventStr + event.getType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sb.append(eventStr + "<br>");
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.append(String.format("%s: %s %s<br>", xName, df_x.format(dataX), unitX));
|
||||||
|
sb.append(String.format("%s: %s %s<br>", yName, df_y.format(dataY), unitY));
|
||||||
|
sb.append(String.format("%d<sup>%s</sup> sample", sampleIdx, ord_end));
|
||||||
|
|
||||||
|
// End tooltip
|
||||||
|
sb.append("</html>");
|
||||||
|
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
private List<EventDisplayInfo> buildEventInfo() {
|
private List<EventDisplayInfo> buildEventInfo() {
|
||||||
ArrayList<EventDisplayInfo> eventList = new ArrayList<>();
|
ArrayList<EventDisplayInfo> eventList = new ArrayList<>();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user