1

I would like to place text exactly centred over an exactly specified point on a highly complex path as shown in this Figure:

enter image description here

I have developed my example by specifying the point at 0.1 from the beginning of path and adding a mark to it:

\documentclass[border=1cm]{standalone}

\usepackage{tikz}
\usetikzlibrary{decorations.text, decorations.markings}

\begin{document}
\begin{tikzpicture}

\coordinate (A) at (0,0);
\coordinate (B) at (1, 3);
\coordinate (C) at (2, -1);
\coordinate (D) at (3, 0.5);

%placement of mark                                                                                                                                                                                          
\draw plot [smooth] coordinates { (A) (B) (C) (D) };
\path [
   postaction={decorate},
     decoration={
       markings,
       mark = at position 0.1 with {\fill[red] circle[radius=0.2cm];}
  }
] plot [smooth] coordinates { (A) (B) (C) (D) };

%placement of text                                                                                                                                                                                          
\path [
   postaction={decorate},
     decoration={
       text along path,
       raise=0.4cm,
       text align/left indent = {0.1\dimexpr\pgfdecoratedpathlength\relax},
       text={here!!}
  }
] plot [smooth] coordinates { (A) (B) (C) (D) };

\end{tikzpicture}
\end{document}

The output is

enter image description here

To centre the text over the mark I would only need to replace left with center in text align/left indent = {0.1\dimexpr\pgfdecoratedpathlength\relax}. Then everything would be perfect! Unfortunately after this change the example no longer compiles.

How to fix this problem?

Viesturs
  • 7,895

1 Answers1

2

Just add the text to the markings. (You need transform shape to rotate it to become typeset along the tangent at that point.)

\documentclass[border=1cm]{standalone}

\usepackage{tikz}
\usetikzlibrary{decorations.markings}

\begin{document}
\begin{tikzpicture}

\coordinate (A) at (0,0);
\coordinate (B) at (1, 3);
\coordinate (C) at (2, -1);
\coordinate (D) at (3, 0.5);

%placement of mark                                                                                                                                                                                          
\draw plot [smooth] coordinates { (A) (B) (C) (D) };
\path [
   postaction={decorate},
     decoration={
       markings,
       mark = at position 0.1 with {\fill[red] circle[radius=0.2cm];
       \node[transform shape] at (0,0.5) {here!};}
  }
] plot [smooth] coordinates { (A) (B) (C) (D) };

%placement of text                                                                                                                                                                                          
\end{tikzpicture}
\end{document}

enter image description here

Alternatively you can just subtract 50% of the width from the shift. (Note that I use in this code \pgfmathsetmacro{\mywidth}{5*width("here!!")} because 5*0.1=1/2 so in 0.1\dimexpr\pgfdecoratedpathlength-\mywidth pt\relax we subtract 50% of the width of the text.)

\documentclass[border=1cm]{standalone}

\usepackage{tikz}
\usetikzlibrary{decorations.text, decorations.markings}

\begin{document}
\begin{tikzpicture}

\coordinate (A) at (0,0);
\coordinate (B) at (1, 3);
\coordinate (C) at (2, -1);
\coordinate (D) at (3, 0.5);

%placement of mark                                                                                                                                                                                          
\draw plot [smooth] coordinates { (A) (B) (C) (D) };
\path [
   postaction={decorate},
     decoration={
       markings,
       mark = at position 0.1 with {\fill[red] circle[radius=0.2cm];}
  }
] plot [smooth] coordinates { (A) (B) (C) (D) };

\pgfmathsetmacro{\mywidth}{5*width("here!!")}
%placement of text                                                                                                                                                                                          
\path [
   postaction={decorate},
     decoration={
       text along path,
       raise=0.4cm,
       text align/left indent ={0.1\dimexpr\pgfdecoratedpathlength-\mywidth pt\relax},
       text={here!!}
  }
] plot [smooth] coordinates { (A) (B) (C) (D) };

\end{tikzpicture}
\end{document}

enter image description here

Some style for that. (Note that I use the hobby path simply because otherwise there can be dimension too large problems. These problems have nothing to do with the specifics of the style, it is a general problem of decorated paths.)

\documentclass[tikz,border=1cm]{standalone}
\usetikzlibrary{decorations.text, decorations.markings,hobby}
\tikzset{move text/.style args={#1 to pos #2}{%
postaction={decorate,
/utils/exec=\pgfmathsetmacro{\mywidth}{(0.5/#2)*width("#1")},
     decoration={
       text along path,
       raise=0.4cm,
       text align/left indent={#2\dimexpr\pgfdecoratedpathlength-\mywidth pt\relax},
       text={here!!}
  }}
}}
\begin{document}
\foreach \X in {0.1,0.2,...,0.9}
{\begin{tikzpicture}[]
\path[use as bounding box] (-2,-1) rectangle (4,4);
\coordinate (A) at (0,0);
\coordinate (B) at (1, 3);
\coordinate (C) at (2, -1);
\coordinate (D) at (3, 0.5);

\draw [
   postaction={decorate,
     decoration={
       markings,
       mark = at position \X\space with {\fill[red] circle[radius=0.2cm];}
  }},move text={here!!} to pos \X,
] plot [smooth,hobby] coordinates { (A) (B) (C) (D) };

\end{tikzpicture}}
\end{document}

enter image description here

  • The marking is used in this example to highlight the exact point. What if I do not need any marking? – Viesturs Jun 25 '19 at 16:16
  • @Viesturs Just drop \fill[red] circle[radius=0.2cm];. –  Jun 25 '19 at 16:18
  • It turns out we are using a markings loophole to place text in a way impossible with text decorations. – Viesturs Jun 25 '19 at 16:20
  • @Viesturs I added a second proposal in which you just subtract 50% of the width of the text from the shift. This does work with the text decorations. –  Jun 25 '19 at 16:22
  • Your solution fails if position is changed from 0.1 to something else. How do you get 5 in \pgfmathsetmacro{\mywidth}{5*width("here!!")}. You need to explain that 0.1 is a factor to 5 to produce 0.5. If some other position is used the new coefficient is calculated as 0.5/coeff. – Viesturs Jun 27 '19 at 16:18
  • @Viesturs I took 5 because you multiply everything with 0.1 and 0.1*5=1/2. One could write a simple style that does arbitrary positions. –  Jun 27 '19 at 16:22
  • Could you please explain this in your answer? – Viesturs Jun 27 '19 at 16:27
  • @Viesturs I added a style that does all the computations, and also added the explanation. –  Jun 27 '19 at 16:35
  • Thanks for your effort. – Viesturs Jun 27 '19 at 16:39