This is a tool I made for representing the polarization states of light in my thesis. This demonstrates the use of the fixed point calculation package fp.sty to process user-defined parameters while rendering a TikZ picture. In this example, a ellipse is rendered, representing the polarization state of light for an arbitrary x-amplitude y-amplitude, and relative phase. See http://en.wikipedia.org/wiki/Polarization for background information on polarization states of light.
In this example, a relatively simple command is called from within a tikzpicture environment:
\begin{tikzpicture}
%usage: \polellipse{ E_{0x} }{ E_{0y} }{ phase }
\polellipse{3}{2}{45}
\end{tikzpicture}
The contents of the \polellipse command is rather lengthy, but can be broken down into two main parts. The first part performs the necessary math to convert the user-defined parameters $E_{0x}$, $E_{0y}$, and $phase$ into values which are useful to the drawing process. The second part uses the calculated numbers to draw a coordinate axis, the ellipse, and appropriate annotation.
This example can be helpful when preparing a document describing various polarization states of light. The document can contain an arbitrary number of \polellipse commands, each with an arbitrary configuration of parameters. Each rendered figure is based on the same code, so a desired change to the style can update all figures.
This general technique can be applied to any TikZ figure, where the document calls any number of commands with some passed parameters, and some computation is be performed to render the diagrams.
%ellipse.tex
%
%Author: Jeff Hein
%
%Created: July 5, 2009
%
%Notes: This file demonstrates the use of fixed point math package fp.sty, where numbers can be computed and manipulated to perform a desired task. In this example, a TikZ picture of a polarization ellipse is rendered, where the user can specify the electric field magnitudes in the x and y directions, as well as the phase difference between the two oscillating field components. Some computation is performed to convert this information to values that are useful to rendering the ellipse.
\documentclass{article}
%========
%packages
%========
\usepackage{tikz} %tikz graphics package for drawing with pgf
\usepackage{fp} %for fixed point math
\usepackage{ifthen} %for \ifthenelse{}{}{} conditional statements
\usepackage[active,tightpage]{preview} %set the document for figure preview
%===================
%Style configuration
%===================
\pagestyle{empty}
\PreviewEnvironment{tikzpicture}
\setlength\PreviewBorder{2mm}
\usetikzlibrary{calc}
%line thickness styles: ultra thin, very thin, (thin), semithick, thick, very thick, ultra thick
%line dash styles: loosely dashed, densely dashed, loosely dotted, densely dotted
\tikzset{bkgd_line/.style={very thin,color=gray}}
\tikzset{dashed_bkgd_line/.style={thin, dashed,color=gray}}
\tikzset{dimension_line/.style={very thin,color=gray}}
\tikzset{axis_line/.style={thin}}
\tikzset{object_line/.style={thick}}
\tikzset{textlabel/.style={color=red}}
%===================
%Command Definitions
%===================
%Command: polellipse
%
%parameters:
%
%1: x-axis magnitude
%2: y-axis magnitude
%3: phase between x-y components: \phase = \delta_y - \delta_x
%
\newcommand{\polellipse}[3]{%
%
%NOTE:see http://spie.org/x32373.xml for some background on the math behind this calculation.
%
\coordinate(origin) at (0,0);
%constants
\FPset{\LABELOFFSET}{.1}
%input parameters
%================
%\Eoy: Electric field magnitude in the y-direction, (Eoy \geq 0)
\FPset{\Eoy}{#2}
%\Eox: Electric field magnitude in the x-direction, (Eoy \geq 0)
\FPset{\Eox}{#1}
%\phase: phase difference between E_y and E_x, in degrees (\phase \leq 0 < 360)
\FPset{\phase}{#3}
\FPiflt{\phase}{0}
\FPadd{\phase}{\phase}{360}
\else \fi
%\convert phase to radians
\FPmul{\phase}{\phase}{\FPpi} %\phase = \phase * \PI
\FPdiv{\phase}{\phase}{180} %\phase = \phase / 180
%Begin calculations, and reality check
%=====================================
\ifthenelse{\equal{\Eox}{0}}{%
%error case: \Eox = \Eoy = 0
\FPifzero{\Eoy}
\errmessage{ELLIPSE PLOT ERROR: Both Eox and Eoy cannot be zero!}
\else \fi
%special case: \Eox = 0
\FPdiv{\alp}{\FPpi}{2} %\alp = \pi/2
}
{%
%normal case, \Eox \neq 0
\FPdiv{\scratch}{\Eoy}{\Eox} %\scratch = \Eoy/\Eox
\FParctan{\alp}{\scratch} %\alp = \arctan{\scratch}
}
%normalize magnitudes, used for plotting
%=======================================
\FPpow{\scratchy}{\Eoy}{2} %\scratchy = \Eoy^2
\FPpow{\scratchx}{\Eox}{2} %\scratchx = \Eox^2
\FPadd{\scratch}{\scratchy}{\scratchx} %\scratch = \scratchy + \scratchx
\FProot{\norm}{\scratch}{2} %\norm = \sqrt{\scratch}
\FPdiv{\Eoynorm}{\Eoy}{\norm} %\Eoynorm = \Eoy / \norm
\FPdiv{\Eoxnorm}{\Eox}{\norm} %\Eoynorm = \Eox / \norm
%determine major and minor axes
%==============================
\FPmul{\scratch}{\alp}{2} %\scratch = \alp* 2
\FPsin{\sintwoalp}{\scratch} %\alp = \sin\scratch
%\sin2\chi = \sin2\alp \sin\phase
\FPsin{\scratch}{\phase} %\scratch = \sin\phase
\FPmul{\sintwochi}{\scratch}{\sintwoalp} %\sintwochi = \scratch * \sintwoalp
%solve for \tan\chi
\FParcsin{\scratch}{\sintwochi} %\scratch = \arcsin{\sintwochi}
\FPdiv{\scratch}{\scratch}{2} %\scratch = \scratch / 2
\FPtan{\tanchi}{\scratch} %\tanchi = \tan{\scratch}
%if \tanchi is less than zero, the proceeding power operation will fail.
\FPabs{\tanchi}{\tanchi}
%\b = -\frac{\tanchi}{\sqrt{ 1 + \tanchi^2}}
\FPpow{\scratch}{\tanchi}{2} %\scratch = \tanchi^2
\FPadd{\scratch}{\scratch}{1} %\scratch = \scratch + 1
\FProot{\scratch}{\scratch}{2} %\scratch = \sqrt{\scratch}
\FPdiv{\b}{\tanchi}{\scratch} %\b = \tanchi / \scratch
%\a = \sqrt{1 - \b^2}
\FPpow{\scratch}{\b}{2} %\scratch = \b^2
\FPsub{\scratch}{1}{\scratch} %\scratch = 1 - \scratch
\FProot{\a}{\scratch}{2} %\a = \sqrt{\scratch}
%determine orientation angle
%===========================
%\tantwoalp = \tan{2\alp}
\FPmul{\twoalp}{\alp}{2} %\scratch = \alp * 2
%check for infinite tan!
\FPmul{\scratch}{\twoalp}{180}
\FPdiv{\scratch}{\scratch}{\FPpi}
\FPround{\scratch}{\scratch}{3}
\ifthenelse{\equal{\scratch}{90.000}}{%
%special case: if \twoalp is 90 degrees, \tantwoalp will be infinite
\FPset{\orang}{\alp} %force \orang to \alp
}
{
%regular case
\FPtan{\tantwoalp}{\twoalp} %\tantwoalp = \tan\scratch
%\tantwopsi = \tantwoalp \cos\phase
\FPcos{\scratch}{\phase} %\scratch = \cos\phase
\FPmul{\tantwopsi}{\tantwoalp}{\scratch} %\tantwopsi = \tantwoalp * \scratch
\FParctan{\scratch}{\tantwopsi} %\scratch = \arctan{\tantwopsi}
\FPdiv{\orang}{\scratch}{2} %\orang = \scratch / 2
%assign proper quadrant: if the orientation angle is less than zero, increase by 90 degrees
\FPiflt{\orang}{0}
\FPdiv{\scratch}{\FPpi}{2}
\FPadd{\orang}{\orang}{\scratch}
\else \fi
}
%convert \phase to degrees
\FPmul{\phase}{\phase}{180}
\FPdiv{\phase}{\phase}{\FPpi}
\FPround{\phase}{\phase}{1}
%convert \orang to degrees
\FPmul{\orang}{\orang}{180}
\FPdiv{\orang}{\orang}{\FPpi}
%final check on proper quadrant: if \phase is between 90 and 270, increase orientation by 90 degrees
\FPset{\scratch}{0}
\FPifgt{\phase}{90.0}
%if the first test passes, then prime the increment amount
\FPset{\scratch}{90}
\else \fi
\FPiflt{\phase}{270}
%if the second test passes, then increment by amount. This will be zero if the first test didn't pass, and so we have a makeshift AND operation here!
\FPadd{\orang}{\orang}{\scratch} %add \pi/2 to orientation angle
\else \fi
%if Eox was zero to start with, just set orientation to 90 degrees
\FPifzero{\Eox}
%special case: \Eox = 0
\FPset{\orang}{90} %\orang = 90 degrees
\else \fi
%determine perpendicular axis direction for rendering minor axis
%print output for testing
%\draw (0,-2in) node{\FPprint{\scratch}};
%\draw (0,-2in) node{$a$:\FPprint{\a}\quad\quad $b$:\FPprint{\b}\quad\quad orientation angle:\FPprint{\orang}};
%define points for labels
\begin{scope}[rotate around={\orang:(origin)}]
\coordinate (a) at ($ (\a in, 0) + (\LABELOFFSET in,0) $);
\coordinate (b) at ($ (0, \b in) + (0,\LABELOFFSET in)$);
%determine arrow position and direction
\coordinate (arrow1front) at ($ (0, \b in) $);
\coordinate (arrow2front) at ($ (0, -\b in) $);
\FPifgt{\phase}{180}
\coordinate (arrow1back) at ($ (0, \b in) - .001*(\a in,0) $);
\coordinate (arrow2back) at ($ (0, -\b in) + .001*(\a in,0) $);
\else
\coordinate (arrow1back) at ($ (0, \b in) + .001*(\a in,0) $);
\coordinate (arrow2back) at ($ (0, -\b in) - .001*(\a in,0) $);
\fi
\end{scope}
%points for labels Eox, Eoy, \delta
\coordinate (e) at ($ .5*(\Eoxnorm in,0) + (0,-\Eoynorm in) $);
\coordinate (f) at ($ .5*(0,-\Eoynorm in) + (\Eoxnorm in,0) $);
\coordinate (g) at ($ (-.2in,0) + (0,\Eoynorm in) $);
%draw the x-y plane
\draw[axis_line, ->] (-1.25in,0) -- (1.25in,0) node[textlabel,anchor=west]{$x$};
\draw[axis_line, ->] (0,-1.25in) -- (0,1.25in) node[textlabel,anchor=south]{$y$};
%draw the major and minor axis lines
\draw[dimension_line,rotate=\orang] (-\a in,0) -- (\a in,0);
\draw[dimension_line,rotate=\orang] (0, -\b in) -- (0, \b in);
%draw the x-y amplitude bounding box
\draw[dimension_line] (-\Eoxnorm in,-\Eoynorm in) rectangle (\Eoxnorm in,\Eoynorm in);
%draw the ellipse and arrows showing the sense of rotation
\draw[object_line,rotate=\orang,->] (0,0) ellipse (\a in and \b in);
\draw[object_line,->] (arrow1back) -- (arrow1front);
\draw[object_line,->] (arrow2back) -- (arrow2front);
%label major-minor axes
\FPifgt{\b}{.1} %threshold for displaying major-minor axis labels
\draw (a) node[textlabel]{$a$}; %=\a); %uncomment and merge if you want to display the major axis size. Maybe do a \FPround{\a}{\a}{1} beforehand!
\draw (b) node[textlabel]{$b$}; %=\b); %uncomment and merge if you want to display the minor axis size. Maybe do a \FPround{\b}{\b}{1} beforehand!
\else \fi
%label the x-y components and delta
\draw (e) node[textlabel,anchor=north]{$E_{0x} = \Eox$};
\draw (f) node[textlabel,anchor=north west]{$E_{0y} = \Eoy$};
\draw (g) node[textlabel,anchor=south east]{$\delta = \phase^\circ$};
%label orinetation angle
\FPifgt{\orang}{1} %threshold for displaying orientation angle
\draw[dimension_line] (.3in, 0) arc (0:\orang:.3in);
\FPdiv{\scratch}{\orang}{2} %scratch = ema/2
\draw[rotate=\scratch] (.5in,0) node[textlabel]{$\psi$};
\else \fi
}
%end ellipse command
%=============
%main document
%=============
\begin{document}
%\section*{Background} %to render this, remove the preview environment
%
%\subsubsection*{Electric Field Vectors}
%
%\begin{align}\begin{split}
% E_x(t) &= E_{0x}\cos(\omega t)\\
% E_y(t) &= E_{0y}\cos(\omega t + \delta)\\
% \vec{E}(t) &= E_x(t)\hat{x} + E_y(t)\hat{y}
%\end{split}\end{align}
%For further information about polarization states of light and calculating the polarization ellipse, see your favorite optics book!
\begin{tikzpicture}
%usage: \polellipse{ E0x }{ E0y }{ phase }
\polellipse{3}{2}{45}
\end{tikzpicture}
%alternative example:
%uncomment the following block and remove the preview environment from the beginning of the document
%polarization ellipse figures
% \foreach \i in {1,3,5,9}
% {
% \foreach \j in {-40,-20,0,30,60,140}
% {
% \begin{tikzpicture}[scale=.25]
% %\polellipse{ E_{0x} }{ E_{0y} }{ \delta }
% \polellipse{4}{\i}{\j}
% \end{tikzpicture}
% }
%newline for proper formatting!
% \\
% }
\end{document}