Makro zum Zeichnen von Stapeln farbiger horizontaler Rechtecke

Makro zum Zeichnen von Stapeln farbiger horizontaler Rechtecke

Ich habe ein Projekt, das viele Zeichnungen wie die gezeigte erfordert, mit Stapeln horizontaler Rechtecke, die nach Länge farbcodiert sind (z. B. sind alle Quadrate weiß, alle 1 x 2 Rechtecke sind rot, wie Cuisenaire-Stäbe). Ich habe dies auf sehr direkte Weise mit \put und \framebox codiert und würde mich über eine Antwort mit TikZ freuen. Idealerweise wäre die Eingabe für ein Bild wie dieses nicht viel mehr als die Liste der Längen, d. h. {{4},{3,2},{2,3},{1,4}} und {{1,3,1},{1,2,2},{1,1,3}}.

Probe

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

Antwort1

Hier ist eine ziemlich kurzeTikZLösung, die die farbigen Rechtecke mithilfe verschachtelter \foreachAnweisungen erstellt, um eine durch Kommas getrennte Liste von Rechtecklängen zu analysieren. Mit dem Code unter den beiden Zeilen

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

Erzeugen Sie die Rechtecke:

Bildbeschreibung hier eingeben

Die Einfärbung der Rechtecke ist ein wenig raffiniert, denn sie erfolgt mit folgendemTikZStile:

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

Beim Zeichnen wird jedem Rechteck die entsprechende Farbe zugewiesen. Der Stil wird über die Länge des Rechtecks ​​festgelegt rectangle <length>.

Hier ist der vollständige Code:

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

Wie das zweite Beispiel zeigt, \ColouredRectanglesakzeptiert der Befehl ein optionales Argument für die Gestaltung der zugrunde liegenden tikzpictureUmgebung.

Antwort2

Mit expl3und tikz.

Befehle

  • \fancyblockerhält ein 2-dim-Array zum Erstellen von Blöcken. Die Füllfarbe ist standardmäßig zufällig (ändern Sie random=falsesie mit ), und Sie können den Pfadstil mit festlegen [<style>]oder die Füllfarbe schnell mit einstellen |<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}}
}
  • \randomblockempfängt ein 1-dim-Array zum Zeichnen von zufälligen Blöcken, wobei die Länge jeder Zeile dem entsprechenden Element des Arrays entspricht.
\randomblock{4, 5, 4}
  • \randomrectangleerhält zwei Zahlen, nämlich die Breite und Höhe des Rechtecks, das aus mehreren zufälligen Blöcken besteht.
\randomrectangle{4}{7}

Bildbeschreibung hier eingeben

Vollständiger Code

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

Antwort3

Basierend auf meiner Antwort hier:Kann TikZ Pixelkunstbilder erstellen?

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

Bildbeschreibung hier eingeben

Antwort4

Sie können verwenden 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}

Bildbeschreibung hier eingeben

verwandte Informationen