3

I see this all the time, inline graphics (in this case tikz picture) do not obey line breaks and flow like a word.

In this example document, there are no forces new lines and the picture sticks out to the margin and beyond. (What you see is a screenshot from evince, you can see the margins in both sides.

rebelpicture

If this is the natural behavior, how can I make the graphics to not stick to the margins?

MWE:

\documentclass[]{article}
\usepackage[]{pgfplots}
\begin{document}
aaaaaaaaaa aaaaaaaaaaaaaa aaaaaaaaaaaaa aaaaaaaaaaaa aaaaaaaa %
\begin{tikzpicture}
\begin{axis}
\end{axis}
\end{tikzpicture}
 bbbbbbbbbb bbbbbbbbbbbb bbbbbbbbbb
\end{document}

After posting the question I found possible duplicates: How can one make LaTeX break lines between graphics correctly? and How to avoid using \sloppy document-wide to fix overfull \hbox problems? . \sloppy seems to be a partial answer, since it has to be selectively used around the problematic paragraph, a general solution would be nice too.

alfC
  • 14,350
  • 1
    For all practical purposes, the tikzpicture is a "word" (it is in an hbox, not a vbox) or at least it can be used as such (that's a feature, not a bug). If you want it to not act as a word, you have to set it as such, either in its own paragraph or centering environment, or something. – Steven B. Segletes Jun 05 '14 at 17:23
  • @StevenB.Segletes, yes that is what I want, but wouldn't a word appear in the next line if it didn't fit in the current line? – alfC Jun 05 '14 at 17:27
  • If a word is too long, LaTeX sometimes cannot resolve the problems with full justification, and ends up protruding into the margin. This can happen with any long inline box, such as \makebox, etc. If you were in \raggedright mode, the line break would have happened. But in full justify mode, LaTeX just couldn't make it work. – Steven B. Segletes Jun 05 '14 at 17:29
  • @StevenB.Segletes, thanks for the explanation. The question would be then how to make LaTeX (or TeX? I never know) smarter at doing the justificiation. For example by knowing the typical size of the graph? Actually now that you mention it, LaTeX may be choosing a lesser bad because the "aaa aaa" line will look too separate then. However the picture going outside the physical margin is really really bad. – alfC Jun 05 '14 at 17:33
  • If you do aaaaa{\centering\begin{tikzpicture}...\end{tikzpicture}\par} bbbb, you may get something preferable. There are many such ways... – Steven B. Segletes Jun 05 '14 at 17:35
  • @StevenB.Segletes, centering doesn't work. But ...\sloppy \begin{tikzpicture}... works. The problem is that I am not sure if sloppy will be kept activated for the rest of the document and that apparently is a bad practice since high quality justification will be lost for normal cases. – alfC Jun 05 '14 at 17:40
  • \begin{sloppypar}...\end{sloppypar} – Steven B. Segletes Jun 05 '14 at 17:45
  • if you are willing to let the picture be on a line by itself, you could treat it as an unnumbered equation and wrap it in \[ ... \]. – barbara beeton Jun 05 '14 at 17:53
  • @barbarabeeton, I just want it to behave like a word. – alfC Jun 05 '14 at 18:02
  • 1
    @StevenB.Segletes, sloppypar made the trick. That presumably must enclose the whole paragraph. I wonder if there is a more "local" option that I can just put next to the offending picture. BTW, I realize that this has more to do with the size of the word/picture than with the fact that it is a picture. (for example a \begin{axis}[tiny] will not produce bad behavior at all). Obviously the problem is that the justify algorithm doesn't expect very long words. – alfC Jun 05 '14 at 18:07
  • if the picture you show here is typical, that is, if the picture is much larger (in particular, taller) than a word in the text, then sloppypar is probably the approach most likely to work, albeit the result will probably not look very good. a small picture, such as a logo, in scale with an ordinary word, is often inserted either as in-line code (as you have here) or with \includegraphics and behaves very nicely. a wide element (for example an unbreakable url as well as a picture) will stress the line-breaking algorithm. – barbara beeton Jun 05 '14 at 18:13
  • The way LaTeX works, it sets a whole paragraph at a time, trying to satisfy a set of weighted constraints (the weights being set by "penalties" and \sloppy just defining different weight values). Because of this fundamental process, you can not set part of a paragraph as sloppy. I did have a related answer that might emulate a partial sloppy. If I find it, I'll provide the pointer. – Steven B. Segletes Jun 05 '14 at 18:13
  • @StevenB.Segletes , The problem is not only the size of the figures. I found this problem again even when putting a sequence of (really) small figures or small tables after each other (in contradiction to what I said earlier). It seems that LaTeX doesn't know how to "stretch" (for justification) the spaces between things that are not made of letter (real words). I finally found that the simplest solution is to separate the figures with something like \\ from the rest. (It also worked with \phantom{,} which I found in desperation.) – alfC May 10 '16 at 05:53
  • 1
    @alfC If I were to have a string of figures that I intended to be on a single line of text, I would tend to use \hfil or \hfill as the interfigure separator, as they are, by design, stretchable. – Steven B. Segletes May 10 '16 at 09:54

2 Answers2

5

The various comments to your question have indicated two things:

1) everyone recommends against large images as inline characters

2) you (for whatever reason) wish to have your large image set as in inline character, and not, for example, as a separate figure.

Given that, let me review the comment highlights.

1) The tikzpicture being in an hbox and not a vbox, will be treated as an inline character if it is not set apart in its own environment or group.

2) The way LaTeX works, it sets a whole paragraph at a time, trying to satisfy a set of weighted constraints (the weights being set by "penalties" and \sloppy just defining different weight values).

3) If you were using raggedright justification, the constraints are fewer and LaTeX would provide the line break to prevent margin overrun. However, with full alignment, LaTeX may be unable, using the default penalties, to arrive at a satisfactory solution. In those cases it produces an "overfull hbox" which in this case manifests as margin overrun.

4) You discovered that \sloppy "fixes" the problem, but you are worried that you don't want to prepare a whole document as sloppy.

So my first fix was to use the sloppypar environment to only fix the offending paragraph (paragraph 1 in the MWE).

You then asked if one could effectively provide a sloppypar like solution over a partial paragraph. I would say you are going from bad to worse, but I seemed to recall this solution, Cutting corners - how to delete 1 pt (0.3515 mm) or so, for squeezing things onto one row. Here I use it to stretch things across a partial row, in paragraph 2 of the MWE. It is worse than sloppypar because the word spacing changes mid line (yech!), but at least the line with the bbb characters is not "sloppy" (as you requested).

Paragraph 3 of the MWE was your own example, to prove that sloppypar does not extend over the remainder of the document.

\documentclass[]{article}
\usepackage[]{pgfplots}
\def\squeeze#1{\squeezeit#1 \relax\relax}
% REVISED SOLUTION
\def\squeezeit#1 #2\relax{#1\if\relax#2\else
  \findlast#1\relax\relax%
    \if.\LastChar\hfil\else
      \if,\LastChar\hfil\else
        \hfil\hfil%
       \fi
    \fi
  \squeezeit#2\relax\fi%
}
\def\findlast#1#2\relax{\def\LastChar{#1}\if\relax#2\else\findlast#2\relax\fi}
\textheight 9in
\begin{document}
\begin{sloppypar}
aaaaaaaaaa aaaaaaaaaaaaaa aaaaaaaaaaaaa aaaaaaaaaaaa aaaaaaaa %
\begin{tikzpicture}
\begin{axis}
\end{axis}
\end{tikzpicture}
 bbbbbbbbbb bbbbbbbbbbbb bbbbbbbbbb
\end{sloppypar}

\squeeze{aaaaaaaaaa aaaaaaaaaaaaaa aaaaaaaaaaaaa aaaaaaaaaaaa} aaaaaaaa %
\begin{tikzpicture}
\begin{axis}
\end{axis}
\end{tikzpicture}
 bbbbbbbbbb bbbbbbbbbbbb bbbbbbbbbb

aaaaaaaaaa aaaaaaaaaaaaaa aaaaaaaaaaaaa aaaaaaaaaaaa aaaaaaaa %
\begin{tikzpicture}
\begin{axis}
\end{axis}
\end{tikzpicture}
 bbbbbbbbbb bbbbbbbbbbbb bbbbbbbbbb
\end{document}

enter image description here

4

It is unrelated to graphics, it is just acting like a word it can not hyphenate:

enter image description here

\documentclass[]{article}
\setlength\parfillskip{2\baselineskip}
\begin{document}

\noindent X\dotfill X

aaaaaaaaaa aaaaaaaaaaaaaa aaaaaaaaaaaaa aaaaaaaaaaaa aaaaaaaa %
ZZZZZZZZZZZZZZZZZZZZZZZZ
 bbbbbbbbbb bbbbbbbbbbbb bbbbbbbbbb

\noindent X\dotfill X

\begin{sloppypar}
aaaaaaaaaa aaaaaaaaaaaaaa aaaaaaaaaaaaa aaaaaaaaaaaa aaaaaaaa %
ZZZZZZZZZZZZZZZZZZZZZZZZ
 bbbbbbbbbb bbbbbbbbbbbb bbbbbbbbbb
\end{sloppypar}

\noindent X\dotfill X

aaaaaaaaaa aaaaaaaaaaaaaa aaaaaaaaaaaaa aaaaaaaaaaaa aaaaaaaa\\
ZZZZZZZZZZZZZZZZZZZZZZZZ
 bbbbbbbbbb bbbbbbbbbbbb bbbbbbbbbb

\noindent X\dotfill X

aaaaaaaaaa aaaaaaaaaaaaaa aaaaaaaaaaaaa aaaaaaaaaaaa aaaaaaaa\linebreak
ZZZZZZZZZZZZZZZZZZZZZZZZ
 bbbbbbbbbb bbbbbbbbbbbb bbbbbbbbbb

\end{document}
David Carlisle
  • 757,742
  • That makes sense. Do you know if there is some command to hint for a linebreak but not force it? This way I can put this command infront of "large objects". For example aaaa \maybelinebreak ZZZZZZZZZZZZZZZZZZZZZZZ – alfC Jun 05 '14 at 19:53
  • \linebreak[2] or any number less that 4 (which is a forced break) – David Carlisle Jun 05 '14 at 20:08
  • Actually something like \linebreak[] is what I am looking for. Unfortunately, \linebreak in particular doesn't seem to have a good fine tuning, since, for the original example, [3] doesn't break the line and [4], as you said, forces the break in all conditions. A [3.9] would be the solution but there is no such thing. Currently I am trying with ...aaaaaaaa \linebreak[3] \begin{tikzpicture}... – alfC Jun 06 '14 at 06:26
  • @alfC you probably need to allow white space to stretch as well as encouraging a break at that point – David Carlisle Jun 06 '14 at 07:30
  • With the \strech command? – alfC Jun 06 '14 at 08:33
  • @alfC well I would use \setlength\emergencystretch{.5\textwidth} locally at the start of the paragraph, also you can use \penalty n for any number between 0 and -10000 to encourage line breaks see http://tex.stackexchange.com/questions/168987/applications-of-various-strength-of-linebreak-command/168999#168999 – David Carlisle Jun 06 '14 at 09:00