I answer this old question (which should belong to mathematics, so writing formulas would be awful) with some demos.
Suppose that P0 and P3 are your starting and ending points of your arc, P1 and P2 are the control points of the Bezier curve, and x is a measure of the angle divided by two. Suppose x is less than pi / 2.
Let PM be the midpoint of the segment P0P3 and PH the midpoint of the arc. To bring the arc closer, we want the Bezier curve to start at P0, pass through PH, end at P3 and touch the arc at P0 and P3.
(Click Run Code Snippet to display the drawing. Curses to imgur still does not support SVG.)
<svg xmlns="http://www.w3.org/2000/svg" viewBox="10 20 80 80"> <style>text{font-size:40%;font-style:italic;text-anchor:middle}tspan{font-size:50%;font-style:normal}</style> <rect x="10" y="20" width="80" height="80" fill="none" stroke="gray"></rect> <path stroke="gray" stroke-dasharray="3,2" fill="none" d="M25,30 62.6,31.62 80,65 22.19,95.13 25,30 80,65 M22.19,95.13 62.6,31.62"></path> <path stroke="black" fill="none" d="M25,30A65.19 65.19 0 0 1 80,65"></path> <circle r="1" fill="red" cx="25" cy="30"></circle> <circle r="1" fill="green" cx="80" cy="65"></circle> <circle r="1" fill="magenta" cx="22.19" cy="95.13"></circle> <circle r="1" fill="darkgreen" cx="52.5" cy="47.5"></circle> <circle r="1" fill="yellow" cx="57.19" cy="40.13"></circle> <circle r="1" fill="maroon" cx="62.6" cy="31.62"></circle> <circle r="1" fill="orange" cx="48.27" cy="31"></circle> <circle r="1" fill="teal" cx="69.24" cy="44.35"></circle> <text x="25" y="28">P<tspan>0</tspan></text> <text x="48.27" y="29">P<tspan>1</tspan></text> <text x="71.24" y="42.35">P<tspan>2</tspan></text> <text x="83" y="63">P<tspan>3</tspan></text> <text x="62.6" y="29.62">P<tspan>E</tspan></text> <text x="59.19" y="47.13">P<tspan>H</tspan></text> <text x="54.5" y="54.5">P<tspan>M</tspan></text> </svg>
Let PE be the intersection of lines tangent to an arc in P0 and P3. For the curve to touch the arc, P1 must lie on the segment P0PE, and P2 must lie on P3PE. Let k be the ratio of P0P1 / P0PE (also equal to P3P2 / P3PE):
P1 = (1 - k) P0 + k PE
P2 = (1 - k) P3 + k PE
We also have the following (we do some proportions):
PM = (P0 + P3) / 2
PH = PM / cos (x) = PM sec (x) = (P0 + P3) sec (x) / 2
PE = PH / cos (x) = PM sec (x) ^ 2 = (P0 + P3) sec (x) ^ 2/2
To simplify our calculations, I believed that all vector points are based on the center, but in the end, it does not matter.
The general 4-point Bezier curve is given by the formula
C (t) = t ^ 3 P3 + 3 (1 - t) t ^ 2 P2 + 3 (1 - t) ^ 2 t P1 + (1 - t) ^ 3 P0
We must have C (1/2) = PH, therefore
C (1/2) = (P0 + 3 P1 + 3 P2 + P3) / 8
= ((P0 + P3) + 3 (1 - k) P0 + 3 k PE + 3 (1 - k) P3 + 3 k PE) / 8
= ((P0 + P3) + 3 (1 - k) (P0 + P3) + 6 k PE) / 8
= (P0 + P3) (1 + 3 (1 - k) + 3 ks (x) ^ 2) / 8
So this is our equation (multiplied by 8) to find k:
8 C (1/2) = 8 PH
=> (P0 + P3) (4 - 3 k + 3 k sec (x) ^ 2) = 4 (P0 + P3) sec (x)
. Get rid of the vectors (P0 + P3) and get:
4 - 3 k + 3 k sec (x) ^ 2 = 4 s (x)
=> 3 k (sec (x) ^ 2 - 1) = 4 (sec (x) - 1)
=> k = 4/3 (sec (x) + 1)
Now you know where to place the control points. Hurrah!
If you have x = pi / 4, you get k = 0.552 ... You may have seen this value.
When working with elliptical arcs, all you have to do is scale the coordinates of the points accordingly.
If you have to deal with large angles, I suggest breaking them down into more curves. This is actually what some programs do when drawing arcs, since calculating a Bezier curve is sometimes faster than using sines and cosines.