// Update "shape" and "segments" from the current value of "points":
  void updateShape() {
    if (points.size() < 2) {
      shape = null;
      segments.clear();
      return;
    }
    // Pad out the control point list using wraparound,
    // to make a closed spline:

    ArrayList extraPoints = new ArrayList(points);
    extraPoints.add(0, points.get(points.size() - 2));
    extraPoints.add(1, points.get(points.size() - 1));
    extraPoints.add(points.get(0));
    extraPoints.add(points.get(1));

    // Rotate the padded points so generated segment indices will align
    // with indices in the points ArrayList:

    Object first = extraPoints.get(0);
    extraPoints.remove(0);
    extraPoints.add(first);

    GeneralPath path = new GeneralPath();

    int m = extraPoints.size();
    ensureBases(m);

    segments.clear();

    // Iterate over segments:
    for (int i = 3; i < m - 1; i++) {

      Polynomial xNum = new Polynomial(0);
      Polynomial yNum = new Polynomial(0);

      Polynomial xDen = new Polynomial(0);
      Polynomial yDen = new Polynomial(0);

      // Iterate over control points:
      for (int j = 0; j < m; j++) {

        Point2D p = (Point2D) extraPoints.get(j);

        BasisFunction basis = (BasisFunction) Bases.get(j);

        double px = p.getX();
        double py = p.getY();

        Polynomial xSegNum = basis.getSegment(i).multiply(px * Weight);
        Polynomial ySegNum = basis.getSegment(i).multiply(py * Weight);

        Polynomial xSegDen = basis.getSegment(i).multiply(Weight);
        Polynomial ySegDen = basis.getSegment(i).multiply(Weight);

        xNum = xNum.add(xSegNum);
        yNum = yNum.add(ySegNum);

        xDen = xDen.add(xSegDen);
        yDen = yDen.add(ySegDen);
      }
      Shape curve = Polynomial.createRationalShape(xNum, xDen, yNum, yDen, i, i + 1, .1);
      segments.add(curve);
      path.append(curve, true);
    }
    path.closePath();
    shape = path;
  }