% \iffalse meta-comment % % Copyright (C) 2015 by Matthew Wardrop % --------------------------------------------------------------------------- % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3 % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3 or later is part of all distributions of LaTeX % version 2005/12/01 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Matthew Wardrop % % This work consists of the files blochsphere.dtx and blochsphere.ins % and the derived filebase blochsphere.sty. % % \fi % % \iffalse %<*driver> \ProvidesFile{blochsphere.dtx} % %\NeedsTeXFormat{LaTeX2e}[1999/12/01] %\ProvidesPackage{blochsphere} %<*package> [2015/09/15 v1.1 blochsphere drawing package] % % %<*driver> \documentclass{ltxdoc} \EnableCrossrefs \CodelineIndex \RecordChanges \usepackage{blochsphere} \usepackage{minted} \usepackage{hyperref} \setlength{\parskip}{0.7em} \newenvironment{key}[2]{ \noindent{\llap{Option: \bf\tt #2\hskip 9pt}} }{} \newcommand{\DescribeKey}[3][]{ \noindent{\llap{\bf\tt #2\hskip 9pt}[default = #1] #3} } \usepackage{listings} \lstset{breaklines=true} \begin{document} \DocInput{blochsphere.dtx} \PrintChanges \PrintIndex \end{document} % % \fi % % \CheckSum{841} % % \CharacterTable % {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z % Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z % Digits \0\1\2\3\4\5\6\7\8\9 % Exclamation \! Double quote \" Hash (number) \# % Dollar \$ Percent \% Ampersand \& % Acute accent \' Left paren \( Right paren \) % Asterisk \* Plus \+ Comma \, % Minus \- Point \. Solidus \/ % Colon \: Semicolon \; Less than \< % Equals \= Greater than \> Question mark \? % Commercial at \@ Left bracket \[ Backslash \\ % Right bracket \] Circumflex \^ Underscore \_ % Grave accent \` Left brace \{ Vertical bar \| % Right brace \} Tilde \~} % % % \changes{v1.1}{2015/09/15}{Fix \\drawAxis using removed keyval "mark"} % \changes{v1.0}{2015/08/17}{Initial version} % % \DoNotIndex{\newcommand,\newenvironment} % % \providecommand*{\url}{\texttt} % \GetFileInfo{blochsphere.dtx} % \title{The \textsf{blochsphere} package} % \author{Matthew Wardrop \\ \url{mister.wardrop@gmail.com}} % \date{\fileversion~from \filedate} % % \maketitle % % \tableofcontents % % \section{Introduction} % % The |blochsphere| package is used to draw pseudo-3D Blochsphere diagrams, such as that % shown in figure \ref{fig:blochsphere}. It supports various annotations, such as % great and small circles, axes, rotation markings and state vectors. It can be used % in a standalone fashion, or nested within a |tikzpicture| environment by setting % the environment option |nested| to |true|. % % \section{Usage} % % Using |blochsphere| is as simple as creating a `blochsphere' environment. % \begin{minted}{LaTeX} % \begin{blochsphere}[] % ... % \end{blochsphere} % \end{minted} % By default, this will create a blank Bloch sphere ready for annotation. The options can be % any of those described in the next section. % % \noindent\DescribeMacro{\drawBall} \oarg{options}\\ % This macro draws the basic Bloch sphere, according to the options defined in the next section. % % \noindent\DescribeMacro{\drawBallGrid} \oarg{options} \marg{latdegsep} \marg{longdegsep}\\ % This macro draws latitude and longitude circles at an interval defined by |latdegsep| and |longdegsep| respectively. % % \noindent\DescribeMacro{\setDrawingPlane} \oarg{options} \marg{tiltangle} \marg{rotationangle}\\ % This macro defines a transformation matrix within TikZ to create the effect of 2D projections of 3D planes, % named according to the |plane| option. This is used internally in all of the drawing commands. % % \noindent\DescribeMacro{\setLatitudinalDrawingPlane} \oarg{options} \marg{latitude}\\ % This is a special case of |\setDrawingPlane| that constructs the transform required to draw a 2D image in % a latitudinal plane. % % \noindent\DescribeMacro{\setLongitudinalDrawingPlane} \oarg{options} \marg{longitude}\\ % This is a special case of |\setDrawingPlane| that constructs the transform required to draw a 2D image in % a longitudinal plane. % % \noindent\DescribeMacro{\drawCircle} \oarg{options} \marg{tiltangle} \marg{rotationangle}\\ % Draws a circle on the surface of a Bloch sphere around the axis which is tilted by |tiltangle| % from the z-axis and with a rotation of |rotationangle| about the z-axis. % % \noindent\DescribeMacro{\drawGreatCircle} \oarg{options} \marg{tiltangle} \marg{rotationangle}\\ % An alias of |\drawCircle|. % % \noindent\DescribeMacro{\drawSmallCircle} \oarg{options} \marg{tiltangle} \marg{rotationangle} \marg{offsetLatitude}\\ % Draws a circle on the surface of a Bloch sphere around the axis which is tilted by |tiltangle| % from the z-axis and with a rotation of |rotationangle| about the z-axis, with an offset along the axis % such that it reaches an effective latitude of |offsetLatitude|. % % \noindent\DescribeMacro{\drawLatitudeCircle} \oarg{options} \marg{latitude}\\ % Draws a circle on the Bloch sphere corresponding to the given latitude. % % \noindent\DescribeMacro{\drawLongitudeCircle} \oarg{options} \marg{longitude}\\ % Draws a great circle on the Bloch sphere corresponding to the given longitude. % % \noindent\DescribeMacro{\drawRotationLeft} \oarg{options} \marg{tiltangle} \marg{rotationangle} \marg{axisoffset} \marg{clearangle}\\ % Draw a left-handed rotation about the Bloch sphere, titled and rotated as for a circle % with the same parameters, with a gap in the line where the arrow should go of % |clearangle| degrees. % % \noindent\DescribeMacro{\drawRotationRight} \oarg{options} \marg{tiltangle} \marg{rotationangle} \marg{axisoffset} \marg{clearangle}\\ % As above, but a right-handed rotation annotation. % % \noindent\DescribeMacro{\drawAxis} \oarg{options} \marg{tiltangle} \marg{rotationangle}\\ % Draw a line along the axis tilted |tiltangle| degrees from the z-axis, rotated about % the z-axis by |rotationangle| degrees. % % \noindent\DescribeMacro{\labelPolar} \oarg{options} \marg{tikzlabel} \marg{tiltangle} \marg{rotationangle}\\ % Assign a tikz label to the point identified by an angle |tiltangle| from the z-axis % and a rotation |rotationangle| about the z-axis. % % \noindent\DescribeMacro{\labelLatLon} \oarg{options} \marg{tikzlabel} \marg{latitude} \marg{longitude}\\ % Assign a tikz label to the point identified the specified latitude and longitude. % % \noindent\DescribeMacro{\drawStatePolar} \oarg{options} \marg{tikzlabel} \marg{tiltangle} \marg{rotationangle}\\ % Draw a vector from the origin to the point identified by an angle |tiltangle| % from the z-axis and a rotation |rotationangle| about the z-axis, which will % be labelled |tikzlabel|. % % \noindent\DescribeMacro{\drawStateLatLon} \oarg{options} \marg{tikzlabel} \marg{latitude} \marg{longitude}\\ % Draw a vector from the origin to the point identified by the provided % latitude and longitude, which will be labelled |tikzlabel|. % % % \section{Package, Environment and Macro options} % For convenience, all options at all levels share the same namespace. Therefore, all % options passed to the package will be the defaults for all environment, which will % in turn be the defaults for all subsequent macro calls. % % % \DescribeKey[1.5cm]{radius} % {This option controls the radius of the qubit, and can be specified in any valid \LaTeX units.} % % % \DescribeKey[15]{tilt}{This option controls the tilt (into the page) of the top of the bloch sphere (in degrees).} % % % \DescribeKey[-20]{rotation}{This option controls the (right-handed) rotation of the Blochsphere around the (potentially tilted) z-axis, also specified in degrees.} % % % \DescribeKey[white]{color}{This specifies the colour of the drawn ball.} % % % \DescribeKey[0.7]{opacity}{This option controls the opacity of the ball, allowing lines drawn behind the ball to be visible.} % % % \DescribeKey[]{style}{This option controls the current drawing style, and supports any valid tikz styling.} % % % \DescribeKey[1]{scale}{This option allows one to temporarily change the scale of drawn circles/etc, allowing annotations to ``hover'' over the Bloch sphere.} % % % \DescribeKey[current plane]{plane}{The name which should label the current plane being defined, or the plane to be used.} % % % \DescribeKey[(0,0,0)]{shift}{The three dimensional offset by which the currently being drawn objects should be shifted.} % % % \DescribeKey[3d]{ball}{Specifies how the ball should be drawn. Options are: {\tt 3d}, {\tt circle}, {\tt none}} % % % \DescribeKey[black]{statecolor}{The color with which the state vectors should be drawn.} % % % \DescribeKey[0.4pt]{statewidth}{The width with which state vectors should be drawn.} % % % \DescribeKey[]{axisarrow}{The arrow to use at the end of a drawn axis.} % % % \DescribeKey[false]{labelmark}{Whether a black dot should be drawn at the point being labelled.} % % % \DescribeKey[false]{nested}{Whether the {\tt blochsphere} environment is being nested in a |tikzpicture| environment. If it is nested, then this should be set to true.} % % % \section{Example} % In this section we provide example code to generate the following diagram: % % \begin{figure}[h!] % \begin{center} % \includegraphics{example.pdf} % \end{center} % \caption{Example Bloch Sphere \label{fig:blochsphere}} % \end{figure} % % \newminted{latex}{gobble=2,linenos} % \begin{latexcode} % \begin{blochsphere}[radius=1.5 cm,tilt=15,rotation=-20] % \drawBallGrid[style={opacity=0.3}]{30}{30} % % \drawGreatCircle[style={dashed}]{-60}{0}{0} % \drawGreatCircle[style={dashed}]{60}{0}{0} % % \drawRotationLeft[scale=1.3,style={red}]{-60}{0}{0}{15} % \drawRotationRight[scale=1.3,style={red}]{60}{0}{0}{15} % % \node at (-0.8,1.9) {\textcolor{red}{\tiny $J_{12}(t)$}}; % \node at (1.1,1.8) {\textcolor{red}{\tiny $J_{23}(t)$}}; % % \labelLatLon{up}{90}{0}; % \labelLatLon{down}{-90}{90}; % \node[above] at (up) {{\tiny $\left|1\right>$ }}; % \node[below] at (down) {{\tiny $\left|0\right>$}}; % % \labelLatLon[labelmark=false]{d}{15}{90}; % \node at (d) {\color{gray}\fontsize{0.15cm}{1em}\selectfont $60^\circ$}; % % \labelLatLon[labelmark=falsa]{d2}{5}{78}; % \node at (d2) {\color{gray}\fontsize{0.15cm}{1em}\selectfont $60^\circ$}; % \end{blochsphere} % \end{latexcode} % % \StopEventually{} % % \section{Implementation} % % \iffalse %<*package> % \fi % \subsection{Preamble} % \begin{macrocode} \NeedsTeXFormat{LaTeX2e}[1994/06/01] \ProvidesPackage{blochsphere}[2015/08/17] % \end{macrocode} % \iffalse %% \usepackage{trace} %%\tracingall % \fi % % \begin{macrocode} \usepackage{tikz,etoolbox,environ,ifthen,kvsetkeys,kvoptions} \usetikzlibrary{decorations.pathreplacing, decorations.markings, calc, fadings} % \end{macrocode} % % \subsection{Package/Environment/Macro options} % % \begin{key}{blochsphere}{radius} % \begin{macrocode} \define@key{blochsphere}{radius}{% \def\blochsphere@radius{#1}% } \providecommand{\blochsphere@radius}{1cm} % \end{macrocode} % \end{key} % % % \begin{key}{blochsphere}{tilt} % \begin{macrocode} \define@key{blochsphere}{tilt}{% \def\blochsphere@tilt{#1}% } \providecommand{\blochsphere@tilt}{15} % \end{macrocode} % \end{key} % % % \begin{key}{blochsphere}{rotation} % \begin{macrocode} \define@key{blochsphere}{rotation}{% \def\blochsphere@rotation{#1}% } \providecommand{\blochsphere@rotation}{-20} % \end{macrocode} % \end{key} % % % \begin{key}{blochsphere}{color} % \begin{macrocode} \define@key{blochsphere}{color}{% \def\blochsphere@color{#1}% } \providecommand{\blochsphere@color}{white} % \end{macrocode} % \end{key} % % % \begin{key}{blochsphere}{opacity} % \begin{macrocode} \define@key{blochsphere}{opacity}{% \def\blochsphere@opacity{#1}% } \providecommand{\blochsphere@opacity}{0.7} % \end{macrocode} % \end{key} % % % \begin{key}{blochsphere}{style} % \begin{macrocode} \define@key{blochsphere}{style}{% \def\blochsphere@style{#1}% } \providecommand{\blochsphere@style}{} % \end{macrocode} % \end{key} % % % \begin{key}{blochsphere}{scale} % \begin{macrocode} \define@key{blochsphere}{scale}{% \def\blochsphere@scale{#1}% } \providecommand{\blochsphere@scale}{1} % \end{macrocode} % \end{key} % % % \begin{key}{blochsphere}{plane} % \begin{macrocode} \define@key{blochsphere}{plane}{% \def\blochsphere@plane{#1}% } \providecommand{\blochsphere@plane}{current plane} % \end{macrocode} % \end{key} % % % \begin{key}{blochsphere}{shift} % \begin{macrocode} \define@key{blochsphere}{shift}{% \def\blochsphere@shift{{#1}}% } \providecommand{\blochsphere@shift}{{0,0,0}} % \end{macrocode} % \end{key} % % % \begin{key}{blochsphere}{ball} % \begin{macrocode} \define@key{blochsphere}{ball}{% \def\blochsphere@ball{#1}% } \providecommand{\blochsphere@ball}{3d} % \end{macrocode} % \end{key} % % % \begin{key}{blochsphere}{statecolor} % \begin{macrocode} \define@key{blochsphere}{statecolor}{% \def\blochsphere@statecolor{#1}% } \providecommand{\blochsphere@statecolor}{black} % \end{macrocode} % \end{key} % % % \begin{key}{blochsphere}{statewidth} % \begin{macrocode} \define@key{blochsphere}{statewidth}{% \def\blochsphere@statewidth{#1}% } \providecommand{\blochsphere@statewidth}{0.4pt} % \end{macrocode} % \end{key} % % % \begin{key}{blochsphere}{axisarrow} % \begin{macrocode} \define@key{blochsphere}{axisarrow}{% \def\blochsphere@axisarrow{#1}% } \providecommand{\blochsphere@axisarrow}{} % \end{macrocode} % \end{key} % % % \begin{key}{blochsphere}{labelmark} % \begin{macrocode} \define@key{blochsphere}{labelmark}{% \setboolean{blochsphere@labelmark}{#1}% } \newboolean{blochsphere@labelmark} \setboolean{blochsphere@labelmark}{false} % \end{macrocode} % \end{key} % % % \begin{key}{blochsphere}{nested} % \begin{macrocode} \define@key{blochsphere}{nested}{% \setboolean{blochsphere@nested}{#1}% } \newboolean{blochsphere@nested} \setboolean{blochsphere@nested}{false} % \end{macrocode} % \end{key} % \begin{macrocode} \ProcessKeyvalOptions{blochsphere}\relax % \end{macrocode} % % \subsection{{\bfseries\tt blochsphere} Environment} % This is the central environment definition. Note that all macros defined % below will only be defined within this environment. % % \begin{environment}{blochsphere} % \begin{macrocode} \newenvironment{blochsphere}[1][]{ \begingroup \makeatletter \ignorespaces\setkeys{blochsphere}{#1}\unskip% \pgfdeclarelayer{back}% \pgfdeclarelayer{front}% \pgfsetlayers{back,main,front}% \pgfkeys{% /tikz/on layer/.code={% \pgfonlayer{##1}\begingroup% \aftergroup\endpgfonlayer% \aftergroup\endgroup% },% /tikz/node on layer/.code={% \gdef\node@@on@layer{% \setbox\tikz@tempbox=\hbox\bgroup\pgfonlayer{##1}\unhbox\tikz@tempbox\endpgfonlayer\egroup}% \aftergroup\node@on@layer% },% /tikz/end node on layer/.code={% \endpgfonlayer\endgroup\endgroup% }% }% \def\node@on@layer{\aftergroup\node@@on@layer}% % \end{macrocode} % \begin{macro}{\drawBall} % \begin{macrocode} \newcommand\drawBall[1][]{ \begingroup \setkeys{blochsphere}{##1} \expandafter\ifstrequal\expandafter{\blochsphere@ball}{3d}{ \fill[on layer=main,ball color=\blochsphere@color,opacity=\blochsphere@opacity] (0,0) circle (\blochsphere@radius); % 3D lighting effect }{} \expandafter\ifstrequal\expandafter{\blochsphere@ball}{circle}{ \draw[on layer=main,color=\blochsphere@color] (0,0) circle (\blochsphere@radius); % 3D lighting effect }{} \endgroup }% % \end{macrocode} % \end{macro} % \begin{macro}{\drawBallGrid} % \begin{macrocode} \newcommand\drawBallGrid[3][]{ \begingroup \setkeys{blochsphere}{##1} \foreach \phi in {0,##2,...,89} { \drawLatitudeCircle{\phi} \drawLatitudeCircle{-\phi} } \foreach \theta in {0,##3,...,179} { \drawLongitudeCircle{\theta} } \endgroup }% % \end{macrocode} % \end{macro} % \begin{macro}{\setDrawingPlane} % \begin{macrocode} \newcommand\setDrawingPlane[3][]{% \setkeys{blochsphere}{##1} \pgfmathsetmacro\aphi{##2} \pgfmathsetmacro\atheta{##3} \pgfmathsetmacro\dot{cos(\aphi)} \ifdim\dot pt<0.7 pt\relax% \pgfmathsetmacro\norm{cos(asin(\dot))} \pgfmathsetmacro\xx{-sin(\aphi)*sin(\blochsphere@rotation - \atheta)} \pgfmathsetmacro\xy{sin(\aphi)*sin(\blochsphere@tilt)*cos(\blochsphere@rotation - \atheta)} \pgfmathsetmacro\yx{-sin(2*\aphi - \blochsphere@rotation + \atheta)/4 - sin(2*\aphi + \blochsphere@rotation - \atheta)/4} \pgfmathsetmacro\yy{(sin(\aphi)*cos(\blochsphere@tilt) - sin(\blochsphere@tilt)*sin(\blochsphere@rotation - \atheta)*cos(\aphi))*sin(\aphi)} \else \pgfmathsetmacro\norm{sqrt(abs(sin(\blochsphere@rotation - \atheta)*cos(\aphi))^2 + abs(sin(\blochsphere@tilt)*cos(\aphi)*cos(\blochsphere@rotation - \atheta))^2 + abs(cos(\aphi)*cos(\blochsphere@tilt)*cos(\blochsphere@rotation - \atheta))^2)} \pgfmathsetmacro\xx{-sin(\blochsphere@rotation - \atheta)*cos(\aphi)} \pgfmathsetmacro\xy{sin(\blochsphere@tilt)*cos(\aphi)*cos(\blochsphere@rotation - \atheta)} \pgfmathsetmacro\yx{-cos(\aphi)^2*cos(\blochsphere@rotation - \atheta)} \pgfmathsetmacro\yy{(sin(\aphi)*cos(\blochsphere@tilt) - sin(\blochsphere@tilt)*sin(\blochsphere@rotation - \atheta)*cos(\aphi))*cos(\aphi)} \fi \computeOffset{shift} \begingroup\newcommand\tmp[1]{\endgroup\noexpand\relax% \tikzset{\blochsphere@plane/.style={cm={\xx/\norm, \xy/\norm, \yx/\norm, \yy/\norm, \unexpanded\expandafter{####1} }}}% } \tmp{\shift} }% % \end{macrocode} % \end{macro} % \begin{macro}{\setLatitudinalDrawingPlane} % \begin{macrocode} \newcommand\setLatitudinalDrawingPlane[2][]{% \pgfmathsetmacro\yshift{sin(##2)*\the\blochsphere@radius} \setDrawingPlane[##1,shift={{0,0,\yshift}}]{0}{0} }% % \end{macrocode} % \end{macro} % \begin{macro}{\setLatitudinalDrawingPlane} % \begin{macrocode} \newcommand\setLongitudinalDrawingPlane[2][]{% \setDrawingPlane[##1]{90}{##2} }% % \end{macrocode} % \end{macro} % \begin{macro}{\drawCircle} % \begin{macrocode} \newcommand\drawCircle[3][]{ \begingroup \setkeys{blochsphere}{##1} \setDrawingPlane{##2}{##3} \computeVisibility{##2}{##3}{agamma}{abeta} \begingroup\edef\tmp{\endgroup% \noexpand\draw[current plane,on layer=back,\unexpanded\expandafter{\blochsphere@style}] \unexpanded\expandafter{(\agamma-\abeta-0.2:\blochsphere@radius+\the\pgflinewidth*0.5) arc (\agamma-\abeta-0.2:\agamma+\abeta+0.2:\blochsphere@radius+\the\pgflinewidth*0.5)}; \noexpand\draw[current plane,on layer=front,\unexpanded\expandafter{\blochsphere@style}] \unexpanded\expandafter{(\agamma+\abeta:\blochsphere@radius+\the\pgflinewidth*0.5) arc (\agamma+\abeta:\agamma-\abeta+360:\blochsphere@radius+\the\pgflinewidth*0.5)}; } \tmp \endgroup }% % \end{macrocode} % \end{macro} % \begin{macro}{\drawGreatCircle} % \begin{macrocode} \newcommand\drawGreatCircle[3][]{ \drawCircle[##1]{##2}{##3} } % \end{macrocode} % \end{macro} % \begin{macro}{\drawSmallCircle} % \begin{macrocode} \newcommand\drawSmallCircle[4][]{ \begingroup \pgfmathsetmacro\xshift{sin(##2)*cos(##3)*\blochsphere@radius*sin(##4)} \pgfmathsetmacro\yshift{sin(##2)*sin(##3)*\blochsphere@radius*sin(##4)} \pgfmathsetmacro\zshift{cos(##2)*\blochsphere@radius*sin(##4)} \pgfmathsetmacro\radius{\blochsphere@radius*cos(##4)} \drawCircle[##1,shift={{\xshift,\yshift,\zshift}},radius=\radius]{##2}{##3} \endgroup }% % \end{macrocode} % \end{macro} % \begin{macro}{\drawLatitudeCircle} % \begin{macrocode} \newcommand\drawLatitudeCircle[2][]{ \begingroup \pgfmathsetmacro\yshift{sin(##2)*\blochsphere@radius} \pgfmathsetmacro\radius{\blochsphere@radius*cos(##2)} \drawCircle[##1,shift={{0,0,\yshift}},radius=\radius]{0}{0} \endgroup }% % \end{macrocode} % \end{macro} % \begin{macro}{\drawLongitudeCircle} % \begin{macrocode} \newcommand\drawLongitudeCircle[2][]{ \begingroup \drawCircle[##1]{90}{##2+90} \endgroup }% % \end{macrocode} % \end{macro} % \begin{macro}{\drawRotationLeft} % \begin{macrocode} \newcommand\drawRotationLeft[5][]{ \begingroup \setkeys{blochsphere}{##1} \pgfmathsetmacro\xshift{sin(##2)*cos(##3)*##4} \pgfmathsetmacro\yshift{sin(##2)*sin(##3)*##4} \pgfmathsetmacro\zshift{cos(##2)*##4} \setDrawingPlane[shift={\xshift,\yshift,\zshift}]{##2}{##3} \computeVisibility{##2}{##3}{agamma}{abeta} \begingroup\edef\tmp{\endgroup% \noexpand\draw[current plane,on layer=back,\unexpanded\expandafter{\blochsphere@style}] \unexpanded\expandafter{(\agamma-\abeta-0.2:\blochsphere@radius*\blochsphere@scale+\the\pgflinewidth*0.5) arc (\agamma-\abeta-0.2:\agamma+\abeta+0.2:\blochsphere@radius*\blochsphere@scale+\the\pgflinewidth*0.5)}; \noexpand\draw[<-,current plane,on layer=front,\unexpanded\expandafter{\blochsphere@style}] \unexpanded\expandafter{(\agamma+\abeta+##5:\blochsphere@radius*\blochsphere@scale+\the\pgflinewidth*0.5) arc (\agamma+\abeta+##5:\agamma-\abeta+360:\blochsphere@radius*\blochsphere@scale+\the\pgflinewidth*0.5)}; } \tmp \endgroup }% % \end{macrocode} % \end{macro} % \begin{macro}{\drawRotationRight} % \begin{macrocode} \newcommand\drawRotationRight[5][]{ \begingroup \setkeys{blochsphere}{##1} \pgfmathsetmacro\xshift{sin(##2)*cos(##3)*##4} \pgfmathsetmacro\yshift{sin(##2)*sin(##3)*##4} \pgfmathsetmacro\zshift{cos(##2)*##4} \setDrawingPlane[shift={\xshift,\yshift,\zshift}]{##2}{##3} \computeVisibility{##2}{##3}{agamma}{abeta} \begingroup\edef\tmp{\endgroup% \noexpand\draw[current plane,on layer=back,\unexpanded\expandafter{\blochsphere@style}] \unexpanded\expandafter{(\agamma-\abeta-0.2:\blochsphere@radius*\blochsphere@scale+\the\pgflinewidth*0.5) arc (\agamma-\abeta-0.2:\agamma+\abeta+0.2:\blochsphere@radius*\blochsphere@scale+\the\pgflinewidth*0.5)}; \noexpand\draw[->,current plane,on layer=front,\unexpanded\expandafter{\blochsphere@style}] \unexpanded\expandafter{(\agamma+\abeta:\blochsphere@radius*\blochsphere@scale+\the\pgflinewidth*0.5) arc (\agamma+\abeta:\agamma-\abeta+360-##5:\blochsphere@radius*\blochsphere@scale+\the\pgflinewidth*0.5)}; } \tmp \endgroup }% % \end{macrocode} % \end{macro} % \begin{macro}{\drawAxis} % \begin{macrocode} \newcommand\drawAxis[3][] { \begingroup \setkeys{blochsphere}{##1} \pgfmathsetmacro\behind{ifthenelse(-sin(##2)*sin(\blochsphere@rotation - ##3)*cos(\blochsphere@tilt) + sin(\blochsphere@tilt)*cos(##2)<0, 1, 0)} \pgfmathsetmacro\newphi{180-##2} \pgfmathsetmacro\newtheta{##3+180} \ifnum\behind=0\relax \labelPolar[scale=1]{blochspheretmpp}{##2}{##3} \labelPolar{blochspheretmps}{##2}{##3} \labelPolar{blochspheretmpe}{\newphi}{\newtheta} \else \labelPolar[scale=1]{blochspheretmpp}{\newphi}{\newtheta} \labelPolar{blochspheretmpe}{##2}{##3} \labelPolar{blochspheretmps}{\newphi}{\newtheta} \fi \begingroup\edef\tmp{\endgroup% \ifnum\behind=0\relax \noexpand\draw[on layer=front,\unexpanded\expandafter{\blochsphere@style},\blochsphere@axisarrow] (blochspheretmpp) -- (blochspheretmps); \noexpand\draw[on layer=back,\unexpanded\expandafter{\blochsphere@style}] (blochspheretmpe) -- (blochspheretmpp); \else \noexpand\draw[on layer=front,\unexpanded\expandafter{\blochsphere@style},\blochsphere@axisarrow] (blochspheretmpp) -- (blochspheretmpe); \noexpand\draw[on layer=back,\unexpanded\expandafter{\blochsphere@style}] (blochspheretmps) -- (blochspheretmpp); \fi } \tmp \endgroup }% % \end{macrocode} % \end{macro} % \begin{macro}{\labelPolar} % \begin{macrocode} \newcommand\labelPolar[4][]{% \begingroup \setkeys{blochsphere}{##1} \setLongitudinalDrawingPlane{##4+90} \pgfmathsetmacro\behind{ifthenelse(-sin(##3)*sin(\blochsphere@rotation - ##4)*cos(\blochsphere@tilt) + sin(\blochsphere@tilt)*cos(##3)<0, 1, 0)} \ifthenelse{\boolean{blochsphere@labelmark}} { \ifnum\behind=1\relax \path[current plane,on layer=back] (90-##3:\blochsphere@radius*\blochsphere@scale) coordinate[mark coordinate] (##2); % \else \path[current plane,on layer=front] (90-##3:\blochsphere@radius*\blochsphere@scale) coordinate[mark coordinate] (##2); % \fi } { \ifnum\behind=1\relax \path[current plane,on layer=back] (90-##3:\blochsphere@radius*\blochsphere@scale) coordinate (##2); % \else \path[current plane,on layer=front] (90-##3:\blochsphere@radius*\blochsphere@scale) coordinate (##2); % \fi } \endgroup }% % \end{macrocode} % \end{macro} % \begin{macro}{\labelLatLon} % \begin{macrocode} \newcommand\labelLatLon[4][]{% \begingroup \pgfmathsetmacro\newphi{90-##3} \labelPolar[##1]{##2}{\newphi}{##4} \endgroup }% % \end{macrocode} % \end{macro} % \begin{macro}{\drawStateLatLon} % \begin{macrocode} \newcommand\drawStateLatLon[4][]{ \begingroup \pgfmathsetmacro\newphi{90-##3} \drawStatePolar[##1]{##2}{\newphi}{##4} \endgroup }% % \end{macrocode} % \end{macro} % \begin{macro}{\drawStatePolar} % \begin{macrocode} \newcommand\drawStatePolar[4][]{ \begingroup \setkeys{blochsphere}{##1} \labelPolar{##2}{##3}{##4} \pgfmathsetmacro\behind{ifthenelse(-sin(##3)*sin(\blochsphere@rotation - ##4)*cos(\blochsphere@tilt) + sin(\blochsphere@tilt)*cos(##3)<0, 1, 0)} \ifnum\behind=1\relax \tikzset{test/.style={ postaction={ decorate, decoration={ markings, mark=at position \pgfdecoratedpathlength-0.5pt with {\arrow[\blochsphere@statecolor,line width=\blochsphere@statewidth,opacity=0.2] {>}; }, mark=between positions 0 and \pgfdecoratedpathlength-5pt step 0.5pt with { \pgfmathsetmacro\myval{multiply(divide( \pgfkeysvalueof{/pgf/decoration/mark info/distance from start}, \pgfdecoratedpathlength),100)}; \pgfsetfillcolor{\blochsphere@statecolor}; \pgfsetfillopacity{0.4-\myval/100*0.2} \pgfpathcircle{\pgfpointorigin}{\blochsphere@statewidth}; \pgfusepath{fill};} }}}} \else \tikzset{test/.style={ postaction={ decorate, decoration={ markings, mark=at position \pgfdecoratedpathlength-0.5pt with {\arrow[\blochsphere@statecolor,line width=\blochsphere@statewidth] {>}; }, mark=between positions 0 and \pgfdecoratedpathlength-5pt step 0.5pt with { \pgfmathsetmacro\myval{multiply(divide( \pgfkeysvalueof{/pgf/decoration/mark info/distance from start}, \pgfdecoratedpathlength),100)}; \pgfsetfillcolor{\blochsphere@statecolor}; \pgfsetfillopacity{0.4+\myval/100*0.6} \pgfpathcircle{\pgfpointorigin}{\blochsphere@statewidth}; \pgfusepath{fill};} }}}} \fi \path [test,on layer=main] (0,0) -- (##2); \endgroup }% % \end{macrocode} % \end{macro} % \begin{macro}{\computeOffset} % \begin{macrocode} \newcommand\computeOffset[2][]{% \setkeys{blochsphere}{##1}% \pgfmathsetmacro{\x}{\blochsphere@shift[0]*cos(\blochsphere@rotation) + \blochsphere@shift[1]*sin(\blochsphere@rotation)}% \pgfmathsetmacro\y{\blochsphere@shift[0]*sin(\blochsphere@rotation)*sin(\blochsphere@tilt) - \blochsphere@shift[1]*sin(\blochsphere@tilt)*cos(\blochsphere@rotation) + \blochsphere@shift[2]*cos(\blochsphere@tilt)} \expandafter\def\csname ##2\endcsname{(\x pt,\y pt)}% }% % \end{macrocode} % \end{macro} % \begin{macro}{\computeVisibility} % \begin{macrocode} \newcommand\computeVisibility[5][]{ \setkeys{blochsphere}{##1} \pgfmathsetmacro\aphi{##2} \pgfmathsetmacro\atheta{##3} \pgfmathsetmacro\d{sqrt(\blochsphere@shift[0]^2+\blochsphere@shift[1]^2+\blochsphere@shift[2]^2)}%% distance from origin of shift \pgfmathsetmacro\tatheta{\atheta+\blochsphere@rotation} \pgfmathsetmacro\dot{cos(\aphi)} \ifdim\dot pt<0.7 pt\relax% \pgfmathsetmacro\domaintest{ifthenelse(and(\blochsphere@rotation - \atheta==0,or(\aphi==0,sin(\blochsphere@tilt==0))),0,1)} \ifdim\domaintest pt=0 pt\relax \pgfmathsetmacro\agamma{0} \else \pgfmathsetmacro\agamma{-90+atan(cos(\blochsphere@tilt)*cos(\blochsphere@rotation - \atheta)/(sin(\aphi)*sin(\blochsphere@tilt) + sin(\blochsphere@rotation - \atheta)*cos(\aphi)*cos(\blochsphere@tilt)))} \fi \else \pgfmathsetmacro\domaintest{ifthenelse(and(Mod(\blochsphere@rotation-\atheta,180)==90,Mod(\blochsphere@tilt,180)==90),0,1)} \pgfmathsetmacro\domaintesttwo{ifthenelse(Mod(\blochsphere@rotation-\atheta,180)==90,0,1)} \pgfmathsetmacro\domaintestthree{ifthenelse(Mod(\blochsphere@tilt,180)==90,0,1)} \ifdim\domaintest pt=0 pt\relax \pgfmathsetmacro\agamma{360-90*\blochsphere@tilt/abs(\blochsphere@tilt)} \else \ifdim\domaintesttwo pt=0 pt\relax \pgfmathsetmacro\agamma{360-90*(sin(\aphi)*tan(\blochsphere@tilt)+cos(\aphi)*sin(\blochsphere@rotation-\atheta))/abs(sin(\aphi)*tan(\blochsphere@tilt)+cos(\aphi)*sin(\blochsphere@rotation-\atheta))} \else \ifdim\domaintestthree pt=0 pt\relax \pgfmathsetmacro\agamma{360-90*\blochsphere@tilt/abs(\blochsphere@tilt)*cos(\blochsphere@rotation-\atheta)/abs(cos(\blochsphere@rotation-\atheta))} \else \pgfmathsetmacro\agamma{360-atan( (sin(\aphi)*tan(\blochsphere@tilt)+cos(\aphi)*sin(\blochsphere@rotation-\atheta))/cos(\blochsphere@rotation-\atheta) )} \fi \fi \fi \fi \pgfmathsetmacro\aalpha{acos(-sin(\aphi)*sin(\blochsphere@rotation)*cos(\atheta)*cos(\blochsphere@tilt) + sin(\aphi)*sin(\atheta)*cos(\blochsphere@rotation)*cos(\blochsphere@tilt) + sin(\blochsphere@tilt)*cos(\aphi))} \pgfmathsetmacro\aalphatest{atan(\d/\blochsphere@radius)} \ifdim\aalpha pt<\aalphatest pt\relax \pgfmathsetmacro\abeta{0} \else \pgfmathsetmacro\abeta{acos(\d*cot(\aalpha)/\blochsphere@radius)} \fi \pgfmathsetmacro\abeta{ifthenelse(\blochsphere@shift[2]<0,\abeta+2*(90-\abeta),\abeta)} \expandafter\pgfmathsetmacro\csname ##4\endcsname{\agamma} \expandafter\pgfmathsetmacro\csname ##5\endcsname{\abeta} }% % \end{macrocode} % \end{macro} % \begin{macrocode} \tikzset{% >=latex, % option for nice arrows inner sep=0pt,% outer sep=2pt,% mark coordinate/.style={inner sep=0pt,outer sep=0pt,minimum size=3pt, fill=black,circle}% }% \pgfdeclareradialshading[tikz@ball]{ball}{\pgfqpoint{-10bp}{10bp}}{% color(0bp)=(tikz@ball!30!white); color(9bp)=(tikz@ball!75!white); color(18bp)=(tikz@ball!90!black); color(25bp)=(tikz@ball!70!black); color(50bp)=(black) }% \ifthenelse{\boolean{blochsphere@nested}}{}{% \begin{tikzpicture} \drawBall }% } % \end{macrocode} % \end{environment} % \begin{macrocode} { \ifthenelse{\boolean{blochsphere@nested}}{}{ \end{tikzpicture}% }% \endgroup% } \endinput % \end{macrocode} % % \iffalse % % \fi % % \Finale \endinput