2

I have a simple example here with three nodes and arrows connecting them, with labels on the arrows. However, I would like the labels to be vertically aligned (i.e., I want to move the 2 label up to have the same vertical position as the 1 label but still overlap its own arrow).

\documentclass[border=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows,positioning,shapes}
\begin{document}
\begin{tikzpicture}
\node at (0,0) [rectangle,draw] (a) {$a$};
\node at (-1,-1) [rectangle,draw] (b) {$b$};
\node at (1,-2) [rectangle,draw] (c) {$c$};
\draw [->,>=latex] (a) -> node [] (l1) {1} (b);
\draw [->,>=latex] (a) -> node [] (l2) {2} (c);
\end{tikzpicture}
\end{document} 

first example

  • ?? Where did you get the syntax from ?? // However, why don't you forget about the labels and place two nodes where you need them, containing said description? – MS-SPO Nov 23 '23 at 16:10
  • Because then I have to finetune the x-coordinate so that it overlaps the arrow. I would like it to figure this out automatically. – Jeffrey Girard Nov 23 '23 at 16:17
  • 1
    There's no built-in placement for this. In this case at (intersection of l1--{[shift=(right:1)]l1 and a--c) would find the position you want. But it's not so easy with auto placement. – Qrrbrbirlbel Nov 23 '23 at 16:21
  • @Qrrbrbirlbel, can you please explain where this code would fit into my example? – Jeffrey Girard Nov 23 '23 at 16:28
  • 1
    You'd need something like \node at ...; i.e. place the node separately at the intersection of paths. – cfr Nov 23 '23 at 16:32
  • @Qrrbrbirlbel I like your suggestion very much -- more general and therefore more useful. I had trouble researching it, and no wonder as, apparently (and unfortunately) that notation is currently deprecated: https://tex.stackexchange.com/questions/31398/tikz-intersection-of-two-lines – sgmoye Nov 25 '23 at 13:15
  • And, more definitively: https://sourceforge.net/p/pgf/git/ci/c1e51497546e4eec1b2bda9ddbfa52a3322473c5/tree/doc/generic/pgf/text-en/pgfmanual-en-tikz-coordinates.tex#l468 – sgmoye Nov 25 '23 at 13:31
  • @sgmoye I'm aware. And I'm usually one to advocate for newer solutions (arrows.meta, positioning, [] for circles and arcs) instead of the deprecated versions but in this case I don't understand why intersection cs:/intersection of is so bad. It was a really good way to find an intersection between two lines (and not just two straight paths). Technically, you could also use the intersections library on-the-fly so you wouldn't have to create the paths on the user-level. My on height of key does a very specialized version of it as well. – Qrrbrbirlbel Nov 25 '23 at 14:10
  • @sgmoye The intersection cs: also allowed to find an intersection between a line and a circle node (needed calc library, I believe) and the results were not always good. But for straight lines, it works very well. If it ever vanishes, we can add it back via our own cs: if needed. – Qrrbrbirlbel Nov 25 '23 at 14:12

4 Answers4

5

The TikZ library intersections could be useful here. All that is needed is a 'helper' path extending horizontally from b that intersects the path from a to c -- placing '2' at the intersection finishes the figure. Easy, and fairly automatic. For specific instances, this approach will certainly require some adjustment.

By the way, the rectangle and circle shapes are always available without the shapes library, and rectangle is used by default for nodes. Saves a few keystrokes.

\documentclass[border=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows,positioning,intersections}
\begin{document}
\begin{tikzpicture}
\node at (0,0) [draw] (a) {$a$};
\node at (-1,-1) [draw] (b) {$b$};
\node at (1,-2) [draw] (c) {$c$};
\draw [->,>=latex] (a) -> node [inner sep=1pt,fill=white] (l1) {1} (b);
\draw [name path=ac,->,>=latex] (a) -> (c)coordinate(c1);
\path [name path=tmppath] (l1) -- (l1 -| c1);% helper path to get intersection
\node [fill=white,inner sep=1pt,name intersections={of=tmppath and ac}] at (intersection-1) {2};
\end{tikzpicture}
\end{document} 

output

sgmoye
  • 8,586
3

This drawing is an instructive example to do with Metapost -- the drawing language that is integrated with lualatex.

\documentclass[border=5mm]{standalone}
\usepackage{luamplib}
\begin{document}
\mplibtextextlabel{enable}
\begin{mplibcode}
beginfig(1);

numeric u; u = 42; path a, b, c;

a = unitsquare shifted -(1/2, 1/2) scaled 1/3 u; b = a shifted (-u, -u); c = a shifted (u, -2u);

forsuffixes s = a, b, c: draw s; label("$" & str s & "$", center s); endfor

ahangle := 30; drawarrow center a -- center b cutbefore a cutafter b; drawarrow center a -- center c cutbefore a cutafter c;

z1 = 0.5 [center a, center b]; z2 = whatever[center a, center c]; y2 = y1;

for i=1, 2: picture p; p = thelabel("$" & decimal i & "$", z[i]); unfill bbox p; draw p; endfor

endfig; \end{mplibcode} \end{document}

Compile this example with lualatex to produce a PDF that looks like this:

enter image description here

Notes

The approach here is to define three square <path> variables, a, b, and c shifted to the appropriate locations. Draw them and label them, then add the two arrows. The interesting bit is then this:

z1 = 0.5 [center a, center b];
z2 = whatever[center a, center c];
y2 = y1;

This defines two <pair> variables, z1 and z2. z1 is defined to be half way between the centre of a and the centre of b; z2 is defined to be somewhere along the line from the centre of a to the centre of c. Then in the third step the y-coordinate of z2 is set to be the same as the y-coordinate of z1. Which is what the OP wanted. MP allows you to have partial equations like this, provided only that all the points are defined before you try to draw them.

Thruston
  • 42,268
3

Code

\documentclass[border=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows.meta} % “arrows” is deprecated
\makeatletter
\tikzset{
  on height of/.code={%
    \pgf@process{\tikz@scan@one@point\pgfutil@firstofone(#1)}\pgf@ya=\pgf@y
    \tikz@timer@start \pgf@yb=\pgf@y \tikz@timer@end \pgf@yc=\pgf@y
    \pgfmathsetmacro\tikz@time{(\pgf@ya-\pgf@yb)/(\pgf@yc-\pgf@yb)}}}
\makeatother

\tikzset{node on line/.style={inner sep=+.15em, fill=white}} \begin{document}

%% manually via “intersection of” \begin{tikzpicture}[> = Latex] \path[nodes=draw] node at ( 0, 0) (a) {$a$} node at (-1,-1) (b) {$b$} node at ( 1,-2) (c) {$c$}; \path[->] (a) edge node (l1) {1} (b) edge (c) node at (intersection of l1--{[xshift=1cm]l1} and a--c) (l2) {2}; \end{tikzpicture}

%% using “on height of” \begin{tikzpicture}[> = Latex] \path[nodes=draw] node at ( 0, 0) (a) {$a$} node at (-1,-1) (b) {$b$} node at ( 1,-2) (c) {$c$}; \path[->, nodes=node on line] (a) edge node (l1) {1} (b) edge node[on height of=l1] (l2) {2} (c); \end{tikzpicture}

%% auto placement will need help \begin{tikzpicture}[> = Latex, auto=right] \path[nodes=draw] node at ( 0, 0) (a) {$a$} node at (-1,-1) (b) {$b$} node at ( 1,-2) (c) {$c$}; \path[->, inner sep=+.15em] (a) edge node (l1) {1} (b) edge node[swap, on height of=l1.south] (l2) {2} (c); \end{tikzpicture} \end{document}

Output

enter image description here

Qrrbrbirlbel
  • 119,821
0

This approach is as good or bad as others:

  • use pos-parameter
  • determine its value as needed

I found pos=0.185 experimentally ... And as long as you can't read out the coordinates of (a), (b) etc. ...

result

\documentclass[border=3mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{arrows,shapes}
\begin{document}
 \begin{tikzpicture}[
    >=latex
 ]
    \node at ( 0, 0)    [rectangle,draw] (a) {$a$};
    \node at (-1,-1)    [rectangle,draw] (b) {$b$};
    \node at ( 1,-2)    [rectangle,draw] (c) {$c$};
    \draw [->] (a) -- node [pos=.5] (l1) {1} (b);
    \draw [->] (a) -- node [pos=.185] (l2) {2} (c);
 \end{tikzpicture}
\end{document} 
MS-SPO
  • 11,519