6

I want to have a coordinate like coordinate[pos=0.675](X) It seems not to works. What have I to do?

enter image description here

\documentclass[marigin=5pt, tikz]{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}[]
\draw[] (0,0) -- (3,5) coordinate[pos=0.675, label=N](N) node{works};  
\draw[blue] (0,0) arc (0:75:4) coordinate[pos=0.675, label=A](A) node{works too};  
\draw[red, shift={(2,0)}](0,0) parabola [parabola height =3cm](4,0) coordinate[pos=0.675, label=P] (P) node{works not}; 
\end{tikzpicture}
\end{document}

2 Answers 2

6

First of all, your observation is correct. Second, this is by far not the only path construction that does not have a "timer". For instance, this is also true for the sin and cos path constructions, and of course plots.

\documentclass[margin=5pt, tikz]{standalone}
\usepackage{pifont}
\usepackage{amssymb}
\begin{document}
\begin{tikzpicture}[]
\draw[] (0,0) -- (3,5) coordinate[pos=0.675, label=N](N)
 node[circle,draw]{\ding{51}};  
\draw[blue] (0,0) arc (0:75:4) coordinate[pos=0.675, label=A](A) node[circle,draw]{\ding{51}};  
\draw[red, shift={(2,0)}](0,0) parabola [parabola height =3cm](4,0) 
coordinate[pos=0.675, label=P] (P) node[circle,draw]{\ding{55}}; 
\draw[cyan, shift={(6,2)}](0,0) sin(2,1)  
coordinate[pos=0.675, label=Q] (Q) node[circle,draw]{\ding{55}}; 
\draw[cyan, shift={(6,4.5)}](0,0) cos(2,-1)  
coordinate[pos=0.675, label=R] (R) node[circle,draw]{\ding{55}}; 
\end{tikzpicture}
\end{document}

enter image description here

In fact, the pos syntax only really works for

  1. straight lines (\tikz@timer@line),
  2. single Bezier curve stretches (\tikz@timer@curve), and
  3. arcs (\tikz@timer@arc).

So what is going on here? Internally TikZ works with a "timer", the relevant macros from tikz.code.tex are \tikz@timer (as well as \tikz@timer@start and \tikz@timer@end). As far as I can see, only \tikz@timer@line (with the subcases \tikz@timer@hvline and \tikz@timer@vhline), \tikz@timer@curve and \tikz@timer@arc are implemented. If your question is whether or not one could add a timer for parabolae, sines and cosines, the answer is likely affirmative, but given the complexity of the other timers in tikz.code.tex the actual realization will be messy.

So, in order to answer the question

How to place a coordinate at parabola-path-position?

I recommend looking at the decorations.markings library.

\documentclass[margin=5pt, tikz]{standalone}
\usetikzlibrary{decorations.markings}
\begin{document}
\begin{tikzpicture}
\draw[red,postaction={decorate,
    decoration={markings,
    mark=at position 0.675 with {\coordinate[label=P](P);}}}]
(0,0) parabola [parabola height =3cm](4,0)  node[below]{works}; 
\end{tikzpicture}
\end{document}

enter image description here

(If you encounter dimension too large errors with this decoration, some of them can be cured with use fpu reciprocal that ships with circuitikz.)

As a side remark, if you use pgfplots the pos key does work for one-dimensional plots, even for pretty complex ones.

5

As the other answer explains, for parabola no timer is set up, not even the line-to timer (as for the rectangle path operator).

Patching \tikz@parabola@semifanal

However, we can hack one in by patching \tikz@parabola@semifinal. That's the TikZ macro that finalizes the parabola operator. This however also breaks forwards compatibility. The lines commented with % %% Timer are the ones I added. These are needed

  • to save the start (\edef\tikz@timer@start{…}),
  • to save the “bend” (\xdef\tikz@timer@middle{…}) and
  • to save the end of the parabola (\edef\tikz@timer@end) as well as
  • to actually instruct TikZ to use our custom timer (\let\tikz@timer\tikz@timer@parabola) which I piggy-back in \tikz@parabola@b to not have to deal with the \expandafters.

New timer for parabolas

The new timer \tikz@timer@parabola uses these tree saved points (we might be able to use \tikz@parabola@b again but then we also had to do all these calculations again).

The timer is set up in a way that the bend is always at pos = 0.5, this means however that when we draw only one side of the parabola, half the points collapse into the bend (see the second example).

Since PGF's parabolas are actually drawn as arcs we can use \pgftransformcurveattime, the control points are calculated the same as they are for drawing the parabolas.

Code

\documentclass[tikz]{standalone}
\makeatletter
\def\tikz@parabola@semifinal#1{%
    \tikz@flush@moveto%
    % Save original start:
    \edef\tikz@timer@start{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}% %% Timer: save start position
    \pgf@xb=\tikz@lastx%
    \pgf@yb=\tikz@lasty%
    \tikz@make@last@position{#1}%
    \edef\tikz@timer@end{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}% %% Timer: save target position
    \pgf@xc=\tikz@lastx%
    \pgf@yc=\tikz@lasty%
    \begingroup% now calculate bend:
        \let\tikz@after@path\pgfutil@empty%
        \expandafter\tikzset\expandafter{\tikz@parabola@option}%
        \tikz@lastxsaved=\tikz@parabola@bend@factor\tikz@lastx%
        \tikz@lastysaved=\tikz@parabola@bend@factor\tikz@lasty%
        \advance\tikz@lastxsaved by\pgf@xb%
        \advance\tikz@lastysaved by\pgf@yb%
        \advance\tikz@lastxsaved by-\tikz@parabola@bend@factor\pgf@xb%
        \advance\tikz@lastysaved by-\tikz@parabola@bend@factor\pgf@yb%
        \expandafter\tikz@make@last@position\expandafter{\tikz@parabola@bend}%
        \xdef\tikz@timer@middle{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}% %% Timer: save bend postion
        % Calculate delta from bend
        \advance\pgf@xc by-\tikz@lastx%
        \advance\pgf@yc by-\tikz@lasty%
        % Ok, now calculate delta to bend
        \advance\tikz@lastx by-\pgf@xb%
        \advance\tikz@lasty by-\pgf@yb%
        \xdef\tikz@parabola@b{{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}{\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}%
            \noexpand\let\noexpand\tikz@timer\noexpand\tikz@timer@parabola}% %% Timer added
    \expandafter\endgroup%
    \expandafter\expandafter\expandafter\pgfpathparabola\expandafter\tikz@parabola@b%
    \expandafter\tikz@scan@next@command\tikz@after@path%
}%
\def\tikz@timer@parabola{% following calculations, see \def of \pgfpathparabola in pgfcorepathconstruct.code.tex (l. 1261)
    \ifdim\tikz@time pt<.5pt\relax % first part
        \pgf@process{\tikz@timer@middle}%
        \pgf@xc\pgf@x\pgf@yc\pgf@y
        \pgf@xb\pgf@x\pgf@yb\pgf@y
        \pgf@process{\tikz@timer@start}%
        \advance\pgf@xc-\pgf@x\[email protected]\pgf@xc
        \advance\pgf@xc\pgf@x                 % = start_x + .1125 (middle_x - start_x)
        \advance\pgf@yc-\pgf@y\[email protected]\pgf@yc
        \advance\pgf@yc\pgf@y                 % = start_y + .225 (middle_y - start_y)
        \advance\pgf@xb\pgf@x\[email protected]\pgf@xb % = .5 (middle_x + start_x) = start_x + .5 (middle_x - start_x)
        \pgf@xa=\tikz@time pt%
        \pgf@xa=2\pgf@xa                      % = 2 * \tikz@time
        \edef\tikz@marshall{\noexpand\pgftransformcurveattime{\strip@pt\pgf@xa}{\noexpand\tikz@timer@start}%
                           {\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}%
                           {\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}%
                           {\noexpand\tikz@timer@middle}}%
        \tikz@marshall
    \else % second part
        \pgf@process{\tikz@timer@end}%
        \pgf@xc\pgf@x
        \pgf@xb\pgf@x
        \pgf@yb\pgf@y
        \pgf@process{\tikz@timer@middle}%
        \advance\pgf@xc\pgf@x\[email protected]\pgf@xc % = .5 (end_x + middle_x) = middle_x + .5 (end_x - middle_x)
        \advance\pgf@xb-\pgf@x\[email protected]\pgf@xb
        \advance\pgf@xb\pgf@x                 % = middle_x + .8875 (end_x - middle_x)
        \advance\pgf@yb-\pgf@y\[email protected]\pgf@yb
        \advance\pgf@yb\pgf@y                 % = middle_y + .775 (end_y - middle_y)
        \pgf@xa=\tikz@time pt%
        \advance\[email protected]%
        \pgf@xa=2\pgf@xa                      % = 2 (\tikz@zime - .5)
        \edef\tikz@marshall{\noexpand\pgftransformcurveattime{\strip@pt\pgf@xa}{\noexpand\tikz@timer@middle}%
                           {\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@y}}%
                           {\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}%
                           {\noexpand\tikz@timer@end}}%
        \tikz@marshall
    \fi}
\makeatother
\begin{document}
\begin{tikzpicture}
    \draw[]     (0,0) --  (3,5)    coordinate[pos=0.675, label=N] (N) node {works};  
    \draw[blue] (0,0) arc (0:75:4) coordinate[pos=0.675, label=A] (A) node {works too};  
    \draw[red, shift={(2,0)}](0,0) parabola [parabola height =3cm] (4,0)
                                   coordinate[pos=0.4,   label=P] (P) node {works now}; 
\end{tikzpicture}
\begin{tikzpicture}
    \draw[help lines]  (-2.25,-1.25) grid (2.25,3.25);
    \draw              ( 2,-1) parabola bend (0,0) (-1,3);
    \draw[ultra thick] (-2,-1) parabola bend (0,0) ( 1,3) foreach \pos in {1,...,4,6,7,...,9}
                               {node[pos=\pos/10,sloped,fill=white,font=\tiny,inner sep=+0pt]{\pos}};
\end{tikzpicture}
\begin{tikzpicture}
    \draw[help lines, overlay] (-3,-3) grid (1.25, 1);
    \draw                      (-2,-2) parabola (1,0)
         foreach \pos in {0,1,...,10} {node[pos=\pos/10, alias=@, inner sep=+1pt,
            append after command={(@) edge node[pos=1,font=\tiny,inner sep=+0pt,anchor=-18*\pos+90]
               {\pos} ++(-18*\pos+270:.5cm) }] {.}};
\end{tikzpicture}
\end{document}

Output

two different parabolas half a parabola

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .