
Tengo un proyecto que requiere muchos dibujos como el que se muestra, con pilas de rectángulos horizontales codificados por colores según su longitud (por ejemplo, todos los cuadrados son blancos, todos los rectángulos de 1 por 2 son rojos, como las varillas de Cuisenaire). Codifiqué esto de una manera muy directa usando \put y \framebox, me alegraría recibir una respuesta usando TikZ. Lo ideal sería que la entrada para una imagen como ésta no fuera mucho mayor que la lista de longitudes, es decir, {{4},{3,2},{2,3},{1,4}} y {{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}
Respuesta1
He aquí un resumen bastante breve.TikZsolución que construye los rectángulos coloreados utilizando \foreach
declaraciones anidadas para analizar una lista separada por comas de longitudes de rectángulos. Con el código debajo de las dos líneas.
\ColouredRectangles{{4},{3,2},{2,3},{1,4}} \qquad
\ColouredRectangles[ultra thick]{{1,3,1},{1,2,2},{1,1,3}}
producir los rectángulos:
La coloración de los rectángulos es un poco complicada porque se hace usando lo siguienteTikZestilos:
\tikzset{
rectangle 1/.style = {fill=white},
rectangle 2/.style = {fill=red},
rectangle 3/.style = {fill=green},
rectangle 4/.style = {fill=violet},
}
Cuando se dibuja cada rectángulo, se le asigna el color apropiado utilizando la longitud del rectángulo para establecer su estilo rectangle <length>
.
Aquí está el código completo:
\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}
Como muestra el segundo ejemplo, el \ColouredRectangles
comando acepta un argumento opcional para diseñar el tikzpicture
entorno subyacente.
Respuesta2
Con expl3
y tikz
.
Comandos
\fancyblock
recibe una matriz de 2 atenuaciones para construir bloques. El color de relleno es aleatorio de forma predeterminada (úselorandom=false
para cambiarlo) y puede configurar el estilo de trazado[<style>]
o configurar el color de relleno rápidamente con|<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
recibe una matriz de 1 atenuación para dibujar bloques aleatorios, siendo la longitud de cada fila el elemento correspondiente de la matriz.
\randomblock{4, 5, 4}
\randomrectangle
recibe dos números, que son el ancho y el alto del rectángulo que está compuesto por múltiples bloques aleatorios.
\randomrectangle{4}{7}
Código completo
\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}
Respuesta3
Basado en mi respuesta aquí:¿Puede TikZ crear imágenes pixel art?
\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}
Respuesta4
Puedes usar 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}