code: public static float Spline(float x, int numKnots, int[] xknots, int[] yknots) {
          int span;
          int numSpans = numKnots - 3;
          float k0, k1, k2, k3;
          float c0, c1, c2, c3;
  
          if (numSpans < 1)
              throw new IllegalArgumentException("Too few knots in spline");
  
          for (span = 0; span < numSpans; span++)
              if (xknots[span + 1] > x)
                  break;
          if (span > numKnots - 3)
              span = numKnots - 3;
          float t = (float) (x - xknots[span]) / (xknots[span + 1] - xknots[span]);
          span--;
          if (span < 0) {
              span = 0;
              t = 0;
          }
  
          k0 = yknots[span];
          k1 = yknots[span + 1];
          k2 = yknots[span + 2];
          k3 = yknots[span + 3];
  
          c3 = -0.5f * k0 + 1.5f * k1 + -1.5f * k2 + 0.5f * k3;
          c2 = 1f * k0 + -2.5f * k1 + 2f * k2 + -0.5f * k3;
          c1 = -0.5f * k0 + 0f * k1 + 0.5f * k2 + 0f * k3;
          c0 = 0f * k0 + 1f * k1 + 0f * k2 + 0f * k3;
  
          return ((c3 * t + c2) * t + c1) * t + c0;
      }
docs: compute a Catmull-Rom spline, but with variable knot spacing.
  
  @param x        the input parameter
  @param numKnots the number of knots in the spline
  @param xknots   the array of knot x values
  @param yknots   the array of knot y values
  @return the spline value