递归Steiner链


11

斯坦纳链是一组N个圆,每个圆与两个其他不相交的圆以及该链的上一个和下一个圆相切,如下图所示:

订单3 5阶 订单7

在此挑战中,您将编写一个程序/函数以递归方式绘制Steiner链,也就是说,给定链的圆将是链的另一次迭代的基础圆:

在此处输入图片说明

挑战

编写一个程序/函数,该程序/函数接受图像尺寸以及表示链的每个连续迭代中圆圈水平的整数列表,并输出绘制了递归Steiner链的图像。

输入值

您的程序/函数将接受2个参数:

  • s -图片的宽度和高度
  • ls -表示链的每个连续迭代中存在的圆数的正整数列表,从最上链到最下链排序

输出量

您的程序/函数将输出尺寸为sx 的图像,s显示可追溯的Steiner链。

  • 顶层基圆将与图像一样大,直径为s,位于图像内部
  • 为了简化起见,Steiner链的2个基圆将是同心的,即2个基线圆的中心点将是相同的
  • 给定的外半径,R和圆的在链条的数量,N为内半径的公式R'R' = (R-R*sin(pi/N))/(sin(pi/N)+1)
  • 链的圆以及内部基圆将是链的下一次迭代的外部基圆
  • 在通过链环递归时,下一个链的顺序应对应于中的下一个值 ls
  • 在通过链的内圈递归时,顺序应与其父顺序相同(例如[5,2]):
  • 订单5.2
  • 所有链条应在深度为 ls
  • 链条的旋转无关紧要:
  • 旋转1 旋转2
  • 但是,递归链相对于其父母中心点的旋转应相同:
  • 订单5.2 无效订单5.2
  • 所有圆都应画出轮廓或实心填充
  • 颜色选择留给实现,除了漏洞(例如,用相同的颜色填充所有内容)

示例运行

在以下示例中,颜色由确定(depth of the recursion)^4

您可以在此处找到源。

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


Answers:


4

Javascript ES6,379个字节

此解决方案用于生成问题中的示例运行。

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

取消高尔夫:

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

注意:f返回画布。

运行示例(假设<body>要追加一个):

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

应将以下图像转储到页面:

输出量

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.