8

I have a full-page figure that needs to be rotated to fit on the page. I started out with this figure in an appendix at the end of my document, and just wrapped the figure in \begin{landscape}...\end{landscape} (from the pdflscape package; I'm using pdflatex) and I was pretty happy with the results. However, I've decided the figure needs to be in the middle of the document, and I'm having trouble reproducing the results there.

The best I've come up with so far is to use the sidewaysfigure environment from the rotating package:

\documentclass{article}
\usepackage{blindtext}

\usepackage{pdflscape}
\usepackage{rotating}

\begin{document}
\blindtext[3]

\begin{sidewaysfigure}
\caption{This figure and its caption are sideways.  Ideally I would also like the pdf page containing it to be rotated so that the figure is upright for on-screen viewing.}
\end{sidewaysfigure}

\blindtext[3]

\begin{figure}
\caption{this figure should be numbered after the other one, come after it in the document, and be oriented normally.}
\end{figure}

\blindtext[2]
\end{document}

This works pretty well, except that I really liked the feature of pdflscape where the PDF page is rotated so that the figure contents and caption are oriented optimally for on-screen viewing, which seems to be missing when using the rotating package.

Things I've tried:

  • using the landscape environment anyway. This gives an immediate page break at the point in the source where the figure occurs.
  • using the landscape environment in an \afterpage{}. This sorta works, except that it's actually moving the figure around, the numbering gets switched with the subsequent figure, which is undesirable.
  • I didn't actually try it, but this solution involving fancyhdr won't work because there are going to be other figure pages (in fact, it's currently looking like this landscape figure is going to be immediately followed by a figure page)
  • I was even desperate and tried using the internal commands (\PLS@AddRotate{90}) that pdflscape uses, but they apply immediately, so the wrong page gets wrotated.

The output from sidewaysfigure is good enough to be getting on with (I think I'm falling into this trap!), but if there are any ways to fix this, I'd very much appreciate it!

This question ends up being very similar to this other one by another user which never received an answer due to not having enough details.

  • +1 for wrotating the wrong page. if it's feasible, placing the figure at a chapter break might give you a little more freedom. – barbara beeton Apr 29 '16 at 20:52
  • 1
  • @UlrikeFischer Interesting... I like where you're starting, though I think I'm going to improve upon it a little. – arcticmac Apr 29 '16 at 23:55
9
+50

This combines sidwaysfigure and pdflscape into one environment. It uses the aux file to locate where the figure actually winds up.

\documentclass{article}
\usepackage{blindtext}% MWE only
\usepackage{graphicx}% for \rotatebox
\usepackage{everypage}
\usepackage{environ}
\usepackage{pdflscape}% not required

\newcounter{abspage}% \thepage not reliab

\makeatletter
\newcommand{\newSFPage}[1]% #1 = \theabspage
  {\global\expandafter\let\csname SFPage@#1\endcsname\null}

\NewEnviron{SidewaysFigure}{\begin{figure}[p]
\protected@write\@auxout{\let\theabspage=\relax}% delays expansion until shipout
  {\string\newSFPage{\theabspage}}%
\ifdim\textwidth=\textheight
  \rotatebox{90}{\parbox[c][\textwidth][c]{\linewidth}{\BODY}}%
\else
  \rotatebox{90}{\parbox[c][\textwidth][c]{\textheight}{\BODY}}%
\fi
\end{figure}}

\AddEverypageHook{% check if sideways figure on this page
  \ifdim\textwidth=\textheight
    \stepcounter{abspage}% already in landscape
  \else
    \@ifundefined{SFPage@\theabspage}{}{\global\pdfpageattr{/Rotate 0}}%
    \stepcounter{abspage}%
    \@ifundefined{SFPage@\theabspage}{}{\global\pdfpageattr{/Rotate 90}}%
  \fi}
\makeatother

\begin{document}
\blindtext[3]

\begin{SidewaysFigure}
\caption{This figure and its caption are sideways.  
Ideally I would also like the pdf page containing it to be rotated so that the figure is upright for on-screen viewing.}
\end{SidewaysFigure}

%\begin{landscape}

\blindtext[3]

\begin{figure}
\caption{this figure should be numbered after the other one, come after it in the document, and be oriented normally.}
\end{figure}

\blindtext[4]
%\end{landscape}
\end{document}
  • So basically the difference is that you're implementing something like the sidewaysfigure environment yourself? Or is there some other difference between that and what you're doing? – arcticmac May 3 '16 at 19:14
  • 1
    I never use packages if I can do it myself. I even developed a solution which did not use zref, but decided no one else would be interested. – John Kormylo May 3 '16 at 20:52
  • Fair enough! Though it might be worth editing your answer to make that more clear. My first read through, it sounded like you thought it performed better ("This doesn't force a page break") for some reason and I had to look closely to see that that shouldn't be the case. And actually, I'd potentially be interested in seeing your solution without zref, at least from an academic point of view. – arcticmac May 4 '16 at 16:39
  • 1
    Since I appear to have reinvented sidewaysfigure, I redid my solution as an environment. – John Kormylo May 5 '16 at 16:57
  • This looks interesting, however, when I compile it, it does not turn the caption... – Mil Sep 7 '16 at 16:22
1

Based on this answer to another question (suggested by @UlrikeFischer), I hit upon the atbegshi package, which lets you run things when a page is being typeset (in this case, adding the /Rotate 90 command to the PDF page).

I originally tried to make do like this (simplified some things that seemed unnecessary from the original answer, as well as changing it to rotate the page instead of double page width):

\AtBeginShipout{\ifnum\thepage=0\pageref{landscapefigure}
  \pdfpageattr{/Rotate 90}
\fi}

However, that seems to break when including the hyperref package, which I definitely want to use in my real document. So then I went back, and incorporated the \zref stuff from the original answer and wrapped it all up in a nice macro:

\makeatletter
\newcommand{\rotateFigurePageForLabel}[1]{%
  \zlabel{#1}%
  \AtBeginShipout{%
  \ifnum\c@page=\zref@extractdefault{#1}{abspage}{0}
    \pdfpageattr{/Rotate 90}
  \fi}
}
\makeatother

Usage is now something like:

\begin{sidewaysfigure}
  \caption{This figure and its caption are sideways.  So is the page in the PDF.}
  \label{fig:landscapefigure}
  \rotateFigurePageForLabel{fig:landscapefigure}
\end{sidewaysfigure}

(of course, this may be a bit sneaky because it's creating a new \zlabel with the label text you give it, but I was originally hoping to have it just use the regular label. I couldn't figure out a good way to get that to play nice with hyperref though.)

  • Well I know why I didn't use pageref: It can't be used reliable as a number in tests. Eg it could be a roman number. – Ulrike Fischer Apr 30 '16 at 7:20
  • 1
    @UlrikeFischer yeah, I have no doubt you know much better than I do what you're doing. And you're absolutely right that \pageref wouldn't really be a good idea. I was just sad to need to use yet another package and a command as long and hard to remember as \zref@extractdefault{#1}{abspage}{0} vs \pageref which is nice and short and easy to remember. (I was also trying to avoid just copying and pasting everything until I understood why it was needed; I'm still not very good at advanced TeX stuff.) – arcticmac May 3 '16 at 19:10
  • @arcticmac I'm trying to accomplish in what you have succeded, but your answer isn't clear enough. Could you please elaborate your answer to full working example? – daniatic Jan 16 '18 at 20:27

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.