TikZ 솔루션

TikZ 솔루션

tikz를 사용하여 이 정확한 다이어그램을 다시 만들려고 합니다. 지금까지 나는 다른 프랙탈 구성에 이것을 사용한 이후 tikz에서 중첩된 장식을 사용하려고 시도했습니다. 그러나 이러한 구성은 모두 Koch 곡선과 같이 tikz에 의해 미리 정의된 장식이거나 Sierpinski 삼각형과 같이 스택 교환에서 솔루션을 찾은 것이었습니다.

나는 내 자신의 장식을 정의하기 위해 많은 노력을 기울여왔지만 tikz 초보자에게는 꽤 복잡한 과정인 것 같고 내가 하려는 것과 너무 유사한 예를 찾지 못했습니다. 린데마이어 시스템을 사용하는 것도 가능하다는 것을 알고 있지만 라인 구성에 사용하는 방법만 이해합니다.

도움이 된다면 가장 간단한 방법은 정사각형을 원점이 왼쪽 하단에 있는 초기 모양으로 설정한 다음 왼쪽 하단 정사각형에 대해 1/4로 크기를 조정하고 1/4로 크기를 조정하는 것입니다. 4 그런 다음 왼쪽 상단 사각형 등을 위쪽으로 변환한 다음 초기를 대체할 새 모양을 설정하고 다음 반복을 준비합니다.

문제의 프랙탈

어떤 도움이라도 주시면 감사하겠습니다!

답변1

Lindenmayer 시스템을 사용하는 방법은 다음과 같습니다. 5개 이상의 주문은 LuaLaTeX로 컴파일하세요.

% \RequirePackage{luatex85} % Only for LuaLaTeX and standalone class
\documentclass[varwidth,border=5]{standalone}
\usepackage{tikz}
\usetikzlibrary{lindenmayersystems}
\pgfdeclarelindenmayersystem{square fractal}{%
  \symbol{S}{\pgflsystemstep=0.5\pgflsystemstep}
  \symbol{A}{\pgftransformshift%
    {\pgfqpoint{0.75\pgflsystemstep}{0.75\pgflsystemstep}}}
  \symbol{R}{\pgftransformrotate{90}}
  \symbol{Q}{%
    \pgfpathrectangle{\pgfqpoint{-0.5\pgflsystemstep}{-0.5\pgflsystemstep}}%
    {\pgfqpoint{\pgflsystemstep}{\pgflsystemstep}}%
  }
  \rule{Q -> [SQ[ASQ][RASQ][RRASQ][RRRASQ]]}
}
\begin{document}
\foreach\i in {0,...,5}{%
\tikz\fill [l-system={square fractal, step=5cm, axiom=Q, order=\i}] 
  lindenmayer system;
\ifodd\i\par\bigskip\leavevmode\fi
}
\end{document}

여기에 이미지 설명을 입력하세요

장식을 사용하는 방법은 다음과 같습니다.

\documentclass[varwidth,border=5]{standalone}
\usepackage{tikz}
\usetikzlibrary{decorations}
\pgfdeclaredecoration{square fractal}{start}{
\state{start}[width=0pt,next state=draw]{
  \pgfpathmoveto{\pgfpointdecoratedinputsegmentfirst}
}
\state{draw}[width=\pgfdecoratedinputsegmentlength]{
  \pgfpointdiff{\pgfpointdecoratedinputsegmentfirst}%
    {\pgfpointdecoratedinputsegmentlast}
  \pgfgetlastxy\tmpx\tmpy
  \pgfmathveclen\tmpx\tmpy
  \pgfmathparse{\pgfmathresult/4}%
  \let\tmp=\pgfmathresult
  \pgfpathlineto{\pgfpoint{\tmp}{+0pt}}
  \pgfpathlineto{\pgfpoint{\tmp}{-\tmp}}
  \pgfpathlineto{\pgfpoint{3*\tmp}{-\tmp}}
  \pgfpathlineto{\pgfpoint{3*\tmp}{+0pt}}
  \pgfpathlineto{\pgfpointdecoratedinputsegmentlast}
}
\state{final}{
  \pgfpathclose
}
}
\begin{document}
\tikz[decoration=square fractal]
  \fill (0,0) rectangle (4,4);
\tikz[decoration=square fractal]
  \fill decorate { (0,0) rectangle (4,4) };
\\
\tikz[decoration=square fractal]
  \fill decorate { decorate { (0,0) rectangle (4,4) } };
\tikz[decoration=square fractal]
  \fill decorate { decorate { decorate { (0,0) rectangle (4,4) } } };
\end{document}

여기에 이미지 설명을 입력하세요

답변2

TikZ 솔루션

프랙탈의 검은색 사각형은 다음을 통해 생성됩니다.확장 가능재귀.

\documentclass[tikz]{standalone}

\usepackage{etoolbox}
\makeatletter
\patchcmd{\tikz@@command@path}{=100}{=10000}{}{\errmessage{Patching failed.}}
\makeatother

\makeatletter
\newcommand*{\@SquareFractal}[4]{%
  % #1: order
  % #2: edge length
  % #3: x position of lower left corner
  % #4: y position of lower left corner
  \ifnum#1=0
    (#3,#4)rectangle(\the\dimexpr(#3)+(#2)\relax,\the\dimexpr(#4)+(#2)\relax)%
    \expandafter\@gobble
  \else
    \expandafter\@firstofone
  \fi
  {
    % Middle
    \expandafter\@SquareFractal
    \expandafter{\the\numexpr(#1)-1\expandafter}%
    \expandafter{\the\dimexpr(#2)/2\expandafter}%
    \expandafter{\the\dimexpr(#3)+(#2)/4\expandafter}%
    \expandafter{\the\dimexpr(#4)+(#2)/4}%
    % Bottom left
    \expandafter\@SquareFractal
    \expandafter{\the\numexpr(#1)-1\expandafter}%
    \expandafter{\the\dimexpr(#2)/4}%
    {#3}%
    {#4}%
    % Bottom right
    \expandafter\@SquareFractal
    \expandafter{\the\numexpr(#1)-1\expandafter}%
    \expandafter{\the\dimexpr(#2)/4\expandafter}%
    \expandafter{\the\dimexpr(#3)+(#2)*3/4}%
    {#4}%
    % Top left
    \expandafter\@SquareFractal
    \expandafter{\the\numexpr(#1)-1\expandafter}%
    \expandafter{\the\dimexpr(#2)/4\expandafter}%
    \expandafter{\the\dimexpr(#3)\expandafter}%
    \expandafter{\the\dimexpr(#4)+(#2)*3/4}%
    % Top right
    \expandafter\@SquareFractal
    \expandafter{\the\numexpr(#1)-1\expandafter}%
    \expandafter{\the\dimexpr(#2)/4\expandafter}%
    \expandafter{\the\dimexpr(#3)+(#2)*3/4\expandafter}%
    \expandafter{\the\dimexpr(#4)+(#2)*3/4}%
  }%
}


\newcommand*{\SquareFractal}[2]{%
  % #1: order
  % #2: edge length
  \begingroup
    \edef\x{\@SquareFractal{#1}{#2}{0pt}{0pt}}%
    \expandafter\tikz\expandafter\fill\x;%
  \endgroup
}
\makeatother

\begin{document}
  \foreach\i in {0, ..., 5} {\SquareFractal{\i}{\linewidth}}
\end{document}

전체 그리기 명령은 메모리에 보관되므로 메모리가 제한 요소입니다.

주문 5에 대한 결과:

주문 5

IniTeX 솔루션

다음 예에서는 메모리 부족 없이 더 높은 순서를 얻기 위해 사각형을 그리는 iniTeX의 간단한 규칙을 사용합니다.

TeX의 최대 크기는 16383.99998pt( \maxdimen)입니다. 이는 (2 30 - 1) sp (1 pt = 2 16 sp = 65536 sp)입니다. 다음 레벨의 가장 작은 정사각형은 1/4의 정사각형 가장자리 길이를 사용합니다. 그러면 가장 작은 정사각형 모서리 길이가 1 sp이고 가장 큰 차수는 14이고 결과의 모서리 길이는 2 28 sp입니다.

pdftex -ini -etex이 예제에서는 iniTeX 모드( 또는 ) 에서 pdfTeX 또는 luaTeX를 사용합니다 luatex -ini. LuaTeX는 더 빠르고 메모리 제한이 적습니다. 비교를 위해 차수 8은 pdfTeX에서는 약 45초가 걸리지만 LuaTeX에서는 8초가 걸립니다. LuaTeX를 사용한 더 높은 주문:

  • 주문 10:시간은 3 3/4분, 파일 크기는 47MiB입니다.

  • 주문 11:시간은 33분, 파일 크기는 173MiB입니다.

12번째 주문에서 컴퓨터가 포기하고 재부팅해야 했습니다.

예:

\catcode`\{=1
\catcode`\}=2
\catcode`\#=6

\ifx\directlua\undefined
  \pdfoutput=1
  \pdfminorversion=4
  \pdfhorigin=0pt
  \pdfvorigin=0pt
  \pdfcompresslevel=9
\else
  \directlua{%
    tex.enableprimitives('', {'outputmode', 'dimexpr', 'numexpr'})
    tex.enableprimitives('pdf', {'pagewidth', 'pageheight'})
  }
  \outputmode=1
  \directlua{
    pdf.setorigin()
    pdf.setminorversion(4)
    pdf.setcompresslevel(9)
  }
\fi

\dimendef\pagewidth=0
\dimendef\xpos=2

\def\SquareFractal#1#2{%
  % #1: order
  % #2: minimum edge length
  \pagewidth=\dimexpr#2\MulFour#1!\relax
  \immediate\write16{* Calculating square fractal of order #1 ...}%
  \pdfpagewidth=\pagewidth %
  \pdfpageheight=\pagewidth %
  \shipout\hbox{%
    \xpos=0pt\relax
    \SquareFractalRecursiv#1!\pagewidth!0pt!0pt!%
    \kern\dimexpr\pagewidth-\xpos\relax
  }%
  \advance\count0 by 1\relax
}

\def\MulFour#1!{%
  \ifnum#1=0
  \else
    *4%
    \expandafter\MulFour
    \the\numexpr#1-1\expandafter!%
  \fi
}

\def\SquareFractalRecursiv#1!#2!#3!#4!{%
  % #1: order
  % #2: edge length
  % #3: x position of lower left corner
  % #4: y position of lower left corner
  \ifnum#1=0 %
    \iffalse
      \raise#4\hbox to 0pt{%
        \kern#3\relax
        \vrule width#2height#2\relax
        \hss
      }%
    \else
      \ifdim#3=\xpos
      \else
        \kern\dimexpr#3-\xpos\relax
      \fi
      \vrule width#2 depth-#4 height\dimexpr#4+#2\relax
      \xpos=\dimexpr#3+#2\relax
    \fi
  \else
    % Lower left square
    \expandafter\SquareFractalRecursiv
    \the\numexpr#1-1\expandafter!%
    \the\dimexpr#2/4\expandafter!%
    #3!%
    #4!%
    % Middle square
    \expandafter\SquareFractalRecursiv
    \the\numexpr#1-1\expandafter!%
    \the\dimexpr#2/2\expandafter!%
    \the\dimexpr#3+#2/4\expandafter!%
    \the\dimexpr#4+#2/4!%
    % Lower right square
    \expandafter\SquareFractalRecursiv
    \the\numexpr#1-1\expandafter!%
    \the\dimexpr#2/4\expandafter!%
    \the\dimexpr#3+#2*3/4!%
    #4!%
    % Upper left square
    \expandafter\SquareFractalRecursiv
    \the\numexpr#1-1\expandafter!%
    \the\dimexpr#2/4\expandafter!%
    \the\dimexpr#3\expandafter!%
    \the\dimexpr#4+#2*3/4!%
    % Upper right square
    \expandafter\SquareFractalRecursiv
    \the\numexpr#1-1\expandafter!%
    \the\dimexpr#2/4\expandafter!%
    \the\dimexpr#3+#2*3/4\expandafter!%
    \the\dimexpr#4+#2*3/4\expandafter!%
  \fi
}

% BTW, unit bp instead of pt decreases the output file size
% a bit because of less fractional digits.

% \SquareFractal{<order>}{<length of smallest square>}
% The values of the follwing calls are used in such a way
% that the generated fractals with different orders have
% the same widths and heights.

\SquareFractal{0}{4096pt}
\SquareFractal{1}{1024pt}
\SquareFractal{2}{256pt}
\SquareFractal{3}{64pt}
\SquareFractal{4}{16pt}
\SquareFractal{5}{4pt}
\SquareFractal{6}{1pt}% 65536 sp
\SquareFractal{7}{16384sp}
\SquareFractal{8}{4096sp}
\SquareFractal{9}{1024sp}
\SquareFractal{10}{256sp}
\SquareFractal{11}{64sp}
% \SquareFractal{12}{16sp}
% \SquareFractal{13}{4sp}
% \SquareFractal{14}{1sp}
\end

주문 11에 대한 결과(imgur에서 더 나은 해결 방법을 거부함):

결과, 주문 11

정사각형의 수가 너무 많기 때문에 순서가 높은 PDF를 보면 PDF 뷰어의 속도가 느려집니다.

따라서 가장 작은 정사각형을 1 x 1 픽셀의 정사각형으로 사용하여 단색 비트맵 이미지를 생성하는 것이 더 효율적입니다. 그러면 차수 11의 이미지 너비와 높이는 2 22 픽셀 = 4194304 픽셀입니다.

답변3

다음은 관심을 가질 만한 MetaPost를 사용한 시도입니다. 재귀 매크로(square_fractal 이 프로그램의 기반이 되는이 답변에게밀접하게 관련된 주제.

vardef square_fractal(expr A, B, n) =
    save P; pair P[]; P0 = A; P1 = B;
    for i = 1 upto 2:
        P[i+1] = P[i-1] rotatedaround (P[i], -90);
    endfor;
    if n = 0: fill P0 for i = 1 upto 3: -- P[i] endfor -- cycle;
    else:
        save Q; pair Q[]; 
        for i = 0, 2:
            Q[i] = 1/4[P[i],P[i+1]]; Q[i+1] = 3/4[P[i],P[i+1]];
            square_fractal(P[i], Q[i], n-1);
            square_fractal(Q[i+1], P[i+1], n-1);
        endfor;
        square_fractal(P0 rotatedaround (Q0, -90), P1 rotatedaround (Q1, 90), n-1); fi
enddef;

beginfig(1);
    for n = 0 upto 4:
        draw image(square_fractal(origin, (4cm, 0), n)) shifted (n*4.5cm, 0);
    endfor;
endfig;

end.

여기에 이미지 설명을 입력하세요

MetaPost는 0차(정사각형)부터 시작하여 내 컴퓨터에서 최대 6차까지의 출력을 관리합니다. 흥미롭게도 이전 코드가 LuaLaTeX 프로그램에 포함되어 있으면 순서 7에 도달합니다. 이유를 모르겠습니다.

편집하다\mplibnumbersystem{double}여전히 LuaLaTeX 내에서 기본 고정 소수점 숫자 대신 부동 소수점 숫자( 바로 뒤에 추가됨 )를 사용한 후 \usepackage{luamplib}MetaPost는 20분 후에 순서 9의 숫자를 생성합니다. 하지만 내 아주 오래된 노트북(2008년형 MacBook Pro)이 거의 얼어붙을 뻔했기 때문에 감히 더 이상 작업을 진행할 수 없습니다. 어쩌면 더 최신의 더 강력한 컴퓨터에서 다시 시도해 볼 수도 있습니다.

\RequirePackage{luatex85}
\documentclass[border=5mm]{standalone}
\usepackage{luamplib}
    \mplibnumbersystem{double}
\begin{document}
\begin{mplibcode}

vardef square_fractal(expr A, B, n) =
    save P; pair P[]; P0 = A; P1 = B;
    for i = 1 upto 2:
        P[i+1] = P[i-1] rotatedaround (P[i], -90);
    endfor;
    if n = 0: fill P0 for i = 1 upto 3: -- P[i] endfor -- cycle;
    else:
        save Q; pair Q[]; 
        for i = 0, 2:
            Q[i] = 1/4[P[i],P[i+1]]; Q[i+1] = 3/4[P[i],P[i+1]];
            square_fractal(P[i], Q[i], n-1);
            square_fractal(Q[i+1], P[i+1], n-1);
        endfor;
        square_fractal(P0 rotatedaround (Q0, -90), P1 rotatedaround (Q1, 90), n-1); fi
enddef;

beginfig(1);
    square_fractal(origin, (12cm, 0), 9);
endfig;

\end{mplibcode}
\end{document}

아래 그림은 주문 8의 것입니다. 노트북이 얼어붙을 뻔해서 주문 9의 PNG 버전을 제작하지 못했습니다.

여기에 이미지 설명을 입력하세요

답변4

Tikz와 재귀를 사용한 또 다른 대안입니다.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\newcommand\DrawFracSquare[4]{{% {Current number}{Side Length}{X}{Y}
  \ifnum#1=0
    \fill[black] ($(#3,#4)-(#2/2,#2/2)$) rectangle +(#2,#2);
  \else
    \pgfmathsetmacro\NewNumber{int(#1-1)}
    \pgfmathsetmacro\NewSideLength{#2/2}
    \edef\NewRec{\noexpand\DrawFracSquare{\NewNumber}{\NewSideLength}{#3}{#4}}
    \NewRec
    \pgfmathsetmacro\NewSideLength{#2/4}
    \pgfmathsetmacro\NewX{#3+3*#2/8}
    \pgfmathsetmacro\NewY{#4+3*#2/8}
    \edef\NewRec{\noexpand\DrawFracSquare{\NewNumber}{\NewSideLength}{\NewX}{\NewY}}
    \NewRec
    \pgfmathsetmacro\NewX{#3-3*#2/8}
    \pgfmathsetmacro\NewY{#4+3*#2/8}
    \edef\NewRec{\noexpand\DrawFracSquare{\NewNumber}{\NewSideLength}{\NewX}{\NewY}}
    \NewRec
    \pgfmathsetmacro\NewX{#3-3*#2/8}
    \pgfmathsetmacro\NewY{#4-3*#2/8}
    \edef\NewRec{\noexpand\DrawFracSquare{\NewNumber}{\NewSideLength}{\NewX}{\NewY}}
    \NewRec
    \pgfmathsetmacro\NewX{#3+3*#2/8}
    \pgfmathsetmacro\NewY{#4-3*#2/8}
    \edef\NewRec{\noexpand\DrawFracSquare{\NewNumber}{\NewSideLength}{\NewX}{\NewY}}
    \NewRec
  \fi
}}
\begin{document}
\begin{tikzpicture}
  \DrawFracSquare{0}{3}{0}{4}
  \DrawFracSquare{1}{3}{4}{4}
  \DrawFracSquare{2}{3}{8}{4}
  \DrawFracSquare{3}{3}{0}{0}
  \DrawFracSquare{4}{3}{4}{0}
  \DrawFracSquare{5}{3}{8}{0}
\end{tikzpicture}
\end{document}

여기에 이미지 설명을 입력하세요

관련 정보