varkor / quiver

A modern commutative diagram editor for the web.
https://q.uiver.app
MIT License
2.37k stars 78 forks source link

Improve TikZ output #46

Open varkor opened 3 years ago

varkor commented 3 years ago

There are currently a number of situations that quiver struggles to replicate in LaTeX (currently the user will be warned about these situations, and quiver will fall back on an easier style, e.g. replacing a 3-cell with a 1-cell). We would really like to support exporting every diagram that quiver supports. I'm keeping a list here of the remaining problems.

If you feel you may have a solution to one of these issues, I would love to hear from you: please leave a comment! (If it requires extended discussion, we can get in touch through another medium.) Thank you!

loopspace commented 3 years ago

I'm currently working on code that shortens a TikZ path along its path which should be a better fit than how the shorten key works. It will be part of my spath3 library, at https://github.com/pkg/spath3 but it is currently in testing and I haven't yet integrated it into the main code. It's on the to-do list!

varkor commented 3 years ago

If this could eventually be slotted in as a replacement for shorten in arrows, that would be brilliant :)

loopspace commented 3 years ago

Are the curved arrows a single path component (ie line or bezier curve) or are they made up of several segments?

The shorten code shortens the last segment (or the first, depending on which end you are shortening from) and deep within the code it shortens it using the parametrisation of the segment. At the moment, the user specifies a dimension that they want to shorten it by and this is converted to a parameter. For a line segment then the conversion from dimension to parameter is exact. For a bezier curve then it uses the derivative at the end point for the conversion so is a reasonable approximation in a neighbourhood of the end point. Computing arc lengths of bezier's is tricky and I figured this would be good enough (at least until someone complained that it wasn't!).

To work proportionally, I would just use the parameter directly. Again, this won't be exact for beziers.

varkor commented 3 years ago

The TikZ curves are cubic Béziers, so I'm not sure how well this would approximate them. Perhaps one would have to try it in some examples to see whether it's possible to get away with this approximation.

loopspace commented 3 years ago

What I'm asking is whether a curve is a single bezier or are they built up from several?

If you post the outputted TikZ code for one of your paths I could run my code on it with various shortenings to see whether the approximation is noticeable.

varkor commented 3 years ago

Each curve consists of a single Bézier. Here's a typical example (you will need the curve style defined here):

\[\begin{tikzcd}
    {\bullet} & {\bullet}
    \arrow[from=1-1, to=1-2, curve={height=-30pt}]
\end{tikzcd}\]
loopspace commented 3 years ago

I'll need to dig a bit into tikzcd to figure out how it might interface with my code.

In the meantime, here's a screenshot of what it can do. The original curve is the coloured one underneath. It's then been shortened by 5pt increments and plotted with a bar arrow at the end to indicate where it ends. As you can see, each shortened curve lies exactly along the line of the original.

In the upper version, the original curve is shortened each time, by first 5pt, then 10pt, then 15pt and so on. The circles have radius 5pt and 10pt, so the 5pt shortening is about right and the 10pt a bit off. It's clear that the further shortenings are further off, due to the fact that the derivative varies.

In the lower version, the original curve is shortened by 5pt, and then that shorter curve is again shortened by 5pt, and so on. This produces a more consistent shortening as it is effectively re-evaluating the derivative each time.

image

varkor commented 1 year ago

@loopspace: any update on the path shortening feature in spath3? Is it now possible to use spath3 instead of shorten <?

loopspace commented 1 year ago

@varkor Prompted by your post here and on TeX-SX, I went back to look at this and found that I'd already figured out how to do this with the latest version of spath3. I guess I was waiting for it to upload to CTAN before sending it to you and then by the time I did that then it had gone out of my mind. I can only apologise for that.

I'll update the post on TeX-SX as well, but here's the code that now produces the same diagram as is posted there. The 'orrible code in the original is now contained in the key spath/split at keep middle. Using the keyword current means to apply it to the path under construction, avoiding the requirement of saving and reusing the path (which is what is going on in the first example).

\documentclass{article}
%\url{https://tex.stackexchange.com/q/568648/86}
\usepackage{tikz-cd}
\usetikzlibrary{
  calc,
  spath3
}
\def\pv#1{%
  \pgfkeysvalueof{/tikz/quiver/#1}%
}
\tikzset{
  curve/.style={
    quiver/.cd,
    #1,
    /tikz/.cd,
    to path={
      (\tikztostart) .. controls ($(\tikztostart)!\pv{pos}!(\tikztotarget)!\pv{height}!270:(\tikztotarget)$)
    and ($(\tikztostart)!1-\pv{pos}!(\tikztotarget)!\pv{height}!270:(\tikztotarget)$)
    .. (\tikztotarget)\tikztonodes}
  },
  quiver/.cd,
  pos/.initial=0.35,
  height/.initial=0
}

\begin{document}

\begin{tikzpicture}
\draw[spath/save=curve, ultra thick] (0,0) .. controls +(1,2) and +(-1,2) .. (3,0);
\tikzset{
%  spath/split at keep start={curve}{.9},
%  spath/split at keep end={curve}{.1/.9},
  spath/split at keep middle={curve}{.1}{.9},
}
\draw[spath/use={curve},red];
\end{tikzpicture}

\begin{tikzcd}
{\bullet} & {\bullet} & {\bullet}
\arrow[
  from=1-1,
  to=1-2,
  curve={
    height=-40pt
  }
]
\arrow[
  from=1-2,
  to=1-3,
  curve={
    height=-40pt
  },
  /tikz/spath/at end path construction={
    \tikzset{spath/split at keep middle={current}{.1}{.9}}
  },
  color=red,
]
\end{tikzcd}

\end{document}
varkor commented 1 year ago

@loopspace: thanks, I've tested it out and this seems to work perfectly! I'll probably wait a little while for the latest version of spath3 to be available by default e.g. on Overleaf, and will then update the quiver output to make use of it. Thank you very much for your help with this issue!

varkor commented 11 months ago

Triple arrows are now supported since https://github.com/varkor/quiver/commit/3ec01d7e419dc3f8dd22ebd725afa5e6551f06cf.