10

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.

3
  • +1 for wrotating the wrong page. if it's feasible, placing the figure at a chapter break might give you a little more freedom. Apr 29, 2016 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, 2016 at 23:55

2 Answers 2

12
+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}
10
  • 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, 2016 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. May 3, 2016 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, 2016 at 16:39
  • 1
    Since I appear to have reinvented sidewaysfigure, I redid my solution as an environment. May 5, 2016 at 16:57
  • 1
    Thanks! This still works perfectly in 2022. I put your header in landscapefigure.sty and now use \usepackage{landscapefigure} across documents.
    – Luke Davis
    Mar 22, 2022 at 22:03
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.)

3
  • 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. Apr 30, 2016 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, 2016 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, 2018 at 20:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .