재귀 Steiner 체인


11

Steiner Chains는 아래 이미지에서 볼 수 있듯이 N 개의 원 세트로, 각 원이 2 개의 다른 교차하지 않는 원과 체인의 이전 및 다음 원에 접합니다.

주문 3 주문 5 주문 7

이 도전에서는 Steiner 체인을 재귀 적으로 그리는 프로그램 / 함수를 작성합니다. 즉, 주어진 체인의 원은 다른 체인 반복의 기본 원이됩니다.

여기에 이미지 설명을 입력하십시오

도전

연속적인 체인 반복마다 원의 레벨을 나타내는 이미지 차원과 정수 목록을 받아들이는 프로그램 / 함수를 작성하고 재귀 Steiner 체인이 그려진 이미지를 출력하십시오.

입력

귀하의 프로그램 / 기능은 2 개의 인수를받습니다 :

  • s -이미지의 너비와 높이
  • ls -체인의 각 연속 반복에 존재하는 원의 수를 나타내는 양의 정수 목록, 최상위 체인에서 최하단 체인으로 정렬

산출

프로그램 / 기능은 Recusive Steiner 체인을 표시하는 차원 sx 의 이미지를 출력합니다 s.

  • 상단의 기본 원은 지름 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


답변:


4

자바 스크립트 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]))

다음 이미지를 페이지에 덤프해야합니다.

산출

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.