I think you're missing the idea of what a control point is. Control points are generally not on the path itself. Instead they control how the curve of the path is shaped between points. See a spline tutorial for full details.
Now to the problem at hand, you have points on the curve but no actual control points. There are some techniques, like Cardinal Spline, for deriving control points to then pass to one of the curve drawing APIs you mention. You probably want the Path2D.Double
option so you can smoothly string together individual curves.
So for drawing from P1 to P2 to P3, instead of
Path2D.Double path1 = new Path2D.Double();
path1.moveTo(x1, y1);
path1.curveTo(x0, y0, x2, y2, x4, y4);
g.draw(path1);
You want
Path2D.Double path1 = new Path2D.Double();
path1.moveTo(x1, y1);
path1.curveTo(cx1a, cy1a, cx1b, cy1b, x2, y2);
path1.curveTo(cx2a, cy2a, cx2b, cy2b, x3, y3);
g.draw(path1);
where the cx
and cy
coordinates are your derived control points, two control points per cubic spline segment. Possibly,
cx1a = x1 + (x2 - x1) / 3;
cy1a = y1 + (y2 - y1) / 3;
cx1b = x2 - (x3 - x1) / 3;
cy1b = y2 - (y3 - y1) / 3;
cx2a = x2 + (x3 - x1) / 3;
cy2a = y2 + (y3 - y1) / 3;
cx2b = x3 - (x3 - x2) / 3;
cy2b = y3 - (y3 - y2) / 3;
The pattern here is that for the interior points (only P2 in this case) the control points before and after it (c1b and c2a) are offset by the slope of the line between the points before and after it (P1 and P3). For the edge points, the control points are based on the slope between that point and the next closest point.
If you have domain-specific information you might choose different control points. For instance, you might want to force the slopes at the end points to be 0.