我想稍微修改一下pgflibraryshapes.callouts.code.tex
,创建一个小的 tikz 标注包来解决Tikz 标注:定位指针的开始。
我认为我已经找到了唯一相关的行
\pgfmultipartnode{coordinate}{center}{pgf@lib@callout@pointer}
但我不知道如何修改它,因为我不理解 pgf 手册中对 pgfmultipartnode 的非常简短的描述,也不理解参数。
那么:我需要如何修改代码行来定位指针的起点? 理想情况下,我想要一个参数来固定指针到达标注的位置(例如北、西北、西……)或者更简单:始终向西,因为这就是我开始所需要的全部。
详细信息:这是的开头pgflibraryshapes.callouts.code.tex
,其中应包含所有相关信息:
% Copyright 2007 by Mark Wibrow
% This file may be distributed and/or modified
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Public License.
% See the file doc/generic/pgf/licenses/LICENSE for more details.
\usepgflibrary{shapes.symbols}
% Keys for callouts
%
% Common to all callouts:
% /pgf/callout absolute pointer
% /pgf/callout relative pointer
%
% ellipse callout only:
% /pgf/callout pointer arc
%
% rectangle callout only:
% /pgf/callout pointer width
%
% cloud callout only:
% /pgf/callout pointer start size
% /pgf/callout pointer end size
% /pgf/callout pointer segments
%
\newif\ifpgf@lib@callout@absolutepointer
\pgfkeys{/pgf/.cd,
callout pointer arc/.initial=15,
callout pointer width/.initial=.25cm,
callout pointer start size/.initial=.2 of callout,
callout pointer end size/.initial=.1 of callout,
callout pointer segments/.initial=2,
callout absolute pointer/.code={\pgf@lib@callout@makeabsolutepointer{#1}},
callout relative pointer/.code={\pgf@lib@callout@makerelativepointer{#1}},
callout pointer shorten/.initial=0cm
}
\def\pgf@lib@callout@makeabsolutepointer#1{%
\pgf@lib@callout@absolutepointertrue%
{%
\pgftransformshift{#1}%
\pgfmultipartnode{coordinate}{center}{pgf@lib@callout@pointer}{}%
}%
}
\def\pgf@lib@callout@makerelativepointer#1{%
\pgf@lib@callout@absolutepointerfalse%
\def\pgf@lib@callout@relativepointer{#1}%
}
\pgfkeys{/pgf/callout relative pointer=\pgfpointpolar{300}{.5cm}}
% Copyright 2007 by Mark Wibrow
%
% This file may be distributed and/or modified
%
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Public License.
%
% See the file doc/generic/pgf/licenses/LICENSE for more details.
\usepgflibrary{shapes.symbols}
% Keys for callouts
%
% Common to all callouts:
% /pgf/callout absolute pointer
% /pgf/callout relative pointer
%
% ellipse callout only:
% /pgf/callout pointer arc
%
% rectangle callout only:
% /pgf/callout pointer width
%
% cloud callout only:
% /pgf/callout pointer start size
% /pgf/callout pointer end size
% /pgf/callout pointer segments
%
\newif\ifpgf@lib@callout@absolutepointer
\pgfkeys{/pgf/.cd,
callout pointer arc/.initial=15,
callout pointer width/.initial=.25cm,
callout pointer start size/.initial=.2 of callout,
callout pointer end size/.initial=.1 of callout,
callout pointer segments/.initial=2,
callout absolute pointer/.code={\pgf@lib@callout@makeabsolutepointer{#1}},
callout relative pointer/.code={\pgf@lib@callout@makerelativepointer{#1}},
callout pointer shorten/.initial=0cm
}
\def\pgf@lib@callout@makeabsolutepointer#1{%
\pgf@lib@callout@absolutepointertrue%
{%
\pgftransformshift{#1}%
\pgfmultipartnode{coordinate}{center}{pgf@lib@callout@pointer}{}%
}%
}
\def\pgf@lib@callout@makerelativepointer#1{%
\pgf@lib@callout@absolutepointerfalse%
\def\pgf@lib@callout@relativepointer{#1}%
}
\pgfkeys{/pgf/callout relative pointer=\pgfpointpolar{300}{.5cm}}
更新:
使用 pgflibrarymalipivo.callouts.patch.v1.code.tex(参见下面的答案),我可以创建标注示例,如下面的答案所示:)但是,对于这两个示例,我都收到错误消息:
对于pdflatex calloutMinimalExample.tex
(答案中的第一个例子):
(/home/dball/texmf/tex/generic/pgf210/tex/generic/pgf/frontendlayer/tikz/librar
ies/tikzlibraryshapes.multipart.code.tex
(/home/dball/texmf/tex/generic/pgf210/tex/generic/pgf/libraries/shapes/pgflibra
ryshapes.multipart.code.tex))) (./pgflibrarymalipivo.callouts.patch.v1.code.tex
)
No file calloutMinimalExample.aux.
ABD: EveryShipout initializing macros
(/usr/share/texmf-texlive/tex/context/base/supp-pdf.mkii
[Loading MPS to PDF converter (version 2006.09.02).]
)
! Undefined control sequence.
\pgf@sh@bg@rectangle callout ...f@sh@np@\pgf@test
\noexpand \endcsname }\ede...
l.14 ...karounds; no exceptions to optimizations};
? q
OK, entering \batchmode
对于pdflatex calloutLargerExample.tex
(第二个示例),我收到以下错误消息:
(./pgflibrarymalipivo.callouts.patch.v1.code.tex
) (/usr/share/texmf-texlive/tex/latex/tools/multicol.sty)
No file calloutLargerExample.aux.
ABD: EveryShipout initializing macros
(/usr/share/texmf-texlive/tex/context/base/supp-pdf.mkii
[Loading MPS to PDF converter (version 2006.09.02).]
)
! Undefined control sequence.
\pgf@sh@bg@rectangle callout ...f@sh@np@\pgf@test
\noexpand \endcsname }\ede...
l.25 \end{tikzpicture}\par}\vspace{1cm}}}
% The end of \foreach cycles
?
calloutMinimalExample.tex 的更新 2:
使用
\makeatletter(\usetikzlibrary{shapes}\makeatletter)
\makeatother(\usepgflibrary{malipivo.callouts.patch.v1}\makeatother)
导致错误消息
! LaTeX Error: Missing \begin{document}.
See the LaTeX manual or LaTeX Companion for explanation.
Type H <return> for immediate help.
...
l.6 \makeatletter(
\usetikzlibrary{shapes}\makeatletter)
改用
\makeatletter
\usetikzlibrary{shapes}
\makeatother
\usepgflibrary{malipivo.callouts.patch.v1}
导致更新 1 中发布错误消息。
使用
\usetikzlibrary{malipivo.callouts.patch.v1.spaces}
导致错误消息
! I can't find file `tikzlibrarymalipivo.callouts.patch.v1.spaces.code.tex'.
<argument> ...nput tikzlibrary\pgf@temp .code.tex
\catcode `\@ =\csname tikz...
l.5 ...zlibrary{malipivo.callouts.patch.v1.spaces}
(Press Enter to retry, or Control-D to exit)
Please type another input file name:
将 pdflibrarymalipivo.callouts.patch.v1.code.tex 重命名为 tikzlibrarymalipivo.callouts.patch.v1.spaces.code.tex 会导致更新 1 中发布的错误消息。
更新
在使用 Malipivo 的解决方案 ( gflibrarymalipivo.callouts.patch.v1.code.tex
) 时,我遇到了一个问题:我能否以某种方式指定指针进入哪个标注边界(北、南、东、西)?自动解决方案看起来不太好。此外,图形有时会在指针进入标注矩形的地方损坏,见图。在我看来,如果我可以强制指针进入西边界,那么这两个问题都可以解决。
我可以尝试使用 callout 指针 move=...mm,但这没什么帮助:我不明白如何使用它来决定 callout 边框,也无法修复损坏的图形。那么:我该如何指定边框?如何使用 move=...mm?或者我该如何修复gflibrarymalipivo.callouts.patch.v1.code.tex
?
答案1
我想介绍一些我的发现,请原谅我对源代码的挖掘。通过 TikZ 界面轻松访问并进行改进,从头开始绘制/编程会容易得多,但尽可能地遵循要求是一项挑战,我想这有其原因。我把它当作提高 TeX 源代码阅读能力的练习。
所有调用的代码确实都在 中\tex\generic\pgf\libraries\shapes\pgflibraryshapes.callouts.code.tex
,它包含大量代码块,很难直接重新定义它们。无论如何,要分离各部分并不容易,因为它主要由计算组成。该文件部分被注释,命令的名称在某种程度上有所帮助。
我创建了一个备份文件并开始编辑(pgflibrarymalipivo.callouts.patch.v1.code.tex
)。我主要关注绝对+相对矩形标注,其他包括圆+椭圆相关的计算。我需要:
- 一个新的维度/定义或一个新的 pgfkey。
- 存储 pgfkey。
- 正确使用 pgfkey。
至 1.我已\pgfkeys{/pgf/.cd
在callout pointer move/.initial=0cm
文件开头进行了扩展。
至 2。我已经输入\pgfmathsetlengthmacro\moveleftright{\pgfkeysvalueof{/pgf/callout pointer move}}%
并\addtosavedmacro\moveleftright%
进入\pgf@lib@rectanglecallout@pointer
命令。
至 3。最后,我几乎在计算的最后阶段之前修改了pgf@xb
维度,即x
的坐标\borderpoint
(然后测试该点是否位于矩形区域内,我没有修改那部分)。
编辑:我已经尝试完善代码,因此请按原样将其下载到本地目录(未剪切文件可供下载或下面的部分精炼版本)以及此答案中的两个 TeX 示例。我们需要复制\pgfdeclareshape
精炼版本,否则 Linux 上会出现不需要的消息(我猜这是由于\savedmacro
和\addtosavedmacro
)。在 Windows XP 和 Linux Ubuntu 13.10 上使用 pdflatex、lualatex、xelatex 和 latex+dvips(TeXLive 2013)进行了测试。
请自行承担使用风险。这是pgflibrarymalipivo.callouts.patch.v1.code.tex
:
% A patch to the c:\texlive\2013\texmf-dist\tex\generic\pgf\libraries\shapes\pgflibraryshapes.callouts.code.tex file.
%
% Copyright 2007 by Mark Wibrow
%
% This file may be distributed and/or modified
%
% 1. under the LaTeX Project Public License and/or
% 2. under the GNU Public License.
%
% See the file doc/generic/pgf/licenses/LICENSE for more details.
%\usepgflibrary{shapes.symbols}
% Keys for callouts
%
% Common to all callouts:
% /pgf/callout absolute pointer
% /pgf/callout relative pointer
%
% ellipse callout only:
% /pgf/callout pointer arc
%
% rectangle callout only:
% /pgf/callout pointer width
%
% cloud callout only:
% /pgf/callout pointer start size
% /pgf/callout pointer end size
% /pgf/callout pointer segments
%
%\newif\ifpgf@lib@callout@absolutepointer
\pgfkeys{/pgf/.cd,
%callout pointer arc/.initial=15,
%callout pointer width/.initial=.25cm,
%callout pointer start size/.initial=.2 of callout,
%callout pointer end size/.initial=.1 of callout,
%callout pointer segments/.initial=2,
%callout absolute pointer/.code={\pgf@lib@callout@makeabsolutepointer{#1}},
%callout relative pointer/.code={\pgf@lib@callout@makerelativepointer{#1}},
%callout pointer shorten/.initial=0cm,
callout pointer move/.initial=0cm % malipivo
}
\pgfdeclareshape{rectangle callout}{%
\savedmacro\rectanglecalloutpoints{%
%
\pgfmathsetlength\pgf@x{\pgfkeysvalueof{/pgf/inner xsep}}%
\advance\[email protected]\wd\pgfnodeparttextbox%
\pgfmathsetlength\pgf@xa{\pgfkeysvalueof{/pgf/minimum width}}%
\ifdim\pgf@x<.5\pgf@xa%
\[email protected]\pgf@xa%
\fi%
\edef\xtemp{\the\pgf@x}%
\pgfmathaddtolength\pgf@x{\pgfkeysvalueof{/pgf/outer xsep}}%
%
\pgfmathsetlength\pgf@y{\pgfkeysvalueof{/pgf/inner ysep}}%
\advance\[email protected]\ht\pgfnodeparttextbox%
\advance\[email protected]\dp\pgfnodeparttextbox%
\pgfmathsetlength\pgf@ya{\pgfkeysvalueof{/pgf/minimum height}}%
\ifdim\pgf@y<.5\pgf@ya%
\[email protected]\pgf@ya%
\fi%
\edef\ytemp{\the\pgf@y}%
\pgfmathaddtolength\pgf@y{\pgfkeysvalueof{/pgf/outer ysep}}%
%
\edef\xlength{\the\pgf@x}%
\edef\ylength{\the\pgf@y}%
\addtosavedmacro\xlength%
\addtosavedmacro\ylength%
%
\pgfmathsetlengthmacro\pointerwidth{\pgfkeysvalueof{/pgf/callout pointer width}}%
\addtosavedmacro\pointerwidth%
%
\pgfextract@process\centerpoint{%
\[email protected]\wd\pgfnodeparttextbox%
\[email protected]\ht\pgfnodeparttextbox%
\advance\[email protected]\dp\pgfnodeparttextbox%
}%
%
% Process the relative callout pointer.
%
\ifpgf@lib@callout@absolutepointer%
\else%
\pgfextract@process\calloutpointer{%
\pgfextract@process\borderpoint{%
\expandafter\pgfpointborderrectangle\expandafter{\pgf@lib@callout@relativepointer}%
{\pgfqpoint{\xtemp}{\ytemp}}%
}%
\pgfmathanglebetweenpoints{\pgfpointorigin}{\borderpoint}%
\let\pointerangle\pgfmathresult%
\expandafter\pgf@process\expandafter{\pgf@lib@callout@relativepointer}%
\pgfmathveclen@{\pgfmath@tonumber{\pgf@x}}{\pgfmath@tonumber{\pgf@y}}%
\edef\pointerradius{\pgfmathresult pt}%
\pgfpointadd{\borderpoint}{\pgfqpointpolar{\pointerangle}{\pointerradius}}%
\pgf@xa\pgf@x%
\pgf@ya\pgf@y%
\centerpoint%
\advance\pgf@x\pgf@xa%
\advance\pgf@y\pgf@ya%
}%
\pgf@lib@callouts@shortenpointer%
\addtosavedmacro\calloutpointer%
\pgf@lib@rectanglecallout@pointer%
\addtosavedmacro\calloutpointeranchor%
\addtosavedmacro\beforecalloutpointer%
\addtosavedmacro\aftercalloutpointer%
\addtosavedmacro\firstpoint%
\addtosavedmacro\secondpoint%
\addtosavedmacro\thirdpoint%
\addtosavedmacro\fourthpoint%
\fi%
}
\savedanchor\centerpoint{%
\[email protected]\wd\pgfnodeparttextbox%
\[email protected]\ht\pgfnodeparttextbox%
\advance\[email protected]\dp\pgfnodeparttextbox%
}
\savedanchor\basepoint{%
\[email protected]\wd\pgfnodeparttextbox%
\pgf@y0pt\relax%
}
\savedanchor\midpoint{%
\[email protected]\wd\pgfnodeparttextbox%
\pgfmathsetlength\pgf@y{+.5em}%
}
\anchor{center}{\centerpoint}
\anchor{mid}{\midpoint}
\anchor{mid east}{%
\rectanglecalloutpoints%
\midpoint%
\advance\pgf@x\xlength\relax%
}
\anchor{mid west}{%
\rectanglecalloutpoints%
\midpoint%
\advance\pgf@x-\xlength\relax%
}
\anchor{base}{\basepoint}
\anchor{base east}{%
\rectanglecalloutpoints%
\basepoint%
\advance\pgf@x\xlength\relax%
}
\anchor{base west}{%
\rectanglecalloutpoints%
\basepoint%
\advance\pgf@x-\xlength\relax%
}
\anchor{north}{%
\rectanglecalloutpoints%
\centerpoint%
\advance\pgf@y\ylength\relax%
}%
\anchor{south}{%
\rectanglecalloutpoints%
\centerpoint%
\advance\pgf@y-\ylength\relax%
}%
\anchor{east}{%
\rectanglecalloutpoints%
\centerpoint%
\advance\pgf@x\xlength\relax%
}%
\anchor{west}{%
\rectanglecalloutpoints%
\centerpoint%
\advance\pgf@x-\xlength\relax%
}%
\anchor{north east}{%
\rectanglecalloutpoints%
\centerpoint%
\advance\pgf@x\xlength\relax%
\advance\pgf@y\ylength\relax%
}%
\anchor{south west}{%
\rectanglecalloutpoints%
\centerpoint%
\advance\pgf@x-\xlength\relax%
\advance\pgf@y-\ylength\relax%
}%
\anchor{south east}{%
\rectanglecalloutpoints%
\centerpoint%
\advance\pgf@x\xlength\relax%
\advance\pgf@y-\ylength\relax%
}%
\anchor{north west}{%
\rectanglecalloutpoints%
\centerpoint%
\advance\pgf@x-\xlength\relax%
\advance\pgf@y\ylength\relax%
}%
\anchor{pointer}{%
\rectanglecalloutpoints%
\calloutpointeranchor%
}%
\backgroundpath{%
\rectanglecalloutpoints%
\pgf@x\xlength\relax%
\pgf@y\ylength\relax%
\pgfmathaddtolength\pgf@x{-\pgfkeysvalueof{/pgf/outer xsep}}%
\pgfmathaddtolength\pgf@y{-\pgfkeysvalueof{/pgf/outer ysep}}%
\edef\xtemp{\the\pgf@x}%
\edef\ytemp{\the\pgf@y}%
%
% The absolute pointer must be calculated here because the
% anchor of the shape (which is calculated after the saved
% macros and points) affects how the pointer joins the
% main rectangle.
%
\ifpgf@lib@callout@absolutepointer%
\pgfextract@process\calloutpointer{%
\pgfpointanchor{pgf@lib@callout@pointer}{center}%
}%
\pgf@lib@callouts@shortenpointer%
\pgfmathsetlengthmacro\pointerwidth{\pgfkeysvalueof{/pgf/callout pointer width}}%
\pgf@lib@rectanglecallout@pointer%
%
% \pgf@node@name = the shape name (from \pgfmultipartnode)
%
\ifx\pgf@node@name\pgfutil@empty%
\else%
%
% Now hack an extra saved anchor \calloutpointeranchor,
% with the new anchor for the callout pointer.
%
\edef\pgf@sh@@temp{\noexpand\expandafter\noexpand\pgfutil@g@addto@macro\noexpand\csname pgf@sh@np@\pgf@node@name\noexpand\endcsname}%
\edef\pgf@sh@@@temp{%
\noexpand\def\noexpand\calloutpointeranchor{%
\noexpand\pgf@x\the\pgf@x%
\noexpand\pgf@y\the\pgf@y%
}%
}%
\expandafter\pgf@sh@@temp\expandafter{\pgf@sh@@@temp}%
\fi%
\fi%
{%
\pgfsetcornersarced{\pgfqpoint{0pt}{0pt}}%
\pgfpathmoveto{\beforecalloutpointer}%
}%
\pgfpathlineto{\calloutpointer}%
{%
\pgfsetcornersarced{\pgfqpoint{0pt}{0pt}}%
\pgfpathlineto{\aftercalloutpointer}%
}%
{%
\pgftransformshift{\centerpoint}%
\pgfpathlineto{\firstpoint}%
\pgfpathlineto{\secondpoint}%
\pgfpathlineto{\thirdpoint}%
\pgfpathlineto{\fourthpoint}%
{%
\pgfsetcornersarced{\pgfqpoint{0pt}{0pt}}%
\pgfpathclose%
}%
}
}
\anchorborder{%
\pgfextract@process\externalpoint{}%
\rectanglecalloutpoints%
\pgfpointadd{\centerpoint}%
{%
\pgfpointborderrectangle{\pgfpointadd{\centerpoint}{\externalpoint}}%
{\pgfqpoint{\xlength}{\ylength}}%
}%
}%
}
% \pgf@lib@rectanglecallout@pointer
%
% Internal macro for calculations relating to the rectangle callout.
%
% Requires the following to be set up:
%
% \calloutpointer - the location of the callout point.
% \xtemp - the half width of the rectangle
% \ytemp - the half height of the rectangle
% \pointerwidth - the width of the pointer.
%
\def\pgf@lib@rectanglecallout@pointer{%
%
% Ensure that the pointer never connects to the main shape
% too near to a corner. This is done for two reasons:
% 1. It can look ugly.
% 2. If the corners are rounded, a mess can result.
%
% By malipivo, 2014-03-17, two lines
\pgfmathsetlengthmacro\moveleftright{\pgfkeysvalueof{/pgf/callout pointer move}}%
\addtosavedmacro\moveleftright%
\pgfextract@process\borderpoint{%
\pgfpointborderrectangle{%
\centerpoint%
\pgf@xa\pgf@x%
\pgf@ya\pgf@y%
\calloutpointer%
\advance\pgf@x-\pgf@xa%
}{\pgfqpoint{\xtemp}{\ytemp}}%
}%
\pgfmathanglebetweenpoints{\pgfpointorigin}{\borderpoint}%
\let\borderangle\pgfmathresult%
%
\pgfutil@tempdima\pointerwidth\relax%
\pgf@xa\xtemp\relax%
\advance\pgf@xa-\pgfutil@tempdima%
\pgf@ya\ytemp\relax%
\advance\pgf@ya-\pgfutil@tempdima%
%
\pgf@process{%
\pgfutil@ifundefined{pgf@corner@arc}{\pgfpointorigin}{%
\expandafter\pgfqpoint\pgf@corner@arc}%
}%
\advance\pgf@xa-\pgf@x%
\advance\pgf@ya-\pgf@y%
%
\borderpoint%
\pgf@xb\pgf@x%
\advance\pgf@xb by \moveleftright% malipivo
\pgf@yb\pgf@y%
%
\pgf@xc0pt\relax%
\pgf@yc0pt\relax%
%
\pgfmathanglebetweenpoints{\pgfpointorigin}{\pgfqpoint{\xtemp}{\ytemp}}%
\ifdim\borderangle pt<\pgfmathresult pt\relax%
\[email protected]\pgfutil@tempdima%
\ifdim\pgf@yb>\pgf@ya%
\pgf@yb\pgf@ya%
\fi%
%
% Establish the order for drawing the rectangle corners.
%
\edef\firstpoint{\noexpand\pgfqpoint{\xtemp}{\ytemp}}%
\edef\secondpoint{\noexpand\pgfqpoint{-\xtemp}{\ytemp}}%
\edef\thirdpoint{\noexpand\pgfqpoint{-\xtemp}{-\ytemp}}%
\edef\fourthpoint{\noexpand\pgfqpoint{\xtemp}{-\ytemp}}%
\else%
\pgfmathanglebetweenpoints{\pgfpointorigin}{\pgfqpoint{-\xtemp}{\ytemp}}%
\ifdim\borderangle pt<\pgfmathresult pt\relax%
\[email protected]\pgfutil@tempdima%
\ifdim\pgf@xb>\pgf@xa%
\pgf@xb\pgf@xa%
\else%
\ifdim\pgf@xb<-\pgf@xa%
\pgf@xb-\pgf@xa%
\fi%
\fi%
\edef\firstpoint{\noexpand\pgfqpoint{-\xtemp}{\ytemp}}%
\edef\secondpoint{\noexpand\pgfqpoint{-\xtemp}{-\ytemp}}%
\edef\thirdpoint{\noexpand\pgfqpoint{\xtemp}{-\ytemp}}%
\edef\fourthpoint{\noexpand\pgfqpoint{\xtemp}{\ytemp}}%
\else%
\pgfmathanglebetweenpoints{\pgfpointorigin}{\pgfqpoint{-\xtemp}{-\ytemp}}%
\ifdim\borderangle pt<\pgfmathresult pt\relax%
\[email protected]\pgfutil@tempdima%
\ifdim\pgf@yb>\pgf@ya%
\pgf@yb\pgf@ya%
\else%
\ifdim\pgf@yb<-\pgf@ya%
\pgf@yb-\pgf@ya%
\fi%
\fi%
\edef\firstpoint{\noexpand\pgfqpoint{-\xtemp}{-\ytemp}}%
\edef\secondpoint{\noexpand\pgfqpoint{\xtemp}{-\ytemp}}%
\edef\thirdpoint{\noexpand\pgfqpoint{\xtemp}{\ytemp}}%
\edef\fourthpoint{\noexpand\pgfqpoint{-\xtemp}{\ytemp}}%
\else%
\pgfmathanglebetweenpoints{\pgfpointorigin}{\pgfqpoint{\xtemp}{-\ytemp}}%
\ifdim\borderangle pt<\pgfmathresult pt\relax%
\[email protected]\pgfutil@tempdima%
\ifdim\pgf@xb>\pgf@xa%
\pgf@xb\pgf@xa%
\else%
\ifdim\pgf@xb<-\pgf@xa%
\pgf@xb-\pgf@xa%
\fi%
\fi%
\edef\firstpoint{\noexpand\pgfqpoint{\xtemp}{-\ytemp}}%
\edef\secondpoint{\noexpand\pgfqpoint{\xtemp}{\ytemp}}%
\edef\thirdpoint{\noexpand\pgfqpoint{-\xtemp}{\ytemp}}%
\edef\fourthpoint{\noexpand\pgfqpoint{-\xtemp}{-\ytemp}}%
\else%
\[email protected]\pgfutil@tempdima%
\ifdim\pgf@yb<-\pgf@ya%
\pgf@yb-\pgf@ya%
\fi%
\edef\firstpoint{\noexpand\pgfqpoint{\xtemp}{\ytemp}}%
\edef\secondpoint{\noexpand\pgfqpoint{-\xtemp}{\ytemp}}%
\edef\thirdpoint{\noexpand\pgfqpoint{-\xtemp}{-\ytemp}}%
\edef\fourthpoint{\noexpand\pgfqpoint{\xtemp}{-\ytemp}}%
\fi%
\fi%
\fi%
\fi%
\pgfextract@process\beforecalloutpointer{%
\centerpoint%
\advance\pgf@x\pgf@xb%
\advance\pgf@y\pgf@yb%
\advance\pgf@x-\pgf@xc%
\advance\pgf@y-\pgf@yc%
}%
\pgfextract@process\aftercalloutpointer{%
\centerpoint%
\advance\pgf@x\pgf@xb%
\advance\pgf@y\pgf@yb%
\advance\pgf@x\pgf@xc%
\advance\pgf@y\pgf@yc%
}%
%
% Now calculate the pointer anchor.
%
\pgfmathsetlength\pgf@x{\pgfkeysvalueof{/pgf/outer xsep}}%
\pgfmathsetlength\pgf@y{\pgfkeysvalueof{/pgf/outer ysep}}%
\ifdim\pgf@x>\pgf@y%
\edef\outersep{\the\pgf@x}%
\else%
\edef\outersep{\the\pgf@y}%
\fi%
\pgf@lib@callouts@pointeranchor%
}
\endinput
这是一个最小的工作示例{lua|pdf|xe|}latex
,其他格式的用户可能知道如何处理这样的代码,因为 TikZ 在 Plain TeX 和 ConTeXt 中工作(PDF 版本):
\documentclass[10pt,a4paper]{article}
\pagestyle{empty}
\usepackage{tikz}
\usetikzlibrary{shapes}
\usepgflibrary{malipivo.callouts.patch.v1}
\begin{document}
\begin{tikzpicture}
\node[draw, rounded corners=2pt, rectangle]
at (2.6,-1.7) (c22) {Further Rectangle};
\node[rectangle callout, draw, red, inner sep=2pt,
callout absolute pointer={(c22.west)},
callout pointer move=-23mm,
callout pointer width=9mm,
] at (1.48,-.95) {no workarounds; no exceptions to optimizations};
\end{tikzpicture}
\end{document}
指针宽度为 9 毫米(这是 TikZ 中的常规选项),并向左侧移动 23 毫米。我对这两个参数进行了一些实验,以便您可以更好地了解正在发生的事情。我附上了一个非最小示例及其预览。第一页带有洋红色矩形是绝对定位的示例,接下来的两页说明了相对定位(PDF 版本)。
\documentclass[10pt,a4paper]{article}
\pagestyle{empty} % No page numbers please...
\usepackage{tikz} % The core of graphics engine...
\usetikzlibrary{shapes} % The core for callouts...
\usepgflibrary{malipivo.callouts.patch.v1} % An experiment...
\usepackage{multicol} \columnsep=10mm
\voffset=-1.5in \hoffset=-1.5in
\addtolength{\textwidth}{8cm}
\addtolength{\textheight}{7cm}
\begin{document}
\begin{multicols}{3}
\foreach\mytype/\mycolor in {absolute/magenta, relative/blue} {\newpage
\foreach\mymove in {-10,-8,...,10} {% Different moves and
\foreach\mywidth in {2,4,...,10} {% different widths of pointers.
\begin{tikzpicture}
\node[draw, rounded corners=2pt, rectangle] at (2.6,-1.7) (c22) {Further Rectangle};
\node[rectangle callout,
% ellipse callout, % Unsolved case...
% cloud callout, % Unsolved case...
draw, inner sep=2pt, \mycolor, align=center, text width=5cm,
callout \mytype\space pointer={(c22.west)}, % Type of pointer
callout pointer width=\mywidth mm, % Variable width (TikZ)
callout pointer move=\mymove mm, % Variable move (experiment)
] at (1.48,-.95) {width=\mywidth mm; move=$\mymove$ mm};
\end{tikzpicture}\par}\vspace{1cm}}}% The end of \foreach cycles
\end{multicols}
\end{document}