\iffalse
The tikzoptics library

Copyright (C) 2013-2016 by
 Michel Fruchart <[email protected]>

This work may be distributed and/or modified under the conditions of
the LaTeX Project Public License (LPPL), version 1.3c, which can be
found at the address:
https://www.latex-project.org/lppl/lppl-1-3c/

Alternatively, it may be distributed and/or modified under the conditions of
the GNU General Public License (GNU GPL), version 2, which can be found
at the address:
https://www.gnu.org/licenses/gpl-2.0.en.html
or any later version published by the Free Software Foundation.
\fi
\makeatletter


\def\tikzopticsversion{0.2.3}
\def\tikzopticsversiondate{2017-03-11}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% errors from this library
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\def\opticserror#1{\pgfutil@packageerror{tikz/optics}{#1}{}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% handler |collect unknowns|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% from http://tex.stackexchange.com/questions/81821/filtering-options-with-pgfkeys/81985#81985
% used by /tikz/optics/->n-
%
\pgfkeys{
 /handlers/.collect unknowns/.style = {
   unknown options/.initial = {},
   .unknown/.code = {%
     \letcs\reserved{pgfk@\pgfkeyscurrentpath/unknown options}%
     \csedef{pgfk@\pgfkeyscurrentpath/unknown options}{%
       \ifx\reserved\empty\else\expandonce\reserved,\fi
       \expandonce\pgfkeyscurrentname
       \ifx\pgfkeysnovalue##1\else=\expandonce\pgfkeyscurrentvalue\fi
     }%
   }
 }
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% defining |optics| family
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\pgfkeys{
 /tikz/.cd,
 optics/.is family,
 optics/.search also={/tikz},
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% [use optics]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\pgfkeys{
 /tikz/use optics/.append code={
 \pgfkeys{
   /tikz/.cd,
     % shapes
     % FIXME il ne devrait pas y avoir de logique (ni de valeurs par défaut) ici, seulement l'export dans l'espace de nom commun
     lens/.prefix style={shape=lens,optics,draw},
     slit/.prefix style={shape=slit,optics,draw},
     double slit/.prefix style={shape=double slit,optics,draw},
     thin optics element/.prefix style={shape=thin optics element,optics,draw},
     polarizer/.prefix style={shape=polarizer,optics,draw,object aspect ratio=0.1},
     generic optics io/.prefix style={shape=generic optics io,optics,draw},
     sensor/.prefix style={shape=sensor,optics,object aspect ratio=1,draw},
     sensor line/.prefix style={shape=sensor line,optics,draw},
     mirror/.prefix style={shape=mirror,optics,draw},
     spherical mirror/.prefix style={shape=spherical mirror,optics,draw},
     thick optics element/.prefix style={shape=thick optics element,optics,draw,object aspect ratio=0.1},
     heat filter/.prefix style={shape=thick optics element,optics,draw, object aspect ratio=0.05},
     double amici prism/.prefix style={shape=double amici prism,optics,draw, prism height=1cm, prism apex angle=60},
     % styles
     screen/.prefix style={optics,/tikz/optics/screen},
     diffraction grating/.style={optics,/tikz/optics/diffraction grating},
     grid/.style={optics, /tikz/optics/grid},
     semi-transparent mirror/.style={optics, /tikz/optics/semi-transparent mirror},
     diaphragm/.style={optics, /tikz/optics/diaphragm},
     beam splitter/.prefix style={optics,/tikz/optics/beam splitter},
     generic lamp/.prefix style={optics,/tikz/optics/generic lamp},
     generic sensor/.prefix style={optics,/tikz/optics/generic sensor},
     halogen lamp/.prefix style={optics,/tikz/optics/halogen lamp},
     spectral lamp/.prefix style={optics,/tikz/optics/spectral lamp},
     laser/.prefix style={optics,/tikz/optics/laser},
     laser'/.prefix style={optics,/tikz/optics/laser'},
     concave mirror/.prefix style={optics, /tikz/optics/concave mirror},
     convex mirror/.prefix style={optics, /tikz/optics/convex mirror},
     % arrows (styles)
     ->-/.prefix style={optics,/tikz/optics/->-={##1}},
     -<-/.prefix style={optics,/tikz/optics/-<-={##1}},
     ->>-/.prefix style={optics,/tikz/optics/->>-={##1}},
     -<<-/.prefix style={optics,/tikz/optics/-<<-={##1}},
     ->>>-/.prefix style={optics,/tikz/optics/->>>-={##1}},
     -<<<-/.prefix style={optics,/tikz/optics/-<<<-={##1}},
     ->>>>-/.prefix style={optics,/tikz/optics/->>>>-={##1}},
     -<<<<-/.prefix style={optics,/tikz/optics/-<<<<-={##1}},
     ->n-/.prefix style={optics,/tikz/optics/->n-={##1}},
     -<n-/.prefix style={optics,/tikz/optics/-<n-={##1}},
   }
 }
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% We need some existing tikz libraries and tex packages.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\usetikzlibrary{decorations,decorations.markings, decorations.pathreplacing}
\usepackage{etoolbox}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Key |object height|
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\pgfkeys{/tikz/optics/.cd,
 object height/.initial=2cm,
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Shape [thin optics element]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\pgfdeclareshape{thin optics element}
{
 \savedanchor{\center}{
   \pgfpointorigin
 }
 \anchor{center}{\center}

 \savedmacro\objectHeight{%
   \edef\objectHeight{\pgfkeysvalueof{/tikz/optics/object height}}%
 }

 \savedanchor{\north}{
   \pgf@x=0cm%
   \pgf@y=\objectHeight%
   \pgf@y=0.5\pgf@y%
 }
 \anchor{north}{\north}

 \savedanchor{\south}{
   \pgf@x=0cm%
   \pgf@y=\objectHeight%
   \pgf@y=-0.5\pgf@y%
 }
 \anchor{south}{\south}

 \anchor{east}{\center}
 \anchor{west}{\center}

 \anchorborder{%
   \pgf@xb=\pgf@x% xb/yb is target
   \pgf@yb=\pgf@y%
   \south%
   \pgf@xa=\pgf@x% xa/ya is se
   \pgf@ya=\pgf@y%
   \north%
   \advance\pgf@x by-\pgf@xa%
   \advance\pgf@y by-\pgf@ya%
   \pgf@xc=.5\pgf@x% x/y is half width/height
   \pgf@yc=.5\pgf@y%
   \advance\pgf@xa by\pgf@xc% xa/ya becomes center
   \advance\pgf@ya by\pgf@yc%
   \edef\pgf@marshal{%
     \noexpand\pgfpointborderrectangle
     {\noexpand\pgfpoint{\the\pgf@xb}{\the\pgf@yb}}
     {\noexpand\pgfpoint{\the\pgf@xc}{\the\pgf@yc}}%
   }%
   \pgf@process{\pgf@marshal}%
   \advance\pgf@x by\pgf@xa%
   \advance\pgf@y by\pgf@ya%
 }

 \backgroundpath
 {
   \north \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \south \pgf@xb=\pgf@x \pgf@yb=\pgf@y

   \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
   \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
 }
}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Shape [lens]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\newif\iftikz@optics@lens@converging
\tikz@optics@lens@convergingtrue

% keys
% - focal lens is used to define anchors |east focus| and |west focus|
% - lens height is used to define anchors |lens north| and |lens south|
% - lens type (converging or diverging)
\pgfkeys{/tikz/optics/.cd,
 focal length/.initial=1cm,
 lens height/.initial=0.8,
 lens type/.is choice,
 lens type/converging/.code={\tikz@optics@lens@convergingtrue},
 lens type/diverging/.code={\tikz@optics@lens@convergingfalse}
}
\pgfdeclareshape{lens}
{
 \savedanchor{\center}{
   \pgfpointorigin
 }
 \anchor{center}{\center}

 \savedmacro\focalLength{%
   \edef\focalLength{\pgfkeysvalueof{/tikz/optics/focal length}}%
 }

 \savedmacro\objectHeight{%
   \edef\objectHeight{\pgfkeysvalueof{/tikz/optics/object height}}%
 }

 \savedmacro\lensHeight{%
   \pgfmathparse{\pgfkeysvalueof{/tikz/optics/lens height}}%
   \ifpgfmathunitsdeclared%
     \pgfmathsetlengthmacro{\lensHeight}{\pgfkeysvalueof{/tikz/optics/lens height}}%
   \else%
     \pgfmathsetlengthmacro{\lensHeight}{\pgfkeysvalueof{/tikz/optics/lens height}*\pgfkeysvalueof{/tikz/optics/object height}}%
   \fi%
 }

 \savedanchor{\lensnorth}{
   \pgfpointorigin
   \pgf@y=\lensHeight%
   \pgf@y=0.5\pgf@y%
 }
 \anchor{lens north}{\lensnorth}

 \savedanchor{\lenssouth}{
   \pgfpointorigin
   \pgf@y=\lensHeight%
   \pgf@y=-0.5\pgf@y%
 }
 \anchor{lens south}{\lenssouth}

 \savedanchor{\north}{
   \pgf@x=0cm%
   \pgf@y=\objectHeight%
   \pgf@y=0.5\pgf@y%
 }
 \anchor{north}{\north}

 \savedanchor{\south}{
   \pgf@x=0cm%
   \pgf@y=\objectHeight%
   \pgf@y=-0.5\pgf@y%
 }
 \anchor{south}{\south}

 \savedanchor{\eastfocal}{
   \pgf@x=\focalLength%
   \pgf@y=0cm%
 }
 \anchor{east focal point}{\eastfocal}
 \anchor{east focus}{\eastfocal}


 \savedanchor{\westfocal}{
   \pgf@x=-\focalLength%
   \pgf@y=0cm%
 }
 \anchor{west focal point}{\westfocal}
 \anchor{west focus}{\westfocal}

 \anchor{east}{\center}
 \anchor{west}{\center}

 \inheritanchorborder[from=thin optics element]

 \backgroundpath
 {
   \north \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \south \pgf@xa=\pgf@x \pgf@ya=\pgf@y

   \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
   \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}

   \iftikz@optics@lens@converging
     \pgfsetarrowsstart{lens arrow}
     \pgfsetarrowsend{lens arrow}
   \else
     \pgfsetarrowsstart{lens arrow reversed}
     \pgfsetarrowsend{lens arrow reversed}
   \fi
 }
}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Shape [slit]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% keys : slit height
\pgfkeys{/tikz/optics/.cd,
 slit height/.initial=0.1
}

\pgfdeclareshape{slit}
{
 \savedanchor{\center}{
   \pgfpointorigin
 }
 \anchor{center}{\center}
 \anchor{slit center}{\center}
 % TODO par cohérence ?

 \savedmacro\objectHeight{%
   \edef\objectHeight{\pgfkeysvalueof{/tikz/optics/object height}}%
 }

 \savedmacro\slitHeight{%
   \pgfmathparse{\pgfkeysvalueof{/tikz/optics/slit height}}%
   \ifpgfmathunitsdeclared%
     \pgfmathsetlengthmacro{\slitHeight}{\pgfkeysvalueof{/tikz/optics/slit height}}%
   \else%
     \pgfmathsetlengthmacro{\slitHeight}{\pgfkeysvalueof{/tikz/optics/slit height}*\pgfkeysvalueof{/tikz/optics/object height}}%
   \fi%
 }

 \savedanchor{\north}{
   \pgf@x=0cm%
   \pgf@y=\objectHeight%
   \pgf@y=0.5\pgf@y%
 }
 \anchor{north}{\north}

 \savedanchor{\south}{
   \pgf@x=0cm%
   \pgf@y=\objectHeight%
   \pgf@y=-0.5\pgf@y%
 }
 \anchor{south}{\south}

 \savedanchor{\slitnorth}{
   \pgf@x=0cm%
   \pgf@y=\slitHeight%
   \pgf@y=0.5\pgf@y%
 }
 \anchor{slit north}{\slitnorth}

 \savedanchor{\slitsouth}{
   \pgf@x=0cm%
   \pgf@y=\slitHeight%
   \pgf@y=-0.5\pgf@y%
 }
 \anchor{slit south}{\slitsouth}

 \anchor{east}{\center}
 \anchor{west}{\center}

 \inheritanchorborder[from=thin optics element]

 \backgroundpath
 {
   % erreurs possibles dans la spécification du dessin
   \pgfmathparse{notless(\slitHeight, \objectHeight)}
   \ifnum\pgfmathresult=1
     \opticserror{<slit height> should be strictly lower than <object height> (in slit)}
   \fi
   \north \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \slitnorth \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
   \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}

   \south \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \slitsouth \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
   \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
 }
}




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Shape [double slit]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% keys :
% - slit height : (relative) height of the holes (each)
% - slit separation : (relative) distance between the centers of the holes
\pgfkeys{/tikz/optics/.cd,
 object height/.initial=2cm,
 slit height/.initial=0.075,
 slit separation/.initial=0.2
}

\pgfdeclareshape{double slit}
{
 \savedanchor{\center}{
   \pgfpointorigin
 }
 \anchor{center}{\center}

 \savedmacro\objectHeight{%
   \edef\objectHeight{\pgfkeysvalueof{/tikz/optics/object height}}%
 }

 \savedmacro\slitHeight{%
   \pgfmathparse{\pgfkeysvalueof{/tikz/optics/slit height}}%
   \ifpgfmathunitsdeclared%
     \pgfmathsetlengthmacro{\slitHeight}{\pgfkeysvalueof{/tikz/optics/slit height}}%
   \else%
     \pgfmathsetlengthmacro{\slitHeight}{\pgfkeysvalueof{/tikz/optics/slit height}*\pgfkeysvalueof{/tikz/optics/object height}}%
   \fi%
 }

 \savedmacro\slitSeparation{%
   \pgfmathparse{\pgfkeysvalueof{/tikz/optics/slit separation}}%
   \ifpgfmathunitsdeclared%
     \pgfmathsetlengthmacro{\slitSeparation}{\pgfkeysvalueof{/tikz/optics/slit separation}}%
   \else%
     \pgfmathsetlengthmacro{\slitSeparation}{\pgfkeysvalueof{/tikz/optics/slit separation}*\pgfkeysvalueof{/tikz/optics/object height}}%
   \fi%
 }

 \savedmacro\macro@slitOneCenter{
   \def\macro@slitOneCenter{
     \pgfpointorigin
     \pgf@ya=\slitSeparation
     \pgf@ya=0.5\pgf@ya
     \advance \pgf@y by \pgf@ya
   }
 }

 \savedmacro\macro@slitTwoCenter{
   \def\macro@slitTwoCenter{
     \pgfpointorigin
     \pgf@ya=\slitSeparation
     \pgf@ya=-0.5\pgf@ya
     \advance \pgf@y by \pgf@ya
   }
 }

 \savedanchor{\north}{
   \pgf@x=0cm%
   \pgf@y=\objectHeight%
   \pgf@y=0.5\pgf@y%
 }
 \anchor{north}{\north}

 \savedanchor{\south}{
   \pgf@x=0cm%
   \pgf@y=\objectHeight%
   \pgf@y=-0.5\pgf@y%
 }
 \anchor{south}{\south}

 % slit 1
 \savedanchor{\slitOneCenter}{
   \macro@slitOneCenter
 }
 \anchor{slit 1 center}{\slitOneCenter}

 \savedanchor{\slitOneNorth}{
   \macro@slitOneCenter
   \pgf@ya = \slitHeight
   \pgf@ya = 0.5\pgf@ya
   \advance \pgf@y by \pgf@ya
 }
 \anchor{slit 1 north}{\slitOneNorth}

 \savedanchor{\slitOneSouth}{
   \macro@slitOneCenter
   \pgf@ya = \slitHeight
   \pgf@ya = -0.5\pgf@ya
   \advance \pgf@y by \pgf@ya
 }
 \anchor{slit 1 south}{\slitOneSouth}

 % slit 2
 \savedanchor{\slitTwoCenter}{
   \macro@slitTwoCenter
 }
 \anchor{slit 2 center}{\slitTwoCenter}

 \savedanchor{\slitTwoNorth}{
   \macro@slitTwoCenter
   \pgf@ya = \slitHeight
   \pgf@ya = 0.5\pgf@ya
   \advance \pgf@y by \pgf@ya
 }
 \anchor{slit 2 north}{\slitTwoNorth}

 \savedanchor{\slitTwoSouth}{
   \macro@slitTwoCenter
   \pgf@ya = \slitHeight
   \pgf@ya = -0.5\pgf@ya
   \advance \pgf@y by \pgf@ya
 }
 \anchor{slit 2 south}{\slitTwoSouth}

 \anchor{east}{\center}
 \anchor{west}{\center}

 \inheritanchorborder[from=thin optics element]

 \backgroundpath
 {
   % erreurs possibles dans les spécifications du dessin
   \pgfmathparse{notgreater(\slitSeparation, \slitHeight)}
   \ifnum\pgfmathresult=1
     \opticserror{<slit separation> should be strictly lower than <slit height> (in double slit)}
   \fi
   \pgfmathparse{notless(\slitSeparation+\slitHeight, \objectHeight)}
   \ifnum\pgfmathresult=1
     \opticserror{<slit height> plus <slit separation> should be strictly lower than <object height> (in double slit)}
   \fi
   \north \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \slitOneNorth \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
   \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}

   \slitOneSouth \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \slitTwoNorth \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
   \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}

   \slitTwoSouth \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \south \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
   \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
 }
}



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Shape [mirror]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% keys
% - mirror decoration separation
% - mirror decoration amplitude
\pgfkeys{/tikz/optics/.cd,
 object height/.initial=2cm,
 mirror decoration separation/.initial=0.15cm,
 mirror decoration amplitude/.initial=0.125cm,
}

\pgfdeclareshape{mirror}
{
 \savedanchor{\center}{
   \pgfpointorigin
 }
 \anchor{center}{\center}

 \savedmacro\objectHeight{%
   \edef\objectHeight{\pgfkeysvalueof{/tikz/optics/object height}}%
 }

 \savedanchor{\north}{
   \pgf@x=0cm%
   \pgf@y=\objectHeight%
   \pgf@y=0.5\pgf@y%
 }
 \anchor{north}{\north}

 \savedanchor{\south}{
   \pgf@x=0cm%
   \pgf@y=\objectHeight%
   \pgf@y=-0.5\pgf@y%
 }
 \anchor{south}{\south}

 \anchor{east}{\center}
 \anchor{west}{\center}

 % bof
 \inheritanchorborder[from=thin optics element]

 \backgroundpath
 {
   \north \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \south \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   % We use a border decoration to make a mirror (hachures).
   % First set the decoration parameters :
   % - decoration angle
   % l'angle est 45-180 et on multiplie l'amplitude par -1 pour que la décoration commence et finisse par un trait (c'est un peu louche mais bon)
   \def\pgfdecorationsegmentangle{45-180}%
   % - decoration step length
   \pgfmathparse{\pgfkeysvalueof{/tikz/optics/mirror decoration separation}}
   \ifpgfmathunitsdeclared%
     \pgfmathsetlengthmacro{\pgfdecorationsegmentlength}{\pgfkeysvalueof{/tikz/optics/mirror decoration separation}}%
   \else%
     \pgfmathsetlengthmacro{\pgfdecorationsegmentlength}{\pgfkeysvalueof{/tikz/optics/mirror decoration separation}*\pgfkeysvalueof{/tikz/optics/object height}}%
   \fi%
   % magouillons pour que \pgfdecorationsegmentlength soit un multiple de la longueur ...
   \pgfmathsetmacro\initialstep{\pgfdecorationsegmentlength}
   \pgfmathsetmacro\totallength{\pgfkeysvalueof{/tikz/optics/object height}}
   \pgfmathsetmacro\newstep{\totallength/floor(\totallength/\initialstep)}
   \pgfmathsetlengthmacro{\pgfdecorationsegmentlength}{\newstep}
   % fin magouille
   % - decoration amplitude
   % on multiplie par -1 pour que ça aille dans le bon sens (pour éviter des problèmes louches)
   \pgfmathparse{\pgfkeysvalueof{/tikz/optics/mirror decoration amplitude}}
   \ifpgfmathunitsdeclared%
     \pgfmathsetlengthmacro{\pgfdecorationsegmentamplitude}{-1*\pgfkeysvalueof{/tikz/optics/mirror decoration amplitude}}%
   \else%
     \pgfmathsetlengthmacro{\pgfdecorationsegmentamplitude}{-1*\pgfkeysvalueof{/tikz/optics/mirror decoration amplitude}*\pgfkeysvalueof{/tikz/optics/object height}}%
   \fi%
   % Use decoration.
   \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
   \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
   \pgfdecoratecurrentpath{border} %
   % dessin du miroir (trait)
   \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
   \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
 }
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Shape [spherical mirror]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% keys :
% - spherical mirror angle : the aperture angle of the mirror
% - spherical mirror type (concave or convex)
% - spherical mirror orientation (ltr or rtl)
% The properties of the decoration are controled by the same parameters as in [mirror].
% Height is controled by |object height|, as usual.
\pgfkeys{/tikz/optics/spherical mirror angle/.initial=150}

\newif\iftikz@optics@sphericalmirror@concave
\tikz@optics@sphericalmirror@concavetrue
\pgfkeys{/tikz/optics/.cd,
 spherical mirror type/.is choice,
 spherical mirror type/concave/.code={\tikz@optics@sphericalmirror@concavetrue},
 spherical mirror type/convex/.code={\tikz@optics@sphericalmirror@concavefalse}
}

\newif\iftikz@optics@sphericalmirror@ltr
\tikz@optics@sphericalmirror@ltrtrue
\pgfkeys{/tikz/optics/.cd,
 spherical mirror orientation/.is choice,
 spherical mirror orientation/ltr/.code={\tikz@optics@sphericalmirror@ltrtrue},
 spherical mirror orientation/rtl/.code={\tikz@optics@sphericalmirror@ltrfalse}
}

% shortcuts (styles) : [concave mirror] and [convex mirror]
\pgfkeys{/tikz/optics/.cd,
     concave mirror/.style={optics, spherical mirror, /tikz/optics/spherical mirror type=concave},
     convex mirror/.style={optics, spherical mirror, /tikz/optics/spherical mirror type=convex},
}

\pgfdeclareshape{spherical mirror}{%
 \savedmacro\installsphericalmirrorparameters{%
   %
   % Define a \centerpoint
   %
   \pgfextract@process\centerpoint{%
     \pgfpointorigin
   }%
   %
   % Define height
   %
   \pgfmathsetlengthmacro\height{\pgfkeysvalueof{/tikz/optics/object height}}%
   %
   % Function to define angle from radius
   % use e.g. [spherical mirror angle=from_radius(2cm)] instead of e.g. [spherical mirror angle=90]
   % This can seem somewhat ridiculous as we will undo this when calculating \radius, however it helps providing a simpler API.
   % This function has to be defined before parsing \pgfkeysvalueof{/tikz/optics/spherical mirror angle}.
   %
   \pgfmathdeclarefunction{from_radius}{1}{
     \begingroup
     \pgfmathparse{notless(2*#1,\height)}
     \ifnum\pgfmathresult=0
       \opticserror{(in /tikz/optics/spherical mirror angle=from_radius(R)) : for a spherical mirror, the radius R cannot be smaller than half the height </tikz/optics/object height>. Set a bigger radius of a smaller height.}
     \fi
     \newdimen\angle
     \pgfmathsetlength\angle{2*asin(\height/(2*#1))}
     \pgf@x=\angle
     \pgfmathreturn\pgf@x
     \endgroup
   }
   %
   % Define angle
   %
   \pgfmathsetmacro\angle{\pgfkeysvalueof{/tikz/optics/spherical mirror angle}}
   %
   % Compute radius from height and angle
   %
   \pgfmathsetlengthmacro\radius{\height/(2*sin(\angle/2))}
   %
   % Half of the sector angle is more useful.
   %
   \pgfmathmod{\angle}{360}%
   \ifdim\pgfmathresult pt<0pt\relax%
     \pgfmathadd@{\pgfmathresult}{360}%
   \fi%
   \let\angle\pgfmathresult%
   \pgfmathdivide@{\pgfmathresult}{2}%
   \let\halfangle\pgfmathresult%
   %
   % Get the start and end angles of the arc.
   %
   \iftikz@optics@sphericalmirror@concave
     \iftikz@optics@sphericalmirror@ltr
       \pgfmathsetmacro\startangle{-\halfangle}
       \pgfmathsetmacro\endangle{+\halfangle}
     \else
       \pgfmathsetmacro\startangle{180-\halfangle}
       \pgfmathsetmacro\endangle{180+\halfangle}
     \fi
     \else
     \iftikz@optics@sphericalmirror@ltr
       \pgfmathsetmacro\startangle{180-\halfangle}
       \pgfmathsetmacro\endangle{180+\halfangle}
     \else
       \pgfmathsetmacro\startangle{-\halfangle}
       \pgfmathsetmacro\endangle{+\halfangle}
     \fi
   \fi
   %
   % Calculate R cos(angle/2) and R sin(angle/2)
   %
   \pgfmathabs@{\halfangle}%
   \pgfmathcos@{\pgfmathresult}%
   \let\coshalfangle\pgfmathresult%
   \pgfmathabs@{\halfangle}%
   \pgfmathsin@{\pgfmathresult}%
   \let\sinhalfangle\pgfmathresult%
   \pgfmathsetlength\pgf@xa{\radius*\coshalfangle}
   \edef\rcoshalfangle{\the\pgf@xa}%
   \pgfmathsetlength\pgf@xa{\radius*\sinhalfangle}
   \edef\rsinhalfangle{\the\pgf@xa}%
   %
   % Calculate the arc coordinates
   %
   \pgfextract@process\arcstart{%
     \pgfqpointpolar{\startangle}{\radius}%
     \pgf@xa\pgf@x%
     \pgf@ya\pgf@y%
     \centerpoint%
     \advance\pgf@x\pgf@xa%
     \advance\pgf@y\pgf@ya%
   }%
   \pgfextract@process\arcend{%
     \pgfqpointpolar{\endangle}{\radius}%
     \pgf@xa\pgf@x%
     \pgf@ya\pgf@y%
     \centerpoint%
     \advance\pgf@x\pgf@xa%
     \advance\pgf@y\pgf@ya%
   }%
   \def\convexrtlsetx#1#2{
     \iftikz@optics@sphericalmirror@concave%
       \iftikz@optics@sphericalmirror@ltr%
         \advance\pgf@x by #1
       \else% % => rtl
         \advance\pgf@x by #2
       \fi%
     \else% % => convex
       \iftikz@optics@sphericalmirror@ltr%
         \advance\pgf@x by #2
       \else% % => rtl
         \advance\pgf@x by #1
       \fi%
     \fi%
   }
   \def\convexrtlinvert{%
     \iftikz@optics@sphericalmirror@concave%
       \iftikz@optics@sphericalmirror@ltr%
         %nothing
       \else% % => rtl
         \pgf@x=-\pgf@x%
       \fi%
     \else% % => convex
       \iftikz@optics@sphericalmirror@ltr%
         \pgf@x=-\pgf@x%
       \else% % => rtl
         %nothing
       \fi%
     \fi%
   }%
   %
   % Save everything.
   % "NB \addtosavedmacro is currently experimental. May get changed." d'après le code où je l'ai piqué
   %
   \addtosavedmacro{\radius}%
   %
   \addtosavedmacro{\rcoshalfangle}%
   \addtosavedmacro{\rsinhalfangle}%
   %
   \addtosavedmacro{\endangle}%
   \addtosavedmacro{\startangle}%
   %
   \addtosavedmacro{\centerpoint}%
   \addtosavedmacro{\arcstart}%
   \addtosavedmacro{\arcend}%
    \addtosavedmacro{\convexrtlinvert}%
   %
 }%
 %
 % Define anchors
 %
 \savedanchor\mirrorcenterpoint{%
   \pgfpointorigin
 }%
 \savedanchor\centerpoint{%
   \pgfpointorigin%
   \advance\pgf@x by \radius%
   \advance\pgf@x by \rcoshalfangle%
   \iftikz@optics@sphericalmirror@concave%
     \iftikz@optics@sphericalmirror@ltr%
       %nothing
     \else% % => rtl
       \pgf@x=-\pgf@x%
     \fi%
   \else% % => convex
     \iftikz@optics@sphericalmirror@ltr%
       \pgf@x=-\pgf@x%
     \else% % => rtl
       %nothing
     \fi%
   \fi%
   \divide\pgf@x by 2%
 }%
 \savedanchor\focalpoint{%
   \pgfpointorigin%
   \pgf@xa=\radius%
   \advance\pgf@x by .5\pgf@xa%
   \iftikz@optics@sphericalmirror@concave%
     \iftikz@optics@sphericalmirror@ltr%
       %nothing
     \else% % => rtl
       \pgf@x=-\pgf@x%
     \fi%
   \else% % => convex
     \iftikz@optics@sphericalmirror@ltr%
       \pgf@x=-\pgf@x%
     \else% % => rtl
       %nothing
     \fi%
   \fi%
 }%
 \savedanchor\north{%
   \pgfpointorigin
   \pgf@xa=0pt
   \advance\pgf@xa by \rcoshalfangle
   \advance\pgf@xa by \radius
   \divide\pgf@xa by 2
   \advance\pgf@x by \pgf@xa
   \advance\pgf@y by \rsinhalfangle
   \convexrtlinvert
 }%
 \savedanchor\arccenter{%
   \centerpoint
   \advance\pgf@x by \radius
   \convexrtlinvert
 }
 \savedanchor\south{%
   \pgfpointorigin
   \pgf@xa=0pt
   \advance\pgf@xa by \rcoshalfangle
   \advance\pgf@xa by \radius
   \divide\pgf@xa by 2
   \advance\pgf@x by \pgf@xa
   \advance\pgf@y by -\rsinhalfangle
   \convexrtlinvert
 }
 \savedanchor\east{%
   \pgfpointorigin
   \convexrtlsetx{\radius}{\rcoshalfangle}
   \convexrtlinvert
 }
 \savedanchor\west{%
   \pgfpointorigin
   \convexrtlsetx{\rcoshalfangle}{\radius}
   \convexrtlinvert
 }
 \savedanchor\northwest{%
   \pgfpointorigin
   \convexrtlsetx{\rcoshalfangle}{\radius}
   \advance\pgf@y by \rsinhalfangle
   \convexrtlinvert
 }
 \savedanchor\southwest{%
   \pgfpointorigin
   \convexrtlsetx{\rcoshalfangle}{\radius}
   \advance\pgf@y by -\rsinhalfangle
   \convexrtlinvert
 }
 \savedanchor\northeast{%
   \pgfpointorigin
   \convexrtlsetx{\radius}{\rcoshalfangle}
   \advance\pgf@y by \rsinhalfangle
   \convexrtlinvert
 }
 \savedanchor\southeast{%
   \pgfpointorigin
   \convexrtlsetx{\radius}{\rcoshalfangle}
   \advance\pgf@y by -\rsinhalfangle
   \convexrtlinvert
 }
 \anchor{arc start}{%
   \installsphericalmirrorparameters%
   \arcstart%
 }
 \anchor{arc end}{%
   \installsphericalmirrorparameters%
   \arcend%
 }
 \anchor{focal point}{%
   \installsphericalmirrorparameters%
   \focalpoint
 }
 \anchor{focus}{%
   \installsphericalmirrorparameters%
   \focalpoint
 }
 \anchor{mirror center}{\mirrorcenterpoint}
 \anchor{center}{\centerpoint}
 \anchor{arc center}{\arccenter}
 \anchor{north}{\north}%
 \anchor{south}{\south}%
 \anchor{east}{\east}%
 \anchor{west}{\west}%
 \anchor{north west}{\northwest}%
 \anchor{south west}{\southwest}%
 \anchor{north east}{\northeast}%
 \anchor{south east}{\southeast}%
 %
 % Draw backgroundpath
 %
 \backgroundpath{%
   \installsphericalmirrorparameters%
   % We use a border decoration to make a mirror.
   % First set the decoration parameters :
   % - decoration angle
   \iftikz@optics@sphericalmirror@concave
     \def\pgfdecorationsegmentangle{45}%
   \else
     \def\pgfdecorationsegmentangle{-90-45}%
   \fi
   % - decoration step length
   \pgfmathparse{\pgfkeysvalueof{/tikz/optics/mirror decoration separation}}
   \ifpgfmathunitsdeclared%
     \pgfmathsetlengthmacro{\pgfdecorationsegmentlength}{\pgfkeysvalueof{/tikz/optics/mirror decoration separation}}%
   \else%
     \pgfmathsetlengthmacro{\pgfdecorationsegmentlength}{\pgfkeysvalueof{/tikz/optics/mirror decoration separation}*\pgfkeysvalueof{/tikz/optics/object height}}%
   \fi%
   % magouillons pour que \pgfdecorationsegmentlength soit un multiple de la longueur ...
   \pgfmathsetmacro\initialstep{\pgfdecorationsegmentlength}
   \pgfmathsetmacro\totallength{(2*pi/360)*\angle*\radius}
   \pgfmathsetmacro\newstep{\totallength/floor(\totallength/\initialstep)}
   \pgfmathsetlengthmacro{\pgfdecorationsegmentlength}{\newstep}
   % fin magouille
   % - decoration amplitude
   % on multiplie par -1 pour que ça aille dans le bon sens sans devoir modifier l'angle (pour éviter des problèmes louches)
   \pgfmathparse{\pgfkeysvalueof{/tikz/optics/mirror decoration amplitude}}
   \ifpgfmathunitsdeclared%
     \pgfmathsetlengthmacro{\pgfdecorationsegmentamplitude}{-1*\pgfkeysvalueof{/tikz/optics/mirror decoration amplitude}}%
   \else%
     \pgfmathsetlengthmacro{\pgfdecorationsegmentamplitude}{-1*\pgfkeysvalueof{/tikz/optics/mirror decoration amplitude}*\pgfkeysvalueof{/tikz/optics/object height}}%
   \fi%
   % Now use decoration.
   % Draw decoration of path : an arc of radius \radius from \arcstart to \arcend
   \pgfpathmoveto{\arcstart}%
   \pgfpatharc{\startangle}{\endangle}{\radius}%
   \pgfdecoratecurrentpath{border} %
   % Now draw the path.
   \pgfpathmoveto{\arcstart}%
   \pgfpatharc{\startangle}{\endangle}{\radius}%
 }
 %
 % Anchor border
 % This is needed for anchors .<angle> (like mirror.0, mirror.90, etc.) to work.
 %
 \anchorborder{%
   % Save x and y
   \edef\externalx{\the\pgf@x}%
   \edef\externaly{\the\pgf@y}%
   \installsphericalmirrorparameters%
   % Use circular border
   \pgfpointborderellipse{ \pgfpoint{\externalx}{\externaly} }{ \pgfpoint{\radius}{\radius} }%
 }%
}



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Shape [thick optics element]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% keys :
% - object aspect ratio (alias : object width)
% ar = largeur/hauteur => largeur = ar * hauteur
\pgfkeys{/tikz/optics/.cd,
 object aspect ratio/.initial=0.2,
 object width/.style={/tikz/optics/object aspect ratio=#1}
}

\pgfdeclareshape{thick optics element}
{
 \savedanchor{\center}{
   \pgfpointorigin
 }
 \anchor{center}{\center}

 \savedmacro\objectHeight{%
   \edef\objectHeight{\pgfkeysvalueof{/tikz/optics/object height}}%
 }

 \savedmacro\objectWidth{%
   \pgfmathparse{\pgfkeysvalueof{/tikz/optics/object aspect ratio}}
   \ifpgfmathunitsdeclared%
     \pgfmathsetlengthmacro{\objectWidth}{\pgfkeysvalueof{/tikz/optics/object aspect ratio}}%
   \else%
     \pgfmathsetlengthmacro{\objectWidth}{\pgfkeysvalueof{/tikz/optics/object aspect ratio}*\pgfkeysvalueof{/tikz/optics/object height}}%
   \fi%
 }

 \savedanchor{\northeast}{
   \pgf@x=\objectWidth%
   \pgf@y=\objectHeight%
   \pgf@y=0.5\pgf@y%
   \pgf@x=0.5\pgf@x%
 }
 \anchor{north east}{\northeast}

 \savedanchor{\southwest}{
   \pgf@x=\objectWidth%
   \pgf@y=\objectHeight%
   \pgf@y=-0.5\pgf@y%
   \pgf@x=-0.5\pgf@x%
 }
 \anchor{south west}{\southwest}

 \anchor{north}{
   \center \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \pgf@y=\pgf@yb
 }

 \anchor{south}{
   \center \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \pgf@y=\pgf@yb
 }

 \anchor{east}{
   \center \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xb
   \pgf@y=\pgf@ya
 }

 \anchor{west}{
   \center \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xb
   \pgf@y=\pgf@ya
 }

 \anchor{north west}{
   \northeast \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xb
   \pgf@y=\pgf@ya
 }

 \anchor{south east}{
   \northeast \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \pgf@y=\pgf@yb
 }

 \inheritanchorborder[from=rectangle]

 \backgroundpath
 {
   % rectangle
   \pgfpathrectanglecorners{\northeast}{\southwest}
 }
}



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Shape [polarizer]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\pgfdeclareshape{polarizer}
{
 \savedanchor{\center}{
   \pgfpointorigin
 }
 \anchor{center}{\center}

 \savedmacro\objectHeight{%
   \edef\objectHeight{\pgfkeysvalueof{/tikz/optics/object height}}%
 }

 \savedmacro\objectWidth{%
   \pgfmathparse{\pgfkeysvalueof{/tikz/optics/object aspect ratio}}
   \ifpgfmathunitsdeclared%
     \pgfmathsetlengthmacro{\objectWidth}{\pgfkeysvalueof{/tikz/optics/object aspect ratio}}%
   \else%
     \pgfmathsetlengthmacro{\objectWidth}{\pgfkeysvalueof{/tikz/optics/object aspect ratio}*\pgfkeysvalueof{/tikz/optics/object height}}%
   \fi%
 }

 \savedanchor{\northeast}{
   \pgf@x=\objectWidth%
   \pgf@y=\objectHeight%
   \pgf@y=0.5\pgf@y%
   \pgf@x=0.5\pgf@x%
 }
 \anchor{north east}{\northeast}

 \savedanchor{\southwest}{
   \pgf@x=\objectWidth%
   \pgf@y=\objectHeight%
   \pgf@y=-0.5\pgf@y%
   \pgf@x=-0.5\pgf@x%
 }
 \anchor{south west}{\southwest}

 \anchor{north}{
   \center \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \pgf@y=\pgf@yb
 }

 \anchor{south}{
   \center \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \pgf@y=\pgf@yb
 }

 \anchor{east}{
   \center \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xb
   \pgf@y=\pgf@ya
 }

 \anchor{west}{
   \center \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xb
   \pgf@y=\pgf@ya
 }

 \anchor{north west}{
   \northeast \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xb
   \pgf@y=\pgf@ya
 }

 \anchor{south east}{
   \northeast \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \pgf@y=\pgf@yb
 }

 \inheritanchorborder[from=rectangle]

 \backgroundpath
 {
   % rectangle
   \pgfpathrectanglecorners{\northeast}{\southwest}

   % diagonale du polariseur
   \northeast \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgfpathmoveto{\pgfpoint{\pgf@xa}{\pgf@ya}}
   \pgfpathlineto{\pgfpoint{\pgf@xb}{\pgf@yb}}
 }
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Shape [double amici prism]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% keys :
% - prism height
% - prism apex angle
\pgfkeys{/tikz/optics/.cd,
 prism height/.initial=1.5cm,
 prism apex angle/.initial=60,
}
% Idea : we get
% apexAngle
% prismHeight
% demiPrismWidth = tan(apexAngle/2)*prismHeight
%
% so we compute
%
% C = (0,0)
% NE = (demiPrismWidth,0.5*prismHeight)
% SW = (-2*demiPrismWidth,-0.5*prismHeight)
% NW = (-demiPrismWidth,0.5*prismHeight)
% SE = (2*demiPrismWidth,-0.5*prismHeight)
%
% N = (0,0.5*prismHeight)
% S = (0,-0.5*prismHeight)
% E = (3*0.5*demiPrismWidth,0)
% W = (-3.0.5*demiPrismWidth,0)
\pgfdeclareshape{double amici prism}
{
 \savedanchor{\center}{
   \pgfpointorigin
 }
 \anchor{center}{\center}

 \savedmacro\prismHeight{%
   \edef\prismHeight{\pgfkeysvalueof{/tikz/optics/prism height}}%
 }

 \savedmacro\apexAngle{%
     \pgfmathsetlengthmacro{\apexAngle}{\pgfkeysvalueof{/tikz/optics/prism apex angle}}
 }

 \savedmacro\demiPrismWidth{%
     \pgfmathsetlengthmacro{\demiPrismWidth}{tan(0.5*\pgfkeysvalueof{/tikz/optics/prism apex angle})*\pgfkeysvalueof{/tikz/optics/prism height}}
 }

 \savedanchor{\northeast}{
   \pgf@x=\demiPrismWidth%
   \pgf@y=\prismHeight%
   \pgf@y=0.5\pgf@y%
 }
 \anchor{north east}{\northeast}

 \savedanchor{\southwest}{
   \pgf@x=\demiPrismWidth%
   \pgf@y=\prismHeight%
   \pgf@x=-2\pgf@x%
   \pgf@y=-0.5\pgf@y%
 }
 \anchor{south west}{\southwest}

 \savedanchor{\northwest}{
   \pgf@x=\demiPrismWidth%
   \pgf@y=\prismHeight%
   \pgf@x=-\pgf@x%
   \pgf@y=0.5\pgf@y%
 }
 \anchor{north west}{\northwest}

 \savedanchor{\southeast}{
   \pgf@x=\demiPrismWidth%
   \pgf@y=\prismHeight%
   \pgf@x=2\pgf@x%
   \pgf@y=-0.5\pgf@y%
 }
 \anchor{south east}{\southeast}

 \anchor{north}{
   \center \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \pgf@y=\pgf@yb
 }

 \savedanchor{\south}{
   \pgfpointorigin
   \pgf@y=\prismHeight%
   \pgf@y=-0.5\pgf@y%
 }
 \anchor{south}{\south}

 \anchor{east}{
   \southeast \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \advance\pgf@x by\pgf@xb
   \pgf@x=0.5\pgf@x
   \pgf@y=\pgf@ya
   \advance\pgf@y by\pgf@yb
   \pgf@y=0.5\pgf@y
 }

 \anchor{west}{
   \southwest \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \northwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \advance\pgf@x by\pgf@xb
   \pgf@x=0.5\pgf@x
   \pgf@y=\pgf@ya
   \advance\pgf@y by\pgf@yb
   \pgf@y=0.5\pgf@y
 }

  \inheritanchorborder[from=rectangle]

 \backgroundpath
 {
   \northwest
   \pgfpathmoveto{\pgfpoint{\pgf@x}{\pgf@y}}
   \southwest
   \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
   \southeast
   \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
   \northeast
   \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
   \pgfpathclose
   %
   % FIXME : ceci devrait s'appliquer seulement au triangle intérieur -> un fgpath ou assimilé
   \pgfsetbeveljoin
   \northwest
   \pgfpathmoveto{\pgfpoint{\pgf@x}{\pgf@y}}
   \south
   \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
   \northeast
   \pgfpathlineto{\pgfpoint{\pgf@x}{\pgf@y}}
 }
}






%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Shape [generic optics io]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% keys :
% - io body height : height of the body of the io body
% - io body aspect ratio (alias io body width) : width/height of the body of the io body
% - io aperture width : width of the output device (condenser, etc.) [in units of io body height]
% - io aperture height : height of the output device (condenser, etc.) [in units of io body height]
% - io aperture shift : vertical shift of the output device [in units of io body height]
% - io orientation (ltr or rtl)
\pgfkeys{/tikz/optics/.cd,
 io body height/.initial=0.75cm,
 io body aspect ratio/.initial=2,
 io aperture width/.initial=0.33,
 io aperture height/.initial=0.66,
 io aperture shift/.initial=0,
}
\pgfkeys{/tikz/optics/io body width/.style={/tikz/optics/io body aspect ratio=#1}}
%
\newif\if@tikz@optics@io@ltr
\@tikz@optics@io@ltrtrue
%
\pgfkeys{/tikz/optics/io orientation/.is choice}
\pgfkeys{/tikz/optics/io orientation/ltr/.code={\@tikz@optics@io@ltrtrue}}
\pgfkeys{/tikz/optics/io orientation/rtl/.code={\@tikz@optics@io@ltrfalse}}
%
\pgfdeclareshape{generic optics io}
{
 \savedanchor{\center}{
   \pgfpointorigin
 }
 \anchor{center}{\center}

 \savedmacro\objectHeight{%
   \edef\objectHeight{\pgfkeysvalueof{/tikz/optics/io body height}}%
 }

 \savedmacro\objectWidth{%
   \pgfmathparse{\pgfkeysvalueof{/tikz/optics/io body aspect ratio}}
   \ifpgfmathunitsdeclared%
     \pgfmathsetlengthmacro{\objectWidth}{\pgfkeysvalueof{/tikz/optics/io body aspect ratio}}%
   \else%
     \pgfmathsetlengthmacro{\objectWidth}{\pgfkeysvalueof{/tikz/optics/io body aspect ratio}*\pgfkeysvalueof{/tikz/optics/io body height}}%
   \fi%
 }

 \savedmacro\outHeight{%
   \pgfmathparse{\pgfkeysvalueof{/tikz/optics/io aperture height}}
   \ifpgfmathunitsdeclared%
     \pgfmathsetlengthmacro{\outHeight}{\pgfkeysvalueof{/tikz/optics/io aperture height}}%
   \else%
     \pgfmathsetlengthmacro{\outHeight}{\pgfkeysvalueof{/tikz/optics/io aperture height}*\pgfkeysvalueof{/tikz/optics/io body height}}%
   \fi%
 }

 \savedmacro\outWidth{%
   \pgfmathparse{\pgfkeysvalueof{/tikz/optics/io aperture width}}
   \ifpgfmathunitsdeclared%
     \pgfmathsetlengthmacro{\outWidth}{\pgfkeysvalueof{/tikz/optics/io aperture width}}%
   \else%
     \pgfmathsetlengthmacro{\outWidth}{\pgfkeysvalueof{/tikz/optics/io aperture width}*\pgfkeysvalueof{/tikz/optics/io body height}}%
   \fi%
 }

 \savedmacro\outShift{%
   \pgfmathparse{\pgfkeysvalueof{/tikz/optics/io aperture shift}}
   \ifpgfmathunitsdeclared%
     \pgfmathsetlengthmacro{\outShift}{\pgfkeysvalueof{/tikz/optics/io aperture shift}}%
   \else%
     \pgfmathsetlengthmacro{\outShift}{\pgfkeysvalueof{/tikz/optics/io aperture shift}*\pgfkeysvalueof{/tikz/optics/io body height}}%
   \fi%
 }

 \savedanchor{\bodynortheast}{
   \pgf@x=\objectWidth%
   \pgf@y=\objectHeight%
   \pgf@y=0.5\pgf@y%
   \pgf@x=0.5\pgf@x%
 }
 \anchor{body north east}{\bodynortheast}

 \savedanchor{\bodysouthwest}{
   \pgf@x=\objectWidth%
   \pgf@y=\objectHeight%
   \pgf@y=-0.5\pgf@y%
   \pgf@x=-0.5\pgf@x%
 }
 \anchor{body south west}{\bodysouthwest}

 \savedanchor{\outnortheast}{
   \if@tikz@optics@io@ltr
     % Left To Right (LTR)
     \pgf@x=\objectWidth%
     \pgf@x=0.5\pgf@x%
     \advance\pgf@x by\outWidth
   \else
     % Right To Left (RTL)
     \pgf@x=\objectWidth%
     \pgf@x=0.5\pgf@x%
     \pgf@x=-\pgf@x%
   \fi
   \pgf@y=0pt%
   \advance\pgf@y by\outHeight
   \pgf@y=0.5\pgf@y%
   \advance\pgf@y by\outShift
 }
 \anchor{aperture north east}{\outnortheast}

 \savedanchor{\outsouthwest}{
   \if@tikz@optics@io@ltr
     % Left To Right (LTR)
     \pgf@x=\objectWidth%
     \pgf@x=0.5\pgf@x%
   \else
     % Right To Left (RTL)
     \pgf@x=\objectWidth%
     \pgf@x=0.5\pgf@x%
     \advance\pgf@x by\outWidth
     \pgf@x=-\pgf@x%
   \fi
   \pgf@y=0pt%
   \advance\pgf@y by\outHeight
   \pgf@y=-0.5\pgf@y%
   \advance\pgf@y by\outShift
 }
 \anchor{aperture south west}{\outsouthwest}

 \savedanchor{\outcenter}{
   \if@tikz@optics@io@ltr
     % Left To Right (LTR)
     \pgf@x=\objectWidth%
     \advance\pgf@x by\outWidth
   \else
     % Right To Left (RTL)
     \pgf@x=\objectWidth%
     \advance\pgf@x by\outWidth
     \pgf@x=-\pgf@x%
   \fi
   \pgf@x=0.5\pgf@x%
   \pgf@y=0pt%
   \advance\pgf@y by\outShift
 }
 \anchor{aperture center}{\outcenter}


 \anchor{body center}{\center}

 \anchor{text}{
   \pgfpointorigin
   \advance\pgf@x by -.5\wd\pgfnodeparttextbox%
   \advance\pgf@y by -.5\ht\pgfnodeparttextbox%
   \advance\pgf@y by +.5\dp\pgfnodeparttextbox%
 }

 \anchor{body north}{
   \center \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \bodynortheast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \pgf@y=\pgf@yb
 }
 % north = body north
 \anchor{north}{
   \center \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \bodynortheast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \pgf@y=\pgf@yb
 }

 \anchor{body south}{
   \center \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \bodysouthwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \pgf@y=\pgf@yb
 }
 % south = body south
 \anchor{south}{
   \center \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \bodysouthwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \pgf@y=\pgf@yb
 }

 \anchor{body east}{
   \center \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \bodynortheast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xb
   \pgf@y=\pgf@ya
 }

 \anchor{body west}{
   \center \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \bodysouthwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xb
   \pgf@y=\pgf@ya
 }

 \anchor{body north west}{
   \bodynortheast \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \bodysouthwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xb
   \pgf@y=\pgf@ya
 }

 \anchor{body south east}{
   \bodynortheast \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \bodysouthwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \pgf@y=\pgf@yb
 }


 \anchor{aperture north}{
   \outcenter \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \outnortheast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \pgf@y=\pgf@yb
 }

 \anchor{aperture south}{
   \outcenter \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \outsouthwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \pgf@y=\pgf@yb
 }

 \anchor{aperture east}{
   \outcenter \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \outnortheast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xb
   \pgf@y=\pgf@ya
 }

 \anchor{aperture west}{
   \outcenter \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \outsouthwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xb
   \pgf@y=\pgf@ya
 }

 \anchor{aperture north west}{
   \outnortheast \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \outsouthwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xb
   \pgf@y=\pgf@ya
 }

 \anchor{aperture south east}{
   \outnortheast \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \outsouthwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \pgf@y=\pgf@yb
 }

 \anchor{center}{\center}

 \savedanchor{\realeast}{
   \pgfpointorigin
   \if@tikz@optics@io@ltr
     % Left To Right (LTR)
     %ltr : aperture east (<- out north east)
     \pgf@x=\objectWidth%
     \pgf@x=0.5\pgf@x%
     \advance\pgf@x by\outWidth
     %\pgf@y=0pt%
   \else
     % Right To Left (rtl)
     \pgf@x=\objectWidth%
     \pgf@x=0.5\pgf@x%
   \fi
 }
 \anchor{east}{\realeast}

 \savedanchor{\realwest}{
   \pgfpointorigin
   \if@tikz@optics@io@ltr
     % Left To Right (LTR)
     \pgf@x=\objectWidth%
     \pgf@x=-0.5\pgf@x%
   \else
     % Right To Left (rtl)
     \pgf@x=\objectWidth%
     \pgf@x=0.5\pgf@x%
     \advance\pgf@x by\outWidth
     \pgf@x=-\pgf@x%
   \fi
 }
 \anchor{west}{\realwest}

 % this is used only for the anchorborder
 \savedanchor{\anchorbordersouthwest}{
   \if@tikz@optics@io@ltr
     % Left To Right (LTR)
     \pgf@x=\objectWidth%
     \pgf@x=-0.5\pgf@x%
   \else
     % Right To Left (rtl)
     \pgf@x=\objectWidth%
     \pgf@x=0.5\pgf@x%
     \advance\pgf@x by\outWidth
     \pgf@x=-\pgf@x%
   \fi
   \pgf@y=\objectHeight%
   \pgf@y=-0.5\pgf@y%
 }

 % this is used only for the anchorborder
 \savedanchor{\anchorbordernortheast}{
   \if@tikz@optics@io@ltr
     % Left To Right (LTR)
     \pgf@x=\objectWidth%
     \pgf@x=0.5\pgf@x%
     \advance\pgf@x by\outWidth
   \else
     % Right To Left (RTL)
     \pgf@x=\objectWidth%
     \pgf@x=0.5\pgf@x%
     %\pgf@x=-\pgf@x%
   \fi
   \pgf@y=\objectHeight%
   \pgf@y=0.5\pgf@y%
 }

 % anchorborder
 % c'est celui de rectangle, mais un peu ajusté
 \anchorborder{%
   \pgf@xb=\pgf@x% xb/yb is target
   \pgf@yb=\pgf@y%
   \anchorbordersouthwest%
   \pgf@xa=\pgf@x% xa/ya is se
   \pgf@ya=\pgf@y%
   \anchorbordernortheast%
   \advance\pgf@x by-\pgf@xa%
   \advance\pgf@y by-\pgf@ya%
   \pgf@xc=.5\pgf@x% x/y is half width/height
   \pgf@yc=.5\pgf@y%
   \advance\pgf@xa by\pgf@xc% xa/ya becomes center
   \advance\pgf@ya by\pgf@yc%
   \edef\pgf@marshal{%
     \noexpand\pgfpointborderrectangle
     {\noexpand\pgfqpoint{\the\pgf@xb}{\the\pgf@yb}}
     {\noexpand\pgfqpoint{\the\pgf@xc}{\the\pgf@yc}}%
   }%
   \pgf@process{\pgf@marshal}%
   % \advance\pgf@x by\pgf@xa%
   % \advance\pgf@y by\pgf@ya%
 }

 \backgroundpath
 {
   % corps
   \pgfpathrectanglecorners{\bodynortheast}{\bodysouthwest}
   % out
   \pgfpathrectanglecorners{\outnortheast}{\outsouthwest}

   %\pgfusepath{draw}
   % il ne faut PAS mettre ça pour pouvoir utiliser des styles correctement après (genre double)
 }
}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Sensors
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Shape [sensor line]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Sensor line.
%
% This defines anchors center, north, south, east, west, north east
% north west, south east, south west, as well as
% pixel <i> <subanchor> with <subanchor> is any of the former.
% ça va être horrible à faire
%
% keys :
% - sensor line height
% - sensor line aspect ratio (largeur en unités de la hauteur du capteur)
% - sensor line pixel number
% - sensor line pixel width (en unités de la largeur du capteur)
% - sensor line inner ysep (en unités de la hauteur du capteur)
\pgfkeys{/tikz/optics/.cd,
 sensor line height/.initial=2cm,
 sensor line aspect ratio/.initial=0.2,
 sensor line pixel number/.initial=5,
 sensor line pixel width/.initial=0.4,
 sensor line inner ysep/.initial=0.05, % entre le bord et les capteurs
}

\pgfdeclareshape{sensor line}
{
 \savedanchor{\center}{
   \pgfpointorigin
 }
 \anchor{center}{\center}

 \savedmacro\objectHeight{%
   \edef\objectHeight{\pgfkeysvalueof{/tikz/optics/sensor line height}}%
 }

 \savedmacro\objectWidth{%
   \pgfmathsetlengthmacro{\objectWidth}{\pgfkeysvalueof{/tikz/optics/sensor line aspect ratio}*\pgfkeysvalueof{/tikz/optics/sensor line height}}
 }

 \savedmacro\pixelNumber{%
   \pgfmathtruncatemacro\pixelNumber{\pgfkeysvalueof{/tikz/optics/sensor line pixel number}}%
 }

 \savedmacro\innerysep{%
   \pgfmathparse{\pgfkeysvalueof{/tikz/optics/sensor line inner ysep}}
   \ifpgfmathunitsdeclared%
     \pgfmathsetlengthmacro{\innerysep}{\pgfkeysvalueof{/tikz/optics/sensor line inner ysep}}%
   \else%
     \pgfmathsetlengthmacro{\innerysep}{\pgfkeysvalueof{/tikz/optics/sensor line inner ysep}*\pgfkeysvalueof{/tikz/optics/sensor line height}}%
   \fi%
 }

 \savedmacro\pixelWidth{%
   \pgfmathparse{\pgfkeysvalueof{/tikz/optics/sensor line pixel width}}
   \ifpgfmathunitsdeclared%
     \pgfmathsetlengthmacro{\pixelWidth}{\pgfkeysvalueof{/tikz/optics/sensor line pixel width}}%
   \else%
     \pgfmathsetlengthmacro{\pixelWidth}{\pgfkeysvalueof{/tikz/optics/sensor line pixel width}*\objectWidth}%
   \fi%
 }

 \savedmacro\pixelHeight{%
   \pgfmathparse{(\objectHeight-2*\innerysep)/\pixelNumber}
   \edef\pixelHeight{\pgfmathresult pt}%
 }

 \savedanchor{\northeast}{
   \pgf@x=\objectWidth%
   \pgf@y=\objectHeight%
   \pgf@y=0.5\pgf@y%
   \pgf@x=0.5\pgf@x%
 }
 \anchor{north east}{\northeast}

 \savedanchor{\southwest}{
   \pgf@x=\objectWidth%
   \pgf@y=\objectHeight%
   \pgf@y=-0.5\pgf@y%
   \pgf@x=-0.5\pgf@x%
 }
 \anchor{south west}{\southwest}

 \anchor{north}{
   \center \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \pgf@y=\pgf@yb
 }

 \anchor{south}{
   \center \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \pgf@y=\pgf@yb
 }

 \anchor{east}{
   \center \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \northeast \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xb
   \pgf@y=\pgf@ya
 }

 \anchor{west}{
   \center \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xb
   \pgf@y=\pgf@ya
 }

 \anchor{north west}{
   \northeast \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xb
   \pgf@y=\pgf@ya
 }

 \anchor{south east}{
   \northeast \pgf@xa=\pgf@x \pgf@ya=\pgf@y
   \southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
   \pgf@x=\pgf@xa
   \pgf@y=\pgf@yb
 }

 % ok, idée :
 % HAUT (north) du pixel n (allant de 1 à N)
 % \objectHeight/2 - \innerysep - (n-1) * \pixelHeight
 % BAS (south) du pixel n
 % \objectHeight/2 - \innerysep - n * \pixelHeight
 % west = le même que la boite, donc utiliser \southwest
 % east = west + \pixelWidth

 % Le but de ce code est de définir des ancres
 % pixel <i> <pos>
 % pour <i> = 4, 2, ..., \pixelNumber
 % et <pos> = north, south, east, west, north west, south west, north east south east, center
 % Comme \pixelNumber est défini dynamiquement, il faut passer par cette horreur.
 % Le code est inspiré de pfglibraryshapes.geometric.code.tex (shape regular polygon).
 \expandafter\pgfutil@g@addto@macro\csname pgf@sh@s@sensor line\endcsname{%
   \c@pgf@counta\pixelNumber\relax%
   \pgfmathloop%
     \ifnum\c@pgf@counta>0\relax%
       \pgfutil@ifundefined{pgf@anchor@sensor line@pixel\space\the\c@pgf@counta\space north west}{%
       %
       % ...(manually \xdef as \gdef is normally used by \anchor)...
       %
       %
       % pixel surface north
       \expandafter\xdef\csname pgf@anchor@sensor line@pixel\space\the\c@pgf@counta\space north\endcsname{%
         \noexpand\northeast \noexpand\pgf@xa=\noexpand\pgf@x \noexpand\pgf@ya=\noexpand\pgf@y
         \noexpand\southwest \noexpand\pgf@xb=\noexpand\pgf@x \noexpand\pgf@yb=\noexpand\pgf@y
         \noexpand\pgf@x=\noexpand\pixelWidth
         \noexpand\pgf@x=.5\noexpand\pgf@x
         \noexpand\advance\noexpand\pgf@x by\noexpand\pgf@xb
         \noexpand\pgf@y=\noexpand\pgf@ya
         \noexpand\newdimen\noexpand\temp@y
         \noexpand\pgfmathsetlength\noexpand\temp@y{(\the\c@pgf@counta-\noexpand\pixelNumber)*\noexpand\pixelHeight-\noexpand\innerysep}
         \noexpand\advance\noexpand\pgf@y by\noexpand\temp@y
       }%
       %
       %
       % pixel surface north east
       \expandafter\xdef\csname pgf@anchor@sensor line@pixel\space\the\c@pgf@counta\space north east\endcsname{%
         \noexpand\northeast \noexpand\pgf@xa=\noexpand\pgf@x \noexpand\pgf@ya=\noexpand\pgf@y
         \noexpand\southwest \noexpand\pgf@xb=\noexpand\pgf@x \noexpand\pgf@yb=\noexpand\pgf@y
         \noexpand\pgf@x=\noexpand\pixelWidth
         \noexpand\advance\noexpand\pgf@x by\noexpand\pgf@xb
         \noexpand\pgf@y=\noexpand\pgf@ya
         \noexpand\newdimen\noexpand\temp@y
         \noexpand\pgfmathsetlength\noexpand\temp@y{(\the\c@pgf@counta-\noexpand\pixelNumber)*\noexpand\pixelHeight-\noexpand\innerysep}
         \noexpand\advance\noexpand\pgf@y by\noexpand\temp@y
       }%
       %
       %
       % pixel surface north west
       \expandafter\xdef\csname pgf@anchor@sensor line@pixel\space\the\c@pgf@counta\space north west\endcsname{%
         \noexpand\northeast \noexpand\pgf@xa=\noexpand\pgf@x \noexpand\pgf@ya=\noexpand\pgf@y
         \noexpand\southwest \noexpand\pgf@xb=\noexpand\pgf@x \noexpand\pgf@yb=\noexpand\pgf@y
         \noexpand\pgf@x=\noexpand\pgf@xb
         \noexpand\pgf@y=\noexpand\pgf@ya
         \noexpand\newdimen\noexpand\temp@y
         \noexpand\pgfmathsetlength\noexpand\temp@y{(\the\c@pgf@counta-\noexpand\pixelNumber)*\noexpand\pixelHeight-\noexpand\innerysep}
         \noexpand\advance\noexpand\pgf@y by\noexpand\temp@y
       }%
       %
       %
       % pixel surface south
       \expandafter\xdef\csname pgf@anchor@sensor line@pixel\space\the\c@pgf@counta\space south\endcsname{%
         \noexpand\northeast \noexpand\pgf@xa=\noexpand\pgf@x \noexpand\pgf@ya=\noexpand\pgf@y
         \noexpand\southwest \noexpand\pgf@xb=\noexpand\pgf@x \noexpand\pgf@yb=\noexpand\pgf@y
         \noexpand\pgf@x=\noexpand\pixelWidth
         \noexpand\pgf@x=.5\noexpand\pgf@x
         \noexpand\advance\noexpand\pgf@x by\noexpand\pgf@xb
         \noexpand\pgf@y=\noexpand\pgf@ya
         \noexpand\newdimen\noexpand\temp@y
         \noexpand\pgfmathsetlength\noexpand\temp@y{(\the\c@pgf@counta-\noexpand\pixelNumber-1)*\noexpand\pixelHeight-\noexpand\innerysep}
         \noexpand\advance\noexpand\pgf@y by\noexpand\temp@y
       }%
       %
       %
       % pixel surface south east
       \expandafter\xdef\csname pgf@anchor@sensor line@pixel\space\the\c@pgf@counta\space south east\endcsname{%
         \noexpand\northeast \noexpand\pgf@xa=\noexpand\pgf@x \noexpand\pgf@ya=\noexpand\pgf@y
         \noexpand\southwest \noexpand\pgf@xb=\noexpand\pgf@x \noexpand\pgf@yb=\noexpand\pgf@y
         \noexpand\pgf@x=\noexpand\pixelWidth
         \noexpand\advance\noexpand\pgf@x by\noexpand\pgf@xb
         \noexpand\pgf@y=\noexpand\pgf@ya
         \noexpand\newdimen\noexpand\temp@y
         \noexpand\pgfmathsetlength\noexpand\temp@y{(\the\c@pgf@counta-\noexpand\pixelNumber-1)*\noexpand\pixelHeight-\noexpand\innerysep}
         \noexpand\advance\noexpand\pgf@y by\noexpand\temp@y
       }%
       %
       %
       % pixel surface south west
       \expandafter\xdef\csname pgf@anchor@sensor line@pixel\space\the\c@pgf@counta\space south west\endcsname{%
         \noexpand\northeast \noexpand\pgf@xa=\noexpand\pgf@x \noexpand\pgf@ya=\noexpand\pgf@y
         \noexpand\southwest \noexpand\pgf@xb=\noexpand\pgf@x \noexpand\pgf@yb=\noexpand\pgf@y
         \noexpand\pgf@x=\noexpand\pgf@xb
         \noexpand\pgf@y=\noexpand\pgf@ya
         \noexpand\newdimen\noexpand\temp@y
         \noexpand\pgfmathsetlength\noexpand\temp@y{(\the\c@pgf@counta-\noexpand\pixelNumber-1)*\noexpand\pixelHeight-\noexpand\innerysep}
         \noexpand\advance\noexpand\pgf@y by\noexpand\temp@y
       }%
       %
       %
       % pixel surface east
       \expandafter\xdef\csname pgf@anchor@sensor line@pixel\space\the\c@pgf@counta\space east\endcsname{%
         \noexpand\northeast \noexpand\pgf@xa=\noexpand\pgf@x \noexpand\pgf@ya=\noexpand\pgf@y
         \noexpand\southwest \noexpand\pgf@xb=\noexpand\pgf@x \noexpand\pgf@yb=\noexpand\pgf@y
         \noexpand\pgf@x=\noexpand\pixelWidth
         \noexpand\advance\noexpand\pgf@x by\noexpand\pgf@xb
         \noexpand\pgf@y=\noexpand\pgf@ya
         \noexpand\newdimen\noexpand\temp@y
         \noexpand\pgfmathsetlength\noexpand\temp@y{(\the\c@pgf@counta-\noexpand\pixelNumber-0.5)*\noexpand\pixelHeight-\noexpand\innerysep}
         \noexpand\advance\noexpand\pgf@y by\noexpand\temp@y
       }%
       %
       %
       % pixel surface center
       \expandafter\xdef\csname pgf@anchor@sensor line@pixel\space\the\c@pgf@counta\space center\endcsname{%
         \noexpand\northeast \noexpand\pgf@xa=\noexpand\pgf@x \noexpand\pgf@ya=\noexpand\pgf@y
         \noexpand\southwest \noexpand\pgf@xb=\noexpand\pgf@x \noexpand\pgf@yb=\noexpand\pgf@y
         \noexpand\pgf@x=\noexpand\pixelWidth
         \noexpand\pgf@x=.5\noexpand\pgf@x
         \noexpand\advance\noexpand\pgf@x by\noexpand\pgf@xb
         \noexpand\pgf@y=\noexpand\pgf@ya
         \noexpand\newdimen\noexpand\temp@y
         \noexpand\pgfmathsetlength\noexpand\temp@y{(\the\c@pgf@counta-\noexpand\pixelNumber-0.5)*\noexpand\pixelHeight-\noexpand\innerysep}
         \noexpand\advance\noexpand\pgf@y by\noexpand\temp@y
       }%
       %
       %
       % pixel surface west
       \expandafter\xdef\csname pgf@anchor@sensor line@pixel\space\the\c@pgf@counta\space west\endcsname{%
         \noexpand\northeast \noexpand\pgf@xa=\noexpand\pgf@x \noexpand\pgf@ya=\noexpand\pgf@y
         \noexpand\southwest \noexpand\pgf@xb=\noexpand\pgf@x \noexpand\pgf@yb=\noexpand\pgf@y
         \noexpand\pgf@x=\noexpand\pgf@xb
         \noexpand\pgf@y=\noexpand\pgf@ya
         \noexpand\newdimen\noexpand\temp@y
         \noexpand\pgfmathsetlength\noexpand\temp@y{(\the\c@pgf@counta-\noexpand\pixelNumber-0.5)*\noexpand\pixelHeight-\noexpand\innerysep}
         \noexpand\advance\noexpand\pgf@y by\noexpand\temp@y
       }%
     }{\c@pgf@counta0\relax}%
     \advance\c@pgf@counta-1\relax%
   \repeatpgfmathloop%
 }%

 \inheritanchorborder[from=rectangle]

 \backgroundpath
 {
   % rectangle contour
   \pgfpathrectanglecorners{\northeast}{\southwest}

   % dessin des pixels
   \c@pgf@counta\pixelNumber\relax%
   \pgfmathloop%
     \ifnum\c@pgf@counta>0\relax%
       \newdimen\pixel@northeast@x
       \newdimen\pixel@northeast@y
       \newdimen\pixel@southwest@x
       \newdimen\pixel@southwest@y
       \northeast \pgf@xa=\pgf@x \pgf@ya=\pgf@y
       \southwest \pgf@xb=\pgf@x \pgf@yb=\pgf@y
       % calcul pixel@northeast
       %% calcul x
       \pixel@northeast@x=\pgf@xb
       \advance\pixel@northeast@x by\pixelWidth
       %% calcul y
       \pixel@northeast@y=\pgf@ya
       \newdimen\temp@y
       \pgfmathsetlength\temp@y{(\the\c@pgf@counta-\pixelNumber)*\pixelHeight-\innerysep}
       \advance\pixel@northeast@y by\noexpand\temp@y
       % calcul pixel@southwest
       \pixel@southwest@x=\pgf@xb
       \pixel@southwest@y=\pgf@ya
       \newdimen\temp@y
       \pgfmathsetlength\temp@y{(\the\c@pgf@counta-\pixelNumber-1)*\pixelHeight-\innerysep}
       \advance\pixel@southwest@y by\temp@y
       % dessin
       \pgfpathrectanglecorners{\pgfpoint{\pixel@northeast@x}{\pixel@northeast@y}}{\pgfpoint{\pixel@southwest@x}{\pixel@southwest@y}}
     \advance\c@pgf@counta-1\relax%
   \repeatpgfmathloop%
 }
}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Styles defining optics elements in terms of the existing shapes.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Style [screen]
\pgfkeys{/tikz/optics/screen/.style={thin optics element, very thick}}
% Style [diffraction grating]
\pgfkeys{/tikz/optics/diffraction grating/.style={thin optics element, /tikz/optics/cheating dash={on 4pt off 2pt}}}
% Style [grid]
\pgfkeys{/tikz/optics/grid/.style={thin optics element, /tikz/optics/cheating dash={on 4pt off 2pt}, ultra thick}}
% Style [semi-transparent mirror]
\pgfkeys{/tikz/optics/semi-transparent mirror/.style={thin optics element, densely dotted, thick}}
% Style [diaphragm]
\pgfkeys{/tikz/optics/diaphragm/.style={slit,/tikz/optics/slit height=0.4}}


% Style [generic lamp]
\pgfkeys{/tikz/optics/generic lamp/.style={shape=generic optics io,optics,draw}}
% Style [generic sensor]
\pgfkeys{/tikz/optics/generic sensor/.style={shape=generic optics io,optics,io orientation=rtl,draw, io body height=1cm, io body aspect ratio=0.5, io aperture width=0.15}}
% Style [halogen lamp]
\pgfkeys{/tikz/optics/halogen lamp/.style={/tikz/optics/generic lamp, io body height=0.75cm, io body aspect ratio=2,io aperture width=0.33,io aperture height=0.66,io aperture shift=0}}
% Style [spectral lamp]
\pgfkeys{/tikz/optics/spectral lamp/.style={/tikz/optics/generic lamp, io body height=2.25cm, io body aspect ratio=2/3,io aperture width=0.11,io aperture height=0.22,io aperture shift=0.25,/tikz/optics/io multiline}}
% Style [laser]
\pgfkeys{/tikz/optics/laser/.style={/tikz/optics/generic lamp, io body height=0.5cm, io body aspect ratio=3,io aperture width=0.22,io aperture height=0.5,io aperture shift=0}}
% Style [laser']
\pgfkeys{/tikz/optics/laser'/.style={/tikz/optics/generic lamp, io body height=0.5cm, io body aspect ratio=3,io aperture width=0,io aperture height=0.5,io aperture shift=0}}
% Style [beam splitter]
\pgfkeys{/tikz/optics/beam splitter/.style={shape=polarizer, optics, draw, object height=1cm, object aspect ratio=1}}



%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Helper style to draw correctly dashed paths.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% source : http://tex.stackexchange.com/questions/133271/can-tikz-dashed-lines-emulate-pstricks-dashed-lines
% le but est d'avoir des dash symétriques par rapport au milieu et surtout avec un trait entier de chaque côté
\tikzset{
   /tikz/optics/cheating dash/.code args={on #1 off #2}{
       % Use csname so catcode of @ doesn't have do be changed.
       \csname tikz@addoption\endcsname{%
           \pgfgetpath\currentpath%
           \pgfprocessround{\currentpath}{\currentpath}%
           \csname pgf@decorate@parsesoftpath\endcsname{\currentpath}{\currentpath}%
           \pgfmathparse{\csname pgf@decorate@totalpathlength\endcsname-#1}\let\rest=\pgfmathresult%
           \pgfmathparse{#1+#2}\let\onoff=\pgfmathresult%
           \pgfmathparse{max(floor(\rest/\onoff), 1)}\let\nfullonoff=\pgfmathresult%
           \pgfmathparse{max((\rest-\onoff*\nfullonoff)/\nfullonoff+#2, #2)}\let\offexpand=\pgfmathresult%
           \pgfsetdash{{#1}{\offexpand}}{0pt}}%
   }
}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Helper style for multiline io elements.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\pgfkeys{/tikz/optics/io multiline/.code={\newdimen\tmplen\pgfmathsetlength{\tmplen}{\pgfkeysvalueof{/tikz/optics/io body aspect ratio}*\pgfkeysvalueof{/tikz/optics/io body height}}\tikzset{text width=\the\tmplen,align=center}}}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Helper styles to mark interesing points
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


% Style [mark point]
% Describes how interesting points should be drawn (e.g. by [draw focal points], [draw mirror focus], [draw mirror center])
\pgfkeys{/tikz/optics/mark point/.style={optics/mark a cross}}

% Style [draw focal points]
% Should be applied to a [shape=lens] node to draw its focal points according to the style [mark point].
\pgfkeys{/tikz/optics/draw focal points/.style={append after command={
   \pgfextra{
     \begin{pgfinterruptpath}
         \node[/tikz/optics/mark point,#1] at (\tikzlastnode.west focal point) {};
         \node[/tikz/optics/mark point,#1] at (\tikzlastnode.east focal point) {};
     \end{pgfinterruptpath}
   }
 }
}}

% Style [draw mirror focus]
% Should be applied to a [shape=spherical mirror] node to draw its focal point according to the style [mark point].
\pgfkeys{/tikz/optics/draw mirror focus/.style={append after command={
   \pgfextra{
     \begin{pgfinterruptpath}
         \node[/tikz/optics/mark point,#1] at (\tikzlastnode.focus) {};
     \end{pgfinterruptpath}
   }
 }
}}

% Style [draw mirror center]
% Should be applied to a [shape=spherical mirror] node to draw its center according to the style [mark point].
\pgfkeys{/tikz/optics/draw mirror center/.style={append after command={
   \pgfextra{
     \begin{pgfinterruptpath}
         \node[/tikz/optics/mark point,#1] at (\tikzlastnode.mirror center) {};
     \end{pgfinterruptpath}
   }
 }
}}

% Style [mark a cross]
% Draws a cross at the node
\pgfkeys{/tikz/optics/mark a cross/.style={cross out,draw,inner sep=0pt,minimum width=2pt,minimum height=2pt}}

% idée : utiliser pgfextra pour les flèches, si on peut avoir les deux dernières nodes ?

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Helper styles to easily put things on paths.
% It is often needed in optics to have e.g. arrows in the middle of a path.
% It is often needed everywhere to be able to put a coordinate somewhere on
% a path.
% This is the aim of these helpers.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Style [put coordinate]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Le style [put coordinate=<coord> at <pos>] crée une node[coordinate]
% à l'abscisse curviligne <pos> sur le chemin auquel est appliqué le style.
%
% Exemple :
% \draw[put coordinate=P at 0.3] (0,0) to[bend left] (2cm,0);
% \draw[red] (P) -- (0,0);
%
\tikzset{
 put coordinate/.style args={#1 at #2}{decoration={markings, mark=at position #2 with {\node[coordinate] (#1) {};}},postaction={decorate}}
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Style [put arrow]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% The aim of this horrible mess is that I want expansion to take place at the right time, so I can ask for something like
% \draw[/tikz/optics/->-={at=0.25}, /tikz/optics/->-={at=0.75}] (0,0) -- (2cm,2cm) -- (4cm,0);
% and have it work. Obviously, I want more complicated things (several arrows with different directions, colors, number of >, etc. on the same path).
% With a naive implementation, this does not work and the last setting always wins.
% A possible solution would be positional arguments, however keywords arguments are Better (tm).
% Hence the need to take care of expansion order, so the specifications apply only to the currently drawn arrow tip.
% The main idea behing this code is to use Magic (tm) so that Things Work (tm) and never touch it again.
% However, it is obvious from a trivial application of Murphy Law that this will backfire sometime.
% Indeed, a key with positional arguments are used internally (|ordered draw key|), which is called from the parsed arguments.
\tikzset{/tikz/put arrow/.cd,
 pos/.initial=0.5,
 at/.style={pos=#1},
 pos var/.initial={},
 style/.initial={},
 style var/.initial={},
 postaction style/.initial={}, % more expansion magic needed for ->n- and friends (\arrow[thing=stuff] does not seem to work, probably because of the =)
 arrow macro/.initial={arrow},
 arrow macro var/.initial={},
 arrow type/.initial={>},
 arrow type var/.initial={},
 reversed/.style={arrow macro=arrowreversed},
 arrow/.style={arrow type=#1},
 arrow'/.style={arrow type=#1, reversed},
 every arrow/.style={},
}

\tikzset{put arrow/.code={
 % parse arguments correctly
 \tikzset{/tikz/put arrow/.cd, #1}
 \tikzset{/tikz/put arrow/pos var/.expand once={\pgfkeysvalueof{/tikz/put arrow/pos}}}
 \tikzset{/tikz/put arrow/style var/.expanded={\pgfkeysvalueof{/tikz/put arrow/style}}}
 \tikzset{/tikz/put arrow/arrow macro var/.expand once={\pgfkeysvalueof{/tikz/put arrow/arrow macro}}}
 \tikzset{/tikz/put arrow/arrow type var/.expand once={\pgfkeysvalueof{/tikz/put arrow/arrow type}}}
 % call |ordered draw key| which does the real job
 \tikzset{/tikz/put arrow/ordered draw key/.expanded=%
     {\pgfkeysvalueof{/tikz/put arrow/pos var}}%
     {\pgfkeysvalueof{/tikz/put arrow/style var}}%
     {\pgfkeysvalueof{/tikz/put arrow/arrow macro var}}%
     {\pgfkeysvalueof{/tikz/put arrow/arrow type var}}%
     {\pgfkeysvalueof{/tikz/put arrow/postaction style}}%
 }
 % restore initial values
 \tikzset{/tikz/put arrow/pos=0.5}
 \tikzset{/tikz/put arrow/style={}}
 \tikzset{/tikz/put arrow/arrow macro={arrow}}
 \tikzset{/tikz/put arrow/arrow type={>}}
}}

\tikzset{/tikz/put arrow/ordered draw key/.code n args={5}{
 \tikzset{postaction={#5,decorate, decoration={markings, mark=at position #1 with {\csname #3\endcsname[/tikz/put arrow/every arrow,#2]{#4}};}}}
}}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Styles to mark light rays
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\tikzset{/tikz/optics/multiple ray arrow/.cd,
 n/.initial=1,
 n var/.initial=1,
 set n/.code={\pgfsetarrowoptions{multiple ray arrow}{#1}},
}


\pgfkeys{
 /tikz/optics/.cd,
 use ray arrow >/.code 2 args={
   \pgfsetarrowoptions{ray arrow@length}{4pt}
   \pgfsetarrowoptions{ray arrow@angle}{50}
   \tikzset{/tikz/put arrow/postaction style/.expanded={/tikz/optics/multiple ray arrow/set n=#1}}
   \tikzset{/tikz/put arrow/.expanded={arrow={multiple ray arrow}, #2}}
 },
 use ray arrow </.code 2 args={
   \pgfsetarrowoptions{ray arrow@length}{4pt}
   \pgfsetarrowoptions{ray arrow@angle}{50}
   \tikzset{/tikz/put arrow/postaction style/.expanded={/tikz/optics/multiple ray arrow/set n=#1}}
   \tikzset{/tikz/put arrow/.expanded={arrow'={multiple ray arrow}, #2}}
 },
 ->n-/.code={
   \tikzset{/tikz/optics/multiple ray arrow/.cd, .collect unknowns,%
     #1,
     unknown options/.get = \arrowkeys}
   \tikzset{/tikz/optics/multiple ray arrow/n var/.expand once={\pgfkeysvalueof{/tikz/optics/multiple ray arrow/n}}}
   \tikzset{/tikz/optics/use ray arrow >={\pgfkeysvalueof{/tikz/optics/multiple ray arrow/n var}}{\arrowkeys}}
 },
 -<n-/.code={
   \tikzset{/tikz/optics/multiple ray arrow/.cd, .collect unknowns,%
     #1,
     unknown options/.get = \arrowkeys}
   \tikzset{/tikz/optics/multiple ray arrow/n var/.expand once={\pgfkeysvalueof{/tikz/optics/multiple ray arrow/n}}}
   \tikzset{/tikz/optics/use ray arrow <={\pgfkeysvalueof{/tikz/optics/multiple ray arrow/n var}}{\arrowkeys}}
 },
 %
 ->-/.style={/tikz/optics/->n-={n=1, #1}},
 -<-/.style={/tikz/optics/-<n-={n=1, #1}},
 ->>-/.style={/tikz/optics/->n-={n=2, #1}},
 -<<-/.style={/tikz/optics/-<n-={n=2, #1}},
 ->>>-/.style={/tikz/optics/->n-={n=3, #1}},
 -<<<-/.style={/tikz/optics/-<n-={n=3, #1}},
 ->>>>-/.style={/tikz/optics/->n-={n=4, #1}},
 -<<<<-/.style={/tikz/optics/-<n-={n=4, #1}},
}




%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Styles [dim arrow] and [short dim arrow]
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\def\dimarrow@short@position{0}
\newif\ifdimarrow@nearstart
\dimarrow@nearstarttrue
\tikzset{%
 /tikz/dim arrow/.code={\tikzset{draw,/tikz/dim arrow/draw dim arrow}\pgfkeys{/tikz/dim arrow/.cd,#1}},
 /tikz/dim arrow'/.code={\pgfkeysgetvalue{/tikz/dim arrow/raise}{\tmp@tdar}\tikzset{draw,/tikz/dim arrow/draw dim arrow,/tikz/dim arrow/raise=-\tmp@tdar}\pgfkeys{/tikz/dim arrow/.cd,#1}},
 /tikz/short dim arrow/.code={\tikzset{draw,/tikz/dim arrow/draw short dim arrow}\pgfkeys{/tikz/dim arrow/.cd,#1}},
 /tikz/short dim arrow'/.code={\pgfkeysgetvalue{/tikz/dim arrow/raise}{\tmp@tdar}\tikzset{draw,/tikz/dim arrow/draw short dim arrow,/tikz/dim arrow/raise=-\tmp@tdar}\pgfkeys{/tikz/dim arrow/.cd,#1}},
 /tikz/dim arrow/.cd,
 raise/.initial={0.5cm},
 no raise/.style={raise=0},
 label/.code={\pgfkeys{/tikz/dim arrow/label text=#1}},
 label'/.code={\pgfkeys{/tikz/dim arrow/label text=#1,/tikz/dim arrow/label style/.append style={swap},}},
 label text/.initial={},
 label style/.style={},
 label near start/.code={\def\dimarrow@short@position{0}}, % only short
 label near middle/.code={\def\dimarrow@short@position{2}}, % only short
 label near end/.code={\def\dimarrow@short@position{1}}, % only short
 arrow length/.initial={5mm}, % only for short
 draw short dim arrow/.style={to path={\pgfextra{%
   \let\tikz@mode@save=\tikz@mode%
       \let\tikz@options@save=\tikz@options%
   \newdimen\labelTotalRaise
   \pgfmathsetlength\labelTotalRaise{\pgfkeysvalueof{/tikz/dim arrow/raise}}
       \pgfinterruptpath
       \draw[>=technical,->|] \pgfextra{\let\tikz@mode=\tikz@mode@save\let\tikz@options=\tikz@options@save}
   let
       \p1=($(\tikztostart)!\pgfkeysvalueof{/tikz/dim arrow/raise}!90:(\tikztotarget)$),
       \p2=($(\tikztotarget)!\pgfkeysvalueof{/tikz/dim arrow/raise}!-90:(\tikztostart)$)
       in ($(\p1)!-\pgfkeysvalueof{/tikz/dim arrow/arrow length}!(\p2)$) -- ($(\p1)!0!(\p2)$);
   \draw[>=technical,->|] \pgfextra{\let\tikz@mode=\tikz@mode@save\let\tikz@options=\tikz@options@save}
   let
       \p1=($(\tikztostart)!\pgfkeysvalueof{/tikz/dim arrow/raise}!90:(\tikztotarget)$),
       \p2=($(\tikztotarget)!\pgfkeysvalueof{/tikz/dim arrow/raise}!-90:(\tikztostart)$)
       in ($(\p2)!-\pgfkeysvalueof{/tikz/dim arrow/arrow length}!(\p1)$) -- ($(\p2)!0!(\p1)$);
   \ifnum\dimarrow@short@position=0
   \path let
       \p1=($(\tikztostart)!\labelTotalRaise!90:(\tikztotarget)$),
       \p2=($(\tikztotarget)!\labelTotalRaise!-90:(\tikztostart)$)
       in let
   \p3=($(\p1)!-1*\pgfkeysvalueof{/tikz/dim arrow/arrow length}!(\p2)$),
   \p4=($(\p1)!-0*\pgfkeysvalueof{/tikz/dim arrow/arrow length}!(\p2)$)
   in
   (\p3) -- (\p4) node[pos=0.5,auto=left,/tikz/dim arrow/label style] {\pgfkeysvalueof{/tikz/dim arrow/label text}};
 \fi
   \ifnum\dimarrow@short@position=1
     \path let
       \p1=($(\tikztostart)!\labelTotalRaise!90:(\tikztotarget)$),
       \p2=($(\tikztotarget)!\labelTotalRaise!-90:(\tikztostart)$)
       in let
   \p3=($(\p2)!-1*\pgfkeysvalueof{/tikz/dim arrow/arrow length}!(\p1)$),
   \p4=($(\p2)!-0*\pgfkeysvalueof{/tikz/dim arrow/arrow length}!(\p1)$)
   in
   (\p4) -- (\p3) node[pos=0.5,auto=left,/tikz/dim arrow/label style] {\pgfkeysvalueof{/tikz/dim arrow/label text}};
   \fi
 \ifnum\dimarrow@short@position=2
   \path let
       \p1=($(\tikztostart)!\labelTotalRaise!90:(\tikztotarget)$),
       \p2=($(\tikztotarget)!\labelTotalRaise!-90:(\tikztostart)$)
   in
   (\p1) -- (\p2) node[pos=0.5,/tikz/dim arrow/label style] {\pgfkeysvalueof{/tikz/dim arrow/label text}};
 \fi
       \endpgfinterruptpath
     }(\tikztostart) (\tikztotarget) \tikztonodes
   }
 },
 draw dim arrow/.style={to path={\pgfextra{%
   \let\tikz@mode@save=\tikz@mode%
       \let\tikz@options@save=\tikz@options%
   \newdimen\labelTotalRaise
   \pgfmathsetlength\labelTotalRaise{\pgfkeysvalueof{/tikz/dim arrow/raise}}
       \pgfinterruptpath
       \draw[>=technical,|<->|] \pgfextra{\let\tikz@mode=\tikz@mode@save\let\tikz@options=\tikz@options@save}
   let
       \p1=($(\tikztostart)!\pgfkeysvalueof{/tikz/dim arrow/raise}!90:(\tikztotarget)$),
       \p2=($(\tikztotarget)!\pgfkeysvalueof{/tikz/dim arrow/raise}!-90:(\tikztostart)$)
       in (\p1) -- (\p2);
   \path let
       \p1=($(\tikztostart)!\labelTotalRaise!90:(\tikztotarget)$),
       \p2=($(\tikztotarget)!\labelTotalRaise!-90:(\tikztostart)$)
       in (\p1) -- (\p2) node[pos=0.5,auto=left,/tikz/dim arrow/label style] {\pgfkeysvalueof{/tikz/dim arrow/label text}};
   % rq : inner sep controle la distance chemin-node
       \endpgfinterruptpath
     }(\tikztostart) (\tikztotarget) \tikztonodes
   }
 },
}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Arrows
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Arrow lens arrow
% used to draw lenses (perhaps not the best idea).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\pgfsetarrowoptions{lens arrow@length}{6pt}
\pgfsetarrowoptions{lens arrow@angle}{50}
\pgfarrowsdeclare{lens arrow}{lens arrow}
{
  \pgfarrowsleftextend{0pt}
  \pgfarrowsrightextend{0pt}
}
{
 \pgfsetroundcap
 \pgfsetmiterjoin
 \pgfmathsetlength{\pgfutil@tempdimb}{\pgfgetarrowoptions{lens arrow@length}*sin(\pgfgetarrowoptions{lens arrow@angle}/2)}
 \def\arrow@origin{\pgfpoint{0pt}{0pt}}
 \pgfutil@tempdima=\pgfgetarrowoptions{lens arrow@length}%
 \pgfmathsetmacro{\tmp@lens@angle}{90+\pgfgetarrowoptions{lens arrow@angle}}
 \pgfmathsetmacro{\tmp@lens@anglediv}{\pgfgetarrowoptions{lens arrow@angle}/2}
 \advance\pgfutil@tempdima by -1.5\pgflinewidth%
 \pgfmathsetlength{\pgfutil@tempdima}{\pgfutil@tempdima/cos(\pgfgetarrowoptions{lens arrow@angle}/2)}
 \pgfpathmoveto{\pgfpointadd{\arrow@origin}{\pgfqpointpolar{\tmp@lens@angle}{\pgfutil@tempdima}}}
 \pgfpathlineto{\arrow@origin}
 \pgfpathlineto{\pgfpointadd{\arrow@origin}{\pgfqpointpolar{-\tmp@lens@angle}{\pgfutil@tempdima}}}
 \pgfusepathqstroke
}
\pgfarrowsdeclarereversed{lens arrow reversed}{lens arrow reversed}{lens arrow}{lens arrow}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Ray arrow
% It is useful to have an arrow which goes on the exact middle of a path.
% This is used on ->-, etc.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% flèche utilisée pour marquer les rayons lumineux (avec les styles ->-, etc.)
\pgfsetarrowoptions{ray arrow@length}{4pt}
\pgfsetarrowoptions{ray arrow@angle}{45}

\makeatletter

\pgfsetarrowoptions{multiple ray arrow}{0}
\pgfarrowsdeclare{multiple ray arrow}{multiple ray arrow}
{
   \pgfarrowsleftextend{0pt}
   \pgfarrowsrightextend{0pt}
}
{
 \pgfsetroundcap
 \pgfsetmiterjoin
 \pgfutil@tempdima=\pgfgetarrowoptions{ray arrow@length}%
 \pgfmathsetmacro{\tmp@ray@angle}{90+\pgfgetarrowoptions{ray arrow@angle}}
 \pgfmathsetmacro{\tmp@ray@anglediv}{\pgfgetarrowoptions{ray arrow@angle}/2}
 \advance\pgfutil@tempdima by -1.5\pgflinewidth%
 \pgfmathsetlength{\pgfutil@tempdima}{\pgfutil@tempdima/cos(\pgfgetarrowoptions{ray arrow@angle}/2)}
 %
 \foreach \i in {1,...,\pgfgetarrowoptions{multiple ray arrow}}
 {
   \pgfmathsetlength{\pgfutil@tempdimb}{(2*\i-\pgfgetarrowoptions{multiple ray arrow})*\pgfgetarrowoptions{ray arrow@length}*sin(\pgfgetarrowoptions{ray arrow@angle}/2)}
   %
   \def\arrow@origin{\pgfpoint{\pgfutil@tempdimb}{0pt}}
   %
   \pgfpathmoveto{\pgfpointadd{\arrow@origin}{\pgfqpointpolar{\tmp@ray@angle}{\pgfutil@tempdima}}}
   \pgfpathlineto{\arrow@origin}
   \pgfpathlineto{\pgfpointadd{\arrow@origin}{\pgfqpointpolar{-\tmp@ray@angle}{\pgfutil@tempdima}}}
   \pgfusepathqstroke
 }
}


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Arrow technical
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\makeatletter
\pgfarrowsdeclare{technical}{technical}
{%
 \pgfutil@tempdima=0.48pt%
 \pgfutil@tempdimb=\pgflinewidth%
 \ifdim\pgfinnerlinewidth>0pt%
   \pgfmathsetlength\pgfutil@tempdimb{.6\pgflinewidth-.4*\pgfinnerlinewidth}%
 \fi%
 \advance\pgfutil@tempdima by.3\pgfutil@tempdimb%
 \pgfarrowsleftextend{+-3\pgfutil@tempdima}%
 \pgfarrowsrightextend{+8\pgfutil@tempdima}%
}
{%
 \pgfutil@tempdima=0.48pt%
 \pgfutil@tempdimb=\pgflinewidth%
 \ifdim\pgfinnerlinewidth>0pt%
   \pgfmathsetlength\pgfutil@tempdimb{.6\pgflinewidth-.4*\pgfinnerlinewidth}%
 \fi%
 \advance\pgfutil@tempdima by.3\pgfutil@tempdimb%
 \pgfpathmoveto{\pgfqpoint{8\pgfutil@tempdima}{0pt}}%
 \pgfpathlineto{\pgfqpoint{-3\pgfutil@tempdima}{3\pgfutil@tempdima}}%
 \pgfpathlineto{\pgfpointorigin}%
 \pgfpathlineto{\pgfqpoint{-3\pgfutil@tempdima}{-3\pgfutil@tempdima}}%
 \pgfusepathqfill%
}

\pgfarrowsdeclare{technical reversed}{technical reversed}
{%
 \pgfutil@tempdima=0.48pt%
 \pgfutil@tempdimb=\pgflinewidth%
 \ifdim\pgfinnerlinewidth>0pt%
   \pgfmathsetlength\pgfutil@tempdimb{.6\pgflinewidth-.4*\pgfinnerlinewidth}%
 \fi%
 \advance\pgfutil@tempdima by.3\pgfutil@tempdimb%
 \pgfarrowsleftextend{-8\pgfutil@tempdima}
 \pgfarrowsrightextend{-8\pgfutil@tempdima}
}
{%
 \pgfutil@tempdima=0.48pt%
 \pgfutil@tempdimb=\pgflinewidth%
 \ifdim\pgfinnerlinewidth>0pt%
   \pgfmathsetlength\pgfutil@tempdimb{.6\pgflinewidth-.4*\pgfinnerlinewidth}%
 \fi%
 \advance\pgfutil@tempdima by.3\pgfutil@tempdimb%
 \pgfpathmoveto{\pgfqpoint{-8\pgfutil@tempdima}{0pt}}%
 \pgfpathlineto{\pgfqpoint{3\pgfutil@tempdima}{3\pgfutil@tempdima}}%
 \pgfpathlineto{\pgfpointorigin}%
 \pgfpathlineto{\pgfqpoint{3\pgfutil@tempdima}{-3\pgfutil@tempdima}}%
 \pgfusepathqfill%
}


% Changelog:
% 2013-10-21 : ajout du style |distance arrow| et de la décoration |line| correspondante.
% 2013-11-19 : suppression de |distance arrow| et ajout à la place de |dim arrow| et assimilés
% 2013-11-22 : choix entre distances relatives et absolues (http://www.texample.net/tikz/examples/supersonic-nozzle/)
% 2013-11-24 : styles de flèches |->-|, |-<-|, |->>-|, |-<<-| (et flèches pgf |ray arrow|, etc. correspondantes)
% 2013-11-24 : flèches pgf |lens arrow| et |lens arrow reversed|
% 2013-11-24 : |generic optics element| -> |thin optics element| et |thick optics element| ; conséquences. |beam splitter|
% 2014-01-01 : ajout de |double amici prism|,  |optics| -> |use optics| et |one arrow| -> |put arrow| ; |mark a *| supprimés
% 2014-03-19 : anchorborder pour |generic optics io| (les labels devraient donc être placés correctement)
%              |io body aspect ratio| accepte désormais aussi des longueurs absolues, ajout d'un alias |io body width| pour |io body aspect ratio|
% 2014-06-26 : modification du code des flèches |->-|, |->>-|, etc. et ajout de |->>>-|, |->>>>-|,|->n-=<nombre>| (idem dans l'autre sens)
% 2014-07-08 : ajout de |arrow style| à |put arrow|
% 2014-09-20 : ajout de |spherical mirror| et quelques modifications à |mirror| (ajustement de la décoration et de ses réglages par défaut)
% 2014-09-22 : ajustements de |spherical mirror| (concave et convexe), et ajout des styles correspondants |convex mirror| et |concave mirror|
% 2014-09-24 : ajustements de |spherical mirror| (ltr/rtl) ; correction des ancres de generic optics io (aperture north, aperture center, aperture south étaient incorrectes)
% 2014-09-25 : corrections à |spherical mirror| (ltr/rtl vs concave/convex) ;
% 2014-10-02 : ajout d'une fonction |from_radius| pour définir l'angle d'ouverture de |spherical mirror|, encore des corrections à |spherical mirror| (ltr/rtl vs concave/convex) ;
%               macro pour les messages d'erreur
% 2014-10-03 : vérifications de cohérence des grandeurs pour |slit| et |double slit| ; messages d'erreur au besoin
% 2014-12-07 : modifications substantielles à |put arrow| et |optics/->n-|, etc. pour pouvoir avoir plusieurs flèches sur le même chemin ; la compatibilité arrière est brisée.
% 2014-12-11 : nettoyage
% 2015-03-10 : ajout d'un alias |object width| pour |object aspect ratio|, qui accepte désormais aussi des longueurs absolues
% 2015-06-13 : mise en cohérence des noms des points focaux pour le miroir et la lentille (désormais, "focus" et "focal point")
% 2016-11-21 : appel aux biblothèques tikz |decorations| et |decorations.pathreplacing| qui sont nécessaires
\makeatother