Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lines intersection in a flowchart (feature request) #23

Open
Andrew15-5 opened this issue Feb 24, 2023 · 7 comments
Open

Lines intersection in a flowchart (feature request) #23

Andrew15-5 opened this issue Feb 24, 2023 · 7 comments

Comments

@Andrew15-5
Copy link

I found 2 "solutions" for what I need:

But then I (don't remember how) discovered spath3 and knots packages. I can see from the documentation that with them, I can cut one line in place of an intersection to prevent the physical intersection itself. But I was hoping that I can change the way the intersection is redrawn to make one line an arc and leave the other one untouched, or apply the same "cutting" effect (but at the arc intersection).

The given examples are manual work, unlike the knots package, and therefore not desirable.

@Andrew15-5
Copy link
Author

I've missed the spath3 documentation, where it shows the example of doing just that.

Link:
http://mirrors.ctan.org/graphics/pgf/contrib/spath3/spath3_code.pdf (page 22-23)
from:
https://ctan.org/pkg/spath3

@Andrew15-5
Copy link
Author

I understand that I can do it with spath3, as it is a core (lower level API) to knots tikz library.
But can the same thing be done in knots library? By that, I mean less code to write, but with the same result.
If it can't be done, can I request a new feature? It goes like this:

Add an option to knot environment to choose to which intersection(s) should this style (arc path) be applied. Additional options should be provided (from documentation; this is just an example) to give the user some control of the basic settings:

  • bridging span/.initial=8pt
  • bridging gap/.initial=4pt

The last thing is: add the ability to change the direction of the arc, e.g., use one of these paths (over/up arc and under/down/reverse arc):

\tikz[overlay] { \path[spath/save global=intersection arc] (0,0) arc[
  radius=1cm, start angle=180, delta angle=-180]; }
\tikz[overlay] { \path[spath/save global=intersection reverse arc] (0,0) arc[
  radius=1cm, start angle=-180, delta angle=180]; }

It will be very useful for everyone who would need to plot any flowchart, specifically if it's just so happen that in the flowchart there is 1 intersection or more.
In other words, user can plot as much \strands as they want but in case of intersection they can just write one option to knot environment specifying which strands need to be treated as an arc intersection(s).

This will obviously save a lot of time as opposed to using spath3 directly and will shrink down the size of a preamble.

@Andrew15-5 Andrew15-5 changed the title Lines intersection in a flowchart Lines intersection in a flowchart (probably a feature request) Feb 24, 2023
@Andrew15-5
Copy link
Author

I've modified a bit the example from the documentation (I don't know yet how to reuse the same code with tikz):

...
\tikzset{
  bridging path/.initial=intersection arc,
  bridging rpath/.initial=intersection reverse arc,
  bridging span/.initial=8pt,
  bridging gap/.initial=4pt,
  bridge/.style 2 args={
    spath/split at intersections with={#1}{#2},
    spath/insert gaps after
      components={#1}{\pgfkeysvalueof{/tikz/bridging span}},
    spath/join components upright
      with={#1}{\pgfkeysvalueof{/tikz/bridging path}},
    spath/split at intersections with={#2}{#1},
    spath/insert gaps after
      components={#2}{\pgfkeysvalueof{/tikz/bridging gap}},
  },
  rbridge/.style 2 args={
    spath/split at intersections with={#1}{#2},
    spath/insert gaps after
      components={#1}{\pgfkeysvalueof{/tikz/bridging span}},
    spath/join components upright
      with={#1}{\pgfkeysvalueof{/tikz/bridging rpath}},
    spath/split at intersections with={#2}{#1},
    spath/insert gaps after
      components={#2}{\pgfkeysvalueof{/tikz/bridging gap}},
  },
}

\AtBeginDocument{%
  \tikz[overlay] { \path[spath/save global=intersection arc] (0,0) arc[
    radius=1cm, start angle=180, delta angle=-180]; }%
  \tikz[overlay] { \path[spath/save global=intersection reverse arc] (0,0) arc[
    radius=1cm, start angle=-180, delta angle=180]; }%
}

\begin{document}
...
\begin{tikzpicture}
  ...
  \path[spath/save=ab] ...;
  \path[spath/save=cd] ...;
  \tikzset{
    bridging span/.initial=8pt, % any other value
    bridging gap/.initial=4pt, % any other value
    bridge={ab}{cd},
    % or
    rbridge={ab}{cd},
  }
  \draw[spath/use=ab];
  \draw[spath/use=cd];
  ...
\end{tikzpicture}
...
\end{document}

That's a lot of code for a small flowchart IMO, I hope that it can be integrated in knots library. Or at the very least, it can be integrated in spath3.

@loopspace
Copy link
Owner

The knots library and the knot style in the spath3 library work in very different ways. The knot environment works by painting over the intersections and then redrawing the over-strand. So while it might be possible to re-jig the over-strand with a bump, doing the splice and then re-doing the intersection is actually more complicated than the knot environment was designed to cope with. The spath3 library works by actually breaking the path at the intersection point, which is a more powerful method and which makes it possible to do the splicing.

So the two are not meant to be used together and trying to make them work together will be tricky.

The spath3 code comes in two parts: there is the underlying code provided by the spath3 package but then there is also a higher level api from the spath3 TikZ library which is intended to be used by a document writer. This is relatively new so with things like the bridge style that you've found then I haven't integrated that into the package itself as yet because I don't know that it is in its final form. Indeed, it looks like you would like an easy way to flip the arc and that seems quite a reasonable thing to want to do. So while code is still very fluid, I would rather not cement it into the package.

@Andrew15-5
Copy link
Author

Sorry for extending your todo list twice (#23, #24). ;)

But I am really looking forward to using the requested things in my projects/documents.

@Andrew15-5
Copy link
Author

Andrew15-5 commented Mar 6, 2023

I thought I would share my "temporary" setup, which I will be using until this feature is implemented in any package/library. In case, some would like to have/use the same functionality.

Setup
\usepackage{tikz}
\usetikzlibrary{spath3, intersections}

\tikzset{
  flowchart/arc/.initial=flowchart intersection arc,
  flowchart/arc size/.initial=8pt,
  flowchart/gap size/.initial=4pt,
  flowchart/flip arc/.code={
    \ifx#1\relax\relax
    \tikzset{flowchart/arc=flowchart intersection arc}
    \else
    \tikzset{flowchart/arc=intersection reverse arc}
    \fi
  },
  flowchart/insert arcs/.style n args={3}{
    flowchart/flip arc={#3},
    spath/split at intersections with={#1}{#2},
    spath/insert gaps after components={#1}{%
      \pgfkeysvalueof{/tikz/flowchart/arc size}},
    spath/join components upright with={#1}{%
      \pgfkeysvalueof{/tikz/flowchart/arc}},
  },
  flowchart/insert gaps/.style n args={3}{
    spath/split at intersections with={#2}{#1},
    spath/insert gaps after components={#2}{%
      \pgfkeysvalueof{/tikz/flowchart/gap size}},
  },
  flowchart intersections/.style={
    flowchart/insert arcs/.list={#1},
    flowchart/insert gaps/.list={#1},
  },
}

\AtBeginDocument{
  \tikz[overlay]{
    \path[spath/save global=flowchart intersection arc] (0,0) arc[
      radius=1pt,
      start angle=0,
      delta angle=180,
    ];
  }
  \tikzset{
    spath/clone global={intersection reverse arc}{flowchart intersection arc},
    spath/reverse globally=intersection reverse arc
  }
}

\DeclareDocumentCommand\spath{O{} m +m}{\path[#1, spath/save=#2] #3}
\DeclareDocumentCommand\sdraw{O{} m}{\draw[#1, spath/use=#2]}

And then it can be used like so:

\begin{tikzpicture}
  \spath {a} (0,0) -- (2,2);
  \spath {b} (0,1) -- (1,0);
  \spath {c} (0,2) -- (2,0);

  \tikzset{
    flowchart intersections={
      {a}{b}{*},
      {c}{a}{}
    }
  }

  \sdraw {a};
  \sdraw {b};
  \sdraw {c};
\end{tikzpicture}
Full code (MWE)
\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{spath3, intersections}

\tikzset{
  flowchart/arc/.initial=flowchart intersection arc,
  flowchart/arc size/.initial=8pt,
  flowchart/gap size/.initial=4pt,
  flowchart/flip arc/.code={
    \ifx#1\relax\relax
    \tikzset{flowchart/arc=flowchart intersection arc}
    \else
    \tikzset{flowchart/arc=intersection reverse arc}
    \fi
  },
  flowchart/insert arcs/.style n args={3}{
    flowchart/flip arc={#3},
    spath/split at intersections with={#1}{#2},
    spath/insert gaps after components={#1}{%
      \pgfkeysvalueof{/tikz/flowchart/arc size}},
    spath/join components upright with={#1}{%
      \pgfkeysvalueof{/tikz/flowchart/arc}},
  },
  flowchart/insert gaps/.style n args={3}{
    spath/split at intersections with={#2}{#1},
    spath/insert gaps after components={#2}{%
      \pgfkeysvalueof{/tikz/flowchart/gap size}},
  },
  flowchart intersections/.style={
    flowchart/insert arcs/.list={#1},
    flowchart/insert gaps/.list={#1},
  },
}

\AtBeginDocument{
  \tikz[overlay]{
    \path[spath/save global=flowchart intersection arc] (0,0) arc[
      radius=1pt,
      start angle=0,
      delta angle=180,
    ];
  }
  \tikzset{
    spath/clone global={intersection reverse arc}{flowchart intersection arc},
    spath/reverse globally=intersection reverse arc
  }
}

\DeclareDocumentCommand\spath{O{} m +m}{\path[#1, spath/save=#2] #3}
\DeclareDocumentCommand\sdraw{O{} m}{\draw[#1, spath/use=#2]}

\begin{document}

\begin{tikzpicture}
  \spath {a} (0,0) -- (2,2);
  \spath {b} (0,1) -- (1,0);
  \spath {c} (0,2) -- (2,0);

  \tikzset{
    flowchart intersections={
      {a}{b}{*},
      {c}{a}{}
    }
  }

  \sdraw {a};
  \sdraw {b};
  \sdraw {c};
\end{tikzpicture}

\end{document}

Output:

image

For more information, see discussion in #24.

Update: Fixed issues, which are noted here: #23 (comment).

@loopspace
Copy link
Owner

The log for your code contains the line:

Missing character: There is no * (U+002A) in font nullfont!

which is the result of your insert gaps only taking two arguments. It needs to take three so that when you pass it {a}{b}{*} then the * gets absorbed. Otherwise there's a stray * and that's what the error message is about.

Then you also need an empty argument on the line when you don't have a *, otherwise you get:

(\end occurred when \ifx on line 64 was incomplete)
(\end occurred when \if on line 64 was incomplete)

which is the result of trying to send nothing through on the third argument. There's a difference between no argument and an empty argument. There are ways to make that optional, along the lines of the s option for NewDocumentCommand, but the current code isn't sophisticated enough for that.

@Andrew15-5 Andrew15-5 changed the title Lines intersection in a flowchart (probably a feature request) Lines intersection in a flowchart (feature request) Mar 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants