Mamy punkt początkowy (x, y) i promień okręgu. Istnieje również silnik, który może tworzyć ścieżkę z punktów krzywej Béziera.
Jak mogę utworzyć okrąg za pomocą krzywych Béziera?
Odpowiedzi:
Jak już powiedziano: nie ma dokładnej reprezentacji koła za pomocą krzywych Beziera.
Aby uzupełnić pozostałe odpowiedzi: dla krzywej Beziera z n
segmentami optymalna odległość od punktów kontrolnych, w tym sensie, że środek krzywej leży na samym okręgu, wynosi (4/3)*tan(pi/(2n))
.
A więc za 4 punkty (4/3)*tan(pi/8) = 4*(sqrt(2)-1)/3 = 0.552284749831
.
Omówione w comp.graphics.faq
Przedmiot 4.04: Jak dopasować krzywą Beziera do koła?
Co ciekawe, krzywe Beziera mogą przybliżać okrąg, ale nie idealnie do niego pasują. Powszechnym przybliżeniem jest użycie czterech bezierów do modelowania koła, z których każdy ma punkty kontrolne w odległości d = r * 4 * (sqrt (2) -1) / 3 od punktów końcowych (gdzie r jest promieniem okręgu) i kierunek styczny do okręgu w punktach końcowych. Zapewni to, że punkty środkowe Beziers znajdują się na okręgu, a pierwsza pochodna jest ciągła.
Błąd promieniowy w tym przybliżeniu wyniesie około 0,0273% promienia okręgu.
Michael Goldapp, „Aproksymacja łuków kołowych za pomocą wielomianów sześciennych” Computer Aided Geometric Design (# 8 1991 str. 227-238)
Tor Dokken i Morten Daehlen, "Dobre przybliżenie okręgów za pomocą krzywych Beziera z ciągłą krzywizną" Computer Aided Geometric Design (# 7 1990 str. 33-41). http://www.sciencedirect.com/science/article/pii/016783969090019N (artykuł płatny)
Zapoznaj się również z artykułem nieobjętym płatnymi ścianami dostępnymi pod adresem http://spencermortensen.com/articles/bezier-circle/
Zwróć uwagę, że niektóre przeglądarki używają krzywych Beziera do ich rysowania na płótnie, Chrome używa (obecnie) podejścia 4-sektorowego, a Safari używa podejścia 8-sektorowego, różnica jest zauważalna tylko przy wysokiej rozdzielczości, z powodu tego 0,0273%, a także naprawdę widoczne tylko wtedy, gdy łuki są rysowane równolegle i poza fazą, zauważysz, że łuki oscylują od prawdziwego koła. Efekt jest również bardziej zauważalny, gdy krzywa animuje się wokół jej środka promieniowego, promień 600 pikseli to zwykle rozmiar, w którym będzie miał znaczenie.
Niektóre interfejsy API do rysowania nie mają rzeczywistego renderowania łuków, więc używają również krzywych Beziera, na przykład platforma Flash nie ma interfejsu API do rysowania łuków, więc wszelkie struktury oferujące łuki generalnie używają tego samego podejścia krzywej Beziera.
Należy pamiętać, że silniki SVG w przeglądarkach mogą używać innej metody rysowania.
Niezależnie od platformy, której próbujesz użyć, warto sprawdzić, jak odbywa się rysowanie łuku, aby móc przewidzieć takie błędy wizualne i dostosować się.
Odpowiedzi na to pytanie są bardzo dobre, więc niewiele jest do dodania. Zainspirowany tym zacząłem eksperymentować, aby wizualnie potwierdzić rozwiązanie, zaczynając od czterech krzywych Béziera, zmniejszając liczbę krzywych do jednego. O dziwo dowiedziałem się, że przy trzech krzywych Béziera okrąg wyglądał wystarczająco dobrze, ale konstrukcja jest nieco skomplikowana. Właściwie użyłem Inkscape do umieszczenia czarnego przybliżenia Béziera o szerokości 1 piksela na czerwonym kole o szerokości 3 pikseli (wyprodukowanym przez Inkscape). Dla jasności dodałem niebieskie linie i powierzchnie pokazujące obwiednie krzywych Béziera.
Aby zobaczyć siebie, przedstawiam swoje wyniki:
Wykres 1-krzywej (który wygląda jak kropla wciśnięta w róg, tylko dla kompletności):
(Chciałem umieścić tutaj SVG lub PDF, ale to nie jest obsługiwane)
Wiele odpowiedzi już jest, ale znalazłem mały artykuł online z bardzo dobrym sześciennym przybliżeniem beziera koła. Pod względem koła jednostkowego c = 0,55191502449, gdzie c jest odległością od punktów przecięcia osi wzdłuż stycznych do punktów kontrolnych.
Jako pojedyncza ćwiartka dla okręgu jednostkowego z dwoma środkowymi współrzędnymi będącymi punktami kontrolnymi. (0,1),(c,1),(1,c),(1,0)
Błąd promieniowy wynosi zaledwie 0,019608%, więc po prostu musiałem dodać go do tej listy odpowiedzi.
Artykuł można znaleźć tutaj Przybliż koło z sześciennymi krzywymi Béziera
To niemożliwe. Bezier to sześcienny (przynajmniej ... najczęściej używany jest). Nie można dokładnie wyrazić koła sześciennym, ponieważ koło zawiera pierwiastek kwadratowy w swoim równaniu. W konsekwencji musisz przybliżać.
Aby to zrobić, musisz podzielić swój krąg na n-tanty (np. Kwadranty, oktanty). Dla każdego n-tanta używasz pierwszego i ostatniego punktu jako pierwszego i ostatniego krzywej Beziera. Wielokąt Beziera wymaga dwóch dodatkowych punktów. Aby być szybkim, wziąłbym styczne do koła dla każdego skrajnego punktu n-tanta i wybrałbym te dwa punkty jako przecięcie dwóch stycznych (tak, aby zasadniczo twój wielokąt Beziera był trójkątem). Zwiększ liczbę n-tantów, aby dopasować swoją precyzję.
Inne odpowiedzi obejmowały fakt, że prawdziwe koło nie jest możliwe. Ten plik SVG jest przybliżeniem wykorzystującym kwadratowe krzywe Beziera i jest najbliższym możliwym do uzyskania: http://en.wikipedia.org/wiki/File:Circle_and_quadratic_bezier.svg
Oto jeden z krzywymi sześciennymi Beziera: http://en.wikipedia.org/wiki/File:Circle_and_cubic_bezier.svg
Dla osób, które tylko szukają kodu:
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>
Pozwala to narysować okrąg złożony z 4 krzywych Beziera. Napisany w JS, ale można go łatwo przetłumaczyć na inny język
Nie używaj krzywych Beziera, jeśli musisz narysować okrąg za pomocą ścieżki SVG, chyba że jest to wymagane. Na ścieżce możesz Arc
utworzyć 2 półokręgi.
Nie jestem pewien, czy powinienem otworzyć nowe pytanie, ponieważ dotyczy to aproksymacji, ale interesuje mnie ogólna formuła, aby uzyskać punkty kontrolne dla Beziera dowolnego stopnia i uważam, że pasuje do tego pytania. Wszystkie rozwiązania, które znalazłem w sieci, dotyczą tylko krzywych sześciennych, są płatne lub nawet nie rozumiem (nie jestem zbyt dobry z matematyki). Postanowiłem więc spróbować rozwiązać to samodzielnie. Zbadałem odległość punktu kontrolnego od środka koła w zależności od danego kąta i do tej pory stwierdziłem, że:
Gdzie N
jest liczbą punktów kontrolnych dla pojedynczej krzywej i α
jest kątem łuku koła.
W przypadku krzywej kwadratowej można to uprościć do: l ≈ r + r * PI*0.1 * pow(α/90, 2)
To PI*0.1
raczej przypuszczenie - nie obliczyłem idealnej wartości, ale jest dość blisko. Działa to dość dobrze dla krzywej z 1-2 punktami kontrolnymi, dając błąd promienia około 0,2% dla krzywej sześciennej. W przypadku krzywych wyższego stopnia zauważalna jest utrata dokładności. Z 3 punktami kontrolnymi krzywa wygląda podobnie do kwadratowej, więc oczywiście brakuje mi czegoś, ale nie mogę tego rozgryźć i ta metoda generalnie pasuje do moich potrzeb. Oto demo .
Przepraszam, że przywracam ten z martwych, ale uważam, że ten post wraz z tą stroną jest bardzo pomocny w tworzeniu rozszerzalnej formuły.
Zasadniczo możesz utworzyć bliskie koło za pomocą niewiarygodnie prostej formuły, która pozwala na użycie dowolnej liczby krzywych Beziera powyżej 4: Distance = radius * stepAngle / 3
Gdzie Distance
jest odległość między punktem kontrolnym Beziera a najbliższym końcem łuku, promień to radius
okrąg, a stepAngle
jest to kąt między dwoma końcami łuku reprezentowany przez 2π / (liczba krzywych).
Więc żeby trafić jednym strzałem: Distance = radius * 2π / (the number of curves) / 3
Distance = (4/3)*tan(pi/2n)
. Dla dużej liczby łuków jest prawie to samo, ponieważ tan(pi/2)~pi/2n
, ale na przykład dla n=4
(który jest najczęściej używanym przypadkiem) twoja formuła daje, Distance=0.5235...
ale optymalna jest Distance=0.5522...
(więc masz około 5% błędu).
To ciężkie przybliżenie, które będzie wyglądało rozsądnie lub okropnie w zależności od rozdzielczości i precyzji, ale używam sqrt (2) / 2 x radius jako moich punktów kontrolnych. Czytałem dość długi tekst, jak wyprowadza się tę liczbę i warto go przeczytać, ale powyższy wzór jest szybki i brudny.