From 06e702839fdd8fb379621adf82d3f31e4040d320 Mon Sep 17 00:00:00 2001 From: kruland2607 Date: Mon, 4 Feb 2013 14:41:02 -0600 Subject: [PATCH] Implement clamping in while panning. Don't allow panning past the min or max. --- .../openrocket/gui/plot/SimulationPlot.java | 291 ++++++++---------- 1 file changed, 129 insertions(+), 162 deletions(-) diff --git a/core/src/net/sf/openrocket/gui/plot/SimulationPlot.java b/core/src/net/sf/openrocket/gui/plot/SimulationPlot.java index 9b376df8f..991672bc5 100644 --- a/core/src/net/sf/openrocket/gui/plot/SimulationPlot.java +++ b/core/src/net/sf/openrocket/gui/plot/SimulationPlot.java @@ -49,41 +49,41 @@ import org.jfree.ui.RectangleAnchor; import org.jfree.ui.TextAnchor; public class SimulationPlot { - + private static final float PLOT_STROKE_WIDTH = 1.5f; - + private final JFreeChart chart; - + private final PlotConfiguration config; private final Simulation simulation; private final PlotConfiguration filled; private final List eventList; - private final List renderers = new ArrayList(); - + private final List renderers = new ArrayList(); + int branchCount; - - void setShowPoints( boolean showPoints ) { + + void setShowPoints(boolean showPoints) { for (ModifiedXYItemRenderer r : renderers) { r.setBaseShapesVisible(showPoints); } } - - void setShowBranch( int branch ) { + + void setShowBranch(int branch) { XYPlot plot = (XYPlot) chart.getPlot(); int datasetcount = plot.getDatasetCount(); - for( int i =0; i< datasetcount; i++ ) { - int seriescount = ((XYSeriesCollection)plot.getDataset(i)).getSeriesCount(); - XYItemRenderer r = ((XYPlot)chart.getPlot()).getRenderer(i); - for( int j=0; j axes = filled.getAllAxes(); - + // Create the data series for both axes XYSeriesCollection[] data = new XYSeriesCollection[2]; data[0] = new XYSeriesCollection(); data[1] = new XYSeriesCollection(); - + // Get the domain axis type final FlightDataType domainType = filled.getDomainAxisType(); final Unit domainUnit = filled.getDomainAxisUnit(); if (domainType == null) { throw new IllegalArgumentException("Domain axis type not specified."); } - + // Get plot length (ignore trailing NaN's) int typeCount = filled.getTypeCount(); - + // Create the XYSeries objects from the flight data and store into the collections String[] axisLabel = new String[2]; for (int i = 0; i < typeCount; i++) { @@ -131,34 +131,34 @@ public class SimulationPlot { Unit unit = filled.getUnit(i); int axis = filled.getAxis(i); String name = getLabel(type, unit); - + List seriesNames = Util.generateSeriesLabels(simulation); - for( int branchIndex=0; branchIndex plotx = thisBranch.get(domainType); List ploty = thisBranch.get(type); XYSeries series = new XYSeries(seriesNames.get(branchIndex) + ": " + name, false, true); - series.setDescription(thisBranch.getBranchName()+": " + name); + series.setDescription(thisBranch.getBranchName() + ": " + name); int pointCount = plotx.size(); for (int j = 0; j < pointCount; j++) { series.add(domainUnit.toUnit(plotx.get(j)), unit.toUnit(ploty.get(j))); } data[axis].addSeries(series); } - + // Update axis label if (axisLabel[axis] == null) axisLabel[axis] = type.getName(); else axisLabel[axis] += "; " + type.getName(); } - + // Add the data and formatting to the plot XYPlot plot = chart.getXYPlot(); plot.setDomainPannable(true); plot.setRangePannable(true); - + int axisno = 0; for (int i = 0; i < 2; i++) { // Check whether axis has any data @@ -170,7 +170,12 @@ public class SimulationPlot { axis.setLabel(axisLabel[i]); // axis.setRange(axes.get(i).getMinValue(), axes.get(i).getMaxValue()); plot.setRangeAxis(axisno, axis); - + + double domainMin = data[i].getDomainLowerBound(true); + double domainMax = data[i].getDomainUpperBound(true); + + plot.setDomainAxis(new PresetNumberAxis(domainMin, domainMax)); + // Add data and map to the axis plot.setDataset(axisno, data[i]); ModifiedXYItemRenderer r = new ModifiedXYItemRenderer(branchCount); @@ -185,25 +190,25 @@ public class SimulationPlot { axisno++; } } - + plot.getDomainAxis().setLabel(getLabel(domainType, domainUnit)); plot.addDomainMarker(new ValueMarker(0)); plot.addRangeMarker(new ValueMarker(0)); - - - + + + // Create list of events to show (combine event too close to each other) this.eventList = buildEventInfo(); - + // Create the event markers drawDomainMarkers(-1); - + } - + JFreeChart getJFreeChart() { return chart; } - + private String getLabel(FlightDataType type, Unit unit) { String name = type.getName(); if (unit != null && !UnitGroup.UNITS_NONE.contains(unit) && @@ -211,16 +216,16 @@ public class SimulationPlot { name += " (" + unit.getUnit() + ")"; return name; } - - private void drawDomainMarkers( int stage ) { + + private void drawDomainMarkers(int stage) { XYPlot plot = chart.getXYPlot(); - FlightDataBranch mainBranch = simulation.getSimulatedData().getBranch( 0 ); + FlightDataBranch mainBranch = simulation.getSimulatedData().getBranch(0); // Clear existing domain markers plot.clearDomainMarkers(); // Construct domain marker lists collapsing based on time. - + List eventTimes = new ArrayList(); List eventLabels = new ArrayList(); List eventColors = new ArrayList(); @@ -231,25 +236,25 @@ public class SimulationPlot { String text = null; Color color = null; Image image = null; - for( EventDisplayInfo info : eventList ) { - if ( stage >=0 && stage != info.stage ) { + for (EventDisplayInfo info : eventList) { + if (stage >= 0 && stage != info.stage) { continue; } double t = info.time; FlightEvent.Type type = info.event.getType(); - + if (Math.abs(t - prevTime) <= 0.05) { - + if (!typeSet.contains(type)) { text = text + ", " + type.toString(); color = EventGraphics.getEventColor(type); image = EventGraphics.getEventImage(type); typeSet.add(type); } - + } else { - + if (text != null) { eventTimes.add(prevTime); eventLabels.add(text); @@ -263,7 +268,7 @@ public class SimulationPlot { typeSet.clear(); typeSet.add(type); } - + } if (text != null) { eventTimes.add(prevTime); @@ -275,13 +280,13 @@ public class SimulationPlot { // Plot the markers if (config.getDomainAxisType() == FlightDataType.TYPE_TIME) { - + // Domain time is plotted as vertical markers - for ( int i=0; i time = mainBranch.get(FlightDataType.TYPE_TIME); List domain = mainBranch.get(config.getDomainAxisType()); - - LinearInterpolator domainInterpolator = new LinearInterpolator( time, domain ); - - for ( int i=0; i range = mainBranch.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 (filled.getAxis(index) != SimulationPlotPanel.LEFT) { continue; } - + double ycoord = rangeInterpolator.getValue(t); - + // Convert units xcoord = config.getDomainAxisUnit().toUnit(xcoord); ycoord = config.getUnit(index).toUnit(ycoord); - + XYImageAnnotation annotation = new XYImageAnnotation(xcoord, ycoord, image, RectangleAnchor.CENTER); annotation.setToolTipText(event); @@ -335,12 +340,12 @@ public class SimulationPlot { private List buildEventInfo() { ArrayList eventList = new ArrayList(); - - for( int branch=0; branch events = simulation.getSimulatedData().getBranch(branch).getEvents(); - for( FlightEvent event : events ) { + for (FlightEvent event : events) { FlightEvent.Type type = event.getType(); - if ( type != FlightEvent.Type.ALTITUDE && config.isEventActive(type)) { + if (type != FlightEvent.Type.ALTITUDE && config.isEventActive(type)) { EventDisplayInfo info = new EventDisplayInfo(); info.stage = branch; info.time = event.getTime(); @@ -351,11 +356,13 @@ public class SimulationPlot { } Collections.sort(eventList, new Comparator() { - + @Override public int compare(EventDisplayInfo o1, EventDisplayInfo o2) { - if ( o1.time< o2.time) return -1; - if ( o1.time == o2.time)return 0; + if (o1.time < o2.time) + return -1; + if (o1.time == o2.time) + return 0; return 1; } @@ -363,61 +370,8 @@ public class SimulationPlot { return eventList; - /* - double prevTime = -100; - String text = null; - Color color = null; - Image image = null; - for ( int branch=0; branch events = simulation.getSimulatedData().getBranch(branch).getEvents(); - for (int i = 0; i < events.size(); i++) { - FlightEvent event = events.get(i); - double t = event.getTime(); - FlightEvent.Type type = event.getType(); - - if (type != FlightEvent.Type.ALTITUDE && config.isEventActive(type)) { - if (Math.abs(t - prevTime) <= 0.05) { - - if (!typeSet.contains(type)) { - text = text + ", " + type.toString(); - color = EventGraphics.getEventColor(type); - image = EventGraphics.getEventImage(type); - typeSet.add(type); - } - - } else { - - if (text != null) { - EventDisplayInfo info = new EventDisplayInfo(); - info.time = prevTime; - info.event = text; - info.color = color; - info.image = image; - eventList.add(info); - } - prevTime = t; - text = type.toString(); - color = EventGraphics.getEventColor(type); - image = EventGraphics.getEventImage(type); - typeSet.clear(); - typeSet.add(type); - - } - } - } - } - if (text != null) { - EventDisplayInfo info = new EventDisplayInfo(); - info.time = prevTime; - info.event = text; - info.color = color; - info.image = image; - eventList.add(info); - } - return eventList; - */ } - + /** * A modification to the standard renderer that renders the domain marker * labels vertically instead of horizontally. @@ -435,68 +389,68 @@ public class SimulationPlot { * series c stage 1 */ private static class ModifiedXYItemRenderer extends XYLineAndShapeRenderer { - + private final int branchCount; - - private ModifiedXYItemRenderer( int branchCount ) { + + private ModifiedXYItemRenderer(int branchCount) { this.branchCount = branchCount; } - + @Override public Paint lookupSeriesPaint(int series) { - return super.lookupSeriesPaint(series/branchCount); + return super.lookupSeriesPaint(series / branchCount); } - + @Override public Paint lookupSeriesFillPaint(int series) { - return super.lookupSeriesFillPaint(series/branchCount); + return super.lookupSeriesFillPaint(series / branchCount); } - + @Override public Paint lookupSeriesOutlinePaint(int series) { - return super.lookupSeriesOutlinePaint(series/branchCount); + return super.lookupSeriesOutlinePaint(series / branchCount); } - + @Override public Stroke lookupSeriesStroke(int series) { - return super.lookupSeriesStroke(series/branchCount); + return super.lookupSeriesStroke(series / branchCount); } - + @Override public Stroke lookupSeriesOutlineStroke(int series) { - return super.lookupSeriesOutlineStroke(series/branchCount); + return super.lookupSeriesOutlineStroke(series / branchCount); } - + @Override 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 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 public Font lookupLegendTextFont(int series) { - return super.lookupLegendTextFont(series/branchCount); + return super.lookupLegendTextFont(series / branchCount); } - + @Override public Paint lookupLegendTextPaint(int series) { - return super.lookupLegendTextPaint(series/branchCount); + return super.lookupLegendTextPaint(series / branchCount); } - + @Override public void drawDomainMarker(Graphics2D g2, XYPlot plot, ValueAxis domainAxis, Marker marker, Rectangle2D dataArea) { - + if (!(marker instanceof ValueMarker)) { // Use parent for all others super.drawDomainMarker(g2, plot, domainAxis, marker, dataArea); return; } - + /* * Draw the normal marker, but with rotated text. * Copied from the overridden method. @@ -507,9 +461,9 @@ public class SimulationPlot { if (!range.contains(value)) { return; } - + double v = domainAxis.valueToJava2D(value, dataArea, plot.getDomainAxisEdge()); - + PlotOrientation orientation = plot.getOrientation(); Line2D line = null; if (orientation == PlotOrientation.HORIZONTAL) { @@ -517,14 +471,14 @@ public class SimulationPlot { } else { line = new Line2D.Double(v, dataArea.getMinY(), v, dataArea.getMaxY()); } - + final Composite originalComposite = g2.getComposite(); g2.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, marker .getAlpha())); g2.setPaint(marker.getPaint()); g2.setStroke(marker.getStroke()); g2.draw(line); - + String label = marker.getLabel(); RectangleAnchor anchor = marker.getLabelAnchor(); if (label != null) { @@ -533,8 +487,8 @@ public class SimulationPlot { g2.setPaint(marker.getLabelPaint()); Point2D coordinates = calculateDomainMarkerTextAnchorPoint(g2, orientation, dataArea, line.getBounds2D(), marker - .getLabelOffset(), LengthAdjustmentType.EXPAND, anchor); - + .getLabelOffset(), LengthAdjustmentType.EXPAND, anchor); + // Changed: TextAnchor textAnchor = TextAnchor.TOP_RIGHT; TextUtilities.drawRotatedString(label, g2, (float) coordinates.getX() + 2, @@ -543,29 +497,42 @@ public class SimulationPlot { } g2.setComposite(originalComposite); } - + } - + private static class PresetNumberAxis extends NumberAxis { private final double min; private final double max; - + public PresetNumberAxis(double min, double max) { this.min = min; this.max = max; autoAdjustRange(); } - + @Override protected void autoAdjustRange() { this.setRange(min, max); } + + @Override + public void setRange(Range range) { + double lowerValue = range.getLowerBound(); + double upperValue = range.getUpperBound(); + if (lowerValue < min || upperValue > max) { + // Don't blow past the min & max of the range this is important to keep + // panning constrained within the current bounds. + return; + } + super.setRange(new Range(lowerValue, upperValue)); + } + } - + private static class EventDisplayInfo { int stage; double time; FlightEvent event; } - + }