Graphics, Figures & TablesTikZ: Custom shape with input and output ports

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

TikZ: Custom shape with input and output ports

Post by johnahay »

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
goal.png (4.5 KiB) Viewed 12740 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... :cry:

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

Minimal code included below:

Code: Select all

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

Code: Select all

\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}

Recommended reading 2024:

LaTeXguide.org • LaTeX-Cookbook.net • TikZ.org

NEW: TikZ book now 40% off at Amazon.com for a short time.

And: Currently, Packt sells ebooks for $4.99 each if you buy 5 of their over 1000 ebooks. If you choose only a single one, $9.99. How about combining 3 LaTeX books with Python, gnuplot, mathplotlib, Matlab, ChatGPT or other AI books? Epub and PDF. Bundle (3 books, add more for higher discount): https://packt.link/MDH5p

Stefan Kottwitz
Site Admin
Posts: 10324
Joined: Mon Mar 10, 2008 9:44 pm

Re: TikZ: Custom shape with input and output ports

Post by Stefan Kottwitz »

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
LaTeX.org admin
johnahay
Posts: 3
Joined: Mon Jan 04, 2016 5:29 pm

TikZ: Custom shape with input and output ports

Post by johnahay »

Hi, thanks for your reply!

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? :lol:

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:

Code: Select all

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

Code: Select all

\nodeparts{text,lower}
Tells tikz that my shape consists of two labels I can specify using \nodepart.

Code: Select all

\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?

Code: Select all

\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 :mrgreen: )
User avatar
Stefan Kottwitz
Site Admin
Posts: 10324
Joined: Mon Mar 10, 2008 9:44 pm

TikZ: Custom shape with input and output ports

Post by Stefan Kottwitz »

Here is a suggestion using TikZ pic instead of pgf code. This can be adjusted.

Code: Select all

\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
tikz-pic.png (9.46 KiB) Viewed 12698 times
Stefan
LaTeX.org admin
johnahay
Posts: 3
Joined: Mon Jan 04, 2016 5:29 pm

Re: TikZ: Custom shape with input and output ports

Post by johnahay »

Looks very good, I will try that. Thank you!
User avatar
Stefan Kottwitz
Site Admin
Posts: 10324
Joined: Mon Mar 10, 2008 9:44 pm

TikZ: Custom shape with input and output ports

Post by Stefan Kottwitz »

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
bandwidth.png (120.21 KiB) Viewed 12696 times
Stefan
Attachments
bandwidth.pdf
(32.7 KiB) Downloaded 643 times
LaTeX.org admin
Post Reply