From 59161ce421c69ad679d1c22d540f51b9e68a2497 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Sun, 13 Jul 2014 21:30:08 +0000 Subject: pst-optexp git-svn-id: svn://tug.org/texlive/trunk@34592 c570f23f-e606-0410-a88d-b1316a301751 --- .../source/latex/pst-optexp/pst-optexp.dtx | 883 +++++++++++++++------ 1 file changed, 626 insertions(+), 257 deletions(-) (limited to 'Master/texmf-dist/source/latex/pst-optexp/pst-optexp.dtx') diff --git a/Master/texmf-dist/source/latex/pst-optexp/pst-optexp.dtx b/Master/texmf-dist/source/latex/pst-optexp/pst-optexp.dtx index 43723b2c978..7e3c035baa5 100644 --- a/Master/texmf-dist/source/latex/pst-optexp/pst-optexp.dtx +++ b/Master/texmf-dist/source/latex/pst-optexp/pst-optexp.dtx @@ -18,7 +18,7 @@ %\NeedsTeXFormat{LaTeX2e}[1999/12/01] %\ProvidesPackage{pst-optexp} %<*stylefile> - [2014/02/28 v4.8 Optical experimental setups with PSTricks] + [2014/06/04 v4.10 Optical experimental setups with PSTricks] % % %<*driver> @@ -111,7 +111,7 @@ oeBeamCenter, optplate, optretplate, pinhole, crystal, optdetector, optdiode, doveprism, glanthompson, polarization, mirror, beamsplitter, optgrating, optprism, rightangleprism, pentaprism, optaom, - optdipole, opttripole, optfiber, optamp, optmzm, optfilter, + optdipole, opttripole, optfiber, optamp, optmzm, optfilter, optsource, polcontrol, optisolator, optswitch, fiberdelayline, optfiberpolarizer, fibercollimator, optcoupler, wdmcoupler, wdmsplitter, optcirculator, fiberbox, eleccoupler, elecsynthesizer, @@ -3127,6 +3127,84 @@ % \fi % \end{stylelist} % +% \ifGERMAN\section{Optische Quelle}\fi +% \ifENGLISH\section{Optical source}\fi +% +% \begin{ltxsyntax} +% \dipoledesc{optsource} +% \iffalse +%<*ignore> +% \fi +\begin{LTXexample} +\begin{pspicture}(3,2) + \optsource(1.5,1)(3,1){Laser} +\end{pspicture} +\end{LTXexample} +% \iffalse +% +% \fi +% +% \ifENGLISH +% An optical source predefines some properties of any outgoing beam, if +% it is the first component in a beam path. The definable beam +% properties are \Lkeyword{beamangle}, \Lkeyword{beamwidth}, +% \Lkeyword{beamdiv} and \Lkeyword{beamalign}. The properties defined by +% the optical source cannot be overwritten by the beam properties. If a +% property wasn't explicitely defined for a source, it is taken from the +% beam properties. +% +% The default settings for the component position are +% \Lkeyword{position}\opt{=start}. +% \fi +% \ifGERMAN +% Eine optische Quelle gibt ein paar Eigenschaften für alle von ihr +% ausgehenden Strahlen vor, falls es die erste Komponente in einem +% Strahlengang ist. Die verwendbaren Eigenschaften sind +% \Lkeyword{beamangle}, \Lkeyword{beamwidth}, \Lkeyword{beamdiv} und +% \Lkeyword{beamalign}. Alle Eigenschaften, die von einer optischen +% Quelle definiert werden, können nicht später durch Strahlparameter +% überschrieben werden. Wird ein Parameter nicht explizit von der Quelle +% definiert, so werden die Parameter von dem Strahl-Stil verwendet. +% +% Die Voreinstellung für die Positionierung ist +% \Lkeyword{position}\opt{=start}. +% \fi +% \end{ltxsyntax} +% +% \iffalse +%<*ignore> +% \fi +\begin{LTXexample} +\begin{pspicture}(5,2) + \pnodes(1.5,1){A}(5,1){B} + \optsource[innerlabel, beamdiv=10, beamangle=10](A)(B){Laser} + \lens[lens=2 2 2](A)(B) + \optplane(B) + \drawwidebeam{-} + \drawbeam[linecolor=red]{-} +\end{pspicture} +\end{LTXexample} +% \iffalse +% +% \fi +% +% \begin{optionlist} +% \numitem[1.4]{sourcewidth} +% \ifGERMAN Die Breite der Box.\fi +% \ifENGLISH The width of the box.\fi +% +% \numitem[0.8]{sourceheight} +% \ifGERMAN Die Höhe der Box.\fi +% \ifENGLISH The height of the box.\fi +% +% \optitem{sourcesize}{\prm{width} \prm{height}} +% \ifGERMAN Die Breite und Höhe der Box, äquivalent zum Aufruf von +% \Lkeyword{sourcewidth} und \Lkeyword{sourceheight}. +% \fi +% \ifENGLISH The width and height of the box, is equivalent to calling both +% \Lkeyword{sourcewidth} and \Lkeyword{sourceheight}. +% \fi +% \end{optionlist} % % \ifGERMAN\section{Kristall}\fi % \ifENGLISH\section{Crystal}\fi @@ -6788,12 +6866,15 @@ % \cmditem{oenodeIfc}{num}{comp} % % \ifGERMAN -% Der Grenzflächenknoten \prm{num}, wobei \prm{num} eine positive Ganzzahl -% oder \opt{N} ist. Der letzte Knoten ist immer \opt{N}. +% Der Grenzflächenknoten \prm{num}, wobei \prm{num} eine positive +% Ganzzahl oder der Buchstabe \opt{N} ist. Der letzte Knoten ist immer +% \opt{N}, kann aber auch über die entsprechende Zahl angesprochen +% werden. % \fi % \ifENGLISH -% The interface node \prm{num}, where the number is a positive integer or -% \opt{N}. The last node is always defined as \opt{N}. +% The interface node \prm{num}, where the number is a positive integer +% or the character \opt{N}. The last node is always defined as \opt{N} +% but can also be accessed via its number. % \fi % % \cmditem{oenodeIn}{comp} @@ -8065,11 +8146,12 @@ % % \fi % -% \choitem[relative]{beamalign}{rel, relative, abs, absolute} +% \choitem[relative]{beamalign}{rel, relative, abs, absolute, firstcomp} % \ifGERMAN % Gibt vor, ob der Winkel \Lkeyword{beamangle} relativ zu der Verbindung -% zwischen den ersten beiden Komponenten ist, oder ob es sich um einen absoluten -% Winkel handelt. +% zwischen den ersten beiden Komponenten ist, ob es sich um einen +% absoluten Winkel handelt, oder ob der Winkel durch die Ausrichtung der +% ersten Komponente vorgegeben wird. % % Ein absoluter Winkel kann sehr hilfreich sein, falls eine der beiden ersten % Komponenten gedreht oder verschoben wurde. Dabei werden die @@ -8104,6 +8186,37 @@ % % \fi % +% \ifGERMAN +% Im folgenden Beispiel liegen beide Komponenten auf der horizontalen +% Linie $\overline{AB}$. Der grüne Strahl, mit +% \Lkeyword{beamalign}\opt{=rel} verläuft daher auch horizontal. Der +% rote Strahl ist hingegen mit \Lkeyword{beamalign}\opt{=firstcomp} +% entsprechend der Drehung der ersten Komponente ausgerichtet. +% \fi +% \ifENGLISH +% Both components in the following example are align on the horizontal +% line $\overline{AB}$. The green beam with +% \Lkeyword{beamalign}\opt{=rel} is accordingly aligned +% horizontally. The red beam with \Lkeyword{beamalign}\opt{=firstcomp} +% is aligned according to the rotation of the first component: +% \fi +% +% \iffalse +%<*ignore> +% \fi +\begin{LTXexample}[morekeywords = {[21]{beamalign, angle}}] +\begin{pspicture}(4,3) + \pnodes(1.5,1.5){A}(4,1.5){B} + \optbox[position=start, rotateref=r, angle=10](A)(B) + \optplate[position=end, plateheight=3](A)(B) + \addtopsstyle{Beam}{beamdiv=20} + \drawwidebeam{-} + \drawwidebeam[beamalign=firstcomp, linecolor=red]{-} +\end{pspicture} +\end{LTXexample} +% \iffalse +% +% \fi % % \numitem[0]{beampathskip} % \ifGERMAN @@ -8364,11 +8477,11 @@ % \fi \begin{LTXexample}[morekeywords = {[21]{stopinsidecount, startinsidecount}}] \begin{pspicture}(4,2) - \pnodes(0,2){A}(2,0.8){B}(4,2){C} - \optprism[compname=P, prismtype=reflective, prismangle=90](A)(B)(C) - \lens[abspos=1.33](\oenodeIfc{2}{P})(A)% - \lens[abspos=1.33](\oenodeIfc{2}{P})(C)% - \newpsstyle{Beam}{linestyle=none, fillstyle=solid}% + \pnodes(0,2){A}(2,0){B}(4,2){C} + \optprism[compname=P, n=1, prismtype=reflective, prismangle=90](A)(B)(C) + \lens[abspos=1.08](\oenodeIfc{2}{P})(A) + \lens[abspos=1.08](\oenodeIfc{2}{P})(C) + \newpsstyle{Beam}{linestyle=none, fillstyle=solid} \drawwidebeam[fillcolor=green, beamwidth=0.2, beaminsidelast, stopinsidecount=1](A){2}{1} \drawwidebeam[fillcolor=orange, beaminsidefirst, startinsidecount=1, loadbeam]{1}{3}(C) \end{pspicture} @@ -12412,7 +12525,48 @@ % % \begin{optionlist} % \boolitem[false]{showinterfaces} +% \ifGERMAN Zeigt alle Grenzflächen einer Komponente an.\fi +% \ifENGLISH Visualizes all interfaces of a component.\fi +% +% \iffalse +%<*ignore> +% \fi +\begin{LTXexample} +\begin{pspicture}(3,1.5) + \psset[optexp]{showinterfaces, aomgratingcount=6} + \addtopsstyle{IfcStyle}{linewidth=2\pslinewidth} + \pnodes(0,1.5){A}(3,0.5){B}(3,1.5){C} + \optaom[aomalign=symmetric](A)(B)(C){symmetric} + \addtopsstyle{Beam}{arrows=->, linewidth=4\pslinewidth} + \drawbeam[linecolor=red!50](A){}(C) + \drawbeam[linecolor=red](A){}(B) +\end{pspicture} +\end{LTXexample} + +\begin{LTXexample} +\begin{pspicture}(3,1.5) + \psset[optexp]{showinterfaces, aomgratingcount=6} + \addtopsstyle{IfcStyle}{linewidth=2\pslinewidth} + \pnodes(0,1){A}(3,1){B}(3,1.5){C} + \optaom[aomalign=straight](A)(B)(C){straight} + \addtopsstyle{Beam}{arrows=->, linewidth=4\pslinewidth} + \drawbeam[linecolor=red!50](A){}(C) + \drawbeam[linecolor=red](A){}(B) +\end{pspicture} +\end{LTXexample} +% \iffalse +% +% \fi +% % \styleitem[linestyle=dashed, dash=1pt 1pt, linecolor=red!70!black]{IfcStyle} +% \ifGERMAN +% Bestimmt das Aussehen der mit \Lkeyword{showinterfaces} angezeigten +% Grenzflächen. +% \fi +% \ifENGLISH +% Determines the appearance of the interfaces, which are shown with +% \Lkeyword{showinterfaces}. +% \fi % \end{optionlist} % % \ifENGLISH\section{Overview of special nodes}\fi @@ -13348,6 +13502,16 @@ % % \begin{changelog} % \patchcmd{\release}{\setlength{\itemsep}{0pt}}{\setlength{\itemsep}{0pt}\setlength{\parsep}{0pt}}{}{} +% \begin{release}{4.10}{2014-06-04} +% \item Added value \opt{firstcomp} to parameter \opt{beamalign}\see{prm:beamalign} +% \item Modified \cs{optsource} to handle also the beam alignment\see{comp:optsource} +% \end{release} +% \begin{release}{4.9}{2014-06-03} +% \item Added new component \cs{optsource}\see{comp:optsource} +% \item Improved naming of the last component name, which can now be +% accessed also by its number besides using \opt{N}. +% \item Fixed bug related to \opt{extnodes} together with \opt{compname} +% \end{release} % \begin{release}{4.8}{2014-02-28} % \item Added component \cs{optaom}\see{comp:optaom} % \item Added option \opt{beammode}\see{prm:beammode} @@ -13366,7 +13530,7 @@ % \item Added option \opt{usewirestyle}\see{prm:usewirestyle} % \item Added line style \opt{fade}, with options \opt{fadeto}, % \opt{fadepoints}, \opt{fadefunc}, and -% \opt{fadefuncname}\see{prm:fade} +% \opt{fadefuncname}\see{prm:fade}. % \end{release} % \begin{release}{4.4}{2013-07-14} % \item Added component \cs{transmissiongrating}\see{comp:transmissiongrating} @@ -14471,6 +14635,28 @@ }% \psset[optexp]{optboxsize=1.4 0.8}% % \end{macrocode} +% +% Box +% \begin{macrocode} +\define@key[psset]{optexp}{sourcewidth}{% + \pst@checknum{#1}\POE@key@sourcewidth +} +\define@key[psset]{optexp}{sourceheight}{% + \pst@checknum{#1}\POE@key@sourceheight +} +\define@key[psset]{optexp}{sourcesize}{% + \pst@expandafter\POE@psset@@sourcesize{#1} {} {} {}\@nil +}% +\def\POE@psset@@sourcesize#1 #2 #3\@nil{% + \ifx\\#2\\% + \PackageWarning{pst-optexp}{% + Parameter 'sourcesize' requires two numbers.}% + \fi + \psset[optexp]{sourcewidth=#1, sourceheight=#2}% +}% +\psset[optexp]{sourcesize=1.4 0.8}% +% \end{macrocode} +% % arrowbox % \begin{macrocode} \define@key[psset]{optexp}{arrowcompwidth}{% @@ -15463,7 +15649,7 @@ \pst@getint{#1}\POE@key@beampathcount }% \define@choicekey+[psset]{optexp}{beamalign}% - [\val\nr]{rel,abs,relative,absolute}% + [\val\nr]{rel,abs,relative,absolute,firstcomp}% {% \ifcase\nr\relax \let\POE@key@beamalign\POE@str@relative @@ -16240,9 +16426,11 @@ /beamalign \ifx\POE@key@beamalign\POE@str@absolute\space absolute - \else + \else\ifx\POE@key@beamalign\POE@str@relative\space relative - \fi def + \else + firstcomp + \fi\fi def /beampathskip \POE@key@beampathskip\space def \POE@key@beampathcount\space dup -1 gt { beampathskip add } if /beampathcount ED /useNA \ifPOE@useNA true \else false \fi def @@ -16355,12 +16543,16 @@ \ifx\pslinestyle\@none\ifx\psk@ArrowInside\@empty 1\else 0\fi\else 0\fi \addto@pscode{ cleartomark false false }% \else - \addto@pscode{% +% \end{macrocode} +% Get the beamproperties from the first component if it is a source. +% \begin{macrocode} + \POE@HandleSourceBeam % \end{macrocode} % I need to pack it this way in order to avoid replacing the \opt{n} inside the % code here. This must be done later, when it refers to the correct refractive % indices. % \begin{macrocode} + \addto@pscode{% {/nbeam {\POE@key@n cvx exec} bind def \ifPOE@pswarning /Warning /PrintWarning load def @@ -16375,7 +16567,7 @@ 0 exch } if } ifelse \tx@ScreenCoor] cvx - \POE@key@beamangle\space + beamangle currentdict /lastBeamPointTmp undef currentdict /lastVecTmp undef loadbeampoints 1 ge @@ -16422,7 +16614,37 @@ \def\POE@strokesinglebeam{% gsave /Lineto /lineto load def - \tx@Drawbeam + 20 dict begin + DrawbeamPrepare +% \end{macrocode} +% If there are only three elements or less on the stack, the first ray +% misses the next interface or is even parallel to the input interface. +% \begin{macrocode} + counttomark 3 gt { +% \end{macrocode} +% Define some parameters for Drawbeam which are based on TeX-parameters +% \begin{macrocode} + \ifx\psk@arrowA\arrowType@H + \pst@number\pshooklength + \else + \psk@arrowsize\space CLW mul add dup \psk@arrowlength\space mul exch \psk@arrowinset mul neg add + \fi + /arrowlength exch def + /arrowminlength \POE@key@ArrowInsideMinLength\space\pst@number\psunit mul def + /arrowmaxlength \POE@key@ArrowInsideMaxLength\space\pst@number\psunit mul def + /arrowpos \psk@ArrowInsidePos\space def + /arrowno \psk@ArrowInsideNo\space cvi def + /ArrowPosStart \psk@ArrowInsideOffset\space def + /dArrowPosStart \psk@ArrowInsidePos\space def + counttomark 3 idiv /N exch def + (\psk@ArrowInside) length 0 gt { + DrawbeamArrowInside + }{ + DrawbeamSimple + } ifelse + } if + cleartomark + end \tx@setlinejoin \pst@number\pslinewidth SLW \pst@usecolor\pslinecolor @@ -16437,6 +16659,10 @@ % \begin{macrocode} \def\drawwidebeam@ii{% \def\pst@fill##1{ gsave ##1 grestore }% +% \end{macrocode} +% Get the beamproperties from the first component if it is a source. +% \begin{macrocode} + \POE@HandleSourceBeam \addto@pscode{% {/nbeam {\POE@key@n cvx exec} bind def \ifPOE@pswarning @@ -16449,8 +16675,8 @@ % arrange and create the input vectors % \begin{macrocode} \addto@pscode{% - \POE@key@beamangle\space dup - \POE@key@beamdiv\space 0.5 mul dup 4 -1 roll add 3 1 roll sub + beamangle dup + beamdiv 0.5 mul dup 4 -1 roll add 3 1 roll sub }% % \end{macrocode} % the start positions @@ -16464,12 +16690,14 @@ 0 exch } if } ifelse - mark \POE@key@beamwidth\space counttomark 0 eq { - 0 +% \end{macrocode} +% if \opt{beamwidth} is defined at Postscript level, it was defined from the source object. +% \begin{macrocode} + currentdict /beamwidth known { + beamwidth currentdict /beamwidth undef } { - 0.5 mul - } ifelse - exch pop + mark \POE@key@beamwidth\space counttomark 0 eq { 0 } if exch pop + } ifelse 0.5 mul 3 copy add \tx@ScreenCoor\space ToVec 5 1 roll sub \tx@ScreenCoor ] cvx @@ -16559,126 +16787,6 @@ }% % \end{macrocode} % \end{macro} -% -% \begin{macrocode} -\pst@def{Drawbeam}< -% \end{macrocode} -% Remove trailing empty line parts. -% \begin{macrocode} - { counttomark 6 le { - exit - } if - 3 index not { - pop pop pop - }{ - exit - } ifelse - } loop -% \end{macrocode} -% Remove heading empty line parts. Note, that the first point must not have -% 'draw = true', because it is the starting point which we have to move to. -% \begin{macrocode} - { counttomark 3 le { - exit - } if - counttomark 3 sub index not { - counttomark -3 roll pop pop pop - }{ - exit - } ifelse - } loop -% \end{macrocode} -% \begin{macrocode} - counttomark 3 le { -% \end{macrocode} -% first ray misses the next interface or is even parallel to the input interface. -% \begin{macrocode} - cleartomark - }{ -% \end{macrocode} -% This is the /Line definition from \opt{pstricks-add}, adapted to the beam path -% structure which includes the boolean values to indicate if a line is drawn, or -% if we use moveto. There was no way to patch the original definition to account -% for the moveto parts and avoid duplicating the code. -% \begin{macrocode} - counttomark 3 div cvi /N ED - (\psk@ArrowInside) length 0 gt { - \ifx\psk@arrowA\arrowType@H % do we have a Hook arrow at the beginning? - \pst@number\pshooklength % yes - \else - \psk@arrowsize\space CLW mul add dup \psk@arrowlength\space mul exch \psk@arrowinset mul neg add - \fi - /arrowlength exch def - 6 copy pop % copy all four values for the arrow line - /y1 ED /x1 ED pop /y2 ED /x2 ED % save them - /Alpha y2 y1 sub x2 x1 sub Atan def % the gradient of the line - pop 3 -1 roll 5 1 roll - ArrowA - x1 Alpha cos arrowlength mul add % dx add - y1 Alpha sin arrowlength mul add % dy add, to get the current point at the end of the arrow tip - 5 -1 roll 3 1 roll true - /N N 1 sub def - N { - 6 copy pop - /y1 ED /x1 ED pop /y2 ED /x2 ED /draw ED -% \end{macrocode} -% Check for line segment length and draw the arrow only, if the segment is long -% enough. This is in first place to avoid drawing an inside arrow for the -% pinhole which has three interfaces instead of one so that it can be used as -% real spatial filter. -% \begin{macrocode} - x1 y1 x2 y2 @ABDist dup - \POE@key@ArrowInsideMinLength\space\pst@number\psunit mul ge - exch \POE@key@ArrowInsideMaxLength\space\pst@number\psunit mul dup 0 lt - 3 1 roll le or and { - x1 y1 - \psk@ArrowInsidePos\space 1 gt { - /Alpha y2 y1 sub x2 x1 sub Atan def - /ArrowPos \psk@ArrowInsideOffset\space def - /dArrowPos \psk@ArrowInsidePos\space abs def - \psk@ArrowInsideNo\space cvi { - /ArrowPos ArrowPos dArrowPos add def - x1 Alpha cos ArrowPos mul add - y1 Alpha sin ArrowPos mul add - 6 index { ArrowInside } if - pop pop - } repeat - }{ - /ArrowPos \psk@ArrowInsideOffset\space def - /dArrowPos \psk@ArrowInsideNo 1 gt {% - 1.0 \psk@ArrowInsideNo 1.0 add div - }{\psk@ArrowInsidePos } ifelse def - \psk@ArrowInsideNo\space cvi { - /ArrowPos ArrowPos dArrowPos add def - x2 x1 sub ArrowPos mul x1 add - y2 y1 sub ArrowPos mul y1 add - 6 index { ArrowInside } if - pop pop - } repeat - } ifelse - pop pop - } if - draw {Lineto}{moveto} ifelse - } repeat - }{ - pop 5 copy 3 -1 roll pop - ArrowA pop pop pop pop - counttomark 3 idiv -1 2 { - pop { - lineto - }{ - moveto - } ifelse - } for - } ifelse - {CP 4 2 roll ArrowB lineto pop pop } {moveto} ifelse -% \end{macrocode} -% remove the mark -% \begin{macrocode} - pop - } ifelse -> -% \end{macrocode} % % \begin{macrocode} \def\POE@getcomprange#1-#2\@nil{% @@ -17322,61 +17430,6 @@ \let\newOptexpElecComp\newOptexpFiberComp % \end{macrocode} % \end{macro} -% -% \begin{macro}{\POE@compalias} -% Components which have a \opt{compname} assigned, must also be -% available by their component number. Here, all necessary -% informations (nodes, component dictionary) are referenced such that -% any information is accessible via number or name. First parameter is -% the component name, second one the component id. -% \begin{macrocode} -\def\POE@compalias#1#2{% - \POE@Verb{% -% \end{macrocode} -% Copy the component dictionary -% \begin{macrocode} - /\oenode{}{#2} dup currentdict exch known { - load /\oenode{}{#1} ED - } { - pop - } ifelse - (\oenode{}{#1}) (\oenode{}{#2}) - tx@NodeDict begin -% \end{macrocode} -% Copy all interface nodes of the component. -% \begin{macrocode} - 1 { - 3 copy inttostr dup - 3 1 roll 2 copy NodeName - currentdict exch known { - NodeName load 3 1 roll NodeName ED - 1 add - } { - pop (N) NodeName load 3 1 roll - pop (N) NodeName ED - pop exit - } ifelse - } loop -% \end{macrocode} -% Copy all other nodes associated with the component (reference nodes, center -% node, label node etc). -% \begin{macrocode} - [ (A) (B) (@A) (@B) (Center) (Label) (Rotref) - (TrefA) (TrefB) (@TrefA) (@TrefB) (Ext) - counttomark { - counttomark 3 add -2 roll 2 copy counttomark 1 add 2 roll - 3 -1 roll dup 4 1 roll NodeName dup - currentdict exch known { - load 3 1 roll exch NodeName ED - } { - pop pop pop - } ifelse - } repeat pop pop pop - end - }% -\ignorespaces}% -% \end{macrocode} -% \end{macro} % % \begin{macro}{\optplane} % Define an invisible plane which is used only for ray tracing. The first node @@ -17398,6 +17451,72 @@ % \end{macrocode} % \end{macro} % +% \begin{macro}{\POE@SaveBeamParameters} +% Save the current beam parameters. This is used to be able to set a +% source beam with the usual beam parameters. +% \begin{macrocode} +\def\POE@SaveBeamParameters{% + \let\POE@tempA\POE@key@beamangle + \let\POE@tempB\POE@key@beamdiv + \let\POE@tempC\POE@key@beamwidth + \let\POE@tempD\POE@key@beamalign + \let\POE@key@beamangle\relax + \let\POE@key@beamdiv\relax + \let\POE@key@beamwidth\relax + \let\POE@key@beamalign\relax +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\POE@SetSourceAndRestoreBeamParameters} +% \begin{macrocode} +\def\POE@SetSourceAndRestoreBeamParameters{% + \let\POE@key@sourcebeamangle\POE@key@beamangle + \let\POE@key@sourcebeamdiv\POE@key@beamdiv + \let\POE@key@sourcebeamwidth\POE@key@beamwidth + \let\POE@key@sourcebeamalign\POE@key@beamalign + \let\POE@key@beamangle\POE@tempA + \let\POE@key@beamdiv\POE@tempB + \let\POE@key@beamwidth\POE@tempC + \let\POE@key@beamalign\POE@tempD +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\POE@HandleSourceBeam} +% Load beam properties from the first component on the stack, if it is +% an optical source. Also handle the beamalign=firstcomp case, since +% this also depends on the first component. +% \begin{macrocode} +\def\POE@HandleSourceBeam{% + \addto@pscode{% + counttomark 0 eq not { + dup cvn load dup /source known { + /source get { def } forall + }{ pop } ifelse + } if +% \end{macrocode} +% Handle the beamalign=firstcomp case. Calculate the angle of the first +% component's reference line and set the beamalign parameter to +% absolute. +% \begin{macrocode} + beamalign firstcomp eq { + dup dup (Center) NodeName tx@NodeDict exch known not { +% \end{macrocode} +% If we have no node called \opt{\ldots Center}, the first object isn't +% a component, but a node. Switch to relative alignment. +% \begin{macrocode} + pop /beamalign relative def + } { + RelConnAngle@tref exch atan /beamangle exch def + /beamalign absolute def + } ifelse + } if + }% +}% +% \end{macrocode} +% \end{macro} +% % \begin{macro}{\begin@OptexpObj} % \begin{macrocode} \def\begin@OptexpObj{% @@ -17407,7 +17526,9 @@ \begingroup \POE@insideobjtrue \POE@Verb{InitOptexpComp }% + \POE@SaveBeamParameters \use@par + \POE@SetSourceAndRestoreBeamParameters % \end{macrocode} % The \opt{compshift} refers to the $y$-direction, shifting in $x$-direction % is done by \opt{abspos} or \opt{position} @@ -17463,18 +17584,34 @@ \POE@transformnode{\oenode@RefB{}}{\oenode@TrefB{}}% }% }% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\POE@unsetbeamparameters} +% Unset some beam parameters which might be used by \cs{optsource}. +% \begin{macrocode} +\def\POE@unsetbeamparameters{% + \let\POE@key@beamangle\relax + \let\POE@key@beamdiv\relax + \let\POE@key@beamwidth\relax +}% +% \end{macrocode} +% \end{macro} % % \begin{macro}{\end@OptexpObj} % \begin{macrocode} \def\end@OptexpObj{% \ifnum9<1\POE@key@compname\else - \POE@compalias{\POE@key@compname}{\the\POE@cnt}% + \POE@Verb{ + (\oenode{}{\POE@key@compname}) + (\oenode{}{\the\POE@cnt}) CompAlias }% \fi \endgroup \ignorespaces% }% % \end{macrocode} % \end{macro} +% % \begin{macro}{\end@OptexpDipole} % \begin{macrocode} \let\end@OptexpDipole\end@OptexpObj @@ -17736,7 +17873,7 @@ \ifPOE@backlayer \POE@Verb{% (1) (3) (\oenode{}{}) CorrectDipoleIfc - (2) (N) (\oenode{}{}) CorrectDipoleIfc + (2) (4) (\oenode{}{}) CorrectDipoleIfc }% \ifPOE@fiberpresetin@ \ifPOE@fiberpresetin@top @@ -17794,7 +17931,7 @@ \ifPOE@backlayer \POE@Verb{% (1) (2) (\oenode{}{}) CorrectDipoleIfc - (1) (N) (\oenode{}{}) CorrectDipoleIfc + (1) (3) (\oenode{}{}) CorrectDipoleIfc }% \ifPOE@fiberpresetin@ \drawfiber@{FiberIn}[stopnode=1](#1){} @@ -17845,8 +17982,8 @@ \POE@drawcomponent{wdmcoupler}{#4} \ifPOE@backlayer \POE@Verb{% - (1) (N) (\oenode{}{}) CorrectDipoleIfc - (2) (N) (\oenode{}{}) CorrectDipoleIfc + (1) (3) (\oenode{}{}) CorrectDipoleIfc + (2) (3) (\oenode{}{}) CorrectDipoleIfc }% \ifPOE@fiberpresetout@ \drawfiber@{FiberOut}[startnode=N]{}(#3) @@ -18351,6 +18488,7 @@ \newOptexpDipole{crystal} \newOptexpDipole{polarization} \newOptexpDipole{optbox} +\newOptexpDipole{optsource}{position=start} \newOptexpDipole{optplate} \newOptexpDipole{optretplate} \newOptexpDipole{optdetector}{position=end} @@ -19509,6 +19647,48 @@ % \end{macrocode} % \end{macro} % +% \subsubsection{optsource} +% +% \begin{macro}{\optsource@ref} +% \begin{macrocode} +\def\optsource@ref{% + \let\POE@key@optboxwidth\POE@key@sourcewidth + \let\POE@key@optboxheight\POE@key@sourceheight + \optbox@ref +}% +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\optsource@nodes} +% \begin{macrocode} +\def\optsource@nodes{% + \POE@dipole@nodes + \POE@Verb{% + \oenode{}{} begin + 4 dict dup /source exch def begin + \if\POE@key@sourcebeamangle\relax\else + /beamangle \POE@key@sourcebeamangle\space def + \fi + \if\POE@key@sourcebeamdiv\relax\else + /beamdiv \POE@key@sourcebeamdiv\space def + \fi + \if\POE@key@sourcebeamwidth\relax\else + /beamwidth \POE@key@sourcebeamwidth\space def + \fi + \if\POE@key@sourcebeamalign\relax\else + /beamalign \POE@key@sourcebeamalign\space def + \fi + end + source length 0 eq { currentdict /source undef } if + end }% +}% +% +% \begin{macro}{\optsource@comp} +% \begin{macrocode} +\let\optsource@comp\POE@comp@rectangle +% \end{macrocode} +% \end{macro} +% % \subsubsection{optplate} % % \begin{macro}{\optplate@ref} @@ -20910,7 +21090,7 @@ \ifPOE@backlayer \POE@Verb{% (1) (3) (\oenode{}{}) CorrectDipoleIfc - (2) (N) (\oenode{}{}) CorrectDipoleIfc + (2) (4) (\oenode{}{}) CorrectDipoleIfc }% \ifPOE@wirepresetin@top \drawwire@{WireIn1}[stopnode=1](#1){} @@ -21281,25 +21461,6 @@ tx@OptexpDict begin } bind def % \end{macrocode} % \end{macro} -% -% \begin{macro}{IfcCopy} -% Copy an interface \PSvar{from} to an interface \PSvar{to}, must be called -% within the respective component dictionary. This involves also copying the -% node associated with the interface. -% \begin{pssyntax} -% \PSvar{from} \PSvar{to} \PSop{CopyIfc} -% \end{pssyntax} -% \begin{macrocode} -/IfcCopy { - 2 copy IfcName exch IfcName load dup - length dict copy def - name exch NodeName name 3 -1 roll NodeName - tx@NodeDict begin - load dup length dict copy def - end -} bind def -% \end{macrocode} -% \end{macro} % % \begin{macro}{calcNodes} % Calculate the reference node coordinates for reflective components and @@ -21467,7 +21628,7 @@ tx@OptexpDict begin /reverse ED dup cvn load /N get dup reverse { -1 1 } { 1 1 3 -1 roll } ifelse - { 2 copy eq { pop (N) } { inttostr } ifelse + { inttostr 3 -1 roll dup 4 1 roll exch NodeName 3 1 roll } for pop pop @@ -21639,10 +21800,24 @@ tx@OptexpDict begin % \end{macro} % % Define some constants. +% +% These are used for checks of the \opt{beamalign} and \opt{fiberalign} parameters. +% \begin{macrocode} +/relative 0 def /absolute 1 def /center 2 def /firstcomp 3 def +% \end{macrocode} +% +% These constants are used to describe the characteristics of interfaces. % \begin{macrocode} -/relative 0 def /absolute 1 def /center 2 def /refl 0 def /trans 1 def /absorb 2 def /refltrans 3 def /auto 4 def /undefined -1 def +% \end{macrocode} +% +% These give the ordering of the internal interfaces of a component. +% \begin{macrocode} /desc 0 def /asc 1 def /amb 2 def +% \end{macrocode} +% +% The possible status after computing the outgoing vector at an interface. +% \begin{macrocode} /ok 0 def /tir 1 def /missed 2 def /bgRefIndex 0 def % \end{macrocode} @@ -21724,15 +21899,16 @@ tx@OptexpDict begin % only a single plane is specified, create the aliases. % \begin{macrocode} name (1) 3 -1 roll {sc} NewCompIfc - (1) (N) IfcCopy + (1) (2) IfcCopy + (2) (N) IfcAlias }{ N -1 1 { % - dup N eq { pop (N) }{inttostr} ifelse - exch name 3 1 roll {sc} NewCompIfc + inttostr exch name 3 1 roll {sc} NewCompIfc } for + N inttostr (N) IfcAlias } ifelse ambiguous ambIfc 0 gt and { - ambIfc N eq { (N) }{ ambIfc inttostr } ifelse (C) IfcCopy + ambIfc inttostr (C) IfcCopy } if end pop @@ -21764,12 +21940,14 @@ tx@OptexpDict begin % only a single plane is specified, create the aliases. % \begin{macrocode} {0 1} 0 0 trans name (1) {PlainIfc} {sc} NewCompIfc - (1) (N) IfcCopy + (1) (2) IfcCopy + (2) (N) IfcAlias }{ N -1 1 { - dup N eq { pop (N) }{inttostr} ifelse + inttostr {0 1} 0 0 absorb name 6 -1 roll {PlainIfc} {sc} NewCompIfc } for + N inttostr (N) IfcAlias } ifelse end pop @@ -21778,12 +21956,33 @@ tx@OptexpDict begin % \end{macrocode} % \end{macro} % +% \begin{macro}{IfcCopy} +% Copy an interface \PSvar{from} to an interface \PSvar{to}, must be called +% within the respective component dictionary. This involves also copying the +% node associated with the interface. +% \begin{pssyntax} +% \PSvar{from} \PSvar{to} \PSop{CopyIfc} +% \end{pssyntax} +% \begin{macrocode} +/IfcCopy { + 2 copy IfcName exch IfcName load dup + length dict copy def + name exch NodeName name 3 -1 roll NodeName + tx@NodeDict begin + load dup length dict copy def + end +} bind def +% \end{macrocode} +% \end{macro} +% % \begin{macro}{IfcAlias} % Create an alias of an interface. This involves creating also an % alias for the associated node. Must be called withing % \PSvar{NewOptexpComp}. % -% \PSstring{OrigPN} \PSstring{AliasPN} \PSop{IfcAlias} +% \begin{pssyntax} +% \PSstring{OrigPN} \PSstring{AliasPN} \PSop{IfcAlias} +% \end{pssyntax} % \begin{macrocode} /IfcAlias { 2 copy IfcName exch IfcName load def @@ -21793,6 +21992,75 @@ tx@OptexpDict begin } bind def % \end{macrocode} % \end{macro} +% +% \begin{macro}{CompAlias} +% Components which have a \opt{compname} assigned, must also be +% available by their component number. Here, all necessary +% informations (nodes, component dictionary) are referenced such that +% any information is accessible via number or name. +% \begin{pssyntax} +% \PSstring{NameStem} \PSstring{IDStem} \PSop{CompAlias} +% \end{pssyntax} +% \begin{macrocode} +/CompAlias { +% \end{macrocode} +% Copy the component dictionary +% \begin{macrocode} + 2 copy cvn dup currentdict exch known { + load def + } { + pop + } ifelse + tx@NodeDict begin +% \end{macrocode} +% Copy all interface nodes of the component. +% \begin{macrocode} + 1 { + 3 copy inttostr dup + 3 1 roll 2 copy NodeName + currentdict exch known { + NodeName load 3 1 roll NodeName ED + 1 add + } { + pop (N) NodeName load 3 1 roll + pop (N) NodeName ED + pop exit + } ifelse + } loop +% \end{macrocode} +% Copy all other nodes associated with the component (reference nodes, center +% node, label node etc). +% \begin{macrocode} + mark (A) (B) (@A) (@B) (Center) (Label) (Rotref) + (TrefA) (TrefB) (@TrefA) (@TrefB) (Ext) (Origin) + counttomark { + counttomark 3 add -2 roll 2 copy counttomark 1 add 2 roll + 3 -1 roll dup 4 1 roll NodeName dup + currentdict exch known { + load 3 1 roll exch NodeName ED + } { + pop pop pop + } ifelse + } repeat pop +% \end{macrocode} +% Copy additional external nodes, the maximum is 8 (all combinations of +% l, r, t, b, c). Old and new node name stems are still on the stack. +% \begin{macrocode} + exch 1 1 8 { + 3 copy + (Ext) exch 5 string cvs strcat dup 3 1 roll + NodeName 3 1 roll NodeName + dup currentdict exch known { + load def pop + } { + pop pop pop exit + } ifelse + } for + pop pop + end +} bind def +% \end{macrocode} +% \end{macro} % % \begin{macro}{GetPlaneVec} % Push the coordinates of the plane vector on the stack, for curved interfaces @@ -21856,7 +22124,8 @@ tx@OptexpDict begin % \end{macro} % % \begin{macro}{GetIfcCenterCorr} -% Get the center node of a interface, either by specifying the name of the component and the interface number +% Get the coordinates of an interface node. This checks if corrected +% coordinates for proper connection handling are available. % \begin{pssyntax} % \PSvar{IfcNum} \PSstring{CompName} \PSop{GetIfcCenterCorr} \PSvar{X|XCorr Y|YCorr} % \end{pssyntax} @@ -22695,7 +22964,120 @@ tx@OptexpDict begin } bind def % \end{macrocode} % \end{macro} -% +% +% \begin{macro}{DrawbeamPrepare} +% Prepare the data points for drawing with \PSop{DrawbeamSimple} and +% \PSop{DrawbeamArrowInside}. +% \begin{macrocode} +/DrawbeamPrepare { +% \end{macrocode} +% Remove trailing empty line parts. +% \begin{macrocode} + { + counttomark 6 le { exit } if + 3 index not { pop pop pop }{ exit } ifelse + } loop +% \end{macrocode} +% Remove heading empty line parts. Note, that the first point must not have +% 'draw = true', because it is the starting point which we have to move to. +% \begin{macrocode} + { + counttomark 3 le { exit } if + counttomark 3 sub index not { + counttomark -3 roll pop pop pop + }{ + exit + } ifelse + } loop +} bind def +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{DrawbeamSimple} +% \begin{macrocode} +/DrawbeamSimple { + pop 5 copy 3 -1 roll pop + ArrowA pop pop pop pop + counttomark 3 idiv -1 2 { + pop { + lineto + }{ + moveto + } ifelse + } for + {CP 4 2 roll ArrowB lineto pop pop } {moveto} ifelse +} bind def +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{DrawbeamArrowInside} +% This is the /Line definition from \opt{pstricks-add}, adapted to the beam path +% structure which includes the boolean values to indicate if a line is drawn, or +% if we use moveto. There was no way to patch the original definition to account +% for the moveto parts and avoid duplicating the code. +% \begin{macrocode} +/DrawbeamArrowInside { + 6 copy pop + /y1 ED /x1 ED pop /y2 ED /x2 ED + /Alpha y2 y1 sub x2 x1 sub Atan def + pop 3 -1 roll 5 1 roll + ArrowA +% \end{macrocode} +% dx add, and dy add, to get the current point at the end of the arrow tip. +% \begin{macrocode} + x1 Alpha cos arrowlength mul add + y1 Alpha sin arrowlength mul add + 5 -1 roll 3 1 roll true + /N N 1 sub def + N { + 6 copy pop + /y1 ED /x1 ED pop /y2 ED /x2 ED /draw ED +% \end{macrocode} +% Check for line segment length and draw the arrow only, if the segment is long +% enough. This is in first place to avoid drawing an inside arrow for the +% pinhole which has three interfaces instead of one so that it can be used as +% real spatial filter. +% \begin{macrocode} + x1 y1 x2 y2 @ABDist dup + arrowminlength ge + exch arrowmaxlength dup 0 lt + 3 1 roll le or and { + x1 y1 + arrowpos 1 gt { + /Alpha y2 y1 sub x2 x1 sub Atan def + /dArrowPos dArrowPosStart abs def + /ArrowPos ArrowPosStart def + arrowno { + /ArrowPos ArrowPos dArrowPos add def + x1 Alpha cos ArrowPos mul add + y1 Alpha sin ArrowPos mul add + 6 index { ArrowInside } if + pop pop + } repeat + }{ + arrowno 1 gt { + 1.0 arrowno 1.0 add div + }{ + dArrowPosStart + } ifelse /dArrowPos ED + /ArrowPos ArrowPosStart def + arrowno { + /ArrowPos ArrowPos dArrowPos add def + x2 x1 sub ArrowPos mul x1 add + y2 y1 sub ArrowPos mul y1 add + 6 index { ArrowInside } if + pop pop + } repeat + } ifelse + pop pop + } if + draw {Lineto}{moveto} ifelse + } repeat + {CP 4 2 roll ArrowB lineto pop pop } {moveto} ifelse +} bind def +% \end{macrocode} +% \end{macro} +% % \begin{macro}{isAmbiguous} % Check if \PSvar{compname} is ambiguous, i.e. if it can have alternating beam % paths depending on the input and output plane (e.g. beamsplitter can either @@ -23100,11 +23482,7 @@ tx@OptexpDict begin % \begin{macrocode} name GetRefIndex } ifelse - exch dup N eq { - pop (N) - } { - inttostr - } ifelse exch + exch inttostr exch 3 1 roll name 4 1 roll dup IfcName load /mode get @@ -23127,20 +23505,13 @@ tx@OptexpDict begin % \end{macro} % % \begin{macro}{IfcName} -% Construct the interface name from \PSvar{num}. This must be called within a dict of a -% optexpcomp, because the last node ends with (N) instead of the number and we must -% know the number of component interfaces. +% Construct the interface name from \PSvar{num}. % \begin{pssyntax} % \PSvar{num} \PSop{IfcName} \PSname{P@num} % \end{pssyntax} % \begin{macrocode} /IfcName { - dup dup 1 eq not exch N eq and { - pop (N) - } { - inttostr - } ifelse - (P@) exch strcat cvn + inttostr (P@) exch strcat cvn } bind def % \end{macrocode} % \end{macro} @@ -23158,9 +23529,7 @@ tx@OptexpDict begin % \end{macrocode} % \end{macro} % \begin{macro}{NodeName} -% Construct the plane name from IfcNum. This must be called within a dict of a -% optexpcomp, because the last node ends with (N) instead of the number and we must -% know the plane count of the component. +% Construct the node name from a string or number. % \begin{pssyntax} % \PSstring{name} \PSvar{num} \PSop{NodeName} \PSname{N@namenum} % \end{pssyntax} @@ -23884,7 +24253,7 @@ tx@OptexpDict begin % estimation of the fiber connections does not work properly. So these % interfaces are separated as less as possible so that the NearestNode % procedure estimates two different distances. The changed nodes are saved -% only in the interface dictionaly as XCorr and YCorr. You must use these for +% only in the interface dictionary as XCorr and YCorr. You must use these for % the fiber connections. % \begin{pssyntax} % \PSstring{node1} \PSstring{node2} \PSstring{basename} \PSop{CorrectDipoleIfc} -- cgit v1.2.3