Improved appearance plot
This commit is contained in:
parent
dcacc40d88
commit
2f2a3a4272
@ -36,7 +36,7 @@ import org.jfree.chart.LegendItemSource;
|
|||||||
import org.jfree.chart.annotations.XYImageAnnotation;
|
import org.jfree.chart.annotations.XYImageAnnotation;
|
||||||
import org.jfree.chart.axis.NumberAxis;
|
import org.jfree.chart.axis.NumberAxis;
|
||||||
import org.jfree.chart.axis.ValueAxis;
|
import org.jfree.chart.axis.ValueAxis;
|
||||||
import org.jfree.chart.block.LineBorder;
|
import org.jfree.chart.block.BlockBorder;
|
||||||
import org.jfree.chart.plot.DefaultDrawingSupplier;
|
import org.jfree.chart.plot.DefaultDrawingSupplier;
|
||||||
import org.jfree.chart.plot.Marker;
|
import org.jfree.chart.plot.Marker;
|
||||||
import org.jfree.chart.plot.PlotOrientation;
|
import org.jfree.chart.plot.PlotOrientation;
|
||||||
@ -63,28 +63,28 @@ import org.jfree.ui.TextAnchor;
|
|||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class SimulationPlot {
|
public class SimulationPlot {
|
||||||
|
|
||||||
private static final float PLOT_STROKE_WIDTH = 1.5f;
|
private static final float PLOT_STROKE_WIDTH = 1.5f;
|
||||||
|
|
||||||
private final JFreeChart chart;
|
private final JFreeChart chart;
|
||||||
|
|
||||||
private final PlotConfiguration config;
|
private final PlotConfiguration config;
|
||||||
private final Simulation simulation;
|
private final Simulation simulation;
|
||||||
private final PlotConfiguration filled;
|
private final PlotConfiguration filled;
|
||||||
|
|
||||||
private final List<EventDisplayInfo> eventList;
|
private final List<EventDisplayInfo> eventList;
|
||||||
private final List<ModifiedXYItemRenderer> renderers = new ArrayList<ModifiedXYItemRenderer>();
|
private final List<ModifiedXYItemRenderer> renderers = new ArrayList<ModifiedXYItemRenderer>();
|
||||||
|
|
||||||
private final LegendItems legendItems;
|
private final LegendItems legendItems;
|
||||||
|
|
||||||
int branchCount;
|
int branchCount;
|
||||||
|
|
||||||
void setShowPoints(boolean showPoints) {
|
void setShowPoints(boolean showPoints) {
|
||||||
for (ModifiedXYItemRenderer r : renderers) {
|
for (ModifiedXYItemRenderer r : renderers) {
|
||||||
r.setBaseShapesVisible(showPoints);
|
r.setBaseShapesVisible(showPoints);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void setShowBranch(int branch) {
|
void setShowBranch(int branch) {
|
||||||
XYPlot plot = (XYPlot) chart.getPlot();
|
XYPlot plot = (XYPlot) chart.getPlot();
|
||||||
int datasetcount = plot.getDatasetCount();
|
int datasetcount = plot.getDatasetCount();
|
||||||
@ -98,12 +98,12 @@ public class SimulationPlot {
|
|||||||
}
|
}
|
||||||
drawDomainMarkers(branch);
|
drawDomainMarkers(branch);
|
||||||
}
|
}
|
||||||
|
|
||||||
SimulationPlot(Simulation simulation, PlotConfiguration config, boolean initialShowPoints) {
|
SimulationPlot(Simulation simulation, PlotConfiguration config, boolean initialShowPoints) {
|
||||||
this.simulation = simulation;
|
this.simulation = simulation;
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.branchCount = simulation.getSimulatedData().getBranchCount();
|
this.branchCount = simulation.getSimulatedData().getBranchCount();
|
||||||
|
|
||||||
this.chart = ChartFactory.createXYLineChart(
|
this.chart = ChartFactory.createXYLineChart(
|
||||||
//// Simulated flight
|
//// Simulated flight
|
||||||
/*title*/simulation.getName(),
|
/*title*/simulation.getName(),
|
||||||
@ -114,40 +114,42 @@ public class SimulationPlot {
|
|||||||
/*legend*/false,
|
/*legend*/false,
|
||||||
/*tooltips*/true,
|
/*tooltips*/true,
|
||||||
/*urls*/false
|
/*urls*/false
|
||||||
);
|
);
|
||||||
|
|
||||||
|
chart.getTitle().setFont(new Font("Dialog", Font.BOLD, 23));
|
||||||
|
chart.setBackgroundPaint(new Color(240, 240, 240));
|
||||||
this.legendItems = new LegendItems();
|
this.legendItems = new LegendItems();
|
||||||
LegendTitle legend = new LegendTitle(legendItems);
|
LegendTitle legend = new LegendTitle(legendItems);
|
||||||
legend.setMargin(new RectangleInsets(1.0, 1.0, 1.0, 1.0));
|
legend.setMargin(new RectangleInsets(1.0, 1.0, 1.0, 1.0));
|
||||||
legend.setFrame(new LineBorder());
|
legend.setFrame(BlockBorder.NONE);
|
||||||
legend.setBackgroundPaint(Color.white);
|
legend.setBackgroundPaint(new Color(240, 240, 240));
|
||||||
legend.setPosition(RectangleEdge.BOTTOM);
|
legend.setPosition(RectangleEdge.BOTTOM);
|
||||||
chart.addSubtitle(legend);
|
chart.addSubtitle(legend);
|
||||||
|
|
||||||
chart.addSubtitle(new TextTitle(config.getName()));
|
chart.addSubtitle(new TextTitle(config.getName()));
|
||||||
|
|
||||||
// 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();
|
List<Axis> axes = filled.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];
|
||||||
data[0] = new XYSeriesCollection();
|
data[0] = new XYSeriesCollection();
|
||||||
data[1] = new XYSeriesCollection();
|
data[1] = new XYSeriesCollection();
|
||||||
|
|
||||||
// Get the domain axis type
|
// Get the domain axis type
|
||||||
final FlightDataType domainType = filled.getDomainAxisType();
|
final FlightDataType domainType = filled.getDomainAxisType();
|
||||||
final Unit domainUnit = filled.getDomainAxisUnit();
|
final Unit domainUnit = filled.getDomainAxisUnit();
|
||||||
if (domainType == null) {
|
if (domainType == null) {
|
||||||
throw new IllegalArgumentException("Domain axis type not specified.");
|
throw new IllegalArgumentException("Domain axis type not specified.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get plot length (ignore trailing NaN's)
|
// Get plot length (ignore trailing NaN's)
|
||||||
int typeCount = filled.getTypeCount();
|
int typeCount = filled.getTypeCount();
|
||||||
|
|
||||||
int seriesCount = 0;
|
int seriesCount = 0;
|
||||||
|
|
||||||
// Create the XYSeries objects from the flight data and store into the collections
|
// Create the XYSeries objects from the flight data and store into the collections
|
||||||
String[] axisLabel = new String[2];
|
String[] axisLabel = new String[2];
|
||||||
for (int i = 0; i < typeCount; i++) {
|
for (int i = 0; i < typeCount; i++) {
|
||||||
@ -156,11 +158,11 @@ public class SimulationPlot {
|
|||||||
Unit unit = filled.getUnit(i);
|
Unit unit = filled.getUnit(i);
|
||||||
int axis = filled.getAxis(i);
|
int axis = filled.getAxis(i);
|
||||||
String name = getLabel(type, unit);
|
String name = getLabel(type, unit);
|
||||||
|
|
||||||
List<String> seriesNames = Util.generateSeriesLabels(simulation);
|
List<String> seriesNames = Util.generateSeriesLabels(simulation);
|
||||||
|
|
||||||
// Populate data for each branch.
|
// Populate data for each branch.
|
||||||
|
|
||||||
// The primary branch (branchIndex = 0) is easy since all the data is copied
|
// The primary branch (branchIndex = 0) is easy since all the data is copied
|
||||||
{
|
{
|
||||||
int branchIndex = 0;
|
int branchIndex = 0;
|
||||||
@ -180,48 +182,57 @@ public class SimulationPlot {
|
|||||||
for (int branchIndex = 1; branchIndex < branchCount; branchIndex++) {
|
for (int branchIndex = 1; branchIndex < branchCount; branchIndex++) {
|
||||||
FlightDataBranch primaryBranch = simulation.getSimulatedData().getBranch(0);
|
FlightDataBranch primaryBranch = simulation.getSimulatedData().getBranch(0);
|
||||||
FlightDataBranch thisBranch = simulation.getSimulatedData().getBranch(branchIndex);
|
FlightDataBranch thisBranch = simulation.getSimulatedData().getBranch(branchIndex);
|
||||||
|
|
||||||
// Get first time index used in secondary branch;
|
// Get first time index used in secondary branch;
|
||||||
double firstSampleTime = thisBranch.get(FlightDataType.TYPE_TIME).get(0);
|
double firstSampleTime = thisBranch.get(FlightDataType.TYPE_TIME).get(0);
|
||||||
|
|
||||||
XYSeries series = new XYSeries(seriesCount++, false, true);
|
XYSeries series = new XYSeries(seriesCount++, false, true);
|
||||||
series.setDescription(thisBranch.getBranchName() + ": " + name);
|
series.setDescription(thisBranch.getBranchName() + ": " + name);
|
||||||
|
|
||||||
// Copy the first points from the primaryBranch.
|
// Copy the first points from the primaryBranch.
|
||||||
List<Double> primaryT = primaryBranch.get(FlightDataType.TYPE_TIME);
|
List<Double> primaryT = primaryBranch.get(FlightDataType.TYPE_TIME);
|
||||||
List<Double> primaryx = primaryBranch.get(domainType);
|
List<Double> primaryx = primaryBranch.get(domainType);
|
||||||
List<Double> primaryy = primaryBranch.get(type);
|
List<Double> primaryy = primaryBranch.get(type);
|
||||||
|
|
||||||
for (int j = 0; j < primaryT.size(); j++) {
|
for (int j = 0; j < primaryT.size(); j++) {
|
||||||
if (primaryT.get(j) >= firstSampleTime) {
|
if (primaryT.get(j) >= firstSampleTime) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
series.add(domainUnit.toUnit(primaryx.get(j)), unit.toUnit(primaryy.get(j)));
|
series.add(domainUnit.toUnit(primaryx.get(j)), unit.toUnit(primaryy.get(j)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now copy all the data from the secondary branch
|
// Now copy all the data from the secondary branch
|
||||||
List<Double> plotx = thisBranch.get(domainType);
|
List<Double> plotx = thisBranch.get(domainType);
|
||||||
List<Double> ploty = thisBranch.get(type);
|
List<Double> ploty = thisBranch.get(type);
|
||||||
|
|
||||||
int pointCount = plotx.size();
|
int pointCount = plotx.size();
|
||||||
for (int j = 0; j < pointCount; j++) {
|
for (int j = 0; j < pointCount; j++) {
|
||||||
series.add(domainUnit.toUnit(plotx.get(j)), unit.toUnit(ploty.get(j)));
|
series.add(domainUnit.toUnit(plotx.get(j)), unit.toUnit(ploty.get(j)));
|
||||||
}
|
}
|
||||||
data[axis].addSeries(series);
|
data[axis].addSeries(series);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update axis label
|
// Update axis label
|
||||||
if (axisLabel[axis] == null)
|
if (axisLabel[axis] == null)
|
||||||
axisLabel[axis] = type.getName();
|
axisLabel[axis] = type.getName();
|
||||||
else
|
else
|
||||||
axisLabel[axis] += "; " + type.getName();
|
axisLabel[axis] += "; " + type.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the data and formatting to the plot
|
// Add the data and formatting to the plot
|
||||||
XYPlot plot = chart.getXYPlot();
|
XYPlot plot = chart.getXYPlot();
|
||||||
plot.setDomainPannable(true);
|
plot.setDomainPannable(true);
|
||||||
plot.setRangePannable(true);
|
plot.setRangePannable(true);
|
||||||
|
|
||||||
|
// Plot appearance
|
||||||
|
plot.setBackgroundPaint(Color.white);
|
||||||
|
plot.setAxisOffset(new RectangleInsets(0, 0, 0, 0));
|
||||||
|
plot.setRangeGridlinesVisible(true);
|
||||||
|
plot.setRangeGridlinePaint(Color.lightGray);
|
||||||
|
|
||||||
|
plot.setDomainGridlinesVisible(true);
|
||||||
|
plot.setDomainGridlinePaint(Color.lightGray);
|
||||||
|
|
||||||
int axisno = 0;
|
int axisno = 0;
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
// Check whether axis has any data
|
// Check whether axis has any data
|
||||||
@ -233,19 +244,30 @@ public class SimulationPlot {
|
|||||||
axis.setLabel(axisLabel[i]);
|
axis.setLabel(axisLabel[i]);
|
||||||
// axis.setRange(axes.get(i).getMinValue(), axes.get(i).getMaxValue());
|
// 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));
|
||||||
|
|
||||||
double domainMin = data[i].getDomainLowerBound(true);
|
double domainMin = data[i].getDomainLowerBound(true);
|
||||||
double domainMax = data[i].getDomainUpperBound(true);
|
double domainMax = data[i].getDomainUpperBound(true);
|
||||||
|
|
||||||
plot.setDomainAxis(new PresetNumberAxis(domainMin, domainMax));
|
plot.setDomainAxis(new PresetNumberAxis(domainMin, domainMax));
|
||||||
|
|
||||||
// Add data and map to the axis
|
// Add data and map to the axis
|
||||||
|
Color[] colors = {new Color(0,114,189), // Colors for data lines
|
||||||
|
new Color(217,83,25),
|
||||||
|
new Color(237,177,32),
|
||||||
|
new Color(126,49,142),
|
||||||
|
new Color(119,172,48),
|
||||||
|
new Color(77,190,238),
|
||||||
|
new Color(162,20,47)};
|
||||||
plot.setDataset(axisno, data[i]);
|
plot.setDataset(axisno, data[i]);
|
||||||
ModifiedXYItemRenderer r = new ModifiedXYItemRenderer(branchCount);
|
ModifiedXYItemRenderer r = new ModifiedXYItemRenderer(branchCount);
|
||||||
renderers.add(r);
|
renderers.add(r);
|
||||||
plot.setRenderer(axisno, r);
|
plot.setRenderer(axisno, r);
|
||||||
r.setBaseShapesVisible(initialShowPoints);
|
r.setBaseShapesVisible(initialShowPoints);
|
||||||
r.setBaseShapesFilled(true);
|
r.setBaseShapesFilled(true);
|
||||||
|
r.setSeriesPaint(0, colors[i]);
|
||||||
|
r.setSeriesPaint(1, colors[i+2]);
|
||||||
|
r.setSeriesPaint(2, colors[i+4]);
|
||||||
for (int j = 0; j < data[i].getSeriesCount(); j++) {
|
for (int j = 0; j < data[i].getSeriesCount(); j++) {
|
||||||
Stroke lineStroke = new BasicStroke(PLOT_STROKE_WIDTH);
|
Stroke lineStroke = new BasicStroke(PLOT_STROKE_WIDTH);
|
||||||
r.setSeriesStroke(j, lineStroke);
|
r.setSeriesStroke(j, lineStroke);
|
||||||
@ -261,30 +283,30 @@ public class SimulationPlot {
|
|||||||
Stroke lineStroke = r.getSeriesStroke(j);
|
Stroke lineStroke = r.getSeriesStroke(j);
|
||||||
this.legendItems.lineStrokes.add(lineStroke);
|
this.legendItems.lineStrokes.add(lineStroke);
|
||||||
}
|
}
|
||||||
|
|
||||||
plot.mapDatasetToRangeAxis(axisno, axisno);
|
plot.mapDatasetToRangeAxis(axisno, axisno);
|
||||||
axisno++;
|
axisno++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plot.getDomainAxis().setLabel(getLabel(domainType, domainUnit));
|
plot.getDomainAxis().setLabel(getLabel(domainType, domainUnit));
|
||||||
plot.addDomainMarker(new ValueMarker(0));
|
plot.addDomainMarker(new ValueMarker(0));
|
||||||
plot.addRangeMarker(new ValueMarker(0));
|
plot.addRangeMarker(new ValueMarker(0));
|
||||||
|
|
||||||
|
plot.getDomainAxis().setLabelFont(new Font("Dialog", Font.BOLD, 14));
|
||||||
|
|
||||||
// Create list of events to show (combine event too close to each other)
|
// Create list of events to show (combine event too close to each other)
|
||||||
this.eventList = buildEventInfo();
|
this.eventList = buildEventInfo();
|
||||||
|
|
||||||
// Create the event markers
|
// Create the event markers
|
||||||
drawDomainMarkers(-1);
|
drawDomainMarkers(-1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JFreeChart getJFreeChart() {
|
JFreeChart getJFreeChart() {
|
||||||
return chart;
|
return chart;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getLabel(FlightDataType type, Unit unit) {
|
private String getLabel(FlightDataType type, Unit unit) {
|
||||||
String name = type.getName();
|
String name = type.getName();
|
||||||
if (unit != null && !UnitGroup.UNITS_NONE.contains(unit) &&
|
if (unit != null && !UnitGroup.UNITS_NONE.contains(unit) &&
|
||||||
@ -292,16 +314,16 @@ public class SimulationPlot {
|
|||||||
name += " (" + unit.getUnit() + ")";
|
name += " (" + unit.getUnit() + ")";
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void drawDomainMarkers(int stage) {
|
private void drawDomainMarkers(int stage) {
|
||||||
XYPlot plot = chart.getXYPlot();
|
XYPlot plot = chart.getXYPlot();
|
||||||
FlightDataBranch mainBranch = simulation.getSimulatedData().getBranch(0);
|
FlightDataBranch mainBranch = simulation.getSimulatedData().getBranch(0);
|
||||||
|
|
||||||
// Clear existing domain markers
|
// Clear existing domain markers
|
||||||
plot.clearDomainMarkers();
|
plot.clearDomainMarkers();
|
||||||
|
|
||||||
// Construct domain marker lists collapsing based on time.
|
// Construct domain marker lists collapsing based on time.
|
||||||
|
|
||||||
List<Double> eventTimes = new ArrayList<Double>();
|
List<Double> eventTimes = new ArrayList<Double>();
|
||||||
List<String> eventLabels = new ArrayList<String>();
|
List<String> eventLabels = new ArrayList<String>();
|
||||||
List<Color> eventColors = new ArrayList<Color>();
|
List<Color> eventColors = new ArrayList<Color>();
|
||||||
@ -316,21 +338,21 @@ public class SimulationPlot {
|
|||||||
if (stage >= 0 && stage != info.stage) {
|
if (stage >= 0 && stage != info.stage) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
double t = info.time;
|
double t = info.time;
|
||||||
FlightEvent.Type type = info.event.getType();
|
FlightEvent.Type type = info.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();
|
text = text + ", " + type.toString();
|
||||||
color = EventGraphics.getEventColor(type);
|
color = EventGraphics.getEventColor(type);
|
||||||
image = EventGraphics.getEventImage(type);
|
image = EventGraphics.getEventImage(type);
|
||||||
typeSet.add(type);
|
typeSet.add(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
if (text != null) {
|
if (text != null) {
|
||||||
eventTimes.add(prevTime);
|
eventTimes.add(prevTime);
|
||||||
eventLabels.add(text);
|
eventLabels.add(text);
|
||||||
@ -344,7 +366,7 @@ public class SimulationPlot {
|
|||||||
typeSet.clear();
|
typeSet.clear();
|
||||||
typeSet.add(type);
|
typeSet.add(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (text != null) {
|
if (text != null) {
|
||||||
eventTimes.add(prevTime);
|
eventTimes.add(prevTime);
|
||||||
@ -353,58 +375,59 @@ public class SimulationPlot {
|
|||||||
eventImages.add(image);
|
eventImages.add(image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Plot the markers
|
// Plot the markers
|
||||||
if (config.getDomainAxisType() == FlightDataType.TYPE_TIME) {
|
if (config.getDomainAxisType() == FlightDataType.TYPE_TIME) {
|
||||||
|
|
||||||
// Domain time is plotted as vertical markers
|
// Domain time is plotted as vertical markers
|
||||||
for (int i = 0; i < eventTimes.size(); i++) {
|
for (int i = 0; i < eventTimes.size(); i++) {
|
||||||
double t = eventTimes.get(i);
|
double t = eventTimes.get(i);
|
||||||
String event = eventLabels.get(i);
|
String event = eventLabels.get(i);
|
||||||
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(event);
|
||||||
m.setPaint(color);
|
m.setPaint(color);
|
||||||
m.setLabelPaint(color);
|
m.setLabelPaint(color);
|
||||||
m.setAlpha(0.7f);
|
m.setAlpha(0.7f);
|
||||||
|
m.setLabelFont(new Font("Dialog", Font.PLAIN, 13));
|
||||||
plot.addDomainMarker(m);
|
plot.addDomainMarker(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Other domains are plotted as image annotations
|
// Other domains are plotted as image annotations
|
||||||
List<Double> time = mainBranch.get(FlightDataType.TYPE_TIME);
|
List<Double> time = mainBranch.get(FlightDataType.TYPE_TIME);
|
||||||
List<Double> domain = mainBranch.get(config.getDomainAxisType());
|
List<Double> domain = mainBranch.get(config.getDomainAxisType());
|
||||||
|
|
||||||
LinearInterpolator domainInterpolator = new LinearInterpolator(time, domain);
|
LinearInterpolator domainInterpolator = new LinearInterpolator(time, domain);
|
||||||
|
|
||||||
for (int i = 0; i < eventTimes.size(); i++) {
|
for (int i = 0; i < eventTimes.size(); i++) {
|
||||||
double t = eventTimes.get(i);
|
double t = eventTimes.get(i);
|
||||||
String event = eventLabels.get(i);
|
String event = eventLabels.get(i);
|
||||||
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.getTypeCount(); index++) {
|
for (int index = 0; index < config.getTypeCount(); index++) {
|
||||||
FlightDataType type = config.getType(index);
|
FlightDataType type = config.getType(index);
|
||||||
List<Double> range = mainBranch.get(type);
|
List<Double> range = mainBranch.get(type);
|
||||||
|
|
||||||
LinearInterpolator rangeInterpolator = new LinearInterpolator(time, range);
|
LinearInterpolator rangeInterpolator = new LinearInterpolator(time, range);
|
||||||
// Image annotations are not supported on the right-side axis
|
// Image annotations are not supported on the right-side axis
|
||||||
// TODO: LOW: Can this be achieved by JFreeChart?
|
// TODO: LOW: Can this be achieved by JFreeChart?
|
||||||
if (filled.getAxis(index) != SimulationPlotPanel.LEFT) {
|
if (filled.getAxis(index) != SimulationPlotPanel.LEFT) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
double ycoord = rangeInterpolator.getValue(t);
|
double ycoord = rangeInterpolator.getValue(t);
|
||||||
|
|
||||||
// Convert units
|
// Convert units
|
||||||
xcoord = config.getDomainAxisUnit().toUnit(xcoord);
|
xcoord = config.getDomainAxisUnit().toUnit(xcoord);
|
||||||
ycoord = config.getUnit(index).toUnit(ycoord);
|
ycoord = config.getUnit(index).toUnit(ycoord);
|
||||||
|
|
||||||
XYImageAnnotation annotation =
|
XYImageAnnotation annotation =
|
||||||
new XYImageAnnotation(xcoord, ycoord, image, RectangleAnchor.CENTER);
|
new XYImageAnnotation(xcoord, ycoord, image, RectangleAnchor.CENTER);
|
||||||
annotation.setToolTipText(event);
|
annotation.setToolTipText(event);
|
||||||
@ -413,10 +436,10 @@ public class SimulationPlot {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<EventDisplayInfo> buildEventInfo() {
|
private List<EventDisplayInfo> buildEventInfo() {
|
||||||
ArrayList<EventDisplayInfo> eventList = new ArrayList<EventDisplayInfo>();
|
ArrayList<EventDisplayInfo> eventList = new ArrayList<EventDisplayInfo>();
|
||||||
|
|
||||||
for (int branch = 0; branch < branchCount; branch++) {
|
for (int branch = 0; branch < branchCount; branch++) {
|
||||||
List<FlightEvent> events = simulation.getSimulatedData().getBranch(branch).getEvents();
|
List<FlightEvent> events = simulation.getSimulatedData().getBranch(branch).getEvents();
|
||||||
for (FlightEvent event : events) {
|
for (FlightEvent event : events) {
|
||||||
@ -430,9 +453,9 @@ public class SimulationPlot {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Collections.sort(eventList, new Comparator<EventDisplayInfo>() {
|
Collections.sort(eventList, new Comparator<EventDisplayInfo>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int compare(EventDisplayInfo o1, EventDisplayInfo o2) {
|
public int compare(EventDisplayInfo o1, EventDisplayInfo o2) {
|
||||||
if (o1.time < o2.time)
|
if (o1.time < o2.time)
|
||||||
@ -441,20 +464,20 @@ public class SimulationPlot {
|
|||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return eventList;
|
return eventList;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class LegendItems implements LegendItemSource {
|
private static class LegendItems implements LegendItemSource {
|
||||||
|
|
||||||
private final List<String> lineLabels = new ArrayList<String>();
|
private final List<String> lineLabels = new ArrayList<String>();
|
||||||
private final List<Paint> linePaints = new ArrayList<Paint>();
|
private final List<Paint> linePaints = new ArrayList<Paint>();
|
||||||
private final List<Stroke> lineStrokes = new ArrayList<Stroke>();
|
private final List<Stroke> lineStrokes = new ArrayList<Stroke>();
|
||||||
private final List<Shape> pointShapes = new ArrayList<Shape>();
|
private final List<Shape> pointShapes = new ArrayList<Shape>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LegendItemCollection getLegendItems() {
|
public LegendItemCollection getLegendItems() {
|
||||||
LegendItemCollection c = new LegendItemCollection();
|
LegendItemCollection c = new LegendItemCollection();
|
||||||
@ -474,30 +497,30 @@ public class SimulationPlot {
|
|||||||
boolean lineVisible = true;
|
boolean lineVisible = true;
|
||||||
Stroke lineStroke = lineStrokes.get(i);
|
Stroke lineStroke = lineStrokes.get(i);
|
||||||
Paint linePaint = linePaints.get(i);
|
Paint linePaint = linePaints.get(i);
|
||||||
|
|
||||||
Shape legendLine = new Line2D.Double(-7.0, 0.0, 7.0, 0.0);
|
Shape legendLine = new Line2D.Double(-7.0, 0.0, 7.0, 0.0);
|
||||||
|
|
||||||
LegendItem result = new LegendItem(label, description, toolTipText,
|
LegendItem result = new LegendItem(label, description, toolTipText,
|
||||||
urlText, shapeIsVisible, shape, shapeIsFilled, fillPaint,
|
urlText, shapeIsVisible, shape, shapeIsFilled, fillPaint,
|
||||||
shapeOutlineVisible, outlinePaint, outlineStroke, lineVisible,
|
shapeOutlineVisible, outlinePaint, outlineStroke, lineVisible,
|
||||||
legendLine, lineStroke, linePaint);
|
legendLine, lineStroke, linePaint);
|
||||||
|
|
||||||
c.add(result);
|
c.add(result);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A modification to the standard renderer that renders the domain marker
|
* A modification to the standard renderer that renders the domain marker
|
||||||
* labels vertically instead of horizontally.
|
* labels vertically instead of horizontally.
|
||||||
*
|
*
|
||||||
* This class is special in that it assumes the data series are added to it
|
* This class is special in that it assumes the data series are added to it
|
||||||
* in a specific order. In particular they must be "by parameter by stage".
|
* in a specific order. In particular they must be "by parameter by stage".
|
||||||
* Assuming that three series are chosen (a, b, c) and the rocket has 2 stages, the
|
* Assuming that three series are chosen (a, b, c) and the rocket has 2 stages, the
|
||||||
* data series are added in this order:
|
* data series are added in this order:
|
||||||
*
|
*
|
||||||
* series a stage 0
|
* series a stage 0
|
||||||
* series a stage 1
|
* series a stage 1
|
||||||
* series b stage 0
|
* series b stage 0
|
||||||
@ -506,68 +529,68 @@ public class SimulationPlot {
|
|||||||
* series c stage 1
|
* series c stage 1
|
||||||
*/
|
*/
|
||||||
private static class ModifiedXYItemRenderer extends XYLineAndShapeRenderer {
|
private static class ModifiedXYItemRenderer extends XYLineAndShapeRenderer {
|
||||||
|
|
||||||
private final int branchCount;
|
private final int branchCount;
|
||||||
|
|
||||||
private ModifiedXYItemRenderer(int branchCount) {
|
private ModifiedXYItemRenderer(int branchCount) {
|
||||||
this.branchCount = branchCount;
|
this.branchCount = branchCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Paint lookupSeriesPaint(int series) {
|
public Paint lookupSeriesPaint(int series) {
|
||||||
return super.lookupSeriesPaint(series / branchCount);
|
return super.lookupSeriesPaint(series / branchCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Paint lookupSeriesFillPaint(int series) {
|
public Paint lookupSeriesFillPaint(int series) {
|
||||||
return super.lookupSeriesFillPaint(series / branchCount);
|
return super.lookupSeriesFillPaint(series / branchCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Paint lookupSeriesOutlinePaint(int series) {
|
public Paint lookupSeriesOutlinePaint(int series) {
|
||||||
return super.lookupSeriesOutlinePaint(series / branchCount);
|
return super.lookupSeriesOutlinePaint(series / branchCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stroke lookupSeriesStroke(int series) {
|
public Stroke lookupSeriesStroke(int series) {
|
||||||
return super.lookupSeriesStroke(series / branchCount);
|
return super.lookupSeriesStroke(series / branchCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stroke lookupSeriesOutlineStroke(int series) {
|
public Stroke lookupSeriesOutlineStroke(int series) {
|
||||||
return super.lookupSeriesOutlineStroke(series / branchCount);
|
return super.lookupSeriesOutlineStroke(series / branchCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Shape lookupSeriesShape(int series) {
|
public Shape lookupSeriesShape(int series) {
|
||||||
return DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE[series % branchCount % DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE.length];
|
return DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE[series % branchCount % DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE.length];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Shape lookupLegendShape(int series) {
|
public Shape lookupLegendShape(int series) {
|
||||||
return DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE[series % branchCount % DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE.length];
|
return DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE[series % branchCount % DefaultDrawingSupplier.DEFAULT_SHAPE_SEQUENCE.length];
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Font lookupLegendTextFont(int series) {
|
public Font lookupLegendTextFont(int series) {
|
||||||
return super.lookupLegendTextFont(series / branchCount);
|
return super.lookupLegendTextFont(series / branchCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Paint lookupLegendTextPaint(int series) {
|
public Paint lookupLegendTextPaint(int series) {
|
||||||
return super.lookupLegendTextPaint(series / branchCount);
|
return super.lookupLegendTextPaint(series / branchCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void drawDomainMarker(Graphics2D g2, XYPlot plot, ValueAxis domainAxis,
|
public void drawDomainMarker(Graphics2D g2, XYPlot plot, ValueAxis domainAxis,
|
||||||
Marker marker, Rectangle2D dataArea) {
|
Marker marker, Rectangle2D dataArea) {
|
||||||
|
|
||||||
if (!(marker instanceof ValueMarker)) {
|
if (!(marker instanceof ValueMarker)) {
|
||||||
// Use parent for all others
|
// Use parent for all others
|
||||||
super.drawDomainMarker(g2, plot, domainAxis, marker, dataArea);
|
super.drawDomainMarker(g2, plot, domainAxis, marker, dataArea);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Draw the normal marker, but with rotated text.
|
* Draw the normal marker, but with rotated text.
|
||||||
* Copied from the overridden method.
|
* Copied from the overridden method.
|
||||||
@ -578,9 +601,9 @@ public class SimulationPlot {
|
|||||||
if (!range.contains(value)) {
|
if (!range.contains(value)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
double v = domainAxis.valueToJava2D(value, dataArea, plot.getDomainAxisEdge());
|
double v = domainAxis.valueToJava2D(value, dataArea, plot.getDomainAxisEdge());
|
||||||
|
|
||||||
PlotOrientation orientation = plot.getOrientation();
|
PlotOrientation orientation = plot.getOrientation();
|
||||||
Line2D line = null;
|
Line2D line = null;
|
||||||
if (orientation == PlotOrientation.HORIZONTAL) {
|
if (orientation == PlotOrientation.HORIZONTAL) {
|
||||||
@ -588,14 +611,14 @@ public class SimulationPlot {
|
|||||||
} else {
|
} else {
|
||||||
line = new Line2D.Double(v, dataArea.getMinY(), v, dataArea.getMaxY());
|
line = new Line2D.Double(v, dataArea.getMinY(), v, dataArea.getMaxY());
|
||||||
}
|
}
|
||||||
|
|
||||||
final Composite originalComposite = g2.getComposite();
|
final Composite originalComposite = g2.getComposite();
|
||||||
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, marker
|
g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, marker
|
||||||
.getAlpha()));
|
.getAlpha()));
|
||||||
g2.setPaint(marker.getPaint());
|
g2.setPaint(marker.getPaint());
|
||||||
g2.setStroke(marker.getStroke());
|
g2.setStroke(marker.getStroke());
|
||||||
g2.draw(line);
|
g2.draw(line);
|
||||||
|
|
||||||
String label = marker.getLabel();
|
String label = marker.getLabel();
|
||||||
RectangleAnchor anchor = marker.getLabelAnchor();
|
RectangleAnchor anchor = marker.getLabelAnchor();
|
||||||
if (label != null) {
|
if (label != null) {
|
||||||
@ -605,7 +628,7 @@ public class SimulationPlot {
|
|||||||
Point2D coordinates = calculateDomainMarkerTextAnchorPoint(g2,
|
Point2D coordinates = calculateDomainMarkerTextAnchorPoint(g2,
|
||||||
orientation, dataArea, line.getBounds2D(), marker
|
orientation, dataArea, line.getBounds2D(), marker
|
||||||
.getLabelOffset(), LengthAdjustmentType.EXPAND, anchor);
|
.getLabelOffset(), LengthAdjustmentType.EXPAND, anchor);
|
||||||
|
|
||||||
// Changed:
|
// Changed:
|
||||||
TextAnchor textAnchor = TextAnchor.TOP_RIGHT;
|
TextAnchor textAnchor = TextAnchor.TOP_RIGHT;
|
||||||
TextUtilities.drawRotatedString(label, g2, (float) coordinates.getX() + 2,
|
TextUtilities.drawRotatedString(label, g2, (float) coordinates.getX() + 2,
|
||||||
@ -614,24 +637,24 @@ public class SimulationPlot {
|
|||||||
}
|
}
|
||||||
g2.setComposite(originalComposite);
|
g2.setComposite(originalComposite);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class PresetNumberAxis extends NumberAxis {
|
private static class PresetNumberAxis extends NumberAxis {
|
||||||
private final double min;
|
private final double min;
|
||||||
private final double max;
|
private final double max;
|
||||||
|
|
||||||
public PresetNumberAxis(double min, double max) {
|
public PresetNumberAxis(double min, double max) {
|
||||||
this.min = min;
|
this.min = min;
|
||||||
this.max = max;
|
this.max = max;
|
||||||
autoAdjustRange();
|
autoAdjustRange();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void autoAdjustRange() {
|
protected void autoAdjustRange() {
|
||||||
this.setRange(min, max);
|
this.setRange(min, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setRange(Range range) {
|
public void setRange(Range range) {
|
||||||
double lowerValue = range.getLowerBound();
|
double lowerValue = range.getLowerBound();
|
||||||
@ -643,13 +666,14 @@ public class SimulationPlot {
|
|||||||
}
|
}
|
||||||
super.setRange(new Range(lowerValue, upperValue));
|
super.setRange(new Range(lowerValue, upperValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class EventDisplayInfo {
|
private static class EventDisplayInfo {
|
||||||
int stage;
|
int stage;
|
||||||
double time;
|
double time;
|
||||||
FlightEvent event;
|
FlightEvent event;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user