使用 pgfmultipartnode 及其参数(在 pgflibraryshapes.callouts.code.tex 中)

使用 pgfmultipartnode 及其参数(在 pgflibraryshapes.callouts.code.tex 中)

我想稍微修改一下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)。我主要关注绝对+相对矩形标注,其他包括圆+椭圆相关的计算。我需要:

  1. 一个新的维度/定义或一个新的 pgfkey。
  2. 存储 pgfkey。
  3. 正确使用 pgfkey。

至 1.我已\pgfkeys{/pgf/.cdcallout 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}

纳米MWE1 纳米分子 纳米MWE3

相关内容