quiver icon indicating copy to clipboard operation
quiver copied to clipboard

Bug with `curve` when distance is too small

Open drewheard opened this issue 1 year ago • 4 comments

The following looks rather horrible:

\documentclass{article} \usepackage{quiver} \usepackage{tikz-cd} \usepackage{amsmath} \usetikzlibrary{nfold} \DeclareMathOperator{\Spaces}{Spaces}

\usepackage[english]{babel}

% Set page size and margins % Replace letterpaper' with a4paper' for UK/EU standard size \usepackage[letterpaper,top=2cm,bottom=2cm,left=3cm,right=3cm,marginparwidth=1.75cm]{geometry}

% Useful packages \usepackage{amsmath} \usepackage{graphicx} \usepackage[colorlinks=true, allcolors=blue]{hyperref}

\title{Your Paper} \author{You}

\begin{document}

% https://q.uiver.app/#q=WzAsMixbMCwwLCJhIl0sWzEsMCwiYiJdLFsxLDAsImciLDAseyJjdXJ2ZSI6LTF9XSxbMCwxLCJmIiwwLHsiY3VydmUiOi0xfV0sWzMsMiwiIiwwLHsibGV2ZWwiOjEsInN0eWxlIjp7Im5hbWUiOiJhZGp1bmN0aW9uIn19XV0= [\begin{tikzcd}[ampersand replacement=&] {\Spaces} & {\Spaces_{\le n}} \arrow[""{name=0, anchor=center, inner sep=0}, "\Omega^n_+", curve={height=-6pt}, from=1-2, to=1-1] \arrow[""{name=1, anchor=center, inner sep=0}, "\Sigma^n_+", curve={height=-6pt}, from=1-1, to=1-2] \arrow["\dashv"{anchor=center, rotate=-90}, draw=none, from=1, to=0] \end{tikzcd}] \end{document}`

Presumably there is a bug in quiver.sty?

drewheard avatar Oct 08 '23 18:10 drewheard

Could you put your code in a code block, so I can copy it properly, and could you include a screenshot of what the diagram looks like for you?

varkor avatar Oct 10 '23 17:10 varkor

Sure.

\documentclass{article}
\usepackage{quiver}
\usepackage{tikz-cd}
\usepackage{amsmath}
\usetikzlibrary{nfold}
\DeclareMathOperator{\Spaces}{Spaces}

\usepackage[english]{babel}

% Set page size and margins
% Replace `letterpaper' with `a4paper' for UK/EU standard size
\usepackage[letterpaper,top=2cm,bottom=2cm,left=3cm,right=3cm,marginparwidth=1.75cm]{geometry}

% Useful packages
\usepackage{amsmath}
\usepackage{graphicx}
\usepackage[colorlinks=true, allcolors=blue]{hyperref}

\title{Your Paper}
\author{You}

\begin{document}

% https://q.uiver.app/#q=WzAsMixbMCwwLCJhIl0sWzEsMCwiYiJdLFsxLDAsImciLDAseyJjdXJ2ZSI6LTF9XSxbMCwxLCJmIiwwLHsiY3VydmUiOi0xfV0sWzMsMiwiIiwwLHsibGV2ZWwiOjEsInN0eWxlIjp7Im5hbWUiOiJhZGp1bmN0aW9uIn19XV0=
\[\begin{tikzcd}[ampersand replacement=\&]
	{\Spaces} \& {\Spaces_{\le n}}
	\arrow[""{name=0, anchor=center, inner sep=0}, "\Omega^n_+", curve={height=-6pt}, from=1-2, to=1-1]
	\arrow[""{name=1, anchor=center, inner sep=0}, "\Sigma^n_+", curve={height=-6pt}, from=1-1, to=1-2]
	\arrow["\dashv"{anchor=center, rotate=-90}, draw=none, from=1, to=0]
\end{tikzcd}\]
\end{document}

The output is as follows: Untitled

It can be fixed by making the spacer a little larger.

drewheard avatar Oct 10 '23 17:10 drewheard

@drewheard: thanks. Here's a minimised version of the issue:

\documentclass{article}
\usepackage{quiver}

\begin{document}

\[\begin{tikzcd}
	XXXXXXXXX & XXXXXXXXX
	\arrow[curve, from=1-1, to=1-2]
\end{tikzcd}\]

\end{document}

Produces: image This does look like an issue with the curve command in the quiver.sty package, thanks. I'll look into it.

For now, it can be addressed by increasing the spacing a little, as you pointed out.

varkor avatar Oct 10 '23 18:10 varkor

You can easily see where the bug is by drawing out the control points. (I mean assume you come up with how to draw the control points, which is not very trivial given you're limited to use a path specification. Use a colored node suffices.)

\tikzset{curve/.style={settings={#1},to path={
            node (__quiver_control1) at ($(\tikztostart)!\pv{pos}!(\tikztotarget)!\pv{height}!270:(\tikztotarget)$) [red, fill, circle, inner sep=1pt] {}
            node (__quiver_control2) at ($(\tikztostart)!1-\pv{pos}!(\tikztotarget)!\pv{height}!270:(\tikztotarget)$) [blue, fill, circle, inner sep=1pt] {}
            (\tikztostart)
    .. controls (__quiver_control1.center) and (__quiver_control2.center)
.. (\tikztotarget)\tikztonodes}}}

Looking at the result, the problem is that the partway modifier computes the distance between the center of the nodes, instead of between the arrow endpoints as it should.

The bug comes directly from the answer https://tex.stackexchange.com/questions/556893/curve-of-fixed-height-between-two-nodes-in-tikz-cd/556902#556902 .

The only way I can think of to compute the actual distance between two nodes is the following: (draw a line between two nodes, draw nodes, then retrieve coordinate of nodes)

%! TEX program = pdflatex
\documentclass{article}
\usepackage{quiver}

\begin{document}


% A TikZ style for curved arrows of a fixed height, due to AndréC.
\tikzset{curve/.style={settings={#1},to path={
      \pgfextra
        \edef\quiverTmpStart{\tikztostart}
        \edef\quiverTmpTarget{\tikztotarget}
	  	\begin{pgfinterruptpath}
			\draw[gray] (\quiverTmpStart) -- (\quiverTmpTarget)
			node (__quiver_p1) [at start, shape=coordinate] {}
			node (__quiver_p2) [at end, shape=coordinate] {}
			  ;
		\end{pgfinterruptpath}
      \endpgfextra
      (\tikztostart)
      .. controls ($(__quiver_p1)!\pv{pos}!(__quiver_p2)!\pv{height}!270:(__quiver_p2)$)
      and ($(__quiver_p1)!1-\pv{pos}!(__quiver_p2)!\pv{height}!270:(__quiver_p2)$)
    .. (\tikztotarget)\tikztonodes}
},
    settings/.code={\tikzset{quiver/.cd,#1}
        \def\pv##1{\pgfkeysvalueof{/tikz/quiver/##1}}},
    quiver/.cd,pos/.initial=0.35,height/.initial=0}

\[\begin{tikzcd}
	XXXX & XXXXXXXXX
    \arrow[curve={height=3pt}, from=1-1, to=1-2]
\end{tikzcd}\]

\end{document}

While it isn't necessary to copy the \tikztostart,\tikztotarget it seems safer to safeguard against future changes of the library.

Technically https://tex.stackexchange.com/questions/550153/how-to-get-the-length-of-an-arbitrary-path-in-tikz allows getting the length too. But that's not sufficient, we want to know what's the gap of each node.

Of course, in real code change \draw[gray] to \path.

Side note: if you zoom in enough you will see the arrow is not exactly symmetric. I think that's the right behavior anyway.

Or do you prefer this instead?

%! TEX program = pdflatex
\documentclass{article}
\usepackage{quiver}

\begin{document}


% A TikZ style for curved arrows of a fixed height, due to AndréC.
\tikzset{curve/.style={settings={#1},to path={
      \pgfextra
        \edef\quiverTmpStart{\tikztostart}
        \edef\quiverTmpTarget{\tikztotarget}
	  	\begin{pgfinterruptpath}
			\draw[gray] (\quiverTmpStart) -- (\quiverTmpTarget)
			node (__quiver_p1) [at start, shape=coordinate] {}
			node (__quiver_p2) [at end, shape=coordinate] {}
			  ;
		\end{pgfinterruptpath}
      \endpgfextra
      (__quiver_p1)
      .. controls ($(__quiver_p1)!\pv{pos}!(__quiver_p2)!\pv{height}!270:(__quiver_p2)$)
      and ($(__quiver_p1)!1-\pv{pos}!(__quiver_p2)!\pv{height}!270:(__quiver_p2)$)
    .. (__quiver_p2)\tikztonodes}
},
    settings/.code={\tikzset{quiver/.cd,#1}
        \def\pv##1{\pgfkeysvalueof{/tikz/quiver/##1}}},
    quiver/.cd,pos/.initial=0.35,height/.initial=0}

\[\begin{tikzcd}
	XXXX & XXXXXXXXX
    \arrow[curve={height=3pt}, from=1-1, to=1-2]
\end{tikzcd}\]

\end{document}

Side note: naming the style curve seems dangerous, as the user may inadvertently also define a style named curve and will be puzzled why quiver code break. Better name it quiver-curve or something (although that would breaks all backwards compatibility now?)

user202729 avatar May 01 '24 20:05 user202729