1

I'm merging solutions from two different questions, and encountering issues with their compatibility:

The first is from Tikz: Arrowheads in the center, allowing decorations on arrows to have an arrowhead in the middle

The second is from tikz bounding box / cropping: too much space for curves to limit the bounding box when using control points for a curve.

I'm effectively trying to create a directed graph with two loops coming from one edge, so if anyone finds a better solution that would also be great.

I can create the graph I want, but with the bounding box (brown) too large because of the control points:

generated graph with large boundary box Created by the code:

\documentclass{scrarticle}

\usepackage{tikz} \usepackage{lipsum}

\usetikzlibrary{decorations.markings}

\begin{document} \usetikzlibrary{arrows,positioning} % arrows with middlearrow arrow head in middle \tikzset{middlearrow/.style={ decoration={markings, mark= at position 0.5 with {\arrow{#1}} , }, postaction={decorate} } % middlearrow/.default={>} } \lipsum[66] \begin{center} \begin{tikzpicture} \node[circle,fill=black,inner sep=2pt,label=b] (b) at (0,0) {}; \draw[middlearrow={>}] (b) .. controls (2,2) and (2,-2) .. (b); \draw[middlearrow={>}] (b) .. controls (-2,-2) and (-2,2) .. (b); \draw [brown] (current bounding box.south west) rectangle (current bounding box.north east); \end{tikzpicture} \end{center} \lipsum[66] \end{document}

To which I try to add the boundary box solution to remove extra space:

\documentclass{scrarticle}

\usepackage{tikz} \usepackage{lipsum}

%limit boundary box: from https://tex.stackexchange.com/questions/290357/tikz-bounding-box-cropping-too-much-space-for-curves \usetikzlibrary{calc,decorations.pathreplacing} \tikzset{ bezier/controls/.code args={(#1) and (#2)}{ \def\mystartcontrol{#1} \def\mytargetcontrol{#2} }, bezier/limit/.store in=\mylimit, bezier/limit=1cm, bezier/.code={ \tikzset{bezier/.cd,#1} \tikzset{ to path={ let \p0=(\tikztostart), \p1=(\mystartcontrol), \p2=(\mytargetcontrol), \p3=(\tikztotarget), \n0={veclen(\x1-\x0,\y1-\y0)}, \n1={veclen(\x3-\x2,\y3-\y2)}, \n2={\mylimit} in \pgfextra{ \pgfmathtruncatemacro\ok{max((\n0>\n2),(\n1>\n2))} } \ifnum\ok=1 % let \p{01}=($(\p0)!.5!(\p1)$), \p{12}=($(\p1)!.5!(\p2)$), \p{23}=($(\p2)!.5!(\p3)$), \p{0112}=($(\p{01})!.5!(\p{12})$), \p{1223}=($(\p{12})!.5!(\p{23})$), \p{01121223}=($(\p{0112})!.5!(\p{1223})$) in to[bezier={controls={(\p{01}) and (\p{0112})}}] (\p{01121223}) to[bezier={controls={(\p{1223}) and (\p{23})}}] (\p3) \else [overlay=false] .. controls (\p1) and (\p2) .. (\p3) [overlay=true] \fi }, }%, <-- Comma here results in "Missing character: There is no , in font nullfont!" }, limit bb/.style n args={2}{ overlay, decorate, decoration={ show path construction, moveto code={}, lineto code={\path[#2] (\tikzinputsegmentfirst) -- (\tikzinputsegmentlast);}, curveto code={ \path[#2] (\tikzinputsegmentfirst) to[bezier={limit=#1,controls={(\tikzinputsegmentsupporta) and (\tikzinputsegmentsupportb)}}] (\tikzinputsegmentlast); }, closepath code={\path[#2] (\tikzinputsegmentfirst) -- (\tikzinputsegmentlast);}, }, }, limit bb/.default={1mm}{draw}, }

\usetikzlibrary{decorations.markings}

\begin{document} \usetikzlibrary{arrows,positioning} % arrows with middlearrow arrow head in middle \tikzset{middlearrow/.style={ decoration={markings, mark= at position 0.5 with {\arrow{#1}} , }, postaction={decorate} } % middlearrow/.default={>} } \lipsum[66] \begin{center} \begin{tikzpicture} \node[circle,fill=black,inner sep=2pt,label=b] (b) at (0,0) {}; \draw[middlearrow={>},limit bb] (b) .. controls (2,2) and (2,-2) .. (b); \draw[middlearrow={>},limit bb] (b) .. controls (-2,-2) and (-2,2) .. (b); \end{tikzpicture} \end{center} \lipsum[66] \end{document}

which returns an error of "I cannot decorate an empty path". (The second code works as desired removing either middlearrow={>} or limit bb from only the options of both arrows)

I suppose I'm looking for a less technical way of limiting the bounding box size, with manually being an option I'd gladly use.

Zarko
  • 296,517
George
  • 193

1 Answers1

2

Your problem can be solved by use of the bbox library:

\documentclass{scrarticle}
\usepackage{tikz}
\usetikzlibrary{arrows,
                bbox,                % <----
                decorations.markings,
                positioning}
\usepackage{lipsum}

\begin{document} \lipsum[66] \begin{center} \begin{tikzpicture}[bezier bounding box, % <---- middlearrow/.style={decoration={markings, mark=at position 0.5 with {\arrow{#1}} , }, postaction={decorate} } ]
\node[circle,fill=black,inner sep=2pt,label=b] (b) at (0,0) {}; \draw[middlearrow={>}] (b) .. controls (2,2) and (2,-2) .. (b); \draw[middlearrow={>}] (b) .. controls (-2,-2) and (-2,2) .. (b); \draw [brown] (current bounding box.south west) rectangle (current bounding box.north east); \end{tikzpicture} \end{center} \lipsum[66] \end{document}

enter image description here

Note: Libraries should be loaded in document preamble.

Zarko
  • 296,517
  • Thanks! I didn't realise there was a tikz package specifically for this, it's perfect for what I need! I'll make sure to load packages in the preamble too :) – George Nov 29 '22 at 19:32
  • @George, you are welcome! – Zarko Nov 29 '22 at 19:49