Circular Blues

21

Escreva um programa ou função que receba um número inteiro positivo N e recrie esse padrão de círculos dimensionados para ajustar uma imagem de pixel N × N:

círculos extravagantes

Esta imagem é um exemplo de saída válido para N = 946.

Caso não esteja claro, todos os pequenos círculos azul claro têm o mesmo raio e são posicionados nos quatro círculos azul escuro da mesma maneira. Os círculos azul escuro têm o dobro desse raio e estão posicionados de maneira semelhante no grande círculo azul claro.

  • Quaisquer duas cores visualmente distintas podem ser usadas no lugar dos dois tons de azul.

  • O quadrado do plano de fundo precisa ser colorido.

  • Anti-aliasing é opcional.

  • Salve a imagem em um arquivo, exiba-o ou envie os dados brutos da imagem para o stdout.

  • Qualquer formato de arquivo de imagem comum é permitido.

O código mais curto em bytes vence.

Brownie aponta se você estender os aspectos recursivos desse padrão de círculo para outros níveis. (Mantenha isso diferente da entrada do seu desafio.)

Passatempos de Calvin
fonte
O que você quer dizer com "O quadrado de fundo precisa ser colorido"? Se o plano de fundo tiver uma determinada cor por padrão, posso usá-lo como uma das duas cores sem preenchê-lo explicitamente?
Aditsu 28/10/2015
Quero dizer o bg não pode ser uma terceira cor diferente
de Calvino Hobbies

Respostas:

5

CJam, 83 bytes

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

Experimente online

O CJam não possui funcionalidade de saída de imagem dedicada. Meu código gera uma imagem no PBM ASCII. Para postar, converti essa imagem em PNG usando o GIMP.

Observe que nenhuma funcionalidade de desenho de círculo, ou qualquer coisa assim, era usada. A imagem é calculada pixel por pixel.

Saída de amostra

Graus mais altos da subdivisão podem ser criados facilmente, aumentando a constante 3no meio do código.

As imagens dos graus 4 e 5 são assim:

Grau 4Grau 5

A sequência geral do código é:

  1. Gere as coordenadas de todos os pixels, normalizadas no intervalo [-1,0, 1,0].
  2. Passa por todos os pixels.
  3. Loop em graus de subdivisão.
  4. Para cada subdivisão, verifique se o pixel está dentro / fora e mantenha o resultado. A escala / converte as coordenadas de pixel nos sistemas de coordenadas centralizados em um dos quatro sub-círculos. Escolha aquele em que as coordenadas transformadas estão mais próximas do centro.
  5. A partir dos resultados binários internos / externos de cada grau, encontre o primeiro 0, correspondente ao primeiro grau em que o pixel estava fora, e pegue seu módulo 2 para determinar a cor do pixel.

Explicação:

"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
fonte
17

Python 2 + PIL, 262 bytes

insira a descrição da imagem aqui

Essa abordagem determina a cor de cada coordenada de pixel individual usando a função recursiva c. c(x,y,0)renderiza um círculo; c(x,y,1)renderiza um círculo com quatro círculos recortados; c(x,y,2)renderiza a imagem no OP. Qualquer coisa maior que 2 me ganha pontos de 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")

Versão sem golfe:

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")

Imagem extra-recursiva de bônus:

insira a descrição da imagem aqui

Kevin
fonte
Em vez de .save("p.png")apenas usar.show()
Albert Renshaw 16/16
7

PostScript, 335 bytes.

%!
/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

O PostScript não é apenas um formato de arquivo gráfico com recursos de vetor e bitmap; na verdade, é uma linguagem de programação completa de Turing baseada em objetos. O código acima é uma implementação de função recursiva bastante direta. Todos os operadores PostScript são funções, e é comum redefini-los para condensar o código. Observe que o PostScript usa notação polonesa reversa (também conhecida como notação postfix).

Os intérpretes PostScript geralmente leem metadados (como tamanho e título da página) de comentários especiais no início do arquivo; Obviamente, removi tudo, exceto o comentário essencial da assinatura PostScript %!da minha entrada, mas ele ainda deve ser exibido em qualquer interpretador PostScript padrão, por exemplo, GhostScript ou Okular. Também pode ser visualizado usando o utilitário de exibição que acompanha o ImageMagick / GraphicsMagick.

Observe que o arquivo deve terminar em uma nova linha (que eu incluí na minha contagem de bytes) ou o intérprete pode ficar chateado.

O parâmetro de tamanho Npara esse código é 512; é dividido por 2 e duplicado duas vezes para criar os parâmetros para a chamada inicial da função recursiva f. A profundidade de recursão é 2, que é dado imediatamente antes do fno 512 2 div dup dup 2 f. Para manter o tamanho pequeno, a saída é em preto e branco. Embora você possa definir uma profundidade razoável de recursão de número inteiro não negativo razoável, esta versão parece boa apenas com profundidades uniformes.

Esta imagem é um gráfico vetorial, portanto pode ser exibida em qualquer resolução sem pixelização, dependendo da qualidade e das configurações do interpretador / impressora PostScript usado. (FWIW, o PostScript usa curvas cúbicas de Bézier para desenhar arcos circulares, com splines suficientes usados ​​para garantir que o erro seja sempre menor que um pixel no espaço do dispositivo). Para visualizá-lo usando a tela do ImageMagick com qualidade razoavelmente alta, você pode:

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

os mesmos parâmetros também são bons se você deseja usar o ImageMagick convertpara convertê-lo em outro formato. Por exemplo, aqui está uma versão de 640x640 do código PostScript acima convertida em PNG:

Fractal do círculo de 640x640 em preto e branco


Aqui está uma versão um pouco maior que lida com cores RGB e profundidades de recursão ímpares:

%!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

Também permite definir o parâmetro de tamanho Ne a profundidade da recursão dpróximo à parte superior do script.

Fractal do círculo de 640x640 cores, profundidade == 2


Finalmente, aqui está a forma mais legível do código. (Infelizmente, o destaque da sintaxe usado aqui para PostScript deixa muito a desejar, mas acho que é melhor que nada ...). Intérpretes PostScript inteligentes lerão a geometria da página a partir do %%BoundingBox:comentário especial.

%!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

E aqui está a profundidade == 4 saída no formato PNG, mais uma vez criada usando convert (e otimizada com optipng ):

Fractal do círculo de 640x640 cores, profundidade == 4

PM 2Ring
fonte
6

Python 2 + PIL, 361 bytes

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")

Salva a imagem em preto e branco no arquivo c.png:

saída de exemplo

Basicamente, giro um dos círculos de tamanho médio na imagem J. Depois, uso-me como uma máscara para pintar a forma na imagem I, que tem o círculo principal.

Pode ser reduzido usando I.show()no final I.save("c.png"), mas não o fiz funcionar no Python 2. Se alguém puder confirmar que funciona no Python 2, vou mudar para isso.

O programa a seguir gera a imagem como na pergunta (419 bytes):

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
fonte
-1 não é tão bonito quanto a imagem de Calvin;)
Decay Beta
Posso confirmar que o .show () funciona #
Albert Renshaw
Ok, obrigado, eu vou usar isso em vez de save.
21716 Kevin
3

SVG (1249 caracteres)

Sim, muitos personagens. Mas é estático e é processado em qualquer tamanho, o que lhe dá algum bônus.

<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>

Snippet visível:

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>

cutucar
fonte
Observe que, como disse Mego, o SVG não atende aos nossos critérios para se qualificar como uma linguagem de programação . No entanto, o OP pode optar por permitir essa resposta de qualquer maneira; depende dele.
Alex A.
SVG é bom neste caso.
Calvin's Hobbies
Você pode omitir a liderança 0em constantes de ponto flutuante? Por exemplo, substitua 0.4por .4? Na maioria dos idiomas, isso é válido. E uma análise muito rápida da especificação SVG sugere que ela provavelmente deve funcionar também.
Reto Koradi
@RetoKoradi Sim, e você provavelmente pode triturar mais alguns números arredondando com eficiência ou alterando o tamanho de forma que precise de menos decimais, mas tbh. os caminhos resultantes são complicados demais para que isso faça uma enorme diferença. Mas posso tentar outra solução usando máscaras mais tarde.
Poke
2

Mathematica 336 359 bytes

Os principais objetos gráficos são regiões definidas através de combinações lógicas de equações.

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}]

foto

DavidC
fonte
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();}}

Principalmente apenas experimentando o JavaFX.

Captura de tela:

captura de tela

Para pontos brownie, altere 2o código ( d(n,2,0,0)) para um número diferente.

Versão antiga, 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();}}

Deixa algumas arestas indesejadas, como você pode ver nesta captura de tela .

aditsu
fonte
0

JavaScript (ES6), 279

Crie recursivamente telas e adicione a tela filho quatro vezes à tela pai. Na camada inferior, a tela é um único círculo; essa tela é carimbada quatro vezes em uma tela pai e, em seguida, essa tela é carimbada quatro vezes na tela principal final.

(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`)

imagem de envio

Demonstração executável:

Com espaço em branco, comentários e levemente sem armas:

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
)

Isso pode facilmente produzir camadas mais profundas de recursão, alterando o valor inicial o-2ou qualquer o-zvalor maior .

Observe que esse envio será executado apenas no Firefox, devido ao uso dos recursos e da inconsistência do ES6 na API de tela para argumentos fille clip.

apsillers
fonte