As mohsenmadi has already pointed out: in general, this is not something you can do without coming up with your own error indicator. Another idea is to “well allow you to approximate this curve as a sequence of lower order curves”, so that we get something that looks better and does not actually require error rates. This is a bit like “smoothing” a curve on a line, but instead of lines we will use cubic Bezier segments, which gives attractive curves, while preserving all the “acceptable” for modern graphics libraries.
Then what we can do is this: divide this “100th order curve” into a sequence of Bezier cubic, selectively using the curve at regular intervals, and then passing these points through the Catmull-Rom algorithm. The procedure is quite simple:
- Select some regular intervals for
t , for example 0, 0.2, 0.4, 0.6, 0.8 and 1, then - create a set of points tvalues.map (t => getCoordinate (curve, t)). Then,
- build a virtual start and end point: by forming point
0 , starting from point 1 and moving backward along its tangent and forming a point n+1 , starting from n and following its tangent. We do this because: - build poly-Catmull-Rom, starting at virtual point
0 and ending at virtual point n+1 .
Do it in the pictures. Let's start with the 11th order Bezier curve:

And then just let it check at regular intervals:

We come up with the 0th and n + 1st points:

And then we run the Catmull-Rom procedure:
i = 0 e = points.length-4 curves = [] do { crset = points.subset(i, 4) curves.push(formCRCurve(crset)) } while(i++<e)
What does formCRCurve do? Good question:
formCRCurve(points: p1, p2, p3, p4): d_start = vector(p2.x - p1.x, p2.y - p1.y) d_end = vector(p4.x - p3.x, p4.y - p3.y) return Curve(p2, d_start, d_end, p3)
So, we see why we need these virtual points: given the four points, we can form a Kathmull-Rum curve from points 2 to 3, using the tangent information that we get with a little help from points 1 and 4.
Of course, we really want Bezier curves, not Catmull-Roma curves, but since they are the same “view” of the curve, we can freely convert between the two , therefore:
i = 0 e = points.length-4 bcurves = [] do { pointset = points.subset(i, 4) bcurves.push(formBezierCurve(pointset)) } while(i++<e) formBezierCurve(points: p1, p2, p3, p4): return bezier( p2, p2 + (p3 - p1)/6 p3 - (p4 - p2)/6 p3 )
Thus, a Catmull-Rom curve based on points {p1, p2, p3, p4} passing through points p2 and p3 can be written as an equivalent Bezier curve that uses start / control1 / control2 / end coodinates p2 , p2 + (p3 - p1)/6 , p3 - (p4 - p2)/6 and p3 .