New decorated triangle for mathematical formulas

Since the image in the question uses different colors inside the same symbol, I propose a flexible interface that allows one to choose specific settings (via TikZ styles) for the triangle and for the “inner feature” (which can be empty, a plus sign or a horizontal bar). The operator defined below behaves as a binary relation (\mathrel). The left or right triangle vertex is at the height of the math axis (i.e., at the same level as fraction bars, \cdots, + and = signs). I implemented two interfaces:

  • the verbose one: \myTriangle takes one optional argument which consists of PGF keys executed in /tikz/my triangle (e.g., \myTriangle[orientation=right, inner feature type=+, append style={fill=yellow}, append inner feature style={draw=red}]);

  • the terse one: \mytriangle[triangle opts][inner feature opts]{l}{+} or \mytriangle[triangle opts][inner feature opts]{r}{-}, etc. (if the last argument is empty or blank, the triangle will be empty).

Both interfaces are illustrated in the examples below. The color of the “inner feature” is brown by default, since this is how it is in the question. This default can be changed by simple modification of the following line:

set inner feature style={draw=brown, line cap=round, line width=0.3pt}

You can choose the default TikZ settings you want independently for the triangle and for the inner feature using the keys defined in the first \tikzset command of my code. The very same options can be used in the optional argument of \myTriangle.

\documentclass[border=0.5mm]{standalone}
\usepackage{tikz}
\usepackage{xparse} % for the interface allowing concise syntax (\mytriangle)

\makeatletter
\newif\ifmy@triangle@orientation@left
\newif\ifmy@triangle@twosides

\tikzset{
  my triangle/.is family,
  my triangle/.cd,
  set style/.style={style/.style={#1}}, % store for future use
  append style/.style={style/.append style={#1}},
  set style={draw=black, line width=0.3pt},
  inner feature type/.store in=\my@triangle@feature@type,
  inner feature type={},
  set inner feature style/.style={inner feature style/.style={#1}},
  append inner feature style/.style={inner feature style/.append style={#1}},
  set inner feature style={draw=brown, line cap=round, line width=0.3pt},
  orientation/.is choice,
  orientation/left/.code={\my@triangle@orientation@lefttrue},
  orientation/right/.code={\my@triangle@orientation@leftfalse},
  orientation=left,
  transform/.style={},  % semi-private: use only if you understand how it works
}

% Command from egreg (https://tex.stackexchange.com/a/499972/73317)
\newcommand{\math@param}[3]{%
  \fontdimen#3
  \ifx#1\displaystyle\textfont#2
  \else\ifx#1\textstyle\textfont#2
  \else\ifx#1\scriptstyle\scriptfont#2
  \else\scriptscriptfont#2 \fi\fi\fi
}

% #1: Either \my@triangle@left or \my@triangle@right
\newcommand*{\my@triangle@wrap}[1]{%
  \ifx\my@triangle@feature@type\empty
    \my@triangle@twosidesfalse
  \else
    \if\my@triangle@feature@type -%
      \my@triangle@twosidesfalse
    \else
      \if\my@triangle@feature@type +%
        \my@triangle@twosidestrue
      \else
        \errmessage{%
          Unexpected triangle feature type: '\my@triangle@feature@type'}%
      \fi
    \fi
  \fi
  \mathrel{\mathpalette#1\relax}%
}

\newcommand*{\my@triangle@width}{2} % multiple of the math axis height
\newdimen\my@height

% #1: math style
% #2: unused
\newcommand*{\my@triangle@left}[2]{%
  \my@height=\math@param{#1}{2}{22}% height of the math axis
  \begin{tikzpicture}[scale=\my@height/1cm, my triangle/transform]
    \path[my triangle/style, draw=none]
      (0,1) -- (\my@triangle@width,2) -- (\my@triangle@width,0) -- cycle;

    \ifx\my@triangle@feature@type\empty
    \else
      \begin{scope}[every path/.append style={my triangle/inner feature style}]
        \if\my@triangle@feature@type -
          \path (0,1) -- (\my@triangle@width,1);
        \else
          \if\my@triangle@feature@type +
            \path (\my@[email protected], 1) -- (\my@triangle@width+0.5, 1)
                  (\my@triangle@width, 0.5) -- (\my@triangle@width, 1.5);
          \fi
        \fi
      \end{scope}
    \fi

    \path[my triangle/style, fill=none]
      (\my@triangle@width,0) -- (0,1) -- (\my@triangle@width,2)
      \ifmy@triangle@twosides \else --cycle \fi;
  \end{tikzpicture}%
}

\newcommand*{\my@triangle@right}{%
  \tikzset{my triangle/transform/.append style={xscale=-1}}%
  \my@triangle@left
}

% #1: PGF keys executed in '/tikz/my triangle'
\newcommand*{\myTriangle}[1][]{%
  \begingroup
    \tikzset{my triangle/.cd, #1}%
    \expandafter\expandafter\expandafter\my@triangle@wrap
    \ifmy@triangle@orientation@left
      \expandafter\my@triangle@left
    \else
      \expandafter\my@triangle@right
    \fi
  \endgroup
}
\makeatother

% Offer an interface that allows concise syntax
\ExplSyntaxOn
\msg_new:nnn { mytriangle } { invalid-orientation-arg }
  { Invalid~value~for~triangle~orientation:~'#1'. }
\msg_new:nnn { mytriangle } { invalid-feature-type }
  { Invalid~feature~type:~'#1'. }

\tl_new:N \l__mytriangle_orientation_tl
\tl_new:N \l__mytriangle_feature_type_tl

% #1: passed to '/tikz/my triangle/append style'
% #2: passed to '/tikz/my triangle/append inner feature style'
% #3: orientation ('l', 'r')
% #4: inner feature type ('' or ' ', '-', '+')
\NewDocumentCommand \mytriangle { O{} O{} m m }
  {
    \str_case_e:nnF {#3}
      {
        { l } { \tl_set:Nn \l__mytriangle_orientation_tl { left } }
        { r } { \tl_set:Nn \l__mytriangle_orientation_tl { right } }
      }
      { \msg_error:nnn { mytriangle } { invalid-orientation-arg } {#3} }

    \tl_if_blank:nTF {#4}
      { \tl_clear:N \l__mytriangle_feature_type_tl }
      {
        \str_case_e:nnF {#4}
          {
            { - } { \tl_set:Nn \l__mytriangle_feature_type_tl { - } }
            { + } { \tl_set:Nn \l__mytriangle_feature_type_tl { + } }
          }
          { \msg_error:nnn { mytriangle } { invalid-feature-type } {#4} }
      }

    \myTriangle
      [
        append~style={#1}, append~inner~feature~style={#2},
        orientation/.expand~once=\l__mytriangle_orientation_tl,
        inner~feature~type/.expand~once=\l__mytriangle_feature_type_tl,
      ]
  }
\ExplSyntaxOff

\begin{document}

$\begin{array}{@{}l@{}}
a \mytriangle{l}{} b \mytriangle{l}{-} c \mytriangle{l}{+} d
\\
a \mytriangle{r}{} b \mytriangle{r}{-} c \mytriangle{r}{+} d
\\
a \myTriangle[append style={fill=yellow}, inner feature type=-] b
\mytriangle[fill=cyan!60!green][draw=black]{l}{+}
\mytriangle[fill=cyan][draw=yellow]{l}{-}
\mytriangle[fill=red]{l}{+}
\\
a \myTriangle[orientation=right, append style={draw=orange!50!red, fill=yellow},
              inner feature type=+, append inner feature style={draw=cyan}] b
\mytriangle[fill=cyan!60!green][draw=black]{r}{}
\mytriangle[fill=cyan][draw=yellow]{r}{-}
\mytriangle[fill=red]{r}{+}
\end{array}$

\end{document}

enter image description here

Example with subscripts and superscripts:

$\begin{array}{@{}l@{}}
M \mytriangle{l}{ } N
  ^{{\alpha \mytriangle{l}{-} \beta}^{\gamma \mytriangle{l}{+} \delta}}
  _{{\varepsilon \mytriangle{l}{-} \delta}_{\eta \mytriangle{l}{+} \kappa}}
\\[1ex]
M \mytriangle{r}{ } N
  ^{{\alpha \mytriangle{r}{-} \beta}^{\gamma \mytriangle{r}{+} \delta}}
  _{{\varepsilon \mytriangle{r}{-} \delta}_{\eta \mytriangle{r}{+} \kappa}}
\end{array}$

enter image description here


Geometric symbols: a job for l3draw.

\documentclass{article}
\usepackage{amsmath,xparse,l3draw}

\ExplSyntaxOn

\fp_new:N \l__pbmc_triangle_fp

\cs_new_protected:Nn \pmbc_triangle_right:
 {
  \draw_begin:
  \draw_linewidth:n { \l__pmbc_triangle_fp }
  \draw_cap_round:
  \draw_join_round:
  \draw_path_moveto:n { 0.0ex , 0.5ex }
  \draw_path_lineto:n { 1.0ex , 0.0ex }
  \draw_path_lineto:n { 1.0ex , 1.0ex }
  \draw_path_close:
  \draw_path_use_clear:n { stroke }
  \draw_end:
 }
\cs_new_protected:Nn \pmbc_triangle_left:
 {
  \draw_begin:
  \draw_linewidth:n { \l__pmbc_triangle_fp }
  \draw_cap_round:
  \draw_join_round:
  \draw_path_moveto:n { 0.0ex , 0.0ex }
  \draw_path_lineto:n { 1.0ex , 0.5ex }
  \draw_path_lineto:n { 0.0ex , 1.0ex }
  \draw_path_close:
  \draw_path_use_clear:n { stroke }
  \draw_end:
 }
\cs_new_protected:Nn \pmbc_triangle_minus_right:
 {
  \draw_begin:
  \draw_linewidth:n { \l__pmbc_triangle_fp }
  \draw_cap_round:
  \draw_join_round:
  \draw_path_moveto:n { 1.0ex , 0.5ex }
  \draw_path_lineto:n { 0.0ex , 0.5ex }
  \draw_path_lineto:n { 1.0ex , 1.0ex }
  \draw_path_lineto:n { 1.0ex , 0.0ex }
  \draw_path_lineto:n { 0.0ex , 0.5ex }
  \draw_path_close:
  \draw_path_use_clear:n { stroke }
  \draw_end:
 }
\cs_new_protected:Nn \pmbc_triangle_minus_left:
 {
  \draw_begin:
  \draw_linewidth:n { \l__pmbc_triangle_fp }
  \draw_cap_round:
  \draw_join_round:
  \draw_path_moveto:n { 0.0ex , 0.5ex }
  \draw_path_lineto:n { 1.0ex , 0.5ex }
  \draw_path_lineto:n { 0.0ex , 1.0ex }
  \draw_path_lineto:n { 0.0ex , 0.0ex }
  \draw_path_lineto:n { 1.0ex , 0.5ex }
  \draw_path_close:
  \draw_path_use_clear:n { stroke }
  \draw_end:
 }
\cs_new_protected:Nn \pmbc_triangle_plus_right:
 {
  \draw_begin:
  \draw_linewidth:n { \l__pmbc_triangle_fp }
  \draw_cap_round:
  \draw_join_round:
  \draw_path_moveto:n { 1.0ex , 1.0ex }
  \draw_path_lineto:n { 0.0ex , 0.5ex }
  \draw_path_lineto:n { 1.0ex , 0.0ex }
  \draw_path_use_clear:n { stroke }
  \draw_path_moveto:n { 1.0ex , 0.2ex }
  \draw_path_lineto:n { 1.0ex , 0.8ex }
  \draw_path_use_clear:n { stroke }
  \draw_path_moveto:n { 0.7ex, 0.5ex }
  \draw_path_lineto:n { 1.3ex, 0.5ex }
  \draw_path_use_clear:n { stroke }
  \draw_end:
 }
\cs_new_protected:Nn \pmbc_triangle_plus_left:
 {
  \draw_begin:
  \draw_linewidth:n { \l__pmbc_triangle_fp }
  \draw_cap_round:
  \draw_join_round:
  \draw_path_moveto:n { 0.0ex , 1.0ex }
  \draw_path_lineto:n { 1.0ex , 0.5ex }
  \draw_path_lineto:n { 0.0ex , 0.0ex }
  \draw_path_use_clear:n { stroke }
  \draw_path_moveto:n { 0.0ex , 0.2ex }
  \draw_path_lineto:n { 0.0ex , 0.8ex }
  \draw_path_use_clear:n { stroke }
  \draw_path_moveto:n { -0.3ex, 0.5ex }
  \draw_path_lineto:n { +0.3ex, 0.5ex }
  \draw_path_use_clear:n { stroke }
  \draw_end:
 }

\NewDocumentCommand{\BMright}{}
 {
  \mathrel
   {
    \fp_set:Nn \l__pmbc_triangle_fp { 0.08ex }
    \text{\kern0.1ex \pmbc_triangle_right: \kern0.1ex}
   }
 }
\NewDocumentCommand{\BMleft}{}
 {
  \mathrel
   {
    \fp_set:Nn \l__pmbc_triangle_fp { 0.08ex }
    \text{\kern0.1ex \pmbc_triangle_left: \kern0.1ex}
   }
 }
\NewDocumentCommand{\BMminusright}{}
 {
  \mathrel
   {
    \fp_set:Nn \l__pmbc_triangle_fp { 0.08ex }
    \text{\kern0.1ex \pmbc_triangle_minus_right: \kern0.1ex}
   }
 }
\NewDocumentCommand{\BMminusleft}{}
 {
  \mathrel
   {
    \fp_set:Nn \l__pmbc_triangle_fp { 0.08ex }
    \text{\kern0.1ex \pmbc_triangle_minus_left: \kern0.1ex}
   }
 }
\NewDocumentCommand{\BMplusright}{}
 {
  \mathrel
   {
    \fp_set:Nn \l__pmbc_triangle_fp { 0.08ex }
    \text{\kern0.1ex \pmbc_triangle_plus_right: \kern-0.2ex}
    \mkern2mu\nonscript\mkern-2mu
   }
 }
\NewDocumentCommand{\BMplusleft}{}
 {
  \mathrel
   {
    \fp_set:Nn \l__pmbc_triangle_fp { 0.08ex }
    \mkern2mu\nonscript\mkern-2mu
    \text{\kern-0.2ex \pmbc_triangle_plus_left: \kern0.1ex}
   }
 }

\ExplSyntaxOff

\begin{document}

$a \BMright b \BMleft c$

$a \BMminusright b \BMminusleft c$

$a \BMplusright b \BMplusleft c$

$\scriptstyle a \BMplusright b \BMplusleft c$

\LARGE $a \BMright b \BMleft c$

\end{document}

enter image description here


Here's a simple implementation of these symbols. I'm not sure what this B-Method is, so I made them relational symbols with \mathrel so they behave like amsmath's \vartriangleleft and \vartriangleright symbols.

\documentclass{article}
\usepackage{amsmath,amssymb}
\usepackage{trimclip}
\newlength{\trianglewidth}
\newlength{\pluswidth}
\settowidth{\trianglewidth}{\(\vartriangleleft\)}
\settowidth{\pluswidth}{\(+\)}
\newcommand{\lefttrianglebar}{%
    \mathrel{\makebox[\trianglewidth]{%
        \makebox[\trianglewidth]{\(\vartriangleleft\)}%
        \hspace*{-\trianglewidth}%
        \makebox[\trianglewidth]{\(-\)}%
    }}%
}
\newcommand{\righttrianglebar}{%
    \mathrel{\makebox[\trianglewidth]{%
        \makebox[\trianglewidth]{\(-\)}%
        \hspace*{-\trianglewidth}%
        \makebox[\trianglewidth]{\(\vartriangleright\)}%
    }}%
}
\newcommand{\lefttriangleplus}{%
    \mathrel{\makebox[\trianglewidth]{%
        \makebox[\trianglewidth]{\(<\)}%
        \hspace*{-.333\pluswidth}%
        \raisebox{.3\height}{\clipbox{.3\width{} .3\height}{\(+\)}}%
    }}%
}
\newcommand{\righttriangleplus}{%
    \mathrel{\makebox[\trianglewidth]{%
        \raisebox{.3\height}{\clipbox{.3\width{} .3\height}{\(+\)}}%
        \hspace*{-.333\pluswidth}%
        \makebox[\trianglewidth]{\(>\)}%
    }}%
}
\begin{document}
\( A \vartriangleleft  B \qquad A \vartriangleright B \)

\( A \lefttrianglebar  B \qquad A \righttrianglebar  B \)

\( A \lefttriangleplus B \qquad A \righttriangleplus B \)
\end{document}

Addendum

@barbarabeeton pointed out that the triangle symbols with a bar exist as Unicode symbols, and are included in the STIX font. With the stix package, they can be obtained as in the following example.

\documentclass{article}
\usepackage{stix}
\begin{document}
\begin{tabular}{ll}
    \( A \vartriangleleft  B \) & \( A \vartriangleright B \) \\
    \( A \rsub             B \) & \( A \dsub             B \)
\end{tabular}
\end{document}

I think they look somewhat too large, though. Maybe they would be better scaled down a little, to fit better with the other triangle symbols.