loopspace / spath3

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

richer TikZ interface #4

Closed kpym closed 3 years ago

kpym commented 5 years ago

It will be nice to add to the existing save spath and restore spath to add other interface styles.

For example I was not able to reverse a path to answer this TeX.SX question.

loopspace commented 5 years ago

I agree, I tend to add stuff as I find a need for it so it's an incremental process.

Do you think it would be good to add a wholly key-based interface? It might be possible to have something like:

\draw[current path/reverse, current path/weld to=B] <current path specification>;

I posted an answer at that question using ordinary LaTeX comands (with a couple of new ones).

kpym commented 5 years ago

I like very much your proposal ! May be weld before and weld after is better than simply weld to ? Isn't it better (if possible) to have insert spath in a way to be able to do (0,0) -- [insert spath=A] .. [insert spath=B] -- cycle ? Thanks to considering this request.

loopspace commented 5 years ago
\documentclass{article}
%\url{https://tex.stackexchange.com/q/484027/86}
\usepackage{tikz}
\usetikzlibrary{hobby}
\usetikzlibrary{calc}
\usepackage{spath3}

\ExplSyntaxOn
\makeatletter
\DeclareDocumentCommand \SPathReverse {m}
{
  \spath_reverse:n {#1}
}

\DeclareDocumentCommand \SPathClose {m}
{
  \spath_close_path:n {#1}
}

\tikzset{
  insert~ spath/.code={
    \spath_get_current_path:n { current path }
    \spath_weld:nn { current path } { #1 }
    \spath_set_current_path:n { current path }
  },
  reverse~ spath/.code={
    \spath_reverse:n { #1 }
  },
  insert~ reverse~ spath/.code={
    \spath_reverse:n { #1 }
    \spath_get_current_path:n { current path }
    \spath_weld:nn { current path } { #1 }
    \spath_set_current_path:n { current path }
    \spath_reverse:n { #1 }
  },
}
\makeatother
\ExplSyntaxOff

\begin{document}

\begin{tikzpicture}[use Hobby shortcut]

 \path[save spath = A]
  (3.18, 1.05)..
  (2.7,.58)..
  (2.45,-.95)..
  (1.81,-1.35)
  ;
 \path[save spath = B]
  (3.18, 1.05)..
  (1.73,1.01)..
  (0,.57)..
  (-1.07,0)..
  (-1.43, -.26)..
  (-1.76,-.61)..
  (-1.81,-.89)..
  (-1.56,-.91)..
  (-.95, -.78)..
  (0,-.66)..
  (.79,-.7)..
  (1.23,-.88)..
  (1.81,-1.35)
  ;

\SPathReverse{B}
\SPathWeld{A}{B}
\SPathClose{A}

\filldraw[restore spath=A,fill=blue,draw=black,ultra thick];
\end{tikzpicture}

\begin{tikzpicture}[use Hobby shortcut]

 \path[overlay,save spath = A]
  (3.18, 1.05)..
  (2.7,.58)..
  (2.45,-.95)..
  (1.81,-1.35)
  ;

\filldraw[fill=blue, draw=black, ultra thick]
  (3.18, 1.05)..
  (1.73,1.01)..
  (0,.57)..
  (-1.07,0)..
  (-1.43, -.26)..
  (-1.76,-.61)..
  (-1.81,-.89)..
  (-1.56,-.91)..
  (-.95, -.78)..
  (0,-.66)..
  (.79,-.7)..
  (1.23,-.88)..
  ([Hobby finish]1.81,-1.35) % needed to trigger hobby path generation before adding the new path
[insert reverse spath=A] -- cycle
  ;
\end{tikzpicture}
\end{document}

I think there's a few local/global issues to sort out, but the above seems to work well.

kpym commented 5 years ago

It looks like weld is adding lineto to join the paths. But in some situations we want to decide what to put between the paths : moveto, curveto or lineto.

May be having a reverse method totikz (or topgf ?) that transform a soft path to tikz (or pgf) path can be used to have a total freedom of what we put before and what we put after ?

loopspace commented 5 years ago

welding shouldn't add anything between the paths. It translates the second path to start where the first ends and then puts it at the end of the first path, removing the moveto from the start of the second path (every path starts with a moveto). There are some other internal commands which join paths with a lineto, but at the user level then to join paths with a specific path construction should just need putting that construction in place.

So where are you seeing the lineto in the weld?

kpym commented 5 years ago

It's my fault, I changed the path A at the beginning and I observed the appearance of a line, which is due to the \SPathClose but I wrongly concluded that it's a line between the welding points. Sorry.

loopspace commented 5 years ago

No problem.

I've committed a few changes that ought to make a start towards this. It also fixes the issue with closed paths with the calligraphy sublibrary. If you have any test documents, please try it out with them.

loopspace commented 3 years ago

I've been working on this a bit. There's a new TikZ library (\usetikzlibrary{spath3}) to enable them. Some are meant to be used in a \path specification, others are for manipulating soft paths prior to restoring them.

There's also a coordinate specification, (spath cs:5.7) which locates a point along the path.

The bit I'm pondering is whether the underlying spath object is actually necessary or whether it is simpler to use a macro to pass around. There are a few times where it is useful to have a string associated to the path (such as when associating a style to the path automatically) but that wouldn't be difficult to work around if using macros.

So should it be:

\path[save spath=my amazing path]

or

\path[save spath=\MyAmazingPath]

loopspace commented 3 years ago

I'm starting to settle on the new syntax and code. There is now an spath3 TikZ library (documented in spath3.tex) with the new keys. They aren't quite as above as I've put them in an spath/.is family sub-directory.

kpym commented 3 years ago

@loopspace Thanks for all your fantastic work. I'll check this new interface very soon and I'll keep you informed.

kpym commented 3 years ago

It works! I was able to rewrite your TeX.SX answer :)

\documentclass[tikz,border=7pt]{standalone}
\usetikzlibrary{hobby,spath3}

\begin{document}
  \begin{tikzpicture}[use Hobby shortcut]

    \path[spath/save = A]
      (3.18, 1.05)..
      (2.7,.58)..
      (2.45,-.95)..
      (1.81,-1.35)
    ;
    \path[spath/save = B]
      (3.18, 1.05)..
      (1.73,1.01)..
      (0,.57)..
      (-1.07,0)..
      (-1.43, -.26)..
      (-1.76,-.61)..
      (-1.81,-.89)..
      (-1.56,-.91)..
      (-.95, -.78)..
      (0,-.66)..
      (.79,-.7)..
      (1.23,-.88)..
      (1.81,-1.35)
    ;

    \filldraw[fill=blue,draw=black,ultra thick]
      [spath/restore = A]
      [spath/append reverse = B]
      -- cycle
    ;
  \end{tikzpicture}
\end{document}

But, IMO, you should definitely change the way you put the code in your documentations to make it nicer and copy/paste friendly.

loopspace commented 3 years ago

Thanks for testing!

With regard to the code in the documentation, it looks like I hadn't updated it in light of your suggestion over on hobby at https://github.com/loopspace/hobby/issues/3 . I'll make the changes from that over here on all the documentation and hopefully that will fix it.