也就是说,我想创建一个带有六个参数的命令:一个端点P
、一个水平距离a
、一个垂直距离b
、一个水平方向(左或右)、一个垂直方向(上或下),最后是一个位置(线段的上方或下方),然后绘制相应的圆。2x2x2=8
可能的圆弧如下图所示:
这八个圆弧中的每一条都可以用 TikZarc
构造直接实现;半径为\frac{a^2+b^2}{2b}
,并且对于角度有以下对应表(其中\theta
为acos(\frac{2ab}{a^2+b^2})
):
使用 Qrrbrbirlbel 对上述问题之一的回答,很容易为这八种情况中的每一种构建一个临时命令,例如
\tikzset{
rightupabovechord/.style args={#1:#2}{
/utils/exec=%
\pgfmathsetmacro\myTempVal{(#1)*(#1)/(#2)/2+(#2)/2}%
\ifpgfmathunitsdeclared\edef\myTempVal{\myTempVal pt}\fi
\pgfmathsetmacro\myTempAng{acos(2*(#1)*(#2)/((#1)*(#1)+(#2)*(#2)))},
radius=\myTempVal, start angle=180-\myTempAng, end angle=90},
rightupaboveafro/.style={insert path={arc[rightupabovechord={#1}]}},
rightupabovechord a/.initial=, rightupabovechord b/.initial=,
rightupabovechord do/.style={rightupabovechord={\pgfkeysvalueof{/tikz/rightupabovechord a}:\pgfkeysvalueof{/tikz/rightupabovechord b}}},
}
我也可以复制粘贴上述 8 次,然后针对每种情况重写命令,但这肯定是不好的做法,而且浪费时间。如何推广上述命令以涵盖所有情况?我唯一知道的是args={#1:#2}
应该替换为args={#1:#2:#3:#4:#5}
,并且里面的代码/utils/exec
应该包含几个\if
。此时我陷入困境。
任何帮助均感激不尽。
为了回答下面的评论,这里是该问题的完整 LaTeX 源文件:
\documentclass{article}
\usepackage{tikz}
\tikzset{
leftdownbelowchord/.style args={#1:#2}{
/utils/exec=%
\pgfmathsetmacro\myTempVal{(#1)*(#1)/(#2)/2+(#2)/2}%
\ifpgfmathunitsdeclared\edef\myTempVal{\myTempVal pt}\fi
\pgfmathsetmacro\myTempAng{acos(2*(#1)*(#2)/((#1)*(#1)+(#2)*(#2)))},
radius=\myTempVal, start angle=360-\myTempAng, end angle=270},
leftdownbelowafro/.style={insert path={arc[leftdownbelowchord={#1}]}},
leftdownbelowchord a/.initial=, leftdownbelowchord b/.initial=,
leftdownbelowchord do/.style={leftdownbelowchord={\pgfkeysvalueof{/tikz/leftdownbelowchord a}:\pgfkeysvalueof{/tikz/leftdownbelowchord b}}},
}
\tikzset{
leftdownabovechord/.style args={#1:#2}{
/utils/exec=%
\pgfmathsetmacro\myTempVal{(#1)*(#1)/(#2)/2+(#2)/2}%
\ifpgfmathunitsdeclared\edef\myTempVal{\myTempVal pt}\fi
\pgfmathsetmacro\myTempAng{acos(2*(#1)*(#2)/((#1)*(#1)+(#2)*(#2)))},
radius=\myTempVal, start angle=90, end angle=180-\myTempAng},
leftdownaboveafro/.style={insert path={arc[leftdownabovechord={#1}]}},
leftdownabovechord a/.initial=, leftdownabovechord b/.initial=,
leftdownabovechord do/.style={leftdownabovechord={\pgfkeysvalueof{/tikz/leftdownabovechord a}:\pgfkeysvalueof{/tikz/leftdownabovechord b}}},
}
\tikzset{
leftupbelowchord/.style args={#1:#2}{
/utils/exec=%
\pgfmathsetmacro\myTempVal{(#1)*(#1)/(#2)/2+(#2)/2}%
\ifpgfmathunitsdeclared\edef\myTempVal{\myTempVal pt}\fi
\pgfmathsetmacro\myTempAng{acos(2*(#1)*(#2)/((#1)*(#1)+(#2)*(#2)))},
radius=\myTempVal, start angle=270, end angle=180+\myTempAng},
leftupbelowafro/.style={insert path={arc[leftupbelowchord={#1}]}},
leftupbelowchord a/.initial=, leftupbelowchord b/.initial=,
leftupbelowchord do/.style={leftupbelowchord={\pgfkeysvalueof{/tikz/leftupbelowchord a}:\pgfkeysvalueof{/tikz/leftupbelowchord b}}},
}
\tikzset{
leftupabovechord/.style args={#1:#2}{
/utils/exec=%
\pgfmathsetmacro\myTempVal{(#1)*(#1)/(#2)/2+(#2)/2}%
\ifpgfmathunitsdeclared\edef\myTempVal{\myTempVal pt}\fi
\pgfmathsetmacro\myTempAng{acos(2*(#1)*(#2)/((#1)*(#1)+(#2)*(#2)))},
radius=\myTempVal, start angle=\myTempAng, end angle=90},
leftupaboveafro/.style={insert path={arc[leftupabovechord={#1}]}},
leftupabovechord a/.initial=, leftupabovechord b/.initial=,
leftupabovechord do/.style={leftupabovechord={\pgfkeysvalueof{/tikz/leftupabovechord a}:\pgfkeysvalueof{/tikz/leftupabovechord b}}},
}
\tikzset{
rightdownbelowchord/.style args={#1:#2}{
/utils/exec=%
\pgfmathsetmacro\myTempVal{(#1)*(#1)/(#2)/2+(#2)/2}%
\ifpgfmathunitsdeclared\edef\myTempVal{\myTempVal pt}\fi
\pgfmathsetmacro\myTempAng{acos(2*(#1)*(#2)/((#1)*(#1)+(#2)*(#2)))},
radius=\myTempVal, start angle=180+\myTempAng, end angle=270},
rightdownbelowafro/.style={insert path={arc[rightdownbelowchord={#1}]}},
rightdownbelowchord a/.initial=, rightdownbelowchord b/.initial=,
rightdownbelowchord do/.style={rightdownbelowchord={\pgfkeysvalueof{/tikz/rightdownbelowchord a}:\pgfkeysvalueof{/tikz/rightdownbelowchord b}}},
}
\tikzset{
rightdownabovechord/.style args={#1:#2}{
/utils/exec=%
\pgfmathsetmacro\myTempVal{(#1)*(#1)/(#2)/2+(#2)/2}%
\ifpgfmathunitsdeclared\edef\myTempVal{\myTempVal pt}\fi
\pgfmathsetmacro\myTempAng{acos(2*(#1)*(#2)/((#1)*(#1)+(#2)*(#2)))},
radius=\myTempVal, start angle=90, end angle=\myTempAng},
rightdownaboveafro/.style={insert path={arc[rightdownabovechord={#1}]}},
rightdownabovechord a/.initial=, rightdownabovechord b/.initial=,
rightdownabovechord do/.style={rightdownabovechord={\pgfkeysvalueof{/tikz/rightdownabovechord a}:\pgfkeysvalueof{/tikz/rightdownabovechord b}}},
}
\tikzset{
rightupbelowchord/.style args={#1:#2}{
/utils/exec=%
\pgfmathsetmacro\myTempVal{(#1)*(#1)/(#2)/2+(#2)/2}%
\ifpgfmathunitsdeclared\edef\myTempVal{\myTempVal pt}\fi
\pgfmathsetmacro\myTempAng{acos(2*(#1)*(#2)/((#1)*(#1)+(#2)*(#2)))},
radius=\myTempVal, start angle=270, end angle=360-\myTempAng},
rightupbelowafro/.style={insert path={arc[rightupbelowchord={#1}]}},
rightupbelowchord a/.initial=, rightupbelowchord b/.initial=,
rightupbelowchord do/.style={rightupbelowchord={\pgfkeysvalueof{/tikz/rightupbelowchord a}:\pgfkeysvalueof{/tikz/rightupbelowchord b}}},
}
\tikzset{
rightupabovechord/.style args={#1:#2}{
/utils/exec=%
\pgfmathsetmacro\myTempVal{(#1)*(#1)/(#2)/2+(#2)/2}%
\ifpgfmathunitsdeclared\edef\myTempVal{\myTempVal pt}\fi
\pgfmathsetmacro\myTempAng{acos(2*(#1)*(#2)/((#1)*(#1)+(#2)*(#2)))},
radius=\myTempVal, start angle=180-\myTempAng, end angle=90},
rightupaboveafro/.style={insert path={arc[rightupabovechord={#1}]}},
rightupabovechord a/.initial=, rightupabovechord b/.initial=,
rightupabovechord do/.style={rightupabovechord={\pgfkeysvalueof{/tikz/rightupabovechord a}:\pgfkeysvalueof{/tikz/rightupabovechord b}}},
}
\begin{document}
\bigskip
\begin{tikzpicture}
\path (2cm,1cm) coordinate (P);
\path (P) node[anchor=north] {$P$};
\draw (P) node {$\bullet$};
\draw [->] (P) -- ++(3cm,0);
\draw [->] (P) -- ++(-3cm,0);
\draw [->] (P)++(3cm,0) -- ++(0,1cm);
\draw [->] (P)++(3cm,0) -- ++(0,-1cm);
\draw [->] (P)++(-3cm,0) -- ++(0,1cm);
\draw [->] (P)++(-3cm,0) -- ++(0,-1cm);
\path (P)++(2cm,0) node[anchor=south] {$a$};
\path (P)++(-2cm,0) node[anchor=south] {$a$};
\path (P)++(3cm,0.5cm) node[anchor=west] {$b$};
\path (P)++(3cm,-0.5cm) node[anchor=west] {$b$};
\path (P)++(-3cm,0.5cm) node[anchor=east] {$b$};
\path (P)++(-3cm,-0.5cm) node[anchor=east] {$b$};
\draw[blue,->] (P) [leftupbelowafro=3cm:1cm];
\draw[red,->] (P) [rightupbelowafro=3cm:1cm];
\draw[yellow,->] (P) [rightdownbelowafro=3cm:1cm];
\draw[green,->] (P) [leftdownbelowafro=3cm:1cm];
\draw (P)++(0,1.5cm) node {Arcs below};
\path (9cm,1cm) coordinate (Q);
\path (Q) node[anchor=north] {$P$};
\draw (Q) node {$\bullet$};
\draw [->] (Q) -- ++(3cm,0);
\draw [->] (Q) -- ++(-3cm,0);
\draw [->] (Q)++(3cm,0) -- ++(0,1cm);
\draw [->] (Q)++(3cm,0) -- ++(0,-1cm);
\draw [->] (Q)++(-3cm,0) -- ++(0,1cm);
\draw [->] (Q)++(-3cm,0) -- ++(0,-1cm);
\path (Q)++(2cm,0) node[anchor=south] {$a$};
\path (Q)++(-2cm,0) node[anchor=south] {$a$};
\path (Q)++(3cm,0.5cm) node[anchor=west] {$b$};
\path (Q)++(3cm,-0.5cm) node[anchor=west] {$b$};
\path (Q)++(-3cm,0.5cm) node[anchor=east] {$b$};
\path (Q)++(-3cm,-0.5cm) node[anchor=east] {$b$};
\draw[blue,->] (Q) [leftupaboveafro=3cm:1cm];
\draw[red,->] (Q) [rightupaboveafro=3cm:1cm];
\draw[yellow,->] (Q) [rightdownaboveafro=3cm:1cm];
\draw[green,->] (Q) [leftdownaboveafro=3cm:1cm];
\draw (Q)++(0,1.5cm) node {Arcs above};
\end{tikzpicture}
\bigskip
\begin{tabular}{|c|c|c|c|c|}
\hline
Horizontal direction & Vertical direction & Position & Start angle & End angle \\
\hline
Left & Down & Below &$360-\theta$ & $270$ \\
\hline
Left & Down & Above & $90$ & $180-\theta$ \\
\hline
Left & Up & Below & $270$ & $180+\theta$ \\
\hline
Left & Up & Above & $\theta$ & $90$ \\
\hline
Right & Down & Below & $180+\theta$ & $270$ \\
\hline
Right & Down & Above & $90$ & $\theta$ \\
\hline
Right & Up & Below & $270$ & $360-\theta$ \\
\hline
Right & Up & Above & $180-\theta$ & $90$ \\
\hline
\end{tabular}
\end{document}
答案1
不完全是所需的,但差不多:
\documentclass[tikz,border=5]{standalone}
\usetikzlibrary{calc}
\tikzset{afro to/.style={to path={
let \p1=($(\tikztotarget)-(\tikztostart)$),
\n1={(\x1*\x1+\y1*\y1)/(2*\y1)},
\n2={acos((2*\x1*\y1)/(\x1*\x1+\y1*\y1))},
\n3={atan2(\y1,\x1)},
\n3={int((\n3<0?\n3+360:\n3)/90)} in (\tikztostart) [afro #1]
}},
afro above/.style={insert path={
\ifdim\n3<2pt arc (180-\n2:90:\n1) \else arc (270:360-\n2:\n1) \fi
}},
afro below/.style={insert path={
\ifdim\n3<2pt arc (270:360-\n2:\n1) \else arc (180-\n2:90:\n1) \fi
}}}
\begin{document}
\begin{tikzpicture}
\draw [help lines] (-2cm,0) -- (2cm,0) (0,-1cm) -- (0,1cm);
\draw [red] (0,0) to [afro to=above] ( 2, 1);
\draw [green] (0,0) to [afro to=above] (-2, 1);
\draw [blue] (0,0) to [afro to=above] (-2,-1);
\draw [black] (0,0) to [afro to=above] ( 2,-1);
\draw [red, dashed] (0,0) to [afro to=below] ( 2, 1);
\draw [green, dashed] (0,0) to [afro to=below] (-2, 1);
\draw [blue, dashed] (0,0) to [afro to=below] (-2,-1);
\draw [black, dashed] (0,0) to [afro to=below] ( 2,-1);
\end{tikzpicture}
\end{document}