% !TeX root = ./test.tex
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% This is the TikZbricks package
% A package to draw bricks with tikz
% Maintained by samcarter
%
% Project repository and bug tracker:
%
https://github.com/samcarter/TikZbricks
%
% Released under the LaTeX Project Public License v1.3c or later
% See
https://www.latex-project.org/lppl.txt
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\ProvidesPackage{tikzbricks}[2024/12/16 version v0.6 Drawing bricks with TikZ]
\RequirePackage{tikz}
\RequirePackage{tikz-3dplot}
\RequirePackage{xkeyval}
% setting a default viewpoint
\tdplotsetmaincoords{70}{160}
% setting default values
\DeclareOptionX{color}[red]{\def\brick@default@color{#1}}
\DeclareOptionX{frontcolor}[\brick@color!60]{\def\brick@default@frontcolor{#1}}
\DeclareOptionX{topcolor}[\brick@color!40]{\def\brick@default@topcolor{#1}}
\DeclareOptionX{sidecolor}[\brick@color]{\def\brick@default@sidecolor{#1}}
\DeclareOptionX{studcolor}[\brick@color]{\def\brick@default@studcolor{#1}}
\DeclareOptionX{brickheight}[1.3]{\def\brick@default@height{#1}}
\DeclareOptionX{bricklength}[1.0]{\def\brick@default@length{#1}}
\DeclareOptionX{bricktext}[]{\def\brick@default@facetext{#1}}
\DeclareOptionX{brickwidth}[1.0]{\def\brick@default@width{#1}}
\DeclareOptionX{studradius}[0.35]{\def\brick@default@radius{#1}}
\DeclareOptionX{studheight}[0.3]{\def\brick@default@studheight{#1}}
\DeclareOptionX{studtext}[]{\def\brick@default@text{#1}}
\ExecuteOptionsX{color,frontcolor,topcolor,sidecolor,studcolor,brickheight,bricklength,bricktext,brickwidth,studradius,studheight,studtext}
\ProcessOptionsX
% counter to dermine the position of a brick in a wall
\newcounter{brickx}
\newcounter{bricky}
\newcounter{brickz}
% draw a standalone brick
% 1: optional argument
% 2: lenght
% 3: width
\newcommand*{\brick}[3][]{%
\setcounter{brickx}{0}%
\setcounter{bricky}{0}%
\setcounter{brickz}{0}%
\begin{scope}%
\tikzset{/brick/.cd,#1}%
\brick@draw{#2}{#3}%
\end{scope}%
}
% draw a brick in a wall
% 1: optional argument
% 2: lenght
% 3: width
\newcommand*{\wallbrick}[3][]{%
\begin{scope}%
\tikzset{/brick/.cd,#1}%
\brick@draw{#2}{#3}%
\end{scope}%
\addtocounter{brickx}{#2}%
}
% envrinoment to arange the bricks in a wall
% 1: optional argument passed to the tikzpicture
\newenvironment{wall}[1][]{%
\setcounter{brickx}{0}%
\setcounter{bricky}{0}%
\setcounter{brickz}{0}%
\newcommand{\newrow}{%
\setcounter{brickx}{0}%
\addtocounter{brickz}{1}%
}%
\begin{tikzpicture}[#1]
}{%
\end{tikzpicture}%
}
\tikzset{
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Pass unknown keys on to tikz
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
/brick/.search also={/tikz,/pgf},
/brick/.cd,
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% brick options
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
color/.code = \def\brick@color{#1},
color = \brick@default@color,
frontcolor/.code = \def\brick@frontcolor{#1},
frontcolor = \brick@default@frontcolor,
topcolor/.code = \def\brick@topcolor{#1},
topcolor = \brick@default@topcolor,
sidecolor/.code = \def\brick@sidecolor{#1},
sidecolor = \brick@default@sidecolor,
studcolor/.code = \def\brick@studcolor{#1},
studcolor = \brick@default@studcolor,
brickheight/.code = \def\brick@height{#1},
brickheight = \brick@default@height,
bricklength/.code = \def\brick@length{#1},
bricklength = \brick@default@length,
bricktext/.code = \def\brick@facetext{#1},
bricktext = \brick@default@facetext,
brickwidth/.code = \def\brick@width{#1},
brickwidth = \brick@default@width,
studradius/.code = \def\brick@radius{#1},
studradius = \brick@default@radius,
studheight/.code = \def\brick@studheight{#1},
studheight = \brick@default@studheight,
studtext/.code = \def\brick@text{#1},
studtext = \brick@default@text,
}
\newcommand{\brick@draw}[2]{%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% store the current scale factor
% from
https://github.com/samcarter/tikzlings/issues/3#issuecomment-461373494
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\pgfgettransformentries{\tmpscaleA}{\tmpscaleB}{\tmpscaleC}{\tmpscaleD}{\tmp}{\tmp}%
\pgfmathsetmacro{\scalingfactor}{sqrt(abs(\tmpscaleA*\tmpscaleD-\tmpscaleB*\tmpscaleC))*sqrt(abs((\pgf@xx/1cm)*(\pgf@yy/1cm)-(\pgf@xy/1cm)*(\pgf@yx/1cm)))}%
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Drawing the brick
%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{scope}[tdplot_main_coords]
% Drawing faces
\pgfmathparse{sign(sin(\tdplotmainphi))}
\let\brick@sin\pgfmathresult
\pgfmathparse{sign(cos(\tdplotmainphi))}
\let\brick@cos\pgfmathresult
\ifnum\brick@sin<0
% Right
\fill[\brick@sidecolor,thick]
(
\brick@length*\value{brickx},
\brick@width*\value{bricky},
\brick@height*\value{brickz}
)
-- ++(0,0,\brick@height)
-- ++(0,\brick@width*#2,0)
-- ++(0,0,-\brick@height)
-- cycle;
\else
% Left
\fill[\brick@sidecolor,thick]
(
{\brick@length*(#1+\value{brickx})},
\brick@width*\value{bricky},
\brick@height*\value{brickz}
)
-- ++(0,0,\brick@height)
-- ++(0,\brick@width*#2,0)
-- ++(0,0,-\brick@height)
-- cycle;
\fi
\ifnum\brick@cos<0
% Front
\fill[\brick@frontcolor,thick]
(
\brick@length*\value{brickx},
{\brick@width*(#2+\value{bricky})},
\brick@height*\value{brickz}
)
-- ++(\brick@length*#1,0,0)
-- ++(0,0,\brick@height)
-- ++(-\brick@length*#1,0,0)
-- cycle;
\node[align=center, transform shape, canvas is zx plane at y=0, rotate=-90] at (
\brick@length*\value{brickx} + 0.5*\brick@length*#1,
{\brick@width*(#2+\value{bricky})},
\brick@height*\value{brickz} + 0.5*\brick@height
) {\brick@facetext};
\else
% Back
\fill[\brick@frontcolor,thick]
(
\brick@length*\value{brickx},
\brick@width*\value{bricky},
\brick@height*\value{brickz}
)
-- ++(\brick@length*#1,0,0)
-- ++(0,0,\brick@height)
-- ++(-\brick@length*#1,0,0)
-- cycle;
\fi
% Top
\fill[\brick@topcolor,thick]
(
\brick@length*\value{brickx},
\brick@width*\value{bricky},
{\brick@height*(1+\value{brickz})}
)
-- ++(0,\brick@width*#2,0)
-- ++(\brick@length*#1,0,0)
-- +(0,-\brick@width*#2,0)
-- cycle;
% Drawing studs
\foreach \x in {1,...,#1}{
\foreach \y in {1,...,#2}{
% Bottom circle
\fill[\brick@studcolor]
(
{\brick@length*(\x-0.5+\value{brickx})},
{\brick@width*(\y-0.5+\value{bricky})},
{\brick@height*(1+\value{brickz})}
)
circle [radius=\brick@radius];
% Rectangular stem
\fill[\brick@studcolor]
(
{\brick@length*(\x-0.5+\value{brickx})},
{\brick@width*(\y-0.5+\value{bricky})},
{\brick@height*(1+\value{brickz})}
)
++(canvas cs:x=-\brick@radius/0.35*10)
-- ++(canvas cs:y=\brick@studheight*17.8)
-- ++(canvas cs:x=\brick@radius/0.35*20)
-- ++(canvas cs:y=-\brick@studheight*17.8);
% Top circle with text
\fill[\brick@topcolor]
(
{\brick@length*(\x-0.5+\value{brickx})},
{\brick@width*(\y-0.5+\value{bricky})},
{\brick@height*(1+\value{brickz})}
)
++(canvas cs:y=\brick@studheight*17.8)
circle [radius=\brick@radius]
node[\brick@color,scale=\scalingfactor*0.5, font=\sffamily] {\brick@text};
}
}
\end{scope}
}