声明自己的 PGF 形状

声明自己的 PGF 形状

我正在尝试制作一些自己的 PGF 形状,以便稍后在 TikZ 中使用它。该形状应为正方形,内部没有文本,并且应使用指定的边框样式。考虑以下 MWE:

\documentclass[border=1mm]{standalone}
\usepackage{tikz}

\makeatletter

\newlength\mylength
\tikzset{
length/.code={\setlength{\mylength}{#1}},
length = 8mm,
border style/.store in=\borderstyle,
border style = thick,
}

\pgfdeclareshape{myshape}{
    \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}
    % define additional drawing commands
    \backgroundpath{
        % coordinates on frame
        \pgf@xa=-0.5\mylength \pgf@ya=-0.5\mylength
        \pgf@xb=0.5\mylength \pgf@yb=0.5\mylength

        % where can I specify that this path needs to use the \borderstyle?
        \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xa}{\pgf@yb}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
        \pgfpathclose
    }
}
\makeatother

\begin{document}
\begin{tikzpicture}
\node[draw,shape=myshape, label=above:label] at (0,0) (some node) {};
\draw[<-] (some node) -- ++(0,-1);
\end{tikzpicture}
\end{document}

它确实创建了一个边长为 的正方形length,这正是我想要的。但south锚点似乎并不在正方形的南边,而是在正方形内部的某个地方。我猜这是因为我在形状内没有文本。我怎样才能移动所有锚点,使它们位于正方形上?此外,我怎样才能让正方形使用border style上面定义的 I?标签位置也是错误的。它应该在正方形外面,因为我不想在里面放任何文本。

错误的形状

答案1

这是不声明新形状的替代方案。我使用 添加了一个附加元素path picture。由于我不知道您要添加什么,我只选择了对角线,但显然您可以添加任何您想要的。(我个人不会将样式存储在宏中,但会使用.../.style=...它,但我将您的建议保留在这里。)

\documentclass[border=1mm]{standalone}
\usepackage{tikz}

\newlength\mylength
\tikzset{
length/.code={\setlength{\mylength}{#1}},
length = 8mm,
border style/.store in=\borderstyle,
border style = thick,
}
\tikzset{myshape/.style={draw,\borderstyle,
minimum size=\mylength,
path picture={
\draw (path picture bounding box.south west) -- 
(path picture bounding box.north east);
}}}


\begin{document}
\begin{tikzpicture}
\node[myshape, label=above:label] at (0,0) (some node){};
\draw[<-] (some node) -- ++(0,-1);
\end{tikzpicture}
\end{document}

在此处输入图片描述

答案2

这就是你想要的吗?

演示

\documentclass[border=1mm]{standalone}
\usepackage{tikz}

\makeatletter

\newlength\mylength
\tikzset{
length/.code={\setlength{\mylength}{#1}},
length = 8mm,
border style/.store in=\borderstyle,
border style = thick,
}

\pgfdeclareshape{myshape}{
    \savedanchor{\southwest}{\pgfpoint{-0.5\mylength}{-0.5\mylength}}
    \savedanchor{\northeast}{\pgfpoint{0.5\mylength}{0.5\mylength}}
    \inheritanchorborder[from=rectangle]
    \inheritanchor[from=rectangle]{center}
    \inheritanchor[from=rectangle]{north}
    \inheritanchor[from=rectangle]{south}
    \inheritanchor[from=rectangle]{west}
    \inheritanchor[from=rectangle]{east}
    \anchor{text}   % this is used to center the text in the node
        {\pgfpoint{-.5\wd\pgfnodeparttextbox}{-.5\ht\pgfnodeparttextbox}}
    % define additional drawing commands
    \backgroundpath{
        \pgfkeys{/tikz/.cd,
                 \borderstyle}
        \pgfsetlinewidth{\pgflinewidth}
        % coordinates on frame
        \pgf@xa=-0.5\mylength \pgf@ya=-0.5\mylength
        \pgf@xb=0.5\mylength \pgf@yb=0.5\mylength

        % where can I specify that this path needs to use the \borderstyle?
        \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
        \pgfpathlineto{\pgfpoint{\pgf@xa}{\pgf@yb}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
        \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@ya}}
        \pgfpathclose
    }
}
\makeatother

\begin{document}
\begin{tikzpicture}
\node[draw,shape=myshape, label=above:label] at (0,0) (some node) {};
\draw[<-] (some node) -- ++(0,-1);
\end{tikzpicture}
\end{document}

答案3

好的,我已经很接近了。我得到了以下信息,感谢约翰·科米洛

\documentclass[border=1cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes}

\begin{document}



 \tikzset{
    shape example/.style={
    color=black!30,
    draw,
    fill=yellow!30,
    line width=.5cm,
    inner xsep=2.5cm,
    inner ysep=0.5cm}
}


\makeatletter

\pgfdeclareshape{myrect}{
    \savedanchor{\southwest}{\pgfpoint{-6cm-0.5\pgflinewidth}{-6cm-0.5\pgflinewidth}}
    \savedanchor{\northeast}{\pgfpoint{6cm+0.5\pgflinewidth}{6cm + 0.5\pgflinewidth}}
    \inheritanchorborder[from=rectangle]


    \inheritanchor[from=rectangle]{north}
    \inheritanchor[from=rectangle]{east}
    \inheritanchor[from=rectangle]{south}
    \inheritanchor[from=rectangle]{west}
    \inheritanchor[from=rectangle]{center}

    \anchor{text}   % this is used to center the text in the node
        {\pgfpoint{-.5\wd\pgfnodeparttextbox}{-.5\ht\pgfnodeparttextbox}}

    \backgroundpath{
    % Rectangle box

    \pgfpathrectanglecorners{\pgfpointadd{\southwest}{\pgfpoint{0.5\pgflinewidth}{0.5\pgflinewidth}}}{\pgfpointadd{\northeast}{\pgfpoint{-0.5\pgflinewidth}{-0.5\pgflinewidth}}}
    \pgfusepath{draw, fill}

  }

}




\pgfdeclareshape{mytri}{
    \savedanchor{\southwest}{\pgfpoint{-6cm-0.5\pgflinewidth}{-6cm-0.5\pgflinewidth}}
    \savedanchor{\northeast}{\pgfpoint{6cm+0.5\pgflinewidth}{6cm + 0.5\pgflinewidth}}
    \inheritanchorborder[from=rectangle]


    \inheritanchor[from=rectangle]{north}
    \inheritanchor[from=rectangle]{east}
    \inheritanchor[from=rectangle]{south}
    \inheritanchor[from=rectangle]{west}
    \inheritanchor[from=rectangle]{center}

    \anchor{text}   % this is used to center the text in the node
        {\pgfpoint{-.5\wd\pgfnodeparttextbox}{-.5\ht\pgfnodeparttextbox}}

    \backgroundpath{
    % Rectangle box

    \pgfpathmoveto{\pgfpoint{-6cm}{6cm}}
    \pgfpathlineto{\pgfpoint{6cm}{0}}
    \pgfpathlineto{\pgfpoint{-6cm}{-6cm}}
    \pgfpathclose
    \pgfusepath{draw, fill}
  }
}
\makeatother

\Huge

\begin{tikzpicture}
  \node at (0,0)  [name=s,myrect, minimum width=12cm, minimum height=12cm, inner sep = 0pt, shape example, label=above:label]  {};
  \node at (30,0)  [name=s2,mytri, minimum width=12cm, minimum height=12cm, inner sep = 0pt, shape example, label=above:label]  {};

  \draw (-6cm,-6cm) -- (6cm,-6cm);

  \foreach \x/\p in {north/above, east/right, south/below, west/left}
  \draw[shift=(s.\x)] plot[mark=x] coordinates{(0,0)} node[\p] {\color{red}\scriptsize\texttt{(s.\x)}};

  \draw[thin, red] (s2.west) |- (s2.north) -| (s2.east) |- (s2.south) -| cycle;
  \draw[thin, red] (s.west) |- (s.north) -| (s.east) |- (s.south) -| cycle;

  \foreach \x/\p in {north/above, east/right, south/below, west/left}
  \draw[shift=(s2.\x)] plot[mark=x] coordinates{(0,0)} node[\p] {\color{red}\scriptsize\texttt{(s2.\x)}};

\draw[>=latex, ->] (s) -- (s2);
\end{tikzpicture}

\end{document}

对于矩形,锚点现在似乎已正确对齐(即锚点实际上位于线条的外侧,就像 TikZ 中的普通矩形一样),如果使用非常大的线条粗细,这一点就变得很明显。要实现这一点,必须\pgflinewidth考虑线条端点的坐标。

在此处输入图片描述

我想知道是否有一种机制可以自动校正线条粗细?例如,如果考虑三角形,则显然路径点的校正变得更加麻烦,简单地减去是错误的\pgflinewidth

相关内容