I have a plottable function whose normalized domain is [0,1] and whose normalized range is [-1,1]. I also have two TikZ coordinates, (BOTLEFT)
and (TOPRIGHT)
defining the bottom left and top right of a bounding box where I would like the plot to appear.
I would like to effect a skewless, rotationless affine linear coordinate transform such that the plot domain/range is fitted exactly to the bounding box. That is, each point (x,y) is mapped to
(x,y) → (BOTLEFT)
+ ((TOPRIGHT)
– (BOTLEFT)
) · ((x,y) – (0,-1)) ÷ ((1,1) – (0,-1))
For example, the sine wave
\draw[domain = 0:1, samples = 256] plot (\x,{sin(\x*4*pi r)});
when subject to the transform, should fit exactly inside the bounding box
\draw[red] (-2,5) rectangle (1,8);
if (BOTLEFT)
is (-2,5) and (TOPRIGHT)
is (1,8).
TikZ supports the xshift
, yshift
, xscale
and yscale
properties to implement the coordinate transform. However, computing the xscale
and yscale
properties manually using coordinate arithmetic would appear to require isolating the x and y components of (BOTLEFT)
and (TOPRIGHT)
. I know this can be done (e.g., by the let
directive):
\coordinate (BOTLEFT) at ({-.2},.5);
\coordinate (TOPRIGHT) at (.1,.8);
\draw let
\p1 = (BOTLEFT),
\p2 = (TOPRIGHT) in [domain = 0:1, samples = 256,
xshift = \x1,
xscale = (\x2 - \x1)\pts,
yshift = (\y1 + (\y2 - \y1)/2),
yscale = ((\y2 - \y1)/2)\pts
] plot (\x,{sin(\x*4*pi r)});
\draw[red] (BOTLEFT) rectangle (TOPRIGHT);
where \pts
is a macro that expands to *<constant>
to convert from pts to the scaling units for the figure, but this seems extremely messy, especially for TikZ/PGF. I can't help but think that TikZ has some kind of built-in to handle this. It would be especially useful if the transform could be scope
-d, too. That is,
\begin{scope}[<set transform here>]
\draw[domain = 0:1, samples = 256] plot (\x,{sin(\x*4*pi r)});
<more commands in same coordinate frame>
...
\end{scope}
Is there a more elegant way of handling this in TikZ, or am I stuck with hacking the coordinate math in this way?
Clarification #1
The coordinates (BOTLEFT)
and (TOPRIGHT)
are computed using expressions involving node anchor points, not numeric literals as in the example.
Best Answer
This fits (0,0) to (1,1) into (BOTLEFT) to (TOPRIGHT). It involves the fewest math or conversion steps I could think of.