/** * Draws the annotation. * * @param g2 the graphics device. * @param plot the plot. * @param dataArea the data area. * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param rendererIndex the renderer index. * @param info if supplied, this info object will be populated with entity information. */ public void draw( Graphics2D g2, XYPlot plot, Rectangle2D dataArea, ValueAxis domainAxis, ValueAxis rangeAxis, int rendererIndex, PlotRenderingInfo info) { PlotOrientation orientation = plot.getOrientation(); RectangleEdge domainEdge = Plot.resolveDomainAxisLocation(plot.getDomainAxisLocation(), orientation); RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation(plot.getRangeAxisLocation(), orientation); float j2DX = (float) domainAxis.valueToJava2D(this.x, dataArea, domainEdge); float j2DY = (float) rangeAxis.valueToJava2D(this.y, dataArea, rangeEdge); Rectangle2D area = new Rectangle2D.Double( j2DX - this.width / 2.0, j2DY - this.height / 2.0, this.width, this.height); this.drawable.draw(g2, area); String toolTip = getToolTipText(); String url = getURL(); if (toolTip != null || url != null) { addEntity(info, area, rendererIndex, toolTip, url); } }
/** * Draws the item (first pass). This method draws the lines connecting the items. * * @param g2 the graphics device. * @param state the renderer state. * @param dataArea the area within which the data is being drawn. * @param plot the plot (can be used to obtain standard color information etc). * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param dataset the dataset. * @param pass the pass. * @param series the series index (zero-based). * @param item the item index (zero-based). */ protected void drawPrimaryLine( XYItemRendererState state, Graphics2D g2, XYPlot plot, XYDataset dataset, int pass, int series, int item, ValueAxis domainAxis, ValueAxis rangeAxis, Rectangle2D dataArea) { if (item == 0) { return; } // get the data point... double x1 = dataset.getXValue(series, item); double y1 = dataset.getYValue(series, item); if (Double.isNaN(y1) || Double.isNaN(x1)) { return; } double x0 = dataset.getXValue(series, item - 1); double y0 = dataset.getYValue(series, item - 1); if (Double.isNaN(y0) || Double.isNaN(x0)) { return; } RectangleEdge xAxisLocation = plot.getDomainAxisEdge(); RectangleEdge yAxisLocation = plot.getRangeAxisEdge(); double transX0 = domainAxis.valueToJava2D(x0, dataArea, xAxisLocation); double transY0 = rangeAxis.valueToJava2D(y0, dataArea, yAxisLocation); double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation); double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation); // only draw if we have good values if (Double.isNaN(transX0) || Double.isNaN(transY0) || Double.isNaN(transX1) || Double.isNaN(transY1)) { return; } PlotOrientation orientation = plot.getOrientation(); boolean visible; if (orientation == PlotOrientation.HORIZONTAL) { state.workingLine.setLine(transY0, transX0, transY1, transX1); } else if (orientation == PlotOrientation.VERTICAL) { state.workingLine.setLine(transX0, transY0, transX1, transY1); } visible = LineUtilities.clipLine(state.workingLine, dataArea); if (visible) { drawFirstPassShape(g2, pass, series, item, state.workingLine); } }
/** * Draws the annotation. This method is usually called by the {@link XYPlot} class, you shouldn't * need to call it directly. * * @param g2 the graphics device. * @param plot the plot. * @param dataArea the data area. * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param rendererIndex the renderer index. * @param info the plot rendering info. */ public void draw( Graphics2D g2, XYPlot plot, Rectangle2D dataArea, ValueAxis domainAxis, ValueAxis rangeAxis, int rendererIndex, PlotRenderingInfo info) { PlotOrientation orientation = plot.getOrientation(); RectangleEdge domainEdge = Plot.resolveDomainAxisLocation(plot.getDomainAxisLocation(), orientation); RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation(plot.getRangeAxisLocation(), orientation); // compute transform matrix elements via sample points. Assume no // rotation or shear. Rectangle2D bounds = this.shape.getBounds2D(); double x0 = bounds.getMinX(); double x1 = bounds.getMaxX(); double xx0 = domainAxis.valueToJava2D(x0, dataArea, domainEdge); double xx1 = domainAxis.valueToJava2D(x1, dataArea, domainEdge); double m00 = (xx1 - xx0) / (x1 - x0); double m02 = xx0 - x0 * m00; double y0 = bounds.getMaxY(); double y1 = bounds.getMinY(); double yy0 = rangeAxis.valueToJava2D(y0, dataArea, rangeEdge); double yy1 = rangeAxis.valueToJava2D(y1, dataArea, rangeEdge); double m11 = (yy1 - yy0) / (y1 - y0); double m12 = yy0 - m11 * y0; // create transform & transform shape Shape s = null; if (orientation == PlotOrientation.HORIZONTAL) { AffineTransform t1 = new AffineTransform(0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f); AffineTransform t2 = new AffineTransform(m11, 0.0f, 0.0f, m00, m12, m02); s = t1.createTransformedShape(this.shape); s = t2.createTransformedShape(s); } else if (orientation == PlotOrientation.VERTICAL) { AffineTransform t = new AffineTransform(m00, 0, 0, m11, m02, m12); s = t.createTransformedShape(this.shape); } if (this.fillPaint != null) { g2.setPaint(this.fillPaint); g2.fill(s); } if (this.stroke != null && this.outlinePaint != null) { g2.setPaint(this.outlinePaint); g2.setStroke(this.stroke); g2.draw(s); } addEntity(info, s, rendererIndex, getToolTipText(), getURL()); }
/** * Draws the block representing the specified item. * * @param g2 the graphics device. * @param state the state. * @param dataArea the data area. * @param info the plot rendering info. * @param plot the plot. * @param domainAxis the x-axis. * @param rangeAxis the y-axis. * @param dataset the dataset. * @param series the series index. * @param item the item index. * @param crosshairState the crosshair state. * @param pass the pass index. */ public void drawItem( Graphics2D g2, XYItemRendererState state, Rectangle2D dataArea, PlotRenderingInfo info, XYPlot plot, ValueAxis domainAxis, ValueAxis rangeAxis, XYDataset dataset, int series, int item, CrosshairState crosshairState, int pass) { double x = dataset.getXValue(series, item); double y = dataset.getYValue(series, item); double z = 0.0; if (dataset instanceof XYZDataset) { z = ((XYZDataset) dataset).getZValue(series, item); } Paint p = this.paintScale.getPaint(z); double xx0 = domainAxis.valueToJava2D(x + this.xOffset, dataArea, plot.getDomainAxisEdge()); double yy0 = rangeAxis.valueToJava2D(y + this.yOffset, dataArea, plot.getRangeAxisEdge()); double xx1 = domainAxis.valueToJava2D( x + this.blockWidth + this.xOffset, dataArea, plot.getDomainAxisEdge()); double yy1 = rangeAxis.valueToJava2D( y + this.blockHeight + this.yOffset, dataArea, plot.getRangeAxisEdge()); Rectangle2D block; PlotOrientation orientation = plot.getOrientation(); if (orientation.equals(PlotOrientation.HORIZONTAL)) { block = new Rectangle2D.Double( Math.min(yy0, yy1), Math.min(xx0, xx1), Math.abs(yy1 - yy0), Math.abs(xx0 - xx1)); } else { block = new Rectangle2D.Double( Math.min(xx0, xx1), Math.min(yy0, yy1), Math.abs(xx1 - xx0), Math.abs(yy1 - yy0)); } g2.setPaint(p); g2.fill(block); g2.setStroke(new BasicStroke(1.0f)); g2.draw(block); EntityCollection entities = state.getEntityCollection(); if (entities != null) { addEntity(entities, block, dataset, series, item, 0.0, 0.0); } }
/** * Draws a range marker. * * @param g2 the graphics device. * @param plot the plot. * @param axis the value axis. * @param marker the marker. * @param dataArea the area for plotting data (not including 3D effect). */ @Override public void drawRangeMarker( Graphics2D g2, CategoryPlot plot, ValueAxis axis, Marker marker, Rectangle2D dataArea) { Rectangle2D adjusted = new Rectangle2D.Double( dataArea.getX(), dataArea.getY() + getYOffset(), dataArea.getWidth() - getXOffset(), dataArea.getHeight() - getYOffset()); if (marker instanceof ValueMarker) { ValueMarker vm = (ValueMarker) marker; double value = vm.getValue(); Range range = axis.getRange(); if (!range.contains(value)) { return; } GeneralPath path = null; PlotOrientation orientation = plot.getOrientation(); if (orientation == PlotOrientation.HORIZONTAL) { float x = (float) axis.valueToJava2D(value, adjusted, plot.getRangeAxisEdge()); float y = (float) adjusted.getMaxY(); path = new GeneralPath(); path.moveTo(x, y); path.lineTo((float) (x + getXOffset()), y - (float) getYOffset()); path.lineTo((float) (x + getXOffset()), (float) (adjusted.getMinY() - getYOffset())); path.lineTo(x, (float) adjusted.getMinY()); path.closePath(); } else if (orientation == PlotOrientation.VERTICAL) { float y = (float) axis.valueToJava2D(value, adjusted, plot.getRangeAxisEdge()); float x = (float) dataArea.getX(); path = new GeneralPath(); path.moveTo(x, y); path.lineTo(x + (float) this.xOffset, y - (float) this.yOffset); path.lineTo((float) (adjusted.getMaxX() + this.xOffset), y - (float) this.yOffset); path.lineTo((float) (adjusted.getMaxX()), y); path.closePath(); } g2.setPaint(marker.getPaint()); g2.fill(path); g2.setPaint(marker.getOutlinePaint()); g2.draw(path); } else { super.drawRangeMarker(g2, plot, axis, marker, adjusted); // TODO: draw the interval marker with a 3D effect } }
/** * Draws a grid line against the range axis. * * @param g2 the graphics device. * @param plot the plot. * @param axis the value axis. * @param dataArea the area for plotting data (not yet adjusted for any 3D effect). * @param value the value at which the grid line should be drawn. */ public void drawRangeGridline( Graphics2D g2, CategoryPlot plot, ValueAxis axis, Rectangle2D dataArea, double value) { Range range = axis.getRange(); if (!range.contains(value)) { return; } PlotOrientation orientation = plot.getOrientation(); double v = axis.valueToJava2D(value, dataArea, plot.getRangeAxisEdge()); Line2D line = null; if (orientation == PlotOrientation.HORIZONTAL) { line = new Line2D.Double(v, dataArea.getMinY(), v, dataArea.getMaxY()); } else if (orientation == PlotOrientation.VERTICAL) { line = new Line2D.Double(dataArea.getMinX(), v, dataArea.getMaxX(), v); } Paint paint = plot.getRangeGridlinePaint(); if (paint == null) { paint = CategoryPlot.DEFAULT_GRIDLINE_PAINT; } g2.setPaint(paint); Stroke stroke = plot.getRangeGridlineStroke(); if (stroke == null) { stroke = CategoryPlot.DEFAULT_GRIDLINE_STROKE; } g2.setStroke(stroke); g2.draw(line); }
/** * Draws the item (first pass). This method draws the lines connecting the items. Instead of * drawing separate lines, a GeneralPath is constructed and drawn at the end of the series * painting. * * @param g2 the graphics device. * @param state the renderer state. * @param plot the plot (can be used to obtain standard color information etc). * @param dataset the dataset. * @param pass the pass. * @param series the series index (zero-based). * @param item the item index (zero-based). * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param dataArea the area within which the data is being drawn. */ protected void drawPrimaryLineAsPath( XYItemRendererState state, Graphics2D g2, XYPlot plot, XYDataset dataset, int pass, int series, int item, ValueAxis domainAxis, ValueAxis rangeAxis, Rectangle2D dataArea) { RectangleEdge xAxisLocation = plot.getDomainAxisEdge(); RectangleEdge yAxisLocation = plot.getRangeAxisEdge(); // get the data point... double x1 = dataset.getXValue(series, item); double y1 = dataset.getYValue(series, item); double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation); double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation); State s = (State) state; // update path to reflect latest point if (!Double.isNaN(transX1) && !Double.isNaN(transY1)) { float x = (float) transX1; float y = (float) transY1; PlotOrientation orientation = plot.getOrientation(); if (orientation == PlotOrientation.HORIZONTAL) { x = (float) transY1; y = (float) transX1; } if (s.isLastPointGood()) { s.seriesPath.lineTo(x, y); } else { s.seriesPath.moveTo(x, y); } s.setLastPointGood(true); } else { s.setLastPointGood(false); } // if this is the last item, draw the path ... if (item == s.getLastItemIndex()) { // draw path drawFirstPassShape(g2, pass, series, item, s.seriesPath); } }
/** * Draws a line perpendicular to the range axis. * * @param g2 the graphics device. * @param plot the plot. * @param axis the value axis. * @param dataArea the area for plotting data (not yet adjusted for any 3D effect). * @param value the value at which the grid line should be drawn. * @param paint the paint. * @param stroke the stroke. * @see #drawRangeGridline * @since 1.0.13 */ public void drawRangeLine( Graphics2D g2, CategoryPlot plot, ValueAxis axis, Rectangle2D dataArea, double value, Paint paint, Stroke stroke) { Range range = axis.getRange(); if (!range.contains(value)) { return; } Rectangle2D adjusted = new Rectangle2D.Double( dataArea.getX(), dataArea.getY() + getYOffset(), dataArea.getWidth() - getXOffset(), dataArea.getHeight() - getYOffset()); Line2D line1 = null; Line2D line2 = null; PlotOrientation orientation = plot.getOrientation(); if (orientation == PlotOrientation.HORIZONTAL) { double x0 = axis.valueToJava2D(value, adjusted, plot.getRangeAxisEdge()); double x1 = x0 + getXOffset(); double y0 = dataArea.getMaxY(); double y1 = y0 - getYOffset(); double y2 = dataArea.getMinY(); line1 = new Line2D.Double(x0, y0, x1, y1); line2 = new Line2D.Double(x1, y1, x1, y2); } else if (orientation == PlotOrientation.VERTICAL) { double y0 = axis.valueToJava2D(value, adjusted, plot.getRangeAxisEdge()); double y1 = y0 - getYOffset(); double x0 = dataArea.getMinX(); double x1 = x0 + getXOffset(); double x2 = dataArea.getMaxX(); line1 = new Line2D.Double(x0, y0, x1, y1); line2 = new Line2D.Double(x1, y1, x2, y1); } g2.setPaint(paint); g2.setStroke(stroke); g2.draw(line1); g2.draw(line2); }
/** * Initialises the renderer and returns a state object that should be passed to all subsequent * calls to the drawItem() method. Here we calculate the Java2D y-coordinate for zero, since all * the bars have their bases fixed at zero. * * @param g2 the graphics device. * @param dataArea the area inside the axes. * @param plot the plot. * @param dataset the data. * @param info an optional info collection object to return data back to the caller. * @return A state object. */ @Override public XYItemRendererState initialise( Graphics2D g2, Rectangle2D dataArea, XYPlot plot, XYDataset dataset, PlotRenderingInfo info) { XYBarRendererState state = new XYBarRendererState(info); ValueAxis rangeAxis = plot.getRangeAxisForDataset(plot.indexOf(dataset)); state.setG2Base(rangeAxis.valueToJava2D(this.base, dataArea, plot.getRangeAxisEdge())); return state; }
/** * Draws the visual representation of a single data item. * * @param g2 the graphics device. * @param state the renderer state. * @param dataArea the area within which the data is being drawn. * @param info collects information about the drawing. * @param plot the plot (can be used to obtain standard color information etc). * @param domainAxis the domain (horizontal) axis. * @param rangeAxis the range (vertical) axis. * @param dataset the dataset. * @param series the series index (zero-based). * @param item the item index (zero-based). * @param crosshairState crosshair information for the plot (<code>null</code> permitted). * @param pass the pass index. */ public void drawItem( Graphics2D g2, XYItemRendererState state, Rectangle2D dataArea, PlotRenderingInfo info, XYPlot plot, ValueAxis domainAxis, ValueAxis rangeAxis, XYDataset dataset, int series, int item, CrosshairState crosshairState, int pass) { // get the data point... double x = dataset.getXValue(series, item); double y = dataset.getYValue(series, item); double adjx = (this.dotWidth - 1) / 2.0; double adjy = (this.dotHeight - 1) / 2.0; if (!Double.isNaN(y)) { RectangleEdge xAxisLocation = plot.getDomainAxisEdge(); RectangleEdge yAxisLocation = plot.getRangeAxisEdge(); double transX = domainAxis.valueToJava2D(x, dataArea, xAxisLocation) - adjx; double transY = rangeAxis.valueToJava2D(y, dataArea, yAxisLocation) - adjy; g2.setPaint(getItemPaint(series, item)); PlotOrientation orientation = plot.getOrientation(); if (orientation == PlotOrientation.HORIZONTAL) { g2.fillRect((int) transY, (int) transX, this.dotHeight, this.dotWidth); } else if (orientation == PlotOrientation.VERTICAL) { g2.fillRect((int) transX, (int) transY, this.dotWidth, this.dotHeight); } int domainAxisIndex = plot.getDomainAxisIndex(domainAxis); int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis); updateCrosshairValues( crosshairState, x, y, domainAxisIndex, rangeAxisIndex, transX, transY, orientation); } }
/** * Draws the annotation. This method is called by the {@link XYPlot} class, you won't normally * need to call it yourself. * * @param g2 the graphics device. * @param plot the plot. * @param dataArea the data area. * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param rendererIndex the renderer index. * @param info if supplied, this info object will be populated with entity information. */ public void draw( Graphics2D g2, XYPlot plot, Rectangle2D dataArea, ValueAxis domainAxis, ValueAxis rangeAxis, int rendererIndex, PlotRenderingInfo info) { PlotOrientation orientation = plot.getOrientation(); RectangleEdge domainEdge = Plot.resolveDomainAxisLocation(plot.getDomainAxisLocation(), orientation); RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation(plot.getRangeAxisLocation(), orientation); float j2DX1 = 0.0f; float j2DX2 = 0.0f; float j2DY1 = 0.0f; float j2DY2 = 0.0f; if (orientation == PlotOrientation.VERTICAL) { j2DX1 = (float) domainAxis.valueToJava2D(this.x1, dataArea, domainEdge); j2DY1 = (float) rangeAxis.valueToJava2D(this.y1, dataArea, rangeEdge); j2DX2 = (float) domainAxis.valueToJava2D(this.x2, dataArea, domainEdge); j2DY2 = (float) rangeAxis.valueToJava2D(this.y2, dataArea, rangeEdge); } else if (orientation == PlotOrientation.HORIZONTAL) { j2DY1 = (float) domainAxis.valueToJava2D(this.x1, dataArea, domainEdge); j2DX1 = (float) rangeAxis.valueToJava2D(this.y1, dataArea, rangeEdge); j2DY2 = (float) domainAxis.valueToJava2D(this.x2, dataArea, domainEdge); j2DX2 = (float) rangeAxis.valueToJava2D(this.y2, dataArea, rangeEdge); } g2.setPaint(this.paint); g2.setStroke(this.stroke); Line2D line = new Line2D.Float(j2DX1, j2DY1, j2DX2, j2DY2); // line is clipped to avoid JRE bug 6574155, for more info // see JFreeChart bug 2221495 boolean visible = LineUtilities.clipLine(line, dataArea); if (visible) { g2.draw(line); } String toolTip = getToolTipText(); String url = getURL(); if (toolTip != null || url != null) { addEntity(info, ShapeUtilities.createLineRegion(line, 1.0f), rendererIndex, toolTip, url); } }
/** * Draw a single data item. * * @param g2 the graphics device. * @param state the renderer state. * @param dataArea the area in which the data is drawn. * @param plot the plot. * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param dataset the dataset (a {@link StatisticalCategoryDataset} is required). * @param row the row index (zero-based). * @param column the column index (zero-based). * @param pass the pass. */ @Override public void drawItem( Graphics2D g2, CategoryItemRendererState state, Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis, ValueAxis rangeAxis, CategoryDataset dataset, int row, int column, int pass) { // do nothing if item is not visible if (!getItemVisible(row, column)) { return; } // if the dataset is not a StatisticalCategoryDataset then just revert // to the superclass (LineAndShapeRenderer) behaviour... if (!(dataset instanceof StatisticalCategoryDataset)) { super.drawItem(g2, state, dataArea, plot, domainAxis, rangeAxis, dataset, row, column, pass); return; } int visibleRow = state.getVisibleSeriesIndex(row); if (visibleRow < 0) { return; } int visibleRowCount = state.getVisibleSeriesCount(); StatisticalCategoryDataset statDataset = (StatisticalCategoryDataset) dataset; Number meanValue = statDataset.getMeanValue(row, column); if (meanValue == null) { return; } PlotOrientation orientation = plot.getOrientation(); // current data point... double x1; if (getUseSeriesOffset()) { x1 = domainAxis.getCategorySeriesMiddle( column, dataset.getColumnCount(), visibleRow, visibleRowCount, getItemMargin(), dataArea, plot.getDomainAxisEdge()); } else { x1 = domainAxis.getCategoryMiddle( column, getColumnCount(), dataArea, plot.getDomainAxisEdge()); } double y1 = rangeAxis.valueToJava2D(meanValue.doubleValue(), dataArea, plot.getRangeAxisEdge()); // draw the standard deviation lines *before* the shapes (if they're // visible) - it looks better if the shape fill colour is different to // the line colour Number sdv = statDataset.getStdDevValue(row, column); if (pass == 1 && sdv != null) { // standard deviation lines RectangleEdge yAxisLocation = plot.getRangeAxisEdge(); double valueDelta = sdv.doubleValue(); double highVal, lowVal; if ((meanValue.doubleValue() + valueDelta) > rangeAxis.getRange().getUpperBound()) { highVal = rangeAxis.valueToJava2D(rangeAxis.getRange().getUpperBound(), dataArea, yAxisLocation); } else { highVal = rangeAxis.valueToJava2D(meanValue.doubleValue() + valueDelta, dataArea, yAxisLocation); } if ((meanValue.doubleValue() + valueDelta) < rangeAxis.getRange().getLowerBound()) { lowVal = rangeAxis.valueToJava2D(rangeAxis.getRange().getLowerBound(), dataArea, yAxisLocation); } else { lowVal = rangeAxis.valueToJava2D(meanValue.doubleValue() - valueDelta, dataArea, yAxisLocation); } if (this.errorIndicatorPaint != null) { g2.setPaint(this.errorIndicatorPaint); } else { g2.setPaint(getItemPaint(row, column)); } if (this.errorIndicatorStroke != null) { g2.setStroke(this.errorIndicatorStroke); } else { g2.setStroke(getItemOutlineStroke(row, column)); } Line2D line = new Line2D.Double(); if (orientation == PlotOrientation.HORIZONTAL) { line.setLine(lowVal, x1, highVal, x1); g2.draw(line); line.setLine(lowVal, x1 - 5.0d, lowVal, x1 + 5.0d); g2.draw(line); line.setLine(highVal, x1 - 5.0d, highVal, x1 + 5.0d); g2.draw(line); } else { // PlotOrientation.VERTICAL line.setLine(x1, lowVal, x1, highVal); g2.draw(line); line.setLine(x1 - 5.0d, highVal, x1 + 5.0d, highVal); g2.draw(line); line.setLine(x1 - 5.0d, lowVal, x1 + 5.0d, lowVal); g2.draw(line); } } Shape hotspot = null; if (pass == 1 && getItemShapeVisible(row, column)) { Shape shape = getItemShape(row, column); if (orientation == PlotOrientation.HORIZONTAL) { shape = ShapeUtilities.createTranslatedShape(shape, y1, x1); } else if (orientation == PlotOrientation.VERTICAL) { shape = ShapeUtilities.createTranslatedShape(shape, x1, y1); } hotspot = shape; if (getItemShapeFilled(row, column)) { if (getUseFillPaint()) { g2.setPaint(getItemFillPaint(row, column)); } else { g2.setPaint(getItemPaint(row, column)); } g2.fill(shape); } if (getDrawOutlines()) { if (getUseOutlinePaint()) { g2.setPaint(getItemOutlinePaint(row, column)); } else { g2.setPaint(getItemPaint(row, column)); } g2.setStroke(getItemOutlineStroke(row, column)); g2.draw(shape); } // draw the item label if there is one... if (isItemLabelVisible(row, column)) { if (orientation == PlotOrientation.HORIZONTAL) { drawItemLabel( g2, orientation, dataset, row, column, y1, x1, (meanValue.doubleValue() < 0.0)); } else if (orientation == PlotOrientation.VERTICAL) { drawItemLabel( g2, orientation, dataset, row, column, x1, y1, (meanValue.doubleValue() < 0.0)); } } } if (pass == 0 && getItemLineVisible(row, column)) { if (column != 0) { Number previousValue = statDataset.getValue(row, column - 1); if (previousValue != null) { // previous data point... double previous = previousValue.doubleValue(); double x0; if (getUseSeriesOffset()) { x0 = domainAxis.getCategorySeriesMiddle( column - 1, dataset.getColumnCount(), visibleRow, visibleRowCount, getItemMargin(), dataArea, plot.getDomainAxisEdge()); } else { x0 = domainAxis.getCategoryMiddle( column - 1, getColumnCount(), dataArea, plot.getDomainAxisEdge()); } double y0 = rangeAxis.valueToJava2D(previous, dataArea, plot.getRangeAxisEdge()); Line2D line = null; if (orientation == PlotOrientation.HORIZONTAL) { line = new Line2D.Double(y0, x0, y1, x1); } else if (orientation == PlotOrientation.VERTICAL) { line = new Line2D.Double(x0, y0, x1, y1); } g2.setPaint(getItemPaint(row, column)); g2.setStroke(getItemStroke(row, column)); g2.draw(line); } } } if (pass == 1) { // add an item entity, if this information is being collected EntityCollection entities = state.getEntityCollection(); if (entities != null) { addEntity(entities, hotspot, dataset, row, column, x1, y1); } } }
/** * Draws an item for a plot with a vertical orientation. * * @param g2 the graphics device. * @param state the renderer state. * @param dataArea the data area. * @param plot the plot. * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param dataset the data. * @param visibleRow the visible row index. * @param row the row index (zero-based). * @param column the column index (zero-based). */ protected void drawVerticalItem( Graphics2D g2, CategoryItemRendererState state, Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis, ValueAxis rangeAxis, StatisticalCategoryDataset dataset, int visibleRow, int row, int column) { // BAR X double rectX = calculateBarW0( plot, PlotOrientation.VERTICAL, dataArea, domainAxis, state, visibleRow, column); // BAR Y Number meanValue = dataset.getMeanValue(row, column); if (meanValue == null) { return; } double value = meanValue.doubleValue(); double base = 0.0; double lclip = getLowerClip(); double uclip = getUpperClip(); if (uclip <= 0.0) { // cases 1, 2, 3 and 4 if (value >= uclip) { return; // bar is not visible } base = uclip; if (value <= lclip) { value = lclip; } } else if (lclip <= 0.0) { // cases 5, 6, 7 and 8 if (value >= uclip) { value = uclip; } else { if (value <= lclip) { value = lclip; } } } else { // cases 9, 10, 11 and 12 if (value <= lclip) { return; // bar is not visible } base = getLowerClip(); if (value >= uclip) { value = uclip; } } RectangleEdge yAxisLocation = plot.getRangeAxisEdge(); double transY1 = rangeAxis.valueToJava2D(base, dataArea, yAxisLocation); double transY2 = rangeAxis.valueToJava2D(value, dataArea, yAxisLocation); double rectY = Math.min(transY2, transY1); double rectWidth = state.getBarWidth(); double rectHeight = Math.abs(transY2 - transY1); Rectangle2D bar = new Rectangle2D.Double(rectX, rectY, rectWidth, rectHeight); Paint itemPaint = getItemPaint(row, column); GradientPaintTransformer t = getGradientPaintTransformer(); if (t != null && itemPaint instanceof GradientPaint) { itemPaint = t.transform((GradientPaint) itemPaint, bar); } g2.setPaint(itemPaint); g2.fill(bar); // draw the outline... if (isDrawBarOutline() && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) { Stroke stroke = getItemOutlineStroke(row, column); Paint paint = getItemOutlinePaint(row, column); if (stroke != null && paint != null) { g2.setStroke(stroke); g2.setPaint(paint); g2.draw(bar); } } // standard deviation lines Number n = dataset.getStdDevValue(row, column); if (n != null) { double valueDelta = n.doubleValue(); double highVal = rangeAxis.valueToJava2D(meanValue.doubleValue() + valueDelta, dataArea, yAxisLocation); double lowVal = rangeAxis.valueToJava2D(meanValue.doubleValue() - valueDelta, dataArea, yAxisLocation); if (this.errorIndicatorPaint != null) { g2.setPaint(this.errorIndicatorPaint); } else { g2.setPaint(getItemOutlinePaint(row, column)); } if (this.errorIndicatorStroke != null) { g2.setStroke(this.errorIndicatorStroke); } else { g2.setStroke(getItemOutlineStroke(row, column)); } Line2D line; line = new Line2D.Double( rectX + rectWidth / 2.0d, lowVal, rectX + rectWidth / 2.0d, highVal); g2.draw(line); line = new Line2D.Double( rectX + rectWidth / 2.0d - 5.0d, highVal, rectX + rectWidth / 2.0d + 5.0d, highVal); g2.draw(line); line = new Line2D.Double( rectX + rectWidth / 2.0d - 5.0d, lowVal, rectX + rectWidth / 2.0d + 5.0d, lowVal); g2.draw(line); } CategoryItemLabelGenerator generator = getItemLabelGenerator(row, column); if (generator != null && isItemLabelVisible(row, column)) { drawItemLabel(g2, dataset, row, column, plot, generator, bar, (value < 0.0)); } // add an item entity, if this information is being collected EntityCollection entities = state.getEntityCollection(); if (entities != null) { addItemEntity(entities, dataset, row, column, bar); } }
/** * Draws the tasks/subtasks for one item. * * @param g2 the graphics device. * @param state the renderer state. * @param dataArea the data plot area. * @param plot the plot. * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param dataset the data. * @param row the row index (zero-based). * @param column the column index (zero-based). */ protected void drawTasks( Graphics2D g2, CategoryItemRendererState state, Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis, ValueAxis rangeAxis, GanttCategoryDataset dataset, int row, int column) { int count = dataset.getSubIntervalCount(row, column); if (count == 0) { drawTask(g2, state, dataArea, plot, domainAxis, rangeAxis, dataset, row, column); } PlotOrientation orientation = plot.getOrientation(); for (int subinterval = 0; subinterval < count; subinterval++) { RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge(); // value 0 Number value0 = dataset.getStartValue(row, column, subinterval); if (value0 == null) { return; } double translatedValue0 = rangeAxis.valueToJava2D(value0.doubleValue(), dataArea, rangeAxisLocation); // value 1 Number value1 = dataset.getEndValue(row, column, subinterval); if (value1 == null) { return; } double translatedValue1 = rangeAxis.valueToJava2D(value1.doubleValue(), dataArea, rangeAxisLocation); if (translatedValue1 < translatedValue0) { double temp = translatedValue1; translatedValue1 = translatedValue0; translatedValue0 = temp; } double rectStart = calculateBarW0(plot, plot.getOrientation(), dataArea, domainAxis, state, row, column); double rectLength = Math.abs(translatedValue1 - translatedValue0); double rectBreadth = state.getBarWidth(); // DRAW THE BARS... Rectangle2D bar = null; RectangleEdge barBase = null; if (plot.getOrientation() == PlotOrientation.HORIZONTAL) { bar = new Rectangle2D.Double(translatedValue0, rectStart, rectLength, rectBreadth); barBase = RectangleEdge.LEFT; } else if (plot.getOrientation() == PlotOrientation.VERTICAL) { bar = new Rectangle2D.Double(rectStart, translatedValue0, rectBreadth, rectLength); barBase = RectangleEdge.BOTTOM; } Rectangle2D completeBar = null; Rectangle2D incompleteBar = null; Number percent = dataset.getPercentComplete(row, column, subinterval); double start = getStartPercent(); double end = getEndPercent(); if (percent != null) { double p = percent.doubleValue(); if (orientation == PlotOrientation.HORIZONTAL) { completeBar = new Rectangle2D.Double( translatedValue0, rectStart + start * rectBreadth, rectLength * p, rectBreadth * (end - start)); incompleteBar = new Rectangle2D.Double( translatedValue0 + rectLength * p, rectStart + start * rectBreadth, rectLength * (1 - p), rectBreadth * (end - start)); } else if (orientation == PlotOrientation.VERTICAL) { completeBar = new Rectangle2D.Double( rectStart + start * rectBreadth, translatedValue0 + rectLength * (1 - p), rectBreadth * (end - start), rectLength * p); incompleteBar = new Rectangle2D.Double( rectStart + start * rectBreadth, translatedValue0, rectBreadth * (end - start), rectLength * (1 - p)); } } if (getShadowsVisible()) { getBarPainter().paintBarShadow(g2, this, row, column, bar, barBase, true); } getBarPainter().paintBar(g2, this, row, column, bar, barBase); if (completeBar != null) { g2.setPaint(getCompletePaint()); g2.fill(completeBar); } if (incompleteBar != null) { g2.setPaint(getIncompletePaint()); g2.fill(incompleteBar); } if (isDrawBarOutline() && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) { g2.setStroke(getItemStroke(row, column)); g2.setPaint(getItemOutlinePaint(row, column)); g2.draw(bar); } if (subinterval == count - 1) { // submit the current data point as a crosshair candidate int datasetIndex = plot.indexOf(dataset); Comparable columnKey = dataset.getColumnKey(column); Comparable rowKey = dataset.getRowKey(row); double xx = domainAxis.getCategorySeriesMiddle( columnKey, rowKey, dataset, getItemMargin(), dataArea, plot.getDomainAxisEdge()); updateCrosshairValues( state.getCrosshairState(), dataset.getRowKey(row), dataset.getColumnKey(column), value1.doubleValue(), datasetIndex, xx, translatedValue1, orientation); } // collect entity and tool tip information... if (state.getInfo() != null) { EntityCollection entities = state.getEntityCollection(); if (entities != null) { addItemEntity(entities, dataset, row, column, bar); } } } }
/** * Draws a single task. * * @param g2 the graphics device. * @param state the renderer state. * @param dataArea the data plot area. * @param plot the plot. * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param dataset the data. * @param row the row index (zero-based). * @param column the column index (zero-based). */ protected void drawTask( Graphics2D g2, CategoryItemRendererState state, Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis, ValueAxis rangeAxis, GanttCategoryDataset dataset, int row, int column) { PlotOrientation orientation = plot.getOrientation(); RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge(); // Y0 Number value0 = dataset.getEndValue(row, column); if (value0 == null) { return; } double java2dValue0 = rangeAxis.valueToJava2D(value0.doubleValue(), dataArea, rangeAxisLocation); // Y1 Number value1 = dataset.getStartValue(row, column); if (value1 == null) { return; } double java2dValue1 = rangeAxis.valueToJava2D(value1.doubleValue(), dataArea, rangeAxisLocation); if (java2dValue1 < java2dValue0) { double temp = java2dValue1; java2dValue1 = java2dValue0; java2dValue0 = temp; value1 = value0; } double rectStart = calculateBarW0(plot, orientation, dataArea, domainAxis, state, row, column); double rectBreadth = state.getBarWidth(); double rectLength = Math.abs(java2dValue1 - java2dValue0); Rectangle2D bar = null; RectangleEdge barBase = null; if (orientation == PlotOrientation.HORIZONTAL) { bar = new Rectangle2D.Double(java2dValue0, rectStart, rectLength, rectBreadth); barBase = RectangleEdge.LEFT; } else if (orientation == PlotOrientation.VERTICAL) { bar = new Rectangle2D.Double(rectStart, java2dValue1, rectBreadth, rectLength); barBase = RectangleEdge.BOTTOM; } Rectangle2D completeBar = null; Rectangle2D incompleteBar = null; Number percent = dataset.getPercentComplete(row, column); double start = getStartPercent(); double end = getEndPercent(); if (percent != null) { double p = percent.doubleValue(); if (plot.getOrientation() == PlotOrientation.HORIZONTAL) { completeBar = new Rectangle2D.Double( java2dValue0, rectStart + start * rectBreadth, rectLength * p, rectBreadth * (end - start)); incompleteBar = new Rectangle2D.Double( java2dValue0 + rectLength * p, rectStart + start * rectBreadth, rectLength * (1 - p), rectBreadth * (end - start)); } else if (plot.getOrientation() == PlotOrientation.VERTICAL) { completeBar = new Rectangle2D.Double( rectStart + start * rectBreadth, java2dValue1 + rectLength * (1 - p), rectBreadth * (end - start), rectLength * p); incompleteBar = new Rectangle2D.Double( rectStart + start * rectBreadth, java2dValue1, rectBreadth * (end - start), rectLength * (1 - p)); } } if (getShadowsVisible()) { getBarPainter().paintBarShadow(g2, this, row, column, bar, barBase, true); } getBarPainter().paintBar(g2, this, row, column, bar, barBase); if (completeBar != null) { g2.setPaint(getCompletePaint()); g2.fill(completeBar); } if (incompleteBar != null) { g2.setPaint(getIncompletePaint()); g2.fill(incompleteBar); } // draw the outline... if (isDrawBarOutline() && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) { Stroke stroke = getItemOutlineStroke(row, column); Paint paint = getItemOutlinePaint(row, column); if (stroke != null && paint != null) { g2.setStroke(stroke); g2.setPaint(paint); g2.draw(bar); } } CategoryItemLabelGenerator generator = getItemLabelGenerator(row, column); if (generator != null && isItemLabelVisible(row, column)) { drawItemLabel(g2, dataset, row, column, plot, generator, bar, false); } // submit the current data point as a crosshair candidate int datasetIndex = plot.indexOf(dataset); Comparable columnKey = dataset.getColumnKey(column); Comparable rowKey = dataset.getRowKey(row); double xx = domainAxis.getCategorySeriesMiddle( columnKey, rowKey, dataset, getItemMargin(), dataArea, plot.getDomainAxisEdge()); updateCrosshairValues( state.getCrosshairState(), dataset.getRowKey(row), dataset.getColumnKey(column), value1.doubleValue(), datasetIndex, xx, java2dValue1, orientation); // collect entity and tool tip information... EntityCollection entities = state.getEntityCollection(); if (entities != null) { addItemEntity(entities, dataset, row, column, bar); } }
/** * Draw a single data item. * * @param g2 the graphics device. * @param state the renderer state. * @param dataArea the data plot area. * @param plot the plot. * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param dataset the dataset. * @param row the row index (zero-based). * @param column the column index (zero-based). * @param pass the pass index. */ @Override public void drawItem( Graphics2D g2, CategoryItemRendererState state, Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis, ValueAxis rangeAxis, CategoryDataset dataset, int row, int column, int pass) { // do nothing if item is not visible or null if (!getItemVisible(row, column)) { return; } Number value = dataset.getValue(row, column); if (value == null) { return; } PlotOrientation orientation = plot.getOrientation(); RectangleEdge axisEdge = plot.getDomainAxisEdge(); int count = dataset.getColumnCount(); float x0 = (float) domainAxis.getCategoryStart(column, count, dataArea, axisEdge); float x1 = (float) domainAxis.getCategoryMiddle(column, count, dataArea, axisEdge); float x2 = (float) domainAxis.getCategoryEnd(column, count, dataArea, axisEdge); x0 = Math.round(x0); x1 = Math.round(x1); x2 = Math.round(x2); if (this.endType == AreaRendererEndType.TRUNCATE) { if (column == 0) { x0 = x1; } else if (column == getColumnCount() - 1) { x2 = x1; } } double yy1 = value.doubleValue(); double yy0 = 0.0; if (this.endType == AreaRendererEndType.LEVEL) { yy0 = yy1; } if (column > 0) { Number n0 = dataset.getValue(row, column - 1); if (n0 != null) { yy0 = (n0.doubleValue() + yy1) / 2.0; } } double yy2 = 0.0; if (column < dataset.getColumnCount() - 1) { Number n2 = dataset.getValue(row, column + 1); if (n2 != null) { yy2 = (n2.doubleValue() + yy1) / 2.0; } } else if (this.endType == AreaRendererEndType.LEVEL) { yy2 = yy1; } RectangleEdge edge = plot.getRangeAxisEdge(); float y0 = (float) rangeAxis.valueToJava2D(yy0, dataArea, edge); float y1 = (float) rangeAxis.valueToJava2D(yy1, dataArea, edge); float y2 = (float) rangeAxis.valueToJava2D(yy2, dataArea, edge); float yz = (float) rangeAxis.valueToJava2D(0.0, dataArea, edge); double labelXX = x1; double labelYY = y1; g2.setPaint(getItemPaint(row, column)); g2.setStroke(getItemStroke(row, column)); GeneralPath area = new GeneralPath(); if (orientation == PlotOrientation.VERTICAL) { area.moveTo(x0, yz); area.lineTo(x0, y0); area.lineTo(x1, y1); area.lineTo(x2, y2); area.lineTo(x2, yz); } else if (orientation == PlotOrientation.HORIZONTAL) { area.moveTo(yz, x0); area.lineTo(y0, x0); area.lineTo(y1, x1); area.lineTo(y2, x2); area.lineTo(yz, x2); double temp = labelXX; labelXX = labelYY; labelYY = temp; } area.closePath(); g2.setPaint(getItemPaint(row, column)); g2.fill(area); // draw the item labels if there are any... if (isItemLabelVisible(row, column)) { drawItemLabel( g2, orientation, dataset, row, column, labelXX, labelYY, (value.doubleValue() < 0.0)); } // submit the current data point as a crosshair candidate int datasetIndex = plot.indexOf(dataset); updateCrosshairValues( state.getCrosshairState(), dataset.getRowKey(row), dataset.getColumnKey(column), yy1, datasetIndex, x1, y1, orientation); // add an item entity, if this information is being collected EntityCollection entities = state.getEntityCollection(); if (entities != null) { addItemEntity(entities, dataset, row, column, area); } }
/** * Draws the bar for a single (series, category) data item. * * @param g2 the graphics device. * @param state the renderer state. * @param dataArea the data area. * @param plot the plot. * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param dataset the dataset. * @param row the row index (zero-based). * @param column the column index (zero-based). * @param pass the pass index. */ public void drawItem( Graphics2D g2, CategoryItemRendererState state, Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis, ValueAxis rangeAxis, CategoryDataset dataset, int row, int column, int pass) { double previous = state.getSeriesRunningTotal(); if (column == dataset.getColumnCount() - 1) { previous = 0.0; } double current = 0.0; Number n = dataset.getValue(row, column); if (n != null) { current = previous + n.doubleValue(); } state.setSeriesRunningTotal(current); int categoryCount = getColumnCount(); PlotOrientation orientation = plot.getOrientation(); double rectX = 0.0; double rectY = 0.0; RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge(); // Y0 double j2dy0 = rangeAxis.valueToJava2D(previous, dataArea, rangeAxisLocation); // Y1 double j2dy1 = rangeAxis.valueToJava2D(current, dataArea, rangeAxisLocation); double valDiff = current - previous; if (j2dy1 < j2dy0) { double temp = j2dy1; j2dy1 = j2dy0; j2dy0 = temp; } // BAR WIDTH double rectWidth = state.getBarWidth(); // BAR HEIGHT double rectHeight = Math.max(getMinimumBarLength(), Math.abs(j2dy1 - j2dy0)); Comparable seriesKey = dataset.getRowKey(row); Comparable categoryKey = dataset.getColumnKey(column); if (orientation == PlotOrientation.HORIZONTAL) { rectY = domainAxis.getCategorySeriesMiddle( categoryKey, seriesKey, dataset, getItemMargin(), dataArea, RectangleEdge.LEFT); rectX = j2dy0; rectHeight = state.getBarWidth(); rectY = rectY - rectHeight / 2.0; rectWidth = Math.max(getMinimumBarLength(), Math.abs(j2dy1 - j2dy0)); } else if (orientation == PlotOrientation.VERTICAL) { rectX = domainAxis.getCategorySeriesMiddle( categoryKey, seriesKey, dataset, getItemMargin(), dataArea, RectangleEdge.TOP); rectX = rectX - rectWidth / 2.0; rectY = j2dy0; } Rectangle2D bar = new Rectangle2D.Double(rectX, rectY, rectWidth, rectHeight); Paint seriesPaint = getFirstBarPaint(); if (column == 0) { seriesPaint = getFirstBarPaint(); } else if (column == categoryCount - 1) { seriesPaint = getLastBarPaint(); } else { if (valDiff < 0.0) { seriesPaint = getNegativeBarPaint(); } else if (valDiff > 0.0) { seriesPaint = getPositiveBarPaint(); } else { seriesPaint = getLastBarPaint(); } } if (getGradientPaintTransformer() != null && seriesPaint instanceof GradientPaint) { GradientPaint gp = (GradientPaint) seriesPaint; seriesPaint = getGradientPaintTransformer().transform(gp, bar); } g2.setPaint(seriesPaint); g2.fill(bar); // draw the outline... if (isDrawBarOutline() && state.getBarWidth() > BAR_OUTLINE_WIDTH_THRESHOLD) { Stroke stroke = getItemOutlineStroke(row, column); Paint paint = getItemOutlinePaint(row, column); if (stroke != null && paint != null) { g2.setStroke(stroke); g2.setPaint(paint); g2.draw(bar); } } CategoryItemLabelGenerator generator = getItemLabelGenerator(row, column); if (generator != null && isItemLabelVisible(row, column)) { drawItemLabel(g2, dataset, row, column, plot, generator, bar, (valDiff < 0.0)); } // add an item entity, if this information is being collected EntityCollection entities = state.getEntityCollection(); if (entities != null) { addItemEntity(entities, dataset, row, column, bar); } }
/** * Draws the visual representation of a single data item. * * @param g2 the graphics device. * @param state the renderer state. * @param dataArea the area within which the plot is being drawn. * @param info collects information about the drawing. * @param plot the plot (can be used to obtain standard color information etc). * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param dataset the dataset. * @param series the series index (zero-based). * @param item the item index (zero-based). * @param crosshairState crosshair information for the plot (<code>null</code> permitted). * @param pass the pass index (ignored here). */ public void drawItem( Graphics2D g2, XYItemRendererState state, Rectangle2D dataArea, PlotRenderingInfo info, XYPlot plot, ValueAxis domainAxis, ValueAxis rangeAxis, XYDataset dataset, int series, int item, CrosshairState crosshairState, int pass) { // setup for collecting optional entity info... EntityCollection entities = null; if (info != null) { entities = info.getOwner().getEntityCollection(); } IntervalXYDataset intervalDataset = (IntervalXYDataset) dataset; double x = intervalDataset.getXValue(series, item); double yLow = intervalDataset.getStartYValue(series, item); double yHigh = intervalDataset.getEndYValue(series, item); RectangleEdge xAxisLocation = plot.getDomainAxisEdge(); RectangleEdge yAxisLocation = plot.getRangeAxisEdge(); double xx = domainAxis.valueToJava2D(x, dataArea, xAxisLocation); double yyLow = rangeAxis.valueToJava2D(yLow, dataArea, yAxisLocation); double yyHigh = rangeAxis.valueToJava2D(yHigh, dataArea, yAxisLocation); Paint p = getItemPaint(series, item); Stroke s = getItemStroke(series, item); Line2D line = null; Shape shape = getItemShape(series, item); Shape top = null; Shape bottom = null; PlotOrientation orientation = plot.getOrientation(); if (orientation == PlotOrientation.HORIZONTAL) { line = new Line2D.Double(yyLow, xx, yyHigh, xx); top = ShapeUtilities.createTranslatedShape(shape, yyHigh, xx); bottom = ShapeUtilities.createTranslatedShape(shape, yyLow, xx); } else if (orientation == PlotOrientation.VERTICAL) { line = new Line2D.Double(xx, yyLow, xx, yyHigh); top = ShapeUtilities.createTranslatedShape(shape, xx, yyHigh); bottom = ShapeUtilities.createTranslatedShape(shape, xx, yyLow); } g2.setPaint(p); g2.setStroke(s); g2.draw(line); g2.fill(top); g2.fill(bottom); // for item labels, we have a special case because there is the // possibility to draw (a) the regular item label near to just the // upper y-value, or (b) the regular item label near the upper y-value // PLUS an additional item label near the lower y-value. if (isItemLabelVisible(series, item)) { drawItemLabel(g2, orientation, dataset, series, item, xx, yyHigh, false); drawAdditionalItemLabel(g2, orientation, dataset, series, item, xx, yyLow); } // add an entity for the item... if (entities != null) { addEntity(entities, line.getBounds(), dataset, series, item, 0.0, 0.0); } }
/** * Draws the visual representation of a single data item. * * @param g2 the graphics device. * @param state the renderer state. * @param dataArea the area within which the data is being drawn. * @param info collects information about the drawing. * @param plot the plot (can be used to obtain standard color information etc). * @param domainAxis the domain axis. * @param rangeAxis the vertical axis. * @param dataset the dataset. * @param series the series index (zero-based). * @param item the item index (zero-based). * @param crosshairState crosshair information for the plot ({@code null} permitted). * @param pass the pass index. */ @Override public void drawItem( Graphics2D g2, XYItemRendererState state, Rectangle2D dataArea, PlotRenderingInfo info, XYPlot plot, ValueAxis domainAxis, ValueAxis rangeAxis, XYDataset dataset, int series, int item, CrosshairState crosshairState, int pass) { // do nothing if item is not visible if (!getItemVisible(series, item)) { return; } PlotOrientation orientation = plot.getOrientation(); Paint seriesPaint = getItemPaint(series, item); Stroke seriesStroke = getItemStroke(series, item); g2.setPaint(seriesPaint); g2.setStroke(seriesStroke); // get the data point... double x1 = dataset.getXValue(series, item); double y1 = dataset.getYValue(series, item); RectangleEdge xAxisLocation = plot.getDomainAxisEdge(); RectangleEdge yAxisLocation = plot.getRangeAxisEdge(); double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation); double transY1 = (Double.isNaN(y1) ? Double.NaN : rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation)); if (pass == 0 && item > 0) { // get the previous data point... double x0 = dataset.getXValue(series, item - 1); double y0 = dataset.getYValue(series, item - 1); double transX0 = domainAxis.valueToJava2D(x0, dataArea, xAxisLocation); double transY0 = (Double.isNaN(y0) ? Double.NaN : rangeAxis.valueToJava2D(y0, dataArea, yAxisLocation)); if (orientation == PlotOrientation.HORIZONTAL) { if (transY0 == transY1) { // this represents the situation // for drawing a horizontal bar. drawLine(g2, state.workingLine, transY0, transX0, transY1, transX1); } else { // this handles the need to perform a 'step'. // calculate the step point double transXs = transX0 + (getStepPoint() * (transX1 - transX0)); drawLine(g2, state.workingLine, transY0, transX0, transY0, transXs); drawLine(g2, state.workingLine, transY0, transXs, transY1, transXs); drawLine(g2, state.workingLine, transY1, transXs, transY1, transX1); } } else if (orientation == PlotOrientation.VERTICAL) { if (transY0 == transY1) { // this represents the situation // for drawing a horizontal bar. drawLine(g2, state.workingLine, transX0, transY0, transX1, transY1); } else { // this handles the need to perform a 'step'. // calculate the step point double transXs = transX0 + (getStepPoint() * (transX1 - transX0)); drawLine(g2, state.workingLine, transX0, transY0, transXs, transY0); drawLine(g2, state.workingLine, transXs, transY0, transXs, transY1); drawLine(g2, state.workingLine, transXs, transY1, transX1, transY1); } } // submit this data item as a candidate for the crosshair point int domainAxisIndex = plot.getDomainAxisIndex(domainAxis); int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis); updateCrosshairValues( crosshairState, x1, y1, domainAxisIndex, rangeAxisIndex, transX1, transY1, orientation); // collect entity and tool tip information... EntityCollection entities = state.getEntityCollection(); if (entities != null) { addEntity(entities, null, dataset, series, item, transX1, transY1); } } if (pass == 1) { // draw the item label if there is one... if (isItemLabelVisible(series, item)) { double xx = transX1; double yy = transY1; if (orientation == PlotOrientation.HORIZONTAL) { xx = transY1; yy = transX1; } drawItemLabel(g2, orientation, dataset, series, item, xx, yy, (y1 < 0.0)); } } }
/** * Draws the visual representation of a single data item when the plot has a vertical orientation. * * @param g2 the graphics device. * @param state the renderer state. * @param dataArea the area within which the plot is being drawn. * @param plot the plot (can be used to obtain standard color information etc). * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param dataset the dataset (must be an instance of {@link BoxAndWhiskerCategoryDataset}). * @param row the row index (zero-based). * @param column the column index (zero-based). */ public void drawVerticalItem( Graphics2D g2, CategoryItemRendererState state, Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis, ValueAxis rangeAxis, CategoryDataset dataset, int row, int column) { BoxAndWhiskerCategoryDataset bawDataset = (BoxAndWhiskerCategoryDataset) dataset; double categoryEnd = domainAxis.getCategoryEnd(column, getColumnCount(), dataArea, plot.getDomainAxisEdge()); double categoryStart = domainAxis.getCategoryStart(column, getColumnCount(), dataArea, plot.getDomainAxisEdge()); double categoryWidth = categoryEnd - categoryStart; double xx = categoryStart; int seriesCount = getRowCount(); int categoryCount = getColumnCount(); if (seriesCount > 1) { double seriesGap = dataArea.getWidth() * getItemMargin() / (categoryCount * (seriesCount - 1)); double usedWidth = (state.getBarWidth() * seriesCount) + (seriesGap * (seriesCount - 1)); // offset the start of the boxes if the total width used is smaller // than the category width double offset = (categoryWidth - usedWidth) / 2; xx = xx + offset + (row * (state.getBarWidth() + seriesGap)); } else { // offset the start of the box if the box width is smaller than the // category width double offset = (categoryWidth - state.getBarWidth()) / 2; xx = xx + offset; } double yyAverage = 0.0; double yyOutlier; Paint itemPaint = getItemPaint(row, column); g2.setPaint(itemPaint); Stroke s = getItemStroke(row, column); g2.setStroke(s); double aRadius = 0; // average radius RectangleEdge location = plot.getRangeAxisEdge(); Number yQ1 = bawDataset.getQ1Value(row, column); Number yQ3 = bawDataset.getQ3Value(row, column); Number yMax = bawDataset.getMaxRegularValue(row, column); Number yMin = bawDataset.getMinRegularValue(row, column); Shape box = null; if (yQ1 != null && yQ3 != null && yMax != null && yMin != null) { double yyQ1 = rangeAxis.valueToJava2D(yQ1.doubleValue(), dataArea, location); double yyQ3 = rangeAxis.valueToJava2D(yQ3.doubleValue(), dataArea, location); double yyMax = rangeAxis.valueToJava2D(yMax.doubleValue(), dataArea, location); double yyMin = rangeAxis.valueToJava2D(yMin.doubleValue(), dataArea, location); double xxmid = xx + state.getBarWidth() / 2.0; // draw the upper shadow... g2.draw(new Line2D.Double(xxmid, yyMax, xxmid, yyQ3)); g2.draw(new Line2D.Double(xx, yyMax, xx + state.getBarWidth(), yyMax)); // draw the lower shadow... g2.draw(new Line2D.Double(xxmid, yyMin, xxmid, yyQ1)); g2.draw(new Line2D.Double(xx, yyMin, xx + state.getBarWidth(), yyMin)); // draw the body... box = new Rectangle2D.Double( xx, Math.min(yyQ1, yyQ3), state.getBarWidth(), Math.abs(yyQ1 - yyQ3)); if (this.fillBox) { g2.fill(box); } g2.setStroke(getItemOutlineStroke(row, column)); g2.setPaint(getItemOutlinePaint(row, column)); g2.draw(box); } g2.setPaint(this.artifactPaint); // draw mean - SPECIAL AIMS REQUIREMENT... Number yMean = bawDataset.getMeanValue(row, column); if (yMean != null) { yyAverage = rangeAxis.valueToJava2D(yMean.doubleValue(), dataArea, location); aRadius = state.getBarWidth() / 4; // here we check that the average marker will in fact be visible // before drawing it... if ((yyAverage > (dataArea.getMinY() - aRadius)) && (yyAverage < (dataArea.getMaxY() + aRadius))) { Ellipse2D.Double avgEllipse = new Ellipse2D.Double(xx + aRadius, yyAverage - aRadius, aRadius * 2, aRadius * 2); g2.fill(avgEllipse); g2.draw(avgEllipse); } } // draw median... Number yMedian = bawDataset.getMedianValue(row, column); if (yMedian != null) { double yyMedian = rangeAxis.valueToJava2D(yMedian.doubleValue(), dataArea, location); g2.draw(new Line2D.Double(xx, yyMedian, xx + state.getBarWidth(), yyMedian)); } // draw yOutliers... double maxAxisValue = rangeAxis.valueToJava2D(rangeAxis.getUpperBound(), dataArea, location) + aRadius; double minAxisValue = rangeAxis.valueToJava2D(rangeAxis.getLowerBound(), dataArea, location) - aRadius; g2.setPaint(itemPaint); // draw outliers double oRadius = state.getBarWidth() / 3; // outlier radius List outliers = new ArrayList(); OutlierListCollection outlierListCollection = new OutlierListCollection(); // From outlier array sort out which are outliers and put these into a // list If there are any farouts, set the flag on the // OutlierListCollection List yOutliers = bawDataset.getOutliers(row, column); if (yOutliers != null) { for (int i = 0; i < yOutliers.size(); i++) { double outlier = ((Number) yOutliers.get(i)).doubleValue(); Number minOutlier = bawDataset.getMinOutlier(row, column); Number maxOutlier = bawDataset.getMaxOutlier(row, column); Number minRegular = bawDataset.getMinRegularValue(row, column); Number maxRegular = bawDataset.getMaxRegularValue(row, column); if (outlier > maxOutlier.doubleValue()) { outlierListCollection.setHighFarOut(true); } else if (outlier < minOutlier.doubleValue()) { outlierListCollection.setLowFarOut(true); } else if (outlier > maxRegular.doubleValue()) { yyOutlier = rangeAxis.valueToJava2D(outlier, dataArea, location); outliers.add(new Outlier(xx + state.getBarWidth() / 2.0, yyOutlier, oRadius)); } else if (outlier < minRegular.doubleValue()) { yyOutlier = rangeAxis.valueToJava2D(outlier, dataArea, location); outliers.add(new Outlier(xx + state.getBarWidth() / 2.0, yyOutlier, oRadius)); } Collections.sort(outliers); } // Process outliers. Each outlier is either added to the // appropriate outlier list or a new outlier list is made for (Iterator iterator = outliers.iterator(); iterator.hasNext(); ) { Outlier outlier = (Outlier) iterator.next(); outlierListCollection.add(outlier); } for (Iterator iterator = outlierListCollection.iterator(); iterator.hasNext(); ) { OutlierList list = (OutlierList) iterator.next(); Outlier outlier = list.getAveragedOutlier(); Point2D point = outlier.getPoint(); if (list.isMultiple()) { drawMultipleEllipse(point, state.getBarWidth(), oRadius, g2); } else { drawEllipse(point, oRadius, g2); } } // draw farout indicators if (outlierListCollection.isHighFarOut()) { drawHighFarOut(aRadius / 2.0, g2, xx + state.getBarWidth() / 2.0, maxAxisValue); } if (outlierListCollection.isLowFarOut()) { drawLowFarOut(aRadius / 2.0, g2, xx + state.getBarWidth() / 2.0, minAxisValue); } } // collect entity and tool tip information... if (state.getInfo() != null && box != null) { EntityCollection entities = state.getEntityCollection(); if (entities != null) { addItemEntity(entities, dataset, row, column, box); } } }
/** * Draws the annotation. * * @param g2 the graphics device. * @param plot the plot. * @param dataArea the data area. * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param rendererIndex the renderer index. * @param info the plot rendering info. */ public void draw( Graphics2D g2, XYPlot plot, Rectangle2D dataArea, ValueAxis domainAxis, ValueAxis rangeAxis, int rendererIndex, PlotRenderingInfo info) { PlotOrientation orientation = plot.getOrientation(); RectangleEdge domainEdge = Plot.resolveDomainAxisLocation(plot.getDomainAxisLocation(), orientation); RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation(plot.getRangeAxisLocation(), orientation); double j2DX = domainAxis.valueToJava2D(getX(), dataArea, domainEdge); double j2DY = rangeAxis.valueToJava2D(getY(), dataArea, rangeEdge); if (orientation == PlotOrientation.HORIZONTAL) { double temp = j2DX; j2DX = j2DY; j2DY = temp; } double startX = j2DX + Math.cos(this.angle) * this.baseRadius; double startY = j2DY + Math.sin(this.angle) * this.baseRadius; double endX = j2DX + Math.cos(this.angle) * this.tipRadius; double endY = j2DY + Math.sin(this.angle) * this.tipRadius; double arrowBaseX = endX + Math.cos(this.angle) * this.arrowLength; double arrowBaseY = endY + Math.sin(this.angle) * this.arrowLength; double arrowLeftX = arrowBaseX + Math.cos(this.angle + Math.PI / 2.0) * this.arrowWidth; double arrowLeftY = arrowBaseY + Math.sin(this.angle + Math.PI / 2.0) * this.arrowWidth; double arrowRightX = arrowBaseX - Math.cos(this.angle + Math.PI / 2.0) * this.arrowWidth; double arrowRightY = arrowBaseY - Math.sin(this.angle + Math.PI / 2.0) * this.arrowWidth; GeneralPath arrow = new GeneralPath(); arrow.moveTo((float) endX, (float) endY); arrow.lineTo((float) arrowLeftX, (float) arrowLeftY); arrow.lineTo((float) arrowRightX, (float) arrowRightY); arrow.closePath(); g2.setStroke(this.arrowStroke); g2.setPaint(this.arrowPaint); Line2D line = new Line2D.Double(startX, startY, arrowBaseX, arrowBaseY); g2.draw(line); g2.fill(arrow); // draw the label double labelX = j2DX + Math.cos(this.angle) * (this.baseRadius + this.labelOffset); double labelY = j2DY + Math.sin(this.angle) * (this.baseRadius + this.labelOffset); g2.setFont(getFont()); Shape hotspot = TextUtilities.calculateRotatedStringBounds( getText(), g2, (float) labelX, (float) labelY, getTextAnchor(), getRotationAngle(), getRotationAnchor()); if (getBackgroundPaint() != null) { g2.setPaint(getBackgroundPaint()); g2.fill(hotspot); } g2.setPaint(getPaint()); TextUtilities.drawRotatedString( getText(), g2, (float) labelX, (float) labelY, getTextAnchor(), getRotationAngle(), getRotationAnchor()); if (isOutlineVisible()) { g2.setStroke(getOutlineStroke()); g2.setPaint(getOutlinePaint()); g2.draw(hotspot); } String toolTip = getToolTipText(); String url = getURL(); if (toolTip != null || url != null) { addEntity(info, hotspot, rendererIndex, toolTip, url); } }
/** * Draws the visual representation of a single data item. * * @param g2 the graphics device. * @param state the renderer state. * @param dataArea the area within which the data is being drawn. * @param info collects information about the drawing. * @param plot the plot (can be used to obtain standard color information etc). * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param dataset the dataset. * @param series the series index (zero-based). * @param item the item index (zero-based). * @param crosshairState crosshair information for the plot (<code>null</code> permitted). * @param pass the pass index. */ public void drawItem( Graphics2D g2, XYItemRendererState state, Rectangle2D dataArea, PlotRenderingInfo info, XYPlot plot, ValueAxis domainAxis, ValueAxis rangeAxis, XYDataset dataset, int series, int item, CrosshairState crosshairState, int pass) { if (!getItemVisible(series, item)) { return; } // setup for collecting optional entity info... Shape entityArea = null; EntityCollection entities = null; if (info != null) { entities = info.getOwner().getEntityCollection(); } PlotOrientation orientation = plot.getOrientation(); Paint paint = getItemPaint(series, item); Stroke seriesStroke = getItemStroke(series, item); g2.setPaint(paint); g2.setStroke(seriesStroke); // get the data point... double x1 = dataset.getXValue(series, item); double y1 = dataset.getYValue(series, item); if (Double.isNaN(x1) || Double.isNaN(y1)) { return; } RectangleEdge xAxisLocation = plot.getDomainAxisEdge(); RectangleEdge yAxisLocation = plot.getRangeAxisEdge(); double transX1 = domainAxis.valueToJava2D(x1, dataArea, xAxisLocation); double transY1 = rangeAxis.valueToJava2D(y1, dataArea, yAxisLocation); if (getPlotLines()) { if (item == 0) { if (this.drawSeriesLineAsPath) { State s = (State) state; s.seriesPath.reset(); s.lastPointGood = false; } } if (this.drawSeriesLineAsPath) { State s = (State) state; // update path to reflect latest point if (!Double.isNaN(transX1) && !Double.isNaN(transY1)) { float x = (float) transX1; float y = (float) transY1; if (orientation == PlotOrientation.HORIZONTAL) { x = (float) transY1; y = (float) transX1; } if (s.isLastPointGood()) { // TODO: check threshold s.seriesPath.lineTo(x, y); } else { s.seriesPath.moveTo(x, y); } s.setLastPointGood(true); } else { s.setLastPointGood(false); } if (item == dataset.getItemCount(series) - 1) { // draw path g2.setStroke(getSeriesStroke(series)); g2.setPaint(getSeriesPaint(series)); g2.draw(s.seriesPath); } } else if (item != 0) { // get the previous data point... double x0 = dataset.getXValue(series, item - 1); double y0 = dataset.getYValue(series, item - 1); if (!Double.isNaN(x0) && !Double.isNaN(y0)) { boolean drawLine = true; if (getPlotDiscontinuous()) { // only draw a line if the gap between the current and // previous data point is within the threshold int numX = dataset.getItemCount(series); double minX = dataset.getXValue(series, 0); double maxX = dataset.getXValue(series, numX - 1); if (this.gapThresholdType == UnitType.ABSOLUTE) { drawLine = Math.abs(x1 - x0) <= this.gapThreshold; } else { drawLine = Math.abs(x1 - x0) <= ((maxX - minX) / numX * getGapThreshold()); } } if (drawLine) { double transX0 = domainAxis.valueToJava2D(x0, dataArea, xAxisLocation); double transY0 = rangeAxis.valueToJava2D(y0, dataArea, yAxisLocation); // only draw if we have good values if (Double.isNaN(transX0) || Double.isNaN(transY0) || Double.isNaN(transX1) || Double.isNaN(transY1)) { return; } if (orientation == PlotOrientation.HORIZONTAL) { state.workingLine.setLine(transY0, transX0, transY1, transX1); } else if (orientation == PlotOrientation.VERTICAL) { state.workingLine.setLine(transX0, transY0, transX1, transY1); } if (state.workingLine.intersects(dataArea)) { g2.draw(state.workingLine); } } } } } if (getPlotShapes()) { Shape shape = getItemShape(series, item); if (orientation == PlotOrientation.HORIZONTAL) { shape = ShapeUtilities.createTranslatedShape(shape, transY1, transX1); } else if (orientation == PlotOrientation.VERTICAL) { shape = ShapeUtilities.createTranslatedShape(shape, transX1, transY1); } if (shape.intersects(dataArea)) { if (getItemShapeFilled(series, item)) { g2.fill(shape); } else { g2.draw(shape); } } entityArea = shape; } if (getPlotImages()) { Image image = getImage(plot, series, item, transX1, transY1); if (image != null) { Point hotspot = getImageHotspot(plot, series, item, transX1, transY1, image); g2.drawImage( image, (int) (transX1 - hotspot.getX()), (int) (transY1 - hotspot.getY()), null); entityArea = new Rectangle2D.Double( transX1 - hotspot.getX(), transY1 - hotspot.getY(), image.getWidth(null), image.getHeight(null)); } } // draw the item label if there is one... if (isItemLabelVisible(series, item)) { double xx = transX1; double yy = transY1; if (orientation == PlotOrientation.HORIZONTAL) { xx = transY1; yy = transX1; } drawItemLabel(g2, orientation, dataset, series, item, xx, yy, (y1 < 0.0)); } updateCrosshairValues(crosshairState, x1, y1, transX1, transY1, orientation); // add an entity for the item... if (entities != null) { addEntity(entities, entityArea, dataset, series, item, transX1, transY1); } }
/** * Draw a single data item. * * @param g2 the graphics device. * @param state the renderer state. * @param dataArea the area in which the data is drawn. * @param plot the plot. * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param dataset the dataset. * @param row the row index (zero-based). * @param column the column index (zero-based). * @param pass the pass index. */ @Override public void drawItem( Graphics2D g2, CategoryItemRendererState state, Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis, ValueAxis rangeAxis, CategoryDataset dataset, int row, int column, int pass) { if (!getItemVisible(row, column)) { return; } // nothing is drawn for null... Number v = dataset.getValue(row, column); if (v == null) { return; } Rectangle2D adjusted = new Rectangle2D.Double( dataArea.getX(), dataArea.getY() + getYOffset(), dataArea.getWidth() - getXOffset(), dataArea.getHeight() - getYOffset()); PlotOrientation orientation = plot.getOrientation(); // current data point... double x1 = domainAxis.getCategoryMiddle(column, getColumnCount(), adjusted, plot.getDomainAxisEdge()); double value = v.doubleValue(); double y1 = rangeAxis.valueToJava2D(value, adjusted, plot.getRangeAxisEdge()); Shape shape = getItemShape(row, column); if (orientation == PlotOrientation.HORIZONTAL) { shape = ShapeUtilities.createTranslatedShape(shape, y1, x1); } else if (orientation == PlotOrientation.VERTICAL) { shape = ShapeUtilities.createTranslatedShape(shape, x1, y1); } if (pass == 0 && getItemLineVisible(row, column)) { if (column != 0) { Number previousValue = dataset.getValue(row, column - 1); if (previousValue != null) { // previous data point... double previous = previousValue.doubleValue(); double x0 = domainAxis.getCategoryMiddle( column - 1, getColumnCount(), adjusted, plot.getDomainAxisEdge()); double y0 = rangeAxis.valueToJava2D(previous, adjusted, plot.getRangeAxisEdge()); double x2 = x0 + getXOffset(); double y2 = y0 - getYOffset(); double x3 = x1 + getXOffset(); double y3 = y1 - getYOffset(); GeneralPath clip = new GeneralPath(); if (orientation == PlotOrientation.HORIZONTAL) { clip.moveTo((float) y0, (float) x0); clip.lineTo((float) y1, (float) x1); clip.lineTo((float) y3, (float) x3); clip.lineTo((float) y2, (float) x2); clip.lineTo((float) y0, (float) x0); clip.closePath(); } else if (orientation == PlotOrientation.VERTICAL) { clip.moveTo((float) x0, (float) y0); clip.lineTo((float) x1, (float) y1); clip.lineTo((float) x3, (float) y3); clip.lineTo((float) x2, (float) y2); clip.lineTo((float) x0, (float) y0); clip.closePath(); } g2.setPaint(getItemPaint(row, column)); g2.fill(clip); g2.setStroke(getItemOutlineStroke(row, column)); g2.setPaint(getItemOutlinePaint(row, column)); g2.draw(clip); } } } // draw the item label if there is one... if (pass == 1 && isItemLabelVisible(row, column)) { if (orientation == PlotOrientation.HORIZONTAL) { drawItemLabel(g2, orientation, dataset, row, column, y1, x1, (value < 0.0)); } else if (orientation == PlotOrientation.VERTICAL) { drawItemLabel(g2, orientation, dataset, row, column, x1, y1, (value < 0.0)); } } // add an item entity, if this information is being collected EntityCollection entities = state.getEntityCollection(); if (entities != null) { addItemEntity(entities, dataset, row, column, shape); } }
/** * Draws the visual representation of a single data item. * * @param g2 the graphics device. * @param state the renderer state. * @param dataArea the area within which the plot is being drawn. * @param info collects information about the drawing. * @param plot the plot (can be used to obtain standard color information etc). * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param dataset the dataset. * @param series the series index (zero-based). * @param item the item index (zero-based). * @param crosshairState crosshair information for the plot ({@code null} permitted). * @param pass the pass index. */ @Override public void drawItem( Graphics2D g2, XYItemRendererState state, Rectangle2D dataArea, PlotRenderingInfo info, XYPlot plot, ValueAxis domainAxis, ValueAxis rangeAxis, XYDataset dataset, int series, int item, CrosshairState crosshairState, int pass) { if (!getItemVisible(series, item)) { return; } IntervalXYDataset intervalDataset = (IntervalXYDataset) dataset; double value0; double value1; if (this.useYInterval) { value0 = intervalDataset.getStartYValue(series, item); value1 = intervalDataset.getEndYValue(series, item); } else { value0 = this.base; value1 = intervalDataset.getYValue(series, item); } if (Double.isNaN(value0) || Double.isNaN(value1)) { return; } if (value0 <= value1) { if (!rangeAxis.getRange().intersects(value0, value1)) { return; } } else { if (!rangeAxis.getRange().intersects(value1, value0)) { return; } } double translatedValue0 = rangeAxis.valueToJava2D(value0, dataArea, plot.getRangeAxisEdge()); double translatedValue1 = rangeAxis.valueToJava2D(value1, dataArea, plot.getRangeAxisEdge()); double bottom = Math.min(translatedValue0, translatedValue1); double top = Math.max(translatedValue0, translatedValue1); double startX = intervalDataset.getStartXValue(series, item); if (Double.isNaN(startX)) { return; } double endX = intervalDataset.getEndXValue(series, item); if (Double.isNaN(endX)) { return; } if (startX <= endX) { if (!domainAxis.getRange().intersects(startX, endX)) { return; } } else { if (!domainAxis.getRange().intersects(endX, startX)) { return; } } // is there an alignment adjustment to be made? if (this.barAlignmentFactor >= 0.0 && this.barAlignmentFactor <= 1.0) { double x = intervalDataset.getXValue(series, item); double interval = endX - startX; startX = x - interval * this.barAlignmentFactor; endX = startX + interval; } RectangleEdge location = plot.getDomainAxisEdge(); double translatedStartX = domainAxis.valueToJava2D(startX, dataArea, location); double translatedEndX = domainAxis.valueToJava2D(endX, dataArea, location); double translatedWidth = Math.max(1, Math.abs(translatedEndX - translatedStartX)); double left = Math.min(translatedStartX, translatedEndX); if (getMargin() > 0.0) { double cut = translatedWidth * getMargin(); translatedWidth = translatedWidth - cut; left = left + cut / 2; } Rectangle2D bar = null; PlotOrientation orientation = plot.getOrientation(); if (orientation.isHorizontal()) { // clip left and right bounds to data area bottom = Math.max(bottom, dataArea.getMinX()); top = Math.min(top, dataArea.getMaxX()); bar = new Rectangle2D.Double(bottom, left, top - bottom, translatedWidth); } else if (orientation.isVertical()) { // clip top and bottom bounds to data area bottom = Math.max(bottom, dataArea.getMinY()); top = Math.min(top, dataArea.getMaxY()); bar = new Rectangle2D.Double(left, bottom, translatedWidth, top - bottom); } boolean positive = (value1 > 0.0); boolean inverted = rangeAxis.isInverted(); RectangleEdge barBase; if (orientation.isHorizontal()) { if (positive && inverted || !positive && !inverted) { barBase = RectangleEdge.RIGHT; } else { barBase = RectangleEdge.LEFT; } } else { if (positive && !inverted || !positive && inverted) { barBase = RectangleEdge.BOTTOM; } else { barBase = RectangleEdge.TOP; } } if (state.getElementHinting()) { beginElementGroup(g2, dataset.getSeriesKey(series), item); } if (getShadowsVisible()) { this.barPainter.paintBarShadow(g2, this, series, item, bar, barBase, !this.useYInterval); } this.barPainter.paintBar(g2, this, series, item, bar, barBase); if (state.getElementHinting()) { endElementGroup(g2); } if (isItemLabelVisible(series, item)) { XYItemLabelGenerator generator = getItemLabelGenerator(series, item); drawItemLabel(g2, dataset, series, item, plot, generator, bar, value1 < 0.0); } // update the crosshair point double x1 = (startX + endX) / 2.0; double y1 = dataset.getYValue(series, item); double transX1 = domainAxis.valueToJava2D(x1, dataArea, location); double transY1 = rangeAxis.valueToJava2D(y1, dataArea, plot.getRangeAxisEdge()); int domainAxisIndex = plot.getDomainAxisIndex(domainAxis); int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis); updateCrosshairValues( crosshairState, x1, y1, domainAxisIndex, rangeAxisIndex, transX1, transY1, plot.getOrientation()); EntityCollection entities = state.getEntityCollection(); if (entities != null) { addEntity(entities, bar, dataset, series, item, 0.0, 0.0); } }
/** * Draws the visual representation of a single data item when the plot has a horizontal * orientation. * * @param g2 the graphics device. * @param state the renderer state. * @param dataArea the area within which the plot is being drawn. * @param plot the plot (can be used to obtain standard color information etc). * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param dataset the dataset (must be an instance of {@link BoxAndWhiskerCategoryDataset}). * @param row the row index (zero-based). * @param column the column index (zero-based). */ public void drawHorizontalItem( Graphics2D g2, CategoryItemRendererState state, Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis, ValueAxis rangeAxis, CategoryDataset dataset, int row, int column) { BoxAndWhiskerCategoryDataset bawDataset = (BoxAndWhiskerCategoryDataset) dataset; double categoryEnd = domainAxis.getCategoryEnd(column, getColumnCount(), dataArea, plot.getDomainAxisEdge()); double categoryStart = domainAxis.getCategoryStart(column, getColumnCount(), dataArea, plot.getDomainAxisEdge()); double categoryWidth = Math.abs(categoryEnd - categoryStart); double yy = categoryStart; int seriesCount = getRowCount(); int categoryCount = getColumnCount(); if (seriesCount > 1) { double seriesGap = dataArea.getHeight() * getItemMargin() / (categoryCount * (seriesCount - 1)); double usedWidth = (state.getBarWidth() * seriesCount) + (seriesGap * (seriesCount - 1)); // offset the start of the boxes if the total width used is smaller // than the category width double offset = (categoryWidth - usedWidth) / 2; yy = yy + offset + (row * (state.getBarWidth() + seriesGap)); } else { // offset the start of the box if the box width is smaller than // the category width double offset = (categoryWidth - state.getBarWidth()) / 2; yy = yy + offset; } g2.setPaint(getItemPaint(row, column)); Stroke s = getItemStroke(row, column); g2.setStroke(s); RectangleEdge location = plot.getRangeAxisEdge(); Number xQ1 = bawDataset.getQ1Value(row, column); Number xQ3 = bawDataset.getQ3Value(row, column); Number xMax = bawDataset.getMaxRegularValue(row, column); Number xMin = bawDataset.getMinRegularValue(row, column); Shape box = null; if (xQ1 != null && xQ3 != null && xMax != null && xMin != null) { double xxQ1 = rangeAxis.valueToJava2D(xQ1.doubleValue(), dataArea, location); double xxQ3 = rangeAxis.valueToJava2D(xQ3.doubleValue(), dataArea, location); double xxMax = rangeAxis.valueToJava2D(xMax.doubleValue(), dataArea, location); double xxMin = rangeAxis.valueToJava2D(xMin.doubleValue(), dataArea, location); double yymid = yy + state.getBarWidth() / 2.0; // draw the upper shadow... g2.draw(new Line2D.Double(xxMax, yymid, xxQ3, yymid)); g2.draw(new Line2D.Double(xxMax, yy, xxMax, yy + state.getBarWidth())); // draw the lower shadow... g2.draw(new Line2D.Double(xxMin, yymid, xxQ1, yymid)); g2.draw(new Line2D.Double(xxMin, yy, xxMin, yy + state.getBarWidth())); // draw the box... box = new Rectangle2D.Double( Math.min(xxQ1, xxQ3), yy, Math.abs(xxQ1 - xxQ3), state.getBarWidth()); if (this.fillBox) { g2.fill(box); } g2.setStroke(getItemOutlineStroke(row, column)); g2.setPaint(getItemOutlinePaint(row, column)); g2.draw(box); } g2.setPaint(this.artifactPaint); double aRadius = 0; // average radius // draw mean - SPECIAL AIMS REQUIREMENT... Number xMean = bawDataset.getMeanValue(row, column); if (xMean != null) { double xxMean = rangeAxis.valueToJava2D(xMean.doubleValue(), dataArea, location); aRadius = state.getBarWidth() / 4; // here we check that the average marker will in fact be visible // before drawing it... if ((xxMean > (dataArea.getMinX() - aRadius)) && (xxMean < (dataArea.getMaxX() + aRadius))) { Ellipse2D.Double avgEllipse = new Ellipse2D.Double(xxMean - aRadius, yy + aRadius, aRadius * 2, aRadius * 2); g2.fill(avgEllipse); g2.draw(avgEllipse); } } // draw median... Number xMedian = bawDataset.getMedianValue(row, column); if (xMedian != null) { double xxMedian = rangeAxis.valueToJava2D(xMedian.doubleValue(), dataArea, location); g2.draw(new Line2D.Double(xxMedian, yy, xxMedian, yy + state.getBarWidth())); } // collect entity and tool tip information... if (state.getInfo() != null && box != null) { EntityCollection entities = state.getEntityCollection(); if (entities != null) { addItemEntity(entities, dataset, row, column, box); } } }
/** * Draws the visual representation of a single data item, second pass. In the second pass, the * renderer draws the lines and shapes for the individual points in the two series. * * @param x_graphics the graphics device. * @param x_dataArea the area within which the data is being drawn. * @param x_info collects information about the drawing. * @param x_plot the plot (can be used to obtain standard color information etc). * @param x_domainAxis the domain (horizontal) axis. * @param x_rangeAxis the range (vertical) axis. * @param x_dataset the dataset. * @param x_series the series index (zero-based). * @param x_item the item index (zero-based). * @param x_crosshairState crosshair information for the plot (<code>null</code> permitted). */ protected void drawItemPass1( Graphics2D x_graphics, Rectangle2D x_dataArea, PlotRenderingInfo x_info, XYPlot x_plot, ValueAxis x_domainAxis, ValueAxis x_rangeAxis, XYDataset x_dataset, int x_series, int x_item, CrosshairState x_crosshairState) { Shape l_entityArea = null; EntityCollection l_entities = null; if (null != x_info) { l_entities = x_info.getOwner().getEntityCollection(); } Paint l_seriesPaint = getItemPaint(x_series, x_item); Stroke l_seriesStroke = getItemStroke(x_series, x_item); x_graphics.setPaint(l_seriesPaint); x_graphics.setStroke(l_seriesStroke); PlotOrientation l_orientation = x_plot.getOrientation(); RectangleEdge l_domainAxisLocation = x_plot.getDomainAxisEdge(); RectangleEdge l_rangeAxisLocation = x_plot.getRangeAxisEdge(); double l_x0 = x_dataset.getXValue(x_series, x_item); double l_y0 = x_dataset.getYValue(x_series, x_item); double l_x1 = x_domainAxis.valueToJava2D(l_x0, x_dataArea, l_domainAxisLocation); double l_y1 = x_rangeAxis.valueToJava2D(l_y0, x_dataArea, l_rangeAxisLocation); if (getShapesVisible()) { Shape l_shape = getItemShape(x_series, x_item); if (l_orientation == PlotOrientation.HORIZONTAL) { l_shape = ShapeUtilities.createTranslatedShape(l_shape, l_y1, l_x1); } else { l_shape = ShapeUtilities.createTranslatedShape(l_shape, l_x1, l_y1); } if (l_shape.intersects(x_dataArea)) { x_graphics.setPaint(getItemPaint(x_series, x_item)); x_graphics.fill(l_shape); } l_entityArea = l_shape; } // add an entity for the item... if (null != l_entities) { if (null == l_entityArea) { l_entityArea = new Rectangle2D.Double((l_x1 - 2), (l_y1 - 2), 4, 4); } String l_tip = null; XYToolTipGenerator l_tipGenerator = getToolTipGenerator(x_series, x_item); if (null != l_tipGenerator) { l_tip = l_tipGenerator.generateToolTip(x_dataset, x_series, x_item); } String l_url = null; XYURLGenerator l_urlGenerator = getURLGenerator(); if (null != l_urlGenerator) { l_url = l_urlGenerator.generateURL(x_dataset, x_series, x_item); } XYItemEntity l_entity = new XYItemEntity(l_entityArea, x_dataset, x_series, x_item, l_tip, l_url); l_entities.add(l_entity); } // draw the item label if there is one... if (isItemLabelVisible(x_series, x_item)) { drawItemLabel( x_graphics, l_orientation, x_dataset, x_series, x_item, l_x1, l_y1, (l_y1 < 0.0)); } int l_domainAxisIndex = x_plot.getDomainAxisIndex(x_domainAxis); int l_rangeAxisIndex = x_plot.getRangeAxisIndex(x_rangeAxis); updateCrosshairValues( x_crosshairState, l_x0, l_y0, l_domainAxisIndex, l_rangeAxisIndex, l_x1, l_y1, l_orientation); if (0 == x_item) { return; } double l_x2 = x_domainAxis.valueToJava2D( x_dataset.getXValue(x_series, (x_item - 1)), x_dataArea, l_domainAxisLocation); double l_y2 = x_rangeAxis.valueToJava2D( x_dataset.getYValue(x_series, (x_item - 1)), x_dataArea, l_rangeAxisLocation); Line2D l_line = null; if (PlotOrientation.HORIZONTAL == l_orientation) { l_line = new Line2D.Double(l_y1, l_x1, l_y2, l_x2); } else if (PlotOrientation.VERTICAL == l_orientation) { l_line = new Line2D.Double(l_x1, l_y1, l_x2, l_y2); } if ((null != l_line) && l_line.intersects(x_dataArea)) { x_graphics.setPaint(getItemPaint(x_series, x_item)); x_graphics.setStroke(getItemStroke(x_series, x_item)); x_graphics.draw(l_line); } }
/** * Draws the visual representation of a single data item. * * @param g2 the graphics device. * @param state the renderer state. * @param dataArea the area within which the data is being drawn. * @param info collects information about the drawing. * @param plot the plot (can be used to obtain standard color information etc). * @param domainAxis the domain (horizontal) axis. * @param rangeAxis the range (vertical) axis. * @param dataset the dataset (an {@link XYZDataset} is expected). * @param series the series index (zero-based). * @param item the item index (zero-based). * @param crosshairState crosshair information for the plot (<code>null</code> permitted). * @param pass the pass index. */ public void drawItem( Graphics2D g2, XYItemRendererState state, Rectangle2D dataArea, PlotRenderingInfo info, XYPlot plot, ValueAxis domainAxis, ValueAxis rangeAxis, XYDataset dataset, int series, int item, CrosshairState crosshairState, int pass) { // return straight away if the item is not visible if (!getItemVisible(series, item)) { return; } PlotOrientation orientation = plot.getOrientation(); // get the data point... double x = dataset.getXValue(series, item); double y = dataset.getYValue(series, item); double z = Double.NaN; if (dataset instanceof XYZDataset) { XYZDataset xyzData = (XYZDataset) dataset; z = xyzData.getZValue(series, item); } if (!Double.isNaN(z)) { RectangleEdge domainAxisLocation = plot.getDomainAxisEdge(); RectangleEdge rangeAxisLocation = plot.getRangeAxisEdge(); double transX = domainAxis.valueToJava2D(x, dataArea, domainAxisLocation); double transY = rangeAxis.valueToJava2D(y, dataArea, rangeAxisLocation); double transDomain = 0.0; double transRange = 0.0; double zero; switch (getScaleType()) { case SCALE_ON_DOMAIN_AXIS: zero = domainAxis.valueToJava2D(0.0, dataArea, domainAxisLocation); transDomain = domainAxis.valueToJava2D(z, dataArea, domainAxisLocation) - zero; transRange = transDomain; break; case SCALE_ON_RANGE_AXIS: zero = rangeAxis.valueToJava2D(0.0, dataArea, rangeAxisLocation); transRange = zero - rangeAxis.valueToJava2D(z, dataArea, rangeAxisLocation); transDomain = transRange; break; default: double zero1 = domainAxis.valueToJava2D(0.0, dataArea, domainAxisLocation); double zero2 = rangeAxis.valueToJava2D(0.0, dataArea, rangeAxisLocation); transDomain = domainAxis.valueToJava2D(z, dataArea, domainAxisLocation) - zero1; transRange = zero2 - rangeAxis.valueToJava2D(z, dataArea, rangeAxisLocation); } transDomain = Math.abs(transDomain); transRange = Math.abs(transRange); Ellipse2D circle = null; if (orientation == PlotOrientation.VERTICAL) { circle = new Ellipse2D.Double( transX - transDomain / 2.0, transY - transRange / 2.0, transDomain, transRange); } else if (orientation == PlotOrientation.HORIZONTAL) { circle = new Ellipse2D.Double( transY - transRange / 2.0, transX - transDomain / 2.0, transRange, transDomain); } g2.setPaint(getItemPaint(series, item)); g2.fill(circle); g2.setStroke(getItemOutlineStroke(series, item)); g2.setPaint(getItemOutlinePaint(series, item)); g2.draw(circle); if (isItemLabelVisible(series, item)) { if (orientation == PlotOrientation.VERTICAL) { drawItemLabel(g2, orientation, dataset, series, item, transX, transY, false); } else if (orientation == PlotOrientation.HORIZONTAL) { drawItemLabel(g2, orientation, dataset, series, item, transY, transX, false); } } // add an entity if this info is being collected EntityCollection entities = null; if (info != null) { entities = info.getOwner().getEntityCollection(); if (entities != null && circle.intersects(dataArea)) { addEntity( entities, circle, dataset, series, item, circle.getCenterX(), circle.getCenterY()); } } int domainAxisIndex = plot.getDomainAxisIndex(domainAxis); int rangeAxisIndex = plot.getRangeAxisIndex(rangeAxis); updateCrosshairValues( crosshairState, x, y, domainAxisIndex, rangeAxisIndex, transX, transY, orientation); } }
/** * Draws the visual representation of a polygon * * @param x_graphics the graphics device. * @param x_dataArea the area within which the data is being drawn. * @param x_plot the plot (can be used to obtain standard color information etc). * @param x_domainAxis the domain (horizontal) axis. * @param x_rangeAxis the range (vertical) axis. * @param x_positive indicates if the polygon is positive (true) or negative (false). * @param x_xValues a linked list of the x values (expects values to be of type Double). * @param x_yValues a linked list of the y values (expects values to be of type Double). */ private void createPolygon( Graphics2D x_graphics, Rectangle2D x_dataArea, XYPlot x_plot, ValueAxis x_domainAxis, ValueAxis x_rangeAxis, boolean x_positive, LinkedList x_xValues, LinkedList x_yValues) { PlotOrientation l_orientation = x_plot.getOrientation(); RectangleEdge l_domainAxisLocation = x_plot.getDomainAxisEdge(); RectangleEdge l_rangeAxisLocation = x_plot.getRangeAxisEdge(); Object[] l_xValues = x_xValues.toArray(); Object[] l_yValues = x_yValues.toArray(); GeneralPath l_path = new GeneralPath(); if (PlotOrientation.VERTICAL == l_orientation) { double l_x = x_domainAxis.valueToJava2D( ((Double) l_xValues[0]).doubleValue(), x_dataArea, l_domainAxisLocation); if (this.roundXCoordinates) { l_x = Math.rint(l_x); } double l_y = x_rangeAxis.valueToJava2D( ((Double) l_yValues[0]).doubleValue(), x_dataArea, l_rangeAxisLocation); l_path.moveTo((float) l_x, (float) l_y); for (int i = 1; i < l_xValues.length; i++) { l_x = x_domainAxis.valueToJava2D( ((Double) l_xValues[i]).doubleValue(), x_dataArea, l_domainAxisLocation); if (this.roundXCoordinates) { l_x = Math.rint(l_x); } l_y = x_rangeAxis.valueToJava2D( ((Double) l_yValues[i]).doubleValue(), x_dataArea, l_rangeAxisLocation); l_path.lineTo((float) l_x, (float) l_y); } l_path.closePath(); } else { double l_x = x_domainAxis.valueToJava2D( ((Double) l_xValues[0]).doubleValue(), x_dataArea, l_domainAxisLocation); if (this.roundXCoordinates) { l_x = Math.rint(l_x); } double l_y = x_rangeAxis.valueToJava2D( ((Double) l_yValues[0]).doubleValue(), x_dataArea, l_rangeAxisLocation); l_path.moveTo((float) l_y, (float) l_x); for (int i = 1; i < l_xValues.length; i++) { l_x = x_domainAxis.valueToJava2D( ((Double) l_xValues[i]).doubleValue(), x_dataArea, l_domainAxisLocation); if (this.roundXCoordinates) { l_x = Math.rint(l_x); } l_y = x_rangeAxis.valueToJava2D( ((Double) l_yValues[i]).doubleValue(), x_dataArea, l_rangeAxisLocation); l_path.lineTo((float) l_y, (float) l_x); } l_path.closePath(); } if (l_path.intersects(x_dataArea)) { x_graphics.setPaint(x_positive ? getPositivePaint() : getNegativePaint()); x_graphics.fill(l_path); } }
/** * Draw a single data item. * * @param g2 the graphics device. * @param state the renderer state. * @param dataArea the area in which the data is drawn. * @param plot the plot. * @param domainAxis the domain axis. * @param rangeAxis the range axis. * @param dataset the dataset. * @param row the row index (zero-based). * @param column the column index (zero-based). * @param pass the pass index. */ public void drawItem( Graphics2D g2, CategoryItemRendererState state, Rectangle2D dataArea, CategoryPlot plot, CategoryAxis domainAxis, ValueAxis rangeAxis, CategoryDataset dataset, int row, int column, int pass) { // do nothing if item is not visible if (!getItemVisible(row, column)) { return; } Number value = dataset.getValue(row, column); if (value == null) { return; } PlotOrientation orientation = plot.getOrientation(); // current data point... double x1s = domainAxis.getCategoryStart(column, getColumnCount(), dataArea, plot.getDomainAxisEdge()); double x1 = domainAxis.getCategoryMiddle(column, getColumnCount(), dataArea, plot.getDomainAxisEdge()); double x1e = 2 * x1 - x1s; // or: x1s + 2*(x1-x1s) double y1 = rangeAxis.valueToJava2D(value.doubleValue(), dataArea, plot.getRangeAxisEdge()); g2.setPaint(getItemPaint(row, column)); g2.setStroke(getItemStroke(row, column)); if (column != 0) { Number previousValue = dataset.getValue(row, column - 1); if (previousValue != null) { // previous data point... double previous = previousValue.doubleValue(); double x0s = domainAxis.getCategoryStart( column - 1, getColumnCount(), dataArea, plot.getDomainAxisEdge()); double x0 = domainAxis.getCategoryMiddle( column - 1, getColumnCount(), dataArea, plot.getDomainAxisEdge()); double x0e = 2 * x0 - x0s; // or: x0s + 2*(x0-x0s) double y0 = rangeAxis.valueToJava2D(previous, dataArea, plot.getRangeAxisEdge()); if (getStagger()) { int xStagger = row * STAGGER_WIDTH; if (xStagger > (x1s - x0e)) { xStagger = (int) (x1s - x0e); } x1s = x0e + xStagger; } drawLine(g2, (State) state, orientation, x0e, y0, x1s, y0); // extend x0's flat bar drawLine(g2, (State) state, orientation, x1s, y0, x1s, y1); // upright bar } } drawLine(g2, (State) state, orientation, x1s, y1, x1e, y1); // x1's flat bar // draw the item labels if there are any... if (isItemLabelVisible(row, column)) { drawItemLabel(g2, orientation, dataset, row, column, x1, y1, (value.doubleValue() < 0.0)); } // add an item entity, if this information is being collected EntityCollection entities = state.getEntityCollection(); if (entities != null) { Rectangle2D hotspot = new Rectangle2D.Double(); if (orientation == PlotOrientation.VERTICAL) { hotspot.setRect(x1s, y1, x1e - x1s, 4.0); } else { hotspot.setRect(y1 - 2.0, x1s, 4.0, x1e - x1s); } addItemEntity(entities, dataset, row, column, hotspot); } }
/** * Draws the block representing the specified item. * * @param g2 the graphics device. * @param state the state. * @param dataArea the data area. * @param info the plot rendering info. * @param plot the plot. * @param domainAxis the x-axis. * @param rangeAxis the y-axis. * @param dataset the dataset. * @param series the series index. * @param item the item index. * @param crosshairState the crosshair state. * @param pass the pass index. */ @Override public void drawItem( Graphics2D g2, XYItemRendererState state, Rectangle2D dataArea, PlotRenderingInfo info, XYPlot plot, ValueAxis domainAxis, ValueAxis rangeAxis, XYDataset dataset, int series, int item, CrosshairState crosshairState, int pass) { double x = dataset.getXValue(series, item); double y = dataset.getYValue(series, item); double dx = 0.0; double dy = 0.0; if (dataset instanceof VectorXYDataset) { dx = ((VectorXYDataset) dataset).getVectorXValue(series, item); dy = ((VectorXYDataset) dataset).getVectorYValue(series, item); } double xx0 = domainAxis.valueToJava2D(x, dataArea, plot.getDomainAxisEdge()); double yy0 = rangeAxis.valueToJava2D(y, dataArea, plot.getRangeAxisEdge()); double xx1 = domainAxis.valueToJava2D(x + dx, dataArea, plot.getDomainAxisEdge()); double yy1 = rangeAxis.valueToJava2D(y + dy, dataArea, plot.getRangeAxisEdge()); Line2D line; PlotOrientation orientation = plot.getOrientation(); if (orientation.equals(PlotOrientation.HORIZONTAL)) { line = new Line2D.Double(yy0, xx0, yy1, xx1); } else { line = new Line2D.Double(xx0, yy0, xx1, yy1); } g2.setPaint(getItemPaint(series, item)); g2.setStroke(getItemStroke(series, item)); g2.draw(line); // calculate the arrow head and draw it... double dxx = (xx1 - xx0); double dyy = (yy1 - yy0); double bx = xx0 + (1.0 - this.baseLength) * dxx; double by = yy0 + (1.0 - this.baseLength) * dyy; double cx = xx0 + (1.0 - this.headLength) * dxx; double cy = yy0 + (1.0 - this.headLength) * dyy; double angle = 0.0; if (dxx != 0.0) { angle = Math.PI / 2.0 - Math.atan(dyy / dxx); } double deltaX = 2.0 * Math.cos(angle); double deltaY = 2.0 * Math.sin(angle); double leftx = cx + deltaX; double lefty = cy - deltaY; double rightx = cx - deltaX; double righty = cy + deltaY; GeneralPath p = new GeneralPath(); if (orientation == PlotOrientation.VERTICAL) { p.moveTo((float) xx1, (float) yy1); p.lineTo((float) rightx, (float) righty); p.lineTo((float) bx, (float) by); p.lineTo((float) leftx, (float) lefty); } else { // orientation is HORIZONTAL p.moveTo((float) yy1, (float) xx1); p.lineTo((float) righty, (float) rightx); p.lineTo((float) by, (float) bx); p.lineTo((float) lefty, (float) leftx); } p.closePath(); g2.draw(p); // setup for collecting optional entity info... EntityCollection entities = null; if (info != null) { entities = info.getOwner().getEntityCollection(); if (entities != null) { addEntity(entities, line.getBounds(), dataset, series, item, 0.0, 0.0); } } }