Motivation
In the answer Highlight a group of nodes in a tikz tree, Jake suggested combining the convex hull approach from padded boundary of convex hull with the hobby path and I was really intrigued by the possibility.
Preliminary work
At first I tried to modify at least as possible the \convexpath
:
\documentclass[a4paper,11pt]{article}
\usepackage{tikz}
\usetikzlibrary{hobby,backgrounds,calc,trees}
\newcommand{\myconvexpath}[2]{
[
create hobbyhullnodes/.code={
\global\edef\namelist{#1}
\foreach [count=\counter] \nodename in \namelist {
\global\edef\numberofnodes{\counter}
\node at (\nodename) [draw=none,name=hobbyhullnode\counter] {};
}
\node at (hobbyhullnode\numberofnodes) [name=hobbyhullnode0,draw=none] {};
\pgfmathtruncatemacro\lastnumber{\numberofnodes+1}
\node at (hobbyhullnode1) [name=hobbyhullnode\lastnumber,draw=none] {};
},
create hobbyhullnodes
]
($(hobbyhullnode1)!#2!-90:(hobbyhullnode0)$)
\foreach [
evaluate=\currentnode as \previousnode using \currentnode-1,
evaluate=\currentnode as \nextnode using \currentnode+1
] \currentnode in {1,...,\numberofnodes} {
let \p1 = ($(hobbyhullnode\currentnode)!#2!-90:(hobbyhullnode\previousnode) - (hobbyhullnode\currentnode)$),
\n1 = {atan2(\x1,\y1)},
\p2 = ($(hobbyhullnode\currentnode)!#2!90:(hobbyhullnode\nextnode) - (hobbyhullnode\currentnode)$),
\n2 = {atan2(\x2,\y2)},
\n{delta} = {-Mod(\n1-\n2,360)}
in
{arc [start angle=\n1, delta angle=\n{delta}, radius=#2]}
..($(hobbyhullnode\nextnode)!0.5!(hobbyhullnode\currentnode)$)
..($(hobbyhullnode\nextnode)!#2!-90:(hobbyhullnode\currentnode)$)
}
--cycle
}
\begin{document}
\begin{tikzpicture}[use Hobby shortcut]
\node (f) {f}
child { node (g) {g}
child { node (a) {a}
}
child { node (b) {b}
}
}
child { node (h) {h}
child { node (c) {c}
}
};
\begin{pgfonlayer}{background}
\fill[draw,blue, opacity=0.3] \myconvexpath{f,h,c,g}{12pt};
\fill[draw,red, opacity=0.3] \myconvexpath{g,b,a}{12pt};
\end{pgfonlayer}
\end{tikzpicture}
\end{document}
which leads to:
I suspected the combination of arcs
with the hobby path was the cause of cusps, so in another example I tried with:
\documentclass[a4paper,11pt]{article}
\usepackage{tikz}
\usetikzlibrary{hobby,backgrounds,calc,trees}
\newcommand{\myconvexpath}[2]{
[
create hobbyhullnodes/.code={
\global\edef\namelist{#1}
\foreach [count=\counter] \nodename in \namelist {
\global\edef\numberofnodes{\counter}
\node at (\nodename) [draw=none,name=hobbyhullnode\counter] {};
}
\node at (hobbyhullnode\numberofnodes) [name=hobbyhullnode0,draw=none] {};
\pgfmathtruncatemacro\lastnumber{\numberofnodes+1}
\node at (hobbyhullnode1) [name=hobbyhullnode\lastnumber,draw=none] {};
},
create hobbyhullnodes
]
($(hobbyhullnode1)!#2!-90:(hobbyhullnode0)$)
\foreach [
evaluate=\currentnode as \previousnode using \currentnode-1,
evaluate=\currentnode as \nextnode using \currentnode+1
] \currentnode in {1,...,\numberofnodes} {
let \p1 = ($(hobbyhullnode\currentnode)!#2!-90:(hobbyhullnode\previousnode)$),
\n1 = {atan2(\x1,\y1)},
\p2 = ($(hobbyhullnode\currentnode)!#2!90:(hobbyhullnode\nextnode)$),
\n2 = {atan2(\x2,\y2)},
\n{delta} = {-Mod(\n1-\n2,360)},
\n{end}={add(\n1,\n{delta})}
in
{..([in angle=\n1]$(hobbyhullnode\currentnode)!#2!-90:(hobbyhullnode\previousnode)$)..([out angle=\n{end}]$(hobbyhullnode\currentnode)!#2!90:(hobbyhullnode\nextnode)$)}
..($(hobbyhullnode\nextnode)!0.5!(hobbyhullnode\currentnode)$)
..($(hobbyhullnode\nextnode)!#2!-90:(hobbyhullnode\currentnode)$)
}
--cycle
}
\begin{document}
\begin{tikzpicture}[use Hobby shortcut]
\node (f) {f}
child { node (g) {g}
child { node (a) {a}
}
child { node (b) {b}
}
}
child { node (h) {h}
child { node (c) {c}
}
};
\begin{pgfonlayer}{background}
\fill[draw,blue, opacity=0.3] \myconvexpath{f,h,c,g}{12pt};
\fill[draw,red, opacity=0.3] \myconvexpath{g,b,a}{12pt};
\end{pgfonlayer}
\end{tikzpicture}
\end{document}
that gives a not promising result:
Question
Is there a way to automatically recognize the node angle a path will fall when arrives near it? Doing things by hand, one can force a path to follow the desired direction, for example, h.north -> h.east -> h.south
, but how is it possible to do it automatically without the arc
syntax?
Notice that, for some shapes, one could proceed as follows:
\documentclass[a4paper,11pt]{article}
\usepackage{tikz}
\usetikzlibrary{hobby,backgrounds,calc,trees}
\newcommand{\hobbyconvexpath}[2]{
[
create hobbyhullnodes/.code={
\global\edef\namelist{#1}
\foreach [count=\counter] \nodename in \namelist {
\global\edef\numberofnodes{\counter}
\node at (\nodename) [draw=none,name=hobbyhullnode\counter] {};
}
\node at (hobbyhullnode\numberofnodes) [name=hobbyhullnode0,draw=none] {};
\pgfmathtruncatemacro\lastnumber{\numberofnodes+1}
\node at (hobbyhullnode1) [name=hobbyhullnode\lastnumber,draw=none] {};
},
create hobbyhullnodes
]
($(hobbyhullnode1)!#2!-40:(hobbyhullnode0)$)
\foreach [
evaluate=\currentnode as \previousnode using \currentnode-1,
evaluate=\currentnode as \nextnode using \currentnode+1
] \currentnode in {1,...,\numberofnodes} {
let \p1 = ($(hobbyhullnode\currentnode)!#2!-90:(hobbyhullnode\previousnode) $),
\n1 = {atan2(\x1,\y1)},
\p2 = ($(hobbyhullnode\currentnode)!#2!-90:(hobbyhullnode\nextnode)$),
\n2 = {atan2(\x2,\y2)},
\n{delta} = {-Mod(\n1-\n2,360)},
\n{fin}={add(\n1,\n{delta})}
in
{..($(hobbyhullnode\currentnode)!#2!-220:(hobbyhullnode\previousnode)$)..($(hobbyhullnode\currentnode)!#2!40:(hobbyhullnode\nextnode)$)}
%{arc [start angle=\n1, end angle=\n{fin}, radius=#2]}
..($(hobbyhullnode\nextnode)!0.5!(hobbyhullnode\currentnode)$)
..($(hobbyhullnode\nextnode)!#2!-40:(hobbyhullnode\currentnode)$)
}
--cycle
}
\begin{document}
\begin{tikzpicture}[use Hobby shortcut]
\foreach \place/\text in {{(1,0)/a},{(0,-1)/b},{(-1,0)/c},{(0,1)/d}}
\node[name=\text] at \place {\text};
\begin{pgfonlayer}{background}
\fill[draw,green, opacity=0.3] \hobbyconvexpath{a,b,c,d}{10pt};
\end{pgfonlayer}
\end{tikzpicture}
\end{document}
but in general is not a valid approach and it is still to improve, to get at least the same result of Highlight a group of nodes in a tikz tree.
(pos)..controls (controll point)and(controll point)..
would give similar results? Actually, when I answered in Highlight a group of nodes in a tikz tree I didn't considered the possibility...