public void init(final Function function) {
    xAxis.clear();
    yAxis.clear();

    if (function != lastFunction) { // need to reset
      Slot.CIRCLE.clearList();
      Slot.CROSS.clearList();
      Slot.SQUARE.clearList();
      Slot.TRIANGLE.clearList();
    }

    data = new GridPointData(resolution, resolution, 1);
    plot = new InterpolatedPlot(data);

    useSlot.clearList();
    final List<List<ValuePointColored>> points = useSlot.getPoints();
    for (Slot slot : Slot.values()) {
      if (slot.isShow()) {
        for (List<ValuePointColored> valuePoints : slot.getPoints()) {
          for (ValuePointColored valuePoint : valuePoints) {
            xAxis.add(valuePoint);
            yAxis.add(valuePoint);
          }
        }
      }
    }

    // clean drawing panel
    drawablePanel.removeDrawables(InterpolatedPlot.class);
    drawablePanel.addDrawable(plot);

    datasetRecreation =
        new Closure() {

          public void execute(Object input) {
            List<ValuePointColored> vps = (List<ValuePointColored>) input;
            points.add(vps);
            for (ValuePointColored vp : vps) {
              xAxis.add(vp);
              yAxis.add(vp);
            }

            if (points.size() > maxPoints) {
              List<ValuePointColored> removed = points.remove(0);
              for (ValuePointColored valuePoint : removed) {
                xAxis.remove(valuePoint);
                yAxis.remove(valuePoint);
              }
            }

            // for ilustration
            if (xAxis.size() > 0 && yAxis.size() > 0) {
              double lowerXBound =
                  Math.min(
                      data.getLeft(), Math.floor(xAxis.first().getPoint().toArray()[0] - buffer));
              double upperXBound =
                  Math.max(
                      data.getRight(), Math.ceil(xAxis.last().getPoint().toArray()[0] + buffer));
              double lowerYBound =
                  Math.min(
                      data.getBottom(), Math.floor(yAxis.first().getPoint().toArray()[1] - buffer));
              double upperYBound =
                  Math.max(data.getTop(), Math.ceil(yAxis.last().getPoint().toArray()[1] + buffer));

              data.setScale(lowerXBound, upperXBound, lowerYBound, upperYBound);
              double[][][] xyz = data.getData();

              for (int i = 0; i < resolution; i++) {
                for (int j = 0; j < resolution; j++) {
                  Point p = Point.at(xyz[i][j]);
                  // check the cached value of the point
                  xyz[i][j][2] = /*cache.containsKey(p) ? cache.get(p) :*/ function.valueAt(p);
                }
              }
            }

            plot.setGridData(data);

            drawablePanel.repaint();
          }
        };

    lastFunction = function;

    // initialize to center point
    double lowerXBound = Math.floor(centerX - buffer);
    double upperXBound = Math.ceil(centerX + buffer);
    double lowerYBound = Math.floor(centerY - buffer);
    double upperYBound = Math.ceil(centerY + buffer);

    data.setScale(lowerXBound, upperXBound, lowerYBound, upperYBound);
    double[][][] xyz = data.getData();

    for (int i = 0; i < resolution; i++) {
      for (int j = 0; j < resolution; j++) {
        Point p = Point.at(xyz[i][j]);
        // check the cached value of the point
        xyz[i][j][2] = /*cache.containsKey(p) ? cache.get(p) :*/ function.valueAt(p);
      }
    }

    plot.setGridData(data);
    drawablePanel.repaint();
  }
 public void setShowCrossSlot(boolean showCrossSlot) {
   Slot.CROSS.setShow(showCrossSlot);
 }
 public PropertyState getShowCrossSlotState() {
   return Slot.CROSS.getPoints().isEmpty() ? PropertyState.DISABLED : PropertyState.ENABLED;
 }
 public boolean isShowCrossSlot() {
   return Slot.CROSS.isShow();
 }