This is and addendum of a previous question: How to connect pic
s through a set of colorful arrows using tikzpicture
environment.
I would like to be able to draw arrows that do not overlap with nodes and/or pictures without having to manually modify each and every one of the arrows that collide with them using tikz
.
The MWE is taken from marmot's nice answer:
\documentclass{article}
\usepackage[margin=0in,footskip=0in,paperwidth=60cm,paperheight=29cm]{geometry}
\usepackage[english]{babel}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{hyperref}
\usepackage{tikz}
\usetikzlibrary{positioning,fit,calc}
\pgfdeclarelayer{behind}
\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
\pgfsetlayers{behind,background,main,foreground}
\tikzset{
text field/.style={text height=1.5ex,align=center,rounded corners},
nonfillable title field/.style={text height=2ex,text depth=0.3em,anchor=south,text
width=5cm,align=center,font=\footnotesize\sffamily},
fillable title field/.style={text height=3.14ex,text depth=0em,anchor=south,text
width=5cm,align=center,font=\footnotesize\sffamily},
pics/fillable subject/.style={code={%
\node[text field] (-TF)
{\hspace*{-0.5em}\TextField[align=1,name=#1-day,width=1em,charsize=7pt,maxlen=2,bordercolor={1 1 1}]~~/\hspace*{-0.15em}\TextField[align=1,name=#1-month,width=1em,charsize=7pt,maxlen=2,bordercolor={1 1 1}]~~/\hspace*{-0em}\TextField[align=1,name=#1-year,width=2em,charsize=7pt,maxlen=4,bordercolor={1 1 1}]{}~};
\node[nonfillable title field] (-Title)
at ([yshift=0.4em]-TF.north) {#1};
\draw[rounded corners] (-TF.south west) |- (-Title.south west)
|- (-Title.north east) -- (-Title.south east) -| (-TF.south east)
-- cycle;
\draw ([xshift=4pt]-Title.south west) -- ([xshift=-4pt]-Title.south east);
}},
pics/nonfillable subject/.style={code={%
\node[text field] (-TF)
{\hspace{1.2em}~/~\hspace{1.15em}~/~\hspace{2.35em}{}};
\node[nonfillable title field] (-Title)
at ([yshift=0.4em]-TF.north) {#1};
\draw[rounded corners] (-TF.south west) |- (-Title.south west)
|- (-Title.north east) -- (-Title.south east) -| (-TF.south east)
-- cycle;
\draw ([xshift=4pt]-Title.south west) -- ([xshift=-4pt]-Title.south east);
}},
pics/fillable elective subject/.style={code={%
\node[text field] (-TF)
{\hspace*{-0.5em}\TextField[align=1,name=#1-day,width=1em,charsize=7pt,maxlen=2,bordercolor={1 1 1}]~~/\hspace*{-0.15em}\TextField[align=1,name=#1-month,width=1em,charsize=7pt,maxlen=2,bordercolor={1 1 1}]~~/\hspace*{-0em}\TextField[align=1,name=#1-year,width=2em,charsize=7pt,maxlen=4,bordercolor={1 1 1}]{}~};
\node[fillable title field] (-Title)
at ([yshift=0.4em]-TF.north) {\hspace*{-0.34em}\TextField[align=1,name=#1-electivesubject,width=4.5cm,charsize=8pt,height=.5cm,bordercolor={1 1 1}]{}};
\draw[rounded corners] (-TF.south west) |- (-Title.south west)
|- (-Title.north east) -- (-Title.south east) -| (-TF.south east)
-- cycle;
\draw ([xshift=4pt]-Title.south west) -- ([xshift=-4pt]-Title.south east);
}},
pics/nonfillable elective subject/.style={code={%
\node[text field] (-TF)
{\hspace{1.2em}~/~\hspace{1.15em}~/~\hspace{2.35em}{}};
\node[nonfillable title field] (-Title)
at ([yshift=0.4em]-TF.north) {};
\draw[rounded corners] (-TF.south west) |- (-Title.south west)
|- (-Title.north east) -- (-Title.south east) -| (-TF.south east)
-- cycle;
\draw ([xshift=4pt]-Title.south west) -- ([xshift=-4pt]-Title.south east);
}},
manoooh/.style={column sep=-1.75cm,row sep=5mm},
manooohE/.style={column sep=-2.25cm,row sep=5mm,anchor=south},
electives/.style={column sep=-7.25cm,row sep=5mm},
fit sep/.initial=4pt, % change width of node (big rectangle shape)
fit dist/.initial=40pt, % change node distance (big rectangle shape)
inlay top sep/.initial=24pt,
matrix top sep/.initial=24pt,
manoooh curve/.style={to path={let \p1=($(\tikztotarget)-(\tikztostart)$)
in (\tikztostart) .. controls ($(\tikztostart)+(#1*\x1,0)$)
and ($(\tikztotarget)+(-#1*\x1,0)$) .. (\tikztotarget)}},
manoooh curve/.default=0.3
} % From https://tex.stackexchange.com/a/478723/152550
\makeatletter% from https://tex.stackexchange.com/a/85531/121799
\long\def\ifnodedefined#1#2#3{%
\@ifundefined{pgf@sh@ns@#1}{#3}{#2}%
}
\makeatother
\begin{document}
\thispagestyle{empty} % To suppress page number
\noindent
\begin{tikzpicture}
\fill[white,fill=orange] (0,0) rectangle (\paperwidth,-2cm) node[midway,align=center,font=\Huge] {\bfseries Some text here\\\LARGE More text here};
\end{tikzpicture}
\ifdefined\mymatbottom
\else
\typeout{Please\space recompile\space your\space file!}
\def\mymatbottom{-150pt}
\fi
\ifdefined\myheight
\else
\def\myheight{0}
\typeout{Please\space recompile\space your\space file!}
\fi
\ifdefined\LstMatYShifts
\else
\def\LstMatYShifts{{0pt,0pt,0pt,0pt,0pt,0pt,0pt}}
\fi
\ifdefined\LstMatXShifts
\else
\def\LstMatXShifts{{0pt,0pt,0pt,0pt,0pt,0pt,0pt}}
\fi
%\typeout{height:\myheight}
%\typeout{xshifts(in):\LstMatXShifts}
\vfill
\centering
\begin{Form}
\begin{tikzpicture}
% step 1: add the matrices, name them mat0, mat1 etc.
\begin{scope}[local bounding box=matrices]
\matrix[manoooh] (mat0) at ({\LstMatXShifts[0]},{\LstMatYShifts[0]}) {
\pic[local bounding box=A] (0) {nonfillable subject={Subject A}}; \\
\pic (1) {nonfillable subject={Subject B}}; \\
};
\matrix[manoooh] (mat1) at ({\LstMatXShifts[1]},{\LstMatYShifts[1]}) {
\pic (2) {nonfillable subject={Subject C}}; \\
\pic (3) {nonfillable subject={Subject D}}; \\
\pic (4) {nonfillable subject={Subject E}}; \\
\pic (5) {nonfillable subject={Subject F}}; \\
\pic (6) {nonfillable subject={Subject G}}; \\
\pic (7) {nonfillable subject={Subject H}}; \\
\pic (8) {nonfillable subject={Subject I}}; \\
\pic[draw=red] (9) {nonfillable subject={Subject J}}; \\
};
\matrix[manoooh] (mat2) at ({\LstMatXShifts[2]},{\LstMatYShifts[2]}) {
\pic[draw=red] (10) {nonfillable subject={Subject K}}; \\
\pic (11) {nonfillable subject={Subject L}}; \\
\pic (12) {nonfillable subject={Subject A}}; \\
\pic (13) {nonfillable subject={Subject N}}; \\
\pic (14) {nonfillable subject={Subject O}}; \\
\pic (15) {nonfillable subject={Subject P}}; \\
\pic (16) {nonfillable subject={Subject Q}}; \\
\pic (17) {nonfillable subject={Subject R}}; \\
};
\matrix[manoooh] (mat3) at ({\LstMatXShifts[3]},{\LstMatYShifts[3]}) {
\pic[draw=red] (18) {nonfillable subject={Subject S}}; \\
\pic (19) {nonfillable subject={Subject T}}; \\
\pic (20) {nonfillable subject={Subject U}}; \\
\pic (21) {nonfillable subject={Subject V}}; \\
\pic (22) {nonfillable subject={Subject W}}; \\
\pic (23) {nonfillable subject={Subject X}}; \\
\pic (24) {nonfillable subject={Subject Y}}; \\
\pic (25) {nonfillable subject={Subject Z}}; \\
};
\matrix[manooohE] (matE3) at ({\LstMatXShifts[3]},\mymatbottom) {
\pic (L3E1) {nonfillable elective subject={Subject}}; & &
\pic (L3E2) {nonfillable elective subject={Subject}}; \\
& \pic (L3E3) {nonfillable elective subject={Subject}}; & \\
};
\matrix[manoooh] (mat4) at ({\LstMatXShifts[4]},{\LstMatYShifts[4]}) {
& \pic[draw=red] (26) {nonfillable subject={Subject AA}}; & \\
\pic (27) {nonfillable subject={Subject AB}}; & & \pic (28) {nonfillable subject={Subject AC}}; \\
& \pic (29) {nonfillable subject={Subject AD}}; & \\
& \pic (30) {nonfillable subject={Subject AE}}; & \\
& \pic (31) {nonfillable subject={Subject AF}}; & \\
& \pic (32) {nonfillable subject={Subject AG}}; & \\
};
\matrix[manooohE] (matE4) at ({\LstMatXShifts[4]},\mymatbottom) {
\pic (L4E1) {nonfillable elective subject={Subject}}; \\
};
\matrix[manoooh] (mat5) at ({\LstMatXShifts[5]},{\LstMatYShifts[5]}) {
\pic (33) {nonfillable subject={Subject AH}}; \\
\pic (34) {nonfillable subject={Subject AI}}; \\
\pic[draw=red] (35) {nonfillable subject={Subject AJ}}; \\
\pic (36) {nonfillable subject={Subject AK}}; \\
};
\matrix[manooohE] (matE5) at ({\LstMatXShifts[5]},\mymatbottom) {
\pic (L5E1) {nonfillable elective subject={Subject}}; \\
\pic (L5E2) {nonfillable elective subject={Subject}}; \\
\pic (L5E3) {nonfillable elective subject={Subject}}; \\
\pic (L5E4) {nonfillable elective subject={Subject}}; \\
\pic (L5E5) {nonfillable elective subject={Subject}}; \\
};
\end{scope}
\pgfmathsetmacro{\groupwidth}{0}
\pgfmathsetmacro{\lastwidth}{0}
\foreach \X in {0,...,5} %<- if you have more or less matrices, adjust 3
{
\node[anchor=south,yshift=1cm,align=center,font=\LARGE\bfseries\boldmath]
at (mat\X |-matrices.north) (L\X) {Level $\X$};
\ifnodedefined{matE\X}{% has inlay
\node[xshift=1em,anchor=south west,font=\LARGE\bfseries,opacity=0] (matEl\X) at (matE\X.north west) {Electives};
\begin{pgfonlayer}{background}
\path let \p1=($(mat\X.north east)-(mat\X.south west)$) in
node[fit=(matE\X) (matEl\X),inner ysep=5mm,fill=blue!30,rounded
corners=40pt,minimum width=\x1-2*\pgfkeysvalueof{/tikz/fit sep},
inner xsep=\pgfkeysvalueof{/tikz/fit sep}](F\X){};
\node[xshift=1em,anchor=south west,font=\LARGE\bfseries]
(matEl\X) at ([xshift=1.3em]F\X.west|-matEl\X.center) {Electives};
\end{pgfonlayer}
\path let \p1=($(mat\X.north east)-(mat\X.south west)$),
\p2=($(F\X.north east)-(F\X.south west)$),
\n1={max(abs(\y1)/2+abs(\y2)/2+0*\pgfkeysvalueof{/tikz/inlay top sep},\mymatbottom)}
in
\pgfextra{\xdef\mymatbottom{\n1}
\ifnum\X=0
\pgfmathsetmacro{\groupwidth}{0}
\else
\pgfmathsetmacro{\groupwidth}{\groupwidth+max(\x1,\x2)/2+\lastwidth/2+2*\pgfkeysvalueof{/tikz/fit sep}+\pgfkeysvalueof{/tikz/fit dist}}
\fi
\pgfmathsetmacro{\lastwidth}{max(\x1,\x2)+8*\pgfkeysvalueof{/tikz/fit sep}}
\xdef\lastwidth{\lastwidth}
\xdef\groupwidth{\groupwidth}
\pgfmathsetmacro{\myheight}{max(\y1+\y2+%
\pgfkeysvalueof{/tikz/inlay top sep}+\pgfkeysvalueof{/tikz/matrix top sep},%
\myheight)}
\xdef\myheight{\myheight}
\pgfmathsetmacro{\myshift}{(\pgfkeysvalueof{/tikz/inlay top sep}+\y2)/2}
\ifnum\X=0
\xdef\LstMatYShifts{\myshift pt}
\xdef\LstMatXShifts{0pt}
\else
\xdef\LstMatYShifts{\LstMatYShifts,\myshift pt}
\xdef\LstMatXShifts{\LstMatXShifts,\groupwidth pt}
\fi};
% the fit parameters determine the shape of the background rectangles
\begin{pgfonlayer}{behind}
\node[fit=(L\X) (mat\X) (matrices.south-|mat\X.south)
(matE\X) (matEl\X),inner ysep=8mm,inner xsep=4*\pgfkeysvalueof{/tikz/fit sep},
fill=orange!30,rounded corners=50pt](F\X){};
\end{pgfonlayer}}{% no inlay
\path
let \p1=($(mat\X.north east)-(mat\X.south west)$),
\n1={max(abs(\y1)/2,\mymatbottom)}
in
\pgfextra{\xdef\mymatbottom{\n1}
\ifnum\X=0
\pgfmathsetmacro{\groupwidth}{0}
\else
\pgfmathsetmacro{\groupwidth}{\groupwidth+\x1/2+\lastwidth/2+\pgfkeysvalueof{/tikz/fit dist}}
\fi
\xdef\groupwidth{\groupwidth}
\xdef\lastwidth{\x1}
\pgfmathsetmacro{\myheight}{max(\y1+\pgfkeysvalueof{/tikz/matrix top sep},\myheight)}
\xdef\myheight{\myheight}
\ifnum\X=0
\xdef\LstMatYShifts{0pt}
\xdef\LstMatXShifts{0pt}
\else
\xdef\LstMatYShifts{\LstMatYShifts,0pt}
\xdef\LstMatXShifts{\LstMatXShifts,\groupwidth pt}
\fi};
% the fit parameters determine the shape of the background rectangles
\begin{pgfonlayer}{behind}
\node[fit=(L\X) (mat\X) (matrices.south-|mat\X.south),inner ysep=8mm,
fill=orange!30,rounded corners=50pt](F\X){};
\end{pgfonlayer}
}
}
\makeatletter
\immediate\write\@mainaux{\xdef\string\mymatbottom{-\mymatbottom}\relax}
\immediate\write\@mainaux{\xdef\string\myheight{\myheight}\relax}
\immediate\write\@mainaux{\xdef\string\LstMatYShifts{{\LstMatYShifts}}\relax}
\immediate\write\@mainaux{\xdef\string\LstMatXShifts{{\LstMatXShifts}}\relax}
\makeatother
\newcommand\totalnodes{5} % Define the total of subjects that need arrows-1
% From https://tex.stackexchange.com/a/480685/152550
% now add the arrows.
\def\LstCon{%
{
"{2,...,9}",%subjects that 0 links
"{2,10,13,14}",%subjects that 1 links
"{11,14}",%subjects that 2 links
"{10,13,14,25}",%subjects that 3 links
"{36}",%subjects that 8 links
}
}
\foreach \X in {0,...,\totalnodes} {
\pgfmathsetmacro{\huenum}{\X*0.75*(1/\totalnodes)}
\definecolor{mycolor}{hsb}{\huenum,1,1}
\pgfmathsetmacro{\mylst}{\LstCon[\X]}
\foreach \Y in \mylst {
\draw[-latex,mycolor,very thick] (\X-Title.east)
to[manoooh curve] (\Y-Title.west);
}
}
\end{tikzpicture}
\end{Form}
\vfill
\end{document}
We would be able to see those arrows using something like this paths:
As you can see, some yellow, lightblue and the blue arrows have undergone changes due to the collision of one (or more) pic
s.
It is preferable that the algorithm detects that if many colors circulate in the same path, choose another one, since it would be visually confusing to have many colors in the same passage. For example:
If the detection of a lot of arrow traffic is a computational problem, leave it, it is not very important, I am satisfied with the automatic paths.
Thanks!!