Correntes Steiner recursivas

11

As Correntes Steiner são um conjunto de N círculos em que cada círculo é tangente a outros 2 círculos sem interseção, bem como aos círculos anteriores e seguintes da cadeia, conforme visto nas imagens abaixo:

Ordem 3 Ordem 5 Ordem 7

Neste desafio, você escreverá um programa / função que desenha cadeias de Steiner recursivamente, ou seja, os círculos de uma determinada cadeia serão os círculos base de outra iteração de cadeias:

insira a descrição da imagem aqui

Desafio

Escreva um programa / função que aceite as dimensões da imagem e uma lista de números inteiros denotando o nível de círculos em cada iteração sucessiva de cadeias e imprima uma imagem com as cadeias recursivas de Steiner desenhadas para ela.

Entrada

Seu programa / função aceitará 2 argumentos:

  • s - largura e altura da imagem
  • ls - lista de números inteiros positivos que indicam o número de círculos presentes em cada iteração sucessiva de cadeias, ordenadas da cadeia mais superior à mais inferior

Resultado

Seu programa / função exibirá uma imagem da dimensão sx sexibindo a cadeia Steiner recusativa.

  • O círculo base do nível superior será tão grande quanto a imagem com um diâmetro scentrado dentro da imagem
  • Para facilitar as coisas, os 2 círculos básicos de uma cadeia de Steiner serão concêntricos, ou seja, os pontos centrais dos 2 círculos da linha de base serão os mesmos
  • Dado um raio externo R, e o número de círculos em uma cadeia N, a fórmula para o raio interno R'éR' = (R-R*sin(pi/N))/(sin(pi/N)+1)
  • Os círculos da cadeia, bem como o círculo base interno, serão os círculos base externos da próxima iteração de cadeias
  • Ao recorrer pelos círculos da cadeia, a ordem da próxima cadeia deve corresponder ao próximo valor em ls
  • Enquanto se repete através do círculo interno de uma cadeia, a ordem deve ser igual à ordem de seus pais (exemplo [5,2]):
  • Pedido 5.2
  • Todas as cadeias devem terminar a recursão a uma profundidade do comprimento de ls
  • A rotação das correntes não importa:
  • Rotação 1 Rotação 2
  • No entanto, as rotações das cadeias recursivas em relação ao ponto central dos pais devem ser as mesmas:
  • Pedido 5.2 Pedido 5.2 inválido
  • Todos os círculos devem ser desenhados com um contorno ou preenchimento sólido
  • A escolha da cor é deixada para a implementação, exceto as brechas (por exemplo, preenchendo tudo com a mesma cor)

Execuções de exemplo

Nos exemplos a seguir, a cor é determinada por (depth of the recursion)^4.

Você pode encontrar a fonte aqui .

chain(600,[5,4,3])

5.4.3

chain(600,[11,1,1,1,1,1,1])

11.1.1.1.1.1.1

chain(600,[5,6,7,8,9])

5.6.7.8.9

Dendrobium
fonte
1
Relacionado.
Martin Ender

Respostas:

4

Javascript ES6, 379 bytes

Esta solução foi usada para gerar as execuções de exemplo na pergunta.

f=(s,ls)=>{with(V=document.createElement`canvas`)with(getContext`2d`)with(Math)return(width=height=s,translate(s/=2,s),(S=(o,d=0,n=ls[d],i=(o-o*sin(PI/n))/(sin(PI/n)+1),r=0)=>{fillStyle=`rgba(0,0,0,${pow(d/ls.length,4)})`;beginPath(),arc(0,0,o,-PI,PI),fill();if(d++<ls.length){S(i,d,n);for(;r<n;++r){save();translate(0,(o+i)/2);S((o-i)/2,d);restore();rotate((2*PI)/n);}}})(s),V)}

Ungolfed:

f=(s,ls)=>{                                        // define function that accepts image dimensions and a list of orders
 with(V=document.createElement`canvas`)            // create canvas to draw on, bring its functions into current scope chain
 with(getContext`2d`)                              // bring graphics functions into current scope chain
 with(Math)return(                                 // bring Math functions into current scope chain
  width=height=s,                                  // set width and height of image
  translate(s/=2,s),                               // center the transform on image
   (S=(o,d=0,                                      // define recursive function that accepts outer radius, depth, and optionally order
       n=ls[d],                                    // default chain order to corresponding order in input list
       i=(o-o*sin(PI/n))/(sin(PI/n)+1),            // calculate inner base circle radius
       r=0)=>{                                     // initialize for loop var
    fillStyle=`rgba(0,0,0,${pow(d/ls.length,4)})`; // fill based on depth
    beginPath(),arc(0,0,o,-PI,PI),fill();          // draw circle
    if(d++<ls.length){                             // if within recursion limit
     S(i,d,n);                                     //   recurse on inner circle
     for(;r<n;++r){                                //   loop through all circles of the chain
      save();                                      //   save transform
      translate(0,(o+i)/2);                        //   translate origin to middle of the 2 base circles
      S((o-i)/2,d);                                //   recurse on chain circle
      restore();                                   //   restore transform
      rotate((2*PI)/n);                            //   rotate transform to next circle in chain
   }}})(s),                                        // begin the recursion
 V)}                                               // return the canvas

Nota: fretorna uma tela.

Exemplo de execução (pressupõe que haja um <body>para anexar):

document.body.appendChild(f(600,[13,7,11,5,3]))

Deve despejar a seguinte imagem na página:

Resultado

Dendrobium
fonte