2

I use macro to define a group elements into a scope. when I try to positioning it with library,it sounds like doesn't process this case:

\documentclass[border=2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{chains,positioning,fit,calc}  
\makeatletter
\pgfdeclareshape{cross}{
    \inheritsavedanchors[from=circle]
    \inheritanchorborder[from=circle]
    \inheritbackgroundpath[from=circle]
    \foreach \i in {center,north,south,east,west} {
        \inheritanchor[from=circle]{\i}
    }
    \backgroundpath{
        \pgfpathcircle{\pgfpointorigin}{\radius}%
    }
    \foregroundpath{
    \pgfpathmoveto{\pgfpointpolar{-135}{\radius}}%
    \pgfpathlineto{\pgfpointpolar{45}{\radius}}%
    \pgfpathmoveto{\pgfpointpolar{135}{\radius}}%
    \pgfpathlineto{\pgfpointpolar{-45}{\radius}}%
    \pgfusepath{draw}
    }
}
\makeatother
\tikzset{PAD/.style n args={2}{
        start chain=#1,node distance=1mm,minimum width=#2,
        pad/.append  style={on chain,draw,cross,minimum size=0.5cm},
}}
\newcommand{\PINH}[4][] {%[red]{1em}{F}{A,B,C,D}
\begin{scope}[#1,PAD={going right}{#2},local bounding box=#3]
    \foreach \s [count=\i] in {#4} {
        \node[pad,label={[yshift=1mm]above:\s}] (#3\i) {};
    }
    \node[fit=(#31)(#3\i),draw] (F1) {};
\end{scope}
}
\newcommand{\PINV}[4][] {%[red]{1em}{F}{A,B,C,D}
\begin{scope}[#1,PAD={going below}{#2},local bounding box=#3]
    \foreach \s [count=\i] in {#4} {
        \node[pad,label={[xshift=-1mm]left:\s}] (#3\i) {};
    }
    \node[fit=(#31)(#3\i),draw] (F1) {};
\end{scope}
}
\begin{document}
    \begin{tikzpicture}
    \PINH{1em}{S1}{A,B,C,D};
    \PINV[below=1cm of S1]{1em}{S2}{E,F,G,H};
    \end{tikzpicture}
\end{document}

enter image description here

I wish to use relative positioning but do not want to use absolute positioning!

2

I think there is a slight misunderstanding what a scope does. A scope applies its optional arguments to everything that is in it. So it would apply below=1cm of S1, which then gets mixed up with the relative positioning done by the chain. (Think of it trying to say \node[right=1cm of S1] at (0,0 ..., in which case you also have two contradicting statements, and correspondingly a curious result.) If you, however, add a relative shift, it works as you might want it to work.

\documentclass[border=2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{chains,positioning,fit,calc}  
\makeatletter
\pgfdeclareshape{cross}{
    \inheritsavedanchors[from=circle]
    \inheritanchorborder[from=circle]
    \inheritbackgroundpath[from=circle]
    \foreach \i in {center,north,south,east,west} {
        \inheritanchor[from=circle]{\i}
    }
    \backgroundpath{
        \pgfpathcircle{\pgfpointorigin}{\radius}%
    }
    \foregroundpath{
    \pgfpathmoveto{\pgfpointpolar{-135}{\radius}}%
    \pgfpathlineto{\pgfpointpolar{45}{\radius}}%
    \pgfpathmoveto{\pgfpointpolar{135}{\radius}}%
    \pgfpathlineto{\pgfpointpolar{-45}{\radius}}%
    \pgfusepath{draw}
    }
}
\makeatother
\tikzset{PAD/.style n args={2}{
        start chain=#1,node distance=1mm,minimum width=#2,
        pad/.append  style={on chain,draw,cross,minimum size=0.5cm},
}}
\newcommand{\PINH}[4][] {%[red]{1em}{F}{A,B,C,D}
\begin{scope}[#1,PAD={going right}{#2},local bounding box=#3]
    \foreach \s [count=\i] in {#4} {
        \node[pad,label={[yshift=1mm]above:\s}] (#3\i) {};
    }
    \node[fit=(#31)(#3\i),draw] (F1) {};
\end{scope}
}
\newcommand{\PINV}[4][] {%[red]{1em}{F}{A,B,C,D}
\begin{scope}[#1,PAD={going below}{#2},local bounding box=#3]
    \foreach \s [count=\i] in {#4} {
        \node[pad,label={[xshift=-1mm]left:\s}] (#3\i) {};
    }
    \node[fit=(#31)(#3\i),draw] (F1) {};
\end{scope}
}
\begin{document}
    \begin{tikzpicture}
    \PINH{1em}{S1}{A,B,C,D};
    \PINV[shift={([yshift=-0.5cm,xshift=1em]S1.south west)}]{1em}{S2}{E,F,G,H};
    \end{tikzpicture}
\end{document}

enter image description here

1

An alternative way with matrix. They are nodes, therefore you don't need scopes and can use relative positioning.

\documentclass[border=2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning,matrix}  
\makeatletter
\pgfdeclareshape{cross}{
    \inheritsavedanchors[from=circle]
    \inheritanchorborder[from=circle]
    \inheritbackgroundpath[from=circle]
    \foreach \i in {center,north,south,east,west} {
        \inheritanchor[from=circle]{\i}
    }
    \backgroundpath{
        \pgfpathcircle{\pgfpointorigin}{\radius}%
    }
    \foregroundpath{
    \pgfpathmoveto{\pgfpointpolar{-135}{\radius}}%
    \pgfpathlineto{\pgfpointpolar{45}{\radius}}%
    \pgfpathmoveto{\pgfpointpolar{135}{\radius}}%
    \pgfpathlineto{\pgfpointpolar{-45}{\radius}}%
    \pgfusepath{draw}
    }
}
\makeatother

\begin{document}
    \begin{tikzpicture}[
        mycross/.style={%
            draw, 
            cross, 
            inner sep=.3333em, 
            minimum size=.5, 
            anchor=center},
        mybox/.style={%
            matrix of nodes,
            column sep=1mm,
            row sep=1mm,
            draw,
            nodes=mycross,
            nodes in empty cells}
        ]
    \matrix[mybox] (A) {&&&\\};
     \matrix[mybox, below right=1mm and 0pt of A.south west] (B) {\\ \\ \\ \\};
     \foreach \i [count=\ni] in {A,...,D}
        \node[above] at (A.north-|A-1-\ni) {\i};
     \foreach \i [count=\ni] in {E,...,H}
        \node[left] at (B.west|-B-\ni-1) {\i};
    \end{tikzpicture}
\end{document}

enter image description here

1

Another solution with pic:

\documentclass[border=2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{chains,positioning,fit,calc}  
\makeatletter
\pgfdeclareshape{cross}{
    \inheritsavedanchors[from=circle]
    \inheritanchorborder[from=circle]
    \inheritbackgroundpath[from=circle]
    \foreach \i in {center,north,south,east,west} {
        \inheritanchor[from=circle]{\i}
    }
    \backgroundpath{
        \pgfpathcircle{\pgfpointorigin}{\radius}%
    }
    \foregroundpath{
        \pgfpathmoveto{\pgfpointpolar{-135}{\radius}}%
        \pgfpathlineto{\pgfpointpolar{45}{\radius}}%
        \pgfpathmoveto{\pgfpointpolar{135}{\radius}}%
        \pgfpathlineto{\pgfpointpolar{-45}{\radius}}%
        \pgfusepath{draw}
    }
}
\makeatother
\tikzset{
    pics/PINH/.style={
        code = {
            \message{PINH params: #1}
            \foreach \s [count=\i] in {#1} {
                \message{count: \i,\s}
                \node[draw,cross,minimum size=0.5cm,label={above:\s},xshift={\i*0.6cm}] (-\i) {};
            }
            \node[fit=(-1)(-\i),draw] () {};
}}}
\tikzset{
    pics/PINV/.style={
        code = {
            \message{PINV params: #1}
            \foreach \s [count=\i] in {#1} {
                \node[draw,cross,minimum size=0.5cm,label={left:\s},yshift={-\i*0.6cm}] (-\i) {};
            }
            \node[fit=(-1)(-\i),draw] () {};
}}}
\begin{document}
    \begin{tikzpicture}
    \pic (A) {PINH={A,B,C,D}};
    \message{test here:}
    \pic (B) [below=1em of A.south west] {PINV={E,F,G,H}};
    \end{tikzpicture}
\end{document}

enter image description here

Or just replace chain with shift as @marmot's suggestion:

\documentclass[border=2pt]{standalone}
\usepackage{tikz}
\usetikzlibrary{positioning,fit,calc}  
\makeatletter
\pgfdeclareshape{cross}{
    \inheritsavedanchors[from=circle]
    \inheritanchorborder[from=circle]
    \inheritbackgroundpath[from=circle]
    \foreach \i in {center,north,south,east,west} {
        \inheritanchor[from=circle]{\i}
    }
    \backgroundpath{
        \pgfpathcircle{\pgfpointorigin}{\radius}%
    }
    \foregroundpath{
        \pgfpathmoveto{\pgfpointpolar{-135}{\radius}}%
        \pgfpathlineto{\pgfpointpolar{45}{\radius}}%
        \pgfpathmoveto{\pgfpointpolar{135}{\radius}}%
        \pgfpathlineto{\pgfpointpolar{-45}{\radius}}%
        \pgfusepath{draw}
    }
}
\makeatother
\tikzset{pad/.append  style={draw,cross,minimum size=0.5cm},
}
\newcommand{\PINH}[4][] {%[red]{1em}{F}{A,B,C,D}
    \begin{scope}[#1]
        \foreach \s [count=\i] in {#4} {
            \node[pad,label={[yshift=1mm]above:\s},xshift=\i*#2] (#3-\i) {};
        }
        \node[fit=(#3-1)(#3-\i),draw] (#3) {};
    \end{scope}
}
\newcommand{\PINV}[4][] {%[red]{1em}{F}{A,B,C,D}
    \begin{scope}[#1]
        \foreach \s [count=\i] in {#4} {
            \node[pad,label={[xshift=-1mm]left:\s},yshift=-\i*#2] (#3-\i) {};
        }
        \node[fit=(#3-1)(#3-\i),draw] (F1) {};
    \end{scope}
}
\begin{document}
    \begin{tikzpicture}
    \PINH{2em}{S1}{A,B,C,D};
    \PINV[below=1cm of S1]{2em}{S2}{E,F,G,H};
    \foreach \i in {1,...,4} {
        \draw (S1-\i) |- (S2-\i);
    }
    \end{tikzpicture}
\end{document}

enter image description here

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.