Respuestas:
Como ya se dijo: no hay una representación exacta del círculo usando curvas de Bezier.
Para completar las otras respuestas: para la curva de Bezier con n
segmentos, la distancia óptima a los puntos de control, en el sentido de que la mitad de la curva se encuentra en el círculo mismo, es (4/3)*tan(pi/(2n))
.
Así que por 4 puntos lo es (4/3)*tan(pi/8) = 4*(sqrt(2)-1)/3 = 0.552284749831
.
Cubierto en comp.graphics.faq
Asunto 4.04: ¿Cómo encajo una curva de Bezier en un círculo?
Curiosamente, las curvas de Bezier pueden aproximarse a un círculo pero no encajar perfectamente en un círculo. Una aproximación común es usar cuatro beziers para modelar un círculo, cada uno con puntos de control a una distancia d = r * 4 * (sqrt (2) -1) / 3 desde los puntos finales (donde r es el radio del círculo), y en una dirección tangente al círculo en los puntos finales. Esto asegurará que los puntos medios de los Beziers estén en el círculo y que la primera derivada sea continua.
El error radial en esta aproximación será de aproximadamente 0.0273% del radio del círculo.
Michael Goldapp, "Aproximación de arcos circulares por polinomios cúbicos" Diseño geométrico asistido por computadora (# 8 1991 pp.227-238)
Tor Dokken y Morten Daehlen, "Buenas aproximaciones de círculos por curvas de Bézier continuas de curvatura" Diseño geométrico asistido por computadora (# 7 1990 pp. 33-41). http://www.sciencedirect.com/science/article/pii/016783969090019N (artículo no gratuito)
Vea también el artículo sin muro de pago en http://spencermortensen.com/articles/bezier-circle/
Tenga en cuenta que algunos navegadores usan curvas de Bezier para su arco de dibujo de lienzo, Chrome usa (en este momento) un enfoque de 4 sectores y Safari usa un enfoque de 8 sectores, la diferencia es notable solo en alta resolución, debido a ese 0.0273%, y también solo realmente visible cuando los arcos se dibujan en paralelo y fuera de fase, notará que los arcos oscilan desde un círculo verdadero. El efecto también es más notorio cuando la curva se anima alrededor de su centro radial, el radio de 600 px suele ser el tamaño donde marcará la diferencia.
Ciertas API de dibujo no tienen una verdadera representación de arco, por lo que también usan curvas de Bezier, por ejemplo, la plataforma Flash no tiene una API de dibujo de arco, por lo que cualquier marco que ofrezca arcos generalmente utiliza el mismo enfoque de curva de Bezier.
Tenga en cuenta que los motores SVG de los navegadores pueden utilizar un método de dibujo diferente.
Independientemente de la plataforma que intente usar, vale la pena verificar cómo se realiza el dibujo del arco, para que pueda predecir errores visuales como este y adaptarse.
Las respuestas a la pregunta son muy buenas, por lo que hay poco que agregar. Inspirado por eso, comencé a hacer un experimento para confirmar visualmente la solución, comenzando con cuatro curvas de Bézier, reduciendo el número de curvas a una. Sorprendentemente, descubrí que con tres curvas Bézier, el círculo se veía lo suficientemente bien para mí, pero la construcción es un poco complicada. De hecho, utilicé Inkscape para colocar la aproximación de Bézier negra de 1 píxel de ancho sobre un círculo rojo de 3 píxeles de ancho (como lo produjo Inkscape). Para aclarar, agregué líneas y superficies azules que muestran los cuadros delimitadores de las curvas de Bézier.
Para verte a ti mismo, te presento mis resultados:
El gráfico de 1 curva (que parece una gota apretada en una esquina, solo para completar):
(Quería poner el SVG o PDF aquí, pero no es compatible)
Ya hay muchas respuestas, pero encontré un pequeño artículo en línea con una muy buena aproximación bézier cúbica de un círculo. En términos de círculo unitario c = 0.55191502449 donde c es la distancia desde los puntos de intersección del eje a lo largo de las tangentes a los puntos de control.
Como un solo cuadrante para el círculo unitario con las dos coordenadas del medio como puntos de control. (0,1),(c,1),(1,c),(1,0)
El error radial es solo 0.019608%, así que solo tuve que agregarlo a esta lista de respuestas.
El artículo se puede encontrar aquí Aproximadamente un círculo con curvas de Bézier cúbicas
No es posible. Un Bezier es un cúbico (al menos ... el más utilizado es). Un círculo no se puede expresar exactamente con un cúbico, porque un círculo contiene una raíz cuadrada en su ecuación. Como consecuencia, debe aproximarse.
Para hacer esto, debes dividir tu círculo en n-tantes (por ejemplo, cuadrantes, octantes). Para cada n-tant, usa el primer y último punto como el primero y el último de la curva de Bezier. El polígono de Bezier requiere dos puntos adicionales. Para ser rápido, tomaría las tangentes al círculo para cada punto extremo del n-tant y elegiría los dos puntos como la intersección de las dos tangentes (de modo que básicamente su polígono Bezier sea un triángulo). Aumente el número de n-tantes para adaptarse a su precisión.
Las otras respuestas han cubierto el hecho de que no es posible un verdadero círculo. Este archivo SVG es una aproximación que utiliza curvas cuadráticas de Bezier y es lo más parecido que puede obtener: http://en.wikipedia.org/wiki/File:Circle_and_quadratic_bezier.svg
Aquí hay uno con curvas Cubic Bezier: http://en.wikipedia.org/wiki/File:Circle_and_cubic_bezier.svg
Para las personas que solo buscan código:
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>
Esto permite dibujar un círculo que está formado por 4 curvas Bezier. Escrito en JS pero se puede traducir fácilmente a cualquier otro idioma
No estoy seguro de si debería abrir una nueva pregunta ya que se trata de aproximación, pero estoy interesado en la fórmula general para obtener puntos de control para Bezier de cualquier grado y creo que encaja dentro de esta pregunta. Todas las soluciones que encontré en la web son solo para curvas cúbicas o se pagan o ni siquiera entiendo (no soy muy bueno en matemáticas). Así que decidí intentar resolver esto por mi cuenta. Estaba estudiando la distancia del punto de control desde el centro de un círculo dependiendo del ángulo dado y hasta ahora encontré que:
Donde N
es el número de puntos de control para una sola curva y α
es el ángulo del arco del círculo.
Para una curva cuadrática, se puede simplificar a l ≈ r + r * PI*0.1 * pow(α/90, 2)
The PI*0.1
es más bien una suposición: no calculé el valor perfecto, pero está bastante cerca. Esto funciona razonablemente bien para la curva con 1-2 puntos de control que dan un error de radio de aproximadamente 0,2% para la curva cúbica. Para curvas de mayor grado, la pérdida de precisión es notable. Con 3 puntos de control, la curva parece similar a la cuadrática, así que obviamente me pierdo algo, pero no puedo resolverlo y este método generalmente se ajusta a mis necesidades por ahora. Aquí está la demostración .
Lamento traer este de entre los muertos, pero encontré esta publicación muy útil junto con esta página para crear una fórmula expandible.
Básicamente, puede crear un círculo cercano usando una fórmula increíblemente simple que le permite usar cualquier número de curvas Bezier sobre 4: Distance = radius * stepAngle / 3
Donde Distance
es la distancia entre un punto de control de Bezier y el extremo más cercano del arco, el radio es el radius
del círculo y stepAngle
es el ángulo entre los 2 extremos del arco representado por 2π / (el número de curvas).
Entonces, para golpearlo de una vez: Distance = radius * 2π / (the number of curves) / 3
Distance = (4/3)*tan(pi/2n)
. Para un gran número de arcos es casi lo mismo porque tan(pi/2)~pi/2n
, pero por ejemplo para n=4
(que es el caso más utilizado) su fórmula da Distance=0.5235...
pero la óptima es Distance=0.5522...
(por lo que tiene un error de ~ 5%).
Es una aproximación pesada que se verá razonable o terrible dependiendo de la resolución y precisión, pero yo uso sqrt (2) / 2 x radio como mis puntos de control. Leí un texto bastante largo sobre cómo se deriva ese número y vale la pena leerlo, pero la fórmula anterior es rápida y sucia.