# Spy with scale and pgfonlayer in tikz

When I use spy and scale in a tikzpicture, the magnifying glass seems to be magnifying a region not where I specified. The small pointer is in the correct location, though. If I set scale=1.0, the magnification seems to be of the correct location.

Also, if I am using pgfonlayer to create a drawing in the background, how do I get that to be magnified in spy?

Here is a minimal working example:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{spy, backgrounds}
\begin{document}

\begin{figure}

\begin{tikzpicture} [spy using outlines={circle, magnification=4, size=1cm, connect spies},
scale = 1.4,transform shape]
\draw[help lines] (0,0) grid (4,4);
\draw (0,0) -- (3,3) -- (3,0);
\begin{pgfonlayer}{background}
\draw[red] (2.9,0) -- (2.9,4);
\end{pgfonlayer}
\spy [black] on (3,3) in node [left] at (5,5);
\end{tikzpicture}

\end{figure}
\end{document}


Note that I was expecting, in the magnifying glass, a corner of the triangle as well as a part of the vertical red line (in the background layer).

-
Please add a minimal working example (MWE) that illustrates your problem. It would allow others to investigate the problem much more readily. –  Werner Oct 2 '11 at 18:58

I have two suggestion to accompany your question:

• Instead of scaling your spy, I played around with the magnification and size options;
• You can also print something in the background by typesetting it ahead of whatever follows.

This minimal example highlights the above suggestions:

\documentclass{article}
\usepackage{tikz}% http://ctan.org/pkg/pgf
\usetikzlibrary{spy, backgrounds}
\begin{document}

\begin{tikzpicture} [spy using outlines={circle, magnification=8, size=2cm, connect spies, transform shape}]
\draw[red] (2.9,0) -- (2.9,4);
\draw[help lines] (0,0) grid (4,4);
\draw (0,0) -- (3,3) -- (3,0);
%\begin{pgfonlayer}{background}
%  \draw[red] (2.9,0) -- (2.9,4);
%\end{pgfonlayer}
\spy [black] on (3,3) in node [left] at (6,5.5);
\end{tikzpicture}
\end{document}


-

I've just found myself wanting to use layers with the spy library and so found myself in the situation that you describe where only what is on the main layer appears in the spy in node. Reordering the layers is not an option for me, so I took a look at the spy library to see if I could figure out what's going on.

In brief, layers work by saving each layer in a box and then at the end stacking the boxes in the required order. The spy library actually works quite similarly: it saves the drawing in a box so that it can copy it (with clipping) into the node. These don't work together as when stuff is saved onto its layer box, it doesn't get saved into the spy box. The solution I thought of was to ensure that the spy library uses all the layers. Now, this gets a bit complicated with scopes so in the below then I worked with it only for the whole picture.

This probably isn't a final solution, but it's a working one. As I use it I'll probably end up tweaking it a bit. Save the following as tikzlibraryspyall.code.tex and use with \usetikzlibrary{spyall}.

% Spy all styles

\tikzset{
spy all using outlines/.style={
spy picture={
every spy all on node/.style={very thin,draw},
every spy all in node/.style={thick,draw},
#1
}
},
spy all using overlays/.style={
spy picture={
every spy all on node/.style={fill,fill opacity=0.2,text opacity=1},
every spy all in node/.style={fill,fill opacity=0.2,text opacity=1},
#1
}
},
connect spies/.style={
spy connection path={\draw[thin] (tikzspyonnode) -- (tikzspyinnode);}
}
}

%\newbox\tikz@lib@spybox

\let\tikz@lib@spyall@collection=\pgfutil@empty%

\tikzset{spy picture/.style={
size/.style={minimum size=##1},
height/.style={minimum height=##1},
width/.style={minimum width=##1},
execute at begin picture={%
\let\tikz@lib@spyall@save=\tikz@lib@spyall@collection%
\let\spyall=\tikz@lib@spyall@parse%
\tikz@insert@spy@layer
\pgfonlayer{spy}%
},
execute at end picture={%
\endpgfonlayer
{%
\tikz@lib@spyall@collection%
}%
\global\let\tikz@lib@spyall@collection=\tikz@lib@spyall@save%
},%
tikz@lib@spyall@style/.style={#1},
tikz@lib@reset@gs
},
lens/.store in=\tikz@lib@spy@lens,
lens=,
magnification/.style={lens={scale=#1}},
spy connection path/.store in=\tikz@lib@spy@path,
spy connection path=
}

\tikzset{
tikz@lib@reset@gs/.style={black,thin,solid,opaque,line cap=butt,line join=miter}
}

\def\tikz@lib@spyall@parse{%
\pgfutil@ifnextchar[{\tikz@lib@spyall@parse@opt}{\tikz@lib@spyall@parse@opt[]}%]
}
\def\tikz@lib@spyall@parse@opt[#1]{
\pgfutil@ifnextchar x{\tikz@lib@spyall@parse@opta[#1]}{\tikz@lib@spyall@parse@opta[#1]}%]
}
\def\tikz@lib@spyall@parse@opta[#1]on#2in node#3;{%
}

\def\tikz@lib@spyall@do#1#2#3{%
\scope[tikz@lib@spyall@style,#1]
\node [alias=tikzspyonnode,inner sep=0pt,outer sep=0pt,every spy all on node/.try,
/utils/exec={
{%
\let\tikz@transform=\relax
\pgftransformreset%
\expandafter\tikzset\expandafter{\tikz@lib@spy@lens}
\pgftransforminvert%
\pgfgettransformentries\a\b\c\d\e\f%
\global\let\pgf@lib@svg@a=\a%
\global\let\pgf@lib@svg@b=\b%
\global\let\pgf@lib@svg@c=\c%
\global\let\pgf@lib@svg@d=\d%
}%
\tikz@scan@one@point\pgftransformshift#2%
\pgftransformcm{\pgf@lib@svg@a}{\pgf@lib@svg@b}{\pgf@lib@svg@c}{\pgf@lib@svg@d}{\pgfpointorigin}%
}
}]{};
\node [alias=tikzspyinnode,inner sep=0pt,outer sep=0pt,at={#2},every spy all in node/.try,
path picture={\node[anchor=center,tikz@lib@reset@gs]{\nullfont%
\pgfpicture\relax\pgfsetbaseline{default}\pgfsettrimleft{default}\pgfsettrimright{default}%
\pgftransformreset%
\let\tikz@transform=\relax%
\expandafter\tikzset\expandafter{\tikz@lib@spy@lens}%
\pgflowlevelsynccm%
\tikz@scan@one@point\tikz@lib@spyall@shift#2%
\pgflowlevelsynccm%
\pgf@dosavedlayers
\endpgfpicture};}]#3{};
\tikz@lib@spy@path
\endscope
}

\def\tikz@lib@spyall@shift#1{%
\pgf@process{#1}%
\pgf@x=-\pgf@x%
\pgf@y=-\pgf@y%
\pgftransformshift{}%
}

\pgfdeclarelayer{spy}

\def\tikz@insert@spy@layer{%
\expandafter\tikz@insert@spy@@layer\pgf@layerlist\relax
}
\def\tikz@insert@spy@@layer#1main#2\relax{%
\def\pgf@layerlist{#1spy#2,main}%
}

\def\pgf@dosavedlayers{%
\expandafter\pgf@dosavedlayer\pgf@layerlist,,\relax%
}
\def\pgf@dosavedlayer#1,#2,\relax{%
\def\pgf@test{#1}%
\ifx\pgf@test\pgf@maintext%
\copy\pgf@layerbox@main
\else%
\expandafter\copy\csname pgf@layerboxsaved@#1\endcsname
\fi%
\def\pgf@test{#2}%
\ifx\pgf@test\pgfutil@empty%
\else%
\pgf@dosavedlayer#2,\relax%
\fi%
}
\newbox\pgf@layerboxsaved@main
\def\pgf@dosavelayer#1,#2,\relax{%
\def\pgf@test{#1}%
\ifx\pgf@test\pgf@maintext%
\setbox\pgf@layerboxsaved@main=\box\pgf@layerbox@main
\else%
\setbox\csname pgf@layerboxsaved@#1\endcsname=\box\csname pgf@layerbox@#1\endcsname%
\fi%
\def\pgf@test{#2}%
\ifx\pgf@test\pgfutil@empty%
\else%
\pgf@dosavelayer#2,\relax%
\fi%
}

\endinput


Here's a test document. The real document was much more complicated.

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{spyall}

\pgfdeclarelayer{back}
\pgfdeclarelayer{front}
\pgfsetlayers{back,main,front}

\begin{document}

\begin{tikzpicture}[spy all using outlines={circle,magnification=4,size=2cm, connect spies}]
\begin{pgfonlayer}{front}
\draw[ultra thick,black] (.5,0) -- (.5,1);
\end{pgfonlayer}
\draw[ultra thick,blue] (0,0) -- (1,1);
\begin{pgfonlayer}{back}
\draw[ultra thick,green] (1,0) -- (0,1);
\end{pgfonlayer}
\spyall [red] on (.5,.5) in node at (.5,3);
\draw[ultra thick,cyan] (0,.5) -- (1,.5);
\end{tikzpicture}

\end{document}


-