whole_func_string: function smoothPlotter(e) {
    var ctx = e.drawingContext,
        points = e.points;
  
    ctx.beginPath();
    ctx.moveTo(points[0].canvasx, points[0].canvasy);
  
    // right control point for previous point
    var lastRightX = points[0].canvasx, lastRightY = points[0].canvasy;
  
    for (var i = 1; i < points.length; i++) {
      var p0 = points[i - 1],
          p1 = points[i],
          p2 = points[i + 1];
      p0 = p0 && isOK(p0.canvasy) ? p0 : null;
      p1 = p1 && isOK(p1.canvasy) ? p1 : null;
      p2 = p2 && isOK(p2.canvasy) ? p2 : null;
      if (p0 && p1) {
        var controls = getControlPoints({x: p0.canvasx, y: p0.canvasy},
                                        {x: p1.canvasx, y: p1.canvasy},
                                        p2 && {x: p2.canvasx, y: p2.canvasy},
                                        smoothPlotter.smoothing);
        // Uncomment to show the control points:
        // ctx.lineTo(lastRightX, lastRightY);
        // ctx.lineTo(controls[0], controls[1]);
        // ctx.lineTo(p1.canvasx, p1.canvasy);
        lastRightX = (lastRightX !== null) ? lastRightX : p0.canvasx;
        lastRightY = (lastRightY !== null) ? lastRightY : p0.canvasy;
        ctx.bezierCurveTo(lastRightX, lastRightY,
                          controls[0], controls[1],
                          p1.canvasx, p1.canvasy);
        lastRightX = controls[2];
        lastRightY = controls[3];
      } else if (p1) {
        // We're starting again after a missing point.
        ctx.moveTo(p1.canvasx, p1.canvasy);
        lastRightX = p1.canvasx;
        lastRightY = p1.canvasy;
      } else {
        lastRightX = lastRightY = null;
      }
    }
  
    ctx.stroke();
  }
func_code_string: function smoothPlotter(e) {
    var ctx = e.drawingContext,
        points = e.points;
  
    ctx.beginPath();
    ctx.moveTo(points[0].canvasx, points[0].canvasy);
  
    // right control point for previous point
    var lastRightX = points[0].canvasx, lastRightY = points[0].canvasy;
  
    for (var i = 1; i < points.length; i++) {
      var p0 = points[i - 1],
          p1 = points[i],
          p2 = points[i + 1];
      p0 = p0 && isOK(p0.canvasy) ? p0 : null;
      p1 = p1 && isOK(p1.canvasy) ? p1 : null;
      p2 = p2 && isOK(p2.canvasy) ? p2 : null;
      if (p0 && p1) {
        var controls = getControlPoints({x: p0.canvasx, y: p0.canvasy},
                                        {x: p1.canvasx, y: p1.canvasy},
                                        p2 && {x: p2.canvasx, y: p2.canvasy},
                                        smoothPlotter.smoothing);
        // Uncomment to show the control points:
        // ctx.lineTo(lastRightX, lastRightY);
        // ctx.lineTo(controls[0], controls[1]);
        // ctx.lineTo(p1.canvasx, p1.canvasy);
        lastRightX = (lastRightX !== null) ? lastRightX : p0.canvasx;
        lastRightY = (lastRightY !== null) ? lastRightY : p0.canvasy;
        ctx.bezierCurveTo(lastRightX, lastRightY,
                          controls[0], controls[1],
                          p1.canvasx, p1.canvasy);
        lastRightX = controls[2];
        lastRightY = controls[3];
      } else if (p1) {
        // We're starting again after a missing point.
        ctx.moveTo(p1.canvasx, p1.canvasy);
        lastRightX = p1.canvasx;
        lastRightY = p1.canvasy;
      } else {
        lastRightX = lastRightY = null;
      }
    }
  
    ctx.stroke();
  }
func_documentation_string: A plotter which uses splines to create a smooth curve. See tests/plotters.html for a demo. Can be controlled via smoothPlotter.smoothing