public double getMaxValue(int pixelResolution) {
    Rectangle field = new Rectangle(pixelResolution, pixelResolution);
    double[] drawingPoint = plotSheet.toCoordinatePoint(field.x, 0, field);
    double max = Double.NEGATIVE_INFINITY;

    for (int i = 0; i < pixelResolution; i++) {
      drawingPoint = plotSheet.toCoordinatePoint(i, 0, field);
      double f_x = function.f(drawingPoint[0]);
      if (f_x > max) max = f_x;
    }

    return max;
  }
  /* (non-Javadoc)
   * @see rendering.Drawable#paint(java.awt.Graphics)
   */
  @Override
  public void paint(Graphics g) {

    Color oldColor = g.getColor();
    Rectangle field = g.getClipBounds();
    g.setColor(color);

    if (autoscale) {
      double[] start = this.plotSheet.toCoordinatePoint(0, 0, field);
      double[] end =
          this.plotSheet.toCoordinatePoint(0, 0 + this.plotSheet.getFrameThickness(), field);

      this.scaleFactor = Math.abs(end[1] - start[1]);
    } else {
      this.scaleFactor = 1.0;
    }

    if (this.isOnFrame) yOffset = plotSheet.getyRange()[0];

    for (int i = 0; i < this.points[0].length; i++) {
      if (points.length == 3) {
        drawBar(
            points[0][i], points[1][i] * scaleFactor * extraScaleFactor, g, field, points[2][i]);
      } else {
        drawBar(points[0][i], points[1][i] * scaleFactor * extraScaleFactor, g, field);
      }
    }

    g.setColor(oldColor);
  }
  /**
   * draw a single bar at given coordinate and with the given height with given specific size
   *
   * @param x coordinate on plot
   * @param heigth height
   * @param g graphic object used to draw this bar
   * @param field bounds of plot
   * @param size specific size (width) of this bar
   */
  private void drawBar(double x, double heigth, Graphics g, Rectangle field, double size) {

    int[] pointUpLeft = plotSheet.toGraphicPoint(x, heigth, field);
    int[] pointUpRight = plotSheet.toGraphicPoint(x + size, heigth, field);
    int[] pointBottomLeft = plotSheet.toGraphicPoint(x, 0, field);

    if (heigth < 0) {
      pointUpLeft = plotSheet.toGraphicPoint(x, 0, field);
      pointUpRight = plotSheet.toGraphicPoint(x + size, 0, field);
      pointBottomLeft = plotSheet.toGraphicPoint(x, heigth, field);
    }

    if (this.isOnFrame) {
      pointUpLeft = plotSheet.toGraphicPoint(x, this.yOffset, field);
      pointUpRight = plotSheet.toGraphicPoint(x + size, this.yOffset, field);
      pointBottomLeft = plotSheet.toGraphicPoint(x, this.yOffset - heigth, field);
    }

    if (filling) {
      Color oldColor = g.getColor();
      if (this.fillColor != null) g.setColor(fillColor);

      g.fillRect(
          pointUpLeft[0],
          pointUpLeft[1],
          pointUpRight[0] - pointUpLeft[0],
          pointBottomLeft[1] - pointUpLeft[1]);

      // g.fillRect(pointUpLeft[0], pointUpLeft[1], pointUpRight[0]-pointUpLeft[0],
      // pointBottomLeft[1]-pointUpLeft[1]);

      g.setColor(oldColor);
    }

    g.drawRect(
        pointUpLeft[0],
        pointUpLeft[1],
        pointUpRight[0] - pointUpLeft[0],
        pointBottomLeft[1] - pointUpLeft[1]);

    //		g.drawLine(pointUpLeft[0], pointUpLeft[1], pointUpRight[0], pointUpRight[1]);
    //		g.drawLine(pointUpLeft[0], pointUpLeft[1], pointBottomLeft[0], pointBottomLeft[1]);
    //		g.drawLine(pointBottomRight[0], pointBottomRight[1], pointBottomLeft[0],
    // pointBottomLeft[1]);
  }
  /* (non-Javadoc)
   * @see rendering.Drawable#paint(java.awt.Graphics)
   */
  @Override
  public void paint(Graphics g) {
    if (function instanceof StepFunction2D) {
      this.isStepFunction = true;
    }

    Graphics2D g2D = (Graphics2D) g;
    Stroke oldStroke = g2D.getStroke();
    g2D.setStroke(new BasicStroke(this.size)); // set stroke width of 10

    Color oldColor = g.getColor();
    Rectangle field = g.getClipBounds();
    g.setColor(color);

    if (autoscale) {
      double[] start = this.plotSheet.toCoordinatePoint(0, 0, field);
      double[] end =
          this.plotSheet.toCoordinatePoint(0, 0 + this.plotSheet.getFrameThickness(), field);

      this.scaleFactor = Math.abs(end[1] - start[1]);
      //			this.scaleFactor *= binSize;
    } else {
      this.scaleFactor = 1.0;
    }

    if (this.isOnFrame) yOffset = plotSheet.getyRange()[0];

    double[] drawingPoint = plotSheet.toCoordinatePoint(field.x, 0, field);
    if (this.isOnFrame)
      drawingPoint =
          plotSheet.toCoordinatePoint(field.x + this.plotSheet.getFrameThickness(), 0, field);

    double f_x = function.f(drawingPoint[0]) * scaleFactor * extraScaleFactor;
    double f_x_old = f_x;

    int[] coordStart = plotSheet.toGraphicPoint(drawingPoint[0], f_x, field);
    if (this.isOnFrame)
      coordStart = plotSheet.toGraphicPoint(drawingPoint[0], this.yOffset - f_x, field);

    int[] coordEnd = coordStart;

    int leftStart = field.x + 1;
    int rightEnd = field.width + field.x;
    if (this.isOnFrame) {
      leftStart = field.x + this.plotSheet.getFrameThickness() + 1;
      rightEnd = field.width + field.x - this.plotSheet.getFrameThickness();
    }

    if (this.hasLimit) {
      leftStart = plotSheet.xToGraphic(leftLimit, field);
      rightEnd = plotSheet.xToGraphic(rightLimit, field);
    }

    for (int i = leftStart; i < rightEnd; i++) {
      drawingPoint = plotSheet.toCoordinatePoint(i, 0, field);

      coordEnd = coordStart;

      f_x_old = f_x;
      f_x = function.f(drawingPoint[0]) * scaleFactor * extraScaleFactor;
      coordStart = plotSheet.toGraphicPoint(drawingPoint[0], f_x, field);
      if (this.isOnFrame)
        coordStart = plotSheet.toGraphicPoint(drawingPoint[0], this.yOffset - f_x, field);

      double overlap = 0.2 * (plotSheet.getyRange()[1] - plotSheet.getyRange()[0]);

      if (f_x_old != Double.NaN
          && f_x != Double.NaN
          && f_x_old != Double.NEGATIVE_INFINITY
          && f_x != Double.NEGATIVE_INFINITY
          && f_x_old != Double.POSITIVE_INFINITY
          && f_x != Double.POSITIVE_INFINITY
          && f_x_old <= plotSheet.getyRange()[1] + overlap
          && f_x_old >= plotSheet.getyRange()[0] - overlap
          && f_x <= plotSheet.getyRange()[1] + overlap
          && f_x >= plotSheet.getyRange()[0] - overlap) {

        if (!this.isStepFunction) {
          g.drawLine(coordStart[0], coordStart[1], coordEnd[0], coordEnd[1]);
        } else {
          g.drawLine(coordStart[0], coordStart[1], coordStart[0], coordEnd[1]);
        }

      } else if (!warned) {
        System.err.println("Could not draw part of function, possible pole or out of reach");
        warned = true;
      }
    }
    g2D.setStroke(oldStroke);
    g.setColor(oldColor);
  }
 /** set the axis to draw on the border between outer frame and plot */
 public void setOnFrame(double extraSpace) {
   this.isOnFrame = true;
   yOffset = plotSheet.getyRange()[0] - extraSpace;
 }