[Tex/LaTex] Scalebar Overlay and TikZ spy

spytikz-pgf

This question uses code snippets from How to add a scalebar to an image and Drawing on an image with TikZ.

I have an image with a scalebar (absolute positioning) overlay. Its length is determined by ratio=absolute image length/scalebar length which is used inside the image coordinate system (0,0) to (1,1).

I woul like to add a scalebar (of choosable length) on a spy view. But to issue the same rectangle scalebar i would need to know the width of the spy view relativ to the original image. I then could calculate the scalebar as ratio/(rel.view.width) * magnification. Also im having trouble simply putting the zoom view into a scope with relative coordinates as the zoom node seems only usable when using further \spycommands.

What i would like to achieve:
ScalebarSpy

\documentclass{scrartcl}
% image source: http://www.mrulrichslandofbiology.com/images/cheek_cells_3.jpg
\usepackage{tikz}
\usepackage{siunitx}
\usetikzlibrary{positioning,calc,spy}

\newcommand{\scalebarandzoom}[4][white]{
 \begin{tikzpicture}[font=\sffamily\small]

  % IMAGE
  \node[anchor=south west,inner sep=0] (image) at (0,0) { #2 };

  % IMAGE SCOPE
  \begin{scope}[x={(image.south east)},y={(image.north west)},spy using outlines={rectangle,size=1in}]
       % Dirty hack so that spy sees the image content as it is otherwise
     % out of the scope:
       \node[anchor=south west,inner sep=0] (image) at (0,0) { #2 };

     % GRID CODE
     %\draw[help lines,xstep=.1,ystep=.1] (0,0) grid (1,1);
     %\foreach \x in {0,1,...,9} { \node [anchor=north] at (\x/10,0) {0.\x}; }
     %\foreach \y in {0,1,...,9} { \node [anchor=east] at (0,\y/10) {0.\y}; }

     % SCALEBAR
     \fill [#1,xshift=-2mm] (1-#4/#3,2mm) rectangle ++(#4/#3,1.5mm);
     % SPY
     \spy [red,magnification=3] on (0.6,0.4) in node (zoom) [right] at (1.1,0.5);
  \end{scope}
\end{tikzpicture}
}

\begin{document}


\scalebarandzoom[orange]{\includegraphics[width=0.4\linewidth]{cheek.jpg}}{500}{50}


\end{document}

Best Answer

I used a different approach to get the desired result. Instead of spy library, I create two nodes: one for the image, other for the zoomed detail. I include the same image in both, but I clip the second one to the appropiate rectangle, and then use \scalebox to make it bigger. You can also draw lines connecting both nodes (original image and zoomed details).

Since the factor applied to \scalebox is known, it is easy to determine also the dimensions of the "zoomed" scalebar.

I passed as parameters also the corners of the rectangle to be zoomed. Note however that I defined x and y with the same value, so that the helping grid has square cells. This means that, the image coordinate system goes from 0 to 1 for x axis, but not for y axis (unless the image is square itself).

This is my code:

\documentclass{article}

\usepackage{graphicx}
\usepackage{tikz}
\usetikzlibrary{positioning}

\newcommand\scalebarandzoom[8][white]{ 
% #1 = color of bar
% #2 = image size
% #3 = image
% #4 = lower left corner of viewport
% #5 = upper right corner of viewport
% #6 = magnification factor
% #7 = actual size of the image in some units
% #8 = actual size of the scalebar in the same units than #7
\begin{tikzpicture}[x=#2, y=#2, font=\footnotesize]
  \node[anchor=south west,inner sep=0] (image) at (0,0) {\includegraphics[width=#2]{#3}};
  % \draw[help lines,xstep=.1,ystep=.1] (0,0) grid (1,1);
  % \foreach \x in {0,1,...,9} { \node [anchor=north] at (0.\x,0) {.\x}; }
  % \foreach \y in {0,1,...,9} { \node [anchor=east] at (0,0.\y) {.\y}; }
  \coordinate (viewport lower left) at (#4);
  \coordinate (viewport upper right) at (#5);
  \draw[red] (viewport lower left) rectangle (viewport upper right);
  \node[right=of image, draw=red, inner sep=1pt] (zoom) {%
       \scalebox{#6}{\tikz{
          \clip (#4) rectangle (#5);
          \node[anchor=south west,inner sep=0] at (0,0) {\includegraphics[width=#2]{#3}};
         }}%
       };
  % Help lines
  \draw[red, dashed] (viewport lower left|-viewport upper right) -- (zoom.north west);
  \draw[red, dashed] (viewport lower left) -- (zoom.south west);
  % Scalebars
  \fill [#1] (image.south east) ++(-2mm,2mm) ++(-#8/#7,    0mm) rectangle ++(#8/#7,   1.5mm);
  \fill [#1] (zoom.south east)  ++(-2mm,2mm) ++(-#8/#7*#6, 0mm) rectangle ++(#8/#7*#6,1.5mm);
\end{tikzpicture}
}

\begin{document}
\scalebarandzoom[orange]{6cm}{cheek.png}{0.52, 0.23}{0.68,0.35}{3}{500}{50}
\end{document}

And this is the result:

Result

(image cheek.png can be found here)