Controls points that go through a Bezier point with a given angle, lie on the tangent with that angle.
The resulting bending will be the softer the farther away the control point is chosen, so there are many different solutions with the same angle and different curvature..

To find control points with equally soft curvatures for two Bezier points simply find the crossing of the two tangents! Use the crossing as the common control point for both segments, i.e. have C1 = C2.
For any sort of symmetrical curve you need to keep the deviations from the crossing symmetrical, i.e. 50%, 10% etc..
Note that for optimizing the overall shape one also needs to look at the neighbouring points; in general the provided GDI function does a good job; so it is worth considering simply adding more Bezier points for controlling the shape; but of course using the perfect set of control points is the most economic solution.
Update: I have added an example of how well a circle (orange) gets approximated by the math in this interesting post.
Short version: An exact solution isn't really possible but the best fit for a quarter circle is to move the control point to ~0.55% of the crossing point. (d=r*4*(sqrt(2)-1)/3
). Sometimes instead of using a 4 segment solution an 8 segment solution is used for even closer approximation..
private void button_Click(object sender, EventArgs e)
{
int w = Math.Abs(P2.Left - P1.Left);
int h = Math.Abs(P2.Top - P1.Top);
C2.Left = (int) (P2.Left + w * 0.5523f);
C2.Top = P2.Top;
C1.Left = P1.Left;
C1.Top = (int) (P1.Top + h * 0.5523f);
C1.Parent.Invalidate();
}
The code uses Labels
for the points and control points..
Btw: Adding ellipses/circles to a GraphicsPath
will create bezier curves that seem to be approximated just like that.