动态生成 TikZ \pics

动态生成 TikZ \pics

我想\pics动态生成 TikZ。设置图片所需的所有信息(名称、x 坐标、y 坐标)均在表格中给出。

有没有办法将这些信息注入 TikZ 环境并绘制它们?否则我总是必须同步 TikZ 中的图形信息和表格环境中的文本信息。

我也愿意以完全不同的格式定义这些信息,然后将其注入表格和 TikZ 环境。我只想保留单一事实来源。

\documentclass{article}%
\usepackage[a3paper,left=10mm,right=10mm,top=10mm,bottom=10mm]{geometry}%
\usepackage{courier}%
\usepackage[T1]{fontenc}%
\usepackage[parfill]{parskip}%
\usepackage[utf8]{inputenc}%
\usepackage{caption}%
\usepackage{graphicx}%
\usepackage{tikz}%
\tikzset{
PowerSupply/.pic={
\node{\includegraphics[scale=0.05,angle=270]{powerSupply.png}};},
}

\begin{document}
\section*{Electrical Installation Plan}
\subsection*{Component List}

\begin{center}
\begin{tabular}{|c|c|c|c|}
\hline
\textbf{ID} & \textbf{Description} & \textbf{X-Pos} & \textbf{Y-Pos} \\ \hline
A1F5F & PowerSupply1 & 3400 & 2000 \\ \hline %Input 1
7ZF3I & PowerSupply2 & 3400 & 2500 \\ \hline %Input 2
\hline
\end{tabular}
\end{center}

\pagenumbering{gobble}
\begin{figure}[h!]
\centering
\scalebox{2.0}{
\begin{tikzpicture}[x=0.01mm, y=-0.01mm]
\node[inner sep=0pt] (ground_floor) {\includegraphics[width=99.0mm,height=107.4mm]{groundFloor.png}};
\tikzset{shift=(ground_floor.north west)}

\draw[blue, ->, line width=1pt] (0,0) -- (10000,0);
\draw[blue, line width=1pt] (10000,0) --node[scale=0.5,black,above=1mm,align=center]{[mm]}(10000,0);
\foreach \x in {0,1000,...,9000} \draw[blue, line width=1pt] (\x,-100) --node[scale=0.5,black,above=1mm,align=center]{\x} (\x,100);

\draw[blue, ->, line width=1pt] (0,0) -- (0,11000);
\draw[blue, line width=1pt] (0,11000) --node[scale=0.5,black,left=1mm,align=center]{[mm]}(0,11000);
\foreach \y in {0,1000,...,10000} \draw[blue, line width=1pt] (-100,\y) --node[scale=0.5,black,left=1mm,align=center]{\y} (100,\y);

\pic at (3450,2000) {PowerSupply}; %This must be generated automatically from line 2 (ID: A1F5F)
\pic at (3450,2500) {PowerSupply}; %This must be generated automatically from line 3 (ID: 7ZF3I)
\end{tikzpicture}}
\caption{Ground Floor}
\end{figure}
\vfill
\clearpage
\end{document}

例子

示例图像

电源 底层

答案1

您可以使用pgfplotstablepgfplots包(在后台加载tikz)并读取 CSV 文件,然后您可以处理它并使用它来放置\pics或执行任何您想做的事情。我可能会添加一个用于旋转的列,这样您\pic也可以将其放置在其他地方。

对于以下 MWE,我还包括了我对你另一个问题的回答

\documentclass{article}
\usepackage[a4paper, margin=10mm]{geometry}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}

\begin{filecontents}{data.csv}
id, name, x-coord, y-coord, rotation
A1F5F, PowerSupply1, 3590, 2000, 270 
7ZF3I, PowerSupply2, 3590, 2500, 270
O7PYQ, PowerSupply3, 4250, 6070, 180
\end{filecontents}

\pgfplotstableread[col sep=comma]{data.csv}{\csvdata}
\pgfplotstablegetrowsof{\csvdata}
\pgfmathtruncatemacro\CSVDataRows{\pgfplotsretval-1} 

\tikzset{
    PowerSupply/.pic={
        \node[anchor=north, inner sep=0pt]
            {\includegraphics[scale=0.09]{powerSupply}};
    },
}

\begin{document}
\pagenumbering{gobble}

\section*{Electrical Installation Plan}
\subsection*{Component List}

\begin{center}
\pgfplotstabletypeset[
    col sep=comma,
    columns={id, name, x-coord, y-coord},
    columns/id/.style={
        column name=ID,
        string type
    },
    columns/name/.style={
        column name=Description,
        string type
    },
    columns/x-coord/.style={
        column name=X-Pos
    },
    columns/y-coord/.style={
        column name=Y-Pos,
        column type/.add={}{|}
    },
    column type/.add={|}{},
    after row={\hline},
    every head row/.style={before row=\hline},
]{data.csv}
\end{center}

\begin{figure}[h!]
\centering
\begin{tikzpicture}[x=0.01mm, y=-0.01mm]
    \node[inner sep=0pt] (ground_floor)   
        {\includegraphics[width=99.0mm, height=107.4mm]{groundFloor}};
    
    \begin{scope}[shift=(ground_floor.north west)]
        \draw[blue, ->, line width=1pt] (0,0) -- (10000,0);
        \draw[blue, ->, line width=1pt] (0,0) -- (0,11000);
        
        \foreach \x in {0,1000,...,9000} {
            \draw[blue, line width=1pt] (\x,-100) -- 
                node[black, above=1mm] {\tiny\x mm} (\x,100);
        }
        \foreach \y in {0,1000,...,10000} {
            \draw[blue, line width=1pt] (-100,\y) --
                node[black, left=1mm]{\tiny\y mm} (100,\y);
        }

        \foreach \row in {0,...,\CSVDataRows} {
            \pgfplotstablegetelem{\row}{x-coord}\of{\csvdata}
            \pgfmathsetmacro{\x}{\pgfplotsretval}
            \pgfplotstablegetelem{\row}{y-coord}\of{\csvdata}
            \pgfmathsetmacro{\y}{\pgfplotsretval}
            \pgfplotstablegetelem{\row}{rotation}\of{\csvdata}
            \pgfmathsetmacro{\r}{\pgfplotsretval}
            \pic[rotate=\r, transform shape] at (\x,\y) {PowerSupply};
        }
    \end{scope}
\end{tikzpicture}
\caption{Ground Floor}
\end{figure}
\vfill
\clearpage
\end{document}

在此处输入图片描述


扩展以将标签添加到节点。由于您想使用节点来包含图像,因此您需要将其添加transform shape\pic,但这也会旋转附加到节点的标签。如果您希望标签不旋转,则需要取消旋转。

我扩展了\pic代码,以便\pic现在可以接受参数。这些参数可用于添加标签并将此标签定位到父节点。

\documentclass{article}
\usepackage[a4paper, margin=10mm]{geometry}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}

\begin{filecontents}{data.csv}
id, name, x-coord, y-coord, rotation
A1F5F, PowerSupply1, 3590, 2000, 270 
7ZF3I, PowerSupply2, 3590, 2500, 270
O7PYQ, PowerSupply3, 4250, 6070, 180
\end{filecontents}

\pgfplotstableread[col sep=comma]{data.csv}{\csvdata}
\pgfplotstablegetrowsof{\csvdata}
\pgfmathtruncatemacro\CSVDataRows{\pgfplotsretval-1} 

\tikzset{
    pics/PowerSupply/.style={
        code={
            \tikzset{PowerSupply/.cd, #1}
            \node[anchor=north, inner sep=0pt] (-p)
                {\includegraphics[scale=0.09]{powerSupply}};
            \node[
                inner sep=0pt,
                anchor={90+\pgfkeysvalueof{/tikz/PowerSupply/label position}},
                rotate={-1*\pgfkeysvalueof{/tikz/PowerSupply/label position}}
            ] at (-p.south) {\tiny \pgfkeysvalueof{/tikz/PowerSupply/label}};
        }
    },
    PowerSupply/label/.initial={},
    PowerSupply/label position/.initial={0}
}

\begin{document}
\pagenumbering{gobble}

\section*{Electrical Installation Plan}
\subsection*{Component List}

\begin{center}
\pgfplotstabletypeset[
    col sep=comma,
    columns={id, name, x-coord, y-coord},
    columns/id/.style={
        column name=ID,
        string type
    },
    columns/name/.style={
        column name=Description,
        string type
    },
    columns/x-coord/.style={
        column name=X-Pos
    },
    columns/y-coord/.style={
        column name=Y-Pos,
        column type/.add={}{|}
    },
    column type/.add={|}{},
    after row={\hline},
    every head row/.style={before row=\hline},
]{data.csv}
\end{center}

\begin{figure}[h!]
\centering
\begin{tikzpicture}[x=0.01mm, y=-0.01mm]
    \node[inner sep=0pt] (ground_floor)   
        {\includegraphics[width=99.0mm, height=107.4mm]{groundFloor}};
    
    \begin{scope}[shift=(ground_floor.north west)]
        \draw[blue, ->, line width=1pt] (0,0) -- (10000,0);
        \draw[blue, ->, line width=1pt] (0,0) -- (0,11000);
        
        \foreach \x in {0,1000,...,9000} {
            \draw[blue, line width=1pt] (\x,-100) -- 
                node[black, above=1mm] {\tiny\x mm} (\x,100);
        }
        \foreach \y in {0,1000,...,10000} {
            \draw[blue, line width=1pt] (-100,\y) --
                node[black, left=1mm]{\tiny\y mm} (100,\y);
        }

        \foreach \row in {0,...,\CSVDataRows} {
            \pgfplotstablegetelem{\row}{x-coord}\of{\csvdata}
            \pgfmathsetmacro{\x}{\pgfplotsretval}
            \pgfplotstablegetelem{\row}{y-coord}\of{\csvdata}
            \pgfmathsetmacro{\y}{\pgfplotsretval}
            \pgfplotstablegetelem{\row}{rotation}\of{\csvdata}
            \pgfmathsetmacro{\r}{\pgfplotsretval}
            \pgfplotstablegetelem{\row}{id}\of{\csvdata}
            \pgfmathsetmacro{\i}{"\pgfplotsretval"}
            \pic[rotate=\r, transform shape] at (\x,\y) {
                PowerSupply={
                    label={\i},
                    label position={\r}
                }
            };
        }
    \end{scope}
\end{tikzpicture}
\caption{Ground Floor}
\end{figure}
\vfill
\clearpage
\end{document}

在此处输入图片描述


您还可以重命名为\pic,例如,ElectricComponent并在列表中为组件类型添加另一列。然后您可以使用相同的方式\pic放置不同的图片:

\documentclass{article}
\usepackage[a4paper, margin=10mm]{geometry}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}

\begin{filecontents}{data.csv}
id, name, type, x-coord, y-coord, rotation
A1F5F, PowerSupply1, PowerSupply, 3590, 2000, 270 
7ZF3I, PowerSupply2, PowerSupply, 3590, 2500, 270
O7PYQ, PowerSupply3, PowerSupply, 4250, 6070, 180
A7HAZ, Switch1, singleSwitch, 5700, 6070, 180
\end{filecontents}

\pgfplotstableread[col sep=comma]{data.csv}{\csvdata}
\pgfplotstablegetrowsof{\csvdata}
\pgfmathtruncatemacro\CSVDataRows{\pgfplotsretval-1} 

\tikzset{
    pics/ElectricComponent/.style={
        code={
            \tikzset{ElectricComponent/.cd, #1}
            \node[anchor=north, inner sep=0pt] (-p)
                {\includegraphics[scale=0.09]{\pgfkeysvalueof{/tikz/ElectricComponent/type}}};
            \node[
                inner sep=0pt,
                anchor={90+\pgfkeysvalueof{/tikz/ElectricComponent/label position}},
                rotate={-1*\pgfkeysvalueof{/tikz/ElectricComponent/label position}}
            ] at (-p.south) {\tiny \pgfkeysvalueof{/tikz/ElectricComponent/label}};
        }
    },
    ElectricComponent/type/.initial={PowerSupply},
    ElectricComponent/label/.initial={},
    ElectricComponent/label position/.initial={0}
}

\begin{document}
\pagenumbering{gobble}

\section*{Electrical Installation Plan}
\subsection*{Component List}

\begin{center}
\pgfplotstabletypeset[
    col sep=comma,
    columns={id, name, x-coord, y-coord},
    columns/id/.style={
        column name=ID,
        string type
    },
    columns/name/.style={
        column name=Description,
        string type
    },
    columns/x-coord/.style={
        column name=X-Pos
    },
    columns/y-coord/.style={
        column name=Y-Pos,
        column type/.add={}{|}
    },
    column type/.add={|}{},
    after row={\hline},
    every head row/.style={before row=\hline},
]{data.csv}
\end{center}

\begin{figure}[h!]
\centering
\begin{tikzpicture}[x=0.01mm, y=-0.01mm]
    \node[inner sep=0pt] (ground_floor)   
        {\includegraphics[width=99.0mm, height=107.4mm]{groundFloor}};
    
    \begin{scope}[shift=(ground_floor.north west)]
        \draw[blue, ->, line width=1pt] (0,0) -- (10000,0);
        \draw[blue, ->, line width=1pt] (0,0) -- (0,11000);
        
        \foreach \x in {0,1000,...,9000} {
            \draw[blue, line width=1pt] (\x,-100) -- 
                node[black, above=1mm] {\tiny\x mm} (\x,100);
        }
        \foreach \y in {0,1000,...,10000} {
            \draw[blue, line width=1pt] (-100,\y) --
                node[black, left=1mm]{\tiny\y mm} (100,\y);
        }

        \foreach \row in {0,...,\CSVDataRows} {
            \pgfplotstablegetelem{\row}{x-coord}\of{\csvdata}
            \pgfmathsetmacro{\x}{\pgfplotsretval}
            \pgfplotstablegetelem{\row}{y-coord}\of{\csvdata}
            \pgfmathsetmacro{\y}{\pgfplotsretval}
            \pgfplotstablegetelem{\row}{rotation}\of{\csvdata}
            \pgfmathsetmacro{\r}{\pgfplotsretval}
            \pgfplotstablegetelem{\row}{type}\of{\csvdata}
            \pgfmathsetmacro{\t}{"\pgfplotsretval"}
            \pgfplotstablegetelem{\row}{id}\of{\csvdata}
            \pgfmathsetmacro{\i}{"\pgfplotsretval"}
            \pic[rotate=\r, transform shape] at (\x,\y) {
                ElectricComponent={
                    type={\t},
                    label={\i},
                    label position={\r}
                }
            };
        }
    \end{scope}
\end{tikzpicture}
\caption{Ground Floor}
\end{figure}
\vfill
\clearpage
\end{document}

在此处输入图片描述


无需任何 TiZ魔法:

\documentclass{article}
\usepackage[a4paper, margin=10mm]{geometry}
\usepackage{pgfplotstable}
\pgfplotsset{compat=newest}

\begin{filecontents}{data.csv}
id, name, type, x-coord, y-coord, rotation
A1F5F, PowerSupply1, powerSupply, 3590, 2000, 270 
7ZF3I, PowerSupply2, powerSupply, 3590, 2500, 270
O7PYQ, PowerSupply3, powerSupply, 4250, 6070, 180
A7HAZ, Switch1, singleSwitch, 5700, 6070, 180
\end{filecontents}

\pgfplotstableread[col sep=comma]{data.csv}{\csvdata}

\begin{document}
\pagenumbering{gobble}

\begin{center}
\pgfplotstabletypeset[
    col sep=comma,
    columns={id, name, type, x-coord, y-coord},
    columns/id/.style={
        column name=ID,
        string type
    },
    columns/name/.style={
        column name=Description,
        string type
    },
    columns/type/.style={
        column name=Type,
        assign cell content/.code={
            \pgfkeyssetvalue{/pgfplots/table/@cell content}{
                \includegraphics[scale=0.09]{##1}
            }
        }
    },
    columns/x-coord/.style={
        column name=X-Pos
    },
    columns/y-coord/.style={
        column name=Y-Pos,
        column type/.add={}{|}
    },
    column type/.add={|}{},
    after row={\hline},
    every head row/.style={before row=\hline},
]{data.csv}
\end{center}

\end{document}

在此处输入图片描述

答案2

如果我们使用 OpTeX,则不需要使用 TikZ,因为有\puttext宏。powerSupply.png图像被保存到,\pwbox并且此框在循环中被复制(并旋转)\fornum

\newcount\pwtotal
\def\d #1, #2, #3, #4, #5 {\advance\pwtotal by1
   \sxdef{\pws:id}{#1}\sxdef{\pws:d}{#2}\sxdef{\pws:x}{#3}\sxdef{\pws:y}{#4}\sxdef{\pws:r}{#5}%
}
\def\pws{pws:\the\pwtotal}

\def\putpw#1{\pdfsave\pdfrotate{#1}\copy\pwbox\pdfrestore}
\newdimen\pwunit \pwunit=.01mm

%% Save power supply image:

\newbox\pwbox
\setbox\pwbox=\hbox to0pt{\hss \picw=5mm \vbox to0pt{\inspic{powerSupply.png}\vss}\hss}

%% Save data:

\d A1F5F, PowerSupply1, 3590, 2000, 270 
\d 7ZF3I, PowerSupply2, 3590, 2500, 270
\d O7PYQ, PowerSupply3, 4250, 6070, 180

%% Print table:

\noindent\hfil\table{|c|c|c|c|}{\crl
   \bf Id & \bf Description & \bf X-Pos & \bf Y-pos \crl
   \fornum 1..\pwtotal \do{\cs{pws:#1:id}&\cs{pws:#1:d}&\cs{pws:#1:x}&\cs{pws:#1:y}\crl}
}
\bigskip

%% Draw final image:

\noindent\hfil\vbox{
   \picwidth=99mm \picheight=107.4mm
   \vbox to0pt{\inspic{groundFloor.png}\vss} % load background image
   \fornum 1..\pwtotal \do{
      \puttext \cs{pws:#1:x}\pwunit -\cs{pws:#1:y}\pwunit {\putpw{\cs{pws:#1:r}}}
   }
   \kern \picheight
}
\bye

相关内容