5

Suppose I have two images generated using tikz and saved as pdf files. Both had internal nodes that could be referenced at that time. My question is: is there a way to reference those internal nodes if I'm including them in a third document as PDF images?

Of course this mechanism is not needed for the MWE below, however the actual target is a more complex structure.

%% file1.tex
\documentclass[tikz]{standalone};
\begin{document}
\begin{tikzpicture}
    \node[draw](1){1};
\end{tikzpicture}
\end{document}

%% file2.tex
\documentclass[tikz]{standalone};
\begin{document}
\begin{tikzpicture}
    \node[draw](2){2};
\end{tikzpicture}
\end{document}

%% file3.tex
\documentclass[tikz]{standalone};
\begin{document}
\begin{tikzpicture}
    \node[]at(-2,-2){\includegraphics{file1.pdf};
    \node[]at(+2,+2){\includegraphics{file2.pdf};
    %% here is the catch
    % \draw(1)--(2);
\end{tikzpicture}
\end{document}

savebox and friends could be a solution if they preserve the internal node references when transformations are applied (such as rotate or scale), which is not the case as far as I was able to test.

4
  • 2
    I have a solution using \tikzmark for coordinates but it means that you'd have to specify in advance where on the nodes the path should go, rather than using the node shape. However the principle should be adaptable -- but it might need a new feature of \tikzmark. Before I attempt that, can I confirm that you want to treat these nodes as full nodes rather than just reference a specific coordinate (that could be determined in advance)? Feb 17, 2018 at 17:54
  • Hi, @LoopSpace! Thanks for taking a look at this question. In fact, I tried your nice tikzmark package before writing this question but I couldn't come up with a solution for what I wanted. Are you saying that your tikzmarks survive to the pdf generation? BTW: no, reference to coordinates seems to be enough. =)
    – tcpaiva
    Feb 17, 2018 at 18:19
  • 1
    Yes and no. The information generated by \tikzmark is saved to the aux file of the relevant tex file, so inputting the aux files from the subdocuments would load in their tikzmark information. It would then need a little bit of fiddling around with aligning origins to get them to line up, but all that information should be available so in principle that's possible. Feb 17, 2018 at 18:35
  • Sounds neat, @LoopSpace! I have no idea how you are able to do that. =)
    – tcpaiva
    Feb 17, 2018 at 18:38

1 Answer 1

9
+100

Update 2019-12-16: This ended up being merged into the tikzmark package. The code below works almost as-is with one change: \usetikzlibrary{tikzmark} instead of \usetikzlibrary{savenodes}.


(2018-02-18: Update to take into account node transformations)

While attempting a solution to this, I came across some code I'd written for How to save and restore the nodes between tikzpictures? about saving node information between tikz pictures. To transfer this information between documents just needs some way to save and load it, and then a bit of thought about bounding boxes.

As this code is essentially in use in two answers, I've put it into a separate file and uploaded it to github. You can download it from this github repository. At the moment, it's just a single file.

Here's an example based on your code. I use lualatex by default, I've indicated the changes if you use pdflatex. Note that I'm using the filecontents package to generate all of the files from one base file, if you're generating your files by a different method then you don't need these parts and you don't need the \immediate\write18 lines. This example needs running with the --shell-escape option because of this.

Here's the current example code:

\documentclass{article}
%\url{https://tex.stackexchange.com/q/415831/86}
\usepackage{shellesc}
\usepackage{tikz}
\usetikzlibrary{savenodes}
\usepackage{filecontents}

%% file1.tex
\begin{filecontents}{\jobname-1.tex}
\RequirePackage{luatex85}
\documentclass[tikz,border=10pt]{standalone}
\usetikzlibrary{savenodes,shapes.geometric}
\begin{document}
\begin{tikzpicture}[save nodes to file]
\node[draw,rotate=-30,save node](1) at (-2,0) {1};
\draw[->] (0,0) -- (1);
\node[draw,ellipse,save node] (c) at (current bounding box.center) {};
\end{tikzpicture}
\end{document}
\end{filecontents}

%% file2.tex
\begin{filecontents}{\jobname-2.tex}
\RequirePackage{luatex85}
\documentclass[tikz,border=10pt]{standalone}
\usetikzlibrary{savenodes,shapes.geometric}
\begin{document}
\begin{tikzpicture}[save nodes to file]
\node[draw,rotate=-70,save node] (2) at (2,0) {2};
\draw[->] (0,0) -- (2);
\node[draw,ellipse,save node] (c) at (current bounding box.center) {};
\end{tikzpicture}
\end{document}
\end{filecontents}

%% file3.tex

%\immediate\write18{lualatex \jobname-1.tex}
%\immediate\write18{lualatex \jobname-2.tex}

\begin{document}
\begin{tikzpicture}

\node[draw,
  rotate=30,
  restore nodes from file={[transform saved nodes,name prefix=pic-1-]{\jobname-1}}
] (a-1) at (-2,-3) {\includegraphics{\jobname-1.pdf}};

\node[draw,
  rotate=70,
  restore nodes from file={[transform saved nodes,name prefix=pic-2-]{\jobname-2}}
] (a-2) at (+2,+2) {\includegraphics{\jobname-2.pdf}};

\draw[red] (pic-1-1.north west) --  (pic-1-1.north east) --  (pic-1-1.south east) --  (pic-1-1.south west) -- cycle;
\draw[red] (pic-2-2.north west) --  (pic-2-2.north east) --  (pic-2-2.south east) --  (pic-2-2.south west) -- cycle;

\node[red] at (pic-1-1) {1};
\node[red] at (pic-2-2) {2};

\draw (a-1) circle[radius=5pt];
\draw (a-2) circle[radius=5pt];

\draw (pic-1-1) -- (pic-2-2);
\end{tikzpicture}
\end{document}

The interface is now via TikZ keys. The ones defined are:

  • save nodes to file on a scope, this says that any nodes marked to be saved in the scope should be saved to a file (called \jobname.nodes). This is a boolean. One of this or the next keys should be given (or both) to trigger the saving mechanism.
  • set node group=<group name> on a scope, if not saving to a file then nodes are saved as a "node group", this sets the name.
  • save node on a node, this marks that node as one to be saved (either to a file or a list).
  • restore nodes from file=<file name>, this loads in the nodes saved from the given file.
  • restore nodes from list=<group name>, this loads in the nodes saved from the given group.
  • transform saved nodes, this means that the restored nodes are transformed with the last node's transformation (usually, this should be used if the restore nodes from ... is used on a node).
  • name prefix=... this isn't a new key, but is a useful one. The restored nodes pick up the name prefix and name suffix from TikZ's node naming system, so putting this key is a useful way to automatically add a prefix (or suffix) to each restored node name. Note that if this is used with transform saved nodes then the order matters: this must come after transform saved nodes.

Result:

Loading node information

The red nodes are overlaid on top of the original nodes.

12
  • Actually I always wanted to write to you about this. See also tex.stackexchange.com/a/391381/2388. Feb 17, 2018 at 21:30
  • 1
    @tecepe That I'm using LaTeX3 needn't concern you unless you want to dig down into the code to see what's going on. I find it much easier to write code using LaTeX3 than ordinary TeX/LaTeX so I tend to use that these days. I'm working on the rotation part as I type ... Feb 17, 2018 at 22:13
  • 1
    @tecepe Now handles node transformations. Feb 18, 2018 at 16:50
  • 1
    Very impressive. I wouldn't have thought this could be (practically) done ....
    – cfr
    Feb 20, 2018 at 4:36
  • 1
    @Schrödinger'scat it is! I integrated it into tikzmark. I should update this answer to reflect that. Dec 13, 2019 at 6:49

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .