Rekursive Steiner-Ketten

11

Steiner-Ketten sind eine Reihe von N Kreisen, wobei jeder Kreis zwei andere nicht schneidende Kreise sowie den vorherigen und den nächsten Kreis der Kette tangiert, wie in den folgenden Bildern dargestellt:

Bestellung 3 Bestellung 5 Bestellung 7

In dieser Herausforderung schreiben Sie ein Programm / eine Funktion, die Steiner-Ketten rekursiv zeichnet, dh Kreise einer bestimmten Kette sind die Basiskreise einer anderen Ketteniteration:

Geben Sie hier die Bildbeschreibung ein

Herausforderung

Schreiben Sie ein Programm / eine Funktion, die Bilddimensionen und eine Liste von Ganzzahlen akzeptiert, die die Kreisebene in jeder aufeinanderfolgenden Iteration von Ketten angeben, und geben Sie ein Bild mit den darauf gezeichneten rekursiven Steiner-Ketten aus.

Eingang

Ihr Programm / Ihre Funktion akzeptiert 2 Argumente:

  • s - Breite und Höhe des Bildes
  • ls - Liste der positiven ganzen Zahlen, die die Anzahl der Kreise angibt, die in jeder aufeinanderfolgenden Iteration von Ketten vorhanden sind, geordnet von der obersten bis zur untersten Kette

Ausgabe

Ihr Programm / Ihre Funktion gibt ein Bild der Dimension sx aus s, das die wiederkehrende Steiner-Kette anzeigt.

  • Der Basiskreis der obersten Ebene ist so groß wie das Bild mit einem Durchmesser von szentriert im Bild
  • Zur Vereinfachung sind die beiden Grundkreise einer Steiner-Kette konzentrisch, dh die Mittelpunkte der beiden Grundlinienkreise sind gleich
  • Bei einem äußeren Radius Rund der Anzahl der Kreise in einer Kette lautet Ndie Formel für den inneren RadiusR'R' = (R-R*sin(pi/N))/(sin(pi/N)+1)
  • Kreise der Kette sowie der innere Basiskreis sind die äußeren Basiskreise der nächsten Ketteniteration
  • Beim Durchlaufen der Kettenkreise sollte die Reihenfolge der nächsten Kette dem nächsten Wert in entsprechen ls
  • Beim Durchlaufen des inneren Kreises einer Kette sollte die Reihenfolge mit der Reihenfolge der Eltern übereinstimmen (Beispiel [5,2]):
  • Bestellung 5.2
  • Alle Ketten sollten die Rekursion in einer Tiefe von der Länge von beenden ls
  • Die Rotation der Ketten spielt keine Rolle:
  • Drehung 1 Drehung 2
  • Die Rotationen rekursiver Ketten relativ zum Mittelpunkt ihrer Eltern sollten jedoch gleich sein:
  • Bestellung 5.2 Ungültige Reihenfolge 5.2
  • Alle Kreise sollten mit einem Umriss oder einer festen Füllung gezeichnet werden
  • Die Farbauswahl bleibt der Implementierung überlassen, abgesehen von Lücken (z. B. Füllen aller Elemente mit derselben Farbe).

Beispielläufe

In den folgenden Beispielen wird die Farbe durch bestimmt (depth of the recursion)^4.

Die Quelle finden Sie hier .

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
quelle
1
Verbunden.
Martin Ender

Antworten:

4

Javascript ES6, 379 Bytes

Diese Lösung wurde verwendet, um die Beispielläufe in der Frage zu generieren.

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

Hinweis: fGibt eine Zeichenfläche zurück.

Beispiellauf (vorausgesetzt, es gibt einen <body>Anhang):

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

Sollte das folgende Bild auf der Seite ablegen:

Ausgabe

Dendrobium
quelle