我有一些代码可以根据用户输入的二进制矩阵自动绘制多边形网格(由边到边连接的正方形构成的形状)。二进制矩阵用于多边形的边界矩形,其中 1 表示多边形的填充正方形,而 0 表示空正方形(即不属于多边形的正方形)。我想用比网格线更粗的线绘制多边形的边界。理想情况下,我希望网格线和边界线的线粗度都是可调的(网格线宽度已经是可调的)。请参阅下面的代码和相应的图。
\documentclass{article}
\usepackage{tikz}
\usepackage{xcolor}
\newcommand{\drawPolyomino}[3]{
\begin{tikzpicture}[scale=#2]
% Draw the squares
\foreach[count=\jR from 0] \row in {#1} {
\pgfmathtruncatemacro\j{abs(\jR - 3)}
\foreach[count=\i from 0] \cell in \row {
\ifnum\cell=1
\draw[#3] (\i, \j) rectangle ++(1,1);
\fi
}
}
\end{tikzpicture}
}
\begin{document}
\begin{figure}
\centering
\drawPolyomino{{0,1,0,0,0},{1,1,1,1,0},{0,0,1,1,1},{0,0,0,1,0}}{1.0}{thin}
% Input the polyomino, followed by arguments for scale and line width respectively.
\caption{A polyomino constructed from an input binary matrix.}
\end{figure}
\end{document}
答案1
存储您提供的矩阵使得稍后在循环中检索它们变得更加容易。(现在它基本上是一个二维数组。)
这样,就可以检查每个绘制的矩形周围是否有另一个矩形,如果没有(或者数组基本上超出范围→检查\relax
),则绘制边框段。(这也意味着存储该矩阵,即使用键store matrix
,应该始终在不使用其他键的范围内进行store matrix
。否则\relax
作弊将不再有效。)
这不会构造封闭路径。将整个构造放在一条路径上使我们能够填充/阴影整个形状,而无需实际使用轮廓。这也有助于将 s 放在edge
形状的顶部。
这使用与在另一个答案中它可能对行和列的解释与您不同 (?)。在某个时候我有点困惑,但polyomino/picture
其密钥yscale=-1
似乎已经解决了这个问题。
代码
\documentclass[tikz]{standalone}
\tikzset{
polyomino/rect/.style={thin},
polyomino/border/.style={very thick, line cap=rect},
polyomino/picture/.style={yscale=-1},
polyomino/.code=\pgfqkeys{/tikz/polyomino}{#1},
store matrix/.style={
/utils/exec=\def\listrow{0},
/utils/rows/.style={
/utils/exec=\def\listcol{0}%
\edef\listrow{\the\numexpr\listrow+1\relax},
/utils/cols/.estyle={
/utils/exec=\edef\noexpand\listcol{\noexpand\the\numexpr\noexpand\listcol+1\relax},
/tikz/matrix/storage \listrow-\noexpand\listcol/.initial={####1}
},
/utils/cols/.list={##1},
},
/utils/rows/.list={#1}
},
matrix check/.code args={#1:#2=#3}{%
\pgfkeysgetvalue{/tikz/matrix/storage \pgfinteval{#1}-\pgfinteval{#2}}{#3}%
\ifx#3\relax \def#3{0}\fi},
}
\newcommand{\drawPolyomino}[2][]{
\begin{tikzpicture}[store matrix={#2},polyomino/picture,polyomino={#1}]
% Draw the squares
\draw[polyomino/rect] foreach \col in {1,...,\listcol}{
foreach \row in {1,...,\listrow}{
[matrix check/.list={\row:\col=\cell,
\row:\col-1=\cellPrev,
\row:\col+1=\cellNext,
\row+1:\col=\cellAbove,
\row-1:\col=\cellBelow}]
\ifnum\cell=1
(\col , \row ) rectangle +(1,1)
\ifnum\cellPrev=0 (\col , \row ) edge[polyomino/border] +(up:1) \fi
\ifnum\cellAbove=0 (\col , \row+1) edge[polyomino/border] +(right:1)\fi
\ifnum\cellBelow=0 (\col , \row ) edge[polyomino/border] +(right:1)\fi
\ifnum\cellNext=0 (\col+1, \row ) edge[polyomino/border] +(up:1) \fi
\fi
}};
\end{tikzpicture}}
\begin{document}
\drawPolyomino{
{0,1,0,0,0},
{1,1,1,1,0},
{0,0,1,1,1},
{0,0,0,1,0}
}
\drawPolyomino[
rect/.append style={draw=none, top color=green!50, bottom color=blue!50},
border/.append style={ultra thick, draw=red, dash=on 3mm off 4mm phase 0mm}]{
{0,1,0,0,0},
{1,1,1,1,0},
{0,0,1,1,1},
{0,0,0,1,0}
}
\end{document}
输出
答案2
您可以绘制两次并使用 [fill=white] 擦除内部的粗边框。请注意,线条以边缘为中心,因此填充时您将损失近一半的外部厚度。
\documentclass{article}
\usepackage{xcolor}
\usepackage{tikz}
\newcommand{\drawPolyomino}[2]{% #1=binary array, #2=scale
\begin{tikzpicture}[scale=#2]
% Draw the squares
\foreach[count=\jR from 0] \row in {#1} {
\pgfmathtruncatemacro\j{abs(\jR - 3)}
\foreach[count=\i from 0] \cell in \row {
\ifnum\cell=1
\draw[very thick] (\i, \j) rectangle ++(1,1);
\fi
}
}
\foreach[count=\jR from 0] \row in {#1} {
\pgfmathtruncatemacro\j{abs(\jR - 3)}
\foreach[count=\i from 0] \cell in \row {
\ifnum\cell=1
\draw[thin, fill=white] (\i, \j) rectangle ++(1,1);
\fi
}
}
\end{tikzpicture}%
}
\begin{document}
\begin{figure}
\centering
\drawPolyomino{{0,1,0,0,0},{1,1,1,1,0},{0,0,1,1,1},{0,0,0,1,0}}{1.0}
% Input the polyomino, followed by arguments for scale
\caption{A polyomino constructed from an input binary matrix.}
\end{figure}
\end{document}