Zeichnen Sie in tikz-cd einen kreisförmigen Pfad zu einem Knoten selbst

Zeichnen Sie in tikz-cd einen kreisförmigen Pfad zu einem Knoten selbst

Ich möchte in einem kommutativen Diagramm einen eingekreisten Pfeil eines Knotens zeichnen, der auf sich selbst zeigt. Was ich bisher erreichen konnte, sieht wie folgt aus:

Bildbeschreibung hier eingeben

Gibt es eine Möglichkeit, die Schleifen einem echten Kreis ähnlich aussehen zu lassen?

Unten ist ein 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}

Antwort1

Wie im Abschnitt 3.2 des tikz-cdHandbuchs erklärt, kann man to pathmit Pfade optimieren. Um den passenden Start- und Endwinkel des Bogens zu finden, kann man den Knoten mit der calcBibliothek ausmessen. Die Doppelpfeile werden ebenfalls über gezeichnet to path. Diese Pfade sind durch Konstruktionen horizontal. Um die Kantenbeschriftungen beizubehalten, muss man \tikztonodesdem Argument von hinzufügen 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}

Bildbeschreibung hier eingeben

Antwort2

Unten finden Sie eine Version, die gegenüber der akzeptierten Antwort leicht abgeändert wurde. Bei den horizontalen Pfeilen habe ich den Pfeil mit der Höhe von ausgerichtet, \tikztostartanstatt \tikztotargetihn höher zu machen. Um jedoch den Endpunkt des Pfeils richtig zu erhalten, habe ich der Koordinate manuell eine horizontale Verschiebung von 3pt hinzugefügt, was im Code ziemlich hässlich aussieht.

Bildbeschreibung hier eingeben

\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}

Antwort3

TikZ-CD verwendet das asymmetrical rectangle, dessen Mittelpunktsanker nicht in der tatsächlichen vertikalen Mitte, sondern in einem festen Abstand ( axis_height) über der Grundlinie liegt, sodass Pfeile zwischen Knoten derselben Zeile wie Pfeile im Mathematikmodus gezeichnet werden. (Dies führt auch dazu, dass sie immer horizontal sind.)

In diesem Code wird das Kreissegment so gezeichnet, dass es durch die Mitte des Starts verläuft (und den Nord- oder Südanker nicht berührt). Hierzu werden die spath3und die intersectionsBibliotheken verwendet. Dies mathematisch für jede andere Richtung als horizontal/vertikal zu tun, erfordert zu viel Mathematik, als dass ich das herausfinden möchte. Technisch gesehen spath3wird die Bibliothek nur verwendet, um das Kreissegment zu entfernen, das innerhalb des Startknotens liegt. Die entsprechenden Start- und Endwinkel hätten durch Kenntnis der Schnittpunkte bestimmt werden können.

Ich habe TikZ-CD zwei Möglichkeiten zur Verwendung des Stils hinzugefügt circle around rect node:

  1. circle = <padding>( <padding>Standardwert .5ex: ungefähr die Hälfte der inenr-Sekunden der Knoten in einer TikZ-CD)

    Wenn die Polsterung Null wäre, wird der Radius so bestimmt, dass der Kreis die Zielkoordinate/den Zielknoten gerade berühren würde.

  2. circle to = <angle>zeichnet einen Kreis um die Startkoordinate, der in die Richtung „zeigt“ <angle>und den Durchmesser hat circle to distance.

Code

\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}

Ausgabe

Bildbeschreibung hier eingeben

Bildbeschreibung hier eingeben

verwandte Informationen