
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}}.
\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 \foreach
Anweisungen 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:
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, \ColouredRectangles
akzeptiert der Befehl ein optionales Argument für die Gestaltung der zugrunde liegenden tikzpicture
Umgebung.
Antwort2
Mit expl3
und tikz
.
Befehle
\fancyblock
erhält ein 2-dim-Array zum Erstellen von Blöcken. Die Füllfarbe ist standardmäßig zufällig (ändern Sierandom=false
sie 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}}
}
\randomblock
empfä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}
\randomrectangle
erhält zwei Zahlen, nämlich die Breite und Höhe des Rechtecks, das aus mehreren zufälligen Blöcken besteht.
\randomrectangle{4}{7}
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}
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}