# Tikz : Creation of complex custom node

I've come again to pic your interesting brains.

I am trying to make a custom node with a drawing I've made

    \documentclass[tikz, margin=3mm]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{pgfplots,tikz}
\pgfplotsset{compat=1.16}
\usetikzlibrary{calc}

\tikzset{
pics/mynodeB/.style={
code={
\draw[fill] (0,0.5) circle (1cm);
\draw[line width=4pt] (0,0) circle (2.2cm) ;
\pgfmathsetmacro{\AngleA}{52.5}
\draw[fill] (0,-2) arc (-90:-37.8:2cm) arc (29:66.2:1.8cm) arc (-\AngleA:{-180+\AngleA}:1.2cm)  arc ({180-66.2}:{180-29}:1.8cm) arc ({-180+37.8}:-90:2cm) ;
}
},
cross/.style={path picture={
\draw[black] let
\p1 = (path picture bounding box.south),
\p2 = (path picture bounding box.north),
\n1 = {veclen((\x2-\x1),(\y2-\y1))}
in ($(path picture bounding box.south east)!0.5!(path picture bounding box.north west)$) circle (1cm);  % Change is to be made here
}},
}

\begin{document}

\begin{tikzpicture}
\draw[fill] (0,0.5) circle (1cm);
\draw[line width=4pt] (0,0) circle (2.2cm) ;
\pgfmathsetmacro{\AngleA}{52.5}
\draw[fill] (0,-2) arc (-90:-37.8:2cm) arc (29:66.2:1.8cm) arc (-\AngleA:{-180+\AngleA}:1.2cm)  arc ({180-66.2}:{180-29}:1.8cm) arc ({-180+37.8}:-90:2cm) ;

\pic[red] at (5,0) {mynodeB};
\node[cross,minimum size=2cm] at (10,0) {};
\end{tikzpicture}

\end{document}


It gives this

The first is the drawing I'm trying to use. You can see some weird numerical values because I had drawn it using filled circles and some clipping/reversed clipping but it was not working well when I tried to turn it into a node so I approximated the shape with arcs.

The red one is the same drawing done with a "pic" I defined (I don't really know what a pic is, I used a code I found here...). The problem is that a pic is not a node, and I can't use my usual commands to play with it.

The circle on the right is based on a simpler custom node I had made previously. I am trying to make the same drawing than before, but I must not use fixed length (or the shape won't be resized with the node). You can see I have tried in cross/.style evaluating the length \n1 of the node, but if I put \n1 where 1cm is, the circle disappears.

Do you have ideas ?

• Good evening, I did not understand your problem. – AndréC Apr 16 at 20:50
• I want to use the shape I've drawn as a node. You can criticize what I want to do, give me another way, or you can have an idea why the \n1 doesn't work. – LMT-PhD Apr 16 at 21:00
• If a pic is not a node, it is possible to create nodes in a pic and refer to them. So, depending on the use you will make of this pic, there is a solution to your problem. What will be the use of this pic? – AndréC Apr 17 at 5:16
• It looks as if you like to make symbols for people. Do you know the relaxed TikZ- library for people? You may check on CTAN for tikzpeople. – Harald Lichtenstein Apr 17 at 16:10

Quite hard to understand what you're looking for, but here's an attempt to answer. Pics are a way to save drawings and be able to reuse them. Hence, you can scale them too (like I did in violet).

A way to name a pic as a node is to give it the parameter local bounding box=A, for example. Then you can use A like a node, especially to place another one next to it, like I did (with the positioning library).

\documentclass[tikz,border=3.14mm]{standalone}
\usetikzlibrary{positioning}

\tikzset{
mypic/.pic={
\filldraw (0,0.5) circle (1cm);
\draw[line width=4pt] (0,0) circle (2.2cm) ;
\pgfmathsetmacro{\AngleA}{52.5}
\filldraw (0,-2) arc (-90:-37.8:2cm) arc (29:66.2:1.8cm) arc (-\AngleA:{-180+\AngleA}:1.2cm)  arc ({180-66.2}:{180-29}:1.8cm) arc ({-180+37.8}:-90:2cm) ;
}
}

\begin{document}

\begin{tikzpicture}[on grid]
\pic[red,local bounding box=A] {mypic};
\pic[violet,scale=0.5,right=4 cm of A] {mypic};
\end{tikzpicture}

\end{document}

• Thank you for your answer, I'll try it out – LMT-PhD Apr 17 at 8:12
• +1 but quick question (not OP). What is the advantage of using pic instead if a macro that draws the image every time? – Jes Apr 17 at 10:04

You were almost there. You only need to introduce a scale factor that allows you to scale the pic without resorting to the scale key because otherwise you may be in trouble if you use the scale key on the node.

\documentclass[tikz, margin=3mm]{standalone}
\usetikzlibrary{calc}
\tikzset{
pics/mynodeB/.style={
code={
\pgfmathsetmacro{\AngleA}{52.5}
}
},pics/mynodeB/.default=1,
cross/.style={circle,path picture={
\path let
\p1 = (path picture bounding box.south west),
\p2 = (path picture bounding box.north east),
\n1 = {scalar(veclen(\x2-\x1,\y2-\y1)/4.4cm/sqrt(2))}
in (path picture bounding box.center)
pic{mynodeB=\n1};
}},
}

\begin{document}
\begin{tikzpicture}
\draw[fill] (0,0.5) circle (1cm);
\draw[line width=4pt] (0,0) circle (2.2cm) ;
\pgfmathsetmacro{\AngleA}{52.5}
\draw[fill] (0,-2) arc (-90:-37.8:2cm) arc (29:66.2:1.8cm) arc (-\AngleA:{-180+\AngleA}:1.2cm)  arc ({180-66.2}:{180-29}:1.8cm) arc ({-180+37.8}:-90:2cm) ;
\pic[red] at (5,0) {mynodeB};
\node[cross,minimum size=2cm] (A) at (10,0) {};
\node[cross,minimum size=2cm,blue] (B) at (14,0) {};
\draw[thick,orange] (A.45) to[out=45,in=-135] (B.-135);
\end{tikzpicture}
\end{document}


• Thank you for your answer, it's simple and using a node. – LMT-PhD Apr 17 at 8:17
• Can you help me again, I've tried your solution, I'm quite happy with it, but there is something weird with line width, see for yourself the difference between \draw pic{mynode}; and \node[cross,minimum size=4.4cm] (C) at (5,0) {}; – LMT-PhD Apr 21 at 21:34
• Nodes seem to have a circle clip (1cm in diameter) on them – LMT-PhD Apr 23 at 6:25
• The path picture clips against the boundary path, which is a circle. If you choose minimum size=2cm, the radius is 1cm, yes. – user240002 Apr 23 at 6:28

Why not abuse a little bit from path picture? If the node is a circle with minimum size, it's possible measure this size and draw a figure proportional to it.

Following code need some adjustments, but it shows the idea

\documentclass[tikz, margin=3mm]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{calc}

\tikzset{
\fill let \p1=($(path picture bounding box.north)-(path picture bounding box.south)$), \n1={veclen(\p1)} in ([yshift=.1*\n1]path picture bounding box.center) circle(0.22*\n1);
\fill let \p1=($(path picture bounding box.north)-(path picture bounding box.south)$), \n1={veclen(\p1)} in
([shift={(45:.25*\n1)}]path picture bounding box.-135) to[out=-45, in=-135]
([shift={(135:.25*\n1)}]path picture bounding box.-45) to[bend right]
([shift={(135:.5*\n1)}]path picture bounding box.-45) to[out=-135, in=-45]
([shift={(45:.5*\n1)}]path picture bounding box.-135) to[bend right] cycle
;
}}
}

\begin{document}

\begin{tikzpicture}

\node[head, minimum size=4cm, draw, blue, line width=1mm] (a) {};

\node[head, minimum size=2cm, draw, green, line width=1mm] at (4,0) (b) {};

\node[head, minimum size=1cm, draw, red] at (4,2) (b) {};

\end{tikzpicture}

\end{document}


Update: Reduced code.

Previous code solution can be reduced with the help of Mark Wibrow's "alias" and compacting both fill commands into only one.

\documentclass[tikz, margin=3mm]{standalone}
\usepackage[utf8]{inputenc}
\usepackage{tikz}
\usetikzlibrary{calc}

\tikzset{
alias path picture bounding box/.code=\pgfnodealias{#1}{path picture bounding box},
\tikzset{alias path picture bounding box=@}
\fill let \p1=($(@.north)-(@.south)$), \n1={veclen(\p1)} in ([yshift=.1*\n1]@.center) circle(0.22*\n1)%;
([shift={(45:.25*\n1)}]@.-135) to[out=-45, in=-135]
([shift={(135:.25*\n1)}]@.-45) to[bend right]
([shift={(135:.5*\n1)}]@.-45) to[out=-135, in=-45]
([shift={(45:.5*\n1)}]@.-135) to[bend right] cycle
;
}}
}

\begin{document}

\begin{tikzpicture}

\node[head, minimum size=4cm, draw, blue, line width=1mm] (a) {};

\node[head, minimum size=2cm, draw, green, line width=1mm] at (4,0) (b) {};

\node[head, minimum size=1cm, draw, red] at (4,2) (b) {};

\end{tikzpicture}

\end{document}

• Thank you for your answer, it removes the use of 'pic'. – LMT-PhD Apr 24 at 8:47
• When I play with that solution the drawback I have is the use of 'let', which you have to copy an paste for every command you use. That gives me some wet programming. – LMT-PhD Apr 24 at 9:26
• @LMT-PhD With the help of an alias for pathpicture bounding box (see tex.stackexchange.com/a/395641/1952) you can save some typing. And in this particular case, "head" and "body" can be drawn within one command which means only one let expression. See the updated code. – Ignasi Apr 26 at 10:32