2

I'm trying to duplicate as best as possible a particular flow chart design from a textbook.

The following code almost achieves what I want:

\documentclass{article}
\usepackage[margin=0.5in]{geometry}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{arrows.meta}

\usepackage{etoolbox}
\providecommand\segment[1]{\overline{#1}}
\newcommand\aer{\rule[-0.75ex]{1cm}{0.4pt}}
\newcommand\flowchart[1]{%%
  \ifstrequal{#1}{FC1}{$\segment{SE}\cong\segment{SU}$}{}%%
  \ifstrequal{#1}{FC2}{$\angle{E}\cong\angle{U}$}{}%%
  \ifstrequal{#1}{FC3}{$\angle{1}\cong\angle{2}$}{}%%
  \ifstrequal{#1}{FC4}{$\triangle{\aer}\cong\triangle{\aer}$}{}%%
  \ifstrequal{#1}{FC5}{$\segment{MS}\cong{\aer}$}{}%%
  }

\def\mycolor{orange!50}
\pagestyle{empty}
\begin{document}

\begin{tikzpicture}[flowchart step/.style={anchor=north west,
                                           inner sep=3pt,
                                           draw,
                                           \mycolor,
                                           text=black,
                                           minimum height=2.5em,
                                           minimum width=3.5cm,},
                    flowchart step counter/.style={anchor=north west,
                                                   inner sep=0pt,
                                                   fill=\mycolor,
                                                   minimum height=1.25em,
                                                   minimum width=1.25em},
                    next step/.style={arrows=-Stealth,
                                      \mycolor,
                                      line width=3pt},
                                           ]                                   

  \node[flowchart step] (FC1) at (0,0) {\flowchart{FC1}};
  \node[flowchart step] (FC2) at ($(FC1.north west)+(0,-1.5cm)$) {\flowchart{FC2}};
  \node[flowchart step] (FC3) at ($(FC2.north west)+(0,-1.5cm)$) {\flowchart{FC3}};

  \node[flowchart step,minimum width=3.5cm+2em] (FC4) at ($(FC2.north east)+(1.75cm,0)$)    {\flowchart{FC4}};
  \node[flowchart step] (FC5) at ($(FC4.north east)+(1.75cm,0)$)    {\flowchart{FC5}};

  \foreach \myn in {1,2,3,4,5}
  {
    \node[flowchart step counter] ({FC\myn.step counter}) at (FC\myn.north west) {\myn}; 
    \draw ({FC\myn.step counter}.north west) rectangle ({FC\myn.step counter}.south east);
  }

  \draw[next step] (FC1.east) to [out=-10,in=135] (FC4.north west);
  \draw[next step] (FC2.east) to [out=0,in=180]   (FC4.west);
  \draw[next step] (FC3.east) to [out=10,in=-135] (FC4.south  west);

  \draw[next step] (FC4.east) to (FC5.west);
\end{tikzpicture}

\end{document}

enter image description here

The problem is I don't want the arrows to be flush with the boxes they're placed between.

Fine! I figured I could add an outer sep, so I modified the definition of the style flowchart step to be:

flowchart step/.style={anchor=north west,
                  outer sep=3pt,
                  inner sep=3pt,
                  draw,
                  \mycolor,
                  text=black,
                  minimum height=2.5em,
                  minimum width=3.5cm,},

That resulted in the following look:

enter image description here

So now the arrows are doing what I want, but the step counters are not placed correctly.

So, I changed the definition of the style flowchart step counter to

flowchart step counter/.style={anchor=north west,
                       outer sep=3pt,
                       inner sep=0pt,
                       fill=\mycolor,
                       minimum height=1.25em,
                       minimum width=1.25em},

which almost got things right:

enter image description here

Now I can get things correct by changing the line

    \draw ({FC\myn.step counter}.north west) rectangle ({FC\myn.step counter}.south east);

to

    \node[draw,minimum height=1.25em,minimum width=1.25em] at ({{{{FC\myn.step counter}}}}) {};

enter image description here

This can all be easily accomplished by tweaking my styles as:

\begin{tikzpicture}[flowchart step/.style={anchor=north west,
                                           outer sep=3pt,
                                           inner sep=3pt,
                                           draw,
                                           \mycolor,
                                           text=black,
                                           minimum height=2.5em,
                                           minimum width=3.5cm,},
                    flowchart naked step counter/.style={minimum height=1.25em,
                                                         minimum width=1.25em},
                    flowchart step counter/.style={anchor=north west,
                                                   outer sep=3pt,
                                                   inner sep=0pt,
                                                   fill=\mycolor,
                                                   flowchart naked step counter},
                    next step/.style={arrows=-Stealth,
                                      \mycolor,
                                      line width=3pt},
                                           ]                                   

  \node[flowchart step] (FC1) at (0,0) {\flowchart{FC1}};
  \node[flowchart step] (FC2) at ($(FC1.north west)+(0,-1.5cm)$) {\flowchart{FC2}};
  \node[flowchart step] (FC3) at ($(FC2.north west)+(0,-1.5cm)$) {\flowchart{FC3}};

  \node[flowchart step,minimum width=3.5cm+2em] (FC4) at ($(FC2.north east)+(1.75cm,0)$)    {\flowchart{FC4}};
  \node[flowchart step] (FC5) at ($(FC4.north east)+(1.75cm,0)$)    {\flowchart{FC5}};

  \foreach \myn in {1,2,3,4,5}
  {
    \node[flowchart step counter] ({FC\myn.step counter}) at (FC\myn.north west) {\myn}; 
    \node[draw,flowchart naked step counter] at ({{{{FC\myn.step counter}}}}) {};
  }

  \draw[next step] (FC1.east) to [out=-10,in=135] (FC4.north west);
  \draw[next step] (FC2.east) to [out=0,in=180]   (FC4.west);
  \draw[next step] (FC3.east) to [out=10,in=-135] (FC4.south  west);

  \draw[next step] (FC4.east) to (FC5.west);
\end{tikzpicture}

It seems like this could have been much simpler to accomplish if I could have just directly accessed those the nodes/coordinates that \node uses when drawing the shape of the node. But I don't know what they're called; if they're mentioned in the manual, I'm overlooking it somehow.

So, this is not a question about how to render my object in a particular way: I can do that. What I would like to know is: what are the names of the nodes that are used to by \node when passed the key draw?

In other words, <node name>.north east (and its ilk) seems to be determined by the value of outer sep. But when the node draws the shape, the node seems to use values determined only by inner sep. Are there easily accessible names for those points?

  • 1
    Certainly not an answer to your question, but why not use e.g. shorten >=2pt, shorten <=2pt for the arrows you draw? – cfr Nov 15 '14 at 16:19
  • @cfr I was not aware of that key. – A.Ellett Nov 15 '14 at 16:20
  • That certainly explains why you didn't use it ;). It would simplify things here, though.... – cfr Nov 15 '14 at 16:23
  • Is [anchor=north west] deliberate? I would think that [anchor=center] would look better. – John Kormylo Nov 16 '14 at 15:17
  • I think this question and answers can help you: Properly aligning drawn lines between the corners of 2 rectangular nodes in TikZ? – Ignasi Nov 19 '14 at 7:54
3

As cfr said in the comment, there is easier solution for your particular problem by using shorten.

Now for your question, the answer is :

No, there are no anchor names that seats on the node line.

But you can create them. If you want one particular anchor, let say "west 1mm inside", you can use something like label={[coordinate, name=in-west, label distance=-1mm]west:} and then use (in-west).

If you want all anchors you can use the following example to see how you can do it.

\documentclass[varwidth,border=7]{standalone}
\usepackage{tikz}
\usetikzlibrary{math}
\usetikzlibrary{calc}

\tikzset{
  overlay node/.style = {
    alias=Original Node,
    label={[inner sep=0, outer sep=0,
        evaluate={
          coordinate \c;
          \c1=(Original Node.east)-(Original Node.west);
          \w=veclen(\cx1,\cy1);
          \c2=(Original Node.north)-(Original Node.south);
          \h=veclen(\cx2,\cy2);
        },
        minimum width={\w},
        minimum height={\h},
      #1]center:}
  }
}

\begin{document}
  \begin{tikzpicture}[every node/.style={line width=2mm, inner sep=2mm}]
    \node[draw, blue!50, overlay node={name=on line, outer sep=-1mm}](target) at (3,-3) {target};

    \foreach[count=\i] \shape/\rot/\outsep/\col in
      {circle/0/1mm/purple, rectangle/35/2mm/red}{
      \node[yshift={-2*\i cm}, \shape, draw, \col, rotate=\rot, outer sep=\outsep, name=A\i,
          overlay node={name=O\i, \shape, rotate=\rot, outer sep={-\outsep}}]{A\i};
      \draw (A\i.north east) edge[\col, bend left,-latex] (target.north west);
      \draw (O\i.south east) edge[bend right,-latex] (on line.south west);
    }
    \foreach \p in {east,north,south} {
      \node[circle,fill,inner sep=.7pt,outer sep=0,label=\p:\p] at (target.\p) {};
      \node[circle,fill=yellow,inner sep=.7pt,outer sep=0] at (on line.\p) {};
    }
  \end{tikzpicture}
\end{document}

enter image description here

Note 1 : This style overlay node doesn't work well with scale. This is because outer sep has bad scale behavior. This was partially corrected in 3.0 by introducing outer sep=auto.

Note 2 : It doesn't work either with shape=dart (division error!) I can't understand why.

  • Where is outer sep=auto referenced? I could not find it. – Ignasi Feb 11 '15 at 19:15
  • I found it! outer sep=auto is valid in cvs post TiKZ 3.0 – Ignasi Feb 12 '15 at 8:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.