2

How to draw a hierarchical matrix pattern like this one (using TikZ or not)? And how to add a little square matrix between the product between the two retangular matrices?

Is it possible to create a building block that could be reused in the next levels of the hierarchical structure without repeating the same code?

enter image description here

I think the building block could be something like that:

\documentclass[border=3mm]{standalone}
\usepackage{tikz}

\begin{document} \begin{tikzpicture}[baseline={(0, 1.75cm)}] \draw (0,0) rectangle (4,4); \filldraw [ fill={gray} ] (0,2) rectangle (2,4); \filldraw [ fill={gray} ] (2,0) rectangle (4,2);

\filldraw [ fill={gray} ] (0.1,1) rectangle (0.4,1.8);
\filldraw [ fill={gray} ] (0.5,1.5) rectangle (0.8,1.8);
\filldraw [ fill={gray} ] (0.9,1.5) rectangle (1.7,1.8);

\filldraw [ fill={gray} ] (2.1,3) rectangle (2.4,3.8);
\filldraw [ fill={gray} ] (2.5,3.5) rectangle (2.8,3.8);
\filldraw [ fill={gray} ] (2.9,3.5) rectangle (3.7,3.8);

\end{tikzpicture}} \end{document]

MS-SPO
  • 11,519

2 Answers2

4

Description

  • defined pics for the two rectangles (rectangles) and for the square (x0)
  • further pics xi are defined recursively with \defxi
  • the scale is used as a parameter for the recursion

Code

\documentclass[border=3mm]{standalone}

\usepackage{tikz}

\tikzset{ x0/.pic={ \draw[fill={gray}] (0,0) rectangle (1,1); }, rectangles/.pic={ \draw[fill={gray}] (0.1,0.8) rectangle (.3,.2); \draw[fill={gray}] (0.4,0.8) rectangle (.9,.6); }, every pic/.style={transform shape}, }

\newcommand{\defxi}[1]{ \tikzset{ x#1/.pic={ \draw[scale=##1] (0,0) rectangle (1,1); \pic[scale=.5*##1] at (0,.5) {x\the\numexpr#1-1\relax=##1}; \pic[scale=.5*##1] at (.5,0) {x\the\numexpr#1-1\relax=##1}; \pic[scale=.5*##1] at (0,0) {rectangles}; \pic[scale=.5*##1] at (.5,.5) {rectangles}; } } }

\defxi{1} \defxi{2} \defxi{3} \defxi{4}

\begin{document} \begin{tikzpicture} \foreach \i in {0, ..., 4} { \pic at (\i*1.2,0) {x\i=1}; } \end{tikzpicture} \end{document}

Result

enter image description here

dexteritas
  • 9,161
1

I've adapted my recursion code from this polygon related answer. I've removed the whole spiel about drawDist and shiftDist because they make things more complicated than they have to be.

The line width of the two rectangles gets halfed with each deeper level. This is done by

line width=.4pt/2^(\pgfkeysvalueof{/tikz/flakes/level'}-1)

where /tikz/flakes/level' is basically a counter that counts up the deeper we are (whereas level counts down). The default line width thin is 0.4pt which is what I've used here as a starting line width.

Code

\documentclass[tikz]{standalone}
\usepgfkeyslibrary{ext.pgfkeys-plus}
\makeatletter
\pgfqkeys{/handlers}{
  .foreach/.code={\let\pgfkeys@exp@call@\pgfkeys@exp@call
    \foreach\pgf@keys@temp in{#1}{\expandafter\pgfkeys@exp@call@\expandafter{\pgf@keys@temp}}}}
\makeatother
\newcommand*\flakesset{\pgfqkeys{/tikz/flakes}}
\newcommand*\flakescreate[1][]{\begingroup\flakesset{#1,start}\endgroup}
\flakesset{% adapted from https://tex.stackexchange.com/a/685124
  .code=\flakesset{#1}, tikz/.code=\tikzset{#1},
  level/.initial=0, level'/.initial=0, item/.initial=0,
  start item/.initial=0, end item/.initial=3,
  item list/.initial={\pgfkeysvalueof{/tikz/flakes/start item},...,\pgfkeysvalueof{/tikz/flakes/end item}},
  start/.style={level'=0, item=0, tikz=flakes/at start/.try, __do=0},
  __do/.style={
    /utils/TeX/ifnum={\pgfkeysvalueof{/tikz/flakes/level}=0}{__place={#1}}{
      level/.--, level'/.++, before split={#1},
      __split/.foreach/.expanded={\pgfkeysvalueof{/tikz/flakes/item list}}}},
  __split/.code={%
    \pgfkeyssetevalue{/tikz/flakes/item}{#1}%
    \tikzset{flakes/before do={#1}}%
    \flakesset{__do={#1}}%
    \tikzset{flakes/after do/.try={#1}}},
  __place/.code={\path[flakes/styling={#1}](0,0)to[flakes/path={#1}](0,0);},
  before split/.style={
    level \pgfkeysvalueof{/tikz/flakes/level}/.try={#1},
    level \pgfkeysvalueof{/tikz/flakes/level'}'/.try={#1}}}

%% Here starts your definitions \flakesset{ hiermatrix/.style={ /tikz/my test/.style n args={3}{/utils/TeX/if=##1{##2}{##3}}, before do/.style 2 args={ shift={(##1.5,##2.5)}, scale=.5, my test={##1##2}{% if ++ or -- place the drawing and stop recursions /tikz/flakes/__place={##1##2}, /tikz/flakes/__do/.code=}{}}, styling/.style={ my flakes, my test={##1}{line width=.4pt/2^(\pgfkeysvalueof{/tikz/flakes/level'}-1)}{}}, item list={++, -+, --, +-}, path/.style={ my test={##1}{% if ++ or -- draw two rectangles with border to path={ (-1,-1) edge[to path=rectangle(\tikztotarget),thin,path only,draw] (1,1) (-.75, -.5) rectangle ++(.25, 1.125) ++(right:.2) rectangle +(1, -.25)}, }{% otherwise just a rectangle to path={(-1, -1) rectangle (1, 1)}}}}} \begin{document} \tikz[my flakes/.style={draw=black, fill=lightgray}] \matrix[ column sep=5mm, nodes={node font=\bfseries\sffamily, node contents=(\pgfkeysvalueof{/tikz/flakes/level})}, cells={flakes/level/.expanded=\inteval{\pgfmatrixcurrentcolumn-1}} ]{ \path[my flakes] (-1,-1) rectangle (1,1); & \flakescreate[hiermatrix] & \flakescreate[hiermatrix] & \flakescreate[hiermatrix] \ \node[]; & \node[]; & \node[]; & \node[];\}; \end{document}

Output

enter image description here

Qrrbrbirlbel
  • 119,821