作为一门课程的助教,我正在尝试为教授绘制座位表。座位表上将包含每个学生的照片、学生姓名以及学生在教室中的座位位置。我需要制作两个座位表:
- 空白座位表,其中的矩形代表每把椅子,供学生在座位上填写自己的名字。
- 标有学生姓名和照片的座位表。
在尝试绘制演讲厅 80 多个座位的座位表之前,我正在研究一个有 11 个座位的较小示例。目前,我用来绘制空白座位表的代码和输出如下所示:
\documentclass[10pt]{article}
\usepackage[margin=0in,paperwidth=17in, paperheight=11in]{geometry}
\usepackage{tikz}
% Usage: \student{x coord}{y coord}{name}{picture file}
%\newcommand{\student}[4]{%
% \node[anchor=base,inner sep=0,
% label={[text width=20mm,align=center]below:#3}] at (#1,#2)
% {\includegraphics[width=17mm]{#4}};%
%}
% Draw an empty box for each chair
\newcommand{\student}[4]{
\node[anchor=base,shape=rectangle,draw,
minimum width=17mm,minimum height=22mm]
at (#1,#2) {};
}
\begin{document}
\begin{center}
\begin{tikzpicture}
\draw[white] (0,0) -- (43.1,0) -- (43.1,27.9) -- (0,27.9) -- (0,0);
\draw (5,5) -- (10,15);
\draw (12,18) -- (31,18);
\draw (38,5) -- (33,15);
\student{4}{7}{George Washington}{empty-face.png};
\student{5.5}{10}{John Adams}{empty-face.png};
\student{7}{13}{Thomas Jefferson}{empty-face.png};
\student{12.5}{20}{James Madison}{empty-face.png};
\student{17}{20}{James Monroe}{empty-face.png};
\student{21.5}{20}{John Quincy Adams}{empty-face.png};
\student{26}{20}{Andrew Jackson}{empty-face.png};
\student{30.5}{20}{Martin Van Buren}{empty-face.png};
\student{36}{13}{William Henry Harrison}{empty-face.png};
\student{37.5}{10}{John Tyler}{empty-face.png};
\student{39}{7}{James K Polk}{empty-face.png};
\end{tikzpicture}
\end{center}
\end{document}
带有姓名和照片的座位表的代码非常相似:
\documentclass[10pt]{article}
\usepackage[margin=0in,paperwidth=17in, paperheight=11in]{geometry}
\usepackage{tikz}
% Usage: \student{x coord}{y coord}{name}{picture file}
\newcommand{\student}[4]{%
\node[anchor=base,inner sep=0,
label={[text width=20mm,align=center]below:#3}] at (#1,#2)
{\includegraphics[width=17mm]{#4}};%
}
\begin{document}
\begin{center}
\begin{tikzpicture}
\draw[white] (0,0) -- (43.1,0) -- (43.1,27.9) -- (0,27.9) -- (0,0);
\draw[line width=5mm] (5,5) -- (10,15);
\draw[line width=5mm] (12,18) -- (31,18);
\draw[line width=5mm] (38,5) -- (33,15);
\student{4}{7}{George Washington}{empty-face.png};
\student{5.5}{10}{John Adams}{empty-face.png};
\student{7}{13}{Thomas Jefferson}{empty-face.png};
\student{12.5}{20}{James Madison}{empty-face.png};
\student{17}{20}{James Monroe}{empty-face.png};
\student{21.5}{20}{John Quincy Adams}{empty-face.png};
\student{26}{20}{Andrew Jackson}{empty-face.png};
\student{30.5}{20}{Martin Van Buren}{empty-face.png};
\student{36}{13}{William Henry Harrison}{empty-face.png};
\student{37.5}{10}{John Tyler}{empty-face.png};
\student{39}{7}{James K Polk}{empty-face.png};
\end{tikzpicture}
\end{center}
\end{document}
在我之前的帖子中:在 TikZ 的新命令中对齐图像和文本,Peter Grill 建议使用\foreach
循环来绘制多个学生的图表。这是一个好主意!不幸的是,教室里的座位并不规则。事实上,桌子后面有大约 80 个座位,如下图所示:
我的问题如下。
我想要做的是定义一个位置列表:
\newcommand{\ListOfSeats}{
(4,7) (5.5,10) (7,13) (12.5,20) (17,20)
(21.5,20) (26,20) (30.5,20) (36,13) (37.5,10) (39,7)
}
以及学生姓名和照片列表
\newcommand{\ListOfStudents}{
(George Washington, george-washington.jpg)
(John Adams, john-adams.jpg)
(Thomas Jefferson, thomas-jefferson.jpg)
...
}
有没有办法使用单个\foreach
循环绘制所有 80 个座位以及所有 80 名学生的姓名和照片?
感谢您读到最后,这是一个很长的问题,但我希望您觉得它很有趣!
答案1
易于编码
正如我的评论所述,最简单的解决方案编码将是一个列表、一个 foreach 和四个由 分隔的变量/
。
不要在第二部分(包含文件名的部分)中引入任何空格。
如果名称或文件名包含括号,
中的整个变量{ }
,例如
{Sir, St. Comma}/{sir,-st.-comma.jpg}/0/0
代码
\documentclass[10pt]{article}
\usepackage[margin=0in,paperwidth=17in, paperheight=11in]{geometry}
\usepackage{tikz}
% Usage: \student{x coord}{y coord}{name}{picture file}
\newcommand{\student}[4]{%
\node[anchor=base,inner sep=0,
label={[text width=20mm,align=center]below:#3}] at (#1,#2)
{\includegraphics[width=17mm]{#4}};%
}
\newcommand*{\ListOfStudents}{%
George Washington /example-image-10x16.jpg/ 4 / 7,
John Adams /example-image-10x16.jpg/ 5.5/10,
Thomas Jefferson /example-image-10x16.jpg/ 7 /13,
James Madison /example-image-10x16.jpg/12.5/20,
James Monroe /example-image-10x16.jpg/17 /20,
John Quincy Adams /example-image-10x16.jpg/21.5/20,
Andrew Jackson /example-image-10x16.jpg/26 /20,
Martin Van Buren /example-image-10x16.jpg/30.5/20,
William Henry Harrison/example-image-10x16.jpg/36 /13,
John Tyler /example-image-10x16.jpg/37.5/10,
James K Polk /example-image-10x16.jpg/39 / 7}
\begin{document}
\noindent
\begin{tikzpicture}
\useasboundingbox (0,0) rectangle (17in,11in);% see http://tex.stackexchange.com/a/98532/16595
\draw[line width=5mm] (5,5) -- (10,15);
\draw[line width=5mm] (12,18) -- (31,18);
\draw[line width=5mm] (38,5) -- (33,15);
\foreach \sName/\sFile/\sX/\sY in \ListOfStudents {\student{\sX}{\sY}{\sName}{\sFile}}
\end{tikzpicture}
\end{document}
输出
更先进
如果您想要单独的列表,我们可以使用嵌套\foreach
循环和两个可以比较的计数器来找到正确的对(如果它们相等,我们就有正确的(文件)名称和坐标对)。
如果没有给出文件名,则通过小写名称和用破折号 ( ) 替换的空格来构造-
。xstring
包用于替换部分。
.jpg
我还添加了一个选项,如果给出了文件名,则会自动添加扩展名(尽管 TeX/graphicx
有自己的规则来处理没有扩展名的文件名)。
请注意,由于文件不可用,以下代码会引发错误和警告(但我们有一种简单的方法来检查传出的文件名)。
代码
\documentclass[10pt]{article}
\usepackage[margin=0in,paperwidth=17in, paperheight=11in]{geometry}
\usepackage{xstring}
\usepackage{tikz}
% Usage: \student{x coord}{y coord}{name}{picture file}
\newcommand{\student}[4]{%
\node[anchor=base,inner sep=0,
label={[text width=20mm,align=center]below:#3}] at (#1,#2)
{\includegraphics[width=17mm]{#4}};%
}
\newcommand{\ListOfSeats}{%
4/7, 5.5/10, 7/13, 12.5/20, 17/20, 21.5/20, 26/20, 30.5/20, 36/13, 37.5/10, 39/7}
\newcommand*{\ListOfStudents}{%
George Washington,
John Adams,
Thomas Jefferson,
James Madison,
James Monroe/different-filename,
John Quincy Adams,
Andrew Jackson,
Martin Van Buren,
William Henry Harrison/wh-harrison,
John Tyler,
James K Polk}
\begin{document}
\noindent
\begin{tikzpicture}
\useasboundingbox (0,0) rectangle (17in,11in);% see http://tex.stackexchange.com/a/98532/16595
\draw[line width=5mm] (5,5) -- (10,15);
\draw[line width=5mm] (12,18) -- (31,18);
\draw[line width=5mm] (38,5) -- (33,15);
\foreach \sName/\sFile[count=\iOuter from 0] in \ListOfStudents {
\foreach \sX/\sY[count=\iInner from 0] in \ListOfSeats {
\ifnum\iOuter=\iInner
\ifx\sName\sFile
\expandafter\lowercase\expandafter{\expandafter\def\expandafter\sFile\expandafter{\sName.jpg}}
\StrSubstitute{\sFile}{ }{-}[\sFile]
\else \edef\sFile{\sFile.jpg}% includes automatically the extension .jpg (comment line out if not needed)
\fi
\student{\sX}{\sY}{\sName}{\sFile}
\breakforeach
\fi
}
}
\end{tikzpicture}
\end{document}
输出
答案2
即便有可能激怒 Werner [:)],我还是想说,使用\newforeach
,所有元素(包括文件名,例如example-image-10x16.jpg
)都可以被空格包围。
\documentclass[10pt]{article}
\usepackage[margin=0in,paperwidth=17in, paperheight=11in]{geometry}
\usepackage{tikz,loops}
\newcommand*{\ListOfStudents}{%
George Washington / example-image-10x16.jpg / 4 / 7,
John Adams / example-image-10x16.jpg / 5.5 / 10,
Thomas Jefferson / example-image-10x16.jpg / 7 / 13,
James Madison / example-image-10x16.jpg / 12.5 / 20,
James Monroe / example-image-10x16.jpg / 17 / 20,
John Quincy Adams / example-image-10x16.jpg / 21.5 / 20,
Andrew Jackson / example-image-10x16.jpg / 26 / 20,
Martin Van Buren / example-image-10x16.jpg / 30.5 / 20,
William Henry Harrison / example-image-10x16.jpg / 36 / 13,
John Tyler / example-image-10x16.jpg / 37.5 / 10,
James K Polk / example-image-10x16.jpg / 39 / 7
}
\begin{document}
\noindent
\begin{tikzpicture}
\useasboundingbox (0,0) rectangle (17in,11in);
\draw[line width=5mm] (5,5) -- (10,15);
\draw[line width=5mm] (12,18) -- (31,18);
\draw[line width=5mm] (38,5) -- (33,15);
\newforeach [expand list once=true] \name/\file/\x/\y in \ListOfStudents{%
\node[anchor=base,inner sep=0,
label={[text width=20mm,align=center]below:\name}] at (\x,\y)
{\includegraphics[width=17mm]{\file}};
}
\end{tikzpicture}
\end{document}
我们也可以使用
\foreachfox [expand list once=true, arg=#1/#2/#3/#4]\ListOfStudents{%
\edef\tempa{\skvtrimspace{#2}}%
\node[anchor=base,inner sep=0,
label={[text width=20mm,align=center]below:#1}] at (#3,#4)
{\includegraphics[width=17mm]{\tempa}};
}