# Tikz : how to control length in 3D pictures?

I tried to draw a sphere with tikz with isometric projection or oblique projection (perpective cavalière in french).

For oblique projection you have to put a scaling factor (scal < 1) for distance on the x axes. But if I want my sphere to look like a not distorted sphere, I have to put a scaling of zero. Thus, I obtain a projection in (yz) plane. Hereafter is my tikz source code, you can easily switch between isometric and oblique projection :

\documentclass{article}

\usepackage{tikz}
\usetikzlibrary{}

\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}
\setlength\PreviewBorder{2mm}

\tikzstyle{cavaliere} = [x={(-0.866cm,-0.5cm)},y={(1cm,0cm)},z={(0cm,1cm)}]
\tikzstyle{isometrique} = [x={(-0.866cm,-0.5cm)},y={(0.866cm,-0.5cm)},z={(0cm,1cm)}]
\tikzstyle{mesh} = [color=gray, opacity=0.4]

\begin{document}

%
% norm selection :
%
%   if(isometrique)
%
\begin{tikzpicture}[isometrique]
\def\scal{1.}

%   else if(cavaliere)
%
%\begin{tikzpicture}[cavaliere]
%       \def\scal{0.3}
%

\coordinate (O) at (0,0,0);
\draw[->] (O) -- ({\scal * 3},0,0) node[below] {x};
\draw[->] (O) -- (0,3,0) node[below] {y};
\draw[->] (O) -- (0,0,3) node[right] {z};

\def\r{2.}

% meridiens
% \rho joue le role de theta
\foreach \phi in {0,10,...,170} {
\draw[mesh] ({\scal * \r * cos(\phi)}, {\r * sin(\phi)}, 0)
\foreach \rho in {5,10,...,360} {
--({\scal * \r * cos(\phi) * cos(\rho)}, {\r * sin(\phi) * cos(\rho)}, {\r * sin(\rho)})
} -- cycle;
}

% parallels
\foreach \rho in {-60, -40, -19.57, 0, 19.57, 40, 60} {
\draw[mesh] ({\scal * \r * cos(\rho)}, 0, {\r * sin(\rho)})
\foreach \phi in {5,10,...,360} {
-- ({\scal * \r * cos(\rho) * cos(\phi)}, {\r * cos(\rho) * sin(\phi)}, {\r * sin(\rho)})
} -- cycle;
}
\end{tikzpicture}

\end{document}


Do you know how to draw a correct sphere in oblique projection. I prefer that one because the view of what I put into the sphere is better than in isometric projection.

Thanks

EDIT : axes z vertical

\begin{tikzpicture}[x={(-0.385cm,-0.385cm)},y={(1cm,0cm)},z={(0cm,1cm)},scale=4]

\coordinate (O) at (0,0,0);
\draw[->] (O) -- (2,0,0) node[below] {x};
\draw[->] (O) -- (0,2,0) node[below] {y};
\draw[->] (O) -- (0,0,2) node[right] {z};

\foreach \z in {-0.98,-0.96,...,0.98}  {%
\begin{scope}[canvas is xy plane at z=\z]
\draw[gray] (0,0) circle ({sqrt(1-\z*\z)});
\end{scope}}

\begin{scope}[canvas is zy plane at x=0]
\draw (0,0) circle (1cm);
\draw (-1,0) -- (1,0) (0,-1) -- (0,1);
\end{scope}

\begin{scope}[canvas is zx plane at y=0]
\draw (0,0) circle (1cm);
\draw (-1,0) -- (1,0) (0,-1) -- (0,1);
\end{scope}

\begin{scope}[canvas is xy plane at z=0]
\draw (0,0) circle (1cm);
\draw (-1,0) -- (1,0) (0,-1) -- (0,1);
\end{scope}

\end{tikzpicture}


Thus I obtained

-

Simple code, it's better to use arc and to determine the visible part.

I think the result is something like that :

  \documentclass{article}
\usepackage{tikz}
\usetikzlibrary{3D}

\pagestyle{empty}

\begin{document}
\begin{tikzpicture}[scale=4]

\foreach \z in {-0.98,-0.96,...,0.98}  {%
\begin{scope}[canvas is xy plane at z=\z]
\draw[gray] (0,0) circle ({sqrt(1-\z*\z)});
\end{scope}}

\begin{scope}[canvas is zy plane at x=0]
\draw (0,0) circle (1cm);
\draw (-1,0) -- (1,0) (0,-1) -- (0,1);
\end{scope}

\begin{scope}[canvas is zx plane at y=0]
\draw (0,0) circle (1cm);
\draw (-1,0) -- (1,0) (0,-1) -- (0,1);
\end{scope}

\begin{scope}[canvas is xy plane at z=0]
\draw (0,0) circle (1cm);
\draw (-1,0) -- (1,0) (0,-1) -- (0,1);
\end{scope}

\end{tikzpicture}
\end{document}


How to change axes

if the plane facing the viewer is yz , and the receding axis is x, then a point is projected like this:

 y'= y + 1/2  cos(a) x
z'= z + 1/2  sin(a) x


You need to change the system like this, if you want k=0.5 and a=45° :

                   x = { ({-0.5*cos(45)},{-0.5*sin(45)})},
y = { (1cm,0cm)},
z = { (0cm,1cm)}


So x =(-0.35355,-0.35355). I don't why in pgf z =(-0.385,-0.385).

It's possible to try a=30 degrees or a=60 degrees.

  \documentclass{article}
\usepackage{tikz}
\usetikzlibrary{3D}

\pagestyle{empty}

\begin{document}
\begin{tikzpicture}[x = { ({-0.5*cos(45)},{-0.5*sin(45)})},
y = { (1cm,0cm)},
z = { (0cm,1cm)},
scale = 4]

\foreach \x in {-0.98,-0.96,...,0.98}  {%
\begin{scope}[canvas is zy plane at x=\x]
\draw[gray] (0,0) circle ({sqrt(1-\x*\x)});
\end{scope}}

\begin{scope}[canvas is zy plane at x=0]
\draw (0,0) circle (1cm);
\draw (-1,0) -- (1,0) (0,-1) -- (0,1);
\end{scope}

\begin{scope}[canvas is zx plane at y=0]
\draw (0,0) circle (1cm);
\draw (-1,0) -- (1,0) (0,-1) -- (0,1);
\end{scope}

\begin{scope}[canvas is xy plane at z=0]
\draw (0,0) circle (1cm);
\draw (-1,0) -- (1,0) (0,-1) -- (0,1);
\end{scope}

\end{tikzpicture}

\end{document}


-
Hello @altermundus I knew your web site, it's usefull. Your sphere is nice but how can I change orientation of x, y, z axes. I tried something but the sphere looks bad. I did the change on the first post. –  Ger Jun 7 '12 at 7:52
Here I used the "normal" oblic projection with the main plane xy. It's possible to change the factor k or the "fuite" angle, for that you need only to modify zlike this z={(-0.8cm,-0.8cm)}. It's better to modify z with an angle and a coefficient. I added an update to my answer in several minutes. –  Alain Matthes Jun 7 '12 at 8:14
I do not understand. If I use a "fuite angle" of 45° z should be (-0.707,-0.707), right ? So why 0.385 and in your picture you put 3.85 istead of 0.385. –  Ger Jun 7 '12 at 8:50
If I put x={(-0.385cm,-0.385cm)},y={(1cm,0cm)},z={(0cm,1cm)} I get the right view. Your one is distorted with the 1.2 factor. I edit my first post in that way. –  Ger Jun 7 '12 at 8:51
I made a mistake when I modified my code (mm or cm ?). The correct value is -3.85 mm. If the third vector is defined by {(a,a)} then the angle is 45°. The natural projection, I think is : if the plane facing the viewer is xy , and the receding axis is z, then a point is projected like this: x'= x+0.5z.cos(a) y'= y+0.5z.sin(a) and z'=0. It's was you get 0.385 cm = 0.5 cos(45) cm. But it's possible to replace 0.5 by k and effectively in this case you get a distorsion. – –  Alain Matthes Jun 7 '12 at 9:27

This is the code I adapted from the one of altermundus :

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{3d}
\begin{document}
\begin{tikzpicture}[x={({cos(135)},{-sin(45)})},y={(1cm,0cm)},z={(0cm,1cm)},scale=4]

\coordinate (O) at (0,0,0);
\draw[->] (O) -- (2,0,0) node[below] {x};
\draw[->] (O) -- (0,2,0) node[below] {y};
\draw[->] (O) -- (0,0,2) node[right] {z};

\foreach \z in {-0.98,-0.96,...,0.98}  {%
\begin{scope}[canvas is xy plane at z=\z]
\draw[gray] (0,0) circle ({sqrt(1-\z*\z)});
\end{scope}}

\begin{scope}[canvas is zy plane at x=0]
\draw (0,0) circle (1cm);
\draw (-1,0) -- (1,0) (0,-1) -- (0,1);
\end{scope}

\begin{scope}[canvas is zx plane at y=0]
\draw (0,0) circle (1cm);
\draw (-1,0) -- (1,0) (0,-1) -- (0,1);
\end{scope}

\begin{scope}[canvas is xy plane at z=0]
\draw (0,0) circle (1cm);
\draw (-1,0) -- (1,0) (0,-1) -- (0,1);
\end{scope}

\end{tikzpicture}
\end{document}


I tried to put z vertically y in the page and x perpendicular but it doesn't look like really good see below :

It is strange because, on the altermundus figure, the z axes seems to be at 45° from the vertical.

-
By default k=1/2 you can give a look at en.wikipedia.org/wiki/Oblique_projection#Cavalier_projections and at fr.wikipedia.org/wiki/Perspective_cavali%C3%A8re In the english version k=1/2, in the french one, the example is given with k=0.5 and 45° finally 0.5 cos(45) = 0,35 . i don't understand why in pgf the value is 0.385. –  Alain Matthes Jun 7 '12 at 9:34
I made another mistake the z axis is at 45° form the vertical but the coefficent k is not 0.5 but 0.54 in the pgf manual and in the sources?? –  Alain Matthes Jun 7 '12 at 9:38