색상이 지정된 수평 직사각형 스택을 그리는 매크로

색상이 지정된 수평 직사각형 스택을 그리는 매크로

나는 표시된 것과 같은 많은 그림이 필요한 프로젝트를 가지고 있는데, 길이에 따라 색상이 구분된 수평 직사각형의 스택이 있습니다(예: 모든 정사각형은 흰색이고 모든 1x2 직사각형은 Cuisenaire 막대처럼 빨간색입니다). 나는 이것을 \put과 \framebox를 사용하여 매우 직접적인 방법으로 코딩했습니다. TikZ를 사용하여 답변을 주시면 기쁠 것입니다. 이상적으로 이와 같은 그림에 대한 입력은 길이 목록(즉, {{4},{3,2},{2,3},{1,4}} 및 {{1, 3,1},{1,2,2},{1,1,3}}.

견본

\documentclass{article}
\usepackage{graphicx}
\usepackage{color}

\begin{document}

\begingroup
\setlength{\unitlength}{.5cm}
\begin{picture}(10,5)
\setlength{\fboxsep}{0pt}
\thicklines
\put(0,0){\colorbox{white}{\framebox(1,1){}}}  \put(1,0){\colorbox[rgb]{.75,0,1}{\framebox(4,1){}}}
\put(0,1){\colorbox{red}{\framebox(2,1){}}}  \put(2,1){\colorbox{green}{\framebox(3,1){}}}
\put(0,2){\colorbox{green}{\framebox(3,1){}}}  \put(3,2){\colorbox{red}{\framebox(2,1){}}}
\put(0,3){\colorbox[rgb]{.75,0,1}{\framebox(4,1){}}} 
\put(6,0){\colorbox{white}{\framebox(1,1){}}}  \put(7,0){\colorbox{white}{\framebox(1,1){}}}  \put(8,0){\colorbox{green}{\framebox(3,1){}}}
\put(6,1){\colorbox{white}{\framebox(1,1){}}}  \put(7,1){\colorbox{red}{\framebox(2,1){}}}  \put(9,1){\colorbox{red}{\framebox(2,1){}}}
\put(6,2){\colorbox{white}{\framebox(1,1){}}}  \put(7,2){\colorbox{green}{\framebox(3,1){}}}  \put(10,2){\colorbox{white}{\framebox(1,1){}}} 
\end{picture}
\endgroup

\end{document}

답변1

여기에는 상당히 짧은 내용이 있습니다.TikZ중첩된 문을 사용하여 색상이 지정된 사각형을 구성하여 \foreach쉼표로 구분된 사각형 길이 목록을 구문 분석하는 솔루션입니다. 두 줄 아래의 코드로

\ColouredRectangles{{4},{3,2},{2,3},{1,4}}    \qquad
\ColouredRectangles[ultra thick]{{1,3,1},{1,2,2},{1,1,3}}

직사각형을 생성합니다.

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

직사각형의 채색은 다음을 사용하여 수행되기 때문에 약간 까다롭습니다.TikZ스타일:

\tikzset{
   rectangle 1/.style = {fill=white},
   rectangle 2/.style = {fill=red},
   rectangle 3/.style = {fill=green},
   rectangle 4/.style = {fill=violet},
}

각 직사각형을 그릴 때 직사각형의 길이를 사용하여 스타일을 로 설정하여 적절한 색상이 지정됩니다 rectangle <length>.

전체 코드는 다음과 같습니다.

\documentclass{article}
\usepackage{tikz}

\tikzset{
   % the rectangle size sets the style and hence the fill
   rectangle 1/.style = {fill=white},
   rectangle 2/.style = {fill=red},
   rectangle 3/.style = {fill=green},
   rectangle 4/.style = {fill=violet},
}

\newcommand\ColouredRectangles[2][]{%
  \begin{tikzpicture}[#1]
    \foreach \row [count=\rc] in {#2} {% loop through rows
      \xdef\offset{0} % need to remember how far we have drawn so far
      \foreach \col in \row {% loop through columns
         \draw[rectangle \col] (\offset,-\rc) rectangle ++ (\col, -1);
         \xdef\offset{\numexpr\offset+\col\relax}
      }
    }
  \end{tikzpicture}%
}

\begin{document}

    \ColouredRectangles{{4},{3,2},{2,3},{1,4}}    \qquad
    \ColouredRectangles[ultra thick]{{1,3,1},{1,2,2},{1,1,3}}

\end{document}

두 번째 예에서 볼 수 있듯이 \ColouredRectangles명령은 기본 tikzpicture환경의 스타일 지정을 위한 선택적 인수를 허용합니다.

답변2

와 .expl3tikz

명령

  • \fancyblock블록을 구성하기 위해 2차원 배열을 받습니다. 채우기 색상은 기본적으로 무작위이며( random=false변경하려면 사용) 를 사용하여 패스 스타일을 설정 [<style>]하거나 을 사용하여 채우기 색상을 빠르게 설정할 수 있습니다 |<color>|.
\fancyblock[
  at={(8, 0)}, name=b, random=false,
  transpose, y=0.5cm,
  block={
    very thick,
    line width=1pt,
    draw=teal,
  }
]{
  {2, 1, 1},
  {1, [fill=red]2, |green|1},
  {1, 3, {[line width=2pt, draw=black]|teal|1}}
}
  • \randomblock임의의 블록을 그리기 위해 1차원 배열을 수신하며, 모든 행의 길이는 배열의 해당 요소가 됩니다.
\randomblock{4, 5, 4}
  • \randomrectangle여러 개의 무작위 블록으로 구성된 직사각형의 너비와 높이인 두 개의 숫자를 받습니다.
\randomrectangle{4}{7}

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

완전한 코드

\documentclass[tikz, border=1cm]{standalone}
\usepackage{xparse}

\ExplSyntaxOn
\makeatletter

\tl_new:N   \l__at_tl
\tl_new:N   \l__name_tl
\tl_new:N   \l__anchor_tl
\tl_new:N   \l__block_style_tl
\dim_new:N  \l__block_wd_dim
\dim_new:N  \l__x_coor_dim
\dim_new:N  \l__y_coor_dim
\dim_new:N  \l__block_x_unit_dim
\dim_new:N  \l__block_y_unit_dim
\int_new:N  \l__remain_int
\int_new:N  \l__temp_int
\bool_new:N \l__random_bool
\bool_new:N \l__transpose_bool

\keys_define:nn { fancyblock }
  {
    at          . tl_set:N   = \l__at_tl,
    name        . tl_set:N   = \l__name_tl,
    random      . bool_set:N = \l__random_bool,
    random      . default:n  = true,
    transpose   . bool_set:N = \l__transpose_bool,
    transpose   . default:n  = true,
    x           . dim_set:N  = \l__block_x_unit_dim,
    y           . dim_set:N  = \l__block_y_unit_dim,
    unit        . code:n     =
      {
        \dim_set:Nn \l__block_x_unit_dim { #1 }
        \dim_set:Nn \l__block_y_unit_dim { #1 }
      },
    block       . code:n     =
      {
        \tl_put_right:Nn \l__block_style_tl { ,#1 }
      },
    anchor      . choice:,
    anchor / l  . code:n     = { \tl_set:Nn \l__anchor_tl { west } },
    anchor / r  . code:n     = { \tl_set:Nn \l__anchor_tl { east } },
    anchor / t  . code:n     = { \tl_set:Nn \l__anchor_tl { north } },
    anchor / b  . code:n     = { \tl_set:Nn \l__anchor_tl { south } },
    anchor / lb . code:n     = { \tl_set:Nn \l__anchor_tl { south~west } },
    anchor / bl . code:n     = { \tl_set:Nn \l__anchor_tl { south~west } },
    anchor / lt . code:n     = { \tl_set:Nn \l__anchor_tl { north~west } },
    anchor / tl . code:n     = { \tl_set:Nn \l__anchor_tl { north~west } },
    anchor / rb . code:n     = { \tl_set:Nn \l__anchor_tl { south~east } },
    anchor / br . code:n     = { \tl_set:Nn \l__anchor_tl { south~east } },
    anchor / rt . code:n     = { \tl_set:Nn \l__anchor_tl { north~east } },
    anchor / tr . code:n     = { \tl_set:Nn \l__anchor_tl { north~east } },
  }

\NewDocumentCommand { \randomblock } { O{} m }
  {
    \generate_num_matrix:n { #2 }
    \fancyblock[#1]{\clist_use:Nn \l__matrix_clist {,}}
  }

\NewDocumentCommand { \randomrectangle } { O{} m m }
  {
    \seq_clear:N \l_tmpa_seq
    \int_step_inline:nn { #2 }
      {
        \seq_put_right:Nn \l_tmpa_seq { #3 }
      }
    \generate_num_matrix:x
      {
        \seq_use:Nn \l_tmpa_seq { , }
      }
    \fancyblock[#1]{\clist_use:Nn \l__matrix_clist {,}}
  }

\cs_new_protected:Nn \generate_num_matrix:n
  {
    \clist_clear_new:N \l__matrix_clist
    \clist_map_inline:nn { #1 }
      {
        \generate_num_seq:n { ##1 }
        \clist_put_right:Nx \l__matrix_clist
          {
            { { \clist_use:Nn \l__row_clist {,} } }
          }
      }
  }
\cs_generate_variant:Nn \generate_num_matrix:n { x }

\cs_new_protected:Nn \generate_num_seq:n
  {
    \clist_clear_new:N \l__row_clist
    \int_set:Nn \l__remain_int { #1 }
    \int_while_do:nn { \l__remain_int > 0 }
      {
        \int_set:Nn \l__temp_int {
          \int_rand:n { \l__remain_int }
        }
        \int_add:Nn \l__remain_int { -\l__temp_int }
        \clist_put_right:Nx \l__row_clist { \int_use:N \l__temp_int }
      }
  }

\NewDocumentCommand { \fancyblock } { O{} m }
  {
    \tl_clear:N \l__block_style_tl
    \keys_set:nn { fancyblock }
      {
        at        = { (0, 0) },
        block     = { draw, thick },
        unit      = 1cm,
        transpose = false,
        anchor    = lb,
        name      = block,
        random,
        #1
      }
    \draw_block_matrix:x { #2 }
  }

\cs_new_protected:Nn \draw_block_matrix:n
  {
    \clist_set:Nn \l_tmpa_clist { #1 }
    \bool_if:NTF \l__transpose_bool
      {
        \dim_zero:N \l__x_coor_dim
      }
      {
        \dim_zero:N \l__y_coor_dim
        \clist_reverse:N \l_tmpa_clist
      }
    \matrix [anchor=\l__anchor_tl] (\l__name_tl) at \l__at_tl {
      \clist_map_inline:Nn \l_tmpa_clist
        {
          \draw_row:n { ##1 }
          \bool_if:NTF \l__transpose_bool
            {
              \dim_add:Nn \l__x_coor_dim { \l__block_x_unit_dim }
            }
            {
              \dim_add:Nn \l__y_coor_dim { \l__block_y_unit_dim }
            }
        }\\
    };
  }
\cs_generate_variant:Nn \draw_block_matrix:n { x, v, f }

\cs_new_protected:Nn \draw_row:n
  {
    \bool_if:NTF \l__transpose_bool
      {
        \dim_zero:N \l__y_coor_dim
      }
      {
        \dim_zero:N \l__x_coor_dim
      }
    \clist_map_inline:nn { #1 }
      {
        \draw_block:n { ##1 }
      }
  }

\cs_new_protected:Nn \draw_block:n
  {
    \tl_clear_new:N \l__draw_block_tl
    \parse_args:n { #1 }
    \definecolor{random}{RGB}{
      \int_rand:n { 255 },
      \int_rand:n { 255 },
      \int_rand:n { 255 }
    }
    \tl_set:Nx \l_tmpb_tl
      {
        \bool_if:NTF \l__random_bool
          { fill=random }
          { }
      }
    \tl_set:Nx \l__draw_block_tl
      {
        \exp_not:N \path[
          \l__block_style_tl,
          \l_tmpb_tl,
          \seq_use:Nn \l__block_style_seq { , }]
          (\dim_use:N \l__x_coor_dim, \dim_use:N \l__y_coor_dim) --
        \bool_if:NTF \l__transpose_bool
          {
              ++(0, \dim_use:N \l__block_wd_dim) --
              ++(\dim_use:N \l__block_x_unit_dim, 0) --
              ++(0, \dim_eval:n { -\l__block_wd_dim }) -- cycle;
          }
          {
              ++(\dim_use:N \l__block_wd_dim, 0) --
              ++(0, \dim_use:N \l__block_y_unit_dim) --
              ++(\dim_eval:n { -\l__block_wd_dim }, 0) -- cycle;
          }
      }
    \tl_use:N \l__draw_block_tl
    \bool_if:NTF \l__transpose_bool
      {
        \dim_add:Nn \l__y_coor_dim { \l__block_wd_dim }
      }
      {
        \dim_add:Nn \l__x_coor_dim { \l__block_wd_dim }
      }
  }

\cs_new_protected:Nn \parse_args:n
  {
    \seq_clear_new:N \l__block_style_seq
    \fp_set:Nn \l__block_wd_fp { 1 }
    \parse_next_arg: #1\stop
  }

\cs_new_protected:Nn \parse_next_arg:
  {
    \peek_meaning_ignore_spaces:NTF [
      { \parse_style:w }
      {
        \peek_meaning_ignore_spaces:NTF |
          { \parse_fill:w }
          { \parse_len:w }
      }
  }

\cs_new_protected:Npn \parse_style:w [#1]
  {
    \seq_put_right:Nn \l__block_style_seq { #1 }
    \parse_next_arg:
  }

\cs_new_protected:Npn \parse_fill:w |#1|
  {
    \seq_put_right:Nn \l__block_style_seq { fill=#1 }
    \parse_next_arg:
  }

\cs_new_protected:Npn \parse_len:w #1\stop
  {
    \tikz@checkunit{#1}
    \legacy_if:nTF { tikz@isdimension }
      { \dim_set:Nn \l__block_wd_dim { #1 } }
      {
        \bool_if:NTF \l__transpose_bool
          {
            \dim_set:Nn \l__block_wd_dim { \l__block_y_unit_dim * #1 }
          }
          {
            \dim_set:Nn \l__block_wd_dim { \l__block_x_unit_dim * #1 }
          }
      }
  }

\makeatother
\ExplSyntaxOff

\begin{document}
\begin{tikzpicture}
\fancyblock[name=a]{
  {2, 2, 1},
  {1, 2, 1},
  {3, 1, 1}
}
\path (a.south) node [below] {\verb|\fancyblock|};

\fancyblock[
  at={(8, 0)}, name=b, random=false,
  transpose, y=0.5cm,
  block={
    very thick,
    line width=1pt,
    draw=teal,
  }
]{
  {2, 1, 1},
  {1, [fill=red]2, |green|1},
  {1, 3, {[line width=2pt, draw=black]|teal|1}}
}
\path (b.south) node [below] {\verb|\fancyblock| with options};

\randomblock[at={([yshift=1cm]a.north west)}, name=c]{4, 5, 4}
\path (c.south) node [below] {\verb|\randomblock|};

\randomrectangle[at={(c.south -| b.center)}, name=d, anchor=b]{4}{7}
\path (d.south) node [below] {\verb|\randomrectangle|};

\end{tikzpicture}
\end{document}

답변3

내 대답을 바탕으로 :TikZ가 픽셀 아트 이미지를 만들 수 있나요?

\documentclass{article}
\usepackage{xcolor}
\usepackage{stackengine}
\newlength\blocksize
\setlength\blocksize{1ex}
\newcommand\block[2]{\kern-\fboxrule\fboxsep=0pt%
  \fbox{\color{#1}\rule{%
    \dimexpr#2\blocksize+\numexpr#2-1\relax\fboxrule\relax}{\blocksize}}}
\newcommand\gr[1][1]{\block{green}{#1}}
\newcommand\rd[1][1]{\block{red}{#1}}
\newcommand\bl[1][1]{\block{blue}{#1}}
\newcommand\wh[1][1]{\block{white}{#1}}
\setstackgap{S}{-\fboxrule}
\begin{document}
\Shortstack[l]{
\rd\gr[2]\gr\rd[3]\\
\gr\bl[3]\gr\gr\\
\gr\bl\rd[2]\wh\wh\gr}
\end{document} 

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

답변4

당신이 사용할 수있는 pic.

\documentclass[tikz,margin=3mm]{standalone}
\usepackage{color}

\tikzset{
    pics/cube/.style args={#1-#2}{
      code = {
    \draw [black,fill=#2](0,0)--(#1,0)--(#1,1)--(0,1)--cycle;  
      }
      }
      }

\begin{document}

\begin{tikzpicture}
\pic at (0,0) {cube=1-white};
\pic at (1,0) {cube=1-white};
\pic at (2,0) {cube=3-green};
\pic at (0,1) {cube=1-white};
\pic at (1,1) {cube=2-red};
\pic at (3,1) {cube=2-red};
\pic at (0,2) {cube=1-white};
\pic at (1,2) {cube=3-green};
\pic at (4,2) {cube=1-white};
\end{tikzpicture}

\end{document}

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

관련 정보