15

I wonder if it is possible to draw parts of the images only in the maginfied node printed with \spy?

\documentclass[
   border=2cm,
]{standalone}

\usepackage{tikz}
\usetikzlibrary{calc,fit,spy}

\tikzstyle{caption}=[%
   green!70!black,
   <->,
   every node/.style={%
      inner sep=3pt,fill=white,midway,sloped
   }
]
\tikzstyle{hide}=[opacity=0]

\begin{document}
\begin{tikzpicture}[%
   spy using outlines={circle, magnification=4, size=1.5cm, connect spies},
   every spy in node/.style={hide/.style={opacity=1}};
]
   \fill [gray] (0,0) rectangle (2,3);
   \fill [hide,green] (0,0) circle (1pt);
%   \tikzset{execute at begin scope={\tikzset{hide/.style={opacity=1}}}}
   \spy on (0,0) in node at (-2,1);
\end{tikzpicture}
\end{document}

The green circle should only appear in the magnified part.

example 1

I tried to use the style hide to hide an object in the main image and redefine hide in the magnified part to become visible. But neither my every spy in node way nor the execute at begin scope way give any result.


Frédéric’s solution works fine for the simple case where the object to draw lies in the center of the spy node but it doesn’t care about the magnification (i.e. I must calculate the scale factor for the radius manually) and it doesn’t work with more complex images.

It would be great if I can access the (magnified/scaled) coordinates of the original image in the magnification. Here’s a second example showing why Frédéric’s solution won’t work …

\documentclass[
   border=2cm,
]{standalone}

\usepackage{tikz}
\usetikzlibrary{calc,fit,spy}

\tikzstyle{caption}=[%
   green!70!black,
   <->,
   every node/.style={%
      inner sep=3pt,fill=white,midway,sloped
   }
]
\tikzstyle{hide}=[opacity=0.2]% set to 0.2 to make it visible while testing

\begin{document}
\begin{tikzpicture}[%
   spy using outlines={circle, magnification=4, size=1.5cm, connect spies},
   every spy in node/.style={hide/.style={opacity=1}};
]
   \fill [gray] (0,0) coordinate (A) rectangle (2,3);
   \fill [hide,green] ($(A) + (0.02,0.05)$) circle (1pt);
%   \tikzset{execute at begin scope={\tikzset{hide/.style={opacity=1}}}}
   \spy on (0,0) in node at (-2,1);
\end{tikzpicture}
\end{document}

example 2

3 Answers 3

13

This draws something inside a spy but not by hiding and then showing parts. The spy is given a name (actually, the node part of the spy is named), then you can draw by referencing the node or its anchors.

I had to change the format of your spy code, in particular place it within a scope and place the spy specifications with the scope, otherwise I could not get the node referencing to work. If someone could help on this point, I would appreciate.

The code is

\documentclass[border=2cm,]{standalone}

\usepackage{tikz}
\usetikzlibrary{calc,spy}
\begin{document}

\begin{tikzpicture}

\begin{scope}[spy using outlines={circle, magnification=4, size=1.5cm, connect spies}]

\fill [gray] (0,0) rectangle (2,3);
%\fill [hide,green] (0,0) circle (2pt);

\spy[blue] on (0,0) in node (a)  at (-2,1);
\end{scope}   

\fill[green,scale=4] (a.center) circle[radius=2pt];

\end{tikzpicture}

\end{document}

and the result is

enter image description here

1
  • This solution works fine with my example, since the green circle lies on (0,0) = (a.center)but I need to access the coordinates of the original image in the magnification
    – Tobi
    Mar 24, 2012 at 17:09
7

I'm mostly expanding on Frederic's answer, but it was too long for a comment. I didn't know how to do this will \fill, so I switched to use nodes, which lets us use xshift=x and yshift=y for positioning relative to some coordinate. Here's the code:

\documentclass[border=2cm,]{standalone}

\usepackage{tikz}
\usetikzlibrary{calc,spy,shapes}
\begin{document}

\begin{tikzpicture}

\begin{scope}[spy using outlines={circle, magnification=4, size=3cm, connect spies}]

\fill [gray] (0,0) rectangle (2,3);

% here's the circle drawn on the original so you can verify it overlaps
% the one drawn in the spy -- just uncomment to see
%\node[circle,fill=green,inner sep=0,minimum size=2pt] (circle) at (0,1.7) {};

\spy[blue] on (.25,1.5) in node (spy)  at (-2,1);
\end{scope}   

% they spy looks at (0.25,1.5) or (x1,y1) 
% we want to draw on the original at (0,1.7) or (x2,y2)
% thus, we shift our circle by (x2-x1,y2-y1) or (-0.25,0.2)

\node[circle,fill=green,inner sep=0,minimum size=2pt,
      scale=4,xshift=-0.25cm,yshift=0.2cm] (circle) at (spy.center) {};

\end{tikzpicture}

\end{document}

So, your spy is looking at the original, centered at some (x1,y1). You want to draw on the original at some (x2,y2). Thus, you just offset the location of your circle in the spy by (x2-x1, y2-y1) relative to (spy.center) to shift it where you want it. It's a minor calculation, though if you did this a lot of times you could define some variable to calculate it for you. Hope this helps build on the above.

image

5

Based on Hendy’s idea with shiftig I created my own solution without manual calcualtions. It’s just shifting the magnification to the spy in node, do the scaling and clip it.

\documentclass[
   border=2cm,
   draft
]{standalone}

\usepackage{tikz}
\usetikzlibrary{calc,fit,spy}

% Store magnification and lens size in macros
\newcommand\magn{6}
\newcommand\msize{1.5cm}
% Define a style for the canvas transformation
\tikzstyle{only in spy node}=[%
   transform canvas={%
      shift={(tikzspyinnode)},
      scale=\magn,
   }
]

\begin{document}
\begin{tikzpicture}
   % draw the original
   \begin{scope}[%
      spy using outlines={circle, magnification=\magn, size=\msize, connect spies},
      every spy in node/.style={hide/.style={opacity=1}};
   ]
      \fill [gray] (0,0) coordinate (A) rectangle (2,3);
      \spy on (0,0) in node at (-2,1);
   \end{scope}
   % draw something in the magnification only
   \begin{scope}[only in spy node]
      % clip this scope to keep it inside the magnifier
      \clip (0,0) circle ({(\msize/2-0.4pt)/\magn});
      \fill [green] ($(A)+(0.05,0.01)$) circle (1pt);
      \fill [red] ($(A)+(0.1,0.01)$) circle (2pt);
   \end{scope}
\end{tikzpicture}
\end{document}

result

1
  • 1
    If the on-node is not (0,0) the coordinates after the shift in only in spy node will be off. This can fixed by first shifting by the scaled negative on-node, i.e., shift={($-\magn*(tikzspyonnode)+(tikzspyinnode)$)}
    – Xiao Hu
    Jan 21, 2021 at 10:45

You must log in to answer this question.

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