我正在尝试定义一个“标记图标”形状(LIS),它是一个图标(用 pgf 命令绘制,但为简单起见,这里用一个简单的矩形替换),带有一个粘贴在图标上的标签(为简单起见,在这个最小示例中不是这种情况)并且是形状的一部分(边框锚点位于图标和标签的边框)。
通过使用这种形状,我将得到类似于下图的结果;不同之处在于,当标签位于边缘时,边缘将停止在标签的边界处,而不是穿过它。
上面的图片是通过代码得到的:
\documentclass{article}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\fill[red] (0,0) circle (1pt);
\node[draw, label=-90:{Some text}] (node) at (0,0) {};
\foreach \angle in {0,30,...,330} {
\node[draw, label=-\angle:{Some text}] (node-\angle) at (\angle:5cm) {};
\draw (node) -- (node-\angle);
}
\end{tikzpicture}
\end{document}
使用 LIS 形状,我会写:
\documentclass{article}
\usepackage{tikz}
\usepackage{minimal-shapes}
\begin{document}
\begin{tikzpicture}
\fill[red] (0,0) circle (1pt);
\node[lis, align=center] (lis) at (0,0) {Some\\text};
\foreach \angle in {0,30,...,330} {
\node[lis, lis label pos=-\angle, align=center] (lis-\angle) at (\angle:4cm) {LIS \\ \angle};
\draw (lis) -- (lis-\angle);
}
\end{tikzpicture}
\end{document}
我在文件 minimal-shapes.sty 中定义了 LIS 形状。除了边框锚点的计算之外,一切都运行正常,在计算中,保存的值似乎是错误的,并且文本位置和其他点偏移了 180 度。以下是强调问题的改编形状声明。对于调试,返回的锚点边框始终是图标的边框,但在标签边框上应该有锚点边框的位置绘制了一个小圆圈。
\usepgflibrary{intersections}
\pgfkeyssetvalue{/tikz/lis label pos}{-90}
\newlength{\lis@textWidth} \newlength{\lis@textHeight}
\newcommand{\setTextCenterCoords}[0]{
%% SIMPLIFIED VERSION
\pgfmathsetlength{\pgfutil@tempdima}{\wd\pgfnodeparttextbox / 2 + 1.5em}
\pgfpointpolar{\lis@labelPos}{\pgfutil@tempdima}
}
\pgfdeclareshape{lis}{
%% DIMENs
\saveddimen{\textWidth}{
\pgf@x=\wd\pgfnodeparttextbox
\ifdim\pgf@x<\pgfshapeminwidth
\pgf@x=\pgfshapeminwidth
\fi
}
\saveddimen{\textHeight}{\pgf@x=\ht\pgfnodeparttextbox}
%% MACROs
\savedmacro{\computeActorDimens}{
\setlength{\lis@textHeight}{\ht\pgfnodeparttextbox}
\setlength{\lis@textWidth}{\wd\pgfnodeparttextbox}
}
\savedmacro{\lis@labelPos}{
\pgfmathsetmacro{\lis@labelPos}{Mod((\pgfkeysvalueof{/tikz/lis label pos} + 180), 360) - 180}
\pgfwarning{Lis label pos: \pgfkeysvalueof{/tikz/lis label pos} -> \lis@labelPos}
}
%% SAVEDANCHORs
\savedanchor{\upperRightIconCorner}{
\pgfpoint{1em}{1em}
}
\savedanchor{\textCenter}{
\setTextCenterCoords
}
\savedanchor{\upperRightTextCorner}{
\computeActorDimens % Saveddimen do not seem available when declaring saved anchors
\setTextCenterCoords
\pgfmathsetlength{\pgf@x}{\pgf@x + (.5 * \lis@textWidth)}
\pgfmathsetlength{\pgf@y}{\pgf@y + (.5 * \lis@textHeight)}
}
%% ANCHORs
\anchor{center}{\pgfpointorigin}
\anchor{text}{
\textCenter
\pgfmathsetlength{\pgf@x}{\pgf@x - (.5 * \textWidth)}
\pgfmathsetlength{\pgf@y}{\pgf@y - (.5 * \textHeight)}
}
%% BORDER ANCHORs
\anchorborder{%
\@tempdima=\pgf@x \@tempdimb=\pgf@y
%
%\computeActorDimens
\textCenter
\upperRightTextCorner
\pgfintersectionofpaths{
\pgfpathmoveto{\pgfpointorigin}\pgfpathlineto{\pgfpoint{\@tempdima}{\@tempdimb}}
\pgfgetpath\temppath
%\pgfusepath{stroke}
\pgfsetpath\temppath
}{
\pgfpathrectanglecorners{
\pgfpointlineattime{-1}{
\textCenter
}{
\upperRightTextCorner
}
}{
\upperRightTextCorner
}
\pgfgetpath\temppath
%\pgfusepath{stroke}
\pgftext[at=\textCenter]{\footnotesize \lis@labelPos}
\pgfsetpath\temppath
}
%
\pgfwarning{Nb intersections: \pgfintersectionsolutions}
%
\ifnum\pgfintersectionsolutions=0
\pgfpointborderrectangle{\pgfpoint{\@tempdima}{\@tempdimb}}{\upperRightIconCorner}
\else
\pgfintersectionsortbyfirstpath
\pgfpathcircle{\pgfpointintersectionsolution{\pgfintersectionsolutions}}{3pt}
\fi
\pgfpointborderrectangle{\pgfpoint{\@tempdima}{\@tempdimb}}{\upperRightIconCorner}
}
%% DRAWINGs
\backgroundpath{
%% SIMPLIFIED VERSION
\upperRightIconCorner \@tempdima=\pgf@x \@tempdimb=\pgf@y
\pgfpathrectanglecorners{
\pgfpointlineattime{-1}{\pgfpointorigin}{\pgfpoint{\@tempdima}{\@tempdimb}}
}{\pgfpoint{\@tempdima}{\@tempdimb}}
\pgfusepath{stroke}
}
}
通过上述代码,我得到以下结果:
对于中心节点来说,它似乎几乎可以正常工作。但外围节点的 \lis@labelPos 值错误(已显示以显示问题)。当应该有交点时,却发现了一个交点(显示为圆圈),但它出现在节点的错误一侧。如果我取消引用第一个“\pgfusepath{stroke}”,线条会朝向图形外部,而不是朝向中心节点(提供给 \anchorborder 的值 \pgf@x 和 \pgf@y 似乎是错误的)。
我不明白发生了什么。有人能帮忙吗?谢谢
答案1
在 \anchorborder 中绘制任何东西似乎都不是一个好主意。应用于 \anchorborder 内容的转换将绘图置于错误的位置。这可能是交集库上的命令与 \anchorborder 不兼容的相同原因。为了解决我的问题,我从“磁带”形状(顺便说一下,其中有一个错误)中获得了一些灵感。生成的代码如下:
\anchorborder{%
\pgfextract@process\externalpoint{}%
\ifnum\pdfstrcmp{\lis@iconShape}{rectangle}=0%
\pgfpointborderrectangle{\externalpoint}{\iconUpperRightOuterCorner}%
\fi%
\ifnum\pdfstrcmp{\lis@iconShape}{ellipse}=0%
\pgfpointborderellipse{\externalpoint}{\iconUpperRightOuterCorner}%
\fi%
\lis@tmpX=\pgf@x \lis@tmpY=\pgf@y \pgfmathsetmacro{\lis@tmpLgth}{sqrt( pow(\pgf@x,2) + pow(\pgf@y,2) )}%
%
\pgfmathanglebetweenpoints{\pgfpointorigin}{\externalpoint}%
\pgfmathsetmacro{\lis@externalpointAngle}{\pgfmathresult}%
%
\pgfmathsetmacro{\tmpMin}{min(\lis@labelURcornerAngle, \lis@labelULcornerAngle, \lis@labelLLcornerAngle, \lis@labelLRcornerAngle)}%
\pgfmathsetmacro{\tmpMax}{max(\lis@labelURcornerAngle, \lis@labelULcornerAngle, \lis@labelLLcornerAngle, \lis@labelLRcornerAngle)}%
\pgfwarning{LIS shape: \lis@externalpointAngle, (\lis@labelURcornerAngle, \lis@labelULcornerAngle, \lis@labelLLcornerAngle, \lis@labelLRcornerAngle) \lis@labelPos, \tmpMin, \tmpMax}%
\pgfmathsetmacro{\lis@tmpLabelPos}{Mod(\lis@labelPos, 360)}%
\pgfmathparse{not(and(\tmpMin < \lis@tmpLabelPos , \lis@tmpLabelPos < \tmpMax))}%
\ifnum\pgfmathresult=1%
\pgfmathsetmacro{\lis@externalpointAngle}{Mod(\lis@externalpointAngle + 180, 360)}%
\pgfmathsetmacro{\lis@labelURcornerAngle}{Mod(\lis@labelURcornerAngle + 180, 360)}%
\pgfmathsetmacro{\lis@labelULcornerAngle}{Mod(\lis@labelULcornerAngle + 180, 360)}%
\pgfmathsetmacro{\lis@labelLLcornerAngle}{Mod(\lis@labelLLcornerAngle + 180, 360)}%
\pgfmathsetmacro{\lis@labelLRcornerAngle}{Mod(\lis@labelLRcornerAngle + 180, 360)}%
\pgfwarning{LIS shape: \lis@externalpointAngle, (\lis@labelURcornerAngle, \lis@labelULcornerAngle, \lis@labelLLcornerAngle, \lis@labelLRcornerAngle) \lis@labelPos}%
\fi%
%
\ifdim\lis@labelURcornerAngle pt<\lis@externalpointAngle pt%
\ifdim\lis@externalpointAngle pt<\lis@labelULcornerAngle pt%
\lis@setLabelCenterCoords%
\pgfmathsetlength{\lis@tmpXa}{\pgf@x + (.5 * \labelOuterWidth)}%
\pgfmathsetlength{\lis@tmpYa}{\pgf@y + (.5 * \labelOuterHeight)}%
\lis@setLabelCenterCoords%
\pgfmathsetlength{\lis@tmpXb}{\pgf@x - (.5 * \labelOuterWidth)}%
\pgfmathsetlength{\lis@tmpYb}{\pgf@y + (.5 * \labelOuterHeight)}%
\pgfpointintersectionoflines{\pgfpointorigin}{\externalpoint}{\pgfqpoint{\lis@tmpXa}{\lis@tmpYa}}{\pgfqpoint{\lis@tmpXb}{\lis@tmpYb}}%
\pgfmathsetmacro{\lis@tmpLgthB}{sqrt( pow(\pgf@x,2) + pow(\pgf@y,2) )}%
\ifdim\lis@tmpLgthB pt>\lis@tmpLgth pt%
\lis@tmpX=\pgf@x \lis@tmpY=\pgf@y \pgfmathsetmacro{\lis@tmpLgth}{\lis@tmpLgthB}%
\fi%
\fi%
\fi%
%
\ifdim\lis@labelULcornerAngle pt<\lis@externalpointAngle pt%
\ifdim\lis@externalpointAngle pt<\lis@labelLLcornerAngle pt%
\lis@setLabelCenterCoords%
\pgfmathsetlength{\lis@tmpXa}{\pgf@x - (.5 * \labelOuterWidth)}%
\pgfmathsetlength{\lis@tmpYa}{\pgf@y + (.5 * \labelOuterHeight)}%
\lis@setLabelCenterCoords%
\pgfmathsetlength{\lis@tmpXb}{\pgf@x - (.5 * \labelOuterWidth)}%
\pgfmathsetlength{\lis@tmpYb}{\pgf@y - (.5 * \labelOuterHeight)}%
\pgfpointintersectionoflines{\pgfpointorigin}{\externalpoint}{\pgfqpoint{\lis@tmpXa}{\lis@tmpYa}}{\pgfqpoint{\lis@tmpXb}{\lis@tmpYb}}%
\pgfmathsetmacro{\lis@tmpLgthB}{sqrt( pow(\pgf@x,2) + pow(\pgf@y,2) )}%
\ifdim\lis@tmpLgthB pt>\lis@tmpLgth pt%
\lis@tmpX=\pgf@x \lis@tmpY=\pgf@y \pgfmathsetmacro{\lis@tmpLgth}{\lis@tmpLgthB}%
\fi%
\fi%
\fi%
%
\ifdim\lis@labelLLcornerAngle pt<\lis@externalpointAngle pt%
\ifdim\lis@externalpointAngle pt<\lis@labelLRcornerAngle pt%
\lis@setLabelCenterCoords%
\pgfmathsetlength{\lis@tmpXa}{\pgf@x - (.5 * \labelOuterWidth)}%
\pgfmathsetlength{\lis@tmpYa}{\pgf@y - (.5 * \labelOuterHeight)}%
\lis@setLabelCenterCoords%
\pgfmathsetlength{\lis@tmpXb}{\pgf@x + (.5 * \labelOuterWidth)}%
\pgfmathsetlength{\lis@tmpYb}{\pgf@y - (.5 * \labelOuterHeight)}%
\pgfpointintersectionoflines{\pgfpointorigin}{\externalpoint}{\pgfqpoint{\lis@tmpXa}{\lis@tmpYa}}{\pgfqpoint{\lis@tmpXb}{\lis@tmpYb}}%
\pgfmathsetmacro{\lis@tmpLgthB}{sqrt( pow(\pgf@x,2) + pow(\pgf@y,2) )}%
\ifdim\lis@tmpLgthB pt>\lis@tmpLgth pt%
\lis@tmpX=\pgf@x \lis@tmpY=\pgf@y \pgfmathsetmacro{\lis@tmpLgth}{\lis@tmpLgthB}%
\fi%
\fi%
\fi%
%
\ifdim\lis@labelLRcornerAngle pt<\lis@externalpointAngle pt%
\ifdim\lis@externalpointAngle pt<\lis@labelURcornerAngle pt%
\lis@setLabelCenterCoords%
\pgfmathsetlength{\lis@tmpXa}{\pgf@x + (.5 * \labelOuterWidth)}%
\pgfmathsetlength{\lis@tmpYa}{\pgf@y - (.5 * \labelOuterHeight)}%
\lis@setLabelCenterCoords%
\pgfmathsetlength{\lis@tmpXb}{\pgf@x + (.5 * \labelOuterWidth)}%
\pgfmathsetlength{\lis@tmpYb}{\pgf@y + (.5 * \labelOuterHeight)}%
\pgfpointintersectionoflines{\pgfpointorigin}{\externalpoint}{\pgfqpoint{\lis@tmpXa}{\lis@tmpYa}}{\pgfqpoint{\lis@tmpXb}{\lis@tmpYb}}%
\pgfmathsetmacro{\lis@tmpLgthB}{sqrt( pow(\pgf@x,2) + pow(\pgf@y,2) )}%
\ifdim\lis@tmpLgthB pt>\lis@tmpLgth pt%
\lis@tmpX=\pgf@x \lis@tmpY=\pgf@y \pgfmathsetmacro{\lis@tmpLgth}{\lis@tmpLgthB}%
\fi%
\fi%
\fi%
%
\pgf@x=\lis@tmpX \pgf@y=\lis@tmpY%
}