# Short Version

I want to do some fairly complicated coordinate math to make a notional diagram but would like to use pgfplots since I have used it elsewhere in my document and want the axis styles (which I personally prefer) to match.

I do the coordinate math in tikzmath,

\begin{tikzpicture}
\tikzmath{
coordinate \c;
\c0 = (0.0,0.0);
\c1 = (1.0,1.0);
}
\begin{axis}[
xmin=0,
xmax=1,
ymin=0,
ymax=1]
\draw (\c0) -- (\c1);
\coordinate [label=$\c1$] (foo) at (0.5,0.5);
\end{axis}
\end{tikzpicture}


but when I render this, the coordinates are not in the axis coordinate system:

I would like instead to have the following plot:

Is there a way to convert to the axis coordinate system from whatever coordinate system tikzmath uses?

# Long Version

I am trying to make a plot demonstrating quadratic interpolation through a few points. Specifically, I want to show how (unlike cubic interpolation) the shape of the entire curve can be wholly determined by the derivative at one point (I choose the first point). I want to draw this curve for different values of \d0 so I figured I could make use of the cubic control points that TikZ provides (through controls) and calculate what those control points should be.

\begin{tikzpicture}
\tikzmath{
% coordinates
coordinate \p;
\p0 = (0.0,0.0);
\p1 = (0.2,0.6);
\p2 = (0.6,0.9);
\p3 = (1.0,1.0);
% dy/dx values
real \d;
\d0 = 1.0;
\d1 = 2.0 * (\py1 - \py0) / (\px1 - \px0) - \d0;
\d2 = 2.0 * (\py2 - \py1) / (\px2 - \px1) - \d1;
\d3 = 2.0 * (\py3 - \py2) / (\px3 - \px2) - \d2;
% https://math.stackechange.com/a/336679/475643
% quadratic control points
coordinate \q;
\q1 = ({(\px0 + \px1) / 2.0}, {\py0 + \d0 * (\px1 - \px0) / 2.0});
\q2 = ({(\px1 + \px2) / 2.0}, {\py1 + \d1 * (\px2 - \px1) / 2.0});
\q3 = ({(\px2 + \px3) / 2.0}, {\py2 + \d2 * (\px3 - \px2) / 2.0});
% cubic control points, lefthand side
coordinate \s;
\s1 = {(2 / 3 * \q1) + (1 / 3 * \p0)};
\s2 = {(2 / 3 * \q2) + (1 / 3 * \p1)};
\s3 = {(2 / 3 * \q3) + (1 / 3 * \p2)};
% cubic control points, righthand side
coordinate \r;
\r1 = {(2 / 3 * \q1) + (1 / 3 * \p1)};
\r2 = {(2 / 3 * \q2) + (1 / 3 * \p2)};
\r3 = {(2 / 3 * \q3) + (1 / 3 * \p3)};
}
\begin{axis}[
xmin=0,
xmax=60,
ymin=0,
ymax=60,
width=\textwidth,
height=\textwidth]
% https://math.stackexchange.com/q/335226/475643
\draw (axis cs:\p0) .. controls (axis cs:\s1) and (axis cs:\r1) .. (axis cs:\p1);
\draw (axis cs:\p1) .. controls (axis cs:\s2) and (axis cs:\r2) .. (axis cs:\p2);
\draw (axis cs:\p2) .. controls (axis cs:\s3) and (axis cs:\r3) .. (axis cs:\p3);
% datapoints
\draw (axis cs:\p0) node[circle,fill,scale=0.5,label=above:$P_{0}$] {};
\draw (axis cs:\p1) node[circle,fill,scale=0.5,label=above:$P_{1}$] {};
\draw (axis cs:\p2) node[circle,fill,scale=0.5,label=above:$P_{2}$] {};
\draw (axis cs:\p3) node[circle,fill,scale=0.5,label=above:$P_{3}$] {};
\end{axis}
\end{tikzpicture}


If you ignore the bug in computing the control points (still working on it), it seems to plot everything correctly up to some scale factor:

• Axis cs coordinates are only defined inside the axis environment, and tikzmath wouldn't use them anyway. You can compute x and y values using \pgfmathsetmacro (but not \pgfmathsetlengthmacro) and use them inside the axis environment, but coordinates are always screen coordinates. May 14, 2023 at 18:04
• Maybe there's a better approach. What are you trying to achieve? May 14, 2023 at 18:29
• TikZmath uses the current coordinate system, at the place it is used. In your case it uses the xyz coordinate system (without units) which is mapped to the canvas coordinate system (with units). Even if you move your TikZmath inside the axis environment, it will do weird things. At best you need to force the use of the axis coordinate system: \draw[green] (axis cs: \c0) -- (axis cs: \c1); May 14, 2023 at 18:38
• @Qrrbrbirlbel I've updated the post with the particular problem I'm trying to solve. May 14, 2023 at 19:45

• The \tikzmath statement needs to be inside the axis environment.

This seems to make TikZ math to interpret the coordinate specifications one-to-one, i.e. 1pt = 1. All the following coordinate calculation will be taken out in the canvas coordinate system of PGF/TikZ.

• When a coordinate like (\s2) is used inside a TikZ path that will result in (0.3333pt, 1.26666pt), i.e. a coordinate in the aforementioned canvas coordinate system. Forcing PGF/TikZ to interpret this in the axis coordinate system by specifying axis cs: explicitly will turn this back to a PGFPlots coordinate (i.e. 1 = 1pt).

Whether this is and the points before is a nice side effect of how PGFPlots axis coordinate system is implemented or a lucky accident remains to be seen. Expect this not to work properly in more complex cases (3d won't work at all, numbers greather than 16000-ish won't work either).

• The coordinate calculations for r and s are not correct: \s1 = {(2 / 3 * \q1) + (1 / 3 * \p0)}; will result into

\s1 = {(2 / 3 * \qx1, \qy1) + (1 / 3 * \px0, \py0)};


which is probably interpreted as the addition of the two coordinates (2 / 3 * \qx1, \qy1) and (1 / 3 * \px0, \py0), i.e. the factor 1/3 is only applied to the x variable.

When the calc library is loaded the “normal” coordinate calculations will be available:

  \s1 = ($2 / 3 *(\q1) + 1 / 3 *(\p0)$);
\s2 = ($2 / 3 *(\q2) + 1 / 3 *(\p1)$);
\s3 = ($2 / 3 *(\q3) + 1 / 3 *(\p2)$);


Note that there's no space between * and ( as per the manual.

## Code

\documentclass[tikz]{standalone}
\usetikzlibrary{calc, math}
\usepackage{pgfplots}
\begin{document}
\begin{tikzpicture}
\begin{axis}[
xmin=0, xmax=1, ymin=0, ymax=2,
width=\textwidth,
height=\textwidth]
\tikzmath{
% coordinates
coordinate \p;
\p0 = (0.0,0.0);
\p1 = (0.2,0.6);
\p2 = (0.6,0.9);
\p3 = (1.0,1.0);
% dy/dx values
real \d;
\d0 = 1.0;
\d1 = 2.0 * (\py1 - \py0) / (\px1 - \px0) - \d0;
\d2 = 2.0 * (\py2 - \py1) / (\px2 - \px1) - \d1;
\d3 = 2.0 * (\py3 - \py2) / (\px3 - \px2) - \d2;
% https://math.stackexchange.com/a/336679/475643
% quadratic control points
coordinate \q;
\q1 = ({(\px0 + \px1) / 2.0}, {\py0 + \d0 * (\px1 - \px0) / 2.0});
\q2 = ({(\px1 + \px2) / 2.0}, {\py1 + \d1 * (\px2 - \px1) / 2.0});
\q3 = ({(\px2 + \px3) / 2.0}, {\py2 + \d2 * (\px3 - \px2) / 2.0});
% cubic control points, lefthand side
coordinate \s;
\s1 = ($2 / 3 *(\q1) + 1 / 3 *(\p0)$);
\s2 = ($2 / 3 *(\q2) + 1 / 3 *(\p1)$);
\s3 = ($2 / 3 *(\q3) + 1 / 3 *(\p2)$);
% cubic control points, righthand side
coordinate \r;
\r1 = ($2 / 3 *(\q1) + 1 / 3 *(\p1)$);
\r2 = ($2 / 3 *(\q2) + 1 / 3 *(\p2)$);
\r3 = ($2 / 3 *(\q3) + 1 / 3 *(\p3)$);
}
% https://math.stackexchange.com/q/335226
\draw (axis cs:\p0) .. controls (axis cs:\s1) and (axis cs:\r1) .. (axis cs:\p1);
\draw (axis cs:\p1) .. controls (axis cs:\s2) and (axis cs:\r2) .. (axis cs:\p2);
\draw (axis cs:\p2) .. controls (axis cs:\s3) and (axis cs:\r3) .. (axis cs:\p3);
% datapoints
\draw (axis cs:\p0) node[circle,fill,scale=0.5,label=above:$P_{0}$] {};
\draw (axis cs:\p1) node[circle,fill,scale=0.5,label=above:$P_{1}$] {};
\draw (axis cs:\p2) node[circle,fill,scale=0.5,label=above:$P_{2}$] {};
\draw (axis cs:\p3) node[circle,fill,scale=0.5,label=above:$P_{3}$] {};
\end{axis}
\end{tikzpicture}
\end{document}


## Output

• I believe the best approach would be to not use any coordinate calculation at all but only reals. May 14, 2023 at 21:17
• Your fix for the r and s variables is much appreciated. This would have taken me forever to figure out on my own. I don't think that behavior (applying only to the x variable unless parenthesized) is explicitly mentioned anywhere in the TikZ manual? May 14, 2023 at 22:35
• Also, out of curiosity, if I have the calc library loaded, shouldn't I be able to replace the $...$ with {...}? May 14, 2023 at 22:46
• @segfault \q1 is just a simple substitution (expansion) for \qx1,\qy1. If you use (1/3 * \q1 * sqrt 2) it will just be x = 1/3*\qx1 and y = \qy1 * sqrt 2. There's nothing recognizing \q1 as a coordinate, it's just two length separated by a comma. The rest is just the calc library's syntax. First a factor, then a coordinate (with * beforehand) and then possibly another coordinate calculation added (e.g. again a factor and a coordinate). May 14, 2023 at 22:54