Składanie wstążki papieru, na zawsze
Weź długą wstążkę papieru i złóż ją w połowie, zawsze w tym samym kierunku. Zrób to raz: jeden zgięcie. Zrób to cztery razy i rozłóż każde zgięcie do kąta prostego: otrzymasz smoka Hejwaya, tę samą krzywą, którą zauważyli inżynierowie NASA na marginesach rysunków technicznych i tę samą, która zdobiła okładkę powieści Michaela Crichtona Jurassic Park. Fizyczne składanie to ciekawa historia, ale krzywa jest zdefiniowana przez znacznie prostszy obiekt: ciąg ruchów L/R, który podwaja się w każdym kroku.
Zacznij od sekwencji o pojedynczym symbolu L. Aby przejść od generacji n do n+1, skopiuj sekwencję, wstaw L pośrodku i następnie dodaj odwrotność oryginalnej sekwencji, gdzie każdy symbol jest odwrócony (L↔R). To dokładnie zasada, której przestrzega wstążka papieru, gdy ją składamy na pół i zawsze składamy w ten sam sposób: każdy nowy zginanie odbija i odwraca wszystko, co pojawiło się wcześniej.
Grafika żółwiowa: przekształcanie ciągów znaków w piksele
Kiedy masz sekwencję obrotów dla danej generacji, rysowanie jej stanowi problem grafiki żółwiowej: przesuń się o stały krok i w każdym symbole skręć o 90° w lewo (L) lub 90° w prawo (R), a następnie narysuj następny segment. Nie potrzeba żadnej trygonometrii poza czterema ustalonymi kierunkami (0°, 90°, 180°, 270°) – dlatego krzywa renderuje się natychmiast, nawet przy wysokich liczbach iteracji – każdy segment jest współosiowy.
funkcja nextGen(seq) { // seq to tablica +1 (L) / -1 (R) const mid = 1; // wstaw L (+1) w środku const tailRev = [...seq].reverse().map(t => -t); return [...seq, mid, ...tailRev]; } let heading = 0; // 0,1,2,3 = N,E,S,W jako wielokrotności 90° for (const turn of turnSeq) { x += DX[heading] * step; y += DY[heading] * step; drawLineTo(x, y); heading = (heading + turn + 4) % 4; } Również często szybsza alternatywa omija budowanie ciągów znaków w całości: obrót przed krokiem n (1-indeksowany) jest bezpośrednio określany przez położenie najniższego ustawionego bitu, który wynosi 0 w reprezentacji binarnej liczby n, stary trik bitowy odkryty niezależnie przez kilku osób badających krzywą smoka i jej samopodobieństwo. Pozwala to pójść bezpośrednio do segmentu 131 072 bez tworzenia pierwszych 131 071.
function nextGen(seq) {
// seq is an array of +1 (L) / -1 (R)
const mid = 1; // insert an L (+1) in the middle
const tailRev = [...seq].reverse().map(t => -t);
return [...seq, mid, ...tailRev];
}
let heading = 0; // 0,1,2,3 = N,E,S,W as multiples of 90°
for (const turn of turnSeq) {
x += DX[heading] * step; y += DY[heading] * step;
drawLineTo(x, y);
heading = (heading + turn + 4) % 4;
}
Samopodobieństwo i granica, która wykańcza płaszczyznę”, “paragraphs”: [
Żółtawica jest zbudowana z dwóch kopii o połowie wielkości, każda obrócona o 45 stopni i przeskalowana przez 1/√2, połączonych w końcach – bezpośredwiejszy skutek zasady składania i odbijania. To samopodobieństwo daje jej wymiar fraktali dokładnie 2: chociaż jest rysowana jako jednowymiarowa ścieżka, przy wystarczająco dużej iteracji wypełnia obszar, a jej granica to również krzywa fraktalna o wymiarze w przybliżeniu 1,5236. Pomimo ciągłego przecinania się blisko siebie, krzywa generowana przez ten system L nigdy nie przecina się – właściwość udowodniona rygorystycznie przez Chandlera Davis i Donalda Knuta w ich artykule z 1970 roku na temat żółtawicy i innych sekwencji składania papieru.
Najbardziej imponujący fakt: cztery kopie żółtawicy, obrócone o rosnące kąty 90 stopni wokół wspólnego środka, wykańczają płaszczyznę bez szczelin ani nakładania się. Krzywa jest, w ścisłym matematycznym sensie, rep-tilem – może być rozłożona na mniejsze kopie siebie, a większe kopie dokładnie wykorzystują mniejsze kopie. Łączy to ją z całą rodziną krzywych składanych papieru (krzywą Lévy C, terdragon) zbudowanych tą samą ideą przy różnych kątach składania lub liczbie składania na krok.
Dlaczego generacja 17 już ma 131 072 segmenty
Każda kolejna generacja podwaja liczbę segmentów względem poprzedniej: generacja n ma 2ⁿ segmentów. Dlatego, nawet stosunkowo niewielka krzywa na ekranie po zaledwie 17 złożeniach wymaga już 131 072 segmentów liniowych — i dlaczego każda implementacja, która od nowa oblicza pełną sekwencję od zera za każdym klatką, zacznie się zacinać już przed generacją 20. Rozwiązanie zastosowane w tej symulacji jest takie samo, jak w innych fraktalach L-systemu na całym koncie: pełna sekwencja obrotów jest prekomputowana raz na zmianę generacji z wykorzystaniem podwojonego wzoru rekurencyjnego (czas liniowy, a nie wykładniczy), a ponowne narysowanie odbywa się tylko wtedy, gdy zmienia się generacja lub wielkość kroku.
Często zadawane pytania
Czy smok Heighwaya kiedykolwiek przecina się?
Nie. Chociaż segmenty przechodzą bardzo blisko siebie, a krzywizna wydaje się gęsta przy wysokich generacjach, Davis i Knuth udowodnili w 1970 roku, że standardowa krzywa składania papieru nie przecina się sama ze sobą, niezależnie od liczby zgięć.
Dlaczego liczba segmentów podwaja się co kolejna generacja?
Każde złożenie podwaja długość paska papieru, a jego rozłożenie wprowadza jedno nowe zagięcie między każdą parą istniejących segmentów plus oryginalnych, odzwierciedlonych – dlatego generacja n zawsze ma dokładnie 2ⁿ segmentów, co jest wzrostem wykładniczym i dlatego wysokie generacje wymagają wydajnych sekwencji obrotów zamiast prymitywnego ponownego rysowania.
Czy krzywa smoka jest związana z origami lub fraktalami występującymi w naturze?
Jest to matematyczne idealizowanie rzeczywistego składania papieru, a nie naturalny fraktal, taki jak wybrzeże lub paproć. Jednak należy do tej samej rodziny sekwencji składania papieru co krzywa Lévy C i terdragon, a jej granica ma prawdziwą wymiar fraktala (~1.5236), nawet jeśli wypełniona krzywa ma wymiar 2.
Wypróbuj na żywo
Wszystko powyżej działa bezpośrednio w Twojej przeglądarce — otwórz Dragon Curve i zmieniaj parametry podczas działania. Nic nie jest instalowane ani przesyłane na serwer, cały model działa w jednej karcie.
▶ Otwórz symulację Dragon Curve