The following piece of eye candy:
was produced using the following code:
\documentclass[a4paper]{article}
\usepackage{tikz}
\usetikzlibrary{shapes.arrows}
\usetikzlibrary{shadows.blur}
\makeatletter
\def\sin@alpha{0.9}
\def\cos@alpha{0.006} % scaled with eye distance... never mind.
\def\kappa{0.551784} % control point inset for almost-circles
\def\pgf@pos@transform#1#2{%
\ifpgf@pt@identity%
\else%
\pgf@pt@temp=#1%
#1=\pgf@pt@aa#1%
\advance#1 by\pgf@pt@ba#2%
#2=\pgf@pt@bb#2%
\advance#2 by\pgf@pt@ab\pgf@pt@temp%
\fi%
\advance#1 by\pgf@pt@x%
\advance#2 by\pgf@pt@y%
\pgfmathsetmacro{\denominator}{1+\cos@alpha*#2)}%
\pgfmathparse{#1/\denominator}%
#1=\pgfmathresult pt%
#2=\sin@alpha#2%
\pgfmathparse{#2/\denominator}%
#2=\pgfmathresult pt%
}
\makeatother
\begin{document}
\begin{center}
\begin{tikzpicture}[yshift=5cm]
\draw[help lines] (-5,-5) grid (5,5);
\def\r{5}
\draw[thick,draw opacity=0.3,ball color=blue!20,blur shadow]
(\r,0) .. controls(\r,\kappa*\r) and (\kappa*\r,\r) .. (0,\r)
.. controls(-\kappa*\r,\r) and (-\r,\kappa*\r) .. (-\r,0)
.. controls(-\r,-\kappa*\r) and (-\kappa*\r,-\r) .. (0,-\r)
.. controls(\kappa*\r,-\r) and (\r,-\kappa*\r) .. (\r,0) -- cycle;
\foreach \r in {1,2,3,4} {
\draw[draw opacity=0.3] (\r,0) .. controls(\r,\kappa*\r) and (\kappa*\r,\r) .. (0,\r)
.. controls(-\kappa*\r,\r) and (-\r,\kappa*\r) .. (-\r,0)
.. controls(-\r,-\kappa*\r) and (-\kappa*\r,-\r) .. (0,-\r)
.. controls(\kappa*\r,-\r) and (\r,-\kappa*\r) .. (\r,0) -- cycle;
}
\node[arrow box,rotate=45,arrow box arrows={north:6cm,east:6cm,south:6cm,west:6cm},
draw,top color=blue!20,
arrow box shaft width=5mm,arrow box head extend=2mm,arrow box head indent=1mm,
minimum width=5mm,minimum height=5mm,blur shadow] at (0,0) {};
\end{tikzpicture}
\end{center}
\end{document}
(for the blurred shadows, you have to get the pgf-blur package from CTAN. Otherwise just change blur shadow to drop shadow)
The code for the grid, ellipses, and arrows is completely independent of the perspective transform. That is handled by doing nasty things to the low level \pgf@pos@transform
macro. So far so good. But...
- The circle has to be emulated using Bézier splines because the coordinate transform is done before circles are transformed to splines.
- the same will be true for any ellipses, arcs, rounded corners, etc.
- in this case transforming the control points gives a close enough approximation to the transformed Bézier spline, but that's just luck. In general, any curve-to might have to be decomposed into several pieces to get better approximations.
- setting up the perspective transform is really low level.
Any suggestions about how to do this properly? Maybe with a decoration?