7

I have two stocks, A and B. These two "meet" each other at rates q(x), and f(x), by going through a joint-state process called X. Then, A becomes a, and B becomes b.

I thought about visualizing the flowchart as in the attached box. However, I'm clueless as to how solve this within tikz. It'd be best if the arrows are dashed arrows while "inside of X".

flowchart

With protest, here's as far as I came.

\documentclass[border=1in]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}

\tikzstyle{block} = [rectangle, draw, fill=blue!20, 
text width=5em, text centered, rounded corners, minimum height=4em]

\begin{document}
    \begin{tikzpicture}
    \node [block] (X) {X};
    \node [block] [below left=of X] (A) {A};
    \node [block] [above left=of X] (a) {a};
    \node [block] [below right=of X] (B) {B};
    \node [block] [above right=of X] (b) {b};

    \path[->] (A) edge[bend right=90] node [left] {} (a);
    \path[->] (B) edge[bend left=90] node [left] {} (b);

    \end{tikzpicture}
\end{document}
FooBar
  • 983

3 Answers3

11

Just divide the path in three if you want the second part dashed.

If you write NodeName.degreee (for example X.130) you can position the end or the beginning of the path exactly where you need. Imagine the node is a circle angle with the east anchor = 0 degrees, so the south anchor is -90, the north = 90, the east = 180, etc.

\documentclass[border=1in]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}
\tikzset{
    block/.style={
        rectangle, draw, fill=blue!20, 
        text width=5em, text centered, rounded corners, minimum height=4em
        }
    }

\begin{document}
    \begin{tikzpicture}
    \node [block] (X) {X};
    \node [block] [below left=of X] (A) {A};
    \node [block] [above left=of X] (a) {a};
    \node [block] [below right=of X] (B) {B};
    \node [block] [above right=of X] (b) {b};

    \draw (A) to[bend right] (X.-130) node[below left=4pt and 5pt] {$q(x)$};
    \draw[dashed] (X.-130) to[bend right, looseness=.2] (X.130); 
    \draw[->] (X.130) to[bend right] (a);

    \draw (B) to[bend left] (X.-50) node[below right=4pt and 5pt] {$f(x)$};
    \draw[dashed] (X.-50) to[bend left, looseness=.2] (X.50);
    \draw[->] (X.50) to[bend left] (b);

    \end{tikzpicture}
\end{document}

enter image description here

Edit: gorgeous marmot's answer could be simplified without using reverse clipping and putting the straight line behind the X node, like in marya's answer but using on background layer from backgrounds library to not draw it twice.

\documentclass[border=1in]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning,backgrounds}
\tikzset{
    block/.style={
        rectangle, 
        text width=5em,  text centered, rounded corners, minimum height=4em, draw, fill=blue!20
        },
    }

\begin{document}
\begin{tikzpicture}
    \node[block] (X) {X};
    \node [block] [below left=of X] (A) {A};
    \node [block] [above left=of X] (a) {a};
    \node [block] [below right=of X] (B) {B};
    \node [block] [above right=of X] (b) {b};

    \begin{scope}[on background layer]
    \path[->] (A) edge[bend right=90] node[near start, above left] {$q(x)$} (a);
    \path[->] (B) edge[bend left=90]  node[near start, above right] {$f(x)$} (b);
    \end{scope}

    \begin{scope}[dashed]
    \clip[rounded corners] (X.north west) rectangle (X.south east);
    \path[->] (A) edge[bend right=90] (a);
    \path[->] (B) edge[bend left=90]  (b);
    \end{scope}
\end{tikzpicture}
\end{document}

enter image description here

CarLaTeX
  • 62,716
  • Oh, now after seeing the image, I understand I wasn't being clear enough. Ive updated the picture to emphasize what I mean by "dashed while inside of X"... sorry about that – FooBar Dec 22 '18 at 08:03
  • @FooBar See my renewed answer – CarLaTeX Dec 22 '18 at 08:11
10

Well, the easiest solution I came up is this one

\documentclass[border=1in]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}

\tikzstyle{block} = [rectangle, draw, fill=blue!20,
text width=5em, text centered, rounded corners, minimum height=4em]

\begin{document}
    \begin{tikzpicture}
    \node [block] (X) {X};
    \node [block] [below left=of X] (A) {A};
    \node [block] [above left=of X] (a) {a};
    \node [block] [below right=of X] (B) {B};
    \node [block] [above right=of X] (b) {b};

    \path[->] (A) edge[bend right=90] node [left,pos=0.3] {$q(r)$} (a);
    \path[->] (B) edge[bend left=90] node [right,pos=0.3] {$f(r)$} (b);
\node [block] (X) {X};
\path[->,dashed] (A) edge[bend right=90] node [left,pos=0.3] { } (a);
    \path[->,dashed] (B) edge[bend left=90] node [right,pos=0.3] { } (b);
    \end{tikzpicture}
\end{document} 

enter image description here

Maryà
  • 4,830
10

Here is a proposal using reverseclip and use path to draw the dashed path inside and the solid one outside. Please note that \tikzstyle is slightly deprecated.

\documentclass[border=1in]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning}
\makeatletter % https://tex.stackexchange.com/a/38995/121799
\tikzset{
  use path/.code={\pgfsyssoftpath@setcurrentpath{#1}}
}
\makeatother
\tikzset{remember path/.style={save path=\tmprotect}}
% https://tex.stackexchange.com/a/12033/121799
\tikzset{reverseclip/.style={insert path={(current bounding box.north
        east) rectangle (current bounding box.south west)}}}

\tikzset{block/.style={rectangle, draw, fill=blue!20, 
text width=5em, text centered, rounded corners, minimum height=4em}}

\begin{document}
    \begin{tikzpicture}
    \node [block,save path=\pathX] (X) {X};
    \node [block] [below left=of X] (A) {A};
    \node [block] [above left=of X] (a) {a};
    \node [block] [below right=of X] (B) {B};
    \node [block] [above right=of X] (b) {b};

    \begin{scope}
    \clip[use path=\pathX,reverseclip];
    \path[->] (A) edge[bend right=90] (a);
    \path[->] (B) edge[bend left=90]  (b);
    \end{scope}
    \begin{scope}[dashed]
    \clip[use path=\pathX];
    \path[->] (A) edge[bend right=90] (a);
    \path[->] (B) edge[bend left=90]  (b);
    \end{scope}

    \end{tikzpicture}
\end{document}

enter image description here

  • @CarLaTeX I would not say it is strictly "better" but each of them has its own advantage. (I upvoted your post, too, of course.) –  Dec 22 '18 at 09:31
  • @CarLaTeX Thanks for saying that but I guess it is a matter of taste.So we cannot argue about it, ;-) –  Dec 22 '18 at 09:35
  • @CarLaTeX To be honest, I like mine better because if the path in yours would hit a rounded corner, it would get clipped incorrectly. This is why I am doing the use path trick. (And personally I do not find reverseclip inelegant, but that's a matter of taste.) –  Dec 22 '18 at 14:47
  • @CarLaTeX I would nevertheless like to argue that you could add [rounded corners] to \clip such that it becomes \clip[rounded corners] (X.north west) rectangle (X.south east); (which has another simplification: rectangle and 2 corners instead of 4 corners and cycle). To see where that may matter, add a path \draw (A.50) -- (b.-130);. Notice also that use path is not something exotic. save path is already part of plain vanilla TikZ, and use path is part of some common libraries like spath3 (and really useful IMHO). –  Dec 22 '18 at 15:34
  • @CarLaTeX I guess it is really a matter of taste. After all we we are all TikZ beginners. ;-) (Instead of using a phantom node, you could just draw the solid paths on the background, which would avoid to draw the node twice.) –  Dec 22 '18 at 17:01
  • @CarLaTeX Si signora. (Of course this has the slight disadvantage that you increase the complexity if you are already using backgrounds for other things, but then one can add other layers. All this has the slight disadvantage that, if you want the node to be a bit transparent, it won't work. In this sense I think your original solution is better. Frankly, I feel that your original solution and this one are the ones that have the least side effects.) –  Dec 22 '18 at 17:09
  • Are you sure you have put the right reference with https://tex.stackexchange.com/a/12033/121799 ? Here reverseclip is defined with insert path={{(current page.north east) -- (current page.south east) -- (current page.south west) -- (current page.north west) -- (current page.north east)} while you defined it with insert path={{(current bounding box.north east) rectangle (current bounding box.south west)} – AndréC Dec 22 '18 at 17:11
  • I don't think the OP is using backgrounds for other things. Of course, my new solution doesn't work with trasparency, but I already said that yours is the more elegant and correct! – CarLaTeX Dec 22 '18 at 17:13
  • @AndréC There are several versions of this on the market and I try to give credit to the original one for the concept, not for the details. Yes, my variation is a tiny bit shorter, but that is hardly a reason not to give credit to the original idea/post. Once you start giving credit to more original posts, you may realize how good and appropriate that feels. –  Dec 22 '18 at 17:16
  • Shouldn't the one who has intelligently modified the reverseclip's style also be credited? – AndréC Dec 22 '18 at 18:12
  • @AndréC Yes, that would be nice. Whenever you use it, you might, in addition to the original proposal also "cite" this answer. And once you have enough practice, you may cite comments if "your" answer is just saying the same thing. –  Dec 22 '18 at 23:20
  • I had known this syntax for much longer since I used it here https://tex.stackexchange.com/a/444139/138900 – AndréC Dec 23 '18 at 05:19
  • Personally, I vote for the answers, not for those who write them. You are free to vote for people. – AndréC Dec 23 '18 at 16:17
  • @AndréC I vote for answers if I am convinced that they add useful information. If I feel that the answer is just taken from someone else (because I have seen the user "adopting" the post by others without giving appropriate credit), I do not upvote them. –  Dec 23 '18 at 18:27
  • There is no credit to give here, all the credit goes to TIkZ and its manual where we find the operation use as bounding box. We give credit to someone who creates something that does not yet exist in the manual. – AndréC Dec 23 '18 at 19:51
  • @AndréC According to your arguments, your answer is worthless, then. Either there is a point in mentioning use as bounding box in connection with the question (which I think there is), and you should give credit to those who were first, or there is none, in which case you could just delete your answer. Many valuable comments or answers only point to the right place in the manual, and in my opinion a large fraction of them are valuable post. –  Dec 23 '18 at 23:06
  • I don't understand what you're saying. – AndréC Dec 24 '18 at 06:49