缩放外部化的 tikz 图片

缩放外部化的 tikz 图片

我用下列答案为了缩放我的 tikzpictures。

现在我想谈谈外部化图形的问题。问题是该autoscale autoid选项有时需要 2 次编译才能使图形达到正确的大小,因此tikzexternal库生成的 pdf 图像通常大小不正确。

但是现在这些图形已经外部化(并且每个图形都生成了一个 pdf),我认为没有必要再使用它们了autoscale autoid

是否可以创建一个 tikz 环境,允许您管理0.5\columnwidth导入的 pdf(对应于 tikz 图形)的大小(例如)?

平均能量损失

\documentclass[twocolumn,landscape]{article}
\usepackage{xparse}
\usepackage{tikz,tkz-fct}
\usetikzlibrary{calc}
\usetikzlibrary{external}
%\tikzexternalize

\makeatletter
\ExplSyntaxOn
\msg_new:nnn { nilcouv } { duplicate-figure-id }
  { duplicate~figure~identifier:~'#1'. }

% Sequence recording all figure identifiers (for the 'scale to max size' TikZ
% style) found so far
\seq_new:N \g__nilcouv_scale_to_max_style_figure_ids_seq
% Counter used when generating automatic figure identifiers for 'autoscale'
\int_new:N \g_nilcouv_last_autogenerated_figure_nb_int

\cs_new_protected:Npn \__nilcouv_check_unique_id:n #1
  {
    \seq_if_in:NnTF \g__nilcouv_scale_to_max_style_figure_ids_seq {#1}
      { \msg_error:nnn { nilcouv } { duplicate-figure-id } {#1} }
      { \seq_gput_right:Nn \g__nilcouv_scale_to_max_style_figure_ids_seq {#1} }
  }

% Automatic generation of figure ids (the pattern is defined here)
\cs_new:Npn \__nilcouv_autogenerated_id:n #1 { nilcouv~autogenerated~id~#1 }

\cs_generate_variant:Nn \__nilcouv_autogenerated_id:n { V }

\cs_new_protected:Npn \__nilcouv_autoscale:nnn #1#2#3
  { \tikzset { scale~to~max~size={#1}{#2}{#3} } }

\cs_generate_variant:Nn \__nilcouv_autoscale:nnn { x }

\cs_new_protected:Npn \__nilcouv_autoscale_autoid:nn #1#2
  {
    % Increment the counter
    \int_gincr:N \g_nilcouv_last_autogenerated_figure_nb_int
    % Call the 'autoscale' style with the new id
    \__nilcouv_autoscale:xnn
      { \__nilcouv_autogenerated_id:V
        \g_nilcouv_last_autogenerated_figure_nb_int
      }
      {#1}
      {#2}
  }

% Set up aliases using LaTeX2e naming style
\cs_new_eq:NN \nilcouv@check@unique@id \__nilcouv_check_unique_id:n
\cs_new_eq:NN \nilcouv@autoscale@autoid \__nilcouv_autoscale_autoid:nn
\ExplSyntaxOff

% Autoscaling technique that doesn't affect font sizes in TikZ pictures.
% (based on code from marmot: <https://tex.stackexchange.com/a/497749/73317>)
%
% #1: unique per-picture id allowing several pictures to use this mechanism
%     in a given document (it should contain no control sequence token nor
%     active character)
% #2: target width
% #3: target height
\newcommand*{\nilcouv@ExportBB}[3]{%
  \path let
    \p1=($(current bounding box.north east)-(current bounding box.south west)$),
    \n1={#2/\x1},\n2={#3/\y1}
  in \pgfextra{\pgfmathsetmacro{\nilcouv@figscale}{min(\n1,\n2)}%
               \expandafter\xdef\csname nilcouv@auto@figscale@#1\endcsname{%
                 \nilcouv@figscale}};
  \immediate\write\@mainaux{%
    \string\expandafter
    \gdef\string\csname\space nilcouv@auto@figscale@#1\string\endcsname{%
      \csname nilcouv@auto@figscale@#1\endcsname}}%
}

\tikzset{
  % Arguments: figure identifier, target width, target height
  scale to max size/.style n args={3}{
    execute at end picture={\nilcouv@ExportBB{#1}{#2}{#3}},
    /utils/exec={\nilcouv@check@unique@id{#1}%
                 \ifcsname nilcouv@auto@figscale@#1\endcsname
                   \wlog{Found autoscale value for picture '#1'}%
                 \else
                   \typeout{Automatically-scaled pictures: please recompile
                            for picture '#1'.}%
                   \expandafter\gdef
                     \csname nilcouv@auto@figscale@#1\endcsname{1}%
                 \fi},
    scale=\csname nilcouv@auto@figscale@#1\endcsname,
  },
  % Same style except the id is automatically generated using a counter
  autoscale autoid/.style 2 args={%
    /utils/exec={\nilcouv@autoscale@autoid{#1}{#2}}},
}
% End of the code based on <https://tex.stackexchange.com/a/497749/73317>
\makeatother

\begin{document}

\begin{tikzpicture}[autoscale autoid={0.3\columnwidth}{\maxdimen}]
\tkzInit[xmin=-1,xmax=3,ymin=-1,ymax=1.2]
\tkzDrawX
\tkzDrawY
% Fonction 
\tkzClip
\tkzFct[thick,domain=0.55:5]{(\x*\x+\x-1)/(\x**3)}
\tkzDefPointByFct(1.39)\tkzGetPoint{A}\tkzDrawPoint[size=3](A)
\draw[dotted,thick] (1.39,0) -- (1.39, 0.86) -- (0,0.86) node[left] {\( f(x) \)};
\draw[thick] (1.39,-0.1) node[below] {\( x \)} -- (1.39,0.1);
%Annotations
\draw[<->,ultra thick] (1,-0.35) -- (2,-0.35);
\node at (1.5,-0.45){\(A\)};
\draw[dashed] (1, 0) -- (1, 1) -- (0, 1);
\draw[dashed] (2, 0) -- (2, 0.625) -- (0, 0.625);
\draw[<->,ultra thick] (-0.6,0.625) -- (-0.6,1);
\end{tikzpicture}

\end{document}

答案1

这个想法cfr 的答案绝对合理:如果/当命令不想被记忆时,它应该发出\mmzAbort。这正是 Memoize 本身处理\refs 的方式:它会中止记忆,直到引用被定义。

我发布新的答案只是为了解决一些细节问题,其中一些与记忆有关,一些则无关。

  1. 枚举自动缩放的图片的缺点是,在插入或删除图片时需要重新编译它们。

  2. cfr 检测缩放因子是否稳定的机制对于记忆化来说是绝对必要的——否则,就无法判断图片何时准备好了。然而,她的修改带来了一个问题:当目标宽度/高度发生变化时,图片不会调整大小。

  3. 类似地,一旦被记忆,图片就永远不会被重新编译。当\columnwidth发生变化时,问题就会出现。(当图片的代码发生变化时,这不是问题,例如当0.3\columnwidth更改为时0.5\columnwidth。)

  4. 自动缩放代码应该在有或没有 Memoize 的情况下都能工作。

下面的代码解决了所有这些问题。此外,我还擅自将其分成一个包(autoscale.sty)和文档,并根据自己的喜好设计 UI ;-)

问题 (1) 也与 TikZexternal库有关,Memoize 通过引用图片源代码的 md5sums 解决了这个问题。这里的问题当然是获取源代码,但 Memoize 使用的机制也可以被其他软件包轻松使用,因为它是作为单独的软件包 Advice 提供的。下面,Advice 的配置是,每当tikzpicture调用环境时,\storemdfivesum都会执行。这个宏将整个环境作为参数,并且可以轻松计算其 md5sum — 然后调用原始的tikzpicture

我通过将.aux缩放因子存储到控制序列\autoscale@factor@<md5sum> @<目标维度> 中来解决问题 (2)。每当目标宽度或高度发生变化时, 中的因子.aux根本不适用,并且调整大小从头开始。

对于 (3),参数 被autoscale width/height附加到 Memoize 的上下文中 — 每当上下文的值(即扩展)发生变化时,extern 都会被重新编译。虽然\mmzset/\mmznext{context={columnwidth=\the\columnwidth}}文档本身中的某些内容可以工作,但下面的自动缩放宏也可以做到这一点,只需将任何参数粘贴到autoscale width/height上下文中(并说明在图片被记忆时可以附加上下文)。

(4) 对于希望支持它的软件包,Memoize 有一个内置解决方案:软件包存根memoizable,它将所有 Memoize 命令定义为虚拟命令。

%%%%%%%%% autoscale.sty %%%%%%%%%

% cwestiwn: https://tex.stackexchange.com/questions/699289/scaling-externalized-tikz-pictures

% When a package uses Memoize commands, one should say
% \RequirePackage{memoizable} to freely use \mmzset etc. even when Memoize is
% not loaded.
% 
% I found two bugs in Memoize v1.0.0, however --- I forgot to load pgfkeys and
% define \mmzAbort in packages memoizable/nomemoize --- thus the workaround
% below (until v1.0.1).

\RequirePackage{pgfkeys}
\ifdefined\mmzAbort\else\let\mmzAbort\relax\fi
\RequirePackage{memoizable}

\RequirePackage{tikz}
\usetikzlibrary{calc}

% Automatically compute the md5sum of every tikzpicture environment; the md5sum
% is available, within and after the picture, in \currentmdfivesum.
\RequirePackage{advice} % actually unnecessary when Memoize is loaded
\pgfqkeys{/md5sum}{
  .install advice,
  advice={tikzpicture}{inner handler=\storemdfivesum},
}
\RequirePackage{pdftexcmds}
\ifdefined\luatexversion
\long\def\pdf@mdfivesum#1{%
  \directlua{%
    oberdiek.pdftexcmds.mdfivesum("\luaescapestring{#1}", "byte")%
  }%
}%
\fi
\def\storemdfivesum#1{%
  \xdef\currentmdfivesum{\pdf@mdfivesum{\unexpanded{#1}}}%
  \AdviceOriginal#1%
}

% The definition of autoscale begins here.

\tikzset{
  % #1 = target width/height
  autoscale width/.code={\autoscale{#1}{width}{\x1}},
  autoscale height/.code={\autoscale{#1}{height}{\y1}},
}

% #1 = target width/height, #2 = "width"/"height", #3 = "\x1"/"\y1"
\def\autoscale#1#2#3{%
  \ifcsdef{autoscale@factor@\currentmdfivesum @\the\dimexpr#1\relax}{%
    \letcs\autoscale@factor{autoscale@factor@\currentmdfivesum @\the\dimexpr#1\relax}%
  }{%
    \def\autoscale@factor{1}%
  }%
  \pgfkeysalso{%
    execute at end picture=\autoscale@size@to@aux{#1}{#2}{#3},
    scale=\autoscale@factor,
  }%
}

% #1 = target width/height, #2 = "width"/"height", #3 = "\x1"/"\y1"
\def\autoscale@size@to@aux#1#2#3{%
  \path let
  \p1=($(current bounding box.north east)-(current bounding box.south west)$),
  \n1={\autoscale@factor*\x1},
  \n2={#1/#3}
  in \pgfextra{%
    \autoscale@if@roughly@equal{0.1pt}{#1}{\n1}{%
      \immediate\write\@mainaux{%
        \csgdef{autoscale@factor@\currentmdfivesum @\the\dimexpr#1\relax}{\autoscale@factor}%
      }%
      \mmzset{context={target #2=\the\dimexpr#1\relax}}%
    }{%
      \immediate\write\@mainaux{%
        \csgdef{autoscale@factor@\currentmdfivesum @\the\dimexpr#1\relax}{\n2}%
        }%
      \mmzAbort
    }%
  };
}

% Such a macro is actually already defined by Memoize, but as we want autoscale
% to work without Memoize as well, I copied the definition here.  This macro
% checks whether the given dimensions (|#2| and |#3|) are equal within the
% tolerance given by |#1|. (We don't use |\ifpdfabsdim|, because it is
%   unavailable in \hologo{XeTeX}.)
\def\autoscale@if@roughly@equal#1#2#3{%
  \dimen0=\dimexpr#2-#3\relax
  \ifdim\dimen0<0pt
    \dimen0=-\dimen0\relax
  \fi
  \ifdim\dimen0>#1\relax
    \expandafter\@secondoftwo
  \else
    \expandafter\@firstoftwo
  \fi
}%

以及文件:

\documentclass[twocolumn,landscape]{article}

% Memoize must be loaded before autoscale, because autoscale supports
% Memoize. And it must be loaded before tkz-fct, because the latter loads TikZ
% library "fadings".
\usepackage{memoize}
\usepackage{autoscale} % loads TikZ as well
\usepackage{tkz-fct}

\usepackage{lipsum}
\begin{document}

\lipsum[1]

\noindent
\begin{tikzpicture}[autoscale width=\columnwidth]
  \tkzInit[xmin=-1,xmax=3,ymin=-1,ymax=1.2]
  \tkzDrawX
  \tkzDrawY
  % Fonction 
  \tkzClip
  \tkzFct[thick,domain=0.55:5]{(\x*\x+\x-1)/(\x**3)}
  \tkzDefPointByFct(1.39)\tkzGetPoint{A}\tkzDrawPoint[size=3](A)
  \draw[dotted,thick] (1.39,0) -- (1.39, 0.86) -- (0,0.86) node[left] {\( f(x) \)};
  \draw[thick] (1.39,-0.1) node[below] {\( x \)} -- (1.39,0.1);
  % Annotations
  \draw[<->,ultra thick] (1,-0.35) -- (2,-0.35);
  \node at (1.5,-0.45){\(A\)};
  \draw[dashed] (1, 0) -- (1, 1) -- (0, 1);
  \draw[dashed] (2, 0) -- (2, 0.625) -- (0, 0.625);
  \draw[<->,ultra thick] (-0.6,0.625) -- (-0.6,1);
\end{tikzpicture}%

\lipsum[2]

\end{document}

答案2

思考此版本有效。需要 3 次编译才能使输出稳定。并且(最终!)输出(希望)保持稳定。

这使用memoize而不是external库。如果您使用默认perl提取方法或python版本,则不需要完整的 shell-escape。

基本思想是,autoscale除非新计算的比例因子相差不大,否则不要使用新计算的比例因子,以防止原始代码所需的连续重新编译,否则该因子在每次编译时都会发生变化。 (这与外部化无关。 它只是原始代码的一个功能。)

然后,我们将得到的缩放因子与上一次编译时得到的缩放因子进行比较(如果有的话)。如果因子不同,我们将中止记忆化。如果因子相同,我们将继续。记忆化是否真正完成取决于进一步观察的情况memoize。我们只是不会强行停止它。

无论如何,这不是一个理想的解决方案,因为我们没有使用适当的记忆机制来确定何时编译外部映像。但我思考它确实有效。但我仍然不知道它失败的所有情况。

\documentclass[twocolumn,landscape]{article}
% cwestiwn: https://tex.stackexchange.com/questions/699289/scaling-externalized-tikz-pictures
\usepackage[extract=perl]{memoize}
\usepackage{tikz,tkz-fct}
\usetikzlibrary{calc}

\makeatletter
\ExplSyntaxOn
\msg_new:nnn { nilcouv } { duplicate-figure-id }
{ duplicate~figure~identifier:~'#1'. }

% Sequence recording all figure identifiers (for the 'scale to max size' TikZ
% style) found so far
\seq_new:N \g__nilcouv_scale_to_max_style_figure_ids_seq
% Counter used when generating automatic figure identifiers for 'autoscale'
\int_new:N \g_nilcouv_last_autogenerated_figure_nb_int

\cs_new_protected:Npn \__nilcouv_check_unique_id:n #1
{
  \seq_if_in:NnTF \g__nilcouv_scale_to_max_style_figure_ids_seq {#1}
  { \msg_error:nnn { nilcouv } { duplicate-figure-id } {#1} }
  { \seq_gput_right:Nn \g__nilcouv_scale_to_max_style_figure_ids_seq {#1} }
}

% Automatic generation of figure ids (the pattern is defined here)
\cs_new:Npn \__nilcouv_autogenerated_id:n #1 { nilcouv~autogenerated~id~#1 }

\cs_generate_variant:Nn \__nilcouv_autogenerated_id:n { V }

\cs_new_protected:Npn \__nilcouv_autoscale:nnn #1#2#3
{ 
  \tikzset { scale~to~max~size={#1}{#2}{#3} } 
}

\cs_generate_variant:Nn \__nilcouv_autoscale:nnn { x }

\cs_new_protected:Npn \__nilcouv_autoscale_autoid:nn #1#2
{
  % Increment the counter
  \int_gincr:N \g_nilcouv_last_autogenerated_figure_nb_int
  % Call the 'autoscale' style with the new id
  \__nilcouv_autoscale:xnn
  { \__nilcouv_autogenerated_id:V
    \g_nilcouv_last_autogenerated_figure_nb_int
  }
  {#1}
  {#2}
}


% Set up aliases using LaTeX2e naming style
\cs_new_eq:NN \nilcouv@check@unique@id \__nilcouv_check_unique_id:n
\cs_new_eq:NN \nilcouv@autoscale@autoid \__nilcouv_autoscale_autoid:nn
\ExplSyntaxOff

% Autoscaling technique that doesn't affect font sizes in TikZ pictures.
% (based on code from marmot: <https://tex.stackexchange.com/a/497749/73317>)
%
% #1: unique per-picture id allowing several pictures to use this mechanism
%     in a given document (it should contain no control sequence token nor
%     active character)
% #2: target width
% #3: target height
\newcommand*{\nilcouv@ExportBB}[3]{%
  \path let
  \p1=($(current bounding box.north east)-(current bounding box.south west)$),
  \n1={#2/\x1},\n2={#3/\y1}
  in \pgfextra{\pgfmathsetmacro{\nilcouv@figscale}{min(\n1,\n2)}%
    \ifcsname nilcouv@auto@figscale@#1\endcsname
      \edef\nilcouv@tmpb{\csname nilcouv@auto@figscale@#1\endcsname}%
      \pgfmathsetmacro \nilcouv@tmpc{\nilcouv@tmpb - \nilcouv@figscale}%
      \ifdim \nilcouv@tmpc pt<0.1pt
        \relax
      \else
        \expandafter\xdef\csname nilcouv@auto@figscale@#1\endcsname{%
          \nilcouv@figscale}%
      \fi
      \else
        \expandafter\xdef\csname nilcouv@auto@figscale@#1\endcsname{%
          \nilcouv@figscale}%
      \fi
      \edef\nilcouv@tmpe{\csname nilcouv@auto@figscale@old@#1\endcsname}%
      \ifx\nilcouv@tmpe\nilcouv@tmpb
        \relax
      \else
        \mmzAbort
      \fi
    };
  \immediate\write\@mainaux{%
    \string\expandafter
    \gdef\string\csname\space nilcouv@auto@figscale@old@#1\string\endcsname{%
      \csname nilcouv@auto@figscale@#1\endcsname}%
    \string\expandafter
    \gdef\string\csname\space nilcouv@auto@figscale@#1\string\endcsname{%
      \csname nilcouv@auto@figscale@#1\endcsname}}%
}

\tikzset{
  % Arguments: figure identifier, target width, target height
  scale to max size/.style n args={3}{%
    execute at end picture={\nilcouv@ExportBB{#1}{#2}{#3}},
    /utils/exec={\nilcouv@check@unique@id{#1}%
      \ifcsname nilcouv@auto@figscale@#1\endcsname
        \wlog{Found autoscale value for picture '#1'}%
      \else
        \typeout{Automatically-scaled pictures: please recompile
          for picture '#1'.}%
        \expandafter\gdef
        \csname nilcouv@auto@figscale@#1\endcsname{1}%
      \fi
    },
    scale=\csname nilcouv@auto@figscale@#1\endcsname,
  },
  % Same style except the id is automatically generated using a counter
  autoscale autoid/.style 2 args={%
    /utils/exec={%
      \nilcouv@autoscale@autoid{#1}{#2}%
    },
  },
}
% End of the code based on <https://tex.stackexchange.com/a/497749/73317>
\makeatother

\begin{document}
\begin{tikzpicture}[autoscale autoid={0.3\columnwidth}{\maxdimen}]
  \tkzInit[xmin=-1,xmax=3,ymin=-1,ymax=1.2]
  \tkzDrawX
  \tkzDrawY
  % Fonction 
  \tkzClip
  \tkzFct[thick,domain=0.55:5]{(\x*\x+\x-1)/(\x**3)}
  \tkzDefPointByFct(1.39)\tkzGetPoint{A}\tkzDrawPoint[size=3](A)
  \draw[dotted,thick] (1.39,0) -- (1.39, 0.86) -- (0,0.86) node[left] {\( f(x) \)};
  \draw[thick] (1.39,-0.1) node[below] {\( x \)} -- (1.39,0.1);
  %Annotations
  \draw[<->,ultra thick] (1,-0.35) -- (2,-0.35);
  \node at (1.5,-0.45){\(A\)};
  \draw[dashed] (1, 0) -- (1, 1) -- (0, 1);
  \draw[dashed] (2, 0) -- (2, 0.625) -- (0, 0.625);
  \draw[<->,ultra thick] (-0.6,0.625) -- (-0.6,1);
\end{tikzpicture}%

width is 96.05pt and height is 6.83331pt

width is 97.16948pt and height is 6.83331pt

width is 132.29497pt and height is 6.83331pt



abcdefghijklmnopqrstuvwxyz

\end{document}  

使用 memoize 进行外部化、自动缩放图像

編輯記錄:

\mmzPrefix {.//prawf.}
\mmzUsedCMemo {.//prawf.AB565A279548684A84116CD5604FF9BE.memo}
\mmzUsedExtern {.//prawf.AB565A279548684A84116CD5604FF9BE-E778DCCCB8AAB0BBD3F6CFEEFD2421F8.pdf}
\mmzUsedCCMemo {.//prawf.AB565A279548684A84116CD5604FF9BE-E778DCCCB8AAB0BBD3F6CFEEFD2421F8.memo}
\endinput 

文件:

prawf.AB565A279548684A84116CD5604FF9BE-E778DCCCB8AAB0BBD3F6CFEEFD2421F8.memo  
prawf.AB565A279548684A84116CD5604FF9BE.memo  
prawf.mmz.log
prawf.AB565A279548684A84116CD5604FF9BE-E778DCCCB8AAB0BBD3F6CFEEFD2421F8.pdf   
prawf.mmz

答案3

memoize我也考虑过新包装,@cfr 对此进行了很好的总结。 和他们的评论基本上也在这里实现。我没有使用链接的代码,而是使用ext.scalepicture我自己的库tikz-ext包裹并添加了两件事:

  1. 停止条件(参见/tikz/scale picture diff):

    当两次运行之间的图表尺寸差异小于此长度(在两个方向上)时,该图片被认为是最终的和稳定的。

    如果没有它,有两个因素可能会导致这个过程永无止境,而 PGFMath 的不精确性也无济于事:

    1. 节点。
    2. 线宽。

    除非使用(节点)或(线宽),否则这两个东西都不会随scale/ xscale/缩放。而这两者我们通常都不想使用。yscaletransform shapetransform canvas

    像这样的图片

    \tikz
      \draw (0cm, 0cm) rectangle (1cm, 1cm);
    

    尺寸不是 1cm × 1cm 而是 (1cm + 0.4pt) × (1cm + 0.4pt),因为四边都添加了一半的线宽。(默认线宽为 0.4pt/ thin。)

    下面代码中的第一个图像大约需要五次编译,因为节点与边界框接壤。

    甚至有些图像根本无法缩放,这两个图像具有完全相同的尺寸(使用 depecratedright ofpositioningright=of——尽管我们可以node distance根据需要实现更好的键。

    \tikz[scale=1, nodes=draw]\node (A) {ABC} node[right of=A] {DEF};
    \tikz[scale=2, nodes=draw]\node (A) {ABC} node[right of=A] {DEF};
    
  2. \csname mmzAbort\endcsname然后使用宏(使\csname此代码与没有的文档兼容memoize

    这样,如果图片尚未准备好,我们就不会将其外部化。

    externalize库不提供此功能,其工作流程甚至不允许在没有另一层开销工作的情况下实现该功能。

    如果您更改图表或/tikz/scale picture diff值,Memoize 会注意到并生成一张新图片。

请注意F你的f(x)左边被切断,因为这个节点不能缩放,但是左边的空间由于缩放,轴变得非常小,以至于节点大于\tkzClip

代码

\documentclass{article}
\usepackage{memoize}
\usepackage{tikz}
\usetikzlibrary{ext.scalepicture}
\tikzset{
  scale picture diff/.initial=+0.05pt,
  scale picture diff/.value to context}
\makeatletter
\renewcommand*\tikzext@scalepicture@savepicturesize{% overwrite
  \pgf@process{\pgfpointdiff{\pgfpointanchor{current bounding box}{south west}}
                            {\pgfpointanchor{current bounding box}{north east}}}%
  \pgf@xa=\pgf@x \pgf@ya=\pgf@y
  \pgfutil@IfUndefined{tikzext@scalepicture@\pgfpictureid}{%
    \tikzext@scalepicture@write
  }{%
    \tikzext@ifapproxequalto{\pgf@x}{\tikzext@scalepicture@width}{}{%
      \tikzext@ifapproxequalto{\pgf@y}{\tikzext@scalepicture@height}{}{%
        \tikzext@scalepicture@write}}}%
  \let\tikzext@scalepicture@savepicturesize\relax}% only once per picture
\newcommand*\tikzext@scalepicture@write{%
  \immediate\write\pgfutil@auxout{\noexpand\expandafter\gdef\noexpand\csname
    tikzext@scalepicture@\pgfpictureid\endcsname{{\the\pgf@xa}{\the\pgf@ya}}}%
  \csname mmzAbort\endcsname}
% pgfmathapproxequalto checks against 0.0001, too precise for this
\newcommand*\tikzext@ifapproxequalto[2]{%
  \pgfmathsetlength\pgfutil@tempdima{\pgfkeysvalueof{/tikz/scale picture diff}}%
  \advance#1by-#2\relax \ifdim#1<0pt #1=-#1\fi
  \ifdim#1<\pgfutil@tempdima\relax \expandafter\pgfutil@firstoftwo
                             \else \expandafter\pgfutil@secondoftwo \fi}
\makeatother

\usepackage{tikz,tkz-fct}
\begin{document}
\rule{4cm}{4pt}

\begin{tikzpicture}[picture width=4cm, nodes=draw, ultra thick]
\node {ABC};
\node at (2,1) {DEF};
\end{tikzpicture}

\rule{.3\columnwidth}{.4pt}

\begin{tikzpicture}[picture width=.3\columnwidth]
\tkzInit[xmin=-1,xmax=3,ymin=-1,ymax=1.2]
\tkzDrawX\tkzDrawY\tkzClip
\tkzFct[thick,domain=0.55:5]{(\x*\x+\x-1)/(\x**3)}
\tkzDefPointByFct(1.39)\tkzGetPoint{A}\tkzDrawPoint[size=3](A)
\draw[dotted,thick] (1.39,0) -- (1.39, 0.86) -- (0,0.86) node[left] {\( f(x) \)};
\draw[thick] (1.39,-0.1) node[below] {\( x \)} -- (1.39,0.1);
%Annotations
\draw[<->] (1,-0.35) -- (2,-0.35);
\node at (1.5,-0.45){\(A\)};
\draw[dashed] (1, 0) -- (1, 1) -- (0, 1);
\draw[dashed] (2, 0) -- (2, 0.625) -- (0, 0.625);
\draw[<->] (-0.6,0.625) -- (-0.6,1);
\end{tikzpicture}

\tikz[scale=1, nodes=draw]\node (A) {ABC} node[right of=A] {DEF};
\tikz[scale=2, nodes=draw]\node (A) {ABC} node[right of=A] {DEF};
\end{document}

输出

在此处输入图片描述

相关内容