2

Following up on this answer, I've decided to just make this a new environment. Below is my MWE using packages xparse and tikz:

\documentclass[10pt,a4paper]{article}
\usepackage{xparse,tikz}

\NewDocumentEnvironment{overdraw}{ o o m +b } {
    { % begin "\begin{overdraw}"
        \begin{tikzpicture} 
        \node[anchor=south west, inner sep = 0] (image) at (0,0) {
            \includegraphics{#3}
        }; % add image at coordinate (0, 0)
        \IfNoValueTF{#2} {
            \IfNoValueTF{#1} {
                \begin{scope}[x={(image.south east)},y={(image.north west)}]
                % If Optional Arg #1 is empty
            } { \begin{scope}[x={(image.south east)/#1},y={(image.north west)}] }
                % #1 not empty
        } % If Optional Arg #2 is empty
            { \begin{scope}[x={(image.south east)/#1},y={(image.north west)/#2}] }
            % #2 not empty
    } % end "\begin{overdraw}"
    { % begin "\end{overdraw}"
        \end{scope} 
        \end{tikzpicture}
    } % end "\end{overdraw}"
}

\begin{document}
\begin{overdraw}{sample.jpg}
    \draw[red,ultra thick,rounded corners] (0.62,0.65) rectangle (0.78,0.75);
\end{overdraw}
\end{document}

Compiling this returns an error message that goes:

pdfTeX warning (ext4): destination with the same identifier (name{page.1}) has 
been already used, duplicate ignored
<to be read again> 
                   \relax 
l.16 \newpage
              [1]

! Package tikz Error: A node must have a (possibly empty) label text.

See the tikz package documentation for explanation.
Type  H <return>  for immediate help.
 ...                                              

l.20 \end
         {overdraw}
? 
! Emergency stop.
 ...                                              

l.20 \end
         {overdraw}
End of file on the terminal!

What does \newpage have to do with anything I wrote? Is there any way to fix this problem?

EDIT: The package repository in full can be found HERE at Github. Passers-by are welcome to leave comments and notes on tips for managing and developing a good package :D

Paul Kim
  • 1,078
  • I doesn't solve the problem, but \includegraphics{#3};} should be \includegraphics{#3}};. – Ignasi May 28 '19 at 07:40
  • @Ignasi it definitely should, what an embarrassing typo. And indeed, it wasn't a solution to the major problem here... – Paul Kim May 28 '19 at 08:01

1 Answers1

6

Overview

You have a brace matching problem, and the divisions on the x and y vectors were written in a way that isn't supported by TikZ. The following works for me. I have removed your +b argument specifier, since you don't use this argument at all.

\documentclass{article}
\usepackage{graphicx}
\usepackage{tikz}
\usetikzlibrary{calc}

\usepackage{xparse}

\NewDocumentEnvironment{overdraw}{ o o m }%
  {%
    \begin{tikzpicture}
      \node[anchor=south west, inner sep = 0] (image) at (0,0) {
        \includegraphics{#3}
      }; % add image at coordinate (0, 0)

      \IfNoValueTF{#2} {% optional argument #2 not provided
        \IfNoValueTF{#1} {% optional argument #1 not provided
          \begin{scope}[x={(image.south east)},y={(image.north west)}]
        }{% #1 provided
          \pgfmathparse{1/(#1)}
          \begin{scope}[x={($\pgfmathresult*(image.south east)$)},
                        y={(image.north west)}]
        }
      }{% #2 provided
        \pgfmathsetmacro{\myXfactor}{1/(#1)}
        \pgfmathsetmacro{\myYfactor}{1/(#2)}

        \begin{scope}[x={($\myXfactor*(image.south east)$)},
                      y={($\myYfactor*(image.north west)$)}]
      }
  }{
        \end{scope}
    \end{tikzpicture}%
  }% end "\end{overdraw}"

\begin{document}
\begin{overdraw}[1.5][0.8]{example-image}
  \draw[red,ultra thick,rounded corners] (0.62,0.65) rectangle (0.78,0.75);
\end{overdraw}
\end{document}

Screenshot

Code formatting and extraneous spaces

I reformatted the code to make it a bit easier to read (IMHO). Beware of introducing extraneous spaces, since you are not using \ExplSyntaxOn here (note the place of the % characters at environment start, before \begin{tikzpicture}, and at environment end, after \end{tikzpicture}). To see my point, try the above code with:

\begin{document}
a\begin{overdraw}{example-image}
  \draw[red,ultra thick,rounded corners] (0.62,0.65) rectangle (0.78,0.75);
\end{overdraw}b
\end{document}

You'll get this:

ab OK

See the a and b lying on the image baseline? Now, remove the two percent characters I mentioned (before \begin{tikzpicture} and after \end{tikzpicture}) and you'll obtain this:

ab BAD

The whole takes two lines because one \linewidth isn't large enough to hold the indentation box, the a, the b, two interword spaces and the image (given the default value of \parindent).

Dividing a vector by a scalar in TikZ

I added \pgfmathparse computations and the calc TikZ library in order to do the divisions on the x and y vectors that you apparently desired.

On the “non-empty” vs. “provided“ argument check

Please note that:

  • xparse's \IfNoValueTF test does not test if the optional argument is empty, it tests whether it has been provided. One can provide an empty argument, it is still provided. If the criterion you want to decide against is emptiness, I suggest using O{} in the argument specification of \NewDocumentEnvironment and then checking with, for instance, etoolbox's \ifblank command (i.e., 1) you declare the argument as an optional one whose default value is empty, and 2) you check whether it is empty).

  • Using \IfValueTF instead of \IfNoValueTF is likely to make the logic easier to follow, especially when there are imbricated tests like here.

frougon
  • 24,283
  • 1
  • 32
  • 55
  • Not sure why, but there was no overprint until I deleted +m in the argument specification. – sgmoye May 28 '19 at 12:24
  • I expanded the answer, please reread. What do you mean by an overprint?.. – frougon May 28 '19 at 12:26
  • Ah, right, +m is a mandatory argument and we don't provide it! Either provide one or remove the arg specifier. – frougon May 28 '19 at 12:31
  • Just TeXed your altered file. No change. With the { o o m +m} argument specification, there is no red rectangle overprint. Removing the +m fixes the problem. I'm using MacTeX 2019, recently updated. – sgmoye May 28 '19 at 12:32
  • Look in the last edit: I provided an empty arg when the environment is used. Otherwise, remove the +m since you don't use it. I let it in place because I thought it is part of your future plans for the environment. PS.: the rectangle is drawn with current code. – frougon May 28 '19 at 12:33
  • Yes, but surely, having coded \draw[red,ultra thick,rounded corners] (0.62,0.65) rectangle node {X} (0.78,0.75);, you intended the rectangle to appear. As such, that rectangle is said to overprint the graphic. And it was not my environment. – sgmoye May 28 '19 at 12:39
  • That was probably the argument in excess (see my last edit: I have removed the arg since you don't use it at all). It is now overprinted for me. The only thing that doesn't work, AFAIK, is how you divide the coordinates. I have to dig the tikz calc syntax for that, unless someone here knows better. :) – frougon May 28 '19 at 12:42
  • I have expanded my explanations and fixed your code in order to perform the divisions of the x and y vectors by scalars that you apparently desired (the scalars in question being the optional arguments of the overdraw environment). The way you wrote these divisions isn't supported by TikZ, AFAICT. I've also added several screenshots. – frougon May 28 '19 at 13:57
  • @sgmoye Sorry, there was a little misunderstanding, my fault. 1) Since you've been the only person to comment on my answer, I thought you were the OP, therefore I have used the word “you” or “your“ many times when referring to the OP's question or code. :-/ 2) For me, the subject of the question was really the compilation error, as can be seen in the first rev of my answer. I only addressed the other problems later. 3) I didn't code the \draw[red,ultra ...: this was quite at the bottom of the OP's code, I pasted it and overlooked it... – frougon May 28 '19 at 18:23
  • @sgmoye ... at first (only concerned with the compilation error). That was until you started to mention the overprinting thing. 4) “Draw a rectangle on the image” would have been clearer to me, but I eventually understood what overprinting meant in this context. :-) 5) The absence of the rectangle you noticed was due to the excess +b/+m argument grabbed by the environment. Adding +m with no corresponding argument in the call only grabs the \draw token and leaves [red,ultra thick,rounded corners] (0.62,0.65) rectangle (0.78,0.75); in the input stream, which TikZ then royally ignores; – frougon May 28 '19 at 18:25
  • @sgmoye ... you can verify this by either suppressing the \draw token manually or pasting all the [red,ultra thick, ... ,0.75); before }{ \end{scope} inside the environment! 6) AFAIK, I have fixed all issues. – frougon May 28 '19 at 18:27
  • @KPaul If you accept my answer and are interested in having empty optional arguments treated as if they had not been provided at all, I can implement the \ifblank test mentioned in my answer. – frougon May 28 '19 at 18:28
  • I gathered as much, so absolutely no apology necessary. I was also confused by what the purpose of the original code was -- made me hesitant to answer at all. Easy to make the code work (in any number of ways!), but to what end? Thanks for the clarification. – sgmoye May 28 '19 at 18:31
  • @sgmoye I'm not sure either about what the division will be useful for, practically. But probably the OP has an idea. :) – frougon May 28 '19 at 18:34
  • @frougon Thank you for the answer, and sorry for the delayed reply. The division is one of many trial-and-errors I'm implementing to impose a height-to-width ratio, the goal being the top-rightmost corner of an image being (x, y) with x:y being the ratio of the picture, rather than the somewhat-confusing (1,1). And I never knew the percentages behind each line had other meanings than commenting! The ifblank test is also a very good suggestion - I'll make sure to add that to my list of to-dos :D – Paul Kim May 29 '19 at 00:49
  • @K.Paul Thanks for explaining the idea behind the divisions. You may want to look here regarding the percent signs. If you have difficulty with \ifblank, dont hesitate to ask. – frougon May 29 '19 at 06:44
  • I've simplified the code doing the divisions a tiny bit thanks to \pgfmathsetmacro. – frougon Jun 02 '19 at 17:18
  • +1: very helpful answer – Dr. Manuel Kuehner Jun 02 '19 at 17:24