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.
Edit and compile if you like:
% Polarization state of light % Author: Jeff Hein \documentclass{article} %======== %packages %======== \usepackage{tikz} %tikz graphics package for drawing with pgf \usepackage[active,tightpage]{preview} \PreviewEnvironment{tikzpicture} \setlength\PreviewBorder{5pt}% \usepackage{fp} %for fixed point math \usepackage{ifthen} %for \ifthenelse{}{}{} conditional statements %=================== %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}
Click to download: polarization-state-of-light.tex • polarization-state-of-light.pdf
Open in Overleaf: polarization-state-of-light.tex