Подтвердить что ты не робот

Как создать круг с кривыми Безье?

У нас есть начальная точка (x, y) и радиус окружности. Также существует механизм, который может создать путь от точек кривой Безье.

Как создать круг с использованием кривых Безье?

4b9b3361

Ответ 1

Как уже говорилось: точное отображение круга с использованием кривых Безье отсутствует.

Чтобы выполнить другие ответы: для кривой Безье с сегментами n оптимальное расстояние до контрольных точек в том смысле, что середина кривой лежит на самой окружности, равна (4/3)*tan(pi/(2n)).

formula for n segments

Итак, для 4 точек это (4/3)*tan(pi/8) = 4*(sqrt(2)-1)/3 = 0.552284749831.

4 point case

Ответ 2

Покрытие в comp.graphics.faq

Выдержки:

Тема 4.04: Как подогнать кривую Безье к кругу?

Интересно, что кривые Безье могут аппроксимировать круг, но не идеально подходит для круга. Общим приближением является использование четырех безьеров для моделирования круга, каждый с контрольными точками расстояние d = r * 4 * (sqrt (2) -1)/3 от конечных точек (где r - радиус окружности) и в направлении, касающемся круг в конечных точках. Это обеспечит средние точки Безье находится на круге и что первая производная непрерывна. Радиальная ошибка в этом приближении составит около 0,0273% от радиус окружности.

Майкл Гольдапп, "Приближение круговых дуг кубическим полиномы "Автоматизированный геометрический дизайн (№ 8, 1991, pp.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%, а также только по-настоящему видны, когда дуги рисуются параллельно и не соответствуют фазе, вы заметите, что дуги колеблются от истинного круга. Эффект также более заметен, когда кривая оживляет вокруг него радиальный центр, радиус 600 пикселей обычно имеет размер, где он будет иметь значение.

Некоторые API-интерфейсы рисования не имеют истинного дугового рендеринга, поэтому они также используют кривые Безье, например, флэш-платформа не имеет рисования дуги, поэтому любые каркасы, предлагающие дуги, обычно используют один и тот же подход кривой Безье.

Обратите внимание, что в SVG-системах внутри браузеров может использоваться другой метод рисования.

Другие платформы

Независимо от платформы, которую вы пытаетесь использовать, стоит проверить, как выполняется рисование дуги, поэтому вы можете предсказать визуальные ошибки, подобные этому, и адаптироваться.

Ответ 3

Ответы на вопрос очень хорошие, поэтому добавить особо нечего. Вдохновленный этим, я начал проводить эксперимент, чтобы визуально подтвердить решение, начиная с четырех кривых Безье, уменьшая количество кривых до одной. Удивительно, но я обнаружил, что с тремя кривыми Безье круг выглядел достаточно хорошо для меня, но конструкция немного сложнее. На самом деле я использовал Inkscape, чтобы поместить черное приближение Безье шириной в 1 пиксель по красному кругу шириной в 3 пикселя (как в Inkscape). Для пояснения я добавил синие линии и поверхности, показывающие ограничивающие рамки кривых Безье.

Чтобы увидеть себя, я представляю свои результаты:

1-кривой график (который выглядит как капля, сжатая в углу, только для полноты): enter image description here

2-кривой график: enter image description here

3-х кривой график: enter image description here

4-кривой график: enter image description here

(Я хотел разместить SVG или PDF здесь, но это не поддерживается)

Ответ 4

Это невозможно. Безье - куб (по крайней мере... наиболее часто используется). Круг не может быть точно выражен кубической, потому что круг содержит в своем уравнении квадратный корень. Как следствие, вы должны приблизиться.

Чтобы сделать это, вы должны разделить свой круг на n-tants (например, квадранты, октанты). Для каждого n-tant вы используете первую и последнюю точку в качестве первой и последней кривой Безье. Многоугольник Безье требует двух дополнительных точек. Чтобы быть быстрым, я принимал касательные к кругу для каждой крайней точки n-tant и выбирал две точки как пересечение двух касательных (так что в основном ваш многоугольник Безье является треугольником). Увеличьте количество n-tants, чтобы они соответствовали вашей точности.

Ответ 5

В других ответах был рассмотрен тот факт, что истинный круг невозможен. Этот SVG файл является приблизительным, используя кривые Quadratic Bezier, и это самое близкое, что вы можете получить: http://en.wikipedia.org/wiki/File:Circle_and_quadratic_bezier.svg

Здесь один с кривыми Кубического Безье: http://en.wikipedia.org/wiki/File:Circle_and_cubic_bezier.svg

Ответ 6

Уже много ответов, но я нашел небольшую онлайн-статью с очень хорошим кубическим безьевым приближением круга. В терминах единичного круга c = 0,55191502449, где c - расстояние от точек перехвата оси вдоль касательных к контрольным точкам.

Как единый квадрант для единичного круга с двумя средними координатами, являющимися контрольными точками. (0,1),(c,1),(1,c),(1,0)

Радиальная ошибка составляет всего 0,019608%, поэтому мне просто пришлось добавить ее в этот список ответов.

Статья находится здесь Приблизительный круг с кубическими кривыми Безье

Ответ 7

Я не уверен, что я должен открыть новый вопрос, так как это касается aproximation, но меня интересует общая формула для получения контрольных точек для Безье любой степени, и я считаю, что это соответствует этому вопросу. Все решения, которые я нашел в Интернете, предназначены только для кубических кривых или оплачиваются, или я даже не понимаю (я не очень хорошо разбираюсь в математике). Поэтому я решил попытаться решить это самостоятельно. Я изучал расстояние контрольной точки от центра круга, зависящего от заданного угла, и до сих пор я обнаружил, что:

enter image description here

Где N - количество контрольных точек для одной кривой, а α - угол дуги окружности.

Для квадратичной кривой ее можно упростить до l ≈ r + r * PI*0.1 * pow(α/90, 2) PI*0.1 скорее предположение - я не вычислил идеальную ценность, но это довольно близко. Это работает достаточно хорошо для кривой с 1-2 контрольными точками, давая ошибку радиуса около 0,2% для кубической кривой. Для кривых более высокой степени заметна потеря точности. С 3-мя контрольными точками кривая похожа на квадратичную, поэтому, очевидно, я что-то пропускаю, но я не могу понять это, и этот метод в целом соответствует моим потребностям. Вот демонстрация.

Ответ 8

Извините, что вы вернули это из мертвых, но я нашел этот пост очень полезным вместе с этой страницей при разработке расширяемой формулы.

В принципе, вы можете создать ближний круг, используя невероятно простую формулу, которая позволяет использовать любое количество кривых Безье над 4: Distance = radius * stepAngle / 3

Где Distance - расстояние между контрольной точкой Безье и ближайшим концом дуги, радиус - radius круга, а stepAngle - угол между двумя концами дуги, представленный 2π/(количество кривых).

Итак, чтобы поразить его одним выстрелом: Distance = radius * 2π / (the number of curves) / 3

Ответ 9

Для людей, которые просто ищут код:

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>

Ответ 10

Это тяжелое приближение, которое будет выглядеть разумным или ужасным в зависимости от разрешения и точности, но я использую sqrt (2)/2 x radius как мои контрольные точки. Я прочитал довольно длинный текст о том, как это число выведено и стоит его прочитать, но приведенная выше формула является быстрой и грязной.