TransWikia.com

Draw a line flying across shapes and text content

TeX - LaTeX Asked by Eric Sun on April 1, 2021

I want to draw a line between 2 nodes which may fly across existing shape and text content. In the example below, the line connecting a and b are intersecting with the label of init node. I can manually do a "line fly" after I notice the fact from tikz result. But is there some facility which can judge such circumstances and do automatical handling on the run? Something like draw [flyline, ->] (a) to (b)

documentclass[convert]{standalone}
usepackage{tikz}
usetikzlibrary{shapes, positioning}

begin{document}
    begin{tikzpicture}[auto]
        node[rectangle, draw=black, label={right:this is a test}] (init) {hello};
        node[rectangle, draw=black, above right=of init] (a) {a};
        node[rectangle, draw=black, below right=of init] (b) {b};
        draw [->] (a) to (b);
        % I can change to use this after I find the intersect fact from the result
        %draw (a) to (a|-init.north);
        %draw [->] (b|-init.south) to (b);
    end{tikzpicture}
end{document}


Update:
Response to @Rmano’s comment : Thansk for the reply. Yes, use layer can partly resolve my problem. I used `tikz-layers` package which provide 5 predefined layers. Code snippets is as the following:

documentclass[convert]{standalone}
usepackage{tikz}
usetikzlibrary{shapes, positioning, fit}
usepackage{tikz-layers}

begin{document}
    begin{tikzpicture}[auto]
        node[rectangle, draw=black, label={[fill=white, inner sep=2pt, name=lbl]right:this is a test}] (init) {hello};
        node[rectangle, draw=black, above right=of init] (a) {a};
        node[rectangle, draw=black, below right=of init] (b) {b};
        begin{scope}[on behind layer]
            draw [->] (a) to (b);
        end{scope}
        begin{scope}[on background layer]
            node [fit=(init)(a)(b)(lbl), fill=cyan] () {};
        end{scope}
    end{tikzpicture}
end{document}

Which gives the following result

One thing which I feel not quite perfect is that this makes the label covering background fill. Originally label is only text, now it get a shape which is not transparent to background fill. We can change the label fill the same as background fill cyan, but that create another dependency.

Is it possible that label can has a virtual boundary, which only masks underlining draw but not underlining fill?


Update : per @Rmano’s suggestion to use `contour`, update the MWE to the following

documentclass[convert]{standalone}
usepackage{tikz}
usetikzlibrary{shapes, positioning, fit}
usepackage{tikz-layers}
usepackage{bidicontour}
usepackage{bidi}
bidicontourlength{2pt}

begin{document}
    begin{tikzpicture}[auto]
        node[rectangle, draw=black, label={[inner sep=2pt, name=lbl]right:{bidicontour{cyan}{this is a test}}}] (init) {hello};
        node[rectangle, draw=black, above right=of init] (a) {a};
        node[rectangle, draw=black, below right=of init] (b) {b};
        begin{scope}[on behind layer]
            draw [->] (a) to (b);
        end{scope}
        begin{scope}[on background layer]
            node [fit=(init)(a)(b)(lbl), fill=cyan] () {};
        end{scope}
        %draw (a) to (a|-init.north);
        %draw [->] (b|-init.south) to (b);
    end{tikzpicture}
end{document}

Which yields nearly perfect result

Thanks for the help!

One Answer

Is it possible that label can has a virtual boundary, which only masks underlining draw but not underlining fill?

I guess not.

Also in my opinion, there is not much difference between writing label={[fill=cyan]text} and label={[...]bidicontour{cyan}{text}}. One always need to explicitly write the background color in label={...}.

The following example shows an attempt to write the background color only once. The definition of pgfonlayerreversed environment is copied from my previous answer.

documentclass[tikz]{standalone}
usetikzlibrary{backgrounds, shapes, positioning, fit}

usepackage{xpatch}

makeatletter
% copied from my previous answer https://tex.stackexchange.com/a/562606
letpgfonlayerreversedpgfonlayer
letendpgfonlayerreversedendpgfonlayer

xpatchcmdpgfonlayerreversed
  {expandafterboxcsname pgf@layerbox@#1endcsnamebegingroup}
  {begingroup}
  {}{fail}

xpatchcmdendpgfonlayerreversed
  {endgroup}
  {endgroupexpandafterboxcsname pgf@layerbox@pgfonlayer@nameendcsname}
  {}{fail}

% similar to tikz@background@framed, but using "pgfonlayerreversed" envi
deftikz@background@framed@reversed{%
  tikz@background@save%
  pgfonlayerreversed{background}
    path[style=background rectangle] (tikz@bg@minx,tikz@bg@miny) rectangle (tikz@bg@maxx,tikz@bg@maxy);
  endpgfonlayerreversed
}%

% similar to option "show background rectangle"
tikzset{
  show background rectangle reversed/.style={
    execute at end picture=tikz@background@framed@reversed
  }
}
makeatother

% user interface
tikzset{
  background color/.style={
    show background rectangle reversed,
    inner frame sep=2pt,
    background rectangle/.append style={draw=none, #1},
    every node/.append style={#1},
    every label/.append style={#1}
  }
}

begin{document}
    begin{tikzpicture}[background color={fill=cyan}]
        node[draw, label={[inner sep=2pt, name=lbl]right:this is a test}] (init) {hello};
        node[draw, above right=of init] (a) {a};
        node[draw, below right=of init] (b) {b};
        
        begin{scope}[on background layer]
            draw [->] (a) to (b);
        end{scope}
    end{tikzpicture}
end{document}

enter image description here

Correct answer by muzimuzhi Z on April 1, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP