Circular Blues

21

Napisz program lub funkcję, która przyjmuje dodatnią liczbę całkowitą N i odtwarza ten wzór kół skalowanych w celu dopasowania do obrazu pikselowego N × N:

fantazyjne koła

Ten obraz jest poprawnym przykładem wyjścia dla N = 946.

W przypadku, gdy nie jest jasne, wszystkie małe jasnoniebieskie koła mają ten sam promień i są umieszczone w czterech ciemnoniebieskich okręgach w ten sam sposób. Ciemnoniebieskie kółka mają podwójny promień i są podobnie ustawione w dużym jasnoniebieskim kółku.

  • Zamiast dwóch odcieni niebieskiego można zastosować dowolne dwa odrębne wizualnie kolory.

  • Kwadrat w tle musi być pokolorowany.

  • Wygładzanie jest opcjonalne.

  • Zapisz obraz do pliku, wyświetl go lub potokuj surowe dane obrazu na standardowe wyjście.

  • Dowolny wspólny format pliku obrazu jest dozwolony.

Najkrótszy kod w bajtach wygrywa.

Punkty Brownie, jeśli rozszerzysz rekurencyjne aspekty tego wzoru okręgu na kolejne poziomy. (Należy to odróżnić od wpisu dotyczącego wyzwania).

Hobby Calvina
źródło
Co rozumiesz przez „Kwadrat w tle musi być pokolorowany”? Jeśli tło ma domyślnie określony kolor, czy mogę go po prostu użyć jako jednego z 2 kolorów bez wyraźnego wypełnienia go?
aditsu
Mam na myśli, że bg nie może być trzecim innym kolorem
hobby Calvina

Odpowiedzi:

5

CJam, 83 bajty

"P1"li___,.5f+2.@/f*1fm2m*{[3{_~mh1<[[VX][ZmqV]]_Wff*+@2f*f.+{~mh}$0=}*;0]0#2%}%]S*

Wypróbuj online

CJam nie ma dedykowanej funkcji wyjściowej obrazu. Mój kod generuje obraz w PBM ASCII. Aby opublikować, przekonwertowałem ten obraz do formatu PNG za pomocą GIMP.

Zauważ, że nie korzystała z funkcji rysowania okręgów ani nic podobnego. Obraz jest obliczany piksel po pikselu.

Przykładowe dane wyjściowe

Wyższe stopnie podziału można łatwo utworzyć, zwiększając stałą 3wokół środka kodu.

Obrazy stopnia 4 i 5 wyglądają tak:

Stopień 4Stopień 5

Ogólna sekwencja kodu to:

  1. Wygeneruj współrzędne wszystkich pikseli, znormalizowane do zakresu [-1.0, 1.0].
  2. Pętla nad wszystkimi pikselami.
  3. Pętla nad stopniami podziału.
  4. Dla każdego podziału sprawdź, czy piksel znajduje się wewnątrz / na zewnątrz i zachowaj wynik. Skaluj / tłumacz współrzędne pikseli na układy współrzędnych wyśrodkowane w jednym z 4 podokręgów. Wybierz tę, w której przekształcone współrzędne są najbliżej środka.
  5. Na podstawie wyników binarnych wewnątrz / na zewnątrz każdego stopnia znajdź pierwsze 0, odpowiadające pierwszemu stopniowi, w którym piksel znajdował się na zewnątrz, i weź jego moduł 2, aby określić kolor piksela.

Wyjaśnienie:

"P1"    Start of header for PBM ASCII file.
li      Get input n.
__      Two copies for the width/height of the image in the PBM header.
_,      Generate [0 .. n - 1].
.5f+    Add 0.5 to each list entry, since we want to test the pixel centers.
2.@/    Calculate 2.0 / n, which is the distance between two pixels.
f*      Multiply the unscaled pixel coordinates with the pixel distance.
        We now have coordinates in the range [0.0, 2.0].
1fm     Subtract one from each, giving coordinates in range [-1.0, 1.0].
2m*     Cartesian power to calculate all y/x pairs.
{       Start loop over all pixel coordinates.
  [       Start wrapping the inside/outside results for all degrees.
  3{      Start loop over degrees.
    _~mh    Calculate distance from center.
    1<      Compare with 1. This gives inside/outside result for degree.
    [       Start building list of centers for 4 sub-circles.
    [VX]    One is at [0 1]. Note that coordinate order is y/x.
    [ZmqV]  Next one is at [sqrt(3) 0].
    ]       Wrap these two...
    _       ... and copy them.
    Wff*    Mirror all coordinates by multiplying with -1.
    +       Concatenate, giving the centers of all 4 sub-circles.
    @       Get current coordinates to top.
    2f*     Multiply them by 2. Note that the coordinates need to be scaled up by
            a factor 2 to give a circle with half the radius when we test the distance
            to the origin against 1.0.
    f.+     Add the current coordinates to the centers of all 4 sub-circles.
            For each sub-circle, this puts the current coordinates in a coordinate
            space with the origin at the center, and with a radius of 1.0
    {~mh}$  Sort them by distance to the origin...
    0=      ... and take the first one. This picks the sub-circle which has its
            center closest to the current coordinates.
            We now have one coordinate pair, for the closest sub-circle, and are
            ready for the next loop iteration, which tests the next degree of the
            subdivision.
  }*      End loop over degrees.
  ;       Have remaining coordinate pair on stack, pop it.
  0       Add a sentinel for find operation before, so that a 0 is always found.
  ]       End wrapping the inside/outside results for all degrees.
  0#      Find the first 0 (outside) degree.
  2%      Modulo 2 to determine color.
}%      End loop over all pixel coordinates.
]       Wrap the pieces of the PBM header and the pixel list.
S*      Join them with spaces, to produce the necessary spaces for the header.
Reto Koradi
źródło
17

Python 2 + PIL, 262 bajty

wprowadź opis zdjęcia tutaj

To podejście określa kolor każdej współrzędnej piksela za pomocą funkcji rekurencyjnej c. c(x,y,0)renderuje okrąg; c(x,y,1)renderuje okrąg z wyciętymi czterema okręgami; c(x,y,2)renderuje obraz w OP. Wszystko większe niż 2 zarabia mi punkty brownie.

import PIL.Image as I
d=3**.5/2
c=lambda x,y,l=0:c(x,y)&~any(c((x+i)*2,(y+j)*2,l-1)for i,j in[(.5,0),(-.5,0),(0,d),(0,-d)])if l else x*x+y*y<1
z=input()
f=lambda s:2.*s/z-1
I.frombytes("L",(z,z),"".join(" ~"[c(f(i%z),f(i/z),2)]for i in range(z*z))).save("p.png")

Wersja bez gry w golfa:

from PIL import Image
import math
def in_shape(x,y, level=0):
    d = math.sqrt(3)/2
    if level == 0:
        return x**2 + y**2 <= 1
    else:
        t = True
        for dx,dy in [(0.5, 0), (-0.5, 0), (0, d), (0,-d)]:
            if in_shape((x+dx)*2, (y+dy)*2, level-1):
                t = False
        return in_shape(x,y) and t

f = lambda s: ((2*s / float(size))-1)

size = input()
img = Image.new("RGB", (size, size))
pix = img.load()
for i in range(size):
    for j in range(size):
        if in_shape(f(i), f(j), 2):
            pix[i,j] = (0,0,0)
        else:
            pix[i,j] = (255,255,255)
img.save("output.png")

Dodatkowy obraz rekurencyjny:

wprowadź opis zdjęcia tutaj

Kevin
źródło
Zamiast po .save("p.png")prostu użyć.show()
Albert Renshaw
7

PostScript, 335 bajtów.

%!
/D{def}def/B{bind D}D/E{exch}B/A{add}D/c{3 copy 3 -1 roll A E moveto 0 360 arc}B/f{5 dict begin/d E D/r E D/y E D/x E D gsave x y r c clip d 2 mod setgray x y r c fill d 0 gt{/h 3 sqrt 2 div r mul D/r r 2 div D/d d 1 sub D x r A y r d f x r sub y r d f x y h A r d f x y h sub r d f}if grestore end}B 512 2 div dup dup 2 f showpage

PostScript to nie tylko format plików graficznych z funkcjami wektorowymi i bitmapowymi, to w rzeczywistości oparty na obiektach język programowania Turing-complete. Powyższy kod jest dość prostą implementacją funkcji rekurencyjnej. Wszystkie operatory PostScript są funkcjami i ich redefiniowanie w celu zagęszczenia kodu jest powszechne. Zauważ, że PostScript używa odwrotnej notacji polskiej (inaczej notacji postfiksowej).

Tłumacze PostScript zazwyczaj czytają metadane (takie jak rozmiar strony i tytuł) ze specjalnych komentarzy na początku pliku; oczywiście %!z mojego wpisu usunąłem wszystkie istotne komentarze podpisu PostScript , ale powinny one być wyświetlane poprawnie w każdym standardowym interpretera PostScript, np. GhostScript lub Okular. Można go również wyświetlić za pomocą narzędzia wyświetlania dostarczanego z ImageMagick / GraphicsMagick.

Zauważ, że plik powinien kończyć się nowym wierszem (który zawarłem w mojej liczbie bajtów), w przeciwnym razie tłumacz może się zdenerwować.

Parametr rozmiaru Ndla tego kodu to 512; jest podzielony przez 2 i dwukrotnie zduplikowany, aby utworzyć parametry dla początkowego wywołania funkcji rekurencyjnej f. Głębokość rekursji wynosi 2, co jest podane tuż przed fin 512 2 div dup dup 2 f. Aby zachować mały rozmiar, wydruk jest czarno-biały. Chociaż można ustawić dowolną rozsądną nieujemną głębokość rekurencji liczb całkowitych, ta wersja wygląda dobrze tylko z równymi głębokościami.

Ten obraz jest grafiką wektorową, więc może być wyświetlany w dowolnej rozdzielczości bez pikselizacji, w zależności od jakości i ustawień używanego interpretera / drukarki PostScript. (FWIW, PostScript używa krzywych sześciennych Béziera do rysowania łuków kołowych, z wystarczającą liczbą splajnów, aby zapewnić, że błąd jest zawsze mniejszy niż jeden piksel w przestrzeni urządzenia). Aby wyświetlić go za pomocą wyświetlacza ImageMagick w dość wysokiej jakości, możesz:

display -density 300 -geometry 512x512 -page 512x512

te same parametry są również dobre, jeśli chcesz użyć ImageMagick's convertdo konwersji na inny format. Na przykład, oto 640x640 wersja powyższego kodu PostScript przekonwertowanego na PNG:

Fraktal w kręgu 640 x 640


Oto nieco większa wersja, która obsługuje kolory RGB i nieparzyste głębokości rekurencji:

%!PS-Adobe-3.0
/D{def}def/N 512 D/d 2 D/B{bind D}D/E{exch}B/A{add}D/c{3 copy 3 -1 roll A E moveto 0 360 arc}B/k{2 mod 0 eq{.3 .6 .9}{0 .2 .5}ifelse setrgbcolor}B d 1 A k 0 0 N N rectfill/f{5 dict begin/d E D/r E D/y E D/x E D gsave x y r c clip d k x y r c fill d 0 gt{/h 3 sqrt 2 div r mul D/r r 2 div D/d d 1 sub D x r A y r d f x r sub y r d f x y h A r d f x y h sub r d f}if grestore end}B N 2 div dup dup d f showpage

Umożliwia także ustawienie parametru rozmiaru Ni głębokości rekurencji dw górnej części skryptu.

Fraktal z kolorem 640 x 640, głębokość == 2


Wreszcie, oto bardziej czytelna forma kodu. (Niestety, podświetlanie składni użyte tutaj dla PostScript pozostawia wiele do życzenia, ale myślę, że jest lepsze niż nic ...). Inteligentne interpretery PostScript odczytują geometrię strony ze %%BoundingBox:specjalnego komentarza.

%!PS-Adobe-3.0
%%BoundingBox: 0 0 640 640
%%Title: Circle fractal
%%Creator: PM 2Ring
%%Creationdate: (Oct 29 2015)
%%Pages: 1 1
%%EndComments

% for http://codegolf.stackexchange.com/questions/61989/circular-blues

% ----------------------------------------------------------------------

16 dict begin

%Total image width & height in points / pixels
/N 640 def

%Maximum recursion depth
/Depth 4 def

% ----------------------------------------------------------------------

%Draw a circle centred at (x,y), radius r. x y r circle -
/circle{
    3 copy      % x y r  x y r
    3 -1 roll   % x y r  y r x
    add exch    % x y r  x+r y
    moveto
    0 360 arc 
}bind def

% ----------------------------------------------------------------------

%Select 1st color if n is even, select 2nd color if n is odd. n color -
/color{
    2 mod 0 eq
    {.36 .6 .9}
    {0 .25 .5}
    ifelse
    setrgbcolor
}bind def

%Do background square
Depth 1 add color
0 0 N N rectfill

/Q 3 sqrt 2 div def

%Recursive circle pattern. x y r Depth cfrac -
/cfrac{
    5 dict begin
    /Depth exch def
    /r exch def
    /y exch def
    /x exch def

    gsave
    x y r circle clip
    Depth color
    x y r circle fill

    Depth 0 gt
    {
        /dy Q r mul def
        /r r 2 div def
        /Depth Depth 1 sub def 

        x r add y r Depth cfrac
        x r sub y r Depth cfrac
        x y dy add r Depth cfrac
        x y dy sub r Depth cfrac
    }if
    grestore
    end
}bind def

%Call it!
N 2 div dup dup Depth cfrac

showpage

% ----------------------------------------------------------------------

%%Trailer
end
%%EOF

A oto wynik głębokości == 4 w formacie PNG, ponownie utworzony za pomocą konwersji (i zoptymalizowany za pomocą optipng ):

Fraktal z kolorem 640x640, głębokość == 4

PM 2 Ring
źródło
6

Python 2 + PIL, 361 bajtów

import PIL.Image as p,PIL.ImageDraw as d
W=input()
q=W/4
h=2*q
t=3*q
e=W/8
o=int(q*3**.5)
I,J=[p.new("1",(s,s),s>h)for s in[W,h]]
Q=lambda i,x,y,s=q,c=0:d.Draw(i).ellipse((x,y,x+s,y+s),fill=c)
Q(I,0,0,W)
Q(J,0,0,h,1)
[Q(J,k,e)for k in[0,q]]
[Q(J,e,e+k/2)for k in[-o,o]]
[I.paste(1,k,J)for k in[(0,q,h,t),(h,q,4*q,t),(q,q-o,t,t-o),(q,q+o,t,t+o)]]
I.save("c.png")

Zapisuje obraz w czerni i bieli do pliku c.png:

przykładowe wyjście

Zasadniczo generuję jedno z kół o połowie wielkości na obrazie J. Następnie używam siebie jako maski do namalowania kształtu na obrazie I, który ma główny okrąg.

Można go skrócić, używając I.show()na końcu zamiast I.save("c.png"), ale nie uruchomiłem go w Pythonie 2. Jeśli ktoś może potwierdzić, że działa w Pythonie 2, zmienię to.

Poniższy program generuje obraz jak w pytaniu (419 bajtów):

import PIL.Image as p,PIL.ImageDraw as d
W=int(input())
q=W/4
h=2*q
t=3*q
e=W/8
o=int(q*3**.5)
I,J=[p.new(["1","RGB"][s>h],(s,s),s>h and"rgb(13,55,125)")for s in[W,h]]
Q=lambda i,x,y,s=q,c=0:d.Draw(i).ellipse((x,y,x+s,y+s),fill=c)
Q(I,0,0,W,"rgb(97,140,224)")
Q(J,0,0,h,1)
[Q(J,k,e)for k in[0,q]]
[Q(J,e,e+k/2)for k in[-o,o]]
[I.paste("rgb(13,55,125)",k,J)for k in[(0,q,h,t),(h,q,4*q,t),(q,q-o,t,t-o),(q,q+o,t,t+o)]]
I.save("c.png")
PurkkaKoodari
źródło
-1 nie tak ładna jak obraz Calvina;)
Beta Decay
Mogę potwierdzić, że .show () działa
Albert Renshaw
Ok, dzięki, użyję tego zamiast save.
Kevin
3

SVG (1249 znaków)

Tak, wiele postaci. Ale jest statyczny i renderuje w dowolnym rozmiarze, więc daje to pewną premię.

<svg xmlns="http://www.w3.org/2000/svg"><path d="M15,33c-2.5,0-4.6,1.9-4.9,4.3c2.8,1.6,6.1,2.6,9.5,2.6c0.3-0.6,0.4-1.3,0.4-2C20,35.2,17.8,33,15,33zM15,7c2.8,0,5-2.2,5-5c0-0.7-0.1-1.4-0.4-2c-3.5,0.1-6.7,1-9.5,2.6C10.4,5.1,12.5,7,15,7zM25,33c-2.8,0-5,2.2-5,5c0,0.7,0.1,1.4,0.4,2c3.5-0.1,6.7-1,9.5-2.6C29.6,34.9,27.5,33,25,33zM25,7c2.5,0,4.6-1.9,4.9-4.3C27.1,1,23.9,0.1,20.4,0C20.1,0.6,20,1.3,20,2C20,4.7,22.2,7,25,7zM35,28.7C34.8,26,32.6,24,30,24s-4.8,2.1-5,4.7c-3-1.7-5-5-5-8.7c0,3.7-2,6.9-5,8.7C14.8,26,12.6,24,10,24S5.2,26,5,28.7c-3-1.7-5-5-5-8.7c0,7.4,4,13.9,10,17.3c0.1-1.2,0.4-2.4,0.8-3.4c0.9-1.9,2.3-3.5,4.1-4.5c0,0,0,0,0.1,0c0.2,2.6,2.3,4.7,5,4.7s4.8-2.1,5-4.7c0,0,0,0,0.1,0c1.8,1,3.2,2.6,4.1,4.5c0.5,1.1,0.8,2.2,0.8,3.4c6-3.5,10-9.9,10-17.3C40,23.7,38,26.9,35,28.7zM5,11.3c0.2,2.6,2.3,4.7,5,4.7s4.8-2.1,5-4.7c3,1.7,5,5,5,8.7c0-3.7,2-6.9,5-8.7c0.2,2.6,2.3,4.7,5,4.7s4.8-2.1,5-4.7c3,1.7,5,5,5,8.7c0-7.4-4-13.9-10-17.3c-0.1,1.2-0.4,2.4-0.8,3.4C28.3,8,26.8,9.6,25,10.6c0,0,0,0-0.1,0C24.8,8,22.6,6,20,6s-4.8,2.1-5,4.7c0,0,0,0-0.1,0c-1.8-1-3.2-2.6-4.1-4.5C10.4,5,10.1,3.9,10,2.6C4,6.1,0,12.6,0,20C0,16.3,2,13,5,11.3z"/><circle cx="15" cy="20" r="5"/><circle cx="5" cy="20" r="5"/><circle cx="35" cy="20" r="5"/><circle cx="25" cy="20" r="5"/></svg>

Widoczny fragment:

svg { fill: #9FD7FF; background: #2176AA; }
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="400" viewBox="0 0 40 40">
  <path d="M15,33c-2.5,0-4.6,1.9-4.9,4.3c2.8,1.6,6.1,2.6,9.5,2.6c0.3-0.6,0.4-1.3,0.4-2C20,35.2,17.8,33,15,33zM15,7c2.8,0,5-2.2,5-5c0-0.7-0.1-1.4-0.4-2c-3.5,0.1-6.7,1-9.5,2.6C10.4,5.1,12.5,7,15,7zM25,33c-2.8,0-5,2.2-5,5c0,0.7,0.1,1.4,0.4,2c3.5-0.1,6.7-1,9.5-2.6C29.6,34.9,27.5,33,25,33zM25,7c2.5,0,4.6-1.9,4.9-4.3C27.1,1,23.9,0.1,20.4,0C20.1,0.6,20,1.3,20,2C20,4.7,22.2,7,25,7zM35,28.7C34.8,26,32.6,24,30,24s-4.8,2.1-5,4.7c-3-1.7-5-5-5-8.7c0,3.7-2,6.9-5,8.7C14.8,26,12.6,24,10,24S5.2,26,5,28.7c-3-1.7-5-5-5-8.7c0,7.4,4,13.9,10,17.3c0.1-1.2,0.4-2.4,0.8-3.4c0.9-1.9,2.3-3.5,4.1-4.5c0,0,0,0,0.1,0c0.2,2.6,2.3,4.7,5,4.7s4.8-2.1,5-4.7c0,0,0,0,0.1,0c1.8,1,3.2,2.6,4.1,4.5c0.5,1.1,0.8,2.2,0.8,3.4c6-3.5,10-9.9,10-17.3C40,23.7,38,26.9,35,28.7zM5,11.3c0.2,2.6,2.3,4.7,5,4.7s4.8-2.1,5-4.7c3,1.7,5,5,5,8.7c0-3.7,2-6.9,5-8.7c0.2,2.6,2.3,4.7,5,4.7s4.8-2.1,5-4.7c3,1.7,5,5,5,8.7c0-7.4-4-13.9-10-17.3c-0.1,1.2-0.4,2.4-0.8,3.4C28.3,8,26.8,9.6,25,10.6c0,0,0,0-0.1,0C24.8,8,22.6,6,20,6s-4.8,2.1-5,4.7c0,0,0,0-0.1,0c-1.8-1-3.2-2.6-4.1-4.5C10.4,5,10.1,3.9,10,2.6C4,6.1,0,12.6,0,20C0,16.3,2,13,5,11.3z"/>
  <circle cx="15" cy="20" r="5"/>
  <circle cx="5" cy="20" r="5"/>
  <circle cx="35" cy="20" r="5"/>
  <circle cx="25" cy="20" r="5"/>
</svg>

szturchać
źródło
Pamiętaj, że, jak powiedział Mego, SVG nie spełnia naszych kryteriów zakwalifikowania się jako język programowania . Mimo to PO może zezwolić na tę odpowiedź; to zależy od niego.
Alex A.,
SVG jest w tym przypadku w porządku.
Calvin's Hobbies,
Czy możesz pominąć wiodące 0w stałych zmiennoprzecinkowych? Na przykład zastąp 0.4przez .4? W większości języków jest to poprawne. Bardzo szybkie spojrzenie na specyfikację SVG sugeruje, że prawdopodobnie powinna również działać.
Reto Koradi
@RetoKoradi Tak, i prawdopodobnie możesz skruszyć jeszcze kilka liczb, skutecznie zaokrąglając lub zmieniając rozmiar w taki sposób, że potrzebujesz mniej miejsc po przecinku, ale tbh. powstałe ścieżki są po prostu zbyt skomplikowane, aby miało to ogromną różnicę. Ale mogę wypróbować inne rozwiązanie przy użyciu masek później.
poke
2

Mathematica 336 359 bajtów

Głównymi obiektami graficznymi są regiony zdefiniowane za pomocą logicznych kombinacji równań.

r=Red;i=ImplicitRegion;m=i[-2<x<2&&-2<y<2,{x,y}];n=Input[];
t[a_,b_,c_]:=i[(x+a)^2+(y+b)^2<=c,{x,y}];
a_~f~b_:={t[a,b,1],t[-.5+a,b,1/4],t[.5+a,b,1/4],t[a,b-.865,1/4],t[a,b+.865, 1/4]}
g@d_:=RegionIntersection[m,BooleanRegion[#1&&!#2&&!#3&&!#4&&!#5&,d]]
RegionPlot[{m,t[0,0,4],g@f[1,0],g@f[-1,0],g@f[0,1.75], 
g@f[0, -1.75]},ImageSize->n,PlotStyle->{r,Blue,r,r,r,r}]

fotka

DavidC
źródło
1

Java, 550

import javafx.application.*;import javafx.scene.*;import javafx.scene.layout.*;import javafx.scene.shape.*;import javafx.stage.*;public
class C extends Application{static long n;Shape d(float m,float k,float x,float y){float h=m/2;Shape
s=new Circle(x+h,y+h,h);return k>0?s.subtract(s,s.union(s.union(s.union(d(h,k-1,x,y+m/4),d(h,k-1,x+h,y+m/4)),d(h,k-1,x+m/4,y-m*.183f)),d(h,k-1,x+m/4,y+m*.683f))):s;}public
void start(Stage s){s.setScene(new Scene(new Pane(d(n,2,0,0))));s.show();}public
static void main(String[]a){n=Long.valueOf(a[0]);launch();}}

Głównie po prostu eksperymentuje z JavaFX.

Zrzut ekranu:

zrzut ekranu

W przypadku punktów brownie zmień 2kod ( d(n,2,0,0)) na inną liczbę.

Stara wersja, 810

import javafx.application.*;import javafx.scene.*;import javafx.scene.canvas.*;import javafx.scene.effect.*;import javafx.scene.layout.*;import javafx.scene.paint.*;import javafx.stage.*;public
class C extends Application{static long n;Canvas c;GraphicsContext g;void
d(float m,float k,float x,float y){if(k>0){float
h=m/2;g.save();g.beginPath();g.arc(x+h,y+h,h,h,0,360);g.clip();g.fillRect(x,y,m,m);d(h,k-1,x,y+m/4);d(h,k-1,x+h,y+m/4);d(h,k-1,x+m/4,y-m*.183f);d(h,k-1,x+m/4,y+m*.683f);g.restore();}}public
void start(Stage s){c=new Canvas(n,n);g=c.getGraphicsContext2D();g.setGlobalBlendMode(BlendMode.DIFFERENCE);g.setFill(Color.TAN);g.fillRect(0,0,n,n);d(n,3,0,0);Pane
p=new Pane();p.getChildren().add(c);s.setScene(new Scene(p));s.show();}public
static void main(String[]a){n=Long.valueOf(a[0]);launch();}}

Pozostawia pewne niepożądane krawędzie, jak widać na tym zrzucie ekranu .

aditsu
źródło
0

JavaScript (ES6), 279

Rekurencyjnie twórz płótna i dodaj płótno podrzędne cztery razy do płótna nadrzędnego. W dolnej warstwie płótno jest pojedynczym okręgiem; że płótno zostanie wybite cztery razy na płótnie macierzystej, a następnie , że płótno jest wybity cztery razy na końcowym głównego płótnie.

(n,o=0)=>(r=o-2&&f(n/2,o+1),c=document.createElement`canvas`,X=c.getContext`2d`,d=(x,Q)=>(X.drawImage(r,x,k+Q*k*Math.sqrt(3)),d),c.width=c.height=n,m=n/2,k=n/4,X.fillStyle=o%2||"red",X.fill(X.clip(X.arc(m,m,m,0,7))),r&&d(0,0)(m,0)(k,-1)(k,1),o?c:location=c.toDataURL`image/jpeg`)

przesłanie obrazu

Uruchomienie demo:

Z białymi znakami, komentarzami i lekko nie golfowym:

f=(n,o=0)=>(
    // recursively create another canvas if we're not at the deepest layer
    var r;
    if(o < 2) { r = f(n/2,o+1); }

    // create this canvas
    c=document.createElement("canvas"),
    c.width=c.height=n,
    X=c.getContext("2d"),

    // helpful postions
    m=n/2, k=n/4, q=k*Math.sqrt(3),

    // draw a circle and clip future draws within this circle
    // either fills red (the shortest color name) or a non-color that defaults to black
    X.fillStyle= o%2 || "red",
    X.arc(m,m,m,0,7),
    X.clip(),
    X.fill(),

    // define a chainable `drawImage` alias (the `d` function returns itself)
    d=(x,y)=>(X.drawImage(r,x,y),d)

    // if we have a recursive canvas, draw it four times by chaining `d`
    if(r) { d(0,k)(m,k)(k,k-q)(k,k+q); }

    // if this is the top-layer (o==0), show the final jpeg
    if(o == 0) { location = c.toDataURL("image/jpeg"); }

    // return this canvas, to be used recursively
    c
)

Może to łatwo wytworzyć głębsze warstwy rekurencji, zmieniając wartość początkową o-2lub dowolną większą o-z.

Zauważ, że to będzie działać tylko w poddaniu Firefox, dzięki wykorzystaniu ES6 funkcje i niespójność w API na płótnie filli clipargumenty.

apsillery
źródło