1

I am trying to create an environment in which I can place several georeferenced images into a PGFPlots axis.

I have working code that reads in the specified image, reads in the world file (a text file that specifies the bounding box of the image in real-world coordinates) and then saves everything in a pgfplotstable. All of this works as expected.

The problem occurs when I try to draw the images. The \foreach loop I use reads the table row-by-row, assigning the graphics limits defined in the table, and then it is supposed to include the graphics file listed in the first column of the table. What happens is that the last image in the table is being used for each step in the loop and earlier images are not drawn.

What I am trying to get is something like this: enter image description here

What I end up with is this: enter image description here

The three images are positioned correctly - its that the wrong image file is used for all of the steps prior to the last one. I've tried used \let\imageName\pgfplotsretval in the \ExtractRow macro but get an undefined control sequence error when compiling. The only way I can get it to compile is with \xdef\imageName\pgfplotsretval.

MWE below:

\documentclass{standalone}
\usepackage{pgfplots,pgfplotstable}

\def\ExtractRow#1#2{
 \pgfplotstablegetelem{#2}{1}\of#1
 \let\xmin\pgfplotsretval

 \pgfplotstablegetelem{#2}{2}\of#1
 \let\xmax\pgfplotsretval

 \pgfplotstablegetelem{#2}{3}\of#1
 \let\ymin\pgfplotsretval

 \pgfplotstablegetelem{#2}{4}\of#1
 \let\ymax\pgfplotsretval

 \pgfplotstablegetelem{#2}{0}\of#1
 \xdef\imageName{\pgfplotsretval}
}

\begin{document}
\pgfplotstableread[col sep=comma,header=false]{
image1,357294.259463,359521.072742,4574707.814338,4576076.199597
image2,357298.194481,357792.613845,4575702.121062,4576047.871412
image3,357772.545188,358761.387418,4575306.493347,4575997.994047
}\GeoTable

\pgfplotstablegetrowsof{\GeoTable}
\pgfmathsetmacro{\RowCount}{\pgfplotsretval-1}

\begin{tikzpicture}
\begin{axis}
\foreach \i in {0,...,\RowCount}{
    \ExtractRow\GeoTable{\i}
    \addplot graphics[xmin=\xmin,ymin=\ymin,xmax=\xmax,ymax=\ymax]{\imageName};
}   
\end{axis}
\end{tikzpicture}
\end{document}

image1: image1.png

image2: image2.png

image3: image3.png

1

There might be some expanding issue regarding \foreach and \addplot. In my humble opinion, \addplot will read the file name without expanding it. So the three images being included are not image1, image2, and image3, instead, they are \imageName, \imageName, and \imageName. When PGFPLOTS tries to include the images, the three \imageName tokens will all expanded to the latest value: image3, which leads to the result.

To get over this kind of issue, PGF-family usually define a \pgf@marshal so that one can use a single \expandafter to jump over it. In this case, you may do the following:

\begin{axis}
    \foreach \i in {0,...,\RowCount}{
        \ExtractRow\GeoTable{\i}
        \def\pgfplotsmarshal{\addplot graphics[xmin=\xmin,ymin=\ymin,xmax=\xmax,ymax=\ymax]}
        \expandafter\pgfplotsmarshal\expandafter{\imageName.png};
    }
\end{axis}
  • pgfplots has \pgfplotsinvokeforeach for this purpose. – percusse Jan 22 '16 at 8:02
  • @percusse Sounds interesting. Throughout all packages there is only one occurrence of this macro: where it is defined. Anyway, what does invoke mean in this case? – Symbol 1 Jan 22 '16 at 14:50
  • Pgfplots gathers all the plots to decide the axis size and ticks and lots of other stuff. Hence they are not expanded right away and stored as you mention. Invoke means that whatever the loop variable is it will be replaced with its original meaning and then stored. It should be in the pgfplotsutils file somewhere. – percusse Jan 22 '16 at 14:55
  • @percusse I had tried using a \pgfplotsinvokeforeach for this look previously and could not get it to work. – andy Jan 22 '16 at 15:00
  • Changing the loop to \pgfplotsinvokeforeach {0,...,\RowCount}{ \ExtractRow\GeoTable{#1} \addplot graphics[xmin=\xmin,ymin=\ymin,xmax=\xmax,ymax=\ymax]{\imageName}; } compiles but gives me the same result of the last image drawn three times.I think I understand that \pgfplotsinvokeforeach is replacing the index at each step and not the macros defined in \ExtractRow. Any idea how I can get this to work since I need to replace five values:\xmin,\xmax, etc. and not just \imageName in each loop step? – andy Jan 22 '16 at 15:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.