1

I'd like to underline by repeating a symbol (for example +). I have this code that works for underlining with x but I couldn't make it work for +:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing}
\usetikzlibrary{decorations.pathreplacing}
\usetikzlibrary{decorations.shapes}

\newcommand{\latexunderplus}[1]{%
    \tikz[baseline=(todotted.base)]{
        \node[inner xsep=0pt,inner ysep=1pt,outer sep=0pt] (todotted) {#1};
        \draw[decorate,decoration={crosses,shape size=1pt},segment length=2pt] (todotted.south west) -- (todotted.south east);
    }%
}%

\begin{document}
\latexunderplus{qwe}
\end{document}

From what I've read, I could probably use \pgfdeclareshape to declare a new shape corresponding to my symbol, and then use it instead of crosses. This would imply telling tikz how to draw each symbol that I use for underlining. Is there another (simpler) way? For example some function that automagically turns a character into a shape?

  • Can you make the example compilable, with the successful x try and the unsuccessful + try? – egreg Apr 3 '18 at 13:10
4

If you are willing to try a bit of plain TeX you can do this with boxes and leaders:

\documentclass{article}
\def\undermark#1#2{\setbox0\hbox{#2}\hbox to 0pt{\copy0\hss}\lower2ex\hbox to
   \wd0{\cleaders\hbox{#1}\hfil}}
\begin{document}
However, a service-oriented \undermark{$\cdot$}{paradigm} is further compounded
when taking into account the evolution of specifications over a given time period.
Interestingly enough, the fully integrated test program presents extremely
interesting challenges to the preliminary \undermark{$\scriptstyle+$}{qualification} limit.  Similarly, the
incorporation of additional mission constraints must utilize and be functionally
interwoven with possible bidirectional logical relationship \undermark{x}{approaches}.
\end{document}

enter image description here

Observations

  • This is not very robust - for example it will mess with the line breaking if you use it near the end of a line.

  • I think it looks ugly typographically.

Explanation

  • \def\undermark#1#2 defines a command that expects two arguments

  • \setbox0\hbox{#2} sets box register 0 to a box containing the second arg

  • \hbox to 0pt{\copy0\hss} typesets a box of zero width containing the contents of box register 0 with all the contents sticking out the right.

  • \lower2ex typesets the following box 2ex below the baseline

  • \hbox to \wd0{} typesets a a box stretched to the width of box register 0

  • \cleaders\hbox{#1}\hfil creates a stretchy pattern made with copies of box containing the first argument

  • Using this with the anyfontsize works pretty well, except that I have to manually replace the 2ex with whatever works (which won't be the same for abc and qwe because of the q). – xavierm02 Apr 3 '18 at 13:25
  • And about typographical ugliness, it's the best I could find. I have things (terms) that are either positive or negative, and I want to annotate them. The problem is that the supscript is already taken (by ' among other things), and so when I have several of them (for example $t_1$ and $t_2$), making explicit that they are positive with indices makes it ugly ($t_{1+}$, ${t_{1}}_+$, $(t_1)_+$) so instead, I thought of underlining with plus signs $\latexunderplus{t_1}$. I think it makes it decently readable. – xavierm02 Apr 3 '18 at 13:36
  • I picked 2ex because that would clear the descenders in most cases, but you could parameterize it with, say, \ht0... – Thruston Apr 3 '18 at 13:40
  • I tried to make it work with \dimexpr and \ht0 but apparently \ht gives the same height to a and q (which is good for normal underline, but makes it look weird when the underline is made of +s). – xavierm02 Apr 3 '18 at 14:02
  • there is also \dp0, the depth below the baseline... – Thruston Apr 3 '18 at 22:02
3

You may just rotate the crosses and invent a new decoration for the \ominus. This can be done by looking up pgflibrarydecorations.shapes.code.tex, copying the code from there and adjusting it.

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing}
\usetikzlibrary{decorations.pathreplacing}
\usetikzlibrary{decorations.shapes}

\makeatletter
\pgfdeclaredecoration{ominus}{init}
{
  \state{init}[width=+0pt,next state=crosses,persistent precomputation={
    \pgfmathparse{\pgfkeysvalueof{/pgf/decoration/shape start width}/sqrt(8)}
    \edef\pgf@lib@dec@ssw{\pgfmathresult pt}
    \pgfmathparse{\pgfkeysvalueof{/pgf/decoration/shape start height}/2}
    \edef\pgf@lib@dec@ssh{\pgfmathresult pt}
  }]{}  
  \state{crosses}[switch if less than=+\pgfdecorationsegmentlength to last,
                  width=+\pgfdecorationsegmentlength]
  {
    \pgfpathmoveto{\pgfqpoint{-\pgf@lib@dec@ssw}{0pt}}
    \pgfpathlineto{\pgfqpoint{\pgf@lib@dec@ssw}{0pt}}
    \pgfpathlineto{\pgfqpoint{\pgf@lib@dec@ssw}{0pt}}
    \pgfpathcircle{\pgfpointorigin}{\pgf@lib@dec@ssw}\pgfusepath{stroke}
  }
  \state{last}[width=+\pgfdecoratedremainingdistance]
  {
    \pgfpathmoveto{\pgfqpoint{-\pgf@lib@dec@ssw}{0pt}}
    \pgfpathlineto{\pgfqpoint{\pgf@lib@dec@ssw}{0pt}}
    \pgfpathlineto{\pgfqpoint{\pgf@lib@dec@ssw}{0pt}}
    \pgfpathcircle{\pgfpointorigin}{\pgf@lib@dec@ssw}\pgfusepath{stroke}
  }
  \state{final}{
    \pgfpathmoveto{\pgfpointdecoratedpathlast}
    \pgfpathmoveto{\pgfqpoint{-\pgf@lib@dec@ssw}{0pt}}
    \pgfpathlineto{\pgfqpoint{\pgf@lib@dec@ssw}{0pt}}
    \pgfpathlineto{\pgfqpoint{\pgf@lib@dec@ssw}{0pt}}
    \pgfpathcircle{\pgfpointorigin}{\pgf@lib@dec@ssw}\pgfusepath{stroke}
  }
}
\makeatother


\newcommand{\latexunderplus}[1]{%
    \tikz[baseline=(todotted.base)]{
        \node[inner xsep=0pt,inner ysep=1pt,outer sep=0pt] (todotted) {#1};
        \draw[decorate,decoration={crosses,shape size=2pt,transform={rotate=45}},segment length=2pt] (todotted.south west) -- (todotted.south east);
    }%
}%

\newcommand{\latexunderominus}[1]{%
    \tikz[baseline=(todotted.base)]{
        \node[inner xsep=0pt,inner ysep=1pt,outer sep=0pt] (todotted) {#1};
        \draw[decorate,decoration={ominus,shape size=5pt},segment length=5pt] (todotted.south west) -- (todotted.south east);
    }%
}%



\begin{document}
\latexunderplus{qwe}
\latexunderominus{qwe}
\end{document}

enter image description here

  • Yes, but I also need it for $\ominus$. I should've taken another symbol as example... – xavierm02 Apr 3 '18 at 13:28
  • @xavierm02 OK, now with ominus. Please have a look at my update. – marmot Apr 3 '18 at 14:06
0

The two solutions side by side:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.pathmorphing}
\usetikzlibrary{decorations.pathreplacing}
\usetikzlibrary{decorations.shapes}
\usepackage{anyfontsize}
\usepackage{calc}
\def\undermark#1#2{
    \setbox0\hbox{#2}\hbox to 0pt{\copy0\hss}\lower\the\dimexpr\dp0+2pt\relax\hbox to
    \wd0{\cleaders\hbox{#1}\hfil}}

\makeatletter
\pgfdeclaredecoration{ominus}{init}
{
    \state{init}[width=+0pt,next state=crosses,persistent precomputation={
        \pgfmathparse{\pgfkeysvalueof{/pgf/decoration/shape start width}/sqrt(8)}
        \edef\pgf@lib@dec@ssw{\pgfmathresult pt}
        \pgfmathparse{\pgfkeysvalueof{/pgf/decoration/shape start height}/2}
        \edef\pgf@lib@dec@ssh{\pgfmathresult pt}
    }]{}  
    \state{crosses}[switch if less than=+\pgfdecorationsegmentlength to last,
    width=+\pgfdecorationsegmentlength]
    {
        \pgfpathmoveto{\pgfqpoint{-\pgf@lib@dec@ssw}{0pt}}
        \pgfpathlineto{\pgfqpoint{\pgf@lib@dec@ssw}{0pt}}
        \pgfpathlineto{\pgfqpoint{\pgf@lib@dec@ssw}{0pt}}
        \pgfpathcircle{\pgfpointorigin}{\pgf@lib@dec@ssw}\pgfusepath{stroke}
    }
    \state{last}[width=+\pgfdecoratedremainingdistance]
    {
        \pgfpathmoveto{\pgfqpoint{-\pgf@lib@dec@ssw}{0pt}}
        \pgfpathlineto{\pgfqpoint{\pgf@lib@dec@ssw}{0pt}}
        \pgfpathlineto{\pgfqpoint{\pgf@lib@dec@ssw}{0pt}}
        \pgfpathcircle{\pgfpointorigin}{\pgf@lib@dec@ssw}\pgfusepath{stroke}
    }
    \state{final}{
        \pgfpathmoveto{\pgfpointdecoratedpathlast}
        \pgfpathmoveto{\pgfqpoint{-\pgf@lib@dec@ssw}{0pt}}
        \pgfpathlineto{\pgfqpoint{\pgf@lib@dec@ssw}{0pt}}
        \pgfpathlineto{\pgfqpoint{\pgf@lib@dec@ssw}{0pt}}
        \pgfpathcircle{\pgfpointorigin}{\pgf@lib@dec@ssw}\pgfusepath{stroke}
    }
}
\makeatother

\newcommand{\latexunderplus}[1]{%
    \tikz[baseline=(todotted.base)]{
        \node[inner xsep=0pt,inner ysep=1pt,outer sep=0pt] (todotted) {#1};
        \draw[decorate,decoration={crosses,shape size=1.5pt,transform={rotate=45}},segment length=2.5pt] (todotted.south west) -- (todotted.south east);
    }%
}%

\newcommand{\latexunderominus}[1]{%
    \tikz[baseline=(todotted.base)]{
        \node[inner xsep=0pt,inner ysep=1pt,outer sep=0pt] (todotted) {#1};
        \draw[decorate,decoration={ominus,shape size=2.5pt},segment length=3pt] (todotted.south west) -- (todotted.south east);
    }%
}%

\begin{document}

\newcommand{\mytest}[1]{
    $\latexunderplus{\ensuremath{#1}}$
    $\latexunderominus{\ensuremath{#1}}$
    vs
    $\undermark{\fontsize{2pt}{3pt}\selectfont +}{\ensuremath{#1}}$
    $\undermark{\fontsize{2pt}{3pt}\selectfont \ensuremath{\ominus}}{\ensuremath{#1}}$
}

\mytest{\ensuremath{V_1}}\\
\mytest{qwe}\\
\mytest{abc}


\end{document}

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.