% pgf-interference.sty
% LaTeX package for simulating interference patterns
% Author: K. Wehr
% Version 0.1
% 9th January 2022
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License, either version 1.3
% of this license or (at your option) any later version.
% The latest version of this license is in
%
http://www.latex-project.org/lppl.txt
% and version 1.3 or later is part of all distributions of LaTeX
% version 2005/12/01 or later.
%
\ProvidesExplPackage {pgf-interference} {2022-01-09} {0.1} {simulating interference patterns}
\RequirePackage {tikz}
\bool_new:N \g_pgfinterference_draft_bool
\int_new:N \l_pgfinterference_slits_int % Anzahl der Spalte
\fp_new:N \l_pgfinterference_wavelength_fp % Wellenlänge
\fp_new:N \l_pgfinterference_slit_distance_fp % Spaltabstand (in m)
\fp_new:N \l_pgfinterference_slit_width_fp % Spaltbreite (in m)
\fp_new:N \l_pgfinterference_h_fp % Hilfsgröße (in 1/m)
\fp_new:N \l_pgfinterference_hb_fp % Hilfsgröße (dimensionslos)
\fp_new:N \l_pgfinterference_hs_fp % Hilfsgröße (dimensionslos)
\fp_new:N \l_pgfinterference_x_fp % Position auf dem Schirm (in m)
\fp_new:N \l_pgfinterference_screen_distance_fp % Schirmabstand (in m)
\fp_new:N \l_pgfinterference_screen_width_fp % Schirmbreite (in m)
\fp_new:N \l_pgfinterference_screen_height_fp % Schirmhöhe (in m)
\fp_new:N \l_pgfinterference_screen_scale_fp % Skalierung
\fp_new:N \l_pgfinterference_i_fp % relative Intensität innerhalb des Musters
\fp_new:N \l_pgfinterference_i_scale_fp % Skalierung der Intensität
\str_new:N \l_pgfinterference_ruler_type_str
\tl_const:Nn \c_pgfinterference_ruler_unity_tl { \fontsize{9}{9} \upshape \sffamily cm }
\tl_const:Nn \c_pgfinterference_ruler_tick_format_tl { \fontsize{9}{9} \upshape \sffamily }
\dim_new:N \l_pgfinterference_screen_width_dim % Schirmbreite in der Abbildung
\dim_new:N \l_pgfinterference_screen_height_dim % Schirmhöhe in der Abbildung
\dim_new:N \l_pgfinterference_ruler_height_dim % Höhe des Lineals in der Abbildung
\dim_new:N \l_pgfinterference_ruler_ticklength_i_dim % Länge eines langen Skalenstrichs auf dem Lineal
\dim_new:N \l_pgfinterference_ruler_ticklength_ii_dim % Länge eines mittleren Skalenstrichs auf dem Lineal
\dim_new:N \l_pgfinterference_ruler_ticklength_iii_dim % Länge eines kurzen Skalenstrichs auf dem Lineal
\dim_new:N \l_pgfinterference_ruler_linewidth_dim % Strichstärke der Linealskala in der Abbildung
\dim_const:Nn \c_pgfinterference_delta_dim {0.2pt} % Größe eines Bildpunkts
\msg_new:nnn {pgf-interference} {non-positive number}
{
The~value~of~#1~must~be~positive~ \msg_line_context: .
}
\msg_new:nnn {pgf-interference} {wavelength too big}
{
The~wavelength~is~greater~than~1~metre~ \msg_line_context: .~
Radio~waves~are~not~supported!
}
\msg_new:nnn {pgf-interference} {slit width too big}
{
The~slit~width~is~greater~than~the~slit~distance~ \msg_line_context: .~
This~is~not~possible!
}
\int_set:Nn \l_pgfinterference_slits_int {2}
\fp_set:Nn \l_pgfinterference_wavelength_fp {632.8e-9}
\fp_set:Nn \l_pgfinterference_slit_width_fp {1e-5}
\fp_set:Nn \l_pgfinterference_slit_distance_fp {1e-4}
\fp_set:Nn \l_pgfinterference_screen_distance_fp {1}
\fp_set:Nn \l_pgfinterference_screen_width_fp {0.1}
\fp_set:Nn \l_pgfinterference_screen_height_fp {0.03}
\fp_set:Nn \l_pgfinterference_screen_scale_fp {1}
\fp_set:Nn \l_pgfinterference_i_scale_fp {1}
\str_set:Nn \l_pgfinterference_ruler_type_str {none}
\colorlet {pgfinterferencescreencolor} {black}
% Paketoption
\DeclareOption {draft}
{
\bool_gset_true:N \g_pgfinterference_draft_bool
}
\ProcessOptions
% Optionen für das Licht
\keys_define:nn {pgf-interference}
{
wavelength .value_required:n = true ,
wavelength .code:n =
{
\fp_compare:nNnTF {#1} > {0}
{
\fp_set:Nn \l_pgfinterference_wavelength_fp {#1}
}
{
\msg_warning:nnn {pgf-interference} {non-positive number} {wavelength}
}
} ,
intensity .value_required:n = true ,
intensity .code:n =
{
\fp_compare:nNnTF {#1} > {0}
{
\fp_set:Nn \l_pgfinterference_i_scale_fp {#1}
}
{
\msg_warning:nnn {pgf-interference} {non-positive number} {intensity}
}
}
}
% Optionen für das Beugungsobjekt
\keys_define:nn {pgf-interference}
{
slits .value_required:n = true ,
slits .code:n =
{
\int_compare:nNnTF {#1} > {0}
{
\int_set:Nn \l_pgfinterference_slits_int {#1}
}
{
\msg_warning:nnn {pgf-interference} {non-positive number} {slits}
}
} ,
slit-distance .value_required:n = true ,
slit-distance .code:n =
{
\fp_compare:nNnTF {#1} > {0}
{
\fp_set:Nn \l_pgfinterference_slit_distance_fp {#1}
}
{
\msg_warning:nnn {pgf-interference} {non-positive number} {slit-distance}
}
} ,
slit-width .value_required:n = true ,
slit-width .code:n =
{
\fp_compare:nNnTF {#1} > {0}
{
\fp_set:Nn \l_pgfinterference_slit_width_fp {#1}
}
{
\msg_warning:nnn {pgf-interference} {non-positive number} {slit-width}
}
}
}
% Optionen für den Schirm
\keys_define:nn {pgf-interference}
{
screen-distance .value_required:n = true ,
screen-distance .code:n =
{
\fp_compare:nNnTF {#1} > {0}
{
\fp_set:Nn \l_pgfinterference_screen_distance_fp {#1}
}
{
\msg_warning:nnn {pgf-interference} {non-positive number} {screen-distance}
}
} ,
screen-width .value_required:n = true ,
screen-width .code:n =
{
\fp_compare:nNnTF {#1} > {0}
{
\fp_set:Nn \l_pgfinterference_screen_width_fp {#1}
}
{
\msg_warning:nnn {pgf-interference} {non-positive number} {screen-width}
}
} ,
screen-height .value_required:n = true ,
screen-height .code:n =
{
\fp_compare:nNnTF {#1} > {0}
{
\fp_set:Nn \l_pgfinterference_screen_height_fp {#1}
}
{
\msg_warning:nnn {pgf-interference} {non-positive number} {screen-height}
}
} ,
screen-color .value_required:n = true ,
screen-color .code:n = { \colorlet {pgfinterferencescreencolor} {#1} } ,
scale .value_required:n = true ,
scale .code:n =
{
\fp_compare:nNnTF {#1} > {0}
{
\fp_set:Nn \l_pgfinterference_screen_scale_fp {#1}
}
{
\msg_warning:nnn {pgf-interference} {non-positive number} {scale}
}
}
}
% Optionen für das Lineal
\keys_define:nn {pgf-interference}
{
ruler .choices:nn = { above , below , screen , none }
{
\str_set:Nn \l_pgfinterference_ruler_type_str {#1}
} ,
ruler .default:n = {below}
}
\cs_new:Nn \pgfinterference_prepare_ruler:
{
\dim_set:Nn \l_pgfinterference_ruler_height_dim
{
\fp_eval:n { \l_pgfinterference_screen_scale_fp * 1.2 } cm
}
\dim_set:Nn \l_pgfinterference_ruler_ticklength_i_dim
{
\fp_eval:n { \l_pgfinterference_screen_scale_fp * 5 } mm
}
\dim_set:Nn \l_pgfinterference_ruler_ticklength_ii_dim
{
\fp_eval:n { \l_pgfinterference_screen_scale_fp * 4 } mm
}
\dim_set:Nn \l_pgfinterference_ruler_ticklength_iii_dim
{
\fp_eval:n { \l_pgfinterference_screen_scale_fp * 3 } mm
}
\dim_set:Nn \l_pgfinterference_ruler_linewidth_dim
{
\fp_eval:n { \l_pgfinterference_screen_scale_fp * 0.15 } mm
}
}
\cs_new:Nn \pgfinterference_draw_ruler:
{
\str_if_eq:VnTF \l_pgfinterference_ruler_type_str {above}
{
\draw [ line~width = \l_pgfinterference_ruler_linewidth_dim ]
( 0.5 \l_pgfinterference_screen_width_dim , 0.5 \l_pgfinterference_screen_height_dim )
-- ++ ( - \l_pgfinterference_screen_width_dim , 0 ) -- ++ ( 0 , \l_pgfinterference_ruler_height_dim )
node [ below~right , scale = \fp_use:N \l_pgfinterference_screen_scale_fp ] { \c_pgfinterference_ruler_unity_tl }
-- ++ ( \l_pgfinterference_screen_width_dim , 0 ) -- cycle ;
}
{
\str_if_eq:VnTF \l_pgfinterference_ruler_type_str {below}
{
\draw [ line~width = \l_pgfinterference_ruler_linewidth_dim ]
( 0.5 \l_pgfinterference_screen_width_dim , -0.5 \l_pgfinterference_screen_height_dim )
-- ++ ( - \l_pgfinterference_screen_width_dim , 0 ) -- ++ ( 0 , - \l_pgfinterference_ruler_height_dim )
node [ above~right , scale = \fp_use:N \l_pgfinterference_screen_scale_fp ] { \c_pgfinterference_ruler_unity_tl }
-- ++ ( \l_pgfinterference_screen_width_dim , 0 ) -- cycle ;
}
{
\draw [ line~width = \l_pgfinterference_ruler_linewidth_dim ]
( 0.5 \l_pgfinterference_screen_width_dim , 0.5 \l_pgfinterference_screen_height_dim )
-- ++ ( - \l_pgfinterference_screen_width_dim , 0 ) -- ++ ( 0 , - \l_pgfinterference_ruler_height_dim )
node [ above~right , scale = \fp_use:N \l_pgfinterference_screen_scale_fp ] { \c_pgfinterference_ruler_unity_tl }
-- ++ ( \l_pgfinterference_screen_width_dim , 0 ) -- cycle ;
}
}
\int_set:Nn \l_tmpa_int { \fp_eval:n { floor ( 1000 * \l_pgfinterference_screen_width_fp ) - 1 } }
\int_step_inline:nnn {1} { \l_tmpa_int }
{
\dim_set:Nn \l_tmpa_dim { \fp_eval:n { \l_pgfinterference_screen_scale_fp * ##1 } mm }
\dim_sub:Nn \l_tmpa_dim { 0.5 \l_pgfinterference_screen_width_dim }
\int_compare:nNnTF { \int_mod:nn {##1} {10} } = {0}
{
\str_if_eq:VnTF \l_pgfinterference_ruler_type_str {above}
{
\draw [ line~width = \l_pgfinterference_ruler_linewidth_dim ]
( \l_tmpa_dim , 0.5 \l_pgfinterference_screen_height_dim )
-- ++ ( 0 , \l_pgfinterference_ruler_ticklength_i_dim )
node [ above , scale = \fp_use:N \l_pgfinterference_screen_scale_fp ]
{ \c_pgfinterference_ruler_tick_format_tl \int_eval:n {##1/10} } ;
}
{
\str_if_eq:VnTF \l_pgfinterference_ruler_type_str {below}
{
\draw [ line~width = \l_pgfinterference_ruler_linewidth_dim ]
( \l_tmpa_dim , -0.5 \l_pgfinterference_screen_height_dim )
-- ++ ( 0 , - \l_pgfinterference_ruler_ticklength_i_dim )
node [ below , scale = \fp_use:N \l_pgfinterference_screen_scale_fp ]
{ \c_pgfinterference_ruler_tick_format_tl \int_eval:n {##1/10} } ;
}
{
\draw [ line~width = \l_pgfinterference_ruler_linewidth_dim ]
( \l_tmpa_dim , 0.5 \l_pgfinterference_screen_height_dim )
-- ++ ( 0 , - \l_pgfinterference_ruler_ticklength_i_dim )
node [ below , scale = \fp_use:N \l_pgfinterference_screen_scale_fp ]
{ \c_pgfinterference_ruler_tick_format_tl \int_eval:n {##1/10} } ;
}
}
}
{
\int_compare:nNnTF { \int_mod:nn {##1} {5} } = {0}
{
\str_if_eq:VnTF \l_pgfinterference_ruler_type_str {above}
{
\draw [ line~width = \l_pgfinterference_ruler_linewidth_dim ]
( \l_tmpa_dim , 0.5 \l_pgfinterference_screen_height_dim )
-- ++ ( 0 , \l_pgfinterference_ruler_ticklength_ii_dim ) ;
}
{
\str_if_eq:VnTF \l_pgfinterference_ruler_type_str {below}
{
\draw [ line~width = \l_pgfinterference_ruler_linewidth_dim ]
( \l_tmpa_dim , -0.5 \l_pgfinterference_screen_height_dim )
-- ++ ( 0 , - \l_pgfinterference_ruler_ticklength_ii_dim ) ;
}
{
\draw [ line~width = \l_pgfinterference_ruler_linewidth_dim ]
( \l_tmpa_dim , 0.5 \l_pgfinterference_screen_height_dim )
-- ++ ( 0 , - \l_pgfinterference_ruler_ticklength_ii_dim ) ;
}
}
}
{
\str_if_eq:VnTF \l_pgfinterference_ruler_type_str {above}
{
\draw [ line~width = \l_pgfinterference_ruler_linewidth_dim ]
( \l_tmpa_dim , 0.5 \l_pgfinterference_screen_height_dim )
-- ++ ( 0 , \l_pgfinterference_ruler_ticklength_iii_dim ) ;
}
{
\str_if_eq:VnTF \l_pgfinterference_ruler_type_str {below}
{
\draw [ line~width = \l_pgfinterference_ruler_linewidth_dim ]
( \l_tmpa_dim , -0.5 \l_pgfinterference_screen_height_dim )
-- ++ ( 0 , - \l_pgfinterference_ruler_ticklength_iii_dim ) ;
}
{
\draw [ line~width = \l_pgfinterference_ruler_linewidth_dim ]
( \l_tmpa_dim , 0.5 \l_pgfinterference_screen_height_dim )
-- ++ ( 0 , - \l_pgfinterference_ruler_ticklength_iii_dim ) ;
}
}
}
}
}
}
\cs_new:Nn \pgfinterference_draw_pattern:
{
\dim_step_inline:nnnn { -0.5 \l_pgfinterference_screen_width_dim + 0.5 \c_pgfinterference_delta_dim }
{ \c_pgfinterference_delta_dim } { 0.5 \l_pgfinterference_screen_width_dim }
{
\fp_set:Nn \l_pgfinterference_x_fp { \dim_ratio:nn {##1} {100cm} / \l_pgfinterference_screen_scale_fp }
\fp_set:Nn \l_pgfinterference_h_fp
{
pi / \l_pgfinterference_wavelength_fp
/ sqrt ( ( \l_pgfinterference_screen_distance_fp / \l_pgfinterference_x_fp ) ^ 2 + 1 )
}
\fp_set:Nn \l_pgfinterference_hb_fp { \l_pgfinterference_slit_width_fp * \l_pgfinterference_h_fp }
\fp_set:Nn \l_pgfinterference_hs_fp { \l_pgfinterference_slit_distance_fp * \l_pgfinterference_h_fp }
\fp_set:Nn \l_pgfinterference_i_fp
{
( sin ( \l_pgfinterference_hb_fp ) / \l_pgfinterference_hb_fp
* sin ( \l_pgfinterference_slits_int * \l_pgfinterference_hs_fp ) / sin ( \l_pgfinterference_hs_fp )
/ \l_pgfinterference_slits_int ) ^ 2
}
\int_set:Nn \l_tmpa_int
{
\fp_eval:n { round ( 100 * \l_pgfinterference_i_fp * \l_pgfinterference_i_scale_fp ) }
}
\int_compare:nNnTF { \l_tmpa_int } < {100}
{
\colorlet {pgfinterferencecolor}
{
pgfinterferencelasercolor
! \int_use:N \l_tmpa_int
! pgfinterferencescreencolor
}
}
{
\colorlet {pgfinterferencecolor} {pgfinterferencelasercolor}
}
\dim_set:Nn \l_tmpa_dim { ##1 - 0.5 \c_pgfinterference_delta_dim }
\fill [ pgfinterferencecolor ] ( \l_tmpa_dim , -0.5 \l_pgfinterference_screen_height_dim )
rectangle ++ ( \c_pgfinterference_delta_dim , \l_pgfinterference_screen_height_dim ) ;
}
}
\NewDocumentCommand \pgfinterferenceoptions {m}
{
\keys_set:nn {pgf-interference} {#1}
}
\NewDocumentCommand \pgfinterferencepattern {m}
{
\group_begin:
\keys_set:nn {pgf-interference} {#1}
\selectcolormodel {rgb}
\fp_compare:nNnTF { \l_pgfinterference_wavelength_fp * 1e9 } < {1000}
{
\definecolor {pgfinterferencelasercolor} {wave}
{
\fp_eval:n { \l_pgfinterference_wavelength_fp * 1e9 }
}
}
{
\colorlet {pgfinterferencelasercolor} {black}
}
\dim_set:Nn \l_pgfinterference_screen_width_dim
{
\fp_eval:n { 100 * \l_pgfinterference_screen_scale_fp * \l_pgfinterference_screen_width_fp } cm
}
\str_if_eq:VnF \l_pgfinterference_ruler_type_str {none}
{
\pgfinterference_prepare_ruler:
}
\str_if_eq:VnTF \l_pgfinterference_ruler_type_str {screen}
{
\colorlet {pgfinterferencescreencolor} {white}
\dim_set_eq:NN \l_pgfinterference_screen_height_dim \l_pgfinterference_ruler_height_dim
}
{
\dim_set:Nn \l_pgfinterference_screen_height_dim
{
\fp_eval:n { 100 * \l_pgfinterference_screen_scale_fp * \l_pgfinterference_screen_height_fp } cm
}
}
\begin {tikzpicture}
\extractcolorspec {pgfinterferencescreencolor} \pgfinterference_tmpa:
\extractcolorspec {white} \pgfinterference_tmpb:
\bool_lazy_and:nnTF { ! \str_if_eq_p:Vn \l_pgfinterference_ruler_type_str {screen} }
{ \cs_if_eq_p:NN \pgfinterference_tmpa: \pgfinterference_tmpb: }
{
\draw [ fill = pgfinterferencescreencolor ]
( -0.5 \l_pgfinterference_screen_width_dim , -0.5 \l_pgfinterference_screen_height_dim )
rectangle ( 0.5 \l_pgfinterference_screen_width_dim , 0.5 \l_pgfinterference_screen_height_dim ) ;
}
{
\fill [ pgfinterferencescreencolor ]
( -0.5 \l_pgfinterference_screen_width_dim , -0.5 \l_pgfinterference_screen_height_dim )
rectangle ( 0.5 \l_pgfinterference_screen_width_dim , 0.5 \l_pgfinterference_screen_height_dim ) ;
}
\fp_compare:nNnTF { \l_pgfinterference_wavelength_fp } > {1}
{
\msg_warning:nn {pgf-interference} {wavelength too big}
}
{
\fp_compare:nNnTF { \l_pgfinterference_slit_width_fp } > { \l_pgfinterference_slit_distance_fp }
{
\msg_warning:nn {pgf-interference} {slit width too big}
}
{
\bool_if:NF \g_pgfinterference_draft_bool { \pgfinterference_draw_pattern: }
}
}
\str_if_eq:VnF \l_pgfinterference_ruler_type_str {none}
{
\pgfinterference_draw_ruler:
}
\end {tikzpicture}
\group_end:
}