我正在尝试使用 TikZ 绘制一条简单路径,并使用自定义语法来指定它。这有效:
\documentclass{article}
\usepackage{tikz}
\begin{document}
\newcommand{\latticepath}[1]{
\draw[thick] (0,0) node{} \foreach \x in {#1}{ -- \if u\x ++(0,1) \else ++(1,0) \fi node{}};
}
\begin{tikzpicture}[x=3mm,y=3mm]
\tikzset{every node/.style={circle,fill,draw=none,inner sep=2pt}}
\latticepath{r,r,u,r,r,u,u,r,u,r,u,u}
\end{tikzpicture}
\end{document}
但是,我不喜欢用逗号分隔这些值。因此,我编写了这个命令来将字母序列转换为路径组件:
\documentclass{article}
\usepackage{tikz}
\begin{document}
\makeatletter\let\mygobble\@gobble\makeatother
\newcommand{\readpath}[3]{
\def\pathimpl##1{\ifx##1.\let\rest\mygobble\else\ifx##1u#1\else#2\fi\def\rest####1{####1}\fi\rest\pathimpl}
\pathimpl#3.
}
\readpath{Up }{Right }{rrurruururuu}
然而,由于在路径中使用了宏,此实现会产生一系列错误:
\newcommand{\betterlatticepath}[1]{
\draw[thick] (0,0) node{} \readpath{++(0,1) node{}}{++(1,0) node{}}{#1};
}
\begin{tikzpicture}
\tikzset{every node/.style={circle,fill,draw=none,inner sep=2pt}}
\betterlatticepath{rrurruururuu}
\end{tikzpicture}
\end{document}
软件包 tikz 错误:放弃此路径。您忘记了分号吗?。
未定义的控制序列。
您不能在受限水平模式下使用“宏参数字符 #”。
参数必须连续编号。
参数必须连续编号。
\rest 的参数有一个多余的 }。
失控参数?
我试过了\pgfextra
,但是没有用。我该如何让它起作用?
答案1
\pgfextra
以下是使用和insert path
两个自定义键的解决方案:
\documentclass[tikz]{standalone}
\tikzset{
recurse lattice path/.code args={#1#2}{
\ifx#1.
\else
\ifx#1u
\tikzset{insert path={-- ++(0,1) node[fill=black]{}}}
\else
\tikzset{insert path={-- ++(1,0) node[fill=black]{}}}
\fi
\tikzset{recurse lattice path=#2}
\fi
},
lattice path/.code={%
\draw (0,0) node[fill=black]{}
\pgfextra{\tikzset{recurse lattice path={#1.}}};
},
}
\begin{document}
\begin{tikzpicture}
\tikzset{lattice path=rrurrur}
\end{tikzpicture}
\end{document}
编辑:
这是一个更简单的解决方案\pgfextra
:
\documentclass[tikz]{standalone}
\tikzset{
dep u/.style={insert path={-- ++(0,1) node{}}},
dep r/.style={insert path={-- ++(1,0) node{}}},
dep d/.style={insert path={-- ++(0,-1) node{}}},
dep l/.style={insert path={-- ++(-1,0) node{}}},
recurse lattice path/.code args={#1#2}{
\ifx#1.\else\tikzset{dep #1,recurse lattice path=#2}\fi
},
lattice path/.style={recurse lattice path=#1.}
}
\begin{document}
\begin{tikzpicture}
\tikzset{every node/.style={circle,fill,draw=none,inner sep=2pt}}
\draw (0,0) node{} [lattice path=rrurrurrdddlll];
\end{tikzpicture}
\end{document}
答案2
基本上,你不能将使用定义的宏放在\newcommand
TikZ 路径内,因为它会做很多“隐藏”的事情(例如\futurelet
),而 TikZ 无法处理。
但是,您可以将任意代码放入\pgfextra{}
TikZ 路径中。在这种情况下,您可以在里面构建路径\pgfextra
,然后将其插入,如下所示:
\documentclass[tikz,border=0.125cm]{standalone}
\def\addtolatticepath#1{%
\expandafter\def\expandafter\latticepath\expandafter{\latticepath#1}%
}
\def\latticepathletteru{\addtolatticepath{ -- ++(0,1) }}
\def\latticepathletterd{\addtolatticepath{ -- ++(0,-1) }}
\def\latticepathletterl{\addtolatticepath{ -- ++(-1,0) }}
\def\latticepathletterr{\addtolatticepath{ -- ++(1,0) }}
\def\parselatticepath#1{%
\def\latticepath{node {}}%
\Parselatticepath#1@}
\def\Parselatticepath#1{%
\ifx#1@%
\let\next=\relax%
\else%
\csname latticepathletter#1\endcsname%
\addtolatticepath{ node {} }%
\let\next=\Parselatticepath
\fi%
\next}
\tikzset{%
insert lattice path/.style={%
every node/.style={
circle,
fill,
draw=none,
inner sep=2pt
},
insert path={%
\pgfextra{\parselatticepath{#1}}%
\latticepath
}
}
}
\begin{document}
\begin{tikzpicture}
\draw (0,0) [insert lattice path={rrurruururuu}];
\end{tikzpicture}
\end{document}
答案3
这是一个老问题,但由于我没有看到很多使用parser
PGF 库的答案,所以我添加了一个。
\documentclass[tikz,border=7pt]{standalone}
\usepgfmodule{parser}
% macro that add #1 to the current path when used inside \pgfextra
\def\insertpath#1{\tikzset{insert path={#1}}}
% define the parser "lattice path"
\pgfparserdef{lattice path}{initial}{the letter u}{\insertpath{node{} -- ++(0,1) }}
\pgfparserdef{lattice path}{initial}{the letter r}{\insertpath{node{} -- ++(1,0) }}
\pgfparserdef{lattice path}{initial}{the letter d}{\insertpath{node{} -- ++(0,-1)}}
\pgfparserdef{lattice path}{initial}{the letter l}{\insertpath{node{} -- ++(-1,0)}}
\pgfparserdef{lattice path}{initial}{the character .}{\pgfparserswitch{final}}
\begin{document}
\begin{tikzpicture}[every node/.style={circle,fill=red,inner sep=2pt}]
\draw (0,0) \pgfextra{\pgfparserparse{lattice path}rrurrurrdddlll.} node{};
\end{tikzpicture}
\end{document}