%% Package `pst-magneticfield.tex'
%%
%% Manuel Luque
%% JÃ¼rgen Gilg  (â€  2022)
%% Herbert VoÃŸ
%%
%% This program can be redistributed and/or modified under
%% the terms of the LaTeX Project Public License Distributed
%% from CTAN archives in directory macros/latex/base/lppl.txt.
%%
%% A PSTricks related package to draw magnetic field lines
%% It uses the method from Heun
%%
\csname PSTMagneticFieldLoaded\endcsname
\let\PSTMagneticFieldLoaded\endinput
%
% Requires some packages
\ifx\PSTricksLoaded\endinput\else \input pstricks   \fi
\ifx\PSTthreeDLoaded\endinput\else\input pst-3d     \fi
\ifx\PSTnodesLoaded\endinput\else \input pst-node   \fi
\ifx\PSTarrowLoaded\endinput\else \input pst-arrow \fi
\ifx\MultidoLoaded\endinput\else  \input multido.tex\fi
\ifx\PSTXKeyLoaded\endinput\else  \input pst-xkey   \fi
%
\def\fileversion{1.17}
\def\filedate{2022/07/06}
\message{`pst-magneticfield' v\fileversion, \filedate\space (ml,jg,hv)}
%
\edef\PstAtCode{\the\catcode`\@} \catcode`\@=11\relax
%
\SpecialCoor
\pst@addfams{pst-magneticfield}

%% prologue for postcript
\pstheader{pst-magneticfield.pro}%

% the first three parameter cannot be read with \pst@getint, because \pstFP.. do not like
% the values ... used in \psmagenticfieldThreeD
\define@key[psset]{pst-magneticfield}{R}[1]{\def\psk@magneticfieldR{#1}}% rayon d'une spire
\define@key[psset]{pst-magneticfield}{N}[6]{\def\psk@magneticfieldN{#1}}% nombre de spires
\define@key[psset]{pst-magneticfield}{L}[4]{\def\psk@magneticfieldL{#1}}% Longueur de la bobine
\define@key[psset]{pst-magneticfield}{nL}[8]{\pst@getint{#1}\psk@magneticfieldNL}% nombre de lignes de champ
\define@key[psset]{pst-magneticfield}{numSpires}[]{\def\psk@magneticfieldChoixSpires{#1}}% choix individuel des spires
\psset[pst-magneticfield]{numSpires=}% toutes les spires par défaut
\define@key[psset]{pst-magneticfield}{pointsB}[500]{\pst@getint{#1}\psk@magneticfieldB}
\define@key[psset]{pst-magneticfield}{pointsS}[1000]{\pst@getint{#1}\psk@magneticfieldS}% nombre de points autour de chaque spire
\define@key[psset]{pst-magneticfield}{PasB}[0.02]{\pst@checknum{#1}\psk@magneticfieldPasB}% incrément du tracé autour de la bobine
\define@key[psset]{pst-magneticfield}{PasS}[0.00275]{\pst@checknum{#1}\psk@magneticfieldPasS}% incrément du tracé autour de chaque spire
\define@key[psset]{pst-magneticfield}{nS}[1]{\pst@getint{#1}\psk@magneticfieldNS}% nombre de lignes autour de chaque spire
\define@key[psset]{pst-magneticfield}{styleSpire}[styleSpire]{\def\psk@styleSpire{#1}}
\define@key[psset]{pst-magneticfield}{styleCourant}[sensCourant]{\def\psk@styleCourant{#1}}
%
\newpsstyle{styleSpire}{linecap=1,linecolor=red,linewidth=2\pslinewidth}
\newpsstyle{sensCourant}{linecolor=red,linewidth=2\pslinewidth,arrowinset=0.1}
%
\define@boolkey[psset]{pst-magneticfield}[Pst@]{drawSelf}[true]{}
\define@boolkey[psset]{pst-magneticfield}[Pst@]{AntiHelmholtz}[true]{}
\define@boolkey[psset]{pst-magneticfield}[Pst@]{StreamDensityPlot}[true]{}
\define@boolkey[psset]{pst-magneticfield}[Pst@]{setgray}[true]{}
\define@boolkey[psset]{pst-magneticfield}[Pst@]{changeNS}[true]{}
%
\psset[pst-magneticfield]{R=1,L=4,N=6,pointsB=500,pointsS=1000,
  PasB=0.02,PasS=0.00275,nS=1,nL=8,drawSelf,styleSpire=styleSpire,
  styleCourant=sensCourant,AntiHelmholtz=false,StreamDensityPlot=false,setgray=false,
  changeNS=false}
%
\def\tx@MFieldDict{ tx@MFieldDict begin }
%
\def\psmagneticfield{\pst@object{psmagneticfield}}
\def\psmagneticfield@i{\@ifnextchar({\psmagneticfield@ii}{\psmagneticfield@iii(-6,-5)(6,5)}}
\def\psmagneticfield@ii(#1,#2){\@ifnextchar({\psmagneticfield@iii(#1,#2)}{\psmagneticfield@iii(#1,#2)(6,5)}}
\def\psmagneticfield@iii(#1,#2)(#3,#4){%
  \pst@killglue%
  \ifPst@AntiHelmholtz\addbefore@par{N=2}\fi%
  \begin@SpecialObj%
  \pst@Verb{%  make it global
    /NombreSpires \psk@magneticfieldN\space def
    /Radius \psk@magneticfieldR\space def
    /nombreLignes \psk@magneticfieldNL\space def
    /TableauSpires [\psk@magneticfieldChoixSpires] def
    /StepLines Radius nombreLignes 1 add div def
    NombreSpires 1 eq
      { /Longueur 0 def
        /inter 0 def }
      { /Longueur \psk@magneticfieldL\space def
        /inter Longueur NombreSpires 1 sub div def } ifelse % intervalle entre 2 spires
    \ifPst@AntiHelmholtz
      /AntiHelmholtz true def
      TableauSpires length 0 eq {/TS [1 2] def}
                                {/TS TableauSpires def } ifelse
      /inter Radius def
      /yA Radius 2 div def
    \else
      /AntiHelmholtz false def
      TableauSpires length 0 eq {/TS [1 1 NombreSpires {} for] def}
                                {/TS TableauSpires def } ifelse
      /yA Longueur 2 div def
    \fi
    /NbrePointsB \psk@magneticfieldB\space def
    /NbrePointsS \psk@magneticfieldS\space def
    /PasB \psk@magneticfieldPasB\space def
    /PasS \psk@magneticfieldPasS\space def
    /nS \psk@magneticfieldNS\space def
% pour la carte de densite
    /xMin #1 def
    /xMax #3 def
 %      NombreSpires 1 eq {/yMax 2 Radius mul def}{/yMax Longueur 2 mul def} ifelse
    /yMax #4 def
    /yMin #2 def
    /Unit \pst@number\psunit def
    /xUnit \pst@number\psxunit def
    /yUnit \pst@number\psyunit def
    /StreamDensityPlot \ifPst@StreamDensityPlot true \else false \fi def
    /Setgray \ifPst@setgray true \else false \fi def
  }%
  \addto@pscode{ \tx@MFieldDict %\pst@magnetrotate rotate 
                        MagneticField end }%
  \ifPst@drawSelf
    \ifPst@AntiHelmholtz
      \psline[style=\psk@styleSpire](!Radius neg Radius 2 div)(!Radius Radius 2 div)
      \psline[style=\psk@styleSpire](!Radius neg Radius 2 div neg)(!Radius Radius 2 div neg)
      \ifPst@changeNS
        \psline[style=\psk@styleCourant]{->}(!-0.2 Radius 2 div)(!0.2 Radius 2 div)
        \psline[style=\psk@styleCourant]{<-}(!-0.2 Radius 2 div neg)(!0.2 Radius 2 div neg)
      \else
        \psline[style=\psk@styleCourant]{<-}(!-0.2 Radius 2 div)(!0.2 Radius 2 div)
        \psline[style=\psk@styleCourant]{->}(!-0.2 Radius 2 div neg)(!0.2 Radius 2 div neg)
      \fi
    \else
      \ifPst@changeNS
        \multido{\i=1+1}{\psk@magneticfieldN}{% numero de la spire
          \pst@Verb{ /Yspire yA \i\space 1 sub inter mul sub def } % position de la spire
          \psline[style=\psk@styleSpire](! Radius neg Yspire)(! Radius Yspire)
          \psline[style=\psk@styleCourant]{<-}(! -0.2 Yspire)(! 0.2 Yspire)}%
      \else
        \multido{\i=1+1}{\psk@magneticfieldN}{% numero de la spire
          \pst@Verb{ /Yspire yA \i\space 1 sub inter mul sub def } % position de la spire
          \psline[style=\psk@styleSpire](! Radius neg Yspire)(! Radius Yspire)
          \psline[style=\psk@styleCourant]{->}(! -0.2 Yspire)(! 0.2 Yspire)}%
      \fi
    \fi
  \fi
  \end@SpecialObj
  \ignorespaces}
%
\newpsstyle{grille}{subgriddiv=0,gridcolor=lightgray,griddots=10}
\newpsstyle{cadre}{linecolor=green!20}
%
\def\psmagneticfieldThreeD{\pst@object{psmagneticfieldThreeD}}
\def\psmagneticfieldThreeD@i(#1,#2)(#3,#4){%
  \ifPst@AntiHelmholtz\addto@par{N=2}\fi
  \begingroup
  \use@par
  \ifPst@AntiHelmholtz
    \pstFPdiv\yA{\psk@magneticfieldR}{2}
    \ThreeDput{%
      \begin{psclip}{\psframe(#1,#2)(#3,#4)}
        \psframe*[style=cadre](#1,#2)(#3,#4)
        \psgrid[style=grille](#1,#2)(#3,#4)
        \psmagneticfield[drawSelf=false](#1,#2)(#3,#4)%
      \end{psclip}}
    \ThreeDput[normal=0 1 0](0,\yA,0){%
      \psarc[linecolor=red,linewidth=3\pslinewidth](0,0){\psk@magneticfieldR}{0}{180}
      \psarc[linecolor=red,linewidth=3\pslinewidth]{<-}(0,0){\psk@magneticfieldR}{80}{90}
      \psarc[linecolor=red,linewidth=1\pslinewidth,linestyle=dashed](0,0){\psk@magneticfieldR}{180}{360}}
    \ThreeDput[normal=0 1 0](0,-\yA,0){%
      \psarc[linecolor=red,linewidth=3\pslinewidth](0,0){\psk@magneticfieldR}{0}{180}
      \psarc[linecolor=red,linewidth=3\pslinewidth]{->}(0,0){\psk@magneticfieldR}{80}{90}
      \psarc[linecolor=red,linewidth=1\pslinewidth,linestyle=dashed](0,0){\psk@magneticfieldR}{180}{360}}
  \else
    \ifnum\psk@magneticfieldN=1
      \def\MF@inter{0}
      \def\yA{0}
    \else
      \pstFPsub\CalcIntermediaire{\psk@magneticfieldN}{1}
      \pstFPdiv\MF@inter{\psk@magneticfieldL}{\CalcIntermediaire}
      \pstFPdiv\yA{\psk@magneticfieldL}{2}
    \fi
    \ThreeDput{%
      \begin{psclip}{\psframe(#1,#2)(#3,#4)}
        \psframe*[style=cadre](#1,#2)(#3,#4)
        \psgrid[style=grille](#1,#2)(#3,#4)
        \psmagneticfield[drawSelf=false](#1,#2)(#3,#4)%
      \end{psclip}}
    \multido{\iN=1+1,\iS=0+1}{\psk@magneticfieldN}{%
      \pstFPmul\MF@calcA{\iS}{\MF@inter}
      \pstFPsub\posSpire{\yA}{\MF@calcA}
      \ThreeDput[normal=0 1 0](0,\posSpire,0){%
        \psarc[style=\psk@styleSpire](0,0){\psk@magneticfieldR}{0}{180}
        \psarc[style=\psk@styleCourant]{->}(0,0){\psk@magneticfieldR}{80}{90}
        \psarc[style=\psk@styleSpire,linestyle=dashed](0,0){\psk@magneticfieldR}{180}{360}}%
    }%
  \fi
  \endgroup}
%
\define@boolkey[psset]{pst-magneticfield}[Pst@]{showField}[true]{}
\define@boolkey[psset]{pst-magneticfield}[Pst@]{showPoleLabels}[true]{}
\define@key[psset]{pst-magneticfield}{fontstyle}[\large\bfseries\sffamily]{\def\psk@label@fontstyle{#1}}
\define@key[psset]{pst-magneticfield}{magnetScale}[1 1]{\def\pst@magnetscale{#1}}
\psset[pst-magneticfield]{showPoleLabels,fontstyle=\large\bfseries\sffamily,showField=false,
                          magnetScale=1 1}

\def\ps@Bar@Magnet{%
  \psscalebox{\pst@magnetscale}{%
    \psframe*[linecolor=Green](-0.75,-1.75)(0.75,0)%
    \psframe*[linecolor=BrickRed](-0.75,0)(0.75,1.75)%
  \ifPst@showPoleLabels
    \rput{0}(0,1){\textcolor{white}{\psk@label@fontstyle N}}%
    \rput{0}(0,-1){\textcolor{white}{\psk@label@fontstyle S}}%
  \fi}
}%

\definecolor{Red}{cmyk}{0,1,1,0}
\definecolor{BrickRed}{cmyk}{0,0.89,0.94,0.28}
\definecolor{Green}{cmyk}{1,0,1,0}

\def\psBarMagnet{\pst@object{psBarMagnet}}
\def\psBarMagnet@i{\@ifnextchar(\psBarMagnet@ii{\psBarMagnet@ii(0,0)}}%
\def\psBarMagnet@ii(#1){%
  \pst@killglue
  \begingroup
  \addbefore@par{linewidth=2pt,R=0.8,L=3,N=4,pointsS=200,nL=9,nS=0,PasB=0.1,numSpires=0,arrowscale=1.5,arrowinset=0.1}%
  \use@par
  \ifPst@showField
    \rput(#1){%
      \psscalebox{0.4 0.5}{\psmagneticfield[drawSelf=false](-8,-10)(8,10)%
        \multido{\rA=0.6+0.3,\rB=0.8+0.4,\iA=-60+20,\iB=60+-20}{4}{%
          \pccurve[ncurv=\rB,angleA=\iA,angleB=\iB,ArrowInside=->,ArrowInsideNo=2](0.7,\rA)(0.7,-\rA)%
          \psscalebox{-1 1}{\pccurve[ncurv=\rB,angleA=\iA,angleB=\iB,ArrowInside=->,ArrowInsideNo=2](0.7,\rA)(0.7,-\rA)}%
        }}}%
  \fi
  \rput(#1){\ps@Bar@Magnet}%
  \endgroup
  \ignorespaces
}
%
\catcode`\@=\PstAtCode\relax
%
%% END
\endinput

