tikz-cd에서 노드 자체에 대한 원 경로 그리기

tikz-cd에서 노드 자체에 대한 원 경로 그리기

교환 다이어그램에서 자신을 가리키는 노드의 원 화살표를 그리고 싶습니다. 지금까지 달성할 수 있었던 것은 다음과 같습니다.

여기에 이미지 설명을 입력하세요

루프를 실제 원처럼 보이게 만드는 방법이 있나요?

아래는 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기준선 위의 고정 거리( )에 있는 를 사용하여 같은 행의 노드 사이의 화살표가 수학 모드 화살표처럼 그려집니다. (이로 인해 항상 수평이 됩니다.)

이 코드에서는 원형 세그먼트가 시작 지점의 중심을 통과하도록 그려집니다(북쪽 또는 남쪽 앵커에 닿지 않음). 이를 위해 spath3intersections라이브러리가 사용됩니다. 수평/수직 이외의 방향에 대해 수학적으로 이 작업을 수행하려면 수학이 너무 많아서 그것을 파악하고 싶지 않습니다. 기술적으로 spath3라이브러리는 시작 노드 내부에 있는 원의 세그먼트를 제거하는 데만 사용되며, 적절한 시작 및 끝 각도는 교차점을 알면 결정될 수 있습니다.

스타일을 사용하기 위해 TikZ-CD에 두 가지 방법을 추가했습니다 circle around rect node.

  1. circle = <padding>( <padding>기본값은 .5exTikZ-CD에 있는 노드의 내부 간격의 대략 절반입니다.)

    패딩이 0이면 원이 대상 좌표/노드에 닿는 방식으로 반경이 결정됩니다.

  2. 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}

산출

여기에 이미지 설명을 입력하세요

여기에 이미지 설명을 입력하세요

관련 정보