## LaTeX forum ⇒ Graphics, Figures & Tables ⇒ TikZ: Custom shape with input and output ports Topic is solved

Information and discussion about graphics, figures & tables in LaTeX documents.
johnahay
Posts: 3
Joined: Mon Jan 04, 2016 5:29 pm

### TikZ: Custom shape with input and output ports

Dear all!

I'm trying to create some blocks in tikz and create some edges between them. It should look like the attached image. (With more blocks obviously)
goal.png (4.5 KiB) Viewed 7728 times

Each block may have an arbitrary number of inputs on its left hand side, and an arbitrary number of outputs on its right hand side. (-> tikz-anchors?)
The block names, inputs and outputs are generated via a python3 script. (among other things)

I tried to create the block on the right first: "just" 2 inputs, 2 outputs. In the tikz manual I read about "anchors", "declareshape" and "circle split", so I tried to create a rectangle with a second label (somewhere).

It looks like I'm to dumb do that...

Edit:
Another question that I have:
Will I be able to use that with automatic layout?

Minimal code included below:

! Package PGF Math Error: Unknown function port' (in ' port')....! Missing number, treated as zero....! A <box> was supposed to be here....

\documentclass{standalone}\usepackage{tikz}\usetikzlibrary{shapes}\makeatletter     \begin{document} \newbox\pgfnodepartportbox \pgfdeclareshape{document}{	\nodeparts{text, port} 	\savedanchor\centerpoint{%		\pgf@x=.5\wd\pgfnodeparttextbox%		\pgfmathsetlength{\pgf@y}{10mm}%		\pgf@y=-\pgf@y%		\advance\pgf@y by-\dp\pgfnodeparttextbox%		\advance\pgf@y by-.5\pgflinewidth%	}%	\savedanchor\portanchor{%		\pgf@x=-.5\wd\pgfnodepartportbox%		\advance\pgf@x by.5\wd\pgfnodeparttextbox%		\pgfmathsetlength{\pgf@y}{10mm}%		\pgf@y=-2\pgf@y%		\advance\pgf@y by-\ht\pgfnodepartportbox%		\advance\pgf@y by-.5\pgflinewidth%		\advance\pgf@y by-\dp\pgfnodeparttextbox%		\advance\pgf@y by-.5\pgflinewidth%	} 	\inheritsavedanchors[from=rectangle]	\inheritanchorborder[from=rectangle]	\inheritanchor[from=rectangle]{center}	\inheritanchor[from=rectangle]{north}	\inheritanchor[from=rectangle]{south}	\inheritanchor[from=rectangle]{west}	\inheritanchor[from=rectangle]{east}	\inheritbackgroundpath[from=rectangle] 	\anchor{port}{\portanchor} } \begin{tikzpicture}	\node[draw,shape=circle split] (x) {Remark \nodepart{lower} test};	\node[draw,shape=document] at ([shift=(0:3cm)]x) (x) {test1 \nodepart{port} test2};\end{tikzpicture}\end{document}

Tags:

Stefan Kottwitz
Posts: 9597
Joined: Mon Mar 10, 2008 9:44 pm
Hi,

welcome to the forum!

I think programming shapes would be very challenging. That's because you require different anchors and node parts, so it's not just a single shape.

Perhaps it's manageable to create the shapes by macros. Each macro could draw a rectangular shape with text and small input and output nodes. Connection arrows could be pointed at those nodes.

I use macros myself to handle complex drawings with repeated parts. They can take arguments for node texts.

Stefan

johnahay
Posts: 3
Joined: Mon Jan 04, 2016 5:29 pm

As the data is generated by a python3 script, I think I may just create 1 shape definition for each different block. So port counts and sizes will not have to be generated by latex/tikz, alleviating the need for macros?

Problem is: I can't get a custom shape correctly defined in latex/tikz. I don't know latex/tikz enough to create any custom shape (or complex macros). So in my code, I tried to modify the circle split example but ran into the errors posted above.

I found the code for split circle *quite* difficult to understand, but I did not find an easier example. What I think the circle split code does:

\newbox\pgfnodepartlowerbox

Creates a box for the lower text label. Is this empty until the \nodepart command in instantiation via \createnode?

\nodeparts{text,lower}

Tells tikz that my shape consists of two labels I can specify using \nodepart.

\savedanchor\centerpoint{%     \pgf@x=.5\wd\pgfnodeparttextbox%     \pgfmathsetlength{\pgf@y}{\pgfkeysvalueof{/pgf/inner ysep}}%     \pgf@y=-\pgf@y%     \advance\pgf@y by-\dp\pgfnodeparttextbox%     \advance\pgf@y by-.5\pgflinewidth%   }%

I think I don't understand this part for example: What variables are set by this? Does this influence shape sizes too? Is the position of the labels set here?

\inheritbackgroundpath[from=circle]   \beforebackgroundpath{     \pgfutil@tempdima=\radius%     \pgfmathsetlength{\pgf@xb}{\pgfkeysvalueof{/pgf/outer xsep}}%       \pgfmathsetlength{\pgf@yb}{\pgfkeysvalueof{/pgf/outer ysep}}%       \ifdim\pgf@xb<\pgf@yb%       \advance\pgfutil@tempdima by-\pgf@yb%     \else%       \advance\pgfutil@tempdima by-\pgf@xb%     \fi%     \advance\pgfutil@tempdima by-.5\pgflinewidth%       \pgfsetshortenstart{0pt}%     \pgfsetshortenend{0pt}%     \pgfsetarrows{-}%       \pgfpathmoveto{\pgfpointadd{\centerpoint}{\pgfqpoint{-1\pgfutil@tempdima}{0pt}}}%     \pgfpathlineto{\pgfpointadd{\centerpoint}{\pgfqpoint{\pgfutil@tempdima}{0pt}}}%     \pgfusepath{stroke}%   }

This part uses the radius variable to create the visible shapes horizontal line, the circle is inherited. How do the \advance correlate to the \advance in the anchor part?

I'm looking for some dead-simple example code for custom tikz shapes. (e.g. a block with 2 inputs and 2 outputs )

Stefan Kottwitz
Posts: 9597
Joined: Mon Mar 10, 2008 9:44 pm
Here is a suggestion using TikZ pic instead of pgf code. This can be adjusted.

\documentclass[border=10pt]{standalone}\usepackage{tikz}\usetikzlibrary{arrows.meta}\tikzset{>={Latex[width=3mm,length=5mm]}}\renewcommand*{\familydefault}{\sfdefault}\def\Width{1}\def\Heigth{0.5}\tikzset{   block/.style={     thick, draw,     minimum width=2.8cm, minimum height=2cm,     text width = 3cm, inner sep=0pt,     text = black, align=center, font=\LARGE,   },   pics/blockFourInputs/.style args = {#1/#2/#3/#4}{     code = {       \node [block] {\tikzpictext};       \node (-1) at (-\Width,-\Heigth) {#1};       \node (-2) at (-\Width,\Heigth)  {#2};       \node (-3) at  (\Width,\Heigth)  {#3};       \node (-4) at  (\Width,-\Heigth) {#4};     }   }}\begin{document}\begin{tikzpicture}   \pic (block1) [pic text = plup] at (6,3)     {blockFourInputs = p1/p2/o1/o2};   \pic (block2) [pic text = gen]  at (0,0)     {blockFourInputs = //out/};   \pic (block3) [pic text = more] at (6,-3,0)  {blockFourInputs = //in/};   \draw [->] (block2-3) to [in=-180, out=0] ++ (1,0)                         to [in=180,  out=0]    (block1-1);   \draw [->] (block1-4) to [in=90,   out=0] ++ (2,-2)                         to [in=0,    out=270]  (block3-3); \end{tikzpicture}\end{document}

tikz-pic.png (9.46 KiB) Viewed 7686 times

Stefan

johnahay
Posts: 3
Joined: Mon Jan 04, 2016 5:29 pm
Looks very good, I will try that. Thank you!

Stefan Kottwitz
Posts: 9597
Joined: Mon Mar 10, 2008 9:44 pm
It was a quick shot - pic` codes (TikZ 3.0 or above required) are easier than pgf shapes and you can do more in a similar way. Let me know if you would like to know more or if there's trouble in applying it.

And I'm very interested in your final drawings - can you tell us more, post results, perhaps also Python code? I use TikZ for comprehensive network drawings. Just to show, I attach a sample PDF, and embed a downsized preview bitmap. (Not that I post I noticed that my foreground/background bundling ellipses don't work well in the lower part - I accidentally made the lines in the lower parts background lines, to be corrected.)

bandwidth.png (120.21 KiB) Viewed 7684 times

Stefan
Attachments
bandwidth.pdf