如何创建两个具有相同名称但参数数量和样式不同的命令

如何创建两个具有相同名称但参数数量和样式不同的命令

我想定义一个名称相同但参数数量不同的命令。我希望调用 \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}

在此处输入图片描述

相关内容