15

When I am creating hybrid math glyphs, I will find myself often times stacking \rules about the place. But if you look at a collection of CM math symbols (top row), and compare it to a \rule (2nd row)

\documentclass{article}
\begin{document}
\noindent$+ - = \subset \geq \ni$\\$\rule{2ex}{.3pt}$
\end{document}

enter image description here

you will find that strokes comprising the math glyphs exhibit rounded ends, whereas a rule has flattened ends. At typical size, the difference may be insignificant, but for scaled-up glyphs, it is noticeable.

Is there a version of a \rule, which I jokingly here called \mathrule, that will provide the functionality (even the syntax) of a \rule, but with rounded endcaps? (preferably not with tikz, but something more native).

I've considered stretching and squeezing, for example, a minus sign, but that will result in spherical end caps becoming elliptical, especially when the distortion is large.


I was going to put this attempt up to get the ball rolling, but Herbert beat me to it. I'll still leave it here as food for thought.

\documentclass{article}
\usepackage{scalerel}
\usepackage{verbatimbox}
\newsavebox\clippedbullet
\sbox{\clippedbullet}{\addvbuffer[.0pt -.55pt]{$\bullet$}}
\def\CB{\usebox{\clippedbullet}}
\newcommand\mathrule[3][0pt]{%
\raisebox{#1}{\scaleleftright{\kern-.8pt\CB\kern-2.5pt}%
  {\rule{#2-#3}{#3}}{\kern-2.4pt\CB\kern+.0pt}}%
}
\begin{document}
\noindent\mathrule[2pt]{2ex}{.5pt} \mathrule{3ex}{1pt} \mathrule[-1pt]{2ex}{2pt}\\
\rule[2pt]{2ex}{.5pt} \rule{3ex}{1pt} \rule[-1pt]{2ex}{2pt}
\end{document}

enter image description here

1
  • 2
    No, there isn't. Longer arrows are built by repeating minus signs.
    – egreg
    Commented Feb 19, 2014 at 16:18

2 Answers 2

12
\pdfcompresslevel=0 %%% to see how it works in the pdf code
\pdfcompresslevel=0
\documentclass{article}
\parindent=0pt
\makeatletter
\def\mathrule#1#2{%
  \@tempdima=\dimexpr#1-0.5#2
  \@tempdimb=#2
  \@tempdimc=0.5#2
  \hbox to #1{%
    \pdfliteral{ 
      q []0 d 
      1 J %  set line cap to rounded ends
      \strip@pt\@tempdimb\space w \strip@pt\@tempdimc\space 0 m 
      \strip@pt\@tempdima\space 0 l S Q }}}
\makeatletter

\begin{document}
x\mathrule{60bp}{2bp}x

x$\rule{60bp}{2bp}$x
\end{document}

enter image description here

8
  • Just to check: I assume this will work for pdflatex and lualatex, but not for plain latex. Commented Feb 19, 2014 at 16:48
  • That's a great start. But I'm thinking you forgot to shave the rule width off the length of the \mathrule, when you added the rounded ends. Am I just seeing it wrong? Commented Feb 19, 2014 at 16:49
  • add a \ifpdf and then use \special instead of \pdfliteral and the corresponfing PostScript function names. Pretty easy to realize.
    – user2478
    Commented Feb 19, 2014 at 16:49
  • @StevenB.Segletes: pdftex uses linecap=0. linecap=1 has the same line length than linecap=2. You can substract half the linewidth from the beginning and the end of the line and it will be the same.
    – user2478
    Commented Feb 19, 2014 at 16:51
  • Just for clarification, this does not take an optional argument, though a \raisebox could fix that, I suppose. Commented Feb 19, 2014 at 16:59
11

I am posting this as the final result of taking Herbert's solution where I wanted it, which is a drop in replacement for \rule that provides rounded line caps. Herbert deserves the credit and will get the points, but others (like me) might wish to see/use this more seamless drop-in for \rule.

Herbert's solution needed to be placed into an hbox, as he allowed, but it needed substantially more adjustments, as well. The horizontal and vertical kernings were offset relative to that box, the vertical alignment of the rounded rule differed from that of a \rule, just to name a few.

EDIT: I've also taken the initiative to force \mathrule to make a rule with the rounded endcaps on side/side or else the top/bottom, depending on which dimension is larger, such that

\mathrule{2ex}{2ex}
\mathrule{3ex}{2ex}
\mathrule{2ex}{3ex}

gives

enter image description here

In my MWE below, I put the final result through the paces of placing the \mathrule on a line by itself, placing it amongst text, stacking it, as well as \fboxing it, in all cases comparing to its equivalent \rule. The \mystery@factor in this MWE was later resolved by Dan in his comment. His correction is incorporated into the style file roundrule.sty that I present at the end of this answer.

\pdfcompresslevel=0 %%% to see how it works in the pdf code
\documentclass{article}
\usepackage{graphicx}
\usepackage{stackengine}% Used for testing; not needed for \math(v)rule's
\parindent=0pt
\makeatletter

\newcommand\mathrule[3][0pt]{%
  \ifdim#2>#3\math@hrule[#1]{#2}{#3}\else\math@vrule[#1]{#2}{#3}\fi}

\newcommand\math@hrule[3][0pt]{%
  \gdef\mystery@factor{0.07}%
 \@tempdima=#3%
  \rule[#1]{0pt}{#3}% Needed to account for .5\@tempdima vertical offset of rounded rule
  \raisebox{.5\@tempdima+#1}{%
    \makebox[#2][l]{\kern-.5\@tempdima\@@mathrule{#2}{#3}}}%
}

\newcommand\math@vrule[3][0pt]{%
  \gdef\mystery@factor{0.0}%
 \@tempdima=#2%
  \rule[#1]{0pt}{#3}% Needed to account for .5\@tempdima vertical offset of rounded rule
  \raisebox{-.0\@tempdima+#1}{%
    \kern0.5\@tempdima%
    \rotatebox{90}{\kern-0.5\@tempdima\makebox[#3][l]{\@@mathrule{#3}{#2}}}%
    \kern0.5\@tempdima}%
}

\def\@@mathrule#1#2{%
  \@tempdimb=#2%
  \@tempdima=\dimexpr#1-\mystery@factor\@tempdimb%Why 0.07 for \math@hrule?
  \pdfliteral{%
    q []0 d %
    1 J %  set line cap to rounded ends
    \strip@pt\@tempdimb\space w \strip@pt\@tempdimb\space 0 m %
    \strip@pt\@tempdima\space 0 l S Q }}
\makeatother
\begin{document}
\mathrule{60bp}{1bp}\par
\rule{60bp}{1bp}\par
x\mathrule[-1pt]{20bp}{1bp}x\mathrule{20bp}{1bp}x\par
x\rule[-1pt]{20bp}{1bp}x\rule{20bp}{1bp}x\par
\stackunder[2pt]{\rule{60bp}{3bp}}{\mathrule{60bp}{3bp}}\par
\fbox{\mathrule[-1ex]{4ex}{.5ex}}\fbox{\rule[-1ex]{4ex}{.5ex}}\par
\fbox{\mathrule[+1ex]{4ex}{.5ex}}\fbox{\rule[+1ex]{4ex}{.5ex}}\par
\clearpage
\mathrule{1bp}{60bp} \rule{1bp}{60bp}\par
x\mathrule[-1pt]{1bp}{20bp}x\mathrule{1bp}{20bp}x%
  \rule[-1pt]{1bp}{20bp}x\rule{1bp}{20bp}x\par
x\rule[-1pt]{1bp}{20bp}x\rule{1bp}{20bp}x\par
\stackunder[2pt]{\rule{3bp}{10bp}\mathrule{3bp}{10bp}}%
  {\mathrule{3bp}{10bp}\rule{3bp}{10bp}}\par
\fbox{\mathrule[-1ex]{.5ex}{4ex}}\fbox{\rule[-1ex]{.5ex}{4ex}}\par
\fbox{\mathrule[+1ex]{.5ex}{4ex}}\fbox{\rule[+1ex]{.5ex}{4ex}}\par
\end{document}

enter image description here

enter image description here

For those interested in an ad hoc package (and taking azetina's renaming suggestion since it functions outside of math mode), here is roundrule.sty, introducing the macro \roundrule[]{}{}. And thanks to Dan for resolving and eliminating the mystery factor. Of course, \roundrules can be used in text mode without the use of dollar delimiters. Feel free to \let\rrule\roundrule in your preamble, if you get tired of typing the long name.

EDITED to require package calc as well.

\ProvidesPackage{roundrule}
[2014/05/01 V1.01 Provides rules with rounded endcaps]
%
% THIS MATERIAL IS SUBJECT TO THE LaTeX Project Public License
%
% Special thanks to users Herbert and Prof. Dan Luecking at tex.stackexchange.com:
% http://tex.stackexchange.com/questions/161297/
%        is-there-such-a-thing-as-a-mathrule-rounded-endcaps
%
% V1.00 - initial release
% V1.01 - require package calc, which was omitted as an oversight.

\pdfcompresslevel=0 %%% to see how it works in the pdf code
\RequirePackage{graphicx}
\RequirePackage{calc}

\newcommand\roundrule[3][0pt]{%
  \ifdim#2>#3\round@hrule[#1]{#2}{#3}\else\round@vrule[#1]{#2}{#3}\fi}

\newcommand\round@hrule[3][0pt]{%
  \@tempdima=#3%
  \rule[#1]{0pt}{#3}% Needed to account for .5\@tempdima vertical offset of rounded rule
  \raisebox{.5\@tempdima+#1}{%
    \makebox[#2][l]{\kern-.5\@tempdima\@@roundrule{#2}{#3}}}%
}

\newcommand\round@vrule[3][0pt]{%
  \@tempdima=#2%
  \rule[#1]{0pt}{#3}% Needed to account for .5\@tempdima vertical offset of rounded rule
  \raisebox{-.0\@tempdima+#1}{%
    \kern0.5\@tempdima%
    \rotatebox{90}{\kern-0.5\@tempdima\makebox[#3][l]{\@@roundrule{#3}{#2}}}%
    \kern0.5\@tempdima}%
}

\def\@@roundrule#1#2{%
  \@tempdima=#1%
  \@tempdimb=#2%
  \@tempdima=0.996264\@tempdima% LaTeX to PDF point conversion (72/72.27)
  \@tempdimb=0.996264\@tempdimb% LaTeX to PDF point conversion (72/72.27)
  \pdfliteral{%
    q []0 d %
    1 J %  set line cap to rounded ends
    \strip@pt\@tempdimb\space w \strip@pt\@tempdimb\space 0 m %
    \strip@pt\@tempdima\space 0 l S Q }}

\endinput
6
  • Its as easy as a find and replace on the text editor. I would go for the \roundrule
    – azetina
    Commented Feb 20, 2014 at 19:37
  • @azetina I feel a nudge. While naming the package roundrule, do you think the macro should be \roundrule or \rrule? Commented Feb 20, 2014 at 19:41
  • hmmmm??? I would say \rrule is more practical but \roundrule says it all. Honestly, its just taste and consideration for compatibility cases. Is \rrule defined elsewhere?
    – azetina
    Commented Feb 20, 2014 at 19:52
  • 1
    @azetina I already checked. \rrule shows up nowhere on this website. Perhaps I'll leave it \roundrule and let the user employ a \let\rrule\roundrule. Commented Feb 20, 2014 at 19:55
  • 1
    @StevenB.Segletes Could the mystery factor be needed because TeX works with pt, which is 1/72.27 inch, while in PDF the default unit is 1/72 inch? I removed the mystery factor calculations, but added \@tempdima=0.996264\@tempdima and \@tempdimb=0.996264\@tempdimb to \@@mathrule (0.996264 = 72/72.27). It seemed to work just fine for both horizontal and vertical rules: lengths matched within 1pixel at 1600% magnification.
    – Dan
    Commented Feb 20, 2014 at 21:17

You must log in to answer this question.

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