Respostas:
Como já foi dito: não existe uma representação exata do círculo usando as curvas de Bézier.
Para completar as outras respostas: para a curva de Bézier com n
segmentos, a distância ótima aos pontos de controle, no sentido de que o meio da curva está no próprio círculo, é (4/3)*tan(pi/(2n))
.
Então é por 4 pontos (4/3)*tan(pi/8) = 4*(sqrt(2)-1)/3 = 0.552284749831
.
Abrangido no comp.graphics.faq
Assunto 4.04: Como faço para ajustar uma curva de Bezier a um círculo?
Curiosamente, as curvas de Bézier podem se aproximar de um círculo, mas não se encaixam perfeitamente em um círculo. Uma aproximação comum é usar quatro beziers para modelar um círculo, cada um com pontos de controle a uma distância d = r * 4 * (sqrt (2) -1) / 3 dos pontos finais (onde r é o raio do círculo), e em uma direção tangente ao círculo nos pontos finais. Isso garantirá que os pontos médios dos Béziers estejam no círculo e que a primeira derivada seja contínua.
O erro radial nesta aproximação será de cerca de 0,0273% do raio do círculo.
Michael Goldapp, "Aproximação de arcos circulares por polinômios cúbicos" Computer Aided Geometric Design (# 8 1991 pp.227-238)
Tor Dokken e Morten Daehlen, "Good Approximations of circles by curvature-contínua Bezier curves" Computer Aided Geometric Design (# 7 1990 pp. 33-41). http://www.sciencedirect.com/science/article/pii/016783969090019N (artigo não gratuito)
Consulte também o artigo sem acesso pago em http://spencermortensen.com/articles/bezier-circle/
Observe que alguns navegadores usam curvas de Bezier para desenhar o arco de tela, o Chrome usa (atualmente) uma abordagem de 4 setores e o Safari usa uma abordagem de 8 setores, a diferença é perceptível apenas em alta resolução, por causa disso 0,0273%, e também apenas verdadeiramente visível quando os arcos são desenhados em paralelo e fora de fase, você notará que os arcos oscilam a partir de um círculo verdadeiro. O efeito também é mais perceptível quando a curva está animando em torno de seu centro radial, o raio de 600px geralmente é o tamanho em que fará a diferença.
Determinadas APIs de desenho não têm renderização de arco verdadeiro, então também usam curvas de Bezier, por exemplo, a plataforma Flash não tem API de desenho de arco, portanto, quaisquer estruturas que oferecem arcos geralmente usam a mesma abordagem de curva de Bezier.
Observe que os mecanismos SVG nos navegadores podem usar um método de desenho diferente.
Seja qual for a plataforma que você está tentando usar, vale a pena verificar como o desenho do arco é feito, para que você possa prever erros visuais como este e se adaptar.
As respostas à pergunta são muito boas, então há pouco a acrescentar. Inspirado nisso, comecei a fazer um experimento para confirmar visualmente a solução, começando com quatro curvas de Bézier, reduzindo o número de curvas para uma. Surpreendentemente, descobri que com três curvas de Bézier o círculo parecia bom o suficiente para mim, mas a construção é um pouco complicada. Na verdade, usei o Inkscape para colocar a aproximação Bézier preta de 1 pixel de largura sobre um círculo vermelho de 3 pixels de largura (como produzido pelo Inkscape). Para esclarecimento, adicionei linhas e superfícies azuis mostrando as caixas delimitadoras das curvas de Bézier.
Para se ver, estou apresentando meus resultados:
O gráfico de 1 curva (que parece uma gota espremida em um canto, apenas para completar):
(Eu queria colocar o SVG ou PDF aqui, mas isso não é compatível)
Muitas respostas já, mas encontrei um pequeno artigo online com uma aproximação Bezier cúbica muito boa de um círculo. Em termos de círculo unitário c = 0,55191502449 onde c é a distância dos pontos de interceptação do eixo ao longo das tangentes aos pontos de controle.
Como um único quadrante para o círculo unitário com as duas coordenadas do meio sendo os pontos de controle. (0,1),(c,1),(1,c),(1,0)
O erro radial é de apenas 0,019608%, então eu só tive que adicioná-lo a esta lista de respostas.
O artigo pode ser encontrado aqui Aproximar um círculo com curvas de Bézier cúbicas
Não é possível. Um Bézier é um cúbico (pelo menos ... o mais comumente usado é). Um círculo não pode ser expresso exatamente com uma cúbica, porque um círculo contém uma raiz quadrada em sua equação. Como consequência, você deve aproximar.
Para fazer isso, você deve dividir seu círculo em n-tants (por exemplo, quadrantes, octantes). Para cada n-tant, você usa o primeiro e o último ponto como o primeiro e o último da curva de Bézier. O polígono de Bézier requer dois pontos adicionais. Para ser rápido, eu pegaria as tangentes ao círculo para cada ponto extremo da n-tante e escolheria os dois pontos como a interseção das duas tangentes (de modo que basicamente seu polígono de Bezier seja um triângulo). Aumente o número de n-tants para se ajustar à sua precisão.
As outras respostas cobriram o fato de que um círculo verdadeiro não é possível. Este arquivo SVG é uma aproximação usando curvas quadráticas de Bezier e é a coisa mais próxima que você pode obter: http://en.wikipedia.org/wiki/File:Circle_and_quadratic_bezier.svg
Aqui está um com curvas Cúbicas de Bézier: http://en.wikipedia.org/wiki/File:Circle_and_cubic_bezier.svg
Para pessoas que estão apenas procurando por 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>
Isso permite desenhar um círculo que é feito de 4 curvas de Bezier. Escrito em JS, mas pode ser facilmente traduzido para qualquer outro idioma
Não tenho certeza se devo abrir uma nova questão, pois se trata de aproximação, mas estou interessado na fórmula geral para obter pontos de controle para Bézier de qualquer grau e acredito que se encaixa nesta questão. Todas as soluções que encontrei na web são só para curvas cúbicas ou são pagas ou nem entendo (não sou muito bom em matemática). Então decidi tentar resolver isso sozinho. Eu estudei a distância do ponto de controle do centro de um círculo dependendo do ângulo dado e até agora descobri que:
Onde N
é o número de pontos de controle para uma única curva e α
é o ângulo do arco do círculo.
Para a curva quadrática, pode ser simplificado para l ≈ r + r * PI*0.1 * pow(α/90, 2)
The PI*0.1
é um pouco um palpite - eu não calculei o valor perfeito, mas está bem próximo. Isso funciona razoavelmente bem para curva com 1-2 pontos de controle, dando erro de raio de cerca de 0,2% para curva cúbica. Para curvas de grau mais alto, a perda de precisão é perceptível. Com 3 pontos de controle, a curva é semelhante à quadrática, então obviamente estou perdendo algo, mas não consigo descobrir e esse método geralmente se adapta às minhas necessidades por enquanto. Aqui está a demonstração .
Desculpe por trazer este de volta dos mortos, mas eu achei este post muito útil junto com esta página em chegar a uma fórmula expansível.
Basicamente, você pode criar um círculo próximo usando uma fórmula incrivelmente simples que permite usar qualquer número de curvas de Bezier acima de 4: Distance = radius * stepAngle / 3
Onde Distance
é a distância entre um ponto de controle de Bézier e a extremidade mais próxima do arco, raio é o radius
do círculo e stepAngle
é o ângulo entre as 2 extremidades do arco, representado por 2π / (o número de curvas).
Então, para acertar em um tiro: Distance = radius * 2π / (the number of curves) / 3
Distance = (4/3)*tan(pi/2n)
. Para um grande número de arcos é quase o mesmo porque tan(pi/2)~pi/2n
, mas por exemplo para n=4
(que é o caso mais usado) sua fórmula dá, Distance=0.5235...
mas o ideal é Distance=0.5522...
(então você tem ~ 5% de erro).
É uma aproximação pesada que parecerá razoável ou terrível dependendo da resolução e precisão, mas eu uso sqrt (2) / 2 x radius como meus pontos de controle. Eu li um texto bastante longo sobre como esse número é derivado e vale a pena ler, mas a fórmula acima é rápida e suja.