3

I regularly need to represent mathematical intervals, and I find annoying to have to manually tweak the opened brackets (see MWE below).

Is there any way to :

  • define a new arrow tip that starts at the end of the line and extends further (thus exceeding the start and/or stop coordinates) ;
  • having this new arrow tip scalable, to avoid ugly rendering like the one of the MWE ;
  • bonus : having transparency group included by design in the code.

I've searched here, and finally found TikZ: Precisely controlling arrow tip position, but the syntax has changed and I'm not skilled enough to adapt it to the new one.

\documentclass{article}
\usepackage{tikz, amssymb}
\usetikzlibrary{arrows.meta}


\begin{document}
     \tikzset{
        interv oo/.style={{Bracket[reversed, sharp, length=.75ex]}-{Bracket[reversed, sharp, length=.75ex]}, shorten <=-.75ex, shorten >=-0.75ex},
        interv of/.style={{Bracket[reversed, sharp, length=.75ex]}-{Bracket[sharp, length=.75ex]}, shorten <=-.75ex},
        interv fo/.style={{Bracket[sharp, length=.75ex]}-{Bracket[reversed, sharp, length=.75ex]}, shorten >=-0.75ex},
        interv ff/.style={{Bracket[sharp, length=.75ex]}-{Bracket[sharp, length=.75ex]}},
        interv oi/.style={{Bracket[reversed, sharp, length=.75ex]}-, shorten <=-.75ex},
        interv io/.style={-{Bracket[sharp, length=.75ex]}, shorten >=-0.75ex},
        interv fi/.style={{Bracket[sharp, length=.75ex]}-},
        interv if/.style={-{Bracket[sharp, length=.75ex]}},
        label/.style={below, font=\footnotesize} }
    
    \begin{tikzpicture}
        \draw (-3,0) -- (3,0) node[anchor=south] {$\mathbb{R}$};
        \foreach \x in {-1,0,1} \draw (\x,2pt) -- (\x, -2pt) node[anchor=north] {$\x$};
        \begin{scope}[opacity=.5, transparency group]
            \draw[line width=3pt, blue, interv oo] (-1,0) -- (1,0);
        \end{scope}
    \end{tikzpicture}
\end{document}

enter image description here

Many thanks in advance.


Edit : here is what I finally came to. Seems satisfying enough to me. With usage of tabularray that was just put to my knowledge.

\documentclass[12pt,a4paper]{book}
\usepackage[utf8]{inputenc}
\usepackage[T1]{fontenc}
\usepackage{mathpazo}
\usepackage{geometry}
\usepackage[french]{babel}
\usepackage{tikz}
\usetikzlibrary{arrows.meta, arrows}
\usepackage{tabularray}
\frenchbsetup{StandardLists=true}   % Resolves conflict between babel and enumitem

\geometry{
    top=1.5cm, bottom=1.5cm, left=1cm, right=1cm,
    headheight=1cm, headsep=0.5cm,
    footskip=1cm}

\setlength{\parindent}{0mm} % No paragraphe indentation

\begin{document}
    
    \tikzset{
        interv oo/.style={{Bracket[reversed, sharp, length=0pt 2, sep=0pt -1.5]}-{Bracket[reversed, sharp, length=0pt 2, sep=0pt -1.5]}},
        interv of/.style={{Bracket[reversed, sharp, length=0pt 2, sep=0pt -1.5]}-{Bracket[sharp, length=0pt 2]}},
        interv fo/.style={{Bracket[sharp, length=0pt 2]}-{Bracket[reversed, sharp, length=0pt 2, sep=0pt -1.5]}},
        interv ff/.style={{Bracket[sharp, length=0pt 2]}-{Bracket[sharp, length=0pt 2]}},
        interv oi/.style={{Bracket[reversed, sharp, length=0pt 2, sep=0pt -1.5]}-},
        interv io/.style={-{Bracket[reversed, sharp, length=0pt 2, sep=0pt -1.5]}},
        interv fi/.style={{Bracket[sharp, length=0pt 2]}-},
        interv if/.style={-{Bracket[sharp, length=0pt 2]}},
        label/.style={below, font=\footnotesize} }
    
    Compléter le tableau suivant:

    \begin{tblr}{hlines, vlines,
                cell{2-5}{1,4}={mode=dmath},
                colspec={X[1,c,m] X[3,c,m] X[2.2,c,m] X[1.2,c,m]},
                rowsep=10pt,
                row{1} = {font=\bfseries, rowsep=4pt},
            }
        Inégalité & Phrase & Représentation graphique & Intervalle \\

        \ldots x\ldots & {$x$ est un réel\\ strictement supérieur à $-2$\\ et strictement inférieur à $4$} & \begin{tikzpicture}[scale=0.5, >=stealth, baseline={([yshift=-.5ex]current bounding box.center)}]
                % Bornes
                \def\xm{-4.9}
                \def\xM{-\xm}
                % Intervalle
                \draw[line width=4.5pt, green, interv oo] (-2,0) -- (4,0) ;
                % Repère
                \draw[thick,->] (\xm,0) -- (\xM,0) ;
                \foreach \x in {-4,...,4} { \draw (\x, -2mm) -- ++(0, 4mm) ; }
                \node[label] at (0,0) {0} ;
                \node[label] at (1,0) {1} ;
                \node[label, above, white] (0,0) {0} ; % Pour équilibrer le dessin verticalement
        \end{tikzpicture} & x\in\ldots \\
    
        & & \begin{tikzpicture}[scale=0.5, >=stealth, baseline={([yshift=-.5ex]current bounding box.center)}]
            % Bornes
            \def\xm{-4.9}
            \def\xM{-\xm}
            % Intervalle
            \draw[line width=2.5pt, red, interv of] (-2,0) -- (4,0) ;
            % Repère
            \draw[thick,->] (\xm,0) -- (\xM,0) ;
            \foreach \x in {-4,...,4} { \draw (\x, -2mm) -- ++(0, 4mm) ; }
            \node[label] at (0,0) {0} ;
            \node[label] at (1,0) {1} ;
            \node[label, above, white] (0,0) {0} ; % Pour équilibrer le dessin verticalement
        \end{tikzpicture} & \\
    
        & & \begin{tikzpicture}[scale=0.5, >=stealth, baseline={([yshift=-.5ex]current bounding box.center)}]
            % Bornes
            \def\xm{-4.9}
            \def\xM{-\xm}
            % Intervalle
            \draw[line width=2.5pt, orange, interv fo] (-2,0) -- (4,0) ;
            % Repère
            \draw[thick,->] (\xm,0) -- (\xM,0) ;
            \foreach \x in {-4,...,4} { \draw (\x, -2mm) -- ++(0, 4mm) ; }
            \node[label] at (0,0) {0} ;
            \node[label] at (1,0) {1} ;
            \node[label, above, white] (0,0) {0} ; % Pour équilibrer le dessin verticalement
        \end{tikzpicture} & \\
    
        & & \begin{tikzpicture}[scale=0.5, >=stealth, baseline={([yshift=-.5ex]current bounding box.center)}]
            % Bornes
            \def\xm{-4.9}
            \def\xM{-\xm}
            % Intervalle
            \draw[line width=2.5pt, yellow!70!orange, interv ff] (-2,0) -- (4,0) ;
            % Repère
            \draw[thick,->] (\xm,0) -- (\xM,0) ;
            \foreach \x in {-4,...,4} { \draw (\x, -2mm) -- ++(0, 4mm) ; }
            \node[label] at (0,0) {0} ;
            \node[label] at (1,0) {1} ;
            \node[label, above, white] (0,0) {0} ; % Pour équilibrer le dessin verticalement
        \end{tikzpicture} & \\
    
        & & \begin{tikzpicture}[scale=0.5, >=stealth, baseline={([yshift=-.5ex]current bounding box.center)}]
            % Bornes
            \def\xm{-4.9}
            \def\xM{-\xm}
            % Intervalle
            \begin{scope}[transparency group, opacity=.5]
                \draw[line width=2.5pt, cyan, interv oi] (-2,0) -- (\xM,0) ;
            \end{scope}
            % Repère
            \draw[thick,->] (\xm,0) -- (\xM,0) ;
            \foreach \x in {-4,...,4} { \draw (\x, -2mm) -- ++(0, 4mm) ; }
            \node[label] at (0,0) {0} ;
            \node[label] at (1,0) {1} ;
            \node[label, above, white] (0,0) {0} ; % Pour équilibrer le dessin verticalement
        \end{tikzpicture} & \\
    
        & & \begin{tikzpicture}[scale=0.5, >=stealth, baseline={([yshift=-.5ex]current bounding box.center)}]
            % Bornes
            \def\xm{-4.9}
            \def\xM{-\xm}
            % Intervalle
            \draw[line width=2.5pt, purple, interv io] (\xm,0) -- (4,0) ;
            % Repère
            \draw[thick,->] (\xm,0) -- (\xM,0) ;
            \foreach \x in {-4,...,4} { \draw (\x, -2mm) -- ++(0, 4mm) ; }
            \node[label] at (0,0) {0} ;
            \node[label] at (1,0) {1} ;
            \node[label, above, white] (0,0) {0} ; % Pour équilibrer le dessin verticalement
        \end{tikzpicture} & \\
    
        & & \begin{tikzpicture}[scale=0.5, >=stealth, baseline={([yshift=-.5ex]current bounding box.center)}]
            % Bornes
            \def\xm{-4.9}
            \def\xM{-\xm}
            % Intervalle
            \begin{scope}[transparency group, opacity=.5]
                \draw[line width=2.5pt, gray, interv fi] (-2,0) -- (\xM,0) ;
            \end{scope}
            % Repère
            \draw[thick,->] (\xm,0) -- (\xM,0) ;
            \foreach \x in {-4,...,4} { \draw (\x, -2mm) -- ++(0, 4mm) ; }
            \node[label] at (0,0) {0} ;
            \node[label] at (1,0) {1} ;
            \node[label, above, white] (0,0) {0} ; % Pour équilibrer le dessin verticalement
        \end{tikzpicture} & \\
    
        & & \begin{tikzpicture}[scale=0.5, >=stealth, baseline={([yshift=-.5ex]current bounding box.center)}]
            % Bornes
            \def\xm{-4.9}
            \def\xM{-\xm}
            % Intervalle
            \begin{scope}[transparency group, opacity=.5]
                \draw[line width=2.5pt, blue!50!white, interv if] (\xm,0) -- (4,0) ;
            \end{scope}
            % Repère
            \draw[thick,->] (\xm,0) -- (\xM,0) ;
            \foreach \x in {-4,...,4} { \draw (\x, -2mm) -- ++(0, 4mm) ; }
            \node[label] at (0,0) {0} ;
            \node[label] at (1,0) {1} ;
            \node[label, above, white] (0,0) {0} ; % Pour équilibrer le dessin verticalement
        \end{tikzpicture} & \\
    \end{tblr}

\end{document}

enter image description here

5
  • 1
    Regarding transparency group, see: tex.stackexchange.com/a/128758/8650 Nov 3 '21 at 10:36
  • Thanks, I'm aware of transparency group, but I think it's a burden to have to use it in a scope environment rather than specifying it as an option. In this case, I think it would be more simple to consider a line with its endings as a whole. May be I'm wrong, though !
    – natsirt
    Nov 3 '21 at 11:06
  • 1
    Nice question. I'd be interested in your final table :) so useful!
    – JeT
    Nov 3 '21 at 11:29
  • Hope you will be satisfied enough by my proposal.
    – natsirt
    Nov 3 '21 at 14:23
  • In a perfect world, a transparency group should not be needed for this. As it is, the line and arrow head is draw in two separate steps. This makes it possible to have different line width, color, line joint and caps, .... There is a small overlap(normally) between the line and arrow head, to avoid viewer artefacts(again not a perfect world). With transparency, this overlap can only be hidden with a transparency group. -and a transparency group is a scope option. Nov 3 '21 at 15:05
3

You can do that with the sep option(moves the arrow head away from the endpoint coordinate of the line) - it uses the same syntax as length. If you want absolute length of the head, you can change 0pt 1 back to .75ex (or maybe use em or pt for a horizontal distance)

\documentclass[tikz, border=1 cm]{standalone}
\usepackage{amssymb}
\usetikzlibrary{arrows.meta}
\begin{document}
     \tikzset{
        interv oo/.style={{Bracket[reversed, sharp, length=0pt 1, sep=0pt -1]}-{Bracket[reversed, sharp, length=0pt 1, sep=0pt -1]}},
}    
    \begin{tikzpicture}
        \draw (-3,0) -- (3,0) node[anchor=south] {$\mathbb{R}$};
        \foreach \x in {-1,0,1} \draw (\x,2pt) -- (\x, -2pt) node[anchor=north] {$\x$};
        \begin{scope}[opacity=.5, transparency group]
            \draw[line width=5pt, blue, interv oo] (-1,0) -- (1,0);
        \end{scope}
    \end{tikzpicture}
\end{document}

Line with brackets

1
  • 1
    Big thanks ! I will update my question with an example of what I finally wrote, taking advantage of your fine remark about the sep parameter.
    – natsirt
    Nov 3 '21 at 11:07
3

Nice question (+1)!

Unfortunately arrows are designed so (as far as I know), that given arrows lenght consider lenght of arrows heads too. This is in many cases very desired features, but in your and some similar cases some people wish that arrows head will start after (before) arrow lines.

Your work around with defining of arrows length and extend the arrow's line by this length is temporally only way to go. Maybe you should add dependence of arrows head length and needed lines extension from used arrow line thickens. For example something like this:

\documentclass[border=3mm]{standalone}
\usepackage{amssymb}
\usepackage{tikz}
\usetikzlibrary{arrows.meta}

\begin{document}
     \tikzset{
        interv oo/.style={{Bracket[reversed, length=0pt 2]}-{Bracket[reversed, length=0pt 2]}, shorten <=-2\pgflinewidth, shorten >=-2\pgflinewidth},
% I didn't check other definition
       label/.style={font=\footnotesize, below=#1},
        label/.default = {}
             }

    \begin{tikzpicture}
        \draw (-3,1) -- (3,1) node[above] {$\mathbb{R}$};
        \draw (-3,0) -- (3,0) node[above] {$\mathbb{R}$};
        \foreach \x in {-1,0,1}
        { 
        \draw (\x,1.1) -- ++ (0,-0.2) node[label=1.5ex] {$\x$};
        \draw (\x,0.1) -- ++ (0,-0.2) node[label=1.5ex] {$\x$};
        }
        \begin{scope}[opacity=.5, transparency group]
            \draw[line width=3pt, blue, interv oo] (-1,1) -- (1,1);
            \draw[line width=2pt, blue, interv oo] (-1,0) -- (1,0);
        \end{scope}
    \end{tikzpicture}

With above solution the size of arrows heads size is scaled proportional to line widths (what is pleasant features).

enter image description here

Of course it be interesting to have an option for arrows head, which will push them outside of arrows line.

Edit: An example of its use (in your case should be):

interv oo/.style={{Bracket[reversed, outside]}-{Bracket[reversed, outside]}},

Maybe author of the library or some other TikZ guru will provide such option, I'm able only suggest its name: outside :-) . But this is features request. You may write to GitHub.

2
  • 1
    The sep option do just that :o) Nov 3 '21 at 10:20
  • 1
    @hpekristiansen, thank you very much for info (and answer).
    – Zarko
    Nov 3 '21 at 12:05

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.