After gaining a basic understanding of TikZ/PGF it’s time to move on to what I set out to do in the first place: drawing a spherical triangle.

Before jumping straight to a spherical triangle we need to do a bit more ground work on how to draw 3D diagrams?
Before delving into the 3D world I will go over some useful things like the basic mathematical operations that can be used in TikZ/PGF:

The PGF Mathematical Engine:p, li { white-space: pre-wra

  1. \begin{tikzpicture}[scale = 4, rotate=-20]
  2.      See previous post for missing code.
  3.      % Graph Content
  4.      \coordinate (point1) at (1/2, 3*2-5.5);
  5.      \draw (0,0) circle (\R);
  6.      \draw (0,0) — (point1);
  7.      \filldraw [fill = blue!50, draw = black] (point1) circle (\R/30);
  8.      \foreach \ang in {0,10,…,80} {
  9.           \pgfmathparse{\R*2/2*sin(90)};
  10.           \filldraw [fill = green!\ang, draw = black] (\ang:\pgfmathresult) circle (\R/30);
  11.           \pgfmathsetmacro{\XVal}{\R*cos(-\ang)};
  12.           \pgfmathsetmacro{\YVal}{\R*sin(-\ang)};
  13.           \filldraw [fill = yellow!\ang, draw = black] (\XVal, \YVal) circle (\R/30);
  14.      }
  15. \end{tikzpicture}
  • The first and most obvious thing you will probably note is that one image is rotated. Whilst I have applied this transform to the entire figure/diagram a transform can be applied to any primitive.
  • Although touched on briefly, this example shows how to save a coordinate. And just as important that the coordinates can be entered as mathematical expressions that will be evaluated with PGF’s mathmatical engine.
  • What happens if we want a more complicated expression? It turns out we can do this too. But I found that they couldn’t be placed inline, and instead has to be parsed using \pgfmathparse{}. The result is then stored in the \pgfmathresult variable/macro. 
  • But what happens if we need two complicated expressions? After some reading and experimenting I found you can use this function: \pgfmathsetmacro{\YVal}{expression} to save an answer to a variable which can the be used later! 

Ok, so back to drawing 3D stuff…

Transformations:

It seems the key to drawing in 3D is to use transformations. We will be rotating the x-y plane (drawing canvas) using the  following transformation matrices:

 

We can also combine these matrices using Rzyx = Rz*Ry*Rx, which yields:
In TikZ/PGF the default plane is the right handed x-y plane with the x-axis going to the right and the y-axis going up (being right handed the z-axis comes out of the page). This default plane can be transformed using the following function/drawing option:
“[cm={a,b,c,d,(dx,dy)}]”
This represents the following transformation:

In the first example we are rotating a 2D shape in the default plane; this means we want to rotate about the z-axis. This is the Rz matrix:

We need to project into the x-y plane, so we can remove the third row and column as this will only affect a z-value:
Lets have a look at this simple example which uses rotations about the z-axis. First a triangle Δ(0,0)(1,0)(1,1) is drawn. The second figure then shows the triangle rotated 45deg. And the final example shows the original triangle rotated -90deg and translated by (1,1). Note: you can think about this by either translating and then rotating, or rotating and then translating.

 

  1. \begin{tikzpicture}
  2.      \DrawAxis{0}{0}{2}{2};
  3.      \draw [fill = yellow] (0,0) — (1,1) — (1,0);
  4.      \begin{scope}[xshift=3cm]
  5.          \def\Ang{45};
  6.          \DrawAxis{0}{0}{2}{2};
  7.          \draw [cm={cos(\Ang),sin(\Ang),-sin(\Ang),cos(\Ang),(0,0)}
  8.           (0,0) — (1,1) — (1,0);
  9.      \end{scope}
  10.      \begin{scope}[xshift=6cm]
  11.          \DrawAxis{0}{0}{2}{2};
  12.          \draw [cm={cos(\Ang),sin(\Ang),-sin(\Ang),cos(\Ang),(1,1)}
  13.           (0,0) — (1,1) — (1,0);
  14.      \end{scope}
  15. \end{tikzpicture}

Drawing in 3D:

I will start be drawing a parabola, which we will then rotate about the y-axis creating a cone-like shape.

We will now add some ‘circles’ and planes rotated about the x-axis and offset in the y-direction to add some depth to the figure:

p, li { white-space: pre-wra

  1. \begin{tikzpicture}
  2.      \def\fcn{\x*\x};
  3.      \def\phi{10};
  4.      \def\xmin{-1.5}; \def\xmax{1.5};
  5.      \draw[color=black, domain=\xmin:\xmax]
  6.           plot (\x, \fcn) node [above right] {$y = x^2$};
  7.      \foreach \x in {0, .25, …, \xmax} {
  8.           \tikzset{xyplane/.estyle={cm={1, 0, 0, cos(90 + \phi),(0, \fcn)}}}
  9.           \draw[xyplane, color=black] (0, 0) circle (\x);
  10.      }
  11. \end{tikzpicture}
  • \phi is the view angle. We rotate by 90deg to get the plane perpendicular to the page and then adjust a little.

Now we’re starting to have something that looks 3-dimensional. Lets now rotate the parabola around the y-axis:

p, li { white-space: pre-wra

  1. \begin{tikzpicture} [scale =2]
  2.      \def\fcn{\x*\x};
  3.      \def\phi{10};
  4.      \def\xmin{-1.5}; \def\xmax{1.5};
  5.      \foreach \x in {0, 0.25, …, \xmax} {
  6.           \tikzset{xyplane/.estyle={cm={1, 0, 0, cos(90 + \phi),(0, \fcn)}}}
  7.           \draw[xyplane, color=black] (0, 0) circle (\x);
  8.      }
  9.      \foreach \theta in {0, 30, …, 360} {
  10.           \tikzset{xyplane/.estyle={cm={cos(\theta), 0, 0, 1,(0, 0)}}}
  11.           \draw[xyplane, color=black, domain=\xmin:\xmax]
  12.                plot (\x, \fcn);
  13.      }
  14. \end{tikzpicture}\\

Close, but no dice. We need to account for the viewing angle. So to get the correct plane, we need to rotate about the y-axis and the x-axis:

p, li { white-space: pre-wra

  1. \begin{tikzpicture} [scale =2]
  2.      \def\fcn{\x*\x};
  3.      \def\phi{10};
  4.      \def\xmin{-1.5}; \def\xmax{1.5};
  5.      \foreach \x in {0, 0.25, …, \xmax} {
  6.           \tikzset{xyplane/.estyle={cm={1, 0, 0, cos(90 + \phi),(0, \fcn)}}}
  7.           \draw[xyplane, color=black] (0, 0) circle (\x);
  8.      }
  9.      \foreach \theta in {0, 30, …, 360} {
  10.           \tikzset{xyplane/.estyle={cm={cos(\theta), sin(\theta)*sin(\phi), 0,                cos(\phi),(0, 0)}}}
  11.           \draw[xyplane, color=black, domain=\xmin:\xmax]
  12.           plot (\x, \fcn);
  13.      }
  14. \end{tikzpicture}\\

 

Close but the top circle does not quite line up with the rotated parabolas. It turns out this is also to do with the viewing angle (If we look at the Rx rotation matrix and project into the x-y plane we can see that the y value of a coordinate is multiplied by cos(\phi)).
Because we are looking from above the heights appear shorter by a factor of cos(\phi), so when we draw the circles, instead of offsetting the plane by x^2, we need to offset it by cos(\phi)*x^2:

 

The next section will look at drawing a sphere with lines of latitude and longitude.

References:

Advertisements