使用 TikZ 将节点绘制为正方形

使用 TikZ 将节点绘制为正方形

我搜索了但找不到解决方案。 是否可以使用 Ti 绘制节点Z 是正方形而不是任意比例的矩形吗?

最小工作示例可以是这样的:

\documentclass{article}
\usepackage{tikz}

\begin{document}
    \begin{tikzpicture}
        \node at (0,0) [circle,draw] (c100) {$c_{100}$};
        \node at (3,0) [rectangle,draw] (v100) {$v_{100}$};
        \draw (c100) -- (v100);
    \end{tikzpicture}
\end{document}

圆形是完美的圆形,而矩形就是矩形:

使用 TikZ 的圆形和矩形节点

我希望它是正方形。我没有找到任何形状正方形或者。

答案1

这出乎意料地困难。在下面的代码中,我定义了一个自定义节点形状square,它继承自该rectangle形状,但强制其大小为正方形。不幸的是,继承机制不允许重新定义继承的已保存锚点,所以我不得不从 TikZrectangle定义中复制一些代码。

从好的方面来说,它在所有情况下都应该正确(为inner [xy]sepminimum {width,height}和定义不同的值outer [xy]sep)并且具有 的所有锚点rectangle shape

\documentclass[tikz,margin=5pt]{standalone}
\usepackage{tikz}

\makeatletter
% the contents of \squarecorner were mostly stolen from pgfmoduleshapes.code.tex
\def\squarecorner#1{
    % Calculate x
    %
    % First, is width < minimum width?
    \pgf@x=\the\wd\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@xc{\pgfkeysvalueof{/pgf/inner xsep}}%
    \advance\pgf@x by 2\pgf@xc%
    \pgfmathsetlength\pgf@xb{\pgfkeysvalueof{/pgf/minimum width}}%
    \ifdim\pgf@x<\pgf@xb%
        % yes, too small. Enlarge...
        \pgf@x=\pgf@xb%
    \fi%
    % Calculate y
    %
    % First, is height+depth < minimum height?
    \pgf@y=\ht\pgfnodeparttextbox%
    \advance\pgf@y by\dp\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@yc{\pgfkeysvalueof{/pgf/inner ysep}}%
    \advance\pgf@y by 2\pgf@yc%
    \pgfmathsetlength\pgf@yb{\pgfkeysvalueof{/pgf/minimum height}}%
    \ifdim\pgf@y<\pgf@yb%
        % yes, too small. Enlarge...
        \pgf@y=\pgf@yb%
    \fi%
    %
    % this \ifdim is the actual part that makes the node dimensions square.
    \ifdim\pgf@x<\pgf@y%
        \pgf@x=\pgf@y%
    \else
        \pgf@y=\pgf@x%
    \fi
    %
    % Now, calculate right border: .5\wd\pgfnodeparttextbox + .5 \pgf@x + #1outer sep
    \pgf@x=#1.5\pgf@x%
    \advance\pgf@x by.5\wd\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/pgf/outer xsep}}%
    \advance\pgf@x by#1\pgf@xa%
    % Now, calculate upper border: .5\ht-.5\dp + .5 \pgf@y + #1outer sep
    \pgf@y=#1.5\pgf@y%
    \advance\pgf@y by-.5\dp\pgfnodeparttextbox%
    \advance\pgf@y by.5\ht\pgfnodeparttextbox%
    \pgfmathsetlength\pgf@ya{\pgfkeysvalueof{/pgf/outer ysep}}%
    \advance\pgf@y by#1\pgf@ya%
}
\makeatother

\pgfdeclareshape{square}{
    \savedanchor\northeast{\squarecorner{}}
    \savedanchor\southwest{\squarecorner{-}}

    \foreach \x in {east,west} \foreach \y in {north,mid,base,south} {
        \inheritanchor[from=rectangle]{\y\space\x}
    }
    \foreach \x in {east,west,north,mid,base,south,center,text} {
        \inheritanchor[from=rectangle]{\x}
    }
    \inheritanchorborder[from=rectangle]
    \inheritbackgroundpath[from=rectangle]
}

\begin{document}
    \begin{tikzpicture}
        \node[draw,square] {square with rectangular node text};
    \end{tikzpicture}
\end{document}

令人难以置信的令人兴奋的结果

答案2

使用库regular polygon中的形状shapes.geometric。正如 Alenanno 在评论中提到的,您可以定义自己的样式以减少冗长。

我不知道这个大小是怎么计算的,里面有很多空白。设置inner sep为负值可以减小大小,但必须根据节点标签的长度修改该值。

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes.geometric}
\begin{document}
    \begin{tikzpicture}[square/.style={regular polygon,regular polygon sides=4}]
        \node at (0,0) [circle,draw] (c100) {$c_{100}$};
        \node at (3,0) [square,draw] (v100) {$v_{100}$};
        \node at (3,-5) [square,inner sep=-1.3em,draw] {a much longer node label};
        \node at (3,-5) [circle,draw] {a much longer node label};
        \draw (c100) -- (v100);
    \end{tikzpicture}
\end{document}

在此处输入图片描述

答案3

另一个解决方案,目前尚未提及。这个想法是将所需节点设置为一个圆圈,但不绘制它。然后使用fittikz 库绘制一个“适合”该节点的矩形。

\documentclass[tikz,border=2mm]{standalone}
\usepackage{tikz}
\usetikzlibrary{fit}

\begin{document}
    \begin{tikzpicture}
        \node at (0,0) [circle,draw] (c100) {$c_{100}$};
        \node at (3,0) [circle] (v100) {$v_{100}$};
        \node [rectangle,draw,fit=(v100),inner sep=0] {};
        \draw (c100) -- (v100);
    \end{tikzpicture}
\end{document}

方节点

答案4

另一种解决方案。它使用width函数来定义节点的大小。由于使用相同的参数作为node contents大小分隔符,因此必须在选项之前或选项内声明节点的名称和位置。

\documentclass[border=2mm]{standalone}
\usepackage{tikz}
\begin{document}
    \begin{tikzpicture}%
        [square/.style={%
            draw,
            minimum width=width("#1"),
            minimum height=width("#1")+2*\pgfshapeinnerysep,
            node contents={#1}}]

        \node at (0,0) [circle,draw] (c100) {$c_{100}$};
        \node at (3,0) (v100) [square={$v_{100}$}];
%or
%       \node (v100) at (3,0)[square={$v_{100}$}];
%or
%       \node at (3,0) [square={$v_{100}$}, name=v100];
%or
%       \node[square={$v_{100}$}, name=v100, at={(3,0)}];

        \node at (2,-3) (B) [square=a much longer node text];
        \draw (c100) -- (v100);
          \draw (B.south west) -- ++(45:6cm);
    \end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容