我想定义一个名称相同但参数数量不同的命令。我希望调用 \tkzDrawAltitude(A,M,B) 等同于文档中的 \tkzDrawAltitude(A,B)(M)。
我正在考虑这样的事情:
\documentclass{article}
\usepackage{tkz-euclide}
\makeatletter
\def\tkzDrawAltitude{\pgfutil@ifnextchar[{\tkz@Altitude}{\tkz@Altitude[]}}
\def\tkz@Altitude[#1](#2,#3)(#4){%
\begingroup
\tkzUProjection(#2,#3)(#4)
\tkzDrawSLine[add= 0 and 0,/tkzdrawl/.cd,#1](#4,tkzPointResult)
\endgroup
}
\def\tkz@Altitude[#1](#2,#3,#4){%
\begingroup
\tkzUProjection(#2,#4)(#3)
\tkzDrawSLine[add= 0 and 0,/tkzdrawl/.cd,#1](#3,tkzPointResult)
\endgroup
}
\makeatother
\begin{document}
\section{Command (arg,arg)(arg)}
\begin{center}
\begin{tikzpicture}
\tkzInit[ymin=-0.5,ymax=6.6,xmin=-0.5,xmax=7.5]
\tkzClip
\tkzSetUpPoint[color=black,fill=white,size=3]
\tkzDefPoints{3/5/A,1/0/B,7/0/C}
\tkzDefMidPoint(B,C)\tkzGetPoint{M}
\tkzDrawAltitude(A,B)(M)\tkzGetPoint{N}%Command here
\tkzDefPointBy[projection=onto B--C](A)\tkzGetPoint{H}
\tkzDrawSegments(A,B B,C C,A A,H)
\tkzDrawPoints(A,B,C,M,N,H)
\tkzLabelPoints[left](N)
\tkzLabelPoints[above](A)
\tkzLabelPoints[below](B,H,M,C)
\end{tikzpicture}
\end{center}
\section{Command (arg,arg,arg)}
\begin{center}
\begin{tikzpicture}
\tkzInit[ymin=-0.5,ymax=6.6,xmin=-0.5,xmax=7.5]
\tkzClip
\tkzSetUpPoint[color=black,fill=white,size=3]
\tkzDefPoints{3/5/A,1/0/B,7/0/C}
\tkzDefMidPoint(B,C)\tkzGetPoint{M}
\tkzDrawAltitude(A,M,B)\tkzGetPoint{N}%Command here
\tkzDefPointBy[projection=onto B--C](A)\tkzGetPoint{H}
\tkzDrawSegments(A,B B,C C,A A,H)
\tkzDrawPoints(A,B,C,M,N,H)
\tkzLabelPoints[left](N)
\tkzLabelPoints[above](A)
\tkzLabelPoints[below](B,H,M,C)
\end{tikzpicture}
\end{center}
\end{document}
感谢您的帮助!
答案1
您可以重新定义\tkzDrawAltitude
在括号中有一个强制参数,其中最多有两个逗号,以及在括号中有一个可选参数。
如果可选参数未出现,我们假设(A,M,B)
已使用语法。使用\SplitArgument{2}{,}
我们会得到#1
,{A}{M}{B}
所以我们将它传递\auxA@tkzDrawAltitude
给\saved@tkzDrawAltitude(A,M,B)
。
否则,我们假设(A,B)(M)
语法;在这种情况下#1
将是{A}{B}{-NoValue-}
并且#2
将是M
,所以我们将它们传递给\auxB@tkzDrawAltitude
具有四个参数的函数:它忽略第三个参数并将第四个参数放在中间,因此再次调用\saved@tkzDrawAltitude(A,M,B)
。
\documentclass{article}
\usepackage{tkz-euclide}
\makeatletter
% save the command in tkz-euclide
\let\saved@tkzDrawAltitude\tkzDrawAltitude
% carefully redefine it
\RenewDocumentCommand{\tkzDrawAltitude}{
O{}
>{\SplitArgument{2}{,}}r()
d()
}{%
\IfNoValueTF{#3}
{% new syntax (A,M,B)
\auxA@tkzDrawAltitude{#1}#2%
}
{% old syntax (A,B)(M)
\auxB@tkzDrawAltitude{#1}#2{#3}%
}
}
\NewDocumentCommand{\auxA@tkzDrawAltitude}{mmmm}{%
\saved@tkzDrawAltitude[#1](#2,#3,#4)%
}
\NewDocumentCommand{\auxB@tkzDrawAltitude}{mmmmm}{%
\saved@tkzDrawAltitude[#1](#2,#5,#3)%
}
\makeatother
\begin{document}
\section{Command (arg,arg)(arg)}
\begin{center}
\begin{tikzpicture}
\tkzInit[ymin=-0.5,ymax=6.6,xmin=-0.5,xmax=7.5]
\tkzClip
\tkzSetUpPoint[color=black,fill=white,size=3]
\tkzDefPoints{3/5/A,1/0/B,7/0/C}
\tkzDefMidPoint(B,C)\tkzGetPoint{M}
\tkzDrawAltitude[draw=red](A,B)(M)\tkzGetPoint{N}%Command here
\tkzDefPointBy[projection=onto B--C](A)\tkzGetPoint{H}
\tkzDrawSegments(A,B B,C C,A A,H)
\tkzDrawPoints(A,B,C,M,N,H)
\tkzLabelPoints[left](N)
\tkzLabelPoints[above](A)
\tkzLabelPoints[below](B,H,M,C)
\end{tikzpicture}
\end{center}
\section{Command (arg,arg,arg)}
\begin{center}
\begin{tikzpicture}
\tkzInit[ymin=-0.5,ymax=6.6,xmin=-0.5,xmax=7.5]
\tkzClip
\tkzSetUpPoint[color=black,fill=white,size=3]
\tkzDefPoints{3/5/A,1/0/B,7/0/C}
\tkzDefMidPoint(B,C)\tkzGetPoint{M}
\tkzDrawAltitude[draw=red](A,M,B)\tkzGetPoint{N}%Command here
\tkzDefPointBy[projection=onto B--C](A)\tkzGetPoint{H}
\tkzDrawSegments(A,B B,C C,A A,H)
\tkzDrawPoints(A,B,C,M,N,H)
\tkzLabelPoints[left](N)
\tkzLabelPoints[above](A)
\tkzLabelPoints[below](B,H,M,C)
\end{tikzpicture}
\end{center}
\end{document}
输出无[draw=red]
输出[draw=red]
答案2
\tkzDrawAltitude
也许计算第一个分隔参数中逗号分隔元素的数量)
并进行相应的分叉就足够了。
为了计算逗号列表的元素数量,您可以使用 expl3's \clist_count:n
。
\documentclass{article}
\usepackage{xparse}
\usepackage{tkz-euclide}[2020/03/18]
\ExplSyntaxOn
\NewExpandableDocumentCommand{\CommaListElementCount}{}{\clist_count:n}
\ExplSyntaxOff
\makeatletter
\renewcommand*\tkzDrawAltitude{\pgfutil@ifnextchar[{\tkz@Altitude}{\tkz@Altitude[]}}%
\renewcommand*\tkz@Altitude{}%
\def\tkz@Altitude[#1](#2){%
\ifnum\CommaListElementCount{#2}<3 %
\expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi
{\tkz@@Altitude}{\tkz@@@Altitude}[{#1}](#2)%
}%
\@ifdefinable\tkz@@Altitude{%
\def\tkz@@Altitude[#1](#2,#3)(#4){%
\begingroup
\tkzUProjection(#2,#3)(#4)%
\tkzDrawSLine[add= 0 and 0,/tkzdrawl/.cd,#1](#4,tkzPointResult)
\endgroup
}%
%Alternatively:
%\def\tkz@@Altitude[#1](#2,#3)(#4){\tkz@@@Altitude[{#1}]({#2},{#4},{#3})}%
}%
\@ifdefinable\tkz@@@Altitude{%
\def\tkz@@@Altitude[#1](#2,#3,#4){%
\begingroup
\tkzUProjection(#2,#4)(#3)
\tkzDrawSLine[add= 0 and 0,/tkzdrawl/.cd,#1](#3,tkzPointResult)
\endgroup
}%
}%
\makeatother
\begin{document}
\section{Command (arg,arg)(arg)}
\begin{center}
\begin{tikzpicture}
\tkzInit[ymin=-0.5,ymax=6.6,xmin=-0.5,xmax=7.5]
\tkzClip
\tkzSetUpPoint[color=black,fill=white,size=3]
\tkzDefPoints{3/5/A,1/0/B,7/0/C}
\tkzDefMidPoint(B,C)\tkzGetPoint{M}
\tkzDrawAltitude(A,B)(M)\tkzGetPoint{N}%Command here
\tkzDefPointBy[projection=onto B--C](A)\tkzGetPoint{H}
\tkzDrawSegments(A,B B,C C,A A,H)
\tkzDrawPoints(A,B,C,M,N,H)
\tkzLabelPoints[left](N)
\tkzLabelPoints[above](A)
\tkzLabelPoints[below](B,H,M,C)
\end{tikzpicture}
\end{center}
\section{Command (arg,arg,arg)}
\begin{center}
\begin{tikzpicture}
\tkzInit[ymin=-0.5,ymax=6.6,xmin=-0.5,xmax=7.5]
\tkzClip
\tkzSetUpPoint[color=black,fill=white,size=3]
\tkzDefPoints{3/5/A,1/0/B,7/0/C}
\tkzDefMidPoint(B,C)\tkzGetPoint{M}
\tkzDrawAltitude(A,M,B)\tkzGetPoint{N}%Command here
\tkzDefPointBy[projection=onto B--C](A)\tkzGetPoint{H}
\tkzDrawSegments(A,B B,C C,A A,H)
\tkzDrawPoints(A,B,C,M,N,H)
\tkzLabelPoints[left](N)
\tkzLabelPoints[above](A)
\tkzLabelPoints[below](B,H,M,C)
\end{tikzpicture}
\end{center}
\end{document}