5

I am continuing the example I started here, and want to have two images in one picture being positioned relative to each other and using two scopes for the ´spies´. The following MWE includes a first way (without scopes) where I define the coordinate and spy node by own calculations. But i would like to use a scope like in the second example, in order to be independent of the image size i choose (I would have to change every .24\textwidth in the first picture). Adressing relatively to the image (being in [0,1]^2) would be quite preferable I think. Nevertheless, the second example does not work as expected, even more, it does not seem to follow a rule I could see.

In short I want a result as the first image using scopes as in the second example.

What am I doing wrong in the second, scope based, approach?

\documentclass{scrartcl}
\usepackage{amsmath, amsthm, amssymb}
\usepackage{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[english]{babel}
\usepackage{graphicx}
\usepackage{hyperref}
\usepackage{environ,ifthen,tikz,pgfplots}
\usetikzlibrary{shadings,spy,calc}
\begin{document}
    What i have\\
\begin{tikzpicture}[spy using outlines={circle,size=.1\textwidth, magnification=3, connect spies}]
    % image 1
     \node[anchor=south west,inner sep=0pt,label={270:{(a) Image 1}}] (image1) %
     at (-.375\textwidth,0) {% Dummy image 1
                \begin{tikzpicture}
                    \path [top color=blue, bottom color=black]
                        (0,0) rectangle (.24\textwidth,.24\textwidth);
                \end{tikzpicture}};
    \node (spy1) at     ($ (image1.south west) + (350/512*.24\textwidth,380/512*.24\textwidth) $) {};
                \coordinate (spy1to) at ($ (image1.center) + (-.03\textwidth,.23\textwidth) $);
                \spy [black,thick] on (spy1) in node at (spy1to);%
                % ---
                \node[anchor=south west,inner sep=0pt,%
                label={[align=left]270:{(b) Image 2.}}] %
                (image2) at %
                (-.125\textwidth,.125\textwidth) {%
                \begin{tikzpicture}
                    \path [top color=green, bottom color=black]
                        (0,0) rectangle (.24\textwidth,.24\textwidth);
                \end{tikzpicture}};
                \node (spy1a) at %
                ($ (image2.south west) + (350/512*.24\textwidth,380/512*.24\textwidth) $) {};
                \coordinate (spy1ato) at ($ (image2.center) + (-.18\textwidth,.065\textwidth) $);
                \spy [black,thick] on (spy1a) in node at (spy1ato);%
\end{tikzpicture}   

    What i would like to have but it does not work

\begin{tikzpicture}[spy using outlines={circle,size=.1\textwidth, magnification=3, connect spies}]
    % image 1
     \node[anchor=south west,inner sep=0pt,label={270:{(a) Image 1}}] (image1) %
     at (-.375\textwidth,0) {% Dummy image 1
                \begin{tikzpicture}
                    \path [top color=blue, bottom color=black]
                        (0,0) rectangle (.24\textwidth,.24\textwidth);
                \end{tikzpicture}};
                \begin{scope}[x={(image1.south west)}, y={(image1.north east)}] % [0,0] - [1,1] as scope of the image
                        \node (spy1n) at    (350/512,380/512) {};%relative pixel
                        \coordinate (spy1nto) at (-.5,1);
                        \spy [black,thick] on (spy1n) in node at (spy1nto);%
                \end{scope}
                % ---
                \node[anchor=south west,inner sep=0pt,%
                label={[align=left]270:{(b) Image 2.}}] %
                (image2) at %
                (-.125\textwidth,.125\textwidth) {%
                \begin{tikzpicture}
                    \path [top color=green, bottom color=black]
                        (0,0) rectangle (.24\textwidth,.24\textwidth);
                \end{tikzpicture}};
                \begin{scope}[x={(image2.south west)}, y={(image2.north east)}] % [0,0] - [1,1] as scope of the image
                        \node (spy2) at     (350/512,380/512) {};%relative pixel
                        \coordinate (spy2to) at (.5,1);
                        \spy [black,thick] on (spy2) in node at (spy2to);%
                \end{scope}
\end{tikzpicture}
\end{document}

Resulting Document Resulting IMage of the scopes

Edit: As @cfr pointed out: Of course it is not a good idea to nest tikzpictures, I only did that here to get images to \spy on, in general the image-nodes contain .pngs, which is also my purpose in relative adressing, i.e.(350/512,380/512) is of course a pixel in an 512x512image.

Ronny
  • 6,110
  • 1
    You should avoid nesting tikzpicture environments when possible as it can cause problems. (Not the problem here. Just in general.) It would also be much simpler in this case to just use nodes rather than nodes containing pictures containing paths. – cfr Nov 27 '14 at 17:31
  • You're right; in my real example i'm \includegraphicsing in the image-nodes of course in that node, which I wanted to avoid for the MWE. – Ronny Nov 27 '14 at 17:39
  • Makes sense and then you wouldn't need a separate tikzpicture either. – cfr Nov 27 '14 at 18:57
  • Yep. I only use the outer tikzpicture to place the subfigures. – Ronny Nov 27 '14 at 22:11
  • I don't understand how the relative coordinates are supposed to work. You want the magnified bit to appear outside the picture itself, right? But then the (-.5,1), say is relative to the 512x512 coordinate system because it is in the same scope as the part you are magnifying. (I'm not sure why it comes out to the right, rather than to the left of the picture, but it is centred in line with the top of the picture, which seems to be what you should expect?) – cfr Nov 27 '14 at 22:19
  • To be precise, the image.south west should reveal (0,0) for both scopes (w.r.t the corr. image) and ...north east the point (1,1). Then, (-.5,1) states, that the center of the spy magnifier should be at the right border 1/2 (of the image) above the top border. So it's not precisely the placement as in the first example; which it does not (and i really don't know why). Fiddled around with that quite a while. The blue one in the first example should roughly (.25, -.5) in relative coordinates i think, the green one (-.25,.75). – Ronny Nov 27 '14 at 22:30
  • But isn't the -.5 the x coordinate? The 1 is giving the y coordinate and that matches - the magnifier is centred on the top image border. – cfr Nov 27 '14 at 22:34
  • Oh sorry, it's late here, maybe i mixed them up ;) – Ronny Nov 27 '14 at 22:36
  • Do you know where this use of scopes to get relative coordinates is covered in the manual? Experimenting isn't making any sense... ;). I can only get points along a diagonal... – cfr Nov 27 '14 at 22:49
  • Well it works really fine, when you just use that scope to draw things in or around an image, which i found here once (but can't remember where) but I used it for example in this small snippet https://github.com/kellertuer/TikZ-Image-Colorbar (where relative placement works really fine) – Ronny Nov 27 '14 at 22:56
  • Found it http://tex.stackexchange.com/a/9561/8042 - the second code. – Ronny Nov 27 '14 at 23:01
  • Thanks. I read that earlier but I guess I just don't understand how the coordinates are supposed to work. (Using a simple example where I just use a filled rectangle for the image node. That is, taking all the spy and multiple image stuff out. I can still only get points on the diagonal.) – cfr Nov 27 '14 at 23:25

2 Answers2

3

I'm still not sure I understand this. However, I am fairly convinced that the code neither does nor is supposed to do what you think :(. This is not an answer but it is much too long for a comment...

When you write

\begin{scope}[x={(some point)}, y={(some other point)}]

you are setting, I think, the units of measurement. In the original example you linked to, there are a couple of important features of the picture:

  1. The image used to set these points has its south west anchor at the origin of the picture.
  2. (some point) is the south east anchor. This is aligned vertically with its south west anchor i.e. with the origin of the overall picture.
  3. (some other point) is the north west anchor. This is aligned horizontally with its south west anchor i.e. with the origin of the overall picture.

This means that if all coordinates are scaled by the x and y distances corresponding to {(image's south east anchor)} and {(image's north west anchor)} then you can write (a.b) which will be scaled to (xa,yb) and this will look as though the coordinate is placed within a coordinate system relative to the image. But what is really happening is that the x is being scaled by the vector(?) given by (some point) and the y by that given by (some other point).

\documentclass[border=10pt, mult, varwidth, tikz]{standalone}

\begin{document}

  \begin{tikzpicture}
    \node[anchor=south west,inner sep=0] (image) at (0,0) {\includegraphics{example-image-a}};
    \begin{scope}[x={(image.south east)},y={(image.north west)}]
      \foreach \i in {0,.1,...,1.1}
        \foreach \j in {0,.1,...,1.1}
          \path [fill=red] (\i,\j) circle (1pt);;
    \end{scope}
  \end{tikzpicture}

\end{document}

special case

But this is a special case. If the above conditions do not hold, then the effect will be different. (That is, it will be the effect of scaling things by the relevant vectors which will not look like a system of coordinates relative to the image.)

For example:

\documentclass[border=10pt, mult, varwidth, tikz]{standalone}

\begin{document}

  \begin{tikzpicture}
    \node[anchor=south west,inner sep=0] (image) at (-5,5) {\includegraphics{example-image-a}};
    \begin{scope}[x={(image.south east)},y={(image.north west)}]
      \foreach \i in {0,.1,...,1.1}
        \foreach \j in {0,.1,...,1.1}
          \path [fill=red] (\i,\j) circle (1pt);;
    \end{scope}
  \end{tikzpicture}

\end{document}

twisted (standard?) case

Or, changing (-5,5) to (5,5):

an equally twisted exemplar

So to use this trick, you need the south west anchor to be at the origin of the picture. Obviously, you cannot do this for two images placed at different places within a single picture. So you need another method...

cfr
  • 198,882
  • That's a neat explanation of how the previous thingys (with one image in (0,0) work, and i think i understand why my approach fails. However – do you see a solution for my problem? Is there a way to specify real local coordinates for a scope (what I would need) instead of just a scaling? – Ronny Nov 28 '14 at 05:56
  • @Ronny I see you found one? I was thinking of shift but didn't have time to try it out. The other possibility would be to really define a new coordinate system but I thought that would be a whole lot more trouble than it was likely to be worth. Glad you found a method (+1!). – cfr Nov 28 '14 at 12:33
  • shift was the only thing needed additionally to your explanations. – Ronny Nov 28 '14 at 12:38
2

The following solution is based on the hints @cfr gave in his (very good) explanation on what

\begin{scope}[x={(some point)}, y={(some other point)}]

does. I notived at that point, that prior to this question i was not aware on how x=and y= worked. But thanks to his explanations I saw another method so solve my problem, though it's not very different. For the following solution, the anchors of the imageX nodes can be ommitted because scope takes care of that by

  • scaling x= to be really the width of the image
  • scaling y= to be really the height of the image
  • shifting the scope, such that image.south west corresponds to (0,0) in the scope

This in the first scope, the point (-.5,1) adresses a point left to the image at the top border to place the spy in, for the second i chose (.5,1) which is the center top if the image. Both spy on nodes are still given in fractions in order to represent pixel values, to be precise, both adress the same relative point in the image. The following solution still uses a tikzpictureinside a tikzpicture for illustration - which you sould not use in the image nodes in a real code.

\documentclass{scrartcl}
\usepackage{amsmath, amsthm, amssymb}
\usepackage{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[english]{babel}
\usepackage{graphicx}
\usepackage{hyperref}
\usepackage{environ,ifthen,tikz,pgfplots}
\usetikzlibrary{shadings,spy,calc}
\begin{document}

\begin{tikzpicture}[spy using outlines={circle,size=.1\textwidth, magnification=3, connect spies}]
    % image 1
        \node[inner sep=0pt,label={270:{(a) Image 1}}] (image1) %
        at (-.375\textwidth,0) {% Dummy image 1
            \begin{tikzpicture}
                \path [top color=blue, bottom color=black]
                (0,0) rectangle (.24\textwidth,.24\textwidth);
            \end{tikzpicture}};
        \begin{scope}[x={($ (image1.south east) - (image1.south west) $ )},y={( $ (image1.north west) - (image1.south west)$ )}, shift={(image1.south west)}]
            \node (spy1n) at    (350/512,380/512) {};%relative pixel
            \coordinate (spy1nto) at (-.5,1);
            \spy [black,thick] on (spy1n) in node at (spy1nto);%
        \end{scope}
%
        \node[anchor=south west,inner sep=0pt,label={[align=left]270:{(b) Image 2.}}] %
            (image2) at (-.125\textwidth,.125\textwidth) {%
                \begin{tikzpicture}
                    \path [top color=green, bottom color=black]
                    (0,0) rectangle (.24\textwidth,.24\textwidth);
                \end{tikzpicture}};
        \begin{scope}[x={($ (image2.south east) - (image2.south west) $ )},y={( $ (image2.north west) - (image2.south west)$ )}, shift={(image2.south west)}]
            \node (spy2) at     (350/512,380/512) {};%relative pixel
            \coordinate (spy2to) at (.5,1);
            \spy [black,thick] on (spy2) in node at (spy2to);%
        \end{scope}
    \end{tikzpicture}
\end{document}

The resulting image is

enter image description here

exactely what i wanted, and now even including the avoidance of the anchor=south west, whose purpose i also only understood thanks to cfrs answer.

To conclude, the constructed scope of this answer enables relative adressing with respect to a nodes size (and its south west edge as origin). Nevertheless, the node and coordinate of the spy still have to be defined before the spy, because this results in computation of the coordinates inside the scope.

Ronny
  • 6,110