/**
   * 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);
    }
  }
Beispiel #3
0
  /**
   * 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);
    }
  }
Beispiel #5
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);
  }
Beispiel #9
0
  /**
   * 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;
  }
Beispiel #10
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 (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);
    }
  }
Beispiel #14
0
  /**
   * 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);
        }
      }
    }
  }
Beispiel #15
0
  /**
   * 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);
    }
  }
Beispiel #19
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);
    }
  }
Beispiel #23
0
  /**
   * 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);
    }
  }
Beispiel #24
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 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);
      }
    }
  }