最初は、これはPDFビューアの問題だと思いました。たとえば、コード
\documentclass{article}
\usepackage{tikz-cd}
\begin{document}
\begin{tikzcd}
A & B
\arrow[Rightarrow, from=1-1, to=1-2]
\end{tikzcd}
\end{document}
結果にはRightarrow
2 本の小さな余分な灰色の線が含まれているようです。
この問題は、この質問数か月前、著者はnRightarrow
問題を解決したと思われる複雑な新しいスタイルを提供しました (Rightarrow
上、nRightarrow
下):
しかし、この新しいスタイルの必要性はnRightarrow
、主に他のより複雑な問題から生じているようです。そこで、この 2 本の余分な灰色の線の問題に関して、現在までにもっと簡単な解決策が存在するかどうかを知りたいのです。
nRightarrow
以下は、リンクされた質問からコードをコピーした MWE です。
\documentclass{article}
\usepackage{tikz-cd}
\usetikzlibrary{calc}
\newlength{\eqoffset}
\makeatletter
% relative coordinates: (0,0) is the arrow's tail, x points towards the head,
% y points perpendicular, unit distance is \eqoffset
\newcommand{\relptstart}[2]{($($(k0)!#1*\eqoffset+\pgf@shorten@start@additional!0:(k1)$)!#2*\eqoffset!90:(k1)$)}
% (0,0) is the arrow's tip, rest is the same
\newcommand{\relptend}[2]{($($(k1)!#1*\eqoffset-\pgf@shorten@end@additional
-2*\eqoffset-.5*\pgflinewidth!180:(k0)$)!#2*\eqoffset!-90:(k0)$)}
\tikzcdset{
nRightarrow/.style={line join=round,
no head,
/tikz/commutative diagrams/@shiftabletopath,
execute at begin to = {
% Do not use tikzcd@noda or tikzcd@x here, it causes interference.
% Use new names instead
\path (\tikztostart) -- (\tikztotarget) coordinate[pos=0] (k0) coordinate[pos=1] (k1);
\pgfpointnormalised{\pgfpointdiff{\pgfpointanchor{k1}{center}}{\pgfpointanchor{k0}{center}}}
\pgfgetlastxy{\kdx}{\kdy}
\tikzset{
to path={
% arrow body
% the .06 is from \pgftransformxshift{.06\pgfutil@tempdima}
\relptstart{0}{1}
-- \relptend{-.06}{1}
{
% correct vertical position, more central horizontal position
% [xshift=-\kdy*\eqoffset, yshift=\kdx*\eqoffset]
% matches original Rightarrow more closely
[xshift=-\kdy*\eqoffset-\kdx*(\eqoffset+.25*\pgflinewidth),
yshift=\kdx*\eqoffset-\kdy*(\eqoffset+.25*\pgflinewidth)]
\tikztonodes}
\relptstart{0}{-1}
-- \relptend{-.06}{-1}
% arrow tip
% fake the round cap by using round joins and drawing the path twice with a turnaround at the caps
\relptend{2}{0} % tip to top end
.. controls \relptend{1}{0.05} and \relptend{-0.75}{1.25} ..
\relptend{-1.4}{2.65} % top end back to tip
.. controls \relptend{-0.75}{1.25} and \relptend{1}{0.05} ..
\relptend{2}{0} % tip to bottom end
.. controls \relptend{1}{-0.05} and \relptend{-0.75}{-1.25} ..
\relptend{-1.4}{-2.65} % bottom end back to tip
.. controls \relptend{-0.75}{-1.25} and \relptend{1}{-0.05} ..
\relptend{2}{0}
% Add a degenerate path segment at the end so shorten < and shorten > are not applied again
(k1)
}}
}}
}
\setlength{\eqoffset}{.225ex}
\makeatother
\begin{document}
\begin{tikzcd}[column sep=large]
A & B
\arrow[Rightarrow, from=1-1, to=1-2]
\end{tikzcd}
\begin{tikzcd}[column sep=large]
A & B
\arrow[nRightarrow, from=1-1, to=1-2]
\end{tikzcd}
\end{document}
答え1
リンクされた質問は長い議論TikZ-CDの作者と平行線の再実装方法について話し合いました。コードはほとんどPGFレベルで終了。
PGFが線を描く方法を再実装する代わりに、 PGFが線double
を描く方法を少し変更する方法の概念実証を次に示します。double
- 内側の線を長くすることで
- または外側の線を短くすることによっても行えます。
これは完璧とは程遠いが、
- 直線
- 1つのセグメント(開始時に1回の移動のみ)で構成される。
- 破線ではなく、通常の
rect
線端を使用します。
さらに、矢印が描画されたノードに触れないようにするのが最適です。
このspath3
ライブラリは、曲線を歪ませることなく短縮/短縮解除するのに役立ち、また、複数のセグメントを持つパスにこれを適用するのにも役立ちます。
コード
\documentclass[tikz]{standalone}
\usepackage{tikz-cd}
\makeatletter
\def\pgf@double@cheat#1{%
\let\pgf@tips@mode\pgf@tips@mode@false
\pgfsetarrowsstart{}\pgfsetarrowsend{}%
\pgfsetshortenstart{#1}\pgfsetshortenend{#1}%
\pgf@prepare@end@of@path\pgf@prepare@start@of@path}
\pgfset{
shorten outer/.code=%
\pgfmathsetlength\pgfutil@tempdima{#1}%
\pgfkeyssetevalue{/pgf/shorten outer}{\the\pgfutil@tempdima},
shorten outer=+0pt,
unshorten inner/.code=%
\pgfmathsetlength\pgfutil@tempdima{#1}%
\pgfkeyssetevalue{/pgf/unshorten inner}{\the\pgfutil@tempdima},
unshorten inner=+0pt}
\usepackage{etoolbox}
\patchcmd{\pgf@stroke@inner@line}{\pgfsyssoftpath@invokecurrentpath}{%
\ifdim\pgfkeysvalueof{/pgf/unshorten inner}>0pt
\pgf@double@cheat{-\pgfkeysvalueof{/pgf/unshorten inner}}%
\fi\pgfsyssoftpath@invokecurrentpath}{}{\PatchFailed}
\patchcmd{\pgfusepath}{\fi\pgfsyssoftpath@invokecurrentpath\pgf@up@action}{%
\fi \ifdim\pgfinnerlinewidth>0pt
\ifdim\pgfkeysvalueof{/pgf/shorten outer}>0pt
\pgfgetpath\pgf@temppath
\pgf@double@cheat{\pgfkeysvalueof{/pgf/shorten outer}}\fi\fi
\pgfsyssoftpath@invokecurrentpath%
\ifdim\pgfinnerlinewidth>0pt
\ifdim\pgfkeysvalueof{/pgf/shorten outer}>0pt
\pgfsetpath\pgf@temppath\fi\fi\pgf@up@action}{}{\PatchFailed}
\makeatother
\newcommand*\everycell[1]{%
\draw[cd=Rightarrow,#1]node(A){$A$}node(B)at(2,0){$B$}(A)to(B);}
\begin{document}
\tikz[
cd/.code=\tikzcdset{#1}, anchor=base,
cd dbl/.style={cd={background color=green}},
cells={nodes={behind path, help lines, draw, shape=asymmetrical rectangle}},
column 1/.append style={anchor=base west, nodes=path only},
rows/.style args={#1 => #2}{row #1/.append style={#2}},
rows/.list={2 => unshorten inner = .05pt,
3 => shorten outer = .05pt,
4 => {cd dbl=green, unshorten inner = 2pt},
5 => {cd dbl=green, shorten outer = 2pt}}
]\matrix[column sep=\tabcolsep]{
\node{normal:}; & \everycell{} & \everycell{bend left} \\
\node{inner:}; & \everycell{} & \everycell{bend left} \\
\node{outer:}; & \everycell{} & \everycell{bend left} \\
\node{extreme inner:}; & \everycell{} & \everycell{bend left} \\
\node{extreme outer:}; & \everycell{} & \everycell{bend left} \\};
\begin{tikzcd}[unshorten inner=+0.01pt]
A & B
\arrow[Rightarrow, from=1-1, to=1-2]
\end{tikzcd}
\end{document}
出力
この場合は、自分でコンパイルして、さまざまなズーム レベルとさまざまな PDF ビューア/レンダラーで出力を確認するのが最適です。ただし、最初の 2 つの画像をクリックすると、拡大版を表示できます。
答え2
私が書いたtikz-nfold具体的には、この問題を解決するために:
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{cd}
\usetikzlibrary{nfold}
\begin{document}
\begin{tikzcd}
A & B
\arrow[Rightarrow, from=1-1, to=1-2, nfold]
\end{tikzcd}
\end{document}
ちなみに、tikz-cd
最近私に知らせたこれは\usepackage{tikz-cd}
レガシー機能ですが、使用しても問題はありません。