교환 다이어그램에서 자신을 가리키는 노드의 원 화살표를 그리고 싶습니다. 지금까지 달성할 수 있었던 것은 다음과 같습니다.
루프를 실제 원처럼 보이게 만드는 방법이 있나요?
아래는 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에 두 가지 방법을 추가했습니다 circle around rect node
.
circle = <padding>
(<padding>
기본값은.5ex
TikZ-CD에 있는 노드의 내부 간격의 대략 절반입니다.)패딩이 0이면 원이 대상 좌표/노드에 닿는 방식으로 반경이 결정됩니다.
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}