Menu

#482 [parabola] Better parabola operation

v1.0 (example)
closed-fixed
nobody
parabola (1)
5
2018-06-21
2018-05-04
Kpym
No

The curve

(0,0) parabola (1,1) 

is equivalent to

(0,0) .. controls (.5,0) and (0.8875,0.775) .. (1,1) 

but the exact parabola is

(0,0) .. controls (1/3,0) and (2/3,1/3) .. (1,1)

We can see in the code of pgfcorepathconstruct.code.tex at line 1297:

          {\pgfqpoint{.5\pgf@xc}{0\pgf@yc}}% found by trial and error
          {\pgfqpoint{.8875\pgf@xc}{.775\pgf@yc}}% found by trial and error

By the way there is no reason with bend option to draw a parabola using two cubic curves : any parabola can be drawn by a single quadratic (and so cubic) curve. You can check my answer at TeX.SX.

I think that bend=<point> should be interpreted as "the bend is over the x coordinate of the point". This is backward compatible when there exist a parabola that has a bend at the point. And in all other cases the current parabola operation is drawing a non parabola curve, so there is no need of backward compatibility.

Also, it will be good to add trough=<point> option.

Discussion

  • Stefan Pinnow

    Stefan Pinnow - 2018-06-19
    • summary: Better parabola operation --> [parabola] Better parabola operation
    • status: open --> closed-fixed
     
  • Stefan Pinnow

    Stefan Pinnow - 2018-06-19

    Many thanks for the hint. I can confirm this and also added the correct values for the "first" parabola point in the definition (see attached code).

    For the record: Finding better solutions also for the sin and cos functions with the bezierplot package was not successful as can also be seen in the attached code.

    For your suggestion to the improvement of the parabola functionality: I created feature request #117.

    %% <https://sourceforge.net/p/pgf/bugs/482/>
    % used PGFPlots v1.16
    \documentclass[border=5pt]{standalone}
    \usepackage{pgfplots}
        \pgfplotsset{
            compat=1.16,
            every axis/.append style={
                no markers,
                samples=101,
                clip=false,
            },
        }
    \makeatletter
    \def\pgfpathparabola#1#2{%
      {%
        \pgf@process{#2}% untransformed
        \pgf@xb=\pgf@x%
        \pgf@yb=\pgf@y%
        \pgf@process{#1}% untransformed
        \pgf@xc=\pgf@x%
        \pgf@yc=\pgf@y%
        \pgfutil@tempswatrue%
        \ifdim\pgf@xb=0pt\relax%
          \ifdim\pgf@yb=0pt\relax%
            \pgfutil@tempswafalse%
          \fi%
        \fi%
        {%
          \ifpgfutil@tempswa%
            \pgf@arccornersfalse
          \else%
          \fi%
          \pgfutil@tempswatrue%
          \ifdim\pgf@xc=0pt\relax%
            \ifdim\pgf@yc=0pt\relax%
              \pgfutil@tempswafalse%
            \fi%
          \fi%
          \ifpgfutil@tempswa
          {%
            \pgf@pt@x=\pgf@path@lastx%
            \pgf@pt@y=\pgf@path@lasty%
            \pgfpathcurveto%
    % -----------------------------------------------------------------------------
    %          % old solution
    %          {\pgfqpoint{.1125\pgf@xc}{.225\pgf@yc}}% found by trial and error
    %          {\pgfqpoint{.5\pgf@xc}{\pgf@yc}}% found by trial and error
    % -----------------------------------------------------------------------------
              % new exact solution
              {\pgfqpoint{.3333\pgf@xc}{.6667\pgf@yc}}%
              {\pgfqpoint{.6667\pgf@xc}{\pgf@yc}}%
    % -----------------------------------------------------------------------------
              {\pgfqpoint{\pgf@xc}{\pgf@yc}}%
          }%
          \fi%
        }%
        \ifpgfutil@tempswa%
          \pgf@xc=\pgf@xb%
          \pgf@yc=\pgf@yb%
          {%
            \pgf@pt@x=\pgf@path@lastx%
            \pgf@pt@y=\pgf@path@lasty%
            \pgfpathcurveto%
    % -----------------------------------------------------------------------------
    %          % old solution
    %          {\pgfqpoint{.5\pgf@xc}{0\pgf@yc}}% found by trial and error
    %          {\pgfqpoint{.8875\pgf@xc}{.775\pgf@yc}}% found by trial and error
    % -----------------------------------------------------------------------------
              % new exact solution
              {\pgfqpoint{.3333\pgf@xc}{0\pgf@yc}}%
              {\pgfqpoint{.6667\pgf@xc}{.3333\pgf@yc}}%
    % -----------------------------------------------------------------------------
              {\pgfqpoint{\pgf@xc}{\pgf@yc}}%
          }%
        \fi%
      }%
    }
    \makeatother
    \usepackage{bezierplot}
    \begin{document}
    \begin{tikzpicture}
        \begin{axis}
            % real solution
            \addplot+ [blue,domain=0:1] {x^2};
            % tikz function call (current implementation)
            \draw [red,dashed]
                (0,0) parabola (1,1);
            % corresponds to (old) implementation
            % (gives the same result as previous call with old implementation)
            \draw [red!50,loosely dashed]
                (0,0) .. controls (.5,0) and (0.8875,0.775) .. (1,1);
    
            % result from package "bezierplot" which gives following command prompt result
            \draw [green,densely dotted] \bezierplot[0][1] {x^2};
            \draw [green!50,dotted]
                (0,0) .. controls (1/3,0) and (2/3,1/3) .. (1,1);
        \end{axis}
    \end{tikzpicture}
    \begin{tikzpicture}
        \begin{axis}
            % real solution
            \addplot+ [blue,domain=0:1] {-(x-1)^2 + 1};
    
            % tikz function call (current implementation)
            % (this calls the "lower" settings of the implementation)
            \draw [red!50!black,densely dashed]
                (1,1) parabola (0,0);
            % (this calls the "upper" settings of the implementation)
            \draw [red,dashed]
                (0,0) parabola [bend at end] (1,1);
            % corresponds to (old) implementation
            % (gives the same result as previous call with old implementation)
            \draw [red!50,loosely dashed]
                (0,0) .. controls (.1125,.225) and (0.5,1) .. (1,1);
    
            % result from package "bezierplot" which gives following command prompt result
            \draw [green,densely dotted] \bezierplot[0][1] {-(x-1)^2 + 1};
            \draw [green!50,dotted]
                (0,0) .. controls (1/3,2/3) and (2/3,1) .. (1,1);
        \end{axis}
    \end{tikzpicture}
    \begin{tikzpicture}
        \begin{axis}
            % real solution
            \addplot+ [domain=0:pi/2] {sin(deg(x))};
    
            % tikz function call (current implementation)
            \draw [red,dashed]
                (0,0) sin (pi/2,1);
            % corresponds to implementation (should give same result as previous call)
            \draw [red!50,loosely dashed,xscale=pi/2]
                (0,0) .. controls (0.31831,0.5) and (0.63503,1) .. (1,1);
    
            % result from package "bezierplot" which gives following command prompt result
            \draw [green,densely dotted] \bezierplot[0][pi/2] {sin(x)};
            \draw [green!50,dotted,xscale=pi/2]
                (0,0) .. controls (0.3501,0.55) and (0.6548,1) .. (1,1);
        \end{axis}
    \end{tikzpicture}
    \begin{tikzpicture}
        \begin{axis}
            % real solution
            \addplot+ [domain=0:pi/2] {cos(deg(x))};
    
            % tikz function call (current implementation)
            \draw [red,dashed]
                (0,1) cos (pi/2,0);
            % corresponds to implementation (should give same result as previous call)
            \draw [red!50,loosely dashed,xscale=pi/2]
                (0,1) .. controls (0.36497,1) and (0.68169,0.5) .. (1,0);
    
            % result from package "bezierplot" which gives following command prompt result
            \draw [green,densely dotted] \bezierplot[0][pi/2] {cos(x)};
            \draw [green!50,dotted,xscale=pi/2]
                (0,1) .. controls (0.3452,1) and (0.6499,0.55) .. (1,0);
        \end{axis}
    \end{tikzpicture}
    \end{document}
    
     
  • Kpym

    Kpym - 2018-06-20

    If you want a "better" approximation for sin you can keep 0.31831 which is 1/pi but you can replace 0.63503 by 0.63662 which is 2/pi. And the corresponding values for cos are 0.36338 which is 1-2/pi and 0.68169 which is 1-1/pi. But it is not clear that this is a "better" approximation ... it depends how you define "better".

     
  • Stefan Pinnow

    Stefan Pinnow - 2018-06-21

    Regarding the sin/cos improvement see patch request #26.