如何定义房屋形状的 PGF 形状的锚边框

如何定义房屋形状的 PGF 形状的锚边框

我正在尝试定义一种形状,用于在数据来源的图形说明中绘制代理。这些代理通常用房屋形状的符号绘制,即不规则五边形,其中底部两个角是直角,左上角和右上角相同。参见,例如https://www.w3.org/TR/2013/NOTE-prov-primer-20130430/#intuitive-overview-of-prov举例来说。我没有将图片嵌入到该页面,因为我不确定它的许可状态。

由于 tikz 中默认不存在这样的形状,因此我尝试定义自己的形状。我已成功绘制了与目标形状相似的背景路径,但无法定义锚点边框,以便 tikz 自动将指向具有该形状的节点的路径指向形状的中心。

这是我当前拥有的代码:

\documentclass{standalone}
\usepackage[utf8]{inputenc}

\usepackage{fullpage}

\usepackage{tikz}
\usetikzlibrary{math,intersections}
\tikzstyle{agent}=[draw,agentshape]

\makeatletter
\pgfdeclareshape{agentshape}{
  \savedanchor{\centerpoint}{%
    \pgfpoint
      {\dimexpr.5\wd\pgfnodeparttextbox}%
      {\dimexpr.5\ht\pgfnodeparttextbox}%
  }
  \anchor{center}{\centerpoint}

  \savedanchor{\bottomleft}{%
    \pgfpoint{-\pgfshapeinnerxsep}{-\pgfshapeinnerysep}}
  \anchor{south west}{\bottomleft}

  \savedanchor{\bottom}{%
      \pgfpoint{.5\wd\pgfnodeparttextbox}{-\pgfshapeinnerysep}}
  \anchor{south}{\bottom}

  \savedanchor{\bottomright}{%
    \pgfpoint{\dimexpr\wd\pgfnodeparttextbox+\pgfshapeinnerxsep}{-\pgfshapeinnerysep}}
  \anchor{south east}{\bottomright}

  \savedanchor{\right}{%
      \pgfpoint{\dimexpr\wd\pgfnodeparttextbox+\pgfshapeinnerxsep}{\dimexpr.5\ht\pgfnodeparttextbox}}
  \anchor{east}{\right}

  \savedanchor{\topleft}{%
    \pgfpoint{-\pgfshapeinnerxsep}{\dimexpr\ht\pgfnodeparttextbox+\pgfshapeinnerysep}}
  \anchor{north west}{\topleft}

  \savedanchor{\left}{%
      \pgfpoint{-\pgfshapeinnerxsep}{\dimexpr.5\ht\pgfnodeparttextbox}}
  \anchor{west}{\left}

  \savedanchor{\topright}{%
    \pgfpoint{\dimexpr\wd\pgfnodeparttextbox+\pgfshapeinnerxsep}{\dimexpr\ht\pgfnodeparttextbox+\pgfshapeinnerysep}}
  \anchor{north east}{\topright}

  \savedanchor{\top}{%
    \pgfpoint{.5\wd\pgfnodeparttextbox}{\dimexpr1.5\ht\pgfnodeparttextbox+\pgfshapeinnerysep}}
  \anchor{north}{\top}

  \anchorborder{%
    \@tempdima=\pgf@x%
    \@tempdimb=\pgf@y%
    %
    \pgfmathanglebetweenpoints{\centerpoint}{\topright}%
    \pgfmathsetmacro{\@toprightangle}{\pgfmathresult}%
    \pgfmathanglebetweenpoints{\centerpoint}{\top}%
    \pgfmathsetmacro{\@topangle}{\pgfmathresult}%
    \pgfmathanglebetweenpoints{\centerpoint}{\topleft}%
    \pgfmathsetmacro{\@topleftangle}{\pgfmathresult}%
    \pgfmathanglebetweenpoints{\centerpoint}{\bottomleft}%
    \pgfmathsetmacro{\@bottomleftangle}{\pgfmathresult}%
    \pgfmathanglebetweenpoints{\centerpoint}{\bottomright}%
    \pgfmathsetmacro{\@bottomrightangle}{\pgfmathresult}%
    %
    \pgfmathanglebetweenpoints{\centerpoint}{\pgfpoint{\@tempdima}{\@tempdimb}}%
    \pgfmathsetmacro{\@givenangle}{\pgfmathresult}%
    \pgfmathparse{or(\@givenangle > \@bottomrightangle, \@givenangle <= \@toprightangle)}%
    \ifnum\pgfmathresult=1%
      \pgfpointintersectionoflines{\centerpoint}{\pgfpoint{\@tempdima}{\@tempdimb}}{\bottomright}{\topright}%
    \else%
      \pgfmathparse{and(\@givenangle > \@toprightangle, \@givenangle <= \@topangle)}%
      \ifnum\pgfmathresult=1%
        \pgfpointintersectionoflines{\centerpoint}{\pgfpoint{\@tempdima}{\@tempdimb}}{\topright}{\top}%
      \else%
        \pgfmathparse{and(\@givenangle > \@topangle, \@givenangle <= \@topleftangle)}%
        \ifnum\pgfmathresult=1%
          \pgfpointintersectionoflines{\centerpoint}{\pgfpoint{\@tempdima}{\@tempdimb}}{\top}{\topleft}%
        \else%
          \pgfmathparse{and(\@givenangle > \@topleftangle, \@givenangle <= \@bottomleftangle)}%
          \ifnum\pgfmathresult=1%
            \pgfpointintersectionoflines{\centerpoint}{\pgfpoint{\@tempdima}{\@tempdimb}}{\topleft}{\bottomleft}%
          \else%
            \pgfmathparse{and(\@givenangle > \@bottomleftangle, \@givenangle <= \@bottomrightangle)}%
            \ifnum\pgfmathresult=1%
              \pgfpointintersectionoflines{\centerpoint}{\pgfpoint{\@tempdima}{\@tempdimb}}{\bottomleft}{\bottomright}%
            \fi
          \fi
        \fi
      \fi%
    \fi%
  }

  \backgroundpath{
    \pgfpathmoveto{\bottomleft}
    \pgfpathlineto{\bottomright}
    \pgfpathlineto{\topright}
    \pgfpathlineto{\top}
    \pgfpathlineto{\topleft}
    \pgfpathclose
  }
}
\makeatother

\begin{document}

\begin{tikzpicture}
  \node[agent] (agent) at (1,1) {Foo};

  \foreach \coord in {-2,-1.5,...,2} {
    \path[draw,-] (-2,\coord) -- (agent);
    \path[draw,-] (2,\coord) -- (agent);
    \path[draw,-] (\coord,-2) -- (agent);
    \path[draw,-] (\coord,2) -- (agent);
  }
\end{tikzpicture}

\end{document}

结果如下图所示:

编译上述 MWE 的结果

如您所见,从节点顶部和右侧进入的路径似乎指向文本框的左下侧,而从插图底部和左侧进入的路径指向节点下部的中心。这在顶行右侧第三条路径和右行顶部第三条路径中尤为明显。

我如何定义形状以使所有传入路径都指向节点形状的中心?

答案1

我认为一个single arrow形状可以解决你的问题:

\documentclass[tikz,border=2mm]{standalone}
\usetikzlibrary{shapes.arrows}
\begin{document}
\begin{tikzpicture}[myhouse/.style={single arrow, 
        shape border rotate=90, 
        single arrow head extend=0pt, 
        single arrow tip angle=120}]

\node[myhouse, draw] (a) {House};

\node[myhouse, draw] at (30:2cm) (b) {House};

\draw (a)--(b);

\end{tikzpicture}
\end{document}

在此处输入图片描述

相关内容