Відповіді:
Як уже було сказано: точного представлення кола за допомогою кривих Безьє не існує.
Завершити інші відповіді: для кривої Безьє з n
відрізками є оптимальна відстань до контрольних точок, в тому сенсі, що середина кривої лежить на самому колі (4/3)*tan(pi/(2n))
.
Отже, за 4 бали це (4/3)*tan(pi/8) = 4*(sqrt(2)-1)/3 = 0.552284749831
.
Висвітлено у comp.graphics.faq
Тема 4.04: Як підігнати криву Безьє до кола?
Цікаво, що криві Безьє можуть наближати коло, але не цілком підходять до кола. Типовим наближенням є використання чотирьох безьє для моделювання кола, кожен із контрольних точок віддаляє d = r * 4 * (sqrt (2) -1) / 3 від кінцевих точок (де r - радіус кола), а в напрямок, дотичний до кола в кінцевих точках. Це забезпечить, щоб середні точки Безьє були на колі, а перша похідна неперервна.
Радіальна похибка в цьому наближенні становитиме приблизно 0,0273% від радіуса кола.
Майкл Голдапп, "Наближення кругових дуг кубічними многочленами" Геометричне проектування з використанням комп'ютера (№ 8 1991 р. 227-238)
Тор Доккен і Мортен Дален, "Хороші апроксимації кіл безперервними кривизною кривими Безьє" Геометричне проектування за допомогою комп'ютера (№7, 1990, с. 33-41). http://www.sciencedirect.com/science/article/pii/016783969090019N (не безкоштовна стаття)
Також див. Статтю про несплату за адресою http://spencermortensen.com/articles/bezier-circle/
Зверніть увагу, що деякі браузери використовують криві Безьє на своїй дузі для малювання полотна, Chrome використовує (в даний час) 4-секторний підхід, а Safari використовує 8-секторний підхід, різниця помітна лише при високій роздільній здатності, із-за цього 0,0273%, а також по-справжньому видно лише тоді, коли дуги намальовані паралельно та поза фазою, ви помітите, що дуги коливаються від справжнього кола. Ефект також помітніший, коли крива анімує навколо свого радіального центру, радіус 600px - це, як правило, розмір, де це може змінити ситуацію.
Деякі API малювання не мають справжнього рендерингу дуги, тому вони також використовують криві Безьє, наприклад, платформа Flash не має API дугового малювання, тому будь-які фреймворки, що пропонують дуги, зазвичай використовують той самий підхід кривої Безьє.
Зверніть увагу, що двигуни SVG у браузерах можуть використовувати інший спосіб малювання.
Незалежно від платформи, яку ви намагаєтесь використовувати, варто перевірити, як виконується дугоподібне малювання, щоб ви могли передбачити такі візуальні помилки та адаптуватись.
Відповіді на запитання дуже добрі, тому тут мало що додати. Натхненний тим, що я почав проводити експеримент для візуального підтвердження рішення, починаючи з чотирьох кривих Безьє, зменшуючи кількість кривих до однієї. На диво я дізнався, що з трьома кривими Безьє коло виглядало для мене досить добре , але конструкція трохи хитра. Насправді я використовував Inkscape для розміщення чорного наближення Безьє шириною 1 піксель над червоним колом шириною 3 пікселі (як виготовлено Inkscape). Для уточнення я додав сині лінії та поверхні, що показують обмежувальні рамки кривих Безьє.
Щоб побачити себе, я представляю свої результати:
Графік з 1 кривою (який виглядає як крапля, стиснута в кут, лише для повноти):
(Я хотів помістити сюди SVG або PDF, але це не підтримується)
Відповідей вже багато, але я знайшов невеличку статтю в Інтернеті з дуже хорошим кубічним безіє-наближенням кола. В умовах одиничного кола c = 0,55191502449 де c - відстань від точок перетину осі вздовж дотичних до контрольних точок.
Як єдиний квадрант для одиничного кола з двома середніми координатами, які є контрольними точками. (0,1),(c,1),(1,c),(1,0)
Радіальна помилка становить лише 0,019608%, тому мені просто довелося додати її до цього списку відповідей.
Статтю можна знайти тут Орієнтовне коло з кубічними кривими Безьє
Це неможливо. Безьє - це кубік (принаймні ... найчастіше використовується). Коло не можна точно виразити кубічним, оскільки коло містить у своєму рівнянні квадратний корінь. Як наслідок, вам доведеться наблизити.
Для цього вам потрібно розділити своє коло на n-танти (наприклад, квадранти, октанти). Для кожного n-танта ви використовуєте першу і останню точки як першу і останню криві Безьє. Багатокутник Безьє вимагає двох додаткових точок. Щоб бути швидким, я б відвів дотичні до кола для кожної крайньої точки n-танта і вибрав дві точки як перетину двох дотичних (так, щоб ваш багатокутник Безьє в основному був трикутником). Збільште кількість n-тантів відповідно до вашої точності.
Інші відповіді охоплюють той факт, що справжнє коло неможливе. Цей файл SVG є наближенням із використанням квадратичних кривих Безьє і є найближчим, що ви можете отримати: http://en.wikipedia.org/wiki/File:Circle_and_quadratic_bezier.svg
Ось один із кубічними кривими Безьє: http://en.wikipedia.org/wiki/File:Circle_and_cubic_bezier.svg
Людям, які просто шукають код:
https://jsfiddle.net/nooorz24/2u9forep/12/
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
function drawBezierOvalQuarter(centerX, centerY, sizeX, sizeY) {
ctx.beginPath();
ctx.moveTo(
centerX - (sizeX),
centerY - (0)
);
ctx.bezierCurveTo(
centerX - (sizeX),
centerY - (0.552 * sizeY),
centerX - (0.552 * sizeX),
centerY - (sizeY),
centerX - (0),
centerY - (sizeY)
);
ctx.stroke();
}
function drawBezierOval(centerX, centerY, sizeX, sizeY) {
drawBezierOvalQuarter(centerX, centerY, -sizeX, sizeY);
drawBezierOvalQuarter(centerX, centerY, sizeX, sizeY);
drawBezierOvalQuarter(centerX, centerY, sizeX, -sizeY);
drawBezierOvalQuarter(centerX, centerY, -sizeX, -sizeY);
}
function drawBezierCircle(centerX, centerY, size) {
drawBezierOval(centerX, centerY, size, size)
}
drawBezierCircle(200, 200, 64)
<canvas id="myCanvas" width="400" height="400" style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
Це дозволяє намалювати коло, яке складається з 4 кривих Безьє. Написано у форматі JS, але його легко перекласти на будь-яку іншу мову
Я не впевнений, чи слід мені відкривати нове питання, оскільки мова йде про наближення, але мене цікавить загальна формула, щоб отримати контрольні точки для Безьє будь-якого ступеня, і я вважаю, що це вписується в це питання. Усі рішення, які я знайшов в Інтернеті, стосуються лише кубічних кривих або платні, або я навіть не розумію (я не дуже добре володію математикою). Тому я вирішив спробувати вирішити це самостійно. Я вивчав відстань контрольної точки від центру кола залежно від даного кута і до цього часу виявив, що:
Де N
число контрольних точок для однієї кривої і α
кут дуги кола.
Для квадратичної кривої її можна спростити до: l ≈ r + r * PI*0.1 * pow(α/90, 2)
Це PI*0.1
швидше здогадка - я не розрахував ідеальне значення, але це досить близько. Це працює досить добре для кривої з 1-2 контрольними точками, що дає похибку радіусу близько 0,2% для кубічної кривої. Для кривих вищого ступеня помітна втрата точності. Крива з 3 контрольними точками виглядає схожою на квадратичну, тому, очевидно, я щось пропускаю, але я не можу це зрозуміти, і цей метод наразі відповідає моїм потребам. Ось демо .
Вибачте, що поверну це з мертвих, але я знайшов цю публікацію дуже корисною разом із цією сторінкою при розробці розширюваної формули.
В основному, ви можете створити близьке коло, використовуючи неймовірно просту формулу, яка дозволяє використовувати будь-яку кількість кривих Безьє за 4: Distance = radius * stepAngle / 3
Де Distance
відстань між контрольною точкою Безьє та найближчим кінцем дуги, радіус - це radius
окружність, а stepAngle
це кут між 2 кінцями дуги, як представлено 2π / (кількість кривих).
Тож вдарити його одним пострілом: Distance = radius * 2π / (the number of curves) / 3
Distance = (4/3)*tan(pi/2n)
. Для великої кількості дуг це майже однаково, оскільки tan(pi/2)~pi/2n
, але, наприклад, для n=4
(що є найбільш вживаним випадком) ваша формула дає, Distance=0.5235...
але оптимальною є Distance=0.5522...
(отже, у вас є помилка ~ 5%).
Це важке наближення, яке буде виглядати розумно або жахливо залежно від роздільної здатності та точності, але я використовую sqrt (2) / 2 x радіус як свої контрольні точки. Я прочитав досить довгий текст, як виводиться це число, і його варто прочитати, але формула вище - швидка і брудна.