diff options
author | Karl Berry <karl@freefriends.org> | 2016-11-27 23:20:59 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2016-11-27 23:20:59 +0000 |
commit | bfed047a77040d20a5deaecf0eac0cbd2ba93319 (patch) | |
tree | 4f4860ac46d0043e2a228898a3dbe59725227226 /Master/texmf-dist | |
parent | 3d5aca1d4d25ac48082bc49a4e22c078b5df0df8 (diff) |
tikz-optics (27nov16)
git-svn-id: svn://tug.org/texlive/trunk@42592 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist')
-rw-r--r-- | Master/texmf-dist/doc/latex/tikz-optics/README | 4 | ||||
-rw-r--r-- | Master/texmf-dist/doc/latex/tikz-optics/tikz-optics.pdf | bin | 0 -> 374236 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/latex/tikz-optics/tikz-optics.tex | 2316 | ||||
-rw-r--r-- | Master/texmf-dist/tex/latex/tikz-optics/tikzlibraryoptics.code.tex | 2492 |
4 files changed, 4812 insertions, 0 deletions
diff --git a/Master/texmf-dist/doc/latex/tikz-optics/README b/Master/texmf-dist/doc/latex/tikz-optics/README new file mode 100644 index 00000000000..8eef41cee9f --- /dev/null +++ b/Master/texmf-dist/doc/latex/tikz-optics/README @@ -0,0 +1,4 @@ +The tikz library optics is designed to easily draw optical setups with tikz. It provides shapes for lens, mirror, etc. The geometrically (in)correct computation of light rays through the setup is left to the user. When installed, the library can then be loaded through the command `\usetikzlibrary{optics}` in any tex file. To install it, the file `tikzlibraryoptics.code.tex` should be placed wherever TeX can find it, for example in your `TEXMFHOME` folder (see the documentation for details). Alternatively, you can directly `\input` it in your tex file. + +The library is subject to either the LaTeX Project Public License (LPPL 1.3) or the GNU General Public License (GNU GPL 2). +The documentation is subject toeither the LaTeX Project Public License (LPPL 1.3) or the GNU Free Documentation License (GNU FDL 1.3).
\ No newline at end of file diff --git a/Master/texmf-dist/doc/latex/tikz-optics/tikz-optics.pdf b/Master/texmf-dist/doc/latex/tikz-optics/tikz-optics.pdf Binary files differnew file mode 100644 index 00000000000..560ea974768 --- /dev/null +++ b/Master/texmf-dist/doc/latex/tikz-optics/tikz-optics.pdf diff --git a/Master/texmf-dist/doc/latex/tikz-optics/tikz-optics.tex b/Master/texmf-dist/doc/latex/tikz-optics/tikz-optics.tex new file mode 100644 index 00000000000..89fa8e0f96b --- /dev/null +++ b/Master/texmf-dist/doc/latex/tikz-optics/tikz-optics.tex @@ -0,0 +1,2316 @@ +\iffalse +The tikzoptics library documentation + +Copyright (C) 2013-2016 by + Michel Fruchart <michel.fruchart@ens-lyon.org> + +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 Free Documentation License (GNU FDL), version 1.3, which can be found +at the address: +https://www.gnu.org/licenses/fdl-1.3.en.html +or any later version published by the Free Software Foundation. +\fi +% allow compression of cross references. +\pdfminorversion=5 +\pdfobjcompresslevel=2 +\documentclass[a4paper]{ltxdoc} +\usepackage{etex} + +\usepackage[utf8]{inputenc} +\usepackage[T1]{fontenc} +\usepackage[french]{babel} + +\usepackage[a4paper,left=2.25cm,right=2.25cm,top=2.5cm,bottom=2.5cm,nohead]{geometry} +\usepackage{amsmath} + +%\usepackage{makeidx} +\usepackage[version=3]{mhchem} + +\usepackage{csquotes} + +\usepackage{xkeyval,calc,listings} +\usepackage[svgnames,x11names]{xcolor} +\usepackage{xxcolor} % tikz + +\usepackage{tikz} +\usetikzlibrary{shapes,shapes.misc,shapes.geometric} +\usetikzlibrary{arrows} +\usetikzlibrary{calc} +\usetikzlibrary{positioning} +\usetikzlibrary{decorations,decorations.markings,decorations.pathreplacing,decorations.pathmorphing} +\usetikzlibrary{patterns} +\usetikzlibrary{intersections} +\usetikzlibrary{matrix} +\usetikzlibrary{fit} +\usetikzlibrary{ocgx} + + +\usepackage{fancyvrb} + + +\usepackage[framemethod=tikz,usetwoside=false]{mdframed} + +\usepackage{fourier-orns} +\usepackage{lmodern} +\usepackage[charter]{mathdesign} +\usepackage{charter} +\def\rmdefault{bch} % not scaled +\def\sfdefault{SourceSansPro-TLF} + +\usepackage{textcomp} +\usepackage[detect-all=true]{siunitx} +\sisetup{ + math-micro=\muup, + math-ohm =\Omegaup, + text-micro={\fontfamily{mdbch}\textmu}, + text-ohm ={\fontfamily{mdbch}\textohm} +} + +\usepackage{attachfile2} +\attachfilesetup{color=blue} + + +\usepackage[protrusion=true,expansion,kerning=true,final,verbose=false,babel=false]{microtype} +\DisableLigatures{encoding=T1,family=tt*} + + +% corrige l'interaction foireuse entre tikz et babel[french] +\AtBeginEnvironment{tikzpicture}{\shorthandoff{:;!}} +\AtBeginEnvironment{pgfpicture}{\shorthandoff{:;!}} + + +% This is not the standard way to load a tikzlibrary +% but I want to make sure that the documentation loads +% the corresponding library (and not e.g. the production version). +\input{../tikzlibraryoptics.code.tex} + + +\usepackage{hyperref} +\usepackage{bookmark} +\hypersetup{% + colorlinks=true, + linkcolor=blue, + filecolor=blue, + urlcolor=blue, + citecolor=blue, + pdfborder=0 0 0, +} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Macros du manuel pgf/tikz (version : texlive 2012) +% cf. http://tex.stackexchange.com/questions/72999/is-there-a-listings-configuration-for-tikz-as-used-in-pgf-tikz-manual +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\def\pgfautoxrefs{1} +\def\pgfmanual@warning#1{\immediate\write16{! Package pgfmanual Warning: #1}}% + +\input{macros/pgfmanual-en-macros} +\input{macros/pgfmanual.prettyprinter.code.tex} +\input{macros/pgfmanual.pdflinks.code.tex} + + +\pgfkeys{ + % set this to 'false' to disable auto reference generation. + % However, a little bit runtime overhead will still remain + % (and the \pgfmanualpdflabel commands will still be used) + /pdflinks/codeexample links=true, + % + /codeexample/prettyprint/cs arguments/tikzset/.initial=1, + /codeexample/prettyprint/cs/tikzset/.code 2 args={\pgfmanualpdfref{#1}{#1}\{\pgfmanualprettyprintpgfkeys{#2}\pgfmanualclosebrace}, + /codeexample/prettyprint/cs arguments/usetikzlibrary/.initial=1, + /codeexample/prettyprint/cs/usetikzlibrary/.code 2 args={\pgfmanualpdfref{#1}{#1}\{\pgfmanualpdfref{#2}{#2}\pgfmanualclosebrace}, + /codeexample/prettyprint/cs arguments/usepgflibrary/.initial=1, + /codeexample/prettyprint/cs/usepgflibrary/.code 2 args={\pgfmanualpdfref{#1}{#1}\{\pgfmanualpdfref{#2}{#2}\pgfmanualclosebrace}, + % + % + % + % whenever an unqualified key is found, the following key prefix + % list is tried to find a match. + /pdflinks/search key prefixes in={/tikz/,/pgf/,/tikz/optics/,/tikz/dim/arrow/,}, + % + % the link prefix written to the pdf file: + /pdflinks/internal link prefix=tikzopt, + % + /pdflinks/warnings=false, + % for debugging: + /pdflinks/show labels=false, +}% + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Global styles from pgf/tikz manual (version : texlive 2012) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\tikzset{ + every plot/.style={prefix=plots/pgf-}, + shape example/.style={ + color=black!30, + draw, + fill=yellow!30, + line width=.5cm, + inner xsep=2.5cm, + inner ysep=0.5cm}, + line shape example/.style={ + color=black!30, + draw, +% fill=black!30, % utile à quoi ? + line width=.5cm, + inner xsep=2.5cm, + inner ysep=0.5cm} +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Specific environnements +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% + +% Environnement |example only| : aspect similaire à codeexample, mais avec seulement l'exemple (quand le code est trop long) +\newmdenv[ + backgroundcolor=graphicbackground, + linewidth=0pt, + innerleftmargin=0.09cm,innerrightmargin=0.09cm,innertopmargin=0.09cm, + leftmargin=0pt,rightmargin=0pt, + skipabove=5pt, skipbelow=-2pt, + ]{example only} + +% Environnement |warning| +\colorlet{warningbackground}{red!30} +\makeatletter +\newenvironment{warning}{% +\mdfsetup{% + backgroundcolor=warningbackground, + skipabove=5pt, + topline=false,bottomline=false,rightline=false, + innerbottommargin=4pt,innertopmargin=0.18cm, + leftmargin=0cm, innerleftmargin=0.3cm + rightmargin=0cm,innerrightmargin=0.3cm, + linewidth=1pt,linecolor=none, topline=false, bottomline=false, + }% +\begin{mdframed}% +\setlength{\parindent}{0pt}% +\danger\,% +}% +{% +\end{mdframed}% +}% + +% Environnement |update| +\colorlet{updatebackground}{blue!30} +\newenvironment{update}{% +\mdfsetup{% + backgroundcolor=updatebackground, + skipabove=5pt, + topline=false,bottomline=false,rightline=false, + innerbottommargin=4pt,innertopmargin=0.18cm, + leftmargin=0cm, innerleftmargin=0.3cm + rightmargin=0cm,innerrightmargin=0.3cm, + linewidth=1pt,linecolor=none, topline=false, bottomline=false, + }% +\begin{mdframed}% +\setlength{\parindent}{0pt}% +\danger\,% +}% +{% +\end{mdframed}% +}% +\makeatother + +\begin{document} + +\VerbatimFootnotes + +\title{optics --- une bibliothèque tikz pour les schémas d'optique} +\author{Michel Fruchart \\ +\href{mailto:michel (dot) fruchart [at] ens-lyon (dot) org}{\texttt{michel (dot) fruchart [at] ens-lyon (dot) org}}} + +\date{\today{} -- version 0.2.2 \\[0.15cm] +\large\href{https://github.com/fruchart/tikz-optics}{\texttt{https://github.com/fruchart/tikz-optics}}} + +\maketitle + +\section{Introduction} + +Le but de cette bibliothèque est de permettre de facilement faire des schémas optiques avec tikz, c'est-à-dire de dessiner lentilles, miroirs, etc. Le tracé géométriquement correct (ou non) des rayons est laissé à l'utilisateur. + + +\subsection{Legal matters} + +Cette bibliothèque peut être distribuée et modifiée sous les conditions de la licence LaTeX Project Public License (LPPL), version 1.3c\footnote{\url{http://latex-project.org/lppl/lppl-1-3c.txt}}. Elle peut aussi être distribuée et modifiée sous les conditions de la licence GNU General Public License (GNU GPL), soit la version 2\footnote{\url{http://www.gnu.org/licenses/gpl-2.0.en.html}}, soit toute version ultérieure publiée par la Free Software Foundation. Sa documentation, que vous êtes en train de lire, peut être distribuée sous les conditions de la licence LaTeX Project Public License (LPPL), version 1.3c\footnote{\url{http://latex-project.org/lppl/lppl-1-3c.txt}}. Elle peut aussi être distribuée et modifiée sous les conditions de la licence GNU Free Documentation License (GNU FDL), soit la version 1.3\footnote{\url{https://www.gnu.org/licenses/fdl-1.3.en.html}}, soit toute version ultérieure publiée par la Free Software Foundation. + +\subsection{Installation de la bibliothèque} + +Cette bibliothèque est une \enquote{bibliothèque tikz}. Il y a deux façons de l'utiliser : +\begin{itemize} + \item en ajoutant le fichier |tikzlibraryoptics.code.tex| dans un dossier où \TeX{} peut le trouver, par exemple dans votre dossier |TEXMFHOME|\footnote{Pour savoir où il se trouve, on peut utiliser la commande \verb|kpsewhich -var-value TEXMFHOME|. }, puis en utilisant la commande |\usetikzlibrary{optics}| ; + \item en incluant directement le fichier |tikzlibraryoptics.code.tex| contenant la bibliothèque grâce à la commande |\input|. +\end{itemize} + +Si la bibliothèque est placée dans un dossier |TEXMF|, disons |/home/agamemnon/texmf/|, il faut respecter la structure TDS de ces répertoires\footnote{Voir par exemple \url{https://www.ctan.org/TDS-guidelines}}. En pratique, le fichier |tikzlibraryoptics.code.tex| doit être placé dans le dossier |home/agamemnon/texmf/tex/latex/|, ou dans un sous-dossier comme |home/agamemnon/texmf/tex/latex/tikzoptics|. Le plus simple est d'utiliser le contenu de l'archive |tikzoptics.tds.zip|, qui est structuré comme il se doit et peut directement être ajouté dans le dossier |TEXMF| (comme |/home/agamemnon/texmf/|). + +\subsection{Utilisation de la bibliothèque} + +\begin{key}{/tikz/use optics} +Après avoir installé la bibliothèque, il suffit de la charger grace à la commande |\usetikzlibrary{optics}|, puis d'utiliser l'option |use optics| sur une |tikzpicture| pour pouvoir utiliser les commandes\footnote{L'option \texttt{use optics} charge les éléments pertinents de \texttt{/tikz/optics/} dans \texttt{/tikz/}, ce qui permet de les utiliser directement. Séparer a priori les commandes dans des espaces de noms différents permet de réduire le risque de collision de noms.} + +\begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics] + \node[lens] at (0,0) {}; + \node[mirror] at (1cm,0) {}; +\end{tikzpicture} +\end{codeexample} + +Si l'option |use optics| n'est pas utilisée, le code plantera lamentablement (dans les cas favorables) ou aura un comportement inattendu (dans les cas moins favorables). +\end{key} + +\subsection{Élements sur les \texttt{node} de tikz et leur placement} + +\emph{Pour plus de détails, lire le manuel de tikz.} + +En deux mots, une |node| est en gros un objet, qui peut avoir une certaine forme (|shape|). À différents endroits de cette |node| sont définies des ancres (|anchor|). Au contraire d'une |node| qui est en quelque sorte étendue spatialement, ces ancres représentent des points précis sur le canevas de dessin. La |node| a un nom (facultatif) qui permet d'y faire référence dans la suite du dessin, par exemple pour accéder aux coordonnées d'une ancre. + +La syntaxe minimale pour créer une |node| est |\node {};|, mais cela n'est pas très utile. Il faut spécifier où se trouve la |node| en écrivant |\node at |\meta{position}| {};| (où \meta{position} est une coordonnée, comme |(0,1cm)|). Cela n'est toujours pas très utile car rien n'est dessiné. C'est le rôle des |shape| que de déterminer ce qui est dessiné. + +Dessinons ainsi un rectangle rouge en |(0,0)| (ici, c'est le centre du canevas), et de côté |1cm|\footnote{Dans cette documentation, les longueurs ne sont généralement pas écrites avec les conventions du système international, mais avec les conventions habituelles pour du code tikz.} + +% +\begin{codeexample}[width=5cm] +\begin{tikzpicture} + \draw[style=help lines,gray!50] (-2cm,-2cm) grid[step=0.5cm] (2cm,2cm); + \node[rectangle,minimum height=1cm,minimum width=1cm,draw=red] at (0,0) {}; +\end{tikzpicture} +\end{codeexample} +% +J'ai ajouté une grille de pas |0.5cm| pour mieux voir les coordonnées. Dans cet exemple, c'est le centre du rectangle qui est placé au point |(0,0)|. Pour être plus précis, il s'agit de son ancre |center|. C'est le comportement par défaut, mais tout l'intérêt est qu'on peut placer les autres ancres définies par la |shape| au point spécifié. Ajoutons donc à ce dessin un rectangle bleu dont le bas est situé en |(0,0)|. Comme nous allons avoir plusieurs |node| qui partagent les caractéristiques |rectangle,minimum height=1cm,minimum width=1cm|, je les ai placées dans un \emph{style} que j'ai appelé |joli rectangle| (il ne faudrait pas l'appeler |rectangle| car cela existe déjà). Comme le bas est représenté par l'ancre |south|, il faut ajouter l'option |anchor=south| à la |node|: +% +\begin{codeexample}[width=5cm] +\begin{tikzpicture} + \draw[style=help lines,gray!50] (-2cm,-2cm) grid[step=0.5cm] (2cm,2cm); + \tikzstyle{joli rectangle}=[rectangle,minimum height=1cm,minimum width=1cm] + \node[joli rectangle,draw=red] at (0,0) {}; + \node[joli rectangle,draw=blue,anchor=south] at (0,0) {}; +\end{tikzpicture} +\end{codeexample} +% +J'aimerais maintenant tracer un trait noir entre coin en haut à gauche du carré bleu et le coin en bas à droite du carré rouge. Pour cela, il faut pouvoir accéder aux ancres |north west| (en haut à gauche) et |south east| (en bas à droite) des deux |nodes|. Nous allons donc donner un nom à chacune de ces |nodes|, par exemple |Esther| et |Athalie|: +% +\begin{codeexample}[width=5cm] +\begin{tikzpicture} + \draw[style=help lines,gray!50] (-2cm,-2cm) grid[step=0.5cm] (2cm,2cm); + \tikzstyle{joli rectangle}=[rectangle,minimum height=1cm,minimum width=1cm] + \node[joli rectangle,draw=red] + (Esther) at (0,0) {}; + \node[joli rectangle,draw=blue,anchor=south] + (Athalie) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} +% +Pour le moment, cela ne change absolument rien au dessin, mais on peut désormais accéder aux ancres nécessaires par |(Athalie.north west)| et |(Esther.south east)| et dessiner le trait voulu. +% +\begin{codeexample}[width=5cm] +\begin{tikzpicture} + \draw[style=help lines,gray!50] (-2cm,-2cm) grid[step=0.5cm] (2cm,2cm); + \tikzstyle{joli rectangle}=[rectangle,minimum height=1cm,minimum width=1cm] + \node[joli rectangle,draw=red] + (Athalie) at (0,0) {}; + \node[joli rectangle,draw=blue,anchor=south] + (Esther) at (0,0) {}; + \draw (Esther.north west) --(Athalie.south east); +\end{tikzpicture} +\end{codeexample} +% + +Pour placer les points, il est possible d'utiliser une options du genre |left=of (autre node)|, ou encore |above=5mm of (Esther)|. C'est ce qu'on fait dans l'exemple \ref{sec:exemple_dispersion} p.~\pageref{sec:exemple_dispersion}. + +\subsection{Programmer des images : faire des calculs avec tikz} + +\emph{Pour plus de détails, lire le manuel de tikz.} + +Un des principaux avantages\footnote{Un des principaux inconvénients est que cela demande un peu plus de travail, surtout au début.} d'utiliser du code pour générer des schémas est que cela permet de concevoir les schémas comme un programme informatique. Ainsi, on gagne plusieurs choses : +\begin{itemize} + \item en utilisant des variables pour représenter les longueurs et angles du schéma, on peut facilement l'ajuster immédiatement ainsi que le modifier plus tard au besoin ; + \item en utilisant des styles pour l'aspect visuel (couleurs, hachures, etc.), il est plus facile de maintenir une cohérence visuelle entre différents schémas. La modification du style se répercutant sur tous les schémas (tant qu'il n'est pas défini à nouveau), on peut facilement décider de changer le bleu représentant l'eau, ou bien, si on veut distribuer un document en noir et blanc, de la représenter par un motif (|pattern|) approprié ; + \item on peut utiliser les diverses ressources de la programmation que sont les boucles, les conditions, et les calculs pour effectuer des tâches répétitives ou complexes ; + \item il est possible de réutiliser\footnote{J'aimerais ajouter \enquote{facilement} ici, mais ça n'est hélas pas le cas. Le plus simple est de définir une macro contenant le bout de schéma, et cette méthode marche très bien, mais elle a certaines limites.} des bouts de schéma +\end{itemize} + +Le but de cette section est de rappeler rapidement comment faire des calculs avec |pgfmath|. Une référence complète se trouve dans le manuel de |tikz|. Les commandes principales que nous allons utiliser sont la boucle |\foreach|, et les commandes de calcul |\pgfmathcalc| et |\pgfmathresult|, |\pgfmathdef|, et |\pgfmathsetlength|. + +\subsubsection{Calculs} + +La commande |\pgfmathcalc{<expression>}| parse calcule l'|<expression>| qui lui est donnée (selon des règles qui sont spécifiées dans le manuel de tikz) et enregistre le résultat dans la macro |\pgfmathresult|. Si on a besoin de garder ce résultat, il faut le copier dans une autre macro (disons par exemple |\reflexionAngle|) en utilisant |\let\reflexionAngle\pgfmathresult|. La syntaxe des expressions mathématiques est assez naturelle. Pour les détails, je vous renvoie au manuel tikz ; voici néanmoins quelques exemples\footnote{Pour essayer une expression mathématique, le plus simple est d'écrire \verb-\pgfmathparse{2+2}\pgfmathresult- +dans le corps d'un document tex : cela affichera \texttt{\pgfmathparse{2+2}\pgfmathresult} dans le pdf. Ici, j'ai omis les \verb+\pgfmathresult+ pour plus de clareté, mais la commande \verb+\pgfmathparse+ n'affiche rien toute seule ! +} : + +\begin{codeexample}[post={\pgfmathresult}] +\pgfmathparse{5*6+3} +\end{codeexample} + +\begin{codeexample}[post={\pgfmathresult}] +\pgfmathparse{(4^2 + 4)/2} +\end{codeexample} + +\begin{codeexample}[post={\pgfmathresult}] +\pgfmathparse{factorial(4)} +\end{codeexample} + +\begin{codeexample}[post={\pgfmathresult}] +% les angles sont en degres ! +\pgfmathparse{cos(45)} +\end{codeexample} + +\begin{codeexample}[post={\pgfmathresult}] +% r convertit les degres en radians +\pgfmathparse{cos(pi/4 r)} +\end{codeexample} + +\begin{codeexample}[post={\pgfmathresult}] +\pgfmathparse{abs(-sqrt(2)/2)} +\end{codeexample} + +Des fonctions comme |acos|, |sinh|, |ln|, etc. sont disponibles\footnote{Des outils rudimentaires pour travailler avec des vecteurs et un générateur de nombres pseudo-aléatoires existent aussi.}. Il est possible de définir des fonctions via la commande |\pgfmathdeclarefunction| ou la clé |/pgf/declare function|, en fournissant éventuellement une implémentation bas niveau : + + +\begin{example only} +\shorthandoff{;:} +\pgfkeys{/pgf/declare function={f(\x)=1.7280+0.01345/(\x^2);}} +\pgfmathparse{f(1)} +\pgfmathresult +\end{example only} + +\begin{codeexample}[code only] +\pgfkeys{/pgf/declare function={f(\x)=1.7280+0.01345/(\x^2);}} +\pgfmathparse{f(1)} +\pgfmathresult +\end{codeexample} + +À partir de tikz 3.0, la bibliothèque tikz |math| permet de simplifier l'écriture des calculs. + +Il existe aussi des fonctions logiques, et les opérateurs booléens habituels (|not(x)=!x|, \verb+or(x,y)=x||y+, |and(x,y)=x&&y|). Par convention, le booléen |true| est représenté par |1| et |false| par |0|. On a alors divers outils avec plusieurs syntaxes : + + +\begin{codeexample}[post={\pgfmathresult}] +\pgfmathparse{2 <= 4} +\end{codeexample} + +\begin{codeexample}[post={\pgfmathresult}] +\pgfmathparse{greater(1,2)} +\end{codeexample} + +\begin{codeexample}[post={\pgfmathresult}] +\pgfmathparse{not(1.5 == 0 && 1.5 <= 2)} +\end{codeexample} + +La commande |\pgfmathsetmacro{<macro>}{<expression>}| parse l'|<expression>| mathématique de la même manière que |\pgfmathcalc|, et enregistre le résultat du calcul dans |<macro>|. Par exemple, |\pgfmathsetmacro{\transitionProbability}{0.5+0.1}| enregistre |0.6| dans |\transitionProbability|. Par contre, si le résultat du calcul est une chaîne de caractères, il faut utiliser quelque chose comme |\pgfmathparse{<expression>}\let<macro>\pgfmathresult|. + +La commande |\pgfmathtruncatemacro| s'utilise comme |\pgfmathsetmacro|, mais elle renvoie un entier (le résultat tronqué), qui peut être utilisé dans une boucle, ou dans une condition. Par exemple, |\pgfmathtruncatemacro\nmax{5/4}| stocke |1| dans |\nmax|. + +\paragraph{Une remarque sur les définitions et les groupes.} |\pgfmathsetmacro| et les commandes assimilées utilisent la primitive TeX |\def| pour définir les macros, ce qui fait qu'on peut redéfinir une macro sans se préoccuper de savoir si elle existait déjà ou non. De manière générale, je préfère utiliser |\def| plutôt que |\newcommand| pour définir et modifier des variables, car elles peuvent devoir changer lors du tracé du dessin. Cela implique de veiller à ne pas redéfinir des commandes existantes par erreur, mais cela évite aussi beaucoup de tracas. Dans la mesure où le contenu d'une |tikzpicture| est contenu à l'intérieur d'un groupe, les éventuelles redéfinitions intempestives n'ont de conséquences qu'à l'intérieur du dessin. Cela veut aussi dire que pour accèder à une variable définie dans une |tikzpicture|, il faut ajouter un |\global| quelque part. + +\subsubsection{Conditions} + +Quelques mots sur les fonctions logiques de tikz et leur utilisation. + +Une expression comme |greater(\x,pi)| est évaluée à |1| si |\x| est plus grand que $\pi$, et à |0| sinon. Toutes les fonctions logiques se comportent de cette manière. Cela permet de définir des fonctions par morceaux, etc. Pour exécuter du code latex sous condition, une méthode (parmi d'autres) consiste en ce qui suit : + + +\begin{example only} +\foreach \x in {1,2,3,4} +{ +\pgfmathparse{greater(\x,pi)} +\ifnum\pgfmathresult=1 +\x{} est plus grand que $\pi$ ; +\else +\x{} est plus petit que $\pi$ ; +\fi +} +\end{example only} +% +\begin{codeexample}[code only] +\foreach \x in {1,2,3,4} +{ + \pgfmathparse{greater(\x,pi)} + \ifnum\pgfmathresult=1 + \x{} est plus grand que $\pi$ ; + \else + \x{} est plus petit que $\pi$ ; + \fi +} +\end{codeexample} + + +% +Il peut être nécessaire de stocker le résultat de |\pgfmathresult| dans une macro ; la commande |\pgfmathsetmacro| stockerait |1.0| ou |0.0| (des flottants au lieu d'entiers), qui ne peuvent pas être traités par |\ifnum| : il faut donc faire appel à |\pgfmathtruncateresult|. Ainsi, le code suivant reproduit le même résultat : +% +\begin{example only} +\foreach \x in {1,2,3,4} +{ + \pgfmathtruncatemacro\plusGrandQuePi{greater(\x,pi)} + \ifnum\plusGrandQuePi=1 + \x{} est plus grand que $\pi$ ; + \else + \x{} est plus petit que $\pi$ ; + \fi + } +\end{example only} +% +\begin{codeexample}[code only] +\foreach \x in {1,2,3,4} +{ + \pgfmathtruncatemacro\plusGrandQuePi{greater(\x,pi)} + \ifnum\plusGrandQuePi=1 + \x{} est plus grand que $\pi$ ; + \else + \x{} est plus petit que $\pi$ ; + \fi +} +\end{codeexample} + +On peut aussi vouloir spécifier un aspect visuel selon une condition. Une méthode consiste à définir des styles, qu'on assigne selon la condition. Ici, nous tirons un certain nombre de points au hasard dans un carré. Nous voulons distinguer les points qui se trouvent dans un certain cercle des autres. Pour cela, on définit deux styles |inside| et |outside|. Pour le moment, nous allons colorer les points dedans en rouge et deux dehors en bleu : + +\begin{codeexample}[code only] +\tikzset{inside/.style={red},outside/.style={blue}} +\end{codeexample} + +Ensuite, il suffit d'utiliser la fonction |ifthenelse| pour définir une macro |\pointStyle| qui vaut |inside| ou |outside|, selon la position du point situé en |(\posx,\posy)|. Dans l'exemple qui suit, je me suis rendu compte que les couleurs ne se voient pas quand on imprime en noir et blanc, et j'ai donc dessiné des croix rouges ainsi que des plus bleus en modifiant les styles |inside| et |outside| : + +\begin{codeexample}[] +\begin{tikzpicture} + \tikzset{inside/.style={red,mark=x},outside/.style={blue,mark=+}} + \newdimen\radius + \pgfmathsetlength\radius{1cm} + \pgfmathsetmacro\k{2} + \pgfmathtruncatemacro\NumberOfPoints{15} + + \draw (0,0) circle(\radius); + \draw (-\k*\radius,-\k*\radius) rectangle (\k*\radius,\k*\radius); + + \newdimen\posx + \newdimen\posy + \foreach \nil in {1,2,...,\NumberOfPoints} + { + \pgfmathsetlength\posx{\k*\radius*rand} + \pgfmathsetlength\posy{\k*\radius*rand} + \pgfmathparse{ifthenelse(veclen(\posx,\posy)<\radius,"inside", "outside")} + \let\pointStyle\pgfmathresult + \draw[\pointStyle] plot (\posx,\posy); + } +\end{tikzpicture} +\end{codeexample} + +\subsubsection{Boucles \texttt{foreach}} + +La boucle |\foreach| s'utilise grossièrement de la manière suivante : +% +\begin{codeexample}[] +\foreach \x in {1,2,...,10} {\x,} +\end{codeexample} +% +\begin{codeexample}[] +\foreach \x in {0.42,0.5,12.56} {\x,} +\end{codeexample} +% +Il y a un certain nombre de subtilités dans la syntaxe qui permettent de faire des choses élaborées : je vous renvoie au manuel de tikz qui y consacre un chapitre entier ainsi qu'aux exemples. Remarquez que les boucles peuvent être imbriquées. + +Dans l'exemple (inutile) suivant, nous voulons placer une barre tous les |\shift| sur un trait de longueur |\length|. De plus, on veut qu'un trait sur deux soit rouge, et l'autre bleu. On calcule donc le nombre |\imax| de traits à dessiner, puis on utilise une boucle. Dans la boucle, on utilise la parité de la variable de boucle |\i| pour savoir si la barre doit être rouge ou bleue. + +\begin{codeexample}[] +\begin{tikzpicture} + \pgfmathsetmacro\length{4} + \pgfmathsetmacro\shift{0.5} + \pgfmathtruncatemacro\imax{\length/\shift} + + \draw (0,0) -- (\length,0); + \foreach \i in {0,1,2,...,\imax} + { + \pgfmathparse{ifthenelse(equal(mod(\i,2),0),"red","blue")} + \let\chunkStyle\pgfmathresult + \draw[\chunkStyle] (\i*\shift cm,-0.3cm) -- (\i*\shift cm,0.3cm); + } +\end{tikzpicture} +\end{codeexample} + +\subsubsection{Les longueurs} + +En tikz, on travaille toujours, de manière implicite ou explicite, avec des longueurs (et des angles). Par exemple, la coordonnée |(1,2)| signifie généralement |(1cm,2cm)| (en fait, |(1,2)| est vu comme une coordonnée dans un système dont les vecteurs unité ont, par défaut, une longueur d'un centimètre, mais qui peuvent être modifiés). +Le plus souvent, il est raisonnable de préciser explicitement les unités et donc de travailler avec des longueurs. + +En (la)tex, les longueurs doivent être déclarées avant d'être utilisées, et contrairement aux macros, il n'est pas d'usage de les déclarer et de les définir en même temps. La commande |\newdimen{<longueur>}| permet de déclarer une longueur\footnote{Pour la même raison que je préfère \texttt{\textbackslash{}def} à \texttt{\textbackslash{}newcommand} pour définir des variables dans les dessins, je préfère \texttt{\textbackslash{}newdimen} à \texttt{\textbackslash{}newlength}.}. Pour lui donner une valeur, le plus simple est d'utiliser la commande |\pgfmathsetlength{<longueur>}{<expression math>}|, qui parse l'|<expression math>| et l'enregistre dans |<longueur>|. Ainsi, + +\begin{codeexample}[] +\begin{tikzpicture} + \newdimen\hauteurFente + \pgfmathsetlength\hauteurFente{3cm} + \newdimen\largeurFente + \pgfmathsetlength\largeurFente{0.25cm} + \newdimen\ecartFentes + \pgfmathsetlength\ecartFentes{0.5cm} + + \coordinate (L) at (-\ecartFentes/2,0); + \coordinate (R) at (\ecartFentes/2,0); + \foreach \x in {L,R} + \draw[shift={(\x)}] (-\largeurFente/2,-\hauteurFente/2) + rectangle (\largeurFente/2,\hauteurFente/2); +\end{tikzpicture} +\end{codeexample} + +La commande |\pgfmathsetlength| suppose qu'une grandeur sans unité est donnée en points (|pt|). Ainsi, |\pgfmathsetlength\hauteurFente{3}| équivaut à |\pgfmathsetlength\hauteurFente{3pt}|. Néanmoins, il n'est pas une bonne idée de ne pas spécifier l'unité. + +Les fonctions de comparaison de |pgfmath| (comme |greater|, |less|, |equal|) peuvent être utilisées avec des longueurs : par exemple, |\pgfmathparse{2cm <= 4cm}| donne |1|, alors que |\pgfmathparse{2cm <= 4pt}| donne |0|. + +\subsubsection{Un prisme} + +Armés de ces outils, nous pouvons dessiner le parcours de rayons lumineux à travers un prisme en verre. Quelques calculs d'optique géométrique permettent de déterminer les coordonnées nécessaires au tracé, et on obtient ainsi la figure suivante : + +\begin{example only} +\begin{center} +\begin{tikzpicture} + \newdimen\hauteurVerre + \newdimen\largeurVerre + \newdimen\distanceSource + \newdimen\hauteurSource + \newdimen\distanceEcran + \pgfmathsetlength\hauteurVerre{2cm} + \pgfmathsetlength\largeurVerre{1cm} + \pgfmathsetlength\distanceSource{1cm} + \pgfmathsetlength\hauteurSource{1cm} + \pgfmathsetmacro\glassIndex{1.74} + \pgfmathsetlength\distanceEcran{1cm} + + \coordinate (A) at (0,\hauteurVerre); + \coordinate (B) at (0,0); + \coordinate (C) at (\largeurVerre,0); + + % couleur des rayons + \colorlet{current ray color}{red} + + % dessin du prisme + \draw (A) -- (B) -- (C) -- cycle; + + % source + \coordinate (S) at (-\distanceSource,\hauteurSource); + + % tracé des rayons + \foreach \x in {-0.1,0,0.1,0.2,...,1} + { + \pgfmathsetmacro\inAngle{atan((\hauteurSource-\x*\hauteurVerre)/\distanceSource)} + % si le rayon ne croise pas le prisme, pas de déflexion du rayon + \pgfmathtruncatemacro\noDeflexion{or(notgreater(\x,0),notless(\x,1))} + \ifnum\noDeflexion=1 + \draw[dashed,current ray color] (S) + -- (\distanceEcran,{tan(\inAngle)*(\distanceEcran+\largeurVerre+\distanceSource)}); + \else + \pgfmathsetmacro\midAngle{asin((1/\glassIndex)*sin(\inAngle))} + \pgfmathsetmacro\y{\x*(1+\largeurVerre/\hauteurVerre*tan(\midAngle))^(-1)} + \pgfmathsetmacro\appexAngle{atan(\largeurVerre/\hauteurVerre)} + \pgfmathsetmacro\snellSine{\glassIndex*sin(-\appexAngle+\midAngle)} + + % est-ce que le rayon coupe le bas du prisme ? + \pgfmathtruncatemacro\goesOut{greater(\y,1)} + \ifnum\goesOut=1 + % je ne dessine pas les rayons qui couperaient le bas du prisme + \else + % est-ce qu'il y a réflexion totale ? + \pgfmathtruncatemacro\totalReflexion{notgreater(abs(\snellSine),1)} + \ifnum\totalReflexion=1 + \newdimen\screenY + \pgfmathsetlength\screenY{ + (1-\y)*\hauteurVerre + tan(asin(\snellSine)+\appexAngle)* + (\largeurVerre+\distanceEcran - \largeurVerre*\y) + } + \draw[current ray color] (S) -- (\largeurVerre*0,{(1-\x)*\hauteurVerre}) + -- (\largeurVerre*\y,{(1-\y)*\hauteurVerre}) + -- (\largeurVerre+\distanceEcran,\screenY); + \else + \draw[dotted,current ray color] (S) -- (\largeurVerre*0,{(1-\x)*\hauteurVerre}) + -- (\largeurVerre*\y,{(1-\y)*\hauteurVerre}); + \fi + \fi + \fi + } +\end{tikzpicture} +\end{center} +\end{example only} + +Comme nous avons utilisé des paramètres ajustables, il est très facile d'adapter le code de manière à tracer les rayons pour plusieurs longueurs d'ondes (en utilisant la loi de Cauchy) : + +\begin{example only} +\begin{center} +\input{prisme_dispersion.pgf} +\end{center} +\end{example only} +% +Le code servant à générer cette figure étant un peu long, je ne l'ai pas inclus dans le corps du document, mais en pièce jointe : \textattachfile[]{prisme_dispersion.pgf}{prisme\_dispersion.pgf}. + + +\section{Exemples} + +\subsection{Image d'une fente sur un écran} + +Reproduisons un schéma optique simple (qu'il faudrait que je scanne). + +La première étape est de placer tous les éléments. On commence de manière très logique par la lampe, qu'on place en |(0,0)|. Ensuite, tous les éléments sont placé à droite les uns des autres. Par exemple, l'anticalorique est placé à |0.5cm| de la sortie de la lampe (ancre |aperture east| de la |node| |QI|) par l'option |right=0.5cm of (QI.aperture east)|. L'écran et la lentille sont situés relativement à la fente parce que j'ai jugé ça plus pratique pour les modifier indépendamment, mais ce genre de choix dépend de l'humeur et de la situation. J'ai nommé les différents éléments de manière peu cohérente pour souligner que les noms des |nodes| sont très libres : on peut y mettre des espaces, des accents\footnote{Vous remarquerez que je n'utilise pas d'accents dans les exemples de code. C'est parce que le code qui traite ces exemples n'est pas capable de les traiter. Par contre, il n'y a aucun problème à les utiliser dans tikz (une |node| peut s'appeler \texttt{(écran)} sans aucun problème, par exemple).}, etc. Il faut juste éviter d'y mettre de point, virgule, double-point, etc. qui ont un sens particulier (le point sépare le nom d'une |node| de celui de l'ancre visée, par exemple). + +\begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics] + \node[halogen lamp] (quartz iode) at (0,0) {Q.I.}; + \node[heat filter,right=0.5cm of quartz iode.aperture east] (AC) {}; + \node[slit,right=0.75cm of AC] (fente) {}; + \node[lens,right=2cm of fente] (L) {}; + \node[screen,right=5cm of fente] (screen) {}; +\end{tikzpicture} +\end{codeexample} + +% +Une deuxième étape consiste à tracer les rayons lumineux. Ici, on a de la chance car toutes les positions nécessaires sont des ancres des différentes |node|. Par exemple, |(L.lens south)| est située juste avant le bas de |L| de manière à ce que le dessin soit joli (mais on peut quand même accéder à ce bas via |(L.south)| - l'idée est qu'il s'agit alors du bas du support annulaire de la lentille). On relie donc les ancres par des |--| dans une commande |\draw|. +% +\begin{codeexample}[] +\begin{tikzpicture}[use optics] + \node[halogen lamp] (quartz iode) at (0,0) {Q.I.}; + \node[heat filter,right=0.5cm of quartz iode.aperture east] (AC) {} ; + \node[slit,right=0.75cm of AC] (fente) {}; + \node[lens,right=2cm of fente] (L) {}; + \node[screen,right=5cm of fente] (screen) {}; + + \draw[red] (fente.slit north) -- (L.lens north) -- (screen.center) + (fente.slit south) -- (L.lens south) -- (screen.center); +\end{tikzpicture} +\end{codeexample} +% +Il faut ensuite ajouter les étiquettes des différents éléments. Cela est fait via l'option \verb|label|, de la forme \verb|label=|\meta{texte}, ou plus généralement \verb|label=[|\meta{opts}\verb|]|\meta{pos}\verb|:|\meta{texte}. En particulier, pour pouvoir sauter une ligne, il faut par exemple utiliser l'option |align=center|. + +\begin{codeexample}[] +\begin{tikzpicture}[use optics] + \node[halogen lamp] (quartz iode) at (0,0) {Q.I.}; + \node[heat filter,right=0.5cm of quartz iode.aperture east,label={below:AC}] (AC) {} ; + \node[slit,right=0.75cm of AC,label={below:fente}] (fente) {}; + \node[lens,right=2cm of fente,label={[align=center]below:achromat \\ $(L)$}] (L) {}; + \node[screen,right=5cm of fente,label={below:\'ecran}] (screen) {}; + + \draw[red] (fente.slit north) -- (L.lens north) -- (screen.center) + (fente.slit south) -- (L.lens south) -- (screen.center); +\end{tikzpicture} +\end{codeexample} + +Enfin, on ajoute les flèches. Pour ce faire, je définis une coordonnée (c'est une |node| qui n'a qu'une seule ancre et qui ne dessine rien) et j'utilise la position verticale de cette coordonnée (point 1) ainsi que les positions horizontales des (centres des) divers objets (point 2), grace à la syntaxe \texttt{(point 1 -\textbar{} point 2)}. + + +\begin{codeexample}[] +\begin{tikzpicture}[use optics] + \node[halogen lamp] (quartz iode) at (0,0) {Q.I.}; + \node[heat filter,right=0.5cm of quartz iode.aperture east,label={below:AC}] (AC) {} ; + \node[slit,right=0.75cm of AC,label={below:fente}] (fente) {}; + \node[lens,right=2cm of fente,label={[align=center]below:achromat \\ $(L)$}] (L) {}; + \node[screen,right=5cm of fente,label={below:\'ecran}] (screen) {}; + + \draw[red] (fente.slit north) -- (L.lens north) -- (screen.center) + (fente.slit south) -- (L.lens south) -- (screen.center); + + \coordinate (arrow origin) at (0,1.5cm); + + \draw[>=technical,<->] (arrow origin -| fente) -- (arrow origin -| L) node[midway,above] {$d$}; + \draw[>=technical,<->] (arrow origin -| L) -- (arrow origin -| screen) node[midway,above] {$D$}; +\end{tikzpicture} +\end{codeexample} + +Quand le style sera au point, il sera possible d'utiliser |dim arrow| pour indiquer les dimensions au lieu de cette méthode légèrement plus laborieuse. + + + +\subsection{Des interférences} + +Ici, je n'ai pas utilisé |right=of| et ses amis pour placer les |nodes|, mais des calculs de coordonnées. + + +\begin{codeexample}[] +\begin{tikzpicture}[use optics] + \node[laser] (L) at (0,0) {\ce{HeNe}}; + \node[semi-transparent mirror,rotate=45] (ST) at ($(L)+(3cm,0)$) {}; + \node[above] at (ST.north) {s\'eparatrice}; + \node[mirror,rotate=-135] (M1) at ($(ST)+(0,-3cm)$) {}; + \node[mirror,rotate=-45] (M2) at ($(M1)+(5cm,0)$) {}; + \node[sensor line,rotate=45,anchor=pixel 3 west,label={[label distance=0.5cm]above right:Caliens}] + (Caliens) at ($(ST)+(5cm,0)$) {}; + \draw[red] (L.aperture east) -- (ST.center) -- (M1.center) -- (M2.center) -- (Caliens.pixel 3 west); + \draw[red] (L.aperture east) -- (ST.center) -- (Caliens.pixel 3 west); +\end{tikzpicture} +\end{codeexample} + +On a utilisé |anchor=pixel 3 west| pour que le centre du capteur soit placé au point |($(ST)+(5cm,0)$)|. + +Plusieurs possibilités pour ajouter un label sont illustrées : créer une |node| au bon endroit avec le texte voulu (ici \emph{séparatrice}), et utiliser la clé \verb|label| (cf. manuel pgf/tikz). + +\subsection{De la dispersion} +\label{sec:exemple_dispersion} + +La syntaxe |($(A)!0.6!(B)$)| (\emph{partway modifiers}, lisez le manuel tikz pour les détails) permet de déterminer un point situé à la distance |0.6| entre les points |(A)| et |(B)| (|0| correspond à |(A)| et |1| à |(B)|). + +\begin{codeexample}[] +\begin{tikzpicture}[use optics] + % [align=center] permet les labels multiligne + % [font=\footnotesize] fait un texte plus petit + \tikzset{every label/.style={align=center,font=\footnotesize}} + + \node[halogen lamp] (S) at (0,0) {QI}; + \node[heat filter, right=of S] (AC) {}; + \node[diaphragm, right=0.1cm of AC] (diaphragme) {}; + \node[slit, right=0.5cm of diaphragme,label={south:{trou \\ \SI{5}{\milli\meter}}}] (T) {}; + \node[lens,right=2cm of T] (L) {}; + \node[screen,right=2cm of L] (ecran) {}; + + \draw[red] + (T.slit north) -- (L.lens north) -- (ecran.center) + (T.slit south) -- (L.lens south) -- (ecran.center); + + \draw[blue] + (T.slit north) -- (L.lens north) -- ($(ecran.north)!0.6!(ecran.south)$) + (T.slit south) -- (L.lens south) -- ($(ecran.north)!0.4!(ecran.south)$); +\end{tikzpicture} +\end{codeexample} + + +\subsection{Un téléscope de Cassegrain} + +Pour dessiner un miroir troué, on utilise la commande |\clip| de tikz (qu'on place dans un |scope| dont le seul contenu est affecté par le |\clip|). On trace alors les rayons à la main, sans se soucier de l'exactitude du schéma. + +\begin{codeexample}[] +\begin{tikzpicture}[use optics] +% mirror with hole +\begin{scope} + \clip (-0.75cm,-2.2cm) rectangle (1cm,0-0.33cm) (-0.75cm,2.2cm) rectangle (1cm,0+0.33cm); + \node[spherical mirror, object height=4cm, spherical mirror angle=50] (M1) at (0cm,0) {}; +\end{scope} + +% small mirror +\node[convex mirror, spherical mirror orientation=rtl, + object height=1cm, spherical mirror angle=90] (M2) at (-4cm,0) {}; + +% convergence point +\coordinate (F) at (1cm,0); + +% red ray +\begin{scope}[red] + \draw[-<-] (M1.22) coordinate (P1) -- +(-5cm,0); + \draw[->-] (P1) -- (M2.30) coordinate (Q1); + \draw[->-] (Q1) -- ($(Q1)!1.25!(F)$) coordinate (R1); +\end{scope} + +% blue ray +\begin{scope}[blue] + \draw[-<<-] (M1.-22) coordinate (P2) -- +(-5cm,0); + \draw[->>-] (P2) -- (M2.-30) coordinate (Q2); + \draw[->>-] (Q2) -- ($(Q2)!1.25!(F)$) coordinate (R2); +\end{scope} + +% violet ray +\begin{scope}[violet] + \draw[-<-] (M1.22) coordinate (P3) -- +(175:5cm); + \draw (P3) -- (M2.22) coordinate (Q3); + \draw (Q3) -- ($(Q3)!1.25!($(F)+(0,-0.15cm)$)$) coordinate (R3); +\end{scope} + +% sensor +\node[generic sensor, anchor=aperture west] at ($(R1)!0.5!(R2)$) {}; +\end{tikzpicture} +\end{codeexample} + +\subsection{De l'optique géométrique et des calculs} + +\begin{codeexample}[] +\begin{tikzpicture}[use optics] + \node[lens,draw focal points,focal length=1.5cm,object height=2cm] (L) at (0,0) {}; + \coordinate (P) at (-2cm,0.5cm); + \coordinate (Q) at (-2cm,-0.5cm); + \draw[red,shorten >=-1cm] (P) -- ($(L.north)!(P)!(L.south)$) -- (L.east focus); + \draw[red,shorten >=-1cm] (Q) -- ($(L.north)!(Q)!(L.south)$) -- (L.east focus); + \node[screen] at (2.45cm,0) {}; +\end{tikzpicture} +\end{codeexample} + + Cet exemple n'est pas très propre, car j'ai dû allonger manuellement les rayons pour qu'ils aillent jusqu'à l'écran. La méthode suivante, qui consiste à calculer le point d'intersection grâce à une fonction |\toVerticalProjection|, est beaucoup plus propre: + +\begin{codeexample}[] +\begin{tikzpicture}[use optics] + \node[lens,draw focal points,focal length=1.5cm,object height=2cm] (L) at (0,0) {} ; + \coordinate (P) at (-2cm,0.5cm) ; + \coordinate (Q) at (-2cm,-0.5cm) ; + \node[screen] (S) at (2.5cm,0) {}; + + \def\toVerticalProjection#1#2#3{let \p{1} = #1, \p{2} = #2, \p{3} = #3 in + -- (\x{3},{\y{1}+(\y{2}-\y{1})/(\x{2}-\x{1})*(\x{3}-\x{1})})} + + \draw[red] (P) -- ($(L.north)!(P)!(L.south)$) coordinate (Plens) + \toVerticalProjection{(Plens)}{(L.east focus)}{(S)}; + + \draw[red] (Q) -- ($(L.north)!(Q)!(L.south)$) coordinate (Qlens) + \toVerticalProjection{(Qlens)}{(L.east focus)}{(S)}; + +\end{tikzpicture} +\end{codeexample} + +\subsection{De la biréfringence avec un interféromètre de Michelson} + +\input{birefringence_michelson.pgf} + +Cet exemple utilise des intersections pour tracer des rayons lumineux : la syntaxe n'est pas la plus agréable et concise qu'on puisse concevoir, mais elle marche. +Cet exemple est aussi l'occasion de montrer l'utilisation du package \texttt{ocgx} avec \texttt{tikz}. +Le code de la figure est dans le fichier \textattachfile[]{birefringence_michelson.pgf}{birefringence\_michelson.pgf}. + + +\section{Référence} + +\subsection{Généralités} + +\subsubsection{Options communes} + +Certaines options sont communes à beaucoup des |shapes| (à l'exception notable des lampes et capteurs). + +\begin{key}{/tikz/optics/object height=\meta{length} (initially \pgfkeysvalueof{/tikz/optics/object height})} + L'option |object height| contrôle la hauteur de la plupart des objets (c'est le cas si rien n'est précisé). + +\begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[lens, object height=1cm] (L1) at (0,0) {}; + \node[lens, object height=2cm] (L2) at (3cm,0) {}; +\end{tikzpicture} +\end{codeexample} +\end{key} + +\begin{key}{/tikz/optics/object aspect ratio=\meta{number or length} (initially \pgfkeysvalueof{/tikz/optics/object aspect ratio})} + L'option |object aspect ratio| contrôle le rapport d'aspect de la plupart des objets ayant une largeur. Si \meta{number} vaut |1|, la largeur de l'objet est égale à sa hauteur. + Si \meta{number}|=1/2|, la largeur de l'objet vaut la moitié de sa hauteur. + Quand \meta{number or length} est un nombre sans dimension (e.g. |0.5|), il est interprété comme un rapport d'aspect, relatif à la hauteur. Quand il s'agit d'une longueur dimensionnée (e.g. |1cm|), il est directement interprété comme la largeur (\emph{width}) de l'objet. + +\begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[polarizer, object aspect ratio=0.2] (L1) at (0,0) {}; + \node[polarizer, object aspect ratio=0.5] (L2) at (4cm,0) {}; +\end{tikzpicture} +\end{codeexample} +\end{key} + +\begin{stylekey}{/tikz/optics/object width} + L'option |object width| est un alias pour |object aspect ratio|. +\end{stylekey} + +\subsubsection{Longueurs absolues et relatives} + +Les divers éléments ont plusieurs longueurs ajustables. La plupart du temps, il n'est nécessaire de spécifier qu'une seule longueur (généralement la hauteur de l'objet) de manière absolue, c'est-à-dire avec une unité de longueur (|cm|, |pt|, |em|, etc.). Les autres longueurs peuvent être spécifiées en unité de cette longueur absolue de référence (il faut alors spécifier un nombre), ou, si cela s'avère plus pratique, comme des longueurs absolues (il faut alors spécifier une unité). Voici un exemple avec |slit height|, qui peut être spécifié relativement à |object height|. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics] + \draw[style=help lines,gray!50] + (-3cm,-2cm) grid[step=0.5cm] (2cm,2cm); + \node[slit,object height=2cm,slit height=0.5,red,very thick] + at (-2cm,0) {}; + \node[slit,object height=2cm,slit height=0.25,blue,very thick] + at (-1cm,0) {}; + \node[slit,object height=2cm,slit height=0.5cm,violet,very thick] + at (0cm,0) {}; + \node[slit,object height=2cm,slit height=1cm,orange,very thick] + at (1cm,0) {}; +\end{tikzpicture} +\end{codeexample} + +L'intérêt d'utiliser des longueurs \emph{relatives} est que la \emph{forme générale} d'un objet n'est pas modifiée par un changement d'échelle (il n'y a qu'à changer la longueur absolue de référence). + +Les éléments optiques ont plusieurs \enquote{hauteurs}. La hauteur totale est toujours appelée |objet height|, mais par exemple la taille d'une fente est appelée |slit height|, la taille (sans conséquence sur le dessin, mais qui affecte les ancres) d'une lentille sur son support est appelée |lens height|, etc. + +% Note : je ne sais pas si je change les |aspect ratio| par un |object width| qui accepte un \meta{number or length} ... +% => C'est fait pour un bon nombre de trucs. + + +\subsection{Éléments optiques} + +\subsubsection{Lentille} + +\begin{shape}{lens} +Dessine une lentille. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[lens] (L) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} + + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[lens,draw focal points] (L) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} + + \begin{stylekey}{/tikz/optics/draw focal points=\meta{style} (default empty)} + On peut tracer les foyers avec |draw focal points|. En donnant \meta{style} en argument à la clé |draw docal points|, + on peut déterminer comment sont tracés les foyers. Par exemple \texttt{draw focal points={red}} les trace en rouge, et \texttt{draw focal points={circle,draw=none,fill=blue}} trace un cercle rempli en bleu. + \end{stylekey} + + \begin{codeexample}[width=6cm] + \begin{tikzpicture}[use optics,scale=.5] + \node[lens,draw focal points={red}] + (L1) at (0,0) {}; + \node[lens,draw focal points={circle,draw=none,fill=blue}] + (L2) at (3cm,0) {}; + \end{tikzpicture} +\end{codeexample} + +\begin{key}{/tikz/optics/object height=\meta{length} (initially \pgfkeysvalueof{/tikz/optics/object height})} + L'option |object height| est applicable. +\end{key} + +\begin{key}{/tikz/optics/focal length=\meta{length} (initially \pgfkeysvalueof{/tikz/optics/focal length})} + L'option |focal length| contrôle la distance focale de la lentille. + + \begin{codeexample}[width=6cm,pre={\tikzset{every lens node/.append style={optics,draw focal points}}}] +\begin{tikzpicture}[use optics,scale=.5] + \node[lens, focal length=1cm] (L1) at (0,0) {}; + \node[lens, focal length=2cm] (L2) at (0,5cm) {}; +\end{tikzpicture} + \end{codeexample} +\end{key} + + +\begin{key}{/tikz/optics/lens height=\meta{number or length} (initially \pgfkeysvalueof{/tikz/optics/lens height})} + L'option |lens height| contrôle la hauteur de la lentille. Il s'agit soit une longueur abolue (avec unité), soit d'une longueur relative mesurée par rapport à la hauteur totale de la lentille avec support. + + \begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[lens] (L1) at (1cm,0) {}; + \node[lens, lens height=0.5] (L2) at (-1cm,0) {}; + \draw[red] (0,0) -- (L1.lens north) (0,0) -- (L1.lens south); + \draw[green] (0,0) -- (L2.lens north) (0,0) -- (L2.lens south); +\end{tikzpicture} + \end{codeexample} + + % Serait-il plus judicieux d'avoir un système de coordonnées sur la lentille, genre |(L1.0)| pour le centre, |(L1.1)| pour le haut, |(L1.0.5)| pour un point en haut, à mi-lentille, |(L1.-1)| pour le bas, etc. ? Ou est-ce que |($(L1.north)!0.1!(L1.south)$)| suffit amplement ? +\end{key} + + +\begin{key}{/tikz/optics/lens type} + L'option |lens type| contrôle le type de lentille. Utiliser |lens type=converging| permet de dessiner une lentille convergente (c'est l'option par défaut), alors que |lens type=diverging| permet de dessiner une lentille divergente. + + \begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[lens,lens type=converging] (L1) at (-1cm,0) {}; + \node[lens,lens type=diverging] (L2) at (1cm,0) {}; +\end{tikzpicture} + \end{codeexample} +\end{key} + + +La figure suivante récapitule les ancres définies par |lens|. + + +\begin{codeexample}[] +\Huge +\begin{tikzpicture}[use optics] +\node[name=s,lens,object height=7cm,focal length=3cm, +lens height=0.5,line shape example] {}; +\foreach \anchor/\placement in +{north/above,south/below,lens north/right,lens south/right,center/right, +east focus/above,west focus/above} +\draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)} +node[\placement] {\scriptsize\texttt{(s.\anchor)}}; +\end{tikzpicture} +\end{codeexample} + +Les clés |east focus| et |west focus| ont pour synonyme |east focal point| et |west focal point|, respectivement. + + +On peut utiliser la clé \texttt{tikz} \texttt{anchor=} pour placer les lentilles les unes par rapport aux autres. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[lens,draw focal points={red}] + (L1) at (0,0) {}; + \node[lens,draw focal points={circle,draw=blue}, + focal length=0.5cm,anchor=west focus] + (L2) at (L1.east focus) {}; +\end{tikzpicture} +\end{codeexample} + +\end{shape} + +\subsubsection{Fente} + +\begin{shape}{slit} +Dessine une fente. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[slit] (S) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} + +\begin{key}{/tikz/optics/object height=\meta{length} (initially \pgfkeysvalueof{/tikz/optics/object height})} + L'option |object height| est applicable. +\end{key} + + +\begin{key}{/tikz/optics/slit height=\meta{number or length} (initially \pgfkeysvalueof{/tikz/optics/slit height})} +La clé |slit height| définit la hauteur de la fente (s'il s'agit d'une longueur relative, elle est exprimée en unités de la hauteur de l'objet). +Par exemple, \meta{number}|=0.5| donne une fente faisant la moitié de la hauteur du support. De même, \meta{length}|=1cm| donne une fente de |1cm|. Les valeurs de \meta{number} doivent être inférieures à l'unité, et celles de \meta{length} inférieures à celles de |object height|, sans quoi les résultats ne sont pas garantis. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[slit, slit height=0.5] (S) at (0,0) {}; + \node[slit, slit height=0.3] (S) at (1cm,0) {}; + \node[slit, slit height=0.1] (S) at (2cm,0) {}; +\end{tikzpicture} +\end{codeexample} +\end{key} + +La figure suivante récapitule les ancres définies par |slit|. + +\begin{codeexample}[] +\Huge +\begin{tikzpicture}[use optics] +\node[name=s,slit,object height=8cm, +slit height=0.2,line shape example] {}; +\foreach \anchor/\placement in +{north/above,south/below,slit north/right,slit south/right,center/left, +slit center/right} +\draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)} +node[\placement] {\scriptsize\texttt{(s.\anchor)}}; +\end{tikzpicture} +\end{codeexample} + +\end{shape} + +\subsubsection{Double fente} + + +\begin{shape}{double slit} +Dessine une fente double. + +\begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[double slit] (S) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} + +\begin{key}{/tikz/optics/object height=\meta{length} (initially \pgfkeysvalueof{/tikz/optics/object height})} + L'option |object height| est applicable. +\end{key} + + +\begin{key}{/tikz/optics/slit height=\meta{number or length} (initially \pgfkeysvalueof{/tikz/optics/slit height})} +La clé |slit height| définit la hauteur d'une fente (s'il s'agit d'une longueur relative, elle est en unités de la hauteur de l'objet). +Chacune des fentes a une hauteur \meta{number or length}. + +\begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics,scale=.5,optics/slit separation=0.5] + \node[double slit, slit height=0.075] (S) at (0,0) {}; + \node[double slit, slit height=0.1] (S) at (1cm,0) {}; + \node[double slit, slit height=0.2] (S) at (2cm,0) {}; +\end{tikzpicture} +\end{codeexample} +\end{key} + +\begin{key}{/tikz/optics/slit separation=\meta{number or length} (initially \pgfkeysvalueof{/tikz/optics/slit separation})} +La clé |slit separation| définit la distance entre les deux fentes (s'il s'agit d'une longueur relative, elle est en unités de la hauteur de l'objet). + +\begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[double slit, slit separation=0.1] (S) at (0,0) {}; + \node[double slit, slit separation=0.2] (S) at (1cm,0) {}; + \node[double slit, slit separation=0.3] (S) at (2cm,0) {}; +\end{tikzpicture} +\end{codeexample} +\end{key} + + + +La figure suivante récapitule les ancres définies par |double slit|. + +\begin{codeexample}[] +\Huge +\begin{tikzpicture}[use optics] +\node[double slit,name=s,object height=8cm, slit height=0.15, +slit separation=0.5, line shape example] {}; +\foreach \anchor/\placement in +{north/above,south/below,center/left, +slit 1 north/right,slit 1 south/right,slit 1 center/right, +slit 2 north/right,slit 2 south/right,slit 2 center/right} +\draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)} +node[\placement] {\scriptsize\texttt{(s.\anchor)}}; +\end{tikzpicture} +\end{codeexample} + +\end{shape} + + +\subsubsection{Miroir} + + +\begin{shape}{mirror} +Dessine un miroir plan. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[mirror] (S) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} + +\begin{key}{/tikz/optics/object height=\meta{length} (initially \pgfkeysvalueof{/tikz/optics/object height})} + L'option |object height| est applicable. +\end{key} + +\begin{key}{/tikz/optics/mirror decoration separation=\meta{number or length} (initially \pgfkeysvalueof{/tikz/optics/mirror decoration separation})} +Correspond à la clé |/pgf/decoration/segment length| pour la décoration |border| utilisée pour dessiner le miroir (cf. manuel de pgf/tikz). +La valeur correspondant à |/pgf/decoration/segment length| est obtenue en multipliant \meta{number} par la hauteur du miroir. +\end{key} + +\begin{key}{/tikz/optics/mirror decoration amplitude=\meta{number or length} (initially \pgfkeysvalueof{/tikz/optics/mirror decoration amplitude})} +Correspond à la clé |/pgf/decoration/amplitude| pour la décoration |border| utilisée pour dessiner le miroir (cf. manuel de pgf/tikz). +La valeur correspondant à |/pgf/decoration/amplitude| est obtenue en multipliant \meta{number} par la hauteur du miroir. +\end{key} + + +La figure suivante récapitule les ancres définies par |mirror|. + +\begin{codeexample}[] +\Huge +\begin{tikzpicture}[use optics] +\node[mirror,name=s,object height=8cm,line shape example, +mirror decoration separation=0.141, mirror decoration amplitude=0.2] {}; +\foreach \anchor/\placement in +{north/above,south/below,center/right} +\draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)} +node[\placement] {\scriptsize\texttt{(s.\anchor)}}; +\end{tikzpicture} +\end{codeexample} + +La clé |focus| a pour synonyme |focal point|. + +\end{shape} + +\subsubsection{Miroir sphérique} + +\begin{shape}{spherical mirror} +Dessine un miroir sphérique (concave ou convexe). + +\begin{warning} + Cette partie n'est pas encore au point et peut changer sans préavis. +\end{warning} + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[spherical mirror] (M) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} + +\begin{key}{/tikz/optics/object height=\meta{length} (initially \pgfkeysvalueof{/tikz/optics/object height})} + La clé |object height| est applicable. +\end{key} + +\begin{key}{/tikz/optics/spherical mirror angle=\meta{angle} (initially \pgfkeysvalueof{/tikz/optics/spherical mirror angle})} + La clé |spherical mirror angle| contrôle l'angle d'ouverture du miroir sphérique (un arc de cercle de hauteur spécifiée par |object height| et d'ouverture angulaire \meta{angle} est dessiné). + Attention à ne pas choisir $\meta{angle}=0$ : utiliser un miroir plat |mirror| à la place. +\begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics] + \node[spherical mirror, spherical mirror angle=60] at (0,0) {}; + \node[spherical mirror, spherical mirror angle=120] at (2cm,0) {}; + \node[spherical mirror, spherical mirror angle=180] at (4cm,0) {}; +\end{tikzpicture} +\end{codeexample} + +\begin{warning} + La fonction |from_radius| est expérimentale. +\end{warning} + +Il peut être utile de spécifier non pas l'angle d'ouverture, mais le rayon de courbure du miroir ; dans ce but, une fonction |from_radius(R)| calcule l'angle d'ouverture correspondant au rayon |R|, à hauteur |/tikz/optics/object height| imposée. Bien entendu, il n'est pas possible que la hauteur soit supérieure au double du rayon du miroir. +\begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics] + \node[spherical mirror, object height=2cm, + spherical mirror angle=from_radius(3cm), + draw mirror focus, draw mirror center={red}] (M) {}; +\end{tikzpicture} +\end{codeexample} +\end{key} + +\begin{key}{/tikz/optics/spherical mirror type} + La clé |spherical mirror type| contrôle le type de miroir : utiliser |spherical mirror type=concave| donne un miroir concave (c'est l'option par défaut), alors que |spherical mirror type=convex| donne un miroir convexe. + Il est plus commode d'utiliser les styles |convex mirror| et |concave mirror|, qui sont des raccourcis pour cette clé. + +\begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics] + \node[convex mirror, label={[label distance=0.25cm]south:convex mirror}] at (0cm,0) {}; + \node[concave mirror, label={[label distance=0.25cm]south:concave mirror}] at (4cm,0) {}; +\end{tikzpicture} +\end{codeexample} +\end{key} + +\begin{stylekey}{/tikz/optics/concave mirror} + Le style |concave mirror| correspond à |spherical mirror, spherical mirror type=concave|, et dessine un miroir concave. Voir |spherical mirror type| pour un exemple. +\end{stylekey} + +\begin{stylekey}{/tikz/optics/convex mirror} + Le style |convex mirror| correspond à |spherical mirror, spherical mirror type=convex|, et dessine un miroir convexe. Voir |spherical mirror type| pour un exemple. +\end{stylekey} + + +\begin{key}{/tikz/optics/spherical mirror orientation=\meta{type} (initially |ltr|)} + La clé |spherical mirror orientation| contrôle l'orientation de miroir (i.e. dans quel sens on suppose que la lumière se propage). Les valeurs possibles sont |ltr| (\enquote{left to right}) et |rtl| (\enquote{right to left}). + +\begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics] + \node[spherical mirror, spherical mirror orientation=ltr] at (0cm,0) {}; + \node[spherical mirror, spherical mirror orientation=rtl] at (2cm,0) {}; +\end{tikzpicture} +\end{codeexample} +\end{key} + +La décoration du miroir (hachures) est contrôlée par les mêmes clés que celle de |mirror| : |mirror decoration separation| et |mirror decoration amplitude|. + + +La figure suivante récapitule certaines des ancres définies par |spherical mirror|. + +\begin{codeexample}[] +\Huge +\begin{tikzpicture}[use optics] +\node[spherical mirror,name=s,object height=8cm,line shape example, +mirror decoration separation=0.141, mirror decoration amplitude=0.2] {}; +\foreach \anchor/\placement in +{north/above,south/below,center/below right, +east/below right, +west/below, +north east/above right, +north west/above left, +south east/below right, +south west/below left, +mirror center/left, +arc start/above, +arc end/below, +arc center/right, +27/right, +focus/above} +\draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)} +node[\placement] {\scriptsize\texttt{(s.\anchor)}}; +\end{tikzpicture} +\end{codeexample} + +Avec les miroirs sphériques, les \enquote{border anchor} de tikz sont particulièrement utiles. Des ancres numériques (de la forme |node.27|) sont définies, qui permettent d'accèder au bord de la |shape| dans la direction angulaire correspondante (ici à \ang{27}). Rappelons que dans tikz, les angles sont comptés dans le sens trigonométrique à partir de l'axe $Ox$, et exprimés en degrés. Suit un exemple, où on a dessiné le cercle sous-jacent. + +\begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics,scale=.5]] +\coordinate (O) at (0,0); +\node[circle,draw, inner sep=0, outer sep=0,minimum height=2cm, densely dashed, gray!60] (C) at (O) {}; +\node[spherical mirror,draw,object height=2cm,anchor=mirror center, + spherical mirror angle=180] (M) at (O) {}; +\draw[blue] (O) -- (M.0); +\draw[violet] (O) -- (M.45); +\draw[red] (O) -- (M.90); +\draw[orange] (O) -- (M.135); +\end{tikzpicture} +\end{codeexample} + +\begin{warning} + Pour le moment, les angles supérieurs à $\pm$|spherical mirror angle|$/2$ sont traités comme si le miroir était un cercle entier (et pas un arc). Il n'est pas garanti que ce comportement soit maintenu. +\end{warning} + +\end{shape} + + +\begin{stylekey}{/tikz/optics/draw mirror center=\meta{style}} + Le style |draw mirror center| permet de dessiner le centre du miroir (avec le style \meta{style} s'il est spécifié). + +\begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics] +\node[concave mirror,draw mirror center, draw mirror focus={red}] {}; +\end{tikzpicture} +\end{codeexample} +\end{stylekey} + +\begin{stylekey}{/tikz/optics/draw mirror focus=\meta{style}} + Le style |draw mirror focus| permet de dessiner le foyer du miroir (avec le style \meta{style} s'il est spécifié). Voir |draw mirror center| pour un exemple. +\end{stylekey} + +\subsubsection{Polariseur} + +\begin{shape}{polarizer} +Dessine un polariseur. + +\begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[polarizer] (S) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} + + +\begin{key}{/tikz/optics/object height=\meta{length} (initially \pgfkeysvalueof{/tikz/optics/object height})} + L'option |object height| est applicable. +\end{key} + + +\begin{key}{/tikz/optics/object aspect ratio=\meta{number} (initially \pgfkeysvalueof{/tikz/optics/object aspect ratio})} + L'option |object aspect ratio| contrôle le rapport d'aspect du polariseur. Si \meta{number} vaut |1|, la largeur de l'objet est égale à sa hauteur. + Si \meta{number}|=1/2|, la largeur du polariseur vaut la moitié de sa hauteur + + \begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[polarizer, object aspect ratio=0.2] (L1) at (0,0) {}; + \node[polarizer, object aspect ratio=0.5] (L2) at (4cm,0) {}; +\end{tikzpicture} + \end{codeexample} +\end{key} + + + +La figure suivante récapitule les ancres définies par |polarizer|. + +\begin{codeexample}[] +\Huge +\begin{tikzpicture}[use optics] +\node[polarizer,name=s,object height=8cm,object aspect ratio=0.4,shape example] {}; +\foreach \anchor/\placement in +{north/above,south/below,east/right,west/left,center/below, +north east/right,north west/left,south east/right,south west/left} +\draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)} +node[\placement] {\scriptsize\texttt{(s.\anchor)}}; +\end{tikzpicture} +\end{codeexample} + +\end{shape} + + +\subsubsection{Séparateur de faisceau} + +\begin{stylekey}{/tikz/optics/beam splitter} +Dessine un séparateur de faisceau. Les options et ancres sont les mêmes que pour |polarizer|. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[beam splitter] at (0,0) {}; +\end{tikzpicture} +\end{codeexample} + +\end{stylekey} + + +\subsubsection{Prisme à vision directe} + +\begin{shape}{double amici prism} +Dessine un prisme à vision directe (double prisme d'Amici). + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[double amici prism] (PVD) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} + + +\begin{key}{/tikz/optics/prism height=\meta{length} (initially \pgfkeysvalueof{/tikz/optics/prism height})} + La clé |prism height| contrôle la hauteur des trois prismes identiques constituant le PVD (la longueur d'un côté est donc $2/\sqrt{3}$ fois cette hauteur). + + \begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[double amici prism, prism height=1cm] (PVD1) at (0,0) {}; + \node[double amici prism, prism height=0.5cm] (PVD2) at (4cm,0) {}; +\end{tikzpicture} + \end{codeexample} +\end{key} + + +\begin{key}{/tikz/optics/prism apex angle=\meta{angle} (initially \pgfkeysvalueof{/tikz/optics/prism apex angle})} + La clé |prism apex angle| contrôle l'angle au sommet des trois prismes identiques. \meta{angle} est exprimé en degrés. Si \meta{angle} vaut |60|, les prismes sont des triangles isocèles. + + \begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[double amici prism, prism apex angle=40] (PVD1) at (0,0) {}; + \node[double amici prism, prism apex angle=60] (PVD2) at (4cm,0) {}; + \node[double amici prism, prism apex angle=80] (PVD3) at (10cm,0) {}; +\end{tikzpicture} + \end{codeexample} +\end{key} + + + +La figure suivante récapitule les ancres définies par |double amici prism|. + +\begin{codeexample}[] +\Huge +\begin{tikzpicture}[use optics] +\node[double amici prism,name=s,prism height=4.5cm,shape example] {}; +\foreach \anchor/\placement in +{north/above,south/below,east/right,west/left,center/below, +north east/right,north west/left,south east/right,south west/left} +\draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)} +node[\placement] {\scriptsize\texttt{(s.\anchor)}}; +\end{tikzpicture} +\end{codeexample} + +\end{shape} + + +\subsubsection{Élément générique fin} + +\begin{shape}{thin optics element} +Dessine un élement générique (utilisé pour des éléments plus spécifiques). +Cette |shape| peut être utile pour dessiner un objet non prévu, en lui donnant un style pertinent. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[thin optics element] (S) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} + +\begin{key}{/tikz/optics/object height=\meta{length} (initially \pgfkeysvalueof{/tikz/optics/object height})} + L'option |object height| est applicable. +\end{key} + +La figure suivante récapitule les ancres définies par |thin optics element|. + +\begin{codeexample}[] +\Huge +\begin{tikzpicture}[use optics] +\node[thin optics element,name=s,object height=8cm,line shape example] {}; +\foreach \anchor/\placement in +{north/above,south/below,center/right} +\draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)} +node[\placement] {\scriptsize\texttt{(s.\anchor)}}; +\end{tikzpicture} +\end{codeexample} + +\end{shape} + +\subsubsection{Élément générique épais} + +\begin{shape}{thick optics element} +Dessine un élément générique épais. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[thick optics element] at (0,0) {}; +\end{tikzpicture} +\end{codeexample} + + +\begin{key}{/tikz/optics/object height=\meta{length} (initially \pgfkeysvalueof{/tikz/optics/object height})} + L'option |object height| est applicable. +\end{key} + + +\begin{key}{/tikz/optics/object aspect ratio=\meta{number or length} (initially 0.05)} + L'option |object aspect ratio| contrôle le rapport d'aspect de l'objet. +\end{key} + + + + +La figure suivante récapitule les ancres définies par |thick optics element|. + +\begin{codeexample}[] +\Huge +\begin{tikzpicture}[use optics] +\node[thick optics element,name=s,object height=8cm,shape example,object aspect ratio=0.2] {}; +\foreach \anchor/\placement in +{north/above,south/below,east/right,west/left,center/below, +north east/right,north west/left,south east/right,south west/left} +\draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)} +node[\placement] {\scriptsize\texttt{(s.\anchor)}}; +\end{tikzpicture} +\end{codeexample} + +\end{shape} + +\subsubsection{Anticalorique} + +\begin{stylekey}{/tikz/optics/heat filter} +Le style |heat filter| permet de dessiner un filtre anticalorique. Les options de |thick optics element| sont applicables. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[heat filter] (S) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} +\end{stylekey} + + +\subsubsection{Écran} + + +\begin{stylekey}{/tikz/optics/screen} +Le style |screen| permet de dessiner un écran. Les options de |thin optics element| sont applicables. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[screen] (S) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} +\end{stylekey} + +\subsubsection{Réseau de diffraction} + +\begin{stylekey}{/tikz/optics/diffraction grating} +Le style |diffraction grating| permet de dessiner un réseau de diffraction. Les options de |thin optics element| sont applicables. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[diffraction grating] (S) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} +\end{stylekey} + +\subsubsection{Grille} + +\begin{stylekey}{/tikz/optics/grid} +Le style |grid| permet de dessiner une grille. Les options de |thin optics element| sont applicables. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[grid] (S) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} +\end{stylekey} + +\subsubsection{Lame semi-réfléchissante} + +\begin{stylekey}{/tikz/optics/semi-transparent mirror} +Le style |semi-transparent mirror| permet de dessiner un miroir semi-réfléchissant. Les options de |thin optics element| sont applicables. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[semi-transparent mirror] (S) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} +\end{stylekey} + +\subsubsection{Diaphragme} + +\begin{stylekey}{/tikz/optics/diaphragm} +Le style |diaphragm| permet de dessiner un diaphragme (c'est un |slit| avec une fente large). Les options de |slit| sont applicables. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[diaphragm] (S) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} +\end{stylekey} + + +\subsection{Lampes et capteurs} + +\subsubsection{Entrée/sortie optique générique} + +\begin{shape}{generic optics io} +Dessine un système entrée-sortie générique (utilisé pour des objets plus spécifiques). + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[generic optics io] (S) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} + + +\begin{key}{/tikz/optics/io body height=\meta{length} (initially \pgfkeysvalueof{/tikz/optics/io body height})} + La clé |io body height| contrôle la taille de la lampe. En particulier, \meta{length} spécifie la hauteur du corps de la lampe, + et les autres longueurs sont spécifiées relativement à celle-ci. En modifiant \meta{length}, on modifie donc la taille de la lampe + sans la déformer. + + \begin{codeexample}[] +\begin{tikzpicture}[use optics,scale=.5] + \node[generic optics io, io body height=1cm] (L1) at (0,0) {}; + \node[generic optics io, io body height=2cm] (L2) at (10cm,0) {}; +\end{tikzpicture} + \end{codeexample} +\end{key} + +\begin{key}{/tikz/optics/io body aspect ratio=\meta{number or length} (initially \pgfkeysvalueof{/tikz/optics/io body aspect ratio})} + La clé |io body aspect ratio| contrôle le rapport d'aspect de la lampe. Si \meta{number} vaut |1|, la largeur de la lampe est égale à sa hauteur. + Si \meta{number}|=1/2|, la largeur de la lampe vaut la moitié de sa hauteur + + \begin{codeexample}[] +\begin{tikzpicture}[use optics,scale=.5] + \node[generic optics io, io body aspect ratio=1] (L1) at (0,0) {}; + \node[generic optics io, io body aspect ratio=2] (L2) at (8cm,0) {}; +\end{tikzpicture} + \end{codeexample} +\end{key} + +\begin{stylekey}{/tikz/optics/io body width=\meta{number or length}} +La clé |io body width| est un alias pour |io body aspect ratio|. +\end{stylekey} + + +\begin{key}{/tikz/optics/io aperture width=\meta{number or length} (initially \pgfkeysvalueof{/tikz/optics/io aperture width})} + La clé |io aperture width| contrôle la largeur du système de sortie de la lampe (qui représente un condenseur, une lentille de collimation, etc.), en unités de la hauteur du corps de la lampe. Si \meta{number}|=0|, le système de sortie n'est pas affiché. + + \begin{codeexample}[] +\begin{tikzpicture}[use optics,scale=.5] + \node[generic optics io, io aperture width=0] at (0,0) {}; + \node[generic optics io, io aperture width=0.1] at (8cm,0) {}; + \node[generic optics io, io aperture width=0.5] at (16cm,0) {}; +\end{tikzpicture} + \end{codeexample} +\end{key} + + + + +\begin{key}{/tikz/optics/io aperture height=\meta{number or length} (initially \pgfkeysvalueof{/tikz/optics/io aperture height})} + La clé |io aperture width| contrôle la hauteur du système de sortie de la lampe (qui représente un condenseur, une lentille de collimation, etc.), en unités de la hauteur du corps de la lampe. + + \begin{codeexample}[] +\begin{tikzpicture}[use optics,scale=.5] + \node[generic optics io, io aperture height=0.5] at (0,0) {}; + \node[generic optics io, io aperture height=0.8] at (8cm,0) {}; +\end{tikzpicture} + \end{codeexample} +\end{key} + + +\begin{key}{/tikz/optics/io aperture shift=\meta{number or length} (initially \pgfkeysvalueof{/tikz/optics/io aperture shift})} + L'option |io aperture shift| contrôle le décalage du système de sortie de la lampe par rapport au centre, en unités de la hauteur du corps de la lampe. + + \begin{codeexample}[] +\begin{tikzpicture}[use optics,scale=.5, +optics,io body height=2cm,io body aspect ratio=0.5,io aperture height=0.3, io aperture width=0.1] + \node[generic optics io,io aperture shift=-0.25] at (-5cm,0) {}; + \node[generic optics io,io aperture shift=0] at (0,0) {}; + \node[generic optics io,io aperture shift=0.25] at (5cm,0) {}; +\end{tikzpicture} + \end{codeexample} +\end{key} + + +On peut afficher du texte dans le corps d'une lampe en utilisant le texte de la |node|. + +\begin{codeexample}[] +\begin{tikzpicture}[use optics,scale=.5] + \node[generic optics io] at (-5cm,0) {Q.I.}; +\end{tikzpicture} +\end{codeexample} + +\begin{key}{/tikz/optics/io orientation=\meta{type} (initially |ltr|)} + La clé |io orientation| détermine le sens dans lequel est dessiné l'objet (avec l'ouverture à droite (au niveau de l'ancre |east|) quand elle vaut |ltr| et à gauche (au niveau de l'ancre |west|) quand elle vaut |rtl|). Les noms correspondent à \enquote{left to right} et \enquote{right to left}. + Seules les arguments |ltr| et |rtl| sont autorisés. La différence avec |rotate| est que |io orientation| modifie les ancres. + + \begin{codeexample}[] +\begin{tikzpicture}[use optics,scale=.5] + \node[generic optics io] at (0,0) {}; + \node[generic optics io,io orientation=ltr] at (5cm,0) {}; + \node[generic optics io,io orientation=rtl] at (10cm,0) {}; +\end{tikzpicture} + \end{codeexample} +\end{key} + + +On peut afficher du texte dans le corps d'une lampe en utilisant le texte de la |node|. + +\begin{codeexample}[] +\begin{tikzpicture}[use optics,scale=.5] + \node[generic optics io] at (-5cm,0) {Q.I.}; +\end{tikzpicture} +\end{codeexample} + + +La figure suivante récapitule les ancres définies par |generic optics io|. + +\begin{codeexample}[] +\Huge +\begin{tikzpicture}[use optics] +\node[generic optics io,name=s,io body height=4cm,io aperture width=0.7,io body aspect ratio=1.8,shape example] {}; +\foreach \anchor/\placement in +{body north/above,body south/below,body east/above right,body west/right,body center/below, +body north east/above,body north west/above,body south east/below,body south west/below, +aperture north/above,aperture south/below,aperture east/right,aperture west/left,aperture center/below, +aperture north east/right,aperture north west/left,aperture south east/right,aperture south west/left} +\draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)} +node[\placement] {\scriptsize\texttt{(s.\anchor)}}; +\end{tikzpicture} +\end{codeexample} + +Notons que les ancres |body east| et |aperture west| correspondent au même point. Les deux sont définies dans un souci de cohérence. Une ancre |east| est définie comme |body east| ou |aperture east| en fonction de la valeur de |io orientation| de manière à ce que |east| soit la clé la plus à l'est (à droite). La même chose a lieu pour l'ancre |west|. + +La figure suivante récapitule les ancres définies par |generic optics io, io orientation=rtl|. + +\begin{codeexample}[] +\Huge +\begin{tikzpicture}[use optics] +\node[generic optics io,name=s,io body height=4cm,io aperture width=0.7,io body aspect ratio=1.8, +io orientation=rtl,shape example] {}; +\foreach \anchor/\placement in +{body north/above,body south/below,body east/above right,body west/above right,body center/below, +body north east/above,body north west/above,body south east/below,body south west/below, +aperture north/above,aperture south/below,aperture east/right,aperture west/left,aperture center/below, +aperture north east/right,aperture north west/left,aperture south east/right,aperture south west/left} +\draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)} +node[\placement] {\scriptsize\texttt{(s.\anchor)}}; +\end{tikzpicture} +\end{codeexample} + +\end{shape} + + +\subsubsection{Ligne de capteurs} + + +\begin{shape}{sensor line} +Dessine une ligne de capteurs (type Caliens). + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[sensor line] (S) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} + +\begin{key}{/tikz/optics/sensor line height=\meta{length} (initially \pgfkeysvalueof{/tikz/optics/sensor line height})} + La clé |sensor line height| contrôle la taille de la ligne de capteurs. En particulier, \meta{length} spécifie la hauteur du corps de la ligne, + et les autres longueurs peuvent être spécifiées relativement à celle-ci (en ne donnant pas d'unité). Dans ce cas, en modifiant \meta{length}, on modifie donc la taille de la ligne de capteurs + sans la déformer. + + \begin{codeexample}[] +\begin{tikzpicture}[use optics,scale=.5] + \node[sensor line, sensor line height=1cm] (L1) at (0,0) {}; + \node[sensor line, sensor line height=2cm] (L2) at (4cm,0) {}; +\end{tikzpicture} + \end{codeexample} +\end{key} + +\begin{key}{/tikz/optics/sensor line aspect ratio=\meta{number} (initially \pgfkeysvalueof{/tikz/optics/sensor line aspect ratio})} + La clé |sensor line aspect ratio| contrôle le rapport d'aspect de la ligne de capteurs. + + \begin{codeexample}[] +\begin{tikzpicture}[use optics,scale=.5] + \node[sensor line, sensor line aspect ratio=0.2] (L1) at (0,0) {}; + \node[sensor line, sensor line aspect ratio=0.4] (L2) at (4cm,0) {}; +\end{tikzpicture} + \end{codeexample} +\end{key} + + +\begin{key}{/tikz/optics/sensor line pixel number=\meta{number} (initially \pgfkeysvalueof{/tikz/optics/sensor line pixel number})} + La clé |sensor line pixel number| contrôle le nombre de pixels \meta{number} de la ligne de capteurs. + + \begin{codeexample}[] +\begin{tikzpicture}[use optics,scale=.5] + \node[sensor line, sensor line pixel number=2] at (0,0) {}; + \node[sensor line, sensor line pixel number=4] at (4cm,0) {}; + \node[sensor line, sensor line pixel number=10] at (8cm,0) {}; +\end{tikzpicture} + \end{codeexample} +\end{key} + + +\begin{key}{/tikz/optics/sensor line pixel width=\meta{number or length} (initially \pgfkeysvalueof{/tikz/optics/sensor line pixel width})} + La clé |sensor line pixel width| contrôle la largeur des pixels : \meta{number or length} est la largeur d'un pixel (par rapport à la largeur du capteur si elle est relative). + + \begin{codeexample}[] +\begin{tikzpicture}[use optics,scale=.5] + \node[sensor line, sensor line pixel width=0.3] at (0,0) {}; + \node[sensor line, sensor line pixel width=0.8] at (4cm,0) {}; +\end{tikzpicture} + \end{codeexample} +\end{key} + + +\begin{key}{/tikz/optics/sensor line inner ysep=\meta{number or length} (initially \pgfkeysvalueof{/tikz/optics/sensor line inner ysep})} + La clé |sensor line inner ysep| contrôle la séparation entre les bords haut et bas du capteur et les pixels. Si \meta{number or length} est une hauteur relative, elle est comptée par rapport à la hauteur du capteur. La hauteur des pixels est calculée de manière à ce qu'il y en ait un nombre |sensor line pixel number|, en tenant compte de cette séparation. + + \begin{codeexample}[] +\begin{tikzpicture}[use optics,scale=.5] + \node[sensor line,sensor line inner ysep=0] at (0,0) {}; + \node[sensor line,sensor line inner ysep=0.1] at (4cm,0) {}; + \node[sensor line,sensor line inner ysep=0.2] at (8cm,0) {}; +\end{tikzpicture} + \end{codeexample} +\end{key} + + +Les ancres |north|, |south|, |east|, |west|, |center|, |north east|, |north west|, |south east|, |south west|, ainsi que +|pixel <i> <anchor>| où |<anchor>| vaut |north|, |south|, etc. et où |<i>| est le numéro du pixel considéré +(allant de |1| à |sensor line pixel number|) sont définies. Par exemple, on peut utiliser |pixel 3 west|. + +La figure suivante récapitule les ancres définies par |sensor line| définies globalement ainsi que pour le pixel 4 (en rouge). + +\begin{codeexample}[] +\Huge +\begin{tikzpicture}[use optics] +\node[sensor line,name=s,sensor line height=10cm,sensor line aspect ratio=0.8, +sensor line inner ysep=0.1,sensor line pixel number=5, shape example] {}; +\foreach \anchor/\placement in +{north/above,south/below,east/right,west/left,center/below, +north east/right,north west/left,south east/right,south west/left} + +\draw[shift=(s.\anchor)] plot[mark=x] coordinates{(0,0)} +node[\placement] {\scriptsize\texttt{(s.\anchor)}}; + +\foreach \anchor/\placement in +{pixel 4 north/above,pixel 4 south/below,pixel 4 east/right,pixel 4 west/left,pixel 4 center/below, +pixel 4 north east/right,pixel 4 north west/left,pixel 4 south east/right,pixel 4 south west/left} +% manque pixel <i> <subanchor> +\draw[red,shift=(s.\anchor)] plot[mark=x,red] coordinates{(0,0)} +node[\placement] {\scriptsize\texttt{(s.\anchor)}}; + +\end{tikzpicture} +\end{codeexample} + +\end{shape} + + +Remarques : +\begin{itemize} + \item Quand les ancres |east| et |west| ne sont pas définies explicitement, elles sont en fait des alias pour |center|. Cela permet aux clés |right=of...| et assimilées de fonctionner correctement. +\end{itemize} + + + +\subsubsection{Capteur générique} + +\begin{stylekey}{/tikz/optics/generic sensor} +Le style |generic sensor| permet de dessiner un capteur. Les options de |generic optics io| sont applicables. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[generic sensor] (S) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} +\end{stylekey} + +\subsubsection{Lampe générique} + +\begin{stylekey}{/tikz/optics/generic lamp} +Le style |generic lamp| permet de dessiner une lampe. Les options de |generic optics io| sont applicables. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[generic lamp] (S) at (0,0) {}; +\end{tikzpicture} +\end{codeexample} +\end{stylekey} + +\subsubsection{Lampe QI} + +\begin{stylekey}{/tikz/optics/halogen lamp} +Le style |halogen lamp| permet de dessiner une lampe de type \enquote{lampe halogène Quartz Iode}. Les options de |generic optics io| sont applicables. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[halogen lamp] (S) at (0,0) {}; + \node[halogen lamp] (S) at (5cm,0) {QI}; +\end{tikzpicture} +\end{codeexample} +\end{stylekey} + +\subsubsection{Lampe spectrale} + +\begin{stylekey}{/tikz/optics/spectral lamp} +Le style |spectral lamp| permet de dessiner une lampe de type \enquote{lampe spectrale}. Les options de |generic optics io| sont applicables. Par ailleurs, un style est automatiquement appliqué pour autoriser le texte multiligne. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[spectral lamp] (S) at (0,0) {}; + \node[spectral lamp] (S) at (5cm,0) {\ce{Hg} \\ BP}; +\end{tikzpicture} +\end{codeexample} +\end{stylekey} + +\subsubsection{Laser} + +\begin{stylekey}{/tikz/optics/laser} +Le style |laser| permet de dessiner un laser. Les options de |generic optics io| sont applicables. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[laser] (S) at (0,0) {}; + \node[laser] (S) at (5cm,0) {\ce{HeNe}}; +\end{tikzpicture} +\end{codeexample} +\end{stylekey} + +\begin{stylekey}{/tikz/optics/laser'} +Le style |laser'| permet de dessiner un laser sans \enquote{orifice de sortie} (i.e. |io aperture width=0pt|). Les options de |generic optics io| sont applicables. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics,scale=.5] + \node[laser'] (S) at (0,0) {\ce{Nd}:YAG}; + \draw[green] (S.aperture east) -- +(2cm,0); +\end{tikzpicture} +\end{codeexample} +\end{stylekey} + +\subsection{Divers} + + + +\subsubsection{Marquer des rayons} + +\begin{update} + 2014-12-07 : cette partie a été substantiellement modifiée. +\end{update} + +\begin{warning} + Cette partie n'est pas encore stable. Les raccourcis |->-|, etc. ne devraient normalement pas changer +\end{warning} + +Les flèches pour marquer les rayons sont conçues pour se trouver \emph{vraiment} au milieu du rayon (contrairement à ce qui arrive en utilisant simplement |\arrow{>>}| avec |put arrow|). + +\begin{stylekey}{/tikz/optics/->-} + Ce style ajoute une flèche au milieu du chemin. + \begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics] + \draw[->-] (0,0) -- (1.5cm,1cm); +\end{tikzpicture} + \end{codeexample} +\end{stylekey} + +\begin{stylekey}{/tikz/optics/-<-} + Ce style ajoute une flèche au milieu du chemin, dans le sens opposé à |->-|. + \begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics] + \draw[-<-] (0,0) -- (1.5cm,1cm); +\end{tikzpicture} + \end{codeexample} +\end{stylekey} + +\begin{stylekey}{/tikz/optics/->>-} + Ce style ajoute une double flèche au milieu du chemin. + \begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics] + \draw[->>-] (0,0) -- (1.5cm,1cm); +\end{tikzpicture} + \end{codeexample} +\end{stylekey} + +\begin{stylekey}{/tikz/optics/-<<-} + Ce style ajoute une double flèche au milieu du chemin, dans le sens opposé à |-<<-|. + \begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics] + \draw[-<<-] (0,0) -- (1.5cm,1.1cm); +\end{tikzpicture} + \end{codeexample} +\end{stylekey} + +\begin{stylekey}{/tikz/optics/->n-=\{n=\meta{num}, \meta{specs}\}} + Ce style ajoute \meta{num} flèches au milieu du chemin. Les spécifications \meta{specs} sont appliquées aux flèches, suivant la syntaxe de |put arrow|. + \begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics] + \draw[->n-={n=4}] (0,0) -- (1.5cm,1cm); +\end{tikzpicture} + \end{codeexample} +\end{stylekey} + +\begin{stylekey}{/tikz/optics/-<n-={n=\meta{num}, \meta{specs}}} + Ce style ajoute \meta{num} flèches au milieu du chemin, dans le sens opposé à |->n-|. + \begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics] + \draw[-<n-={n=6}] (0,0) -- (1.5cm,1cm); +\end{tikzpicture} + \end{codeexample} +\end{stylekey} + +Des raccourcis allant de |->-| à |->>>>-| (idem pour |-<-|) sont disponibles. Les styles |->-|, |-<-|, etc. utilisent le style |put arrow| avec la flèche |multiple ray arrow|. Ils peuvent donc être configurés en suivant la syntaxe de |put arrow|, par exemple + +\begin{codeexample}[width=4cm] +\begin{tikzpicture}[use optics] + \draw[->>-={at=0.25}, ->-={at=0.75}] (0,0) -- (1.5cm,1cm) -- (3cm, 0); +\end{tikzpicture} +\end{codeexample} + +Cela marche aussi avec |->n-| et |-<n-|. + +\begin{codeexample}[width=4cm] +\begin{tikzpicture}[use optics] + \draw[->n-={n=5, at=0.2, style=red}] (0,0) -- (1.5cm,1cm); +\end{tikzpicture} +\end{codeexample} + +\subsubsection{Placer des choses sur les chemins} + +\begin{update} + 2014-12-07 : cette partie a été substantiellement modifiée. +\end{update} + +\begin{warning} + Cette partie n'est pas encore stable. Tout risque de changer à tout moment. +\end{warning} + +\begin{key}{/tikz/put arrow} +La clé |put arrow| permet d'ajouter facilement une flèche sur un chemin. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics] + \draw[put arrow] (0,0) -- (1.5cm,1cm); +\end{tikzpicture} +\end{codeexample} + +Par défaut, la flèche est |\arrow{>}| et elle est placée au milieu du chemin. +Pour contrôler ces paramètres, il faut utiliser les sous-clés suivantes : + +\begin{key}{/tikz/put arrow/pos=\meta{pos} (initially \pgfkeysvalueof{/tikz/put arrow/pos})} + Positionne la flèche à la position \meta{pos} sur le chemin (par exemple, \meta{pos}|=0.5| place la flèche au milieu du chemin). +\end{key} + +\begin{key}{/tikz/put arrow/at} + Alias pour |/tikz/put arrow/pos|. +\end{key} + +\begin{key}{/tikz/put arrow/arrow=\meta{arrow specification}} + Utilise la flèche définie par \meta{arrow specification} (par exemple |stealth| ou |latex|). +\end{key} + +\begin{key}{/tikz/put arrow/arrow'=\meta{arrow specification}} + Utilise la flèche définie par \meta{arrow specification} (par exemple |stealth| ou |latex|), mais avec une flèche inversée. +\end{key} + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics] + \draw[put arrow={arrow'=stealth}] (0,0) -- (1cm,1cm); + \draw[put arrow={at=0.2}] (2cm,0) -- (3cm,1cm); +\end{tikzpicture} +\end{codeexample} + +\begin{key}{/tikz/put arrow/style=\meta{style}} + Le |\meta{style}| est passé à |\arrow[|\meta{style}|]| pour dessiner les flèches. +\end{key} + +\begin{codeexample}[width=5cm] +\begin{tikzpicture}[use optics] + \draw[red,put arrow={arrow=latex}] + (0,0) -- (1cm,1cm); + \draw[red,put arrow={arrow=latex,style={blue}}] + (1cm,0) -- (2cm,1cm); +\end{tikzpicture} +\end{codeexample} + +\begin{stylekey}{/tikz/put arrow/every arrow} + Il s'agit d'un style passé à toutes les flèches dessinées par |put arrow| (dans la portée du style). Il faut utiliser |every arrow/.style={|\meta{style}|}| (ou |append style|, etc.). +\end{stylekey} + +\begin{codeexample}[width=3cm] +\begin{tikzpicture}[use optics] + \draw[red,put arrow={arrow=latex}] + (0,0) -- (1cm,1cm); + \draw[red, put arrow/every arrow/.style={blue}, + put arrow={at=0.2}, put arrow={at=0.5}, put arrow={at=0.8}] + (1cm,0) -- (2cm,1cm); + \draw[red, >=latex, put arrow/every arrow/.style={blue}, + put arrow={at=0.2}, put arrow={at=0.5}, put arrow={at=0.8}] + (2cm,0) -- (3cm,1cm); +\end{tikzpicture} +\end{codeexample} + + + +Les différentes flèches utilisables sont détaillées dans le manuel de pgf/tikz. + +Pour un contrôle plus fin, il faut utiliser la bibliothèque tikz |markings|. + +Par ailleurs, pour flécher des rayons lumineux, des styles spécifiques |->-|, |-<-|, |->>-| et |-<<-| ont été définis. + +\end{key} + +\subsubsection{Placer des coordonnées sur les chemins} + +\begin{key}{/tikz/put coordinate=\meta{coordinate} at \meta{position}} + +Le style |put coordinate| crée une coordonnée nommée \meta{coordinate} +à l'abscisse curviligne \meta{position} sur le chemin auquel est appliqué le style. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture}[use optics] + \draw[put coordinate=P at 0.3,put coordinate=Q at 0.7] (0,0) + to[bend left] (2cm,0); + \draw[red] (P) -- (1cm,-1cm); + \draw[blue] (Q) -- (1cm,-1cm); +\end{tikzpicture} +\end{codeexample} + +\end{key} + +\subsubsection{Indiquer des dimensions sur les schémas} + +\begin{warning} + Cette partie est expérimentale et sujette à beaucoup de changements brusques sans préavis. +\end{warning} + +Commençons par un exemple. + +\begin{codeexample}[width=6cm] +\begin{tikzpicture} +\draw[fill=yellow!30] + (-1cm,0) coordinate (A) -- (1cm,0) coordinate (B) + -- (1cm,1.5cm) coordinate (B') -- (0.25cm,2.5cm) coordinate (b) + -- (-0.25cm,2.5cm) coordinate (a) -- (-1cm,1.5cm) coordinate (A') + -- cycle; + +\draw (A) to[dim arrow'={label'=$D$}] (B); +\draw (A) to[dim arrow={label=$H$}] (A'); +\draw (a) to[short dim arrow={label=$d$,label near middle}] (b); +\draw (B') to[dim arrow'={label'=$h$}] (b -| B'); +\end{tikzpicture} +\end{codeexample} + + + +\begin{stylekey}{/tikz/dim arrow=\meta{sous-clés}} + Le style |dim arrow| permet d'indiquer des dimensions sur les schémas. Il s'applique à un |to path|. Par exemple, + + \begin{codeexample}[width=4cm] +\begin{tikzpicture}[use optics] + \node[circle,fill=red,inner sep=2pt] (a) at (0,0) {}; + \node[circle,fill=red,inner sep=2pt] (b) at (2cm,0) {}; + \draw (a.center) to[dim arrow={label=$\ell$}] (b.center); +\end{tikzpicture} + \end{codeexample} + + La flèche de dimension est décalée par rapport aux positions de départ et d'arrivée de manière à ne pas se superposer + à l'objet dont on veut marquer la dimension. + + Plusieurs sous-clés permettent de spécifier des options en écriant |dim arrow={|\meta{sous-clés}|}|. + + \begin{key}{/tikz/dim arrow/label=\meta{text}} + La clé |label| permet de spécifier le \meta{texte} à afficher sur la flèche, qui est positionné à gauche de la flèche par rapport au sens du chemin (via |/tikz/auto=left|). + \end{key} + + \begin{key}{/tikz/dim arrow/label'=\meta{text}} + La clé |label'| a le même rôle que |label|, mais le \meta{texte} est affiché à droite dans le sens du chemin. + \end{key} + + +\begin{codeexample}[] +\begin{tikzpicture} + \node[rectangle, draw=black, fill=yellow!30, minimum width=1cm, minimum height=1cm] (R) at (0,0) {}; + + \draw (R.north east) to[dim arrow'={label'=$\ell'$}] (R.south east); + \draw (R.north east) to[dim arrow'={label=$\ell$}] (R.south east); +\end{tikzpicture} +\end{codeexample} + + \begin{key}{/tikz/dim arrow/label text=\meta{text}} + La clé |label text| permet de spécifier le \meta{texte} à afficher sur la flèche sans modifier son positionnement. + \end{key} + + \begin{stylekey}{/tikz/dim arrow/label style} + La clé |label style| permet de spécifier le style avec lequel le label doit être dessiné. + À moins de le faire exprès, il n'est pas conseillé de remplacer ce style (qui est utilisé pour placer le label), mais plutôt d'y ajouter des spécifications grace à |/.append style|. + +\begin{codeexample}[] +\begin{tikzpicture} + \node[rectangle, draw=black, fill=yellow!30, minimum width=1cm, minimum height=1cm] (R) at (0,0) {}; + + \draw (R.north east) + to[dim arrow={label=$L$, label style/.append style=red}] (R.south east); + \draw (R.north west) + to[dim arrow'={label'=$L$}, red] (R.south west); +\end{tikzpicture} +\end{codeexample} + \end{stylekey} + + \begin{key}{/tikz/dim arrow/raise=\meta{length} (initially \pgfkeysvalueof{/tikz/dim arrow/raise})} + La clé |raise| permet de spécifier la distance \meta{length} à laquelle doit être dessinée la flèche de dimension par rapport au chemin initial. + \begin{codeexample}[] +\begin{tikzpicture} + \node[rectangle, draw=black, fill=yellow!30, minimum width=1cm, minimum height=1cm] (R) at (0,0) {}; + + \draw (R.north east) + to[dim arrow={label=$\ell$, raise=0.5cm}, black] (R.south east); + \draw (R.north east) + to[dim arrow={label=$\ell$, raise=1cm}, red] (R.south east); +\end{tikzpicture} +\end{codeexample} + \end{key} + + \begin{stylekey}{/tikz/dim arrow/no raise} + Équivalent à |raise=0|. (Est-ce bien utile ?) + \end{stylekey} +\end{stylekey} + +\begin{stylekey}{/tikz/dim arrow'=\meta{sous-clés}} + Le style |dim arrow'| a le même rôle que |dim arrow|, mais la valeur initiale de |/tikz/dim arrow/raise| est de |-|\texttt{\pgfkeysvalueof{/tikz/dim arrow/raise}} au lieu de \texttt{\pgfkeysvalueof{/tikz/dim arrow/raise}}. + +\begin{codeexample}[] +\begin{tikzpicture} + \node[rectangle, draw=black, fill=yellow!30, minimum width=1cm, minimum height=1cm] (R) at (0,0) {}; + + \draw (R.north east) to[dim arrow'={label=$\ell$}, black] (R.south east); + \draw (R.north east) to[dim arrow={label=$\ell$}, red] (R.south east); +\end{tikzpicture} +\end{codeexample} +\end{stylekey} + + +\begin{stylekey}{/tikz/short dim arrow=\meta{sous-clés}} + Le style |short dim arrow| a le même but que |dim arrow|, mais dans le cas où la dimension à marquer est petite, et où il faut que les flèches soient à l'extérieur. + + \begin{codeexample}[width=4cm] +\begin{tikzpicture}[use optics] + \node[circle,fill=red,inner sep=2pt] (a) at (0,0) {}; + \node[circle,fill=red,inner sep=2pt] (b) at (1cm,0) {}; + \draw (a.center) + to[short dim arrow={label=$\ell$}] + (b.center); +\end{tikzpicture} + \end{codeexample} + + Les options de |/tikz/dim arrow| s'appliquent, ainsi que quelques options supplémentaires. + + \begin{key}{/tikz/dim arrow/label near start} + La clé |label near start| permet de placer l'étiquette donnant la dimension vers le début du chemin. + C'est le comportement par défaut. + +\begin{codeexample}[] +\begin{tikzpicture} + \node[rectangle, draw=black, fill=yellow!30, minimum width=1cm, minimum height=0.5cm] (R) at (0,0) {}; + + \draw (R.north east) to[short dim arrow={label=$\ell$}] (R.south east); +\end{tikzpicture} +\end{codeexample} + \end{key} + + \begin{key}{/tikz/dim arrow/label near end} + La clé |label near end| permet de placer l'étiquette donnant la dimension vers la fin du chemin. + +\begin{codeexample}[] +\begin{tikzpicture} + \node[rectangle, draw=black, fill=yellow!30, minimum width=1cm, minimum height=0.5cm] (R) at (0,0) {}; + + \draw (R.north east) + to[short dim arrow={label=$\ell$, label near end}] (R.south east); +\end{tikzpicture} +\end{codeexample} + \end{key} + + \begin{key}{/tikz/dim arrow/label near middle} + La clé |label near middle| permet de placer l'étiquette donnant la dimension vers le milieu du chemin. + Dans ce cas, l'étiquette n'est pas décalée par rapport à la flèche (parce qu'il n'y a pas de superposition) ; cela peut être rétabli en spécifiant |/tikz/dim arrow/label style| explicitement. + +\begin{codeexample}[] +\begin{tikzpicture} + \node[rectangle, draw=black, fill=yellow!30, minimum width=1cm, minimum height=0.5cm] (R) at (0,0) {}; + + \draw (R.north east) + to[short dim arrow={label=$\ell$, label near middle}] (R.south east); +\end{tikzpicture} +\end{codeexample} + \end{key} + + + + \begin{key}{/tikz/dim arrow/arrow length=\meta{length} (initially \pgfkeysvalueof{/tikz/dim arrow/arrow length})} + La clé |arrow length| permet spécifier la taille \meta{length} des flèches extérieures. + \end{key} +\end{stylekey} + +\begin{stylekey}{/tikz/short dim arrow'=\meta{sous-clés}} + Le style |short dim arrow'| a le même rôle que |short dim arrow|, mais la valeur initiale de |/tikz/dim arrow/raise| est de |-0.5cm| au lieu de |0.5cm|. + + \begin{codeexample}[width=4cm] +\begin{tikzpicture}[use optics] + \coordinate (a) at (0,0); + \coordinate (b) at (1cm,0); + \draw[red,mark=x, draw=none] plot coordinates {(a) (b)}; + \draw (a.center) to[short dim arrow, blue] (b.center); + \draw (a.center) to[short dim arrow', red] (b.center); +\end{tikzpicture} + \end{codeexample} +\end{stylekey} + +\section{Remerciements} + +Je remercie les collègues et amis qui ont essuyé les plâtres en utilisant les premières versions de cette bibliothèque, et en particulier les auteurs du livre \emph{Physique expérimentale}\footnote{\url{http://www.physique-experimentale.com/}} pour lequel la bibliothèque a été développée. + + +\end{document}
\ No newline at end of file diff --git a/Master/texmf-dist/tex/latex/tikz-optics/tikzlibraryoptics.code.tex b/Master/texmf-dist/tex/latex/tikz-optics/tikzlibraryoptics.code.tex new file mode 100644 index 00000000000..e542a9ee86f --- /dev/null +++ b/Master/texmf-dist/tex/latex/tikz-optics/tikzlibraryoptics.code.tex @@ -0,0 +1,2492 @@ +\iffalse +The tikzoptics library + +Copyright (C) 2013-2016 by + Michel Fruchart <michel.fruchart@ens-lyon.org> + +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 + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% 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. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +\usetikzlibrary{decorations,decorations.pathreplacing} + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% 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
\ No newline at end of file |