Циркулярный блюз

21

Напишите программу или функцию, которая принимает положительное целое число N и воссоздает этот шаблон кругов, масштабированный так, чтобы соответствовать пиксельному изображению N × N:

модные круги

Это изображение является допустимым выходным примером для N = 946.

В случае, если неясно, все маленькие голубые круги имеют одинаковый радиус и одинаково расположены в четырех синих кругах. Синие круги имеют удвоенный радиус и аналогично расположены в большом голубом круге.

  • Любые два визуально отличных цвета могут использоваться вместо двух оттенков синего.

  • Квадрат фона должен быть цветным.

  • Сглаживание не является обязательным.

  • Сохраните изображение в файл, отобразите его или передайте необработанные данные изображения в стандартный вывод.

  • Разрешен любой общий формат файла изображения.

Самый короткий код в байтах побеждает.

Брауни указывает, если вы расширите рекурсивные аспекты этого круга на дальнейшие уровни. (Держите это отдельно от вашей записи в конкурсе.)

Кальвин Хобби
источник
Что вы подразумеваете под "фоновым квадратом должен быть окрашен"? Если фон имеет определенный цвет по умолчанию, могу ли я просто использовать его как один из двух цветов, не заполняя его явно?
aditsu
Я имею в виду, что bg не может быть третьим другим цветом
Увлечения Кэлвина

Ответы:

5

CJam, 83 байта

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

Попробуйте онлайн

CJam не имеет специальной функции вывода изображения. Мой код генерирует изображение в PBM ASCII. Для публикации я преобразовал это изображение в PNG, используя GIMP.

Обратите внимание, что никакой функциональности рисования кругов, или что-то подобное, он не использовал. Изображение рассчитывается попиксельно.

Пример вывода

Более высокие степени подразделения могут быть легко созданы путем увеличения константы 3вокруг середины кода.

Изображения степени 4 и 5 выглядят так:

Степень 45 степень

Общая последовательность кода:

  1. Сгенерируйте координаты всех пикселей, нормированные для диапазона [-1.0, 1.0].
  2. Обведите все пиксели.
  3. Цикл по степеням подразделения.
  4. Для каждого подразделения проверьте, находится ли пиксель внутри / снаружи, и сохраните результат. Масштабирование / преобразование координат пикселей в системы координат с центром в одном из 4 подколец. Выберите тот, где преобразованные координаты находятся ближе всего к центру.
  5. Из двоичных внутренних / внешних результатов каждого градуса найдите первый 0, соответствующий первому градусу, в котором пиксель находился снаружи, и возьмите его по модулю 2, чтобы определить цвет пикселя.

Объяснение:

"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.
Рето Коради
источник
17

Python 2 + PIL, 262 байта

введите описание изображения здесь

Этот подход определяет цвет каждой отдельной координаты пикселя, используя рекурсивную функцию c. c(x,y,0)делает круг; c(x,y,1)делает круг с вырезанными из него четырьмя кругами; c(x,y,2)отображает изображение в OP. Все, что больше 2, приносит мне очки брауни.

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

Версия без гольфа:

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

Бонус экстрарекурсивного изображения:

введите описание изображения здесь

Kevin
источник
Вместо того, чтобы .save("p.png")просто использовать.show()
Альберт Реншоу
7

PostScript, 335 байт.

%!
/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 - это не просто формат графических файлов с векторными и растровыми возможностями, это фактически объектно-ориентированный язык программирования Turing. Приведенный выше код является довольно простой рекурсивной реализацией функции. Все операторы PostScript являются функциями, и обычно их переопределяют для сжатия кода. Обратите внимание, что в PostScript используется нотация на обратном польском (нотация постфикса).

Интерпретаторы PostScript обычно читают метаданные (например, размер и заголовок страницы) из специальных комментариев в начале файла; очевидно, я удалил %!из своей записи все, кроме самого необходимого комментария подписи PostScript , но он все равно должен отображаться нормально в любом стандартном интерпретаторе PostScript, например, GhostScript или Okular. Его также можно просмотреть с помощью утилиты отображения, которая поставляется с ImageMagick / GraphicsMagick.

Обратите внимание, что файл должен заканчиваться символом новой строки (который я включил в мой счетчик байтов), иначе интерпретатор может расстроиться.

Параметр размера Nдля этого кода 512; он делится на 2 и дублируется дважды, чтобы создать параметры для первоначального вызова рекурсивной функции f. Глубина рекурсии равна 2, что указывается перед входом fв 512 2 div dup dup 2 f. Чтобы размер был небольшим, на выходе изображение будет черно-белым. Хотя вы можете установить любую разумную неотрицательную целочисленную глубину рекурсии, эта версия хорошо выглядит только с четной глубиной.

Это изображение является векторной графикой, поэтому оно может отображаться в любом разрешении без пикселизации, в зависимости от качества и настроек используемого интерпретатора / принтера PostScript. (FWIW, PostScript использует кубические кривые Безье для рисования дуг окружности с достаточным количеством сплайнов, чтобы гарантировать, что ошибка всегда будет меньше одного пикселя в пространстве устройства). Чтобы просмотреть его с помощью дисплея ImageMagick в достаточно высоком качестве, вы можете сделать:

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

те же параметры также хороши, если вы хотите использовать ImageMagick convertдля преобразования его в другой формат. Например, вот версия 640x640 вышеупомянутого кода PostScript, преобразованного в PNG:

640x640 B & W круговой фрактал


Вот немного увеличенная версия, которая обрабатывает цвета RGB и нечетные глубины рекурсии:

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

Это также позволяет вам установить параметр размера Nи глубину рекурсии dв верхней части скрипта.

640x640 цветовой круг фрактал, глубина == 2


Наконец, вот более читаемая форма кода. (К сожалению, подсветка синтаксиса используется здесь для PostScript оставляет много желать лучшего, но я предполагаю , что это лучше , чем ничего ...). Умные интерпретаторы PostScript будут читать геометрию страницы из %%BoundingBox:специального комментария.

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

А вот вывод глубины == 4 в формате PNG, снова созданный с помощью convert (и оптимизированный с помощью optipng ):

640x640 цветовой круг фрактал, глубина == 4

PM 2Ring
источник
6

Python 2 + PIL, 361 байт

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

Сохраняет изображение в черно-белом режиме в файл c.png:

пример вывода

Я в основном создаю один из половинных кругов на изображении J. Затем я использую себя в качестве маски, чтобы нарисовать фигуру на изображение I, которое имеет основной круг.

Его можно было бы сократить, используя I.show()в конце вместо I.save("c.png"), но я не работал на Python 2. Если кто-то может подтвердить, что он работает на Python 2, я перейду на это.

Следующая программа генерирует изображение как в вопросе (419 байт):

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
источник
-1 не так красиво, как изображение Кальвина;)
Beta Decay
Я могу подтвердить, что .show () работает
Альберт Реншоу
Хорошо, спасибо, я буду использовать это вместо save.
Кевин
3

SVG (1249 символов)

Да, много персонажей. Но это статично и рендеринг в любом размере, так что это дает некоторый бонус.

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

Просмотр фрагмента:

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>

совать
источник
Обратите внимание, что, как сказал Мего, SVG не удовлетворяет нашим критериям для квалификации в качестве языка программирования . Однако ФП может разрешить этот ответ в любом случае; это до него.
Алекс А.
SVG хорошо в этом случае.
Увлечения Кэлвина
Можете ли вы опустить ведущие 0в константах с плавающей точкой? Например, заменить 0.4на .4? На большинстве языков это действительно так. И очень быстрый взгляд на спецификацию SVG предполагает, что она, вероятно, должна работать и их.
Рето Коради
@RetoKoradi Да, и вы, вероятно, можете вычислить еще несколько чисел, эффективно округлив или изменив размер таким образом, чтобы вам требовалось меньше десятичных дробей, но не больше. Получающиеся пути слишком сложны, чтобы это имело огромное значение. Но я могу попробовать другое решение, используя маски позже.
тыкай
2

Mathematica 336 359 байт

Основными графическими объектами являются области, определенные посредством логических комбинаций уравнений.

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

фильм

DavidC
источник
1

Ява, 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();}}

В основном просто экспериментирую с JavaFX.

Скриншот:

Скриншот

Для точек брауни измените 2код в ( d(n,2,0,0)) на другое число.

Старая версия, 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();}}

Это оставляет некоторые нежелательные края, как вы можете видеть на этом скриншоте .

aditsu
источник
0

JavaScript (ES6), 279

Рекурсивно создавайте холсты и добавляйте дочерний холст четыре раза к родительскому холсту. В нижнем слое холст представляет собой один круг; этот холст четыре раза ставится на родительский холст, а затем этот холст четыре раза ставится на последний мастер-холст.

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

представление изображения

Демоверсия запуска:

С пробелами, комментариями и мягким разгромом:

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
)

Это может легко создать более глубокие слои рекурсии путем изменения начального o-2или любого большего o-zзначения.

Обратите внимание, что отправка будет выполняться только в Firefox из-за использования функций ES6 и несогласованности в API Canvas для аргументов fillи clipаргументов.

apsillers
источник