我正在尝试使用文本文件传递我在 Tikz 图中使用的变量的值。我不确定如何将数据从字符串转换为字符。在这里,将automaton.txt
一些数组值(1x4)存储为每行的字符串,我想根据这些字符串重写\statedef
。每次导入时文本文件的行数都会有所不同,并且只\def
接受字符。另外,我想知道是否有任何方法可以将文本文件同步到 overleaf,这样我就可以在 overleaf 的图中看到更改?
\documentclass[tikz,border=1cm]{standalone}
\usepackage{graphicx} % Required for inserting images
\usepackage{amsthm}
\pdfoutput=1
\usepackage{multirow}
\usepackage{lettrine}
\usepackage{graphicx,float}
\usepackage{tikz}
\usetikzlibrary{automata, positioning, arrows.meta,calc,cd}
\usetikzlibrary{patterns}
\usetikzlibrary{datavisualization}
\tikzset{
->, % makes the edges directed
>=stealth, % makes the arrow heads bold
node distance=3cm, % specifies the minimum distance between two nodes. Change if necessary.
every state/.style={thick, fill=gray!10}, % sets the properties for each ’state’ node
initial text=$ $, % sets the text that appears on the start arrow
}
\usepackage[fleqn]{amsmath}
\usepackage{amssymb}
\usepackage{cite}
\usepackage{lettrine}
\let\labelindent\relax
\usepackage{enumitem}
\usepackage{multicol}
\usepackage{readarray}
\usepackage{pgfplots}
\usepackage{pgfmath}
\makeatletter
\newenvironment{customlegend}[1][]{%
\begingroup
% inits/clears the lists (which might be populated from previous
% axes):
\pgfplots@init@cleared@structures
\pgfplotsset{#1}%
}{%
% draws the legend:
\pgfplots@createlegend
\endgroup
}%
% makes \addlegendimage available (typically only available within an
% axis environment):
\def\addlegendimage{\pgfplots@addlegendimage}
\makeatother
\usepackage[T1]{fontenc}
\usepackage[export]{adjustbox}
\usepackage{booktabs,makecell}
\usepackage{graphicx}
\usepackage{xcolor}
\usepackage[labelsep=quad,indention=10pt]{subfig}
\usepackage{ifthen}
\begin{document}
\tikzset{
redfill/.code={
\definecolor{mycolour1}{rgb}{1,0,0}%
\pgfkeysalso{/tikz/fill=mycolour1!40}
}
}
\tikzset{
greenfill/.code={
\definecolor{mycolour2}{rgb}{0,1,0}%
\pgfkeysalso{/tikz/fill=mycolour2!30}
}
}
\tikzset{
bluefill/.code={
\definecolor{mycolour3}{rgb}{0,0,1}%
\pgfkeysalso{/tikz/fill=mycolour3!40}
}
}
\tikzset{
cyanfill/.code={
\pgfkeysalso{/tikz/fill=teal!60}
}
}
\tikzset{
twocolorfill/.style n args={2}{path picture={
\fill[#1] (path picture bounding box.south)--(path picture bounding box.north)--(path picture bounding box.north east)--(path picture bounding box.south east)--cycle;
\fill[#2] (path picture bounding box.south)--(path picture bounding box.north)--(path picture bounding box.north west)--(path picture bounding box.south west)--cycle;
}}
}
\tikzset{
threecolorfill/.style n args={3}{path picture={
\fill[#1] (path picture bounding box.east)--(path picture bounding box.north east)--(path picture bounding box.north west)--(path picture bounding box.west)--cycle;
\fill[#2] (path picture bounding box.center) -- (path picture bounding box.south) arc [start angle=-90, delta angle=-90, radius=1] -- cycle;
\fill[#3] (path picture bounding box.center) -- (path picture bounding box.south) arc [start angle=-90, delta angle=90, radius=1] -- cycle;
}}
}
\tikzset{
fourcolorfill/.style n args={4}{path picture={
\fill[#1] (path picture bounding box.east)--(path picture bounding box.north east)--(path picture bounding box.north)--(path picture bounding box.center)--cycle;
\fill[#2] (path picture bounding box.center)--(path picture bounding box.north)--(path picture bounding box.north west)--(path picture bounding box.west)--cycle;
\fill[#3] (path picture bounding box.center)--(path picture bounding box.south)--(path picture bounding box.south west) -- (path picture bounding box.west) -- cycle;
\fill[#4] (path picture bounding box.center)--(path picture bounding box.south)--(path picture bounding box.south east) -- (path picture bounding box.east) -- cycle;
}}
}
\tikzset{
colorfill1_sub/.code=
{
\ifnum\pgfkeysvalueof{/tikz/colorfill_item}=#1
\tikzset{greenfill}
\else
\fi
},
colorfill2_sub/.code=
{
\ifnum\pgfkeysvalueof{/tikz/colorfill_item}=#1
\tikzset{redfill}
\else
\fi
},
colorfill3_sub/.code=
{
\ifnum\pgfkeysvalueof{/tikz/colorfill_item}=#1
\tikzset{bluefill}
\else
\fi
},
colorfill4_sub/.code=
{
\ifnum\pgfkeysvalueof{/tikz/colorfill_item}=#1
\tikzset{cyanfill}
\else
\fi
},
hashfill1_sub/.code=
{
\ifnum\pgfkeysvalueof{/tikz/colorfill_item}=#1
\tikzset{pattern=north west lines, pattern color=black}
\else
\fi
},
fourcolor1_sub/.code=
{
\ifnum\pgfkeysvalueof{/tikz/colorfill_item}=#1
\tikzset{fourcolorfill={cyanfill}{redfill}{greenfill}{blue!50}}
\else
\fi
},
threecolor1_sub/.code=
{
\ifnum\pgfkeysvalueof{/tikz/colorfill_item}=#1
\tikzset{threecolorfill={cyanfill}{greenfill}{blue!50}}
\else
\fi
},
twocolor1_sub/.code=
{
\ifnum\pgfkeysvalueof{/tikz/colorfill_item}=#1
\tikzset{twocolorfill={blue!50}{cyanfill}}
\else
\fi
},
colorfill_item/.initial=0,
colorfill/.code n args={9}
{
\tikzset{colorfill_item=#1,colorfill1_sub/.list=#2,colorfill2_sub/.list=#3,colorfill3_sub/.list=#4,colorfill4_sub/.list=#5,hashfill1_sub/.list=#6,fourcolor1_sub/.list=#7,threecolor1_sub/.list=#8,twocolor1_sub/.list=#9}
}
}
\begin{figure*}[h]
\centering
\begin{adjustbox}{minipage=\textwidth,scale=0.8}
\begin{tikzpicture}[node distance = 2cm, on grid,>={Stealth[inset=0pt,length=6pt,angle'=28,round]}
]
\begin{customlegend}[legend style={at={(10,-8)},anchor=south},legend columns=-1,legend style={column sep=1ex},legend entries={Proposed Method,PCM PTA-MPC,CB PTA-MPC,PTA-MPC,Failed State}]
\addlegendimage{black,only marks, mark=*, cyanfill,style={scale=4}}
\addlegendimage{black,only marks, mark=*, bluefill,style={scale=4}}
\addlegendimage{black,only marks, mark=*, greenfill,style={scale=4}}
\addlegendimage{black,only marks, mark=*, redfill,style={scale=4}}
\addlegendimage{black,only marks, mark=*, pattern=north west lines, pattern color=black,style={scale=4}}
\end{customlegend};
\readarraysepchar{,}
\readdef{automaton.txt}{\mydata}
\readarray\mydata\datacell[-,\ncols]
\def\test{\pgfkeysvalueof{\mydata[3,4]}}
%% DO NOT put extra space below!!!
%% {first state xcoor,first state ycoor,first state superscript, last state superscript}
%% State Definition
\def\statedef{{2,0,2,10},{8,2,11,14},{8,-2,15,20},{8,-4,21,24},{4,-3,25,26},{5,-6,27,29}}
%% {first state superscript, last state superscript}
%% Straight Edge Definition
\def\straightsolidedge{{1,5},{7,9},{11,12},{14},{15,20},{21,24},{27,29}}
\def\bendrightsolidedge{{2,25},{25,27},{29,22},{24,19},{18,9},{16,7},{4,15},{4,21},{16,23}}
\def\bendleftsolidedge{{12,7},{14,9}}
%% Color Definiton
\def\rstates{{5,22,23,24,25,27,28,29}}
\def\gstates{{11,12}}
\def\bstates{{13}}
\def\cstates{{17,18,19,20}}
\def\hashedstates{{6,10,13,26}}
\def\bicolorstates{{15,16}}
\def\tricolorstates{{7,8}}
\def\quadcolorstates{{2,3,4}}
\node[state,initial,fourcolorfill={cyanfill}{redfill}{greenfill}{blue!50}](q1){$q^{1}$};
\foreach \e in \statedef
{\edef\mye{{\e}}
\pgfmathsetmacro{\myx}{\mye[0]}
\pgfmathsetmacro{\myy}{\mye[1]}
\pgfmathsetmacro{\myfirstind}{\mye[2]}
\pgfmathsetmacro{\mystartind}{int(\mye[2]+1)}
\pgfmathsetmacro{\mylastind}{\mye[3]}
\node [state, colorfill/.expanded={\myfirstind}{\gstates}{\rstates}{\bstates}{\cstates}{\hashedstates}{\quadcolorstates}{\tricolorstates}{\bicolorstates}] at (\myx,\myy) (q\myfirstind){$q^{\myfirstind}$};
\foreach \a[evaluate=\a as \b using int(\a-1)] in {\mystartind,...,\mylastind}{
\node[state, right of=q\b, colorfill/.expanded={\a}{\gstates}{\rstates}{\bstates}{\cstates}{\hashedstates}{\quadcolorstates}{\tricolorstates}{\bicolorstates}] (q\a){$q^{\a}$};
}
}
\foreach \r in \straightsolidedge
{\edef\myr{{\r}}
\pgfmathsetmacro{\mystartstate}{\myr[0]}
\pgfmathsetmacro{\myendstate}{\myr[1]-1}
\foreach \d[evaluate=\d as \e using int(\d+1)] in {\mystartstate,...,\myendstate}{
\draw (q\d) edge (q\e);
}
}
\foreach \t in \bendrightsolidedge
{\edef\myt{{\t}}
\pgfmathsetmacro{\f}{\myt[0]}
\pgfmathsetmacro{\g}{\myt[1]}
\draw (q\f) edge[bend right] (q\g);
}
\foreach \u in \bendleftsolidedge
{\edef\myu{{\u}}
\pgfmathsetmacro{\h}{\myu[0]}
\pgfmathsetmacro{\i}{\myu[1]}
\draw (q\h) edge[bend left] (q\i);
}
\draw (q4) edge[bend left] node [below left]{} (q11);
\end{tikzpicture}
\end{adjustbox}
\end{figure*}
\end{document}
此外,以下是 的内容automaton.txt
。
2,0,2,5
2,2,6,8
2,-2,9,11
答案1
使用lualatex
。我承认我的方法不是很优雅:P。
\documentclass{scrartcl}
\usepackage{luacode}
\usepackage{pgffor}
\begin{filecontents*}{data.txt}
2,0,2,6
2,2,6,8
2,-2,9,11
\end{filecontents*}
\begin{document}
\begin{luacode}
function read_file(file,macro)
f = io.open(file, "r")
concat_string = ""
i = 1
for line in io.lines(file) do
concat_string = concat_string .. "{" .. line .. "},"
i = i + 1
end
-- remove trailing ","
concat_string = concat_string:sub(1,-2)
tex.sprint("\\def" .. "\\" .. macro .. "{" .. concat_string .. "}")
end
\end{luacode}
\directlua{read_file("data.txt", "statedef")}
\noindent
\foreach \s [count=\i from 1] in \statedef{%
State \i{} entries:
\foreach \se in \s {%
\se~
}
\\
}
\end{document}
答案2
可能一些用于迭代数组行和列的嵌套循环对您有用。我决定对以下 MWE 使用 expl3 语法,因为 expl3 带来了\cs_to_str:N
一个可靠地传递控制序列标记名称的例程:
\begin{filecontents*}{MYRENAMEDautomaton.txt}
2,0,2,5
2,2,6,8
2,-2,9,11
1\TeX1,2\TeX2,3\TeX3,4\TeX4
\end{filecontents*}
\documentclass{article}
\usepackage{readarray}
\ExplSyntaxOn
\cs_new:Npn \TwoDArrayToMacro #1#2 {
\group_begin:
\nocheckbounds
\Mostafa_TwoDArrayToMacroLoop:nnnnnnnn {#1}{#2}{1}{1}{}{}{}{}
}
\cs_new:Npn \Mostafa_TwoDArrayToMacroLoop:nnnnnnnn #1#2#3#4#5#6#7#8 {
% #1 array
% #2 macro
% #3 row number
% #4 column number
% #5 row separator
% #6 column separator
% #7 rows gathered
% #8 colum in construction
\int_compare:nNnTF {#3}>{\use:c{\cs_to_str:N #1ROWS}}
{\group_end: \cs_set:Npn #2{#7}}{
\int_compare:nNnTF {#4}>{\use:c{\cs_to_str:N #1COLS}}
{
\exp_after:wN \use_ii_i:nn \exp_after:wN {
\exp_after:wN {
\exp:w\exp_after:wN\exp_after:wN\exp_after:wN\exp_end:
\int_eval:n{(#3)+1}
}
}{\Mostafa_TwoDArrayToMacroLoop:nnnnnnnn{#1}{#2}}{1}{,}{}{#7#5{#8}}{}
}
{
\exp_after:wN \use_ii_i:nn \exp_after:wN {\exp_after:wN {
\exp:w \Mostafa_exp_args_otimes:nNn{4} \use_ii_i:nn {#1[#3,#4]}{\exp_end: #8#6}
}}
{
\exp_after:wN \use_ii_i:nn \exp_after:wN {
\exp_after:wN {
\exp:w\exp_after:wN\exp_after:wN\exp_after:wN\exp_end:
\int_eval:n{(#4)+1}
}
}{\Mostafa_TwoDArrayToMacroLoop:nnnnnnnn{#1}{#2}{#3}}{#5}{,}{#7}
}
}
}
}
\cs_new:Npn \Mostafa_exp_args_otimes:nNn #1#2#3 {
\exp_after:wN\use_ii_i:nn\exp_after:wN{\exp_after:wN{\exp:w
\exp_after:wN \__Mostafa_exp_args_otimes:nn\exp_after:wN {\exp_after:wN}
\tex_romannumeral:D \int_eval:n {(#1)*1000}~d #3}}{#2}
}
\cs_new:Npn \__Mostafa_exp_args_otimes:nn #1#2 {
\__Mostafa_exp_args_otimes:n {#2}{#1\exp_end:}{\__Mostafa_exp_args_otimes:nn{#1#1\exp_after:wN}}
}
\cs_new:Npn \__Mostafa_exp_args_otimes:n #1 {
\__Mostafa_exp_args_otimes:wnw #1{\use_i:nn}d{\use_ii:nn}dd
}
\cs_new:Npn \__Mostafa_exp_args_otimes:wnw #1d#2#3dd{#2}
\ExplSyntaxOff
\begin{document}
\readarraysepchar{,}
\readdef{MYRENAMEDautomaton.txt}{\mydata}
\readarray\mydata\datacell[-,\ncols]
\TwoDArrayToMacro{\datacell}{\statedef}
\ttfamily\selectfont \frenchspacing
\noindent
\verb|\statedef|=\\
\meaning\statedef
\end{document}