在范围内定位元素

在范围内定位元素

我使用宏将一组元素定义到一个范围内。当我尝试用库定位它时,听起来好像没有处理这种情况:

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

在此处输入图片描述

我希望使用相对定位但不想使用绝对定位!

答案1

我认为大家对作用域的作用有些误解。作用域将其可选参数应用于其中的所有内容。因此,它将应用below=1cm of S1,然后与 完成的相对定位混淆chain。(想象一下它试图说\node[right=1cm of S1] at (0,0 ...,在这种情况下,您也有两个相互矛盾的陈述,相应地会产生一个奇怪的结果。)但是,如果您添加相对移位,它就会按您希望的方式工作。

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

在此处输入图片描述

答案2

另一种方法是使用matrix。它们是节点,因此您不需要scopes,也可以使用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}

在此处输入图片描述

答案3

另一个带图片的解决方案:

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

在此处输入图片描述

或者按照@marmot 的建议用 shift 替换 chain :

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

在此处输入图片描述

相关内容