loopspace / spath3

TikZ/PGF package for manipulating soft paths, includes the knots and calligraphy TikZ libraries.
16 stars 2 forks source link

tikz line that connects nodes is shorter when using `\strand` (knots tikz library) instead of `\draw` #22

Closed Andrew15-5 closed 1 year ago

Andrew15-5 commented 1 year ago

I've minimized my usage as much as I could, so here is MWE:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{knots,arrows.meta}
\def\samecode{
  \node[draw] (a) at (0,0) {a};
  \node[draw] (b) at (1,0) {b};
  \draw[arrow, red] (a.east) -- (b.west);
}
\begin{document}
\begin{tikzpicture}[arrow/.style={->}]
  \samecode
  \begin{knot}
    % Strand shortened the line by ~0.4pt
    \strand[arrow] (a.east) -- ([xshift=0.4pt] b.west);
  \end{knot}
\end{tikzpicture}

\begin{tikzpicture}[arrow/.style={-Triangle}]
  \samecode
  \begin{knot}
    % Strand shortened the line by ~3.48pt
    \strand[arrow] (a.east) -- ([xshift=3.48pt] b.west);
  \end{knot}
\end{tikzpicture}
\end{document}

Output (red arrow lines are under the white ones): image

Andrew15-5 commented 1 year ago

TeX Live 2022:

pdflatex -version:

pdfTeX 3.141592653-2.6-1.40.24 (TeX Live 2022)
kpathsea version 6.3.4

lualatex -version:

This is LuaHBTeX, Version 1.15.0 (TeX Live 2022)
Development id: 7509

I've also run (same result):

cd /tmp
git clone https://github.com/loopspace/spath3.git
cd spath3
tex spath3_code.dtx
lualatex file.tex
pdflatex file.tex
loopspace commented 1 year ago

My initial thought is that the shortening of the path that is needed to avoid the path overrunning the arrow tip is being applied twice. If so, the fix is to use the only when rendering key for the arrow specification. I'll test when I can and get back to you.

Thanks for using the library! Always nice to see it being used.

Andrew15-5 commented 1 year ago

Adding strand arrow/.style={only when rendering/.style={arrow}} option to tikzpicture environment and strand arrow option to \strand fixes the problem (white/black arrow fully covers the red one):

...
\begin{tikzpicture}[arrow/.style={-Triangle},
  strand arrow/.style={only when rendering/.style={arrow}}]
  \samecode
  \begin{knot}
    \strand[strand arrow] (a.east) -- (b.west);
  \end{knot}
\end{tikzpicture}
...
Andrew15-5 commented 1 year ago

Can you provide a working example of something like this (if this even possible with tikz):

\begin{tikzpicture}[arrow/.style={-Triangle},
  strand style/.style 1 arg={only when rendering/.style={#1}}]
  \samecode
  \begin{knot}
    \strand[strand style={arrow}] (a.east) -- (b.west);
  \end{knot}
\end{tikzpicture}

This allows to easily move all the \draw options to the \strand via strand style={...}. Otherwise, I would have to manually give all the style I need inside the tikzpicture's options, which will decrease readability. Or I will have to pass only when rendering/.style={...} for each \strand which will also take more space and decrease readability.

loopspace commented 1 year ago

.style 1 arg isn't a thing, you just want .style there. All keys can take a single argument by default (which can be left out).

Andrew15-5 commented 1 year ago

Thanks, it works. I could've also used redundant strand style/.style n args={1}{only when rendering/.style={#1}}.

```latex \begin{tikzpicture}[ arrow/.style={-Triangle}, strand style/.style={only when rendering/.style={#1}}, ] \samecode \begin{knot} \strand[strand style={arrow}] (a.east) -- (b.west); \end{knot} \end{tikzpicture} ```
Andrew15-5 commented 1 year ago

If it's the only fix and nothing new will be added (to remove nested styling for \strand), then I guess you can close this issue.

gruberchr commented 11 months ago

Hi, I had the same problem, when drawing lines with arrows using \strand, but I found this issue #22 just now.

I want to amend, that I didn't have this problem with earlier versions of TeXLive. As far as I remember it occurred the first time at the beginning of this year after an update of TeXLive.

@loopspace Therefore I want to ask, if this behavior (shortened lines) of the knots package is the expected behavior, when the line has arrows? Or is the current behavior unexpected, i.e. is this a bug?

If it is a bug, is it possible to fix it, so that the key only when rendering can be omitted?

Otherwise I guess this behavior needs more explanation in the package documentation.

loopspace commented 11 months ago

@gruberchr It is possible that the behaviour changed as a result of bee0366a0344647b0d038ade4d0aa3403496e29e in the parent spath3 library. This commit meant that a shorten key was applied to a path prior to it being saved (which is what happens to a strand).

The logic here is that when a path is saved, all keys that modify the actual path ought to be applied to the path so that it is saved in its final form. Then when a path is used then all keys that change its appearance should be applied. The issue with the \strand command is separating out these two categories as they aren't all that obvious. For example, when appending an arrow head then a path is typically shortened - this is a modification of the path - and an arrowhead is rendered - this is its appearance. So a single user key has two effects.

Rather than try to figure out all the ins and outs of this, I chickened out and didn't bother! The only when rendering key is to allow the user to figure out which category a key should belong to.

Do you have some code that shows how the current behaviour is not what one might expect?

gruberchr commented 11 months ago

Ok, I see the point. This statement seems to be important:

The only when rendering key is to allow the user to figure out which category a key should belong to.

The problem for the user is, that these subtle differences between keys modifying a path, keys changing its appearance and keys, which do both, are implementation details of the spath3 library and are not obvious to the user. But it seems that one has to be aware of it. This requires more explanation in the documentation, which might not be easy, I guess.

The only when rendering key is explained in one of the examples in section 3. But this explanation is related to the effect of dashed lines, which would lead to dashed gaps without the only when rendering key. Maybe another example is required, e.g. with lines having arrow tips, which can be used to explain the different "categories" of a key.

Here's my MWE. It's a slight modification of the MWE above:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{knots,arrows.meta}

\begin{document}
\begin{tikzpicture}[>/.tip = Latex]
\begin{knot}
\node[draw] (a1) at (0,1) {a};
\node[draw] (b1) at (1,1) {b};
\node[draw] (a2) at (0,0) {a};
\node[draw] (b2) at (1,0) {b};
\draw[->]   (a1) -- (b1);
\strand[->] (a2) -- (b2);
\end{knot}
\end{tikzpicture}
\end{document}

mwe

As you can see, both connections between nodes a and b are almost the same. The only difference is, that the upper connection is drawn with \draw and the lower connection is drawn with \strand. This difference leads to a shortened path in the lower case.

loopspace commented 11 months ago

Documentation is very definitely not my strength!

The shortening effect of the arrow is certainly one that should be in the documentation, and I can think of several variations depending on what behaviour is desired.

Are you happy that this is a documentation issue?

gruberchr commented 11 months ago

If it's not possible or at least if it's not easy to fix this issue in the spath3 library, documentation of it would be ok for me. It should be clear for the user, that you have to "figure out" for which styling keys the only when rendering key is necessary.

Is it possible to visualize drawing of the gaps with another draft mode to see what happens?

The spath3/knots library is very helpful for me. Thank you!

loopspace commented 9 months ago

I had a dig around in the code and think that I have figured out how to disable the double arrow shortening. I've defined a key, spath/disable arrow shortening that does what it says on the tin. So using that key in the only when rendering would mean that the initial shortening was the only shortening and the net result was that the strand was placed correctly. I'll need to test it a bit to be sure that it works as intended, but if you want to test it too then you'll need the latest code.

The relevant commit is: f42dcf9

(Obviously, once it's stable then it will need adequate documentation!)