可換図で、ノードが自分自身を指す円で囲まれた矢印を描画したいと思います。これまでに実現できたのは次のようになります。
ループを実際の円のように見せる方法はありますか?
以下は MWE です。
\documentclass{article}
\usepackage{tikz-cd}
\begin{document}
\begin{tikzcd}[column sep=large]
C & D
\arrow["{F}", bend left = 30, from=1-1, to=1-2]
\arrow["{G}", bend left = 30, from=1-2, to=1-1]
\arrow[""{name=0, anchor=center, inner sep=0}, "{G} \,\circ\, {F}", from=1-1, to=1-1, out=-145, in=145, loop, distance=4em]
\arrow[""{name=1, anchor=center, inner sep=0}, "{F} \,\circ\, {G}", from=1-2, to=1-2, out=35, in=-35, loop, distance=4em]
\arrow["\theta", shorten <=3pt, shorten >=3pt, Rightarrow, from=0, to=1-1]
\arrow["\phi"', shorten <=3pt, shorten >=3pt, Rightarrow, from=1, to=1-2]
\end{tikzcd}
\end{document}
答え1
マニュアルのセクション 3.2 で説明されているようにtikz-cd
、 を使用してto path
パスを微調整できます。円弧の適切な開始角度と終了角度を見つけるには、ライブラリを使用してノードを測定しますcalc
。二重矢印も で描画されますto path
。これらのパスは、構築によって水平になります。エッジ ラベルを保持するには、 の\tikztonodes
引数に を追加する必要がありますto path
。
\documentclass{article}
\usepackage{tikz-cd}
\usetikzlibrary{calc}
\begin{document}
\def\myradius{1.5em}
\begin{tikzcd}[column sep=large]
C & D
\arrow["{F}", bend left = 30, from=1-1, to=1-2]
\arrow["{G}", bend left = 30, from=1-2, to=1-1]
\arrow["{G} \,\circ\, {F}","\mathstrut"{name=0, anchor=center, inner sep=0}, from=1-1, to=1-1,to path={%
let \p1=($(\tikztostart.north)-(\tikztostart.south)$),\n1={scalar(asin(0.5*\y1/\myradius))} in
(\tikztostart.south)arc[start angle=-\n1,end angle=-360+\n1,radius=\myradius]\tikztonodes (\tikztotarget)}]
\arrow["{F} \,\circ\, {G}","\mathstrut"{name=1, anchor=center, inner sep=0}, from=1-2, to=1-2,to path={%
let \p1=($(\tikztostart.north)-(\tikztostart.south)$),\n1={scalar(asin(0.5*\y1/\myradius))} in
(\tikztostart.north)arc[start angle=180-\n1,end angle=-180+\n1,radius=\myradius]\tikztonodes (\tikztotarget)}]
\arrow["\theta", shorten <=3pt, shorten >=3pt, Rightarrow, from=0, to=1-1, to path={(\tikztostart|-\tikztotarget) -- (\tikztotarget)\tikztonodes}]
\arrow["\phi"', shorten <=3pt, shorten >=3pt, Rightarrow, from=1, to=1-2, to path={(\tikztostart|-\tikztotarget) -- (\tikztotarget)\tikztonodes}]
\end{tikzcd}
\end{document}
答え2
以下は、受け入れられた回答から少し変更したバージョンです。水平矢印では、矢印を の高さで\tikztostart
はなくの高さに揃えて\tikztotarget
高くしました。ただし、矢印の終点を正しく取得するために、座標に 3pt の水平シフトを手動で追加しましたが、コードでは非常に見苦しく見えます。
\documentclass{article}
\usepackage{tikz-cd}
\usetikzlibrary{calc}
\begin{document}
\begin{tikzcd}[column sep=large]
C & D
\arrow["{F}", bend left = 30, from=1-1, to=1-2]
\arrow["{G}", bend left = 30, from=1-2, to=1-1]
\arrow["{G} \,\circ\, {F}","\mathstrut"{name=0, anchor=center, inner sep=0}, from=1-1, to=1-1,
to path={let \p1=($(\tikztostart.north)-(\tikztostart.south)$),\n1={scalar(asin(0.5*\y1/1.5em))} in
(\tikztostart.south) arc[start angle=-\n1,end angle=-360+\n1,radius=1.5em]\tikztonodes (\tikztotarget)}]
\arrow["{F} \,\circ\, {G}","\mathstrut"{name=1, anchor=center, inner sep=0}, from=1-2, to=1-2,
to path={let \p1=($(\tikztostart.north)-(\tikztostart.south)$),\n1={scalar(asin(0.5*\y1/1.5em))} in
(\tikztostart.north) arc[start angle=180-\n1,end angle=-180+\n1,radius=1.5em]\tikztonodes (\tikztotarget)}]
\arrow["\theta", shorten <=3pt, shorten >=3pt, Rightarrow, from=0, to=1-1, to path={(\tikztostart) -- ($(\tikztotarget|-\tikztostart)+(-3pt,0)$) \tikztonodes }]
\arrow["\phi"', shorten <=3pt, shorten >=3pt, Rightarrow, from=1, to=1-2, to path={(\tikztostart) -- ($(\tikztotarget|-\tikztostart)+(3pt,0)$) \tikztonodes }]
\end{tikzcd}
\end{document}
答え3
TikZ-CD はasymmetrical rectangle
、中心アンカーが実際の垂直中心ではなく、axis_height
ベースラインから一定の距離 ( ) 上にある を使用します。これにより、同じ行のノード間の矢印が数式モードの矢印のように描画されます。(これにより、矢印は常に水平になります。)
このコードでは、円セグメントは開始点の中心を通るように(北または南のアンカーに触れないように)描画されます。このために、ライブラリspath3
とintersections
ライブラリが使用されます。水平/垂直以外の方向に対してこれを数学的に実行するには、理解したいとは思えないほど多くの計算が必要になります。技術的には、spath3
ライブラリは開始ノード内にある円セグメントを削除するためだけに使用され、適切な開始角度と終了角度は交差点を知ることで決定できます。
スタイルを使用するために、TikZ-CD に 2 つの方法を追加しましたcircle around rect node
。
circle = <padding>
(<padding>
デフォルトは.5ex
、TikZ-CD のノードの inenr seps のおよそ半分)パディングがゼロの場合、円がターゲット座標/ノードにちょうど接触するように半径が決定されます。
circle to = <angle>
開始座標の周囲に、方向を指し<angle>
、直径 の円を描きますcircle to distance
。
コード
\documentclass[tikz]{standalone}
\usepackage{tikz-cd}
\usetikzlibrary{calc, intersections, spath3}
\tikzset{
circle around rect node/.style n args={3}{insert path={%
% #1 = node name, #2 = angle, #3 = distance
(#1.center) edge[
path only, spath/save global=carn@circle,
to path={arc[start angle={(180-(#2))}, delta angle=360, radius={(#3)/2}]}](#1)
(#1.south west) edge[
path only, spath/save global=carn@rect,
to path={rectangle(\tikztotarget)}](#1.north east)
[spath/.cd,
split at intersections with={carn@circle}{carn@rect},
remove components={carn@circle}{1,3},
use=carn@circle]}}}
\tikzcdset{
circle to distance/.initial=3em,
circle to/.style={to path={
[circle around rect node/.expanded={\tikztostart}{#1}
{\pgfkeysvalueof{/tikz/commutative diagrams/circle to distance}}]
\tikztonodes}},
circle/.default=.5ex,
circle/.style={
execute at begin to={%
\path[path only](\tikztostart)
--coordinate[at end](tikzcd@circleend)(\tikztotarget);},
to path={
let \p{tikzcd@diff} = ($(tikzcd@circleend)-(\tikztostart)$) in
[circle around rect node/.expanded={\tikztostart}
{atan2(\y{tikzcd@diff},\x{tikzcd@diff})}
{veclen(\p{tikzcd@diff})+(#1)}]
\tikztonodes}}}
\tikzset{
cd/.code=\tikzcdset{#1},
cd node/.style={font=,cd=every cell,name={#1}}}
\begin{document}
\begin{tikzcd}[
column sep=large, bend angle=30,
% /tikz/column 1/.append style={cd={column sep=normal}},
% /tikz/column 3/.append style={cd={column sep=normal}},
]
G \circ F \arrow[r, "\theta", Rightarrow]
& C \arrow[r, "F", bend left]
\arrow[l, circle]
& D \arrow[l, "G", bend left]
\arrow[r, circle]
& F \circ G \arrow[l, "\phi"', Rightarrow]
\end{tikzcd}
\begin{tikzcd}[column sep=large, bend angle=30]
C \arrow[r, "F", bend left]
\arrow[circle to=180, "G \circ F"' cd node=GF]
\arrow[Rightarrow, shorten <=.8ex, from=GF, "\theta"]
& D \arrow[l, "G", bend left]
\arrow[circle to= 0, "F \circ G"' cd node=FG]
\arrow[Rightarrow, shorten <=.8ex, from=FG, "\phi"']
\end{tikzcd}
\begin{tikzpicture}
\node[draw] (A) {A};
\foreach[count=\i] \ang in {0, 45, ..., 359}
\draw[red!\i0!blue, circle around rect node={A}{\ang}{1cm}];
\end{tikzpicture}
\end{document}