Chaînes récursives de Steiner


11

Les chaînes de Steiner sont un ensemble de N cercles où chaque cercle est tangent à 2 autres cercles non entrecroisés ainsi qu'aux cercles précédent et suivant de la chaîne, comme le montrent les images ci-dessous:

Ordre 3 Ordre 5 Ordre 7

Dans ce défi, vous écrirez un programme / une fonction qui dessine récursivement des chaînes de Steiner, c'est-à-dire que les cercles d'une chaîne donnée seront les cercles de base d'une autre itération de chaînes:

entrez la description de l'image ici

Défi

Écrivez un programme / fonction qui accepte les dimensions de l'image et une liste d'entiers indiquant le niveau des cercles dans chaque itération successive de chaînes, et sortez une image avec les chaînes Steiner récursives attirées dessus.

Contribution

Votre programme / fonction acceptera 2 arguments:

  • s - largeur et hauteur de l'image
  • ls - liste d'entiers positifs indiquant le nombre de cercles présents dans chaque itération successive de chaînes, classés de la chaîne la plus haute à la chaîne la plus basse

Production

Votre programme / fonction affichera une image de dimension sx saffichant la chaîne récurrente de Steiner.

  • Le cercle de base de niveau supérieur sera aussi grand que l'image avec un diamètre de s, centré à l'intérieur de l'image
  • Pour faciliter les choses, les 2 cercles de base d'une chaîne Steiner seront concentriques, c'est-à-dire que les points centraux des 2 cercles de base seront les mêmes
  • Étant donné un rayon extérieur R, et le nombre de cercles dans une chaîne N, la formule du rayon intérieur R'estR' = (R-R*sin(pi/N))/(sin(pi/N)+1)
  • Les cercles de la chaîne ainsi que le cercle de base interne seront les cercles de base externes de la prochaine itération des chaînes
  • Lors de la répétition à travers les cercles de chaîne, l'ordre de la chaîne suivante doit correspondre à la valeur suivante dans ls
  • Tout en récurant à travers le cercle intérieur d'une chaîne, l'ordre doit être le même que celui de ses parents (exemple [5,2]):
  • Commande 5.2
  • Toutes les chaînes doivent terminer la récursivité à une profondeur de la longueur de ls
  • La rotation des chaînes n'a pas d'importance:
  • Rotation 1 Rotation 2
  • Cependant, les rotations des chaînes récursives par rapport au point central de leurs parents devraient être les mêmes:
  • Commande 5.2 Commande non valide 5.2
  • Tous les cercles doivent être dessinés avec un contour ou un remplissage plein
  • Le choix des couleurs est laissé à l'implémentation, sauf pour les failles (par exemple, tout remplir avec la même couleur)

Exemples d'exécutions

Dans les exemples suivants, la couleur est déterminée par (depth of the recursion)^4.

Vous pouvez trouver la source ici .

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


Réponses:


4

Javascript ES6, 379 octets

Cette solution a été utilisée pour générer les exécutions d'exemple dans la question.

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

Non 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

Remarque: frenvoie un canevas.

Exemple d'exécution (en supposant qu'il y a un <body>à ajouter):

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

Devrait vider l'image suivante sur la page:

Production

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.