Quadratic Bézier curves

Help
x42bn6
2009-04-07
2013-05-29
  • x42bn6

    x42bn6 - 2009-04-07

    Hey all, loving the package, but does anyone know how to make a quadratic Bézier curve?

    I just want to construct a parabola but it is at an awkward position and requires me to do lots of manual mathematics if I want to use the parabola construct (scaling, rotation, translation and back again, plus I need to calculate the transformations myself) - it would be a lot easier if there were a way to convert the cubic Bézier implementation that TikZ currently has into a quadratic one.

    Thanks in advance.

     
    • Mark Wibrow

      Mark Wibrow - 2009-04-08

      Hi,

      The following does it (I think) by converting the quadratic bezier to a cubic (this was the easiest way I could think of doing it). You use 'control' (not 'controls') in the curve spec. and TikZ automatically does the rest.
      I have absolutely no time to test this thoroughy, so if there is some problem, just post here and I will (eventually) try and improve it.

      Regards

      Mark

      \documentclass{article}
      \usepackage{tikz}

      \begin{document}

      \makeatletter

      \def\pgfpathquadraticcurveto#1#2{%
          \pgfextract@process\pgfpoint@qbc@start{%
              \pgf@x=\pgf@path@lastx%
              \pgf@y=\pgf@path@lasty%
          }%
          \pgfextract@process\pgfpoint@cbc@controla{%
              \pgfpointadd{\pgfpoint@qbc@start}{%
                  \pgfpointdiff{\pgfpoint@qbc@start}{#1}%
                  \pgf@x=0.666666\pgf@x%
                  \pgf@y=0.666666\pgf@y%
              }%
          }%
          \pgfextract@process\pgfpoint@cbc@controlb{%
              \pgfpointadd{\pgfpoint@cbc@controla}{%
                  \pgfpointdiff{\pgfpoint@qbc@start}{#2}%
                  \pgf@x=0.333333\pgf@x%
                  \pgf@y=0.333333\pgf@y%
              }%
          }%
          \pgfpathcurveto{\pgfpoint@cbc@controla}{\pgfpoint@cbc@controlb}{#2}%
      }%

      \newif\iftikz@curve@quadratic

      \def\tikz@cureveto@@double ntrol{%
          \pgfutil@ifnextchar s{\tikz@curve@quadraticfalse\tikz@curveto@@@double}{%
              \tikz@curve@quadratictrue\tikz@curveto@@@double s}%
      }
      \def\tikz@curveto@@@double s#1{%
        \tikz@scan@one@point\tikz@curveA#1%
      }

      \def\tikz@curveC#1{%
        \tikz@make@last@position{#1}%
        \edef\tikz@curve@third{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}%
        {%
          \tikz@lastxsaved=\tikz@lastx%
          \tikz@lastysaved=\tikz@lasty%
          \tikz@make@last@position{\tikz@curve@second}%
          \xdef\tikz@curve@second{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}%
        }%
        %
        % Start recalculating things in case start and end are shapes.
        %
        % First, the start:
        \ifx\tikz@moveto@waiting\relax%
        \else%
          \pgf@process{\pgfpointshapeborder{\tikz@moveto@waiting}{\tikz@curve@first}}%
          \edef\tikz@timer@start{\noexpand\pgfqpoint{\the\pgf@x}{\the\pgf@y}}%
          \pgfpathmoveto{\pgfqpoint{\pgf@x}{\pgf@y}}%
        \fi%
        \let\tikz@timer@cont@one=\tikz@curve@first%
        \let\tikz@timer@cont@two=\tikz@curve@second%   
        % Second, the end:
        \iftikz@shapeborder%
          % ok, target is a shape. recalculate third
          {%
            \pgf@process{\pgfpointshapeborder{\tikz@shapeborder@name}{\tikz@curve@second}}%
            \tikz@make@last@position{\pgfqpoint{\pgf@x}{\pgf@y}}%
            \edef\tikz@curve@third{\noexpand\pgfqpoint{\the\tikz@lastx}{\the\tikz@lasty}}%
            \tikz@curve@do%
            \global\let\tikz@timer@end@temp=\tikz@curve@third% move out of group
          }%
          \let\tikz@timer@end=\tikz@timer@end@temp%
          \edef\tikz@moveto@waiting{\tikz@shapeborder@name}%   
        \else%
          \tikz@curve@do%
          \let\tikz@timer@end=\tikz@curve@third
          \let\tikz@moveto@waiting=\relax%
        \fi%
        \let\tikz@timer=\tikz@timer@curve% 
        \tikz@scan@next@command%
      }

      \def\tikz@curve@do{%
          \iftikz@curve@quadratic%
              \pgfpathquadraticcurveto{\tikz@curve@first}{\tikz@curve@third}%
          \else
              \pgfpathcurveto{\tikz@curve@first}{\tikz@curve@second}{\tikz@curve@third}%
          \fi%
      }%

      \makeatother

      \begin{tikzpicture}
          \draw [help lines] (0,0) grid (3,2);
          \draw [red]   (0,0) .. controls (0,2) and (3,2) .. (3,0);
          \draw [green] (0,0) .. controls (1.5,2) .. (3,0);
          \draw [blue]  (0,0) .. control  (1.5,2) .. (3,0);
      \end{tikzpicture}
      \end{document}

       

Get latest updates about Open Source Projects, Conferences and News.

Sign up for the SourceForge newsletter:





No, thanks