![Tikz Externalize:手动检查最新情况](https://linux22.com/image/466754/Tikz%20Externalize%EF%BC%9A%E6%89%8B%E5%8A%A8%E6%A3%80%E6%9F%A5%E6%9C%80%E6%96%B0%E6%83%85%E5%86%B5.png)
我正在使用这个宏将我的 pgfplots 缩放到所需的大小:
\newsavebox{\measuredSize}
\newcounter{int}
\newcommand{\resizeToMeasure}[3]{%
\pgfmathsetmacro{\pgfplotswidthtarget}{#2}%
\pgfmathsetmacro{\pgfplotswidth}{#2}%
\pgfmathsetmacro{\pgfplotsheighttarget}{#3}%
\pgfmathsetmacro{\pgfplotsheight}{#3}%
\setcounter{int}{1}%
\loop%
\addtocounter{int}{1}%
\begin{lrbox}{\measuredSize}%
\tikzset{external/export next=false,external/optimize=false}%
\input{#1}%
\end{lrbox}%
\pgfmathsetmacro{\pgfplotswidth}{\pgfplotswidth+\pgfplotswidthtarget-\wd\measuredSize}%
\pgfmathsetmacro{\pgfplotsheight}{\pgfplotsheight+\pgfplotsheighttarget-\ht\measuredSize}%
\ifnum \value{int}<\nIter
\repeat
\filename@parse{#1}
\tikzsetnextfilename{\filename@base}
\input{#1}}
但是,在重新编译而不更改文件时,pgfplots
我不想再次循环该文件,而只是使用库中创建的 pdf external
。所以我认为手动检查该文件并在文件更新后省略循环是一个好主意。在库源代码中,我发现\def\tikzexternal@externalizefig@systemcall@uptodatecheck#1
进行该检查并将其内容tikzpicture
作为参数 #1。现在我的问题是,我找不到库如何读取 tikzpicture 并将其放入该函数中。
以下是 MWE:
\documentclass{standalone}
\usepackage{tikz}
\usepackage{pgfplots}
\pgfplotsset{compat=newest}
\usepackage{filecontents}
\usetikzlibrary{external}
\makeatletter
\newsavebox{\measuredSize}
\newcounter{int}
\newcommand{\resizeToMeasure}[3]{%
\pgfmathsetmacro{\pgfplotswidthtarget}{#2}%
\pgfmathsetmacro{\pgfplotswidth}{#2}%
\pgfmathsetmacro{\pgfplotsheighttarget}{#3}%
\pgfmathsetmacro{\pgfplotsheight}{#3}%
\setcounter{int}{1}%
\loop%
\addtocounter{int}{1}%
\begin{lrbox}{\measuredSize}%
\tikzset{external/export next=false,external/optimize=false}%
\input{#1}%
\end{lrbox}%
\pgfmathsetmacro{\pgfplotswidth}{\pgfplotswidth+\pgfplotswidthtarget-\wd\measuredSize}%
\pgfmathsetmacro{\pgfplotsheight}{\pgfplotsheight+\pgfplotsheighttarget-\ht\measuredSize}%
\ifnum \value{int}<5
\repeat
\filename@parse{#1}
\tikzsetnextfilename{\filename@base}
\input{#1}}
\makeatother
\begin{document}
\begin{filecontents*}{tikzpicture01.tikz}
\begin{tikzpicture}
\begin{axis}[
height=\pgfplotsheight,
width=\pgfplotswidth
]
\addplot coordinates {
( 1.5, 1.28 )
( 1.75, 1.43 )
( 2.0, 1.59 )
( 2.25, 1.75 )
( 2.5, 1.91 )
( 2.75, 2.07 )
( 3.0, 2.23 )
};
\end{axis}
\end{tikzpicture}
\end{filecontents*}
\resizeToMeasure{tikzpicture01.tikz}{7cm}{7cm}
\end{document}
答案1
好的,我找到了一个解决方案,可以进行手动最新检查。不幸的是,我找不到使用库中的内部宏的方法external
,因此我编写了自己的宏\make@uptodate@check
,它与包中使用的宏非常相似。
\def\make@uptodate@check#1{
\def\scanText{}%
\def\name@tikzpicture{tikzpicture}%
\CatchFileDef{\myTikz}{#1}{}%
\long\def\collect@tikz@from@begin##1\begin##2{%
\def\name@environment@begin{##2}%
\ifx\name@environment@begin\name@tikzpicture%
\expandafter\collect@tikz@after@begin%
\else%
\expandafter\collect@tikz@from@begin%
\fi%
}
\long\def\collect@tikz@after@begin##1\end##2{%
\def\name@environment@end{##2}%
\ifx\name@tikzpicture\name@environment@end%
\g@addto@macro\scanText{##1}
\else%
\g@addto@macro\scanText{##1\end{##2}}%
\expandafter\collect@tikz@after@begin%
\fi%
}
\expandafter\collect@tikz@from@begin\myTikz
\filename@parse{#1}%
\tikzsetnextfilename{\filename@base}%
\expandafter\tikzexternal@check@uptodate@mode\expandafter{\scanText}%
}
为了检查图片是否需要更新,它从环境中提取内容tikzpicture
并将其传递\tikzexternal@check@uptodate@mode
给external
库,该库也会更新\tikzexternal@file@isuptodate
。然后resizeToMeasure
检查文件是否是最新的,以跳过 for 循环并直接插入 pdf 文件。
以下是完整的 MWE:
\documentclass{article}
\usepackage{tikz}
\usepackage{catchfile}
\usepackage{pgfplots}
\usetikzlibrary{external} %
\tikzexternalize
\makeatletter
\def\make@uptodate@check#1{
\def\scanText{}%
\def\name@tikzpicture{tikzpicture}%
\CatchFileDef{\myTikz}{#1}{}%
\long\def\collect@tikz@from@begin##1\begin##2{%
\def\name@environment@begin{##2}%
\ifx\name@environment@begin\name@tikzpicture%
\expandafter\collect@tikz@after@begin%
\else%
\expandafter\collect@tikz@from@begin%
\fi%
}
\long\def\collect@tikz@after@begin##1\end##2{%
\def\name@environment@end{##2}%
\ifx\name@tikzpicture\name@environment@end%
\g@addto@macro\scanText{##1}
\else%
\g@addto@macro\scanText{##1\end{##2}}%
\expandafter\collect@tikz@after@begin%
\fi%
}
\expandafter\collect@tikz@from@begin\myTikz
\filename@parse{#1}%
\def\tikzexternal@curfilename{\tikzexternal@filenameprefix\filename@base}%
\expandafter\tikzexternal@check@uptodate@mode\expandafter{\scanText}%
}
\def\pgfmathsetglobalmacro#1#2{\pgfmathparse{#2}%
\global\let#1\pgfmathresult}
\newsavebox{\measuredSize}
\newcounter{int}
\newcommand{\resizeToMeasure}[3]{%
\pgfmathsetglobalmacro{\pgfplotswidthtarget}{#2}%
\pgfmathsetglobalmacro{\pgfplotswidth}{#2}%
\pgfmathsetglobalmacro{\pgfplotsheighttarget}{#3}%
\pgfmathsetglobalmacro{\pgfplotsheight}{#3}%
\make@uptodate@check{#1}%
\filename@parse{#1}%
\iftikzexternal@file@isuptodate%
\typeout{File is up to date! No loop needed!}%
\tikzsetnextfilename{\filename@base}
\input{#1}%
\else%
\typeout{Update File!}%
\setcounter{int}{1}
\loop
\typeout{1}
\addtocounter{int}{1}
\begin{lrbox}{\measuredSize}\tikzset{external/export next=false,external/optimize=false}\input{#1}\end{lrbox}%
\typeout{2}
\pgfmathsetglobalmacro{\pgfplotswidth}{\pgfplotswidth+\pgfplotswidthtarget-\wd\measuredSize}%
\pgfmathsetglobalmacro{\pgfplotsheight}{\pgfplotsheight+\pgfplotsheighttarget-\ht\measuredSize}%
\typeout{3}
\ifnum \value{int}<3%
\repeat%
\tikzset{external/force remake}
\tikzsetnextfilename{\filename@base}
\input{#1}%
\fi%
}
\makeatother
\begin{document}
\begin{filecontents*}{tikzpicture01.tikz}
\begin{tikzpicture}
\begin{axis}[
height=\pgfplotsheight,
width=\pgfplotswidth
]
\addplot coordinates {
( 1.5, 1.28 )
( 1.75, 1.43 )
( 2.0, 1.59 )
( 2.25, 1.75 )
( 2.5, 1.91 )
( 2.75, 2.07 )
( 3.0, 2.23 )
};
\end{axis}
\end{tikzpicture}
\end{filecontents*}
\resizeToMeasure{tikzpicture01.tikz}{7cm}{7cm}
\end{document}