Help
x42bn6
2009-04-07
2013-05-29
• 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.

• 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

\pgfextract@process\pgfpoint@qbc@start{%
\pgf@x=\pgf@path@lastx%
\pgf@y=\pgf@path@lasty%
}%
\pgfextract@process\pgfpoint@cbc@controla{%
\pgfpointdiff{\pgfpoint@qbc@start}{#1}%
\pgf@x=0.666666\pgf@x%
\pgf@y=0.666666\pgf@y%
}%
}%
\pgfextract@process\pgfpoint@cbc@controlb{%
\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}%
}%

\def\tikz@cureveto@@double ntrol{%
}
\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{%
\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}

No, thanks