Cadenas Steiner recursivas

11

Steiner Chains es un conjunto de N círculos donde cada círculo es tangente a otros 2 círculos que no se cruzan, así como a los círculos anteriores y siguientes de la cadena, como se ve en las imágenes a continuación:

Orden 3 Orden 5 Orden 7

En este desafío, escribirá un programa / función que dibuja cadenas Steiner de forma recursiva, es decir, los círculos de una cadena dada serán los círculos base de otra iteración de cadenas:

ingrese la descripción de la imagen aquí

Desafío

Escriba un programa / función que acepte dimensiones de imagen y una lista de enteros que denotan el nivel de los círculos en cada iteración sucesiva de cadenas, y genere una imagen con las cadenas recursivas de Steiner dibujadas a ella.

Entrada

Su programa / función aceptará 2 argumentos:

  • s - ancho y alto de la imagen
  • ls - lista de enteros positivos que denotan el número de círculos presentes en cada iteración sucesiva de cadenas, ordenadas desde la cadena superior hasta la cadena inferior

Salida

Su programa / función generará una imagen de dimensión sx que smuestra la cadena de Steiner recusiva.

  • El círculo base del nivel superior será tan grande como la imagen con un diámetro scentrado dentro de la imagen
  • Para facilitar las cosas, los 2 círculos de base de una cadena Steiner serán concéntricos, es decir, los puntos centrales de los 2 círculos de referencia serán los mismos
  • Dado un radio externo R, y el número de círculos en una cadena N, la fórmula para el radio interno R'esR' = (R-R*sin(pi/N))/(sin(pi/N)+1)
  • Los círculos de la cadena, así como el círculo base interno, serán los círculos base externos de la próxima iteración de cadenas.
  • Mientras se repite a través de los círculos de la cadena, el orden de la siguiente cadena debe corresponder al siguiente valor en ls
  • Mientras se repite a través del círculo interno de una cadena, el orden debe ser el mismo que el orden de sus padres (ejemplo [5,2]):
  • Orden 5.2
  • Todas las cadenas deben terminar la recursión a una profundidad de la longitud de ls
  • La rotación de las cadenas no importa:
  • Rotación 1 Rotación 2
  • Sin embargo, las rotaciones de las cadenas recursivas en relación con el punto central de sus padres deberían ser las mismas:
  • Orden 5.2 Orden inválida 5.2
  • Todos los círculos deben dibujarse con un contorno o relleno sólido.
  • La elección del color se deja a la implementación, salvo las lagunas (por ejemplo, llenar todo con el mismo color)

Ejecuciones de ejemplo

En los siguientes ejemplos, el color está determinado por (depth of the recursion)^4.

Puedes encontrar la fuente aquí .

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
fuente
1
Relacionado.
Martin Ender

Respuestas:

4

Javascript ES6, 379 bytes

Esta solución se utilizó para generar el ejemplo que se ejecuta en la pregunta.

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

Sin golf:

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: fdevuelve un lienzo.

Ejemplo de ejecución (se supone que hay <body>que agregar):

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

Debería volcar la siguiente imagen a la página:

Salida

Dendrobium
fuente