Я отвечаю на этот старый вопрос (который должен принадлежать математике, поэтому написание формул будет ужасно) с некоторыми демонстрациями.
Предположим, P0 и P3 - ваша начальная и конечная точка вашей дуги, P1 и P2 контрольные точки Безье. кривая, а x - это мера угла, деленная на два. Предположим, что x меньше pi / 2.
Пусть PM средняя точка сегмента P0P3 и PH средняя точка дуги. Чтобы приблизить дугу, мы хотим, чтобы кривая Безье начиналась с P0 , проходила через PH , заканчивалась P3 и касалась к дуге в P0 и P3 .
(Нажмите на «Выполнить фрагмент кода», чтобы отобразить рисунок. Проклятия, которые будут игнорировать, пока не поддерживают 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>
Пусть PE пересечение линий, касающихся дуги в P0 и P3 . Чтобы кривая касалась дуги, P1 должен лежать на отрезке P0PE , а P2 должен лежать на P3PE, Пусть k будет отношением P0P1 / P0PE (также равным P3P2 / P3PE ):
P1 = (1 - k ) P0 + k PE
P2 = (1 - k ) P3 + k PE
У нас также есть следующее (сделать некоторые пропорции):
PM = ( P0 + P3 ) / 2
PH = PM / cos ( x ) = PM sec ( x ) = ( P0 + P3 ) сек ( x ) / 2
PE = PH / cos ( x ) = PM сек ( x ) ^ 2 = ( P0 + P3 ) сек ( x ) ^ 2/2
Чтобы упростить наши вычисления, я считал, что все векторные точки основаны на центре, но в итоге это не имеет значения.
Общая 4-точечная кривая Безье задается формулой
C ( t ) = t ^ 3 P3 + 3 (1 - t ) т ^ 2 П2 + 3 (1 - т ) ^ 2 т П1 + (1 - t ) ^ 3 P0
У нас должно быть C (1/2) = PH , поэтому
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 k сек ( х ) ^ 2) / 8
Итак, это наше уравнение (умноженное на 8), чтобы найти k :
8 C (1/2) = 8 PH
=> ( P0 + P3 ) (4 - 3 k + 3 k сек ( x * 1260) *) ^ 2) = 4 ( P0 + P3 ) сек ( x )
Давайте избавимся от векторов ( P0 + P3 ), и мы получим:
4 - 3 k + 3 k сек ( x ) ^ 2 = 4 сек ( x )
=> 3 k (с ( x ) ^ 2 - 1) = 4 (с ( x ) - 1)
=> k = 4/3 (сек ( x ) + 1)
Теперь вы знаете, где разместить контрольные точки. Ура!
Если у вас есть x = pi / 4, вы получите k = 0,552 ... Возможно, вы видели это значение около.
При работе с эллиптическими дугами достаточно лишь соответствующим образом масштабировать координаты точек.
Если вам приходится иметь дело с большими углами, я предлагаю разделить их на несколько кривых. Именно это и делают некоторые программы при рисовании дуг, поскольку вычисление кривой Безье иногда быстрее, чем использование синусов и косинусов.