5

I am trying to create a custom tikz object (mainly based on Complex objects in TikZ: pgfkeys scope and best practice), called blk, which is basically a node with some additional anchor points and optional arguments.

For instance, here blk is simply a node with an additional text label below:

\documentclass[tikz]{standalone}
\usepackage{ifthen}
\makeatletter
% attribute of my custom object
\pgfkeys{
  /blk/.cd,
  label/.initial={},
  }
 % Custom object 'blk' :
\newcommand*{\blk}[1][]{\@blk[#1]}
\def\@blk[#1]#2(#3)#4;{{
\pgfkeys{/blk/.cd,#1}
\pgfkeysgetvalue{/blk/label}\@label 
%
\node [draw,name/.expand once=#2] at (#3) {#4};
% label below 'blk'
\ifthenelse{\equal{\@label}{}}{%empty label
}{%
\node (lab) [below] at (#2.south) {\@label};
}
}}
\makeatother
\begin{document}
\begin{tikzpicture}
\blk[label=test blk]{A}(0,0){block with label};
\blk{B}(0,-2){block without label};
\end{tikzpicture}
\end{document}

which gives

enter image description here

As this object is mainly a node, I would like to be able to pass standard node options (like anchor, color, text width) through it, that is to say I would like to be able to

  • pass individual optional arguments as

    \blk[label= test blk,color = blue]{C}(0,-3){block with label and with a style};
    

without having to manually add all the keys in the definition of my object,

  • and/or pass directly styles

    \tikzset{active/.style={color=blue}}
    \blk[label= test blk,active]{C}(0,-3){block with label and with a style};
    

I feel that the posts How to submit a set of tikz command with pgfkeys? and Expansion Issues When Passing TikZ Styles to Macro Created by Macro may answer the second point, but I have some difficulties to understand them precisely as I am still struggling to understand tikz (and more generally latex) internal mechanics.

Edit To clarify the overall goal, here is my full blk object in its current state :

It is basically a node which has, in addition, a direction dir, a number of inputs nu and a number of output ny and a text label label. When a block blk is created, the anchor points associated to the inputs and outputs are created automatically on the adequate side of the node (determined by its direction).

\makeatletter
\pgfkeys{
  /blk/.cd,
  ny/.initial=1,
  nu/.initial=1,
  dir/.initial={right},
  name/.initial={},
  label/.initial=,
  height/.initial=-1,
  align/.initial=center,
  anchor/.initial=center,
  borderColor/.initial=black,
  txtwidth/.initial={},
  color/.initial={},
}
\newcommand*{\blk}[1][]{\@blk[#1]}
\def\@blk[#1]#2(#3)#4;{{
\pgfkeys{/blk/.cd,#1}
% get and save the values of the arguments
\pgfkeysgetvalue{/blk/ny}\@ny
\pgfkeysgetvalue{/blk/nu}\@nu
\pgfkeysgetvalue{/blk/dir}\@dir    
\pgfkeysgetvalue{/blk/label}\@label    
\pgfkeysgetvalue{/blk/height}\@height
\pgfkeysgetvalue{/blk/align}\@align
\pgfkeysgetvalue{/blk/borderColor}\@borderColor
\pgfkeysgetvalue{/blk/txtwidth}\@blkwidth

\coordinate (blkPos) at (#3);%

\ifthenelse{\equal{\@blkwidth}{}}{
    \node [draw=\@borderColor ,name/.expand once=#2,minimum height=\@height, align=\@align ,anchor =\pgfkeysvalueof{/blk/anchor}] at (blkPos) {#4};
}{    
    \node [draw=\@borderColor ,name/.expand once=#2,minimum height=\@height, align=\@align ,anchor =\pgfkeysvalueof{/blk/anchor},text width=\@blkwidth ] at (blkPos) {#4};    
}
%\node [name/.expand once=#2] at (blkPos) {#4};    
% orientation of the block left to right (standard) or right to left (feedback)
\ifthenelse{\equal{\@dir}{right}}{%
    \coordinate (#2 inputSide) at (#2.west);
    \coordinate (#2 outputSide) at (#2.east);    
    \pgfmathsetmacro{\minD}{-4}
}{%
    \coordinate (#2 inputSide) at (#2.east);
    \coordinate (#2 outputSide) at (#2.west);    
    \pgfmathsetmacro{\minD}{4}    
}
% label of the block
\ifthenelse{\equal{\@label}{}}{%empty label
}{%
\node (lab) [below] at (#2.south) {\@label};
}
% height of the block
\newdimen{\yt}
\pgfextracty{\yt}{\pgfpointanchor{#2}{north}}
\newdimen{\yb}
\pgfextracty{\yb}{\pgfpointanchor{#2}{south}}
\pgfmathabs{\yt-\yb}
\pgfmathsetmacro{\height}{\pgfmathresult*0.035}
% adding inputs
\foreach \inNum in {1,...,\@nu}
{
% creation of the anchor points for the inputs
  \coordinate (#2 initu\inNum) at ($(#2 inputSide) + (0,{(\@nu/2-((\inNum-1)+1/2))*\height/\@nu})$);
  \coordinate (#2 u\inNum) at ($(#2 initu\inNum)+(\minD pt,0)$);
}
%adding outputs
\foreach \outNum in {1,...,\@ny}
{
  \coordinate (#2 inity\outNum) at ($(#2 outputSide) + (0,{(\@ny/2-((\outNum-1)+1/2))*\height/\@ny})$);
  \coordinate (#2 y\outNum) at ($(#2 inity\outNum)-(\minD pt,0)$);
}
}}
\makeatother

As you can see, I began to add additional keys to blk to pass optional arguments to the underlying node but this became tedious..

Together with another object called signal (in charge of drawing the path between 2 blocks), I can writte quite easily block diagrams

\begin{tikzpicture}
\blk[nu=3,ny=3,anchor = east,align=center]{A}(0,0){A};
\blk[nu=2,ny=1,anchor = east]{B}({$(A u2)-(1.5,0)$}){B};
\blk[dir=left,nu=2,ny=1,anchor = south east,align=center]{C}({$(B.east)+(0,0.5)$}){C};
\blk[ny=1,align=center]{D}({$(B u2) +(-2,0)$}){D};
\blk[nu=2,ny=1,anchor=north east]{E}({$(B.east)-(0,0.5)$}){E};

% direct link can be handled easily
\signal(C y1)(B u1);
\signal(B y1)(A u2);
\signal(E y1)(A u3);
\signal(D y1)(B u2);
% backward signals
\signal(A y1)(C u1);
\signal[ctrl=1,yoffset={-0.9cm,0},xoffset={0.1cm,0.1cm}](A y2)(E u1);
\signal[ctrl=1,yoffset={-1cm,0}](A y3)(E u2);
\end{tikzpicture}

which gives

enter image description here

  • Why complicate life? There is \pic offered by tikz. – user11232 Apr 15 '15 at 8:25
  • The goal of my object blk is to build block diagrams. That is to say that each block has a given number of inputs/outputs (specified as optional argument) with associated anchor points and labels. The inputs and outputs of these blocks can then be linked together through a custom object signal which draws an orthogonal path. The example given here is just the basis of the blk object. So I am not sure to see how \pic (which I did not know though) could help me. – Pierre Vuillemin Apr 15 '15 at 8:55
  • All these are possible with pic. Try it :-) – user11232 Apr 15 '15 at 9:00
2

I don't understand how your code works, so my solution is not good enough but will show how to proceed.

You just need an optional parameter with all customizing options. In following code this optional parameter is not optional but it shows how it works.

\documentclass[tikz]{standalone}
\usepackage{ifthen}
\makeatletter
% attribute of my custom object
\pgfkeys{
  /blk/.cd,
  label/.initial={},
  }
 % Custom object 'blk' :
\newcommand*{\blk}[1][]{\@blk[#1]}
\def\@blk[#1,#2]#3(#4)#5;{{
\pgfkeys{/blk/.cd,#1}
\pgfkeysgetvalue{/blk/label}\@label 
%
\node [draw,name/.expand once=#3,#2] at (#4) {#5};
% label below 'blk'
\ifthenelse{\equal{\@label}{}}{%empty label
}{%
\node (lab) [below] at (#3.south) {\@label};
}
}}
\makeatother
\begin{document}
\begin{tikzpicture}
\blk[label=test blk,red]{A}(0,0){block with label};
\blk[,minimum width=5cm, line width=1mm, green, fill=green!20]{B}(0,-2){block without label};
\end{tikzpicture}
\end{document}

enter image description here

|improve this answer|||||
  • This solution is certainly the simplest and I will definitively use it if I don't find something which enables my object blk to be completly transparent. What I mean is that, with that solution, the order of the optional arguments matters, I cannot writte things like \blk[line width=1mm,label=test blk, color=green]{B}(0,-2){blk}; – Pierre Vuillemin Apr 15 '15 at 9:15
  • @PierreVuillemin If you explain how is this complex object and what do you want to get from it, it's possible to find another more suitable declaration. Did you try with a pic as Harish suggested? – Ignasi Apr 15 '15 at 9:25
  • I have added the complete code of my object and an example of the final code/result I currently obtain. Before Harish mentioned it, I did not know pic but I will try it. – Pierre Vuillemin Apr 15 '15 at 10:17
  • I'll look at your code, but in the mean time, maybe this flip-flop shape helps you. – Ignasi Apr 15 '15 at 13:37
  • @PierreVuillemin I was going to write an example with a pic, but I've found tikz-conditional-setting-of-shape-parameters which contain complex nodes. In your case, the pic could be a node with coordinates as input and output ports. – Ignasi Apr 16 '15 at 18:22

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.