10

The at position=<value> syntax for decorations obviously makes the positioning of the decorations dependent on the path length:

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

\begin{document}

\begin{tikzpicture}[decoration={
  markings,
  mark=at position 0.4
  with {\node[draw=blue,fill=blue,inner sep=2pt] {};},
  mark=at position 0.6
  with {\node[circle,draw=green,fill=green,inner sep=2pt] {};}
}
]
\node (A) {A};
\node at (1,0) (B) {B};
\draw[magenta,postaction=decorate] (A) .. controls(0.25,2) and (0.75,-2) .. (B);
\begin{scope}[xshift=3cm]
\node (A) {A};
\node at (1,0) (B) {B};
\draw[magenta,postaction=decorate] (A) .. controls(0.25,4) and (0.75,-4) .. (B);
\end{scope}
\begin{scope}[xshift=6cm]
\node (A) {A};
\node at (1,0) (B) {B};
\draw[magenta,postaction=decorate] (A) .. controls(0.25,7) and (0.75,-7) .. (B);
\end{scope}
\end{tikzpicture}

\end{document}

enter image description here

Since the three magenta paths have increasing length, the markings will be farther apart from each other. Is there a way to place both decorations such that the distance along the path between them remains constant (i.e., placing both decorations at, let's say, half the path but guaranteeing that they will always be 50pt away from each other along the path)?

13

Use \pgfdecoratedpathlength to calculate exact, absolute distances:

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

\begin{document}

\begin{tikzpicture}[decoration={
  markings,
  mark=at position 0.5*\pgfdecoratedpathlength-25pt
  with {\node[draw=blue,fill=blue,inner sep=2pt] {};},
  mark=at position 0.5*\pgfdecoratedpathlength+25pt
  with {\node[circle,draw=green,fill=green,inner sep=2pt] {};}
}
]
\node (A) {A};
\node at (1,0) (B) {B};
\draw[magenta,postaction=decorate] (A) .. controls(0.25,2) and (0.75,-2) .. (B);
\begin{scope}[xshift=3cm]
\node (A) {A};
\node at (1,0) (B) {B};
\draw[magenta,postaction=decorate] (A) .. controls(0.25,4) and (0.75,-4) .. (B);
\end{scope}
\begin{scope}[xshift=6cm]
\node (A) {A};
\node at (1,0) (B) {B};
\draw[magenta,postaction=decorate] (A) .. controls(0.25,7) and (0.75,-7) .. (B);
\end{scope}
\end{tikzpicture}

\end{document}

compiled example

5

Steps:

  • Get the total length of the path with the help of the /pgf/decoration/mark info/distance from start key
    • Save this in \@totallength and make it global
    • at position 1 works not every time (as previously found out on TeX.sx), so a very short distance from the end is used; here -.01pt worked, -.001pt didn’t for the first path
  • Use .5*\@totallength-25pt for the first node and
  • use .5*\@totallength+25pt for the second

Code

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{decorations.markings}
\makeatletter
\tikzset{%
    decorate me/.style={
    decoration={
        markings,
        mark=at position -.01pt with {%
            \pgfkeysgetvalue{/pgf/decoration/mark info/distance from start}\@totallength
            \global\let\@totallength\@totallength
        },
        mark=at position .5*\@totallength-25pt with {\node[draw=blue,fill=blue,inner sep=2pt] {};},
        mark=at position .5*\@totallength+25pt with {\node[circle,draw=green,fill=green,inner sep=2pt] {};}
    },
    postaction=decorate
}
}
\makeatother
\begin{document}

\begin{tikzpicture}
\node (A) {A}; \node at (1,0) (B) {B};
\draw[magenta, decorate me] (A) .. controls(0.25,2) and (0.75,-2) .. (B);
\begin{scope}[xshift=3cm]
\node (A) {A}; \node at (1,0) (B) {B};
\draw[magenta, decorate me] (A) .. controls(0.25,4) and (0.75,-4) .. (B);
\end{scope}
\begin{scope}[xshift=6cm]
\node (A) {A}; \node at (1,0) (B) {B};
\draw[magenta, decorate me] (A) .. controls(0.25,7) and (0.75,-7) .. (B);
\end{scope}
\end{tikzpicture}
\end{document}

Output

enter image description here

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.