From 28186c340f96ee3b31cd8047e8d20081596943e0 Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Mon, 1 Aug 2022 20:22:41 +0000 Subject: bodeplot (1aug22) git-svn-id: svn://tug.org/texlive/trunk@64022 c570f23f-e606-0410-a88d-b1316a301751 --- Master/texmf-dist/tex/latex/bodeplot/bodeplot.sty | 1022 ++++++++++++--------- 1 file changed, 601 insertions(+), 421 deletions(-) (limited to 'Master/texmf-dist/tex') diff --git a/Master/texmf-dist/tex/latex/bodeplot/bodeplot.sty b/Master/texmf-dist/tex/latex/bodeplot/bodeplot.sty index 8ffc111abfb..0fdbc3bcb23 100644 --- a/Master/texmf-dist/tex/latex/bodeplot/bodeplot.sty +++ b/Master/texmf-dist/tex/latex/bodeplot/bodeplot.sty @@ -22,56 +22,52 @@ \pgfplotsset{compat=1.18} \usepgfplotslibrary{groupplots} -\RequirePackage{ifluatex}% -\ifluatex - \let\pdfstrcmp\pdf@strcmp -\fi \newif\if@pgfarg\@pgfargfalse -\DeclareOption{pgf}{% +\DeclareOption{pgf}{ \@pgfargtrue } \newif\if@declutterarg\@declutterargfalse -\DeclareOption{declutter}{% +\DeclareOption{declutter}{ \@declutterargtrue } \newif\if@radarg\@radargfalse -\DeclareOption{rad}{% +\DeclareOption{rad}{ \@radargtrue } +\newif\if@hzarg\@hzargfalse +\DeclareOption{Hz}{ + \@hzargtrue +} \ProcessOptions\relax \newcommand{\n@mod}[2]{(#1)-(floor((#1)/(#2))*(#2))} \if@pgfarg \newcommand{\n@pow}[2]{(#1)^(#2)} - \pgfplotsset{% - trig format plots=rad% + \pgfplotsset{ + trig format plots=rad } \else \newcommand{\n@pow}[2]{(#1)**(#2)} \newcounter{gnuplot@id} \setcounter{gnuplot@id}{0} \if@declutterarg - \tikzset{% - gnuplot@prefix/.style={% - id=\arabic{gnuplot@id}, - prefix=gnuplot/\jobname - }% - } + \edef\bodeplot@prefix{gnuplot/\jobname} \else - \tikzset{% - gnuplot@prefix/.style={% - id=\arabic{gnuplot@id}, - prefix=\jobname - }% - } + \edef\bodeplot@prefix{\jobname} \fi + \tikzset{ + gnuplot@prefix/.style={ + id=\arabic{gnuplot@id}, + prefix=\bodeplot@prefix + } + } \ifwindows\else \if@declutterarg \immediate\write18{mkdir -p gnuplot} \fi \fi \fi -\pgfplotsset{% - bode@style/.style = {% +\pgfplotsset{ + bode@style/.style = { label style={font=\footnotesize}, tick label style={font=\footnotesize}, grid=both, @@ -82,23 +78,66 @@ scale only axis, samples=200, width=5cm, - }% + log basis x=10 + } } +\pgfplotsset{freq@filter/.style = {}} +\def\freq@scale{1} +\pgfplotsset{freq@label/.style = {xlabel = {Frequency (rad/s)}}} +\pgfplotsset{ph@x@label/.style = {xlabel={Phase (deg)}}} +\pgfplotsset{ph@y@label/.style = {ylabel={Phase (deg)}}} +\def\ph@scale{180/pi} \if@radarg - \pgfplotsset{ph@filter/.style = {ytick distance=pi/4, ylabel={Phase (rad)}}}% - \pgfplotsset{ph@x@filter/.style = {xlabel={Phase (rad)}}}% -\else - \pgfplotsset{ph@filter/.style = {y filter/.expression={y*180/pi}, ytick distance=45, ylabel={Phase (deg)}}}% - \pgfplotsset{ph@x@filter/.style = {x filter/.expression={x*180/pi}, xlabel={Phase (deg)}}}% + \pgfplotsset{ph@y@label/.style = {ylabel={Phase (rad)}}} + \pgfplotsset{ph@x@label/.style = {xlabel={Phase (rad)}}} + \def\ph@scale{1} +\fi +\if@hzarg + \def\freq@scale{2*pi} + \pgfplotsset{freq@label/.style = {xlabel = {Frequency (Hz)}}} + \if@pgfarg + \pgfplotsset{freq@filter/.style = {x filter/.expression={x-log10(2*pi)}}} + \fi \fi +\tikzset{ + phase unit/.initial={deg}, + phase unit/.default={deg}, + phase unit/.is choice, + phase unit/deg/.code={ + \renewcommand{\ph@scale}{180/pi} + \pgfplotsset{ph@x@label/.style = {xlabel={Phase (deg)}}} + \pgfplotsset{ph@y@label/.style = {ylabel={Phase (deg)}}} + }, + phase unit/rad/.code={ + \renewcommand{\ph@scale}{1} + \pgfplotsset{ph@y@label/.style = {ylabel={Phase (rad)}}} + \pgfplotsset{ph@x@label/.style = {xlabel={Phase (rad)}}} + }, + frequency unit/.initial={rad}, + frequency unit/.default={rad}, + frequency unit/.is choice, + frequency unit/Hz/.code={ + \renewcommand{\freq@scale}{2*pi} + \pgfplotsset{freq@label/.style = {xlabel = {Frequency (Hz)}}} + \if@pgfarg + \pgfplotsset{freq@filter/.style = {x filter/.expression={x-log10(2*pi)}}} + \fi + }, + frequency unit/rad/.code={ + \renewcommand{\freq@scale}{1} + \pgfplotsset{freq@label/.style = {xlabel = {Frequency (rad/s)}}} + } +} +\def\get@interval@start#1:#2\@nil{#1} +\def\get@interval@end#1:#2\@nil{#2} \newcommand*{\MagK}[2]{(20*log10(abs(#1)))} \newcommand*{\MagKAsymp}{\MagK} \newcommand*{\MagKLin}{\MagK} -\newcommand*{\PhK}[2]{(#1<0?-pi:0)} +\newcommand*{\PhK}[2]{((#1<0?-pi:0)*\ph@scale)} \newcommand*{\PhKAsymp}{\PhK} \newcommand*{\PhKLin}{\PhK} \newcommand*{\MagDel}[2]{0} -\newcommand*{\PhDel}[2]{-#1*t} +\newcommand*{\PhDel}[2]{(-#1*t*\ph@scale)} \newcommand*{\MagPole}[2] {(-20*log10(sqrt(\n@pow{#1}{2} + \n@pow{t - (#2)}{2})))} \newcommand*{\MagPoleLin}[2]{(t < sqrt(\n@pow{#1}{2} + \n@pow{#2}{2}) ? @@ -106,12 +145,12 @@ -20*log10(t) )} \newcommand*{\MagPoleAsymp}{\MagPoleLin} -\newcommand*{\PhPole}[2]{(#1 > 0 ? (#2 > 0 ? +\newcommand*{\PhPole}[2]{((#1 > 0 ? (#2 > 0 ? (\n@mod{-atan2((t - (#2)),-(#1))}{2*pi}) : (-atan2((t - (#2)),-(#1)))) : - (-atan2((t - (#2)),-(#1))))} -\newcommand*{\PhPoleLin}[2]{% - (abs(#1)+abs(#2) == 0 ? -pi/2 : + (-atan2((t - (#2)),-(#1))))*\ph@scale)} +\newcommand*{\PhPoleLin}[2]{ + ((abs(#1)+abs(#2) == 0 ? -pi/2 : (t < (sqrt(\n@pow{#1}{2} + \n@pow{#2}{2}) / (\n@pow{10}{sqrt(\n@pow{#1}{2}/(\n@pow{#1}{2} + \n@pow{#2}{2}))})) ? (-atan2(-(#2),-(#1))) : @@ -122,10 +161,10 @@ (\n@pow{10}{sqrt(\n@pow{#1}{2}/(\n@pow{#1}{2} + \n@pow{#2}{2}))}))))*((#2>0?(#1>0?3*pi/2:-pi/2):-pi/2) + atan2(-(#2),-(#1)))/ (log10(\n@pow{10}{sqrt((4*\n@pow{#1}{2})/ - (\n@pow{#1}{2} + \n@pow{#2}{2}))}))))))} -\newcommand*{\PhPoleAsymp}[2]{(t < (sqrt(\n@pow{#1}{2} + \n@pow{#2}{2})) ? + (\n@pow{#1}{2} + \n@pow{#2}{2}))}))))))*\ph@scale)} +\newcommand*{\PhPoleAsymp}[2]{((t < (sqrt(\n@pow{#1}{2} + \n@pow{#2}{2})) ? (-atan2(-(#2),-(#1))) : - (#2>0?(#1>0?3*pi/2:-pi/2):-pi/2))} + (#2>0?(#1>0?3*pi/2:-pi/2):-pi/2))*\ph@scale)} \newcommand*{\MagZero}{0-\MagPole} \newcommand*{\MagZeroLin}{0-\MagPoleLin} \newcommand*{\MagZeroAsymp}{0-\MagPoleAsymp} @@ -136,686 +175,827 @@ - \n@pow{t}{2}}{2} + \n@pow{2*#1*#2*t}{2})))} \newcommand*{\MagCSPolesLin}[2]{(t < #2 ? -40*log10(#2) : - 40*log10(t))} \newcommand*{\MagCSPolesAsymp}{\MagCSPolesLin} -\newcommand*{\PhCSPoles}[2]{(-atan2((2*(#1)*(#2)*t),(\n@pow{#2}{2} - - \n@pow{t}{2})))} -\newcommand*{\PhCSPolesLin}[2]{(t < (#2 / (\n@pow{10}{abs(#1)})) ? +\newcommand*{\PhCSPoles}[2]{((-atan2((2*(#1)*(#2)*t),(\n@pow{#2}{2} + - \n@pow{t}{2})))*\ph@scale)} +\newcommand*{\PhCSPolesLin}[2]{((t < (#2 / (\n@pow{10}{abs(#1)})) ? 0 : (t >= (#2 * (\n@pow{10}{abs(#1)})) ? (#1>0 ? -pi : pi) : (#1>0 ? (-pi*(log10(t*(\n@pow{10}{#1})/#2))/(2*#1)) : - (pi*(log10(t*(\n@pow{10}{abs(#1)})/#2))/(2*abs(#1))))))} -\newcommand*{\PhCSPolesAsymp}[2]{(#1>0?(t<#2?0:-pi):(t<#2?0:pi))} + (pi*(log10(t*(\n@pow{10}{abs(#1)})/#2))/(2*abs(#1))))))*\ph@scale)} +\newcommand*{\PhCSPolesAsymp}[2]{((#1>0?(t<#2?0:-pi):(t<#2?0:pi))*\ph@scale)} \newcommand*{\MagCSZeros}{0-\MagCSPoles} \newcommand*{\MagCSZerosLin}{0-\MagCSPolesLin} \newcommand*{\MagCSZerosAsymp}{0-\MagCSPolesAsymp} \newcommand*{\PhCSZeros}{0-\PhCSPoles} \newcommand*{\PhCSZerosLin}{0-\PhCSPolesLin} \newcommand*{\PhCSZerosAsymp}{0-\PhCSPolesAsymp} -\newcommand*{\MagCSPolesPeak}[3][]{% +\newcommand*{\MagCSPolesPeak}[3][]{ \draw[#1,->] (axis cs:{#3},{-40*log10(#3)}) -- (axis cs:{#3},{-40*log10(#3)-20*log10(2*abs(#2))}) } -\newcommand*{\MagCSZerosPeak}[3][]{% +\newcommand*{\MagCSZerosPeak}[3][]{ \draw[#1,->] (axis cs:{#3},{40*log10(#3)}) -- (axis cs:{#3},{40*log10(#3)+20*log10(2*abs(#2))}) } -\newcommand*{\MagSOPoles}[2]{% +\newcommand*{\MagSOPoles}[2]{ (-20*log10(sqrt(\n@pow{#2 - \n@pow{t}{2}}{2} + \n@pow{#1*t}{2})))} -\newcommand*{\MagSOPolesLin}[2]{% +\newcommand*{\MagSOPolesLin}[2]{ (t < sqrt(abs(#2)) ? -20*log10(abs(#2)) : - 40*log10(t))} \newcommand*{\MagSOPolesAsymp}{\MagSOPolesLin} -\newcommand*{\PhSOPoles}[2]{(-atan2((#1)*t,((#2) - \n@pow{t}{2})))} -\newcommand*{\PhSOPolesLin}[2]{(#2>0 ? +\newcommand*{\PhSOPoles}[2]{((-atan2((#1)*t,((#2) - \n@pow{t}{2})))*\ph@scale)} +\newcommand*{\PhSOPolesLin}[2]{((#2>0 ? \PhCSPolesLin{(#1/(2*sqrt(#2)))}{(sqrt(#2))} : - (#1>0 ? -pi : pi))} -\newcommand*{\PhSOPolesAsymp}[2]{(#2>0 ? + (#1>0 ? -pi : pi))*\ph@scale)} +\newcommand*{\PhSOPolesAsymp}[2]{((#2>0 ? \PhCSPolesAsymp{(#1/(2*sqrt(#2)))}{(sqrt(#2))} : - (#1>0 ? -pi : pi))} + (#1>0 ? -pi : pi))*\ph@scale)} \newcommand*{\MagSOZeros}{0-\MagSOPoles} \newcommand*{\MagSOZerosLin}{0-\MagSOPolesLin} \newcommand*{\MagSOZerosAsymp}{0-\MagSOPolesAsymp} \newcommand*{\PhSOZeros}{0-\PhSOPoles} \newcommand*{\PhSOZerosLin}{0-\PhSOPolesLin} \newcommand*{\PhSOZerosAsymp}{0-\PhSOPolesAsymp} -\newcommand*{\MagSOPolesPeak}[3][]{% +\newcommand*{\MagSOPolesPeak}[3][]{ \draw[#1,->] (axis cs:{sqrt(abs(#3))},{-20*log10(abs(#3))}) -- (axis cs:{sqrt(abs(#3))},{-20*log10(abs(#3)) - 20*log10(abs(#2/sqrt(abs(#3))))}); } -\newcommand*{\MagSOZerosPeak}[3][]{% +\newcommand*{\MagSOZerosPeak}[3][]{ \draw[#1,->] (axis cs:{sqrt(abs(#3))},{20*log10(abs(#3))}) -- (axis cs:{sqrt(abs(#3))},{20*log10(abs(#3)) + 20*log10(abs(#2/sqrt(abs(#3))))}); } -\newcommand{\BodeZPK}[4][approx/true]{% - \parse@opt{#1}% - \gdef\func@mag{}% - \gdef\func@ph{}% - \build@ZPK@plot{\func@mag}{\func@ph}{\opt@approx}{#2}% - \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]% - \noexpand\begin{groupplot}[% +\newcommand{\BodeZPK}[4][approx/true]{ + \parse@opt{#1} + \gdef\func@mag{} + \gdef\func@ph{} + \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]} + \temp@cmd + \build@ZPK@plot{\func@mag}{\func@ph}{\opt@approx}{#2} + \edef\temp@cmd{\noexpand\begin{groupplot}[ bode@style, - xmin={#3}, - xmax={#4}, - domain=#3:#4, + xmin=#3, + xmax=#4, + domain=#3*\freq@scale:#4*\freq@scale, height=2.5cm, xmode=log, group style = {group size = 1 by 2,vertical sep=0.25cm}, \opt@group - ]% - }% - \temp@cmd - \edef\temp@mag@cmd{\noexpand\nextgroupplot[ytick distance=20, ylabel={Gain (dB)}, xmajorticks=false, \optmag@axes] - \noexpand\addplot[variable=t, thick, \optmag@plot]} - \edef\temp@ph@cmd{\noexpand\nextgroupplot[ph@filter, xlabel={Frequency (rad/s)}, \optph@axes] - \noexpand\addplot[variable=t, thick, \optph@plot]} - \if@pgfarg\else - \edef\temp@mag@cmd{\noexpand\stepcounter{gnuplot@id} \unexpanded\expandafter{\temp@mag@cmd} gnuplot[gnuplot@prefix]} - \edef\temp@ph@cmd{\noexpand\stepcounter{gnuplot@id} \unexpanded\expandafter{\temp@ph@cmd} gnuplot[gnuplot@prefix]} + ]} + \temp@cmd + \edef\temp@mag@cmd{\noexpand\nextgroupplot [ylabel={Gain (dB)}, xmajorticks=false, \optmag@axes] + \noexpand\addplot [freq@filter, variable=t, thick, \optmag@plot]} + \edef\temp@ph@cmd{\noexpand\nextgroupplot [ph@y@label, freq@label, \optph@axes] + \noexpand\addplot [freq@filter, variable=t, thick, \optph@plot]} + \if@pgfarg + \temp@mag@cmd {\func@mag}; + \optmag@commands + \temp@ph@cmd {\func@ph}; + \optph@commands + \else + \stepcounter{gnuplot@id} + \temp@mag@cmd gnuplot [raw gnuplot, gnuplot@prefix] + { set table $meta; + set dummy t; + set logscale x 10; + set xrange [#3*\freq@scale:#4*\freq@scale]; + set samples \pgfkeysvalueof{/pgfplots/samples}; + plot \func@mag; + set table "\bodeplot@prefix\arabic{gnuplot@id}.table"; + plot "$meta" using ($1/(\freq@scale)):($2); + }; + \optmag@commands + \stepcounter{gnuplot@id} + \temp@ph@cmd gnuplot [raw gnuplot, gnuplot@prefix] + { set table $meta; + set dummy t; + set logscale x 10; + set xrange [#3*\freq@scale:#4*\freq@scale]; + set samples \pgfkeysvalueof{/pgfplots/samples}; + plot \func@ph; + set table "\bodeplot@prefix\arabic{gnuplot@id}.table"; + plot "$meta" using ($1/(\freq@scale)):($2); + }; + \optph@commands \fi - \temp@mag@cmd {\func@mag}; - \optmag@commands - \temp@ph@cmd {\func@ph}; - \optph@commands \end{groupplot} \end{tikzpicture} } -\newcommand{\BodeTF}[4][]{% - \parse@opt{#1}% - \gdef\func@mag{}% - \gdef\func@ph{}% - \build@TF@plot{\func@mag}{\func@ph}{#2}% - \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]% - \noexpand\begin{groupplot}[% +\newcommand{\BodeTF}[4][]{ + \parse@opt{#1} + \gdef\func@mag{} + \gdef\func@ph{} + \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]} + \temp@cmd + \build@TF@plot{\func@mag}{\func@ph}{#2} + \edef\temp@cmd{\noexpand\begin{groupplot}[ bode@style, - xmin={#3}, - xmax={#4}, - domain=#3:#4, + xmin=#3, + xmax=#4, + domain=#3*\freq@scale:#4*\freq@scale, height=2.5cm, xmode=log, group style = {group size = 1 by 2,vertical sep=0.25cm}, \opt@group - ]% - }% - \temp@cmd - \edef\temp@mag@cmd{\noexpand\nextgroupplot[ytick distance=20, ylabel={Gain (dB)}, xmajorticks=false, \optmag@axes] - \noexpand\addplot[variable=t, thick, \optmag@plot]} - \edef\temp@ph@cmd{\noexpand\nextgroupplot[ph@filter, xlabel={Frequency (rad/s)}, \optph@axes] - \noexpand\addplot[variable=t, thick, \optph@plot]} - \if@pgfarg\else - \edef\temp@mag@cmd{\noexpand\stepcounter{gnuplot@id} \unexpanded\expandafter{\temp@mag@cmd} gnuplot[gnuplot@prefix]} - \edef\temp@ph@cmd{\noexpand\stepcounter{gnuplot@id} \unexpanded\expandafter{\temp@ph@cmd} gnuplot[gnuplot@prefix]} - \fi - \temp@mag@cmd {\func@mag}; - \optmag@commands + ]} + \temp@cmd + \edef\temp@mag@cmd{\noexpand\nextgroupplot [ylabel={Gain (dB)}, xmajorticks=false, \optmag@axes] + \noexpand\addplot [freq@filter, variable=t, thick, \optmag@plot]} + \edef\temp@ph@cmd{\noexpand\nextgroupplot [ph@y@label, freq@label, \optph@axes] + \noexpand\addplot [freq@filter, variable=t, thick, \optph@plot]} \if@pgfarg - \temp@ph@cmd {\n@mod{\func@ph}{2*pi}}; + \temp@mag@cmd {\func@mag}; + \optmag@commands + \temp@ph@cmd {\n@mod{\func@ph}{2*pi*\ph@scale}}; + \optph@commands \else - \temp@ph@cmd {'+' using (t):\func@ph smooth unwrap}; + \stepcounter{gnuplot@id} + \temp@mag@cmd gnuplot [raw gnuplot, gnuplot@prefix] + { set table $meta; + set dummy t; + set logscale x 10; + set xrange [#3*\freq@scale:#4*\freq@scale]; + set samples \pgfkeysvalueof{/pgfplots/samples}; + plot \func@mag; + set table "\bodeplot@prefix\arabic{gnuplot@id}.table"; + plot "$meta" using ($1/(\freq@scale)):($2); + }; + \optmag@commands + \stepcounter{gnuplot@id} + \temp@ph@cmd gnuplot [raw gnuplot, gnuplot@prefix] + { set table $meta; + set dummy t; + set logscale x 10; + set trange [#3*\freq@scale:#4*\freq@scale]; + set samples \pgfkeysvalueof{/pgfplots/samples}; + plot '+' using (t) : ((\func@ph)/(\ph@scale)) smooth unwrap; + set table "\bodeplot@prefix\arabic{gnuplot@id}.table"; + plot "$meta" using ($1/(\freq@scale)):($2*\ph@scale); + }; + \optph@commands \fi - \optph@commands \end{groupplot} \end{tikzpicture} } -\newcommand{\addBodeZPKPlots}[3][true/{}]{% - \foreach \approx/\opt in {#1} {% - \gdef\plot@macro{}% - \gdef\temp@macro{}% - \ifnum\pdfstrcmp{#2}{phase}=0 - \build@ZPK@plot{\temp@macro}{\plot@macro}{\approx}{#3}% +\newcommand{\addBodeZPKPlots}[3][true/{}]{ + \foreach \approx/\opt in {#1} { + \gdef\plot@macro{} + \gdef\temp@macro{} + \ifnum\pdf@strcmp{#2}{phase}=0 + \build@ZPK@plot{\temp@macro}{\plot@macro}{\approx}{#3} \else - \build@ZPK@plot{\plot@macro}{\temp@macro}{\approx}{#3}% + \build@ZPK@plot{\plot@macro}{\temp@macro}{\approx}{#3} \fi + \edef\supplied@domain{\pgfkeysvalueof{/pgfplots/domain}} + \edef\domain@start{\expandafter\get@interval@start\supplied@domain\@nil} + \edef\domain@end{\expandafter\get@interval@end\supplied@domain\@nil} \if@pgfarg - \edef\temp@cmd{\noexpand\addplot[variable=t,thick,\opt]}% + \edef\temp@cmd{\noexpand\addplot [freq@filter, domain=\domain@start*\freq@scale:\domain@end*\freq@scale, variable=t, thick, \opt]} \temp@cmd {\plot@macro}; \else - \stepcounter{gnuplot@id}% - \edef\temp@cmd{\noexpand\addplot[variable=t,thick,\opt]} - \temp@cmd gnuplot[gnuplot@prefix] {\plot@macro}; + \stepcounter{gnuplot@id} + \edef\temp@cmd{\noexpand\addplot [variable=t, thick, \opt]} + \temp@cmd gnuplot [raw gnuplot, gnuplot@prefix] + { set table $meta; + set dummy t; + set logscale x 10; + set xrange [\domain@start*\freq@scale:\domain@end*\freq@scale]; + set samples \pgfkeysvalueof{/pgfplots/samples}; + plot \plot@macro; + set table "\bodeplot@prefix\arabic{gnuplot@id}.table"; + plot "$meta" using ($1/(\freq@scale)):($2); + }; \fi - }% + } } -\newcommand{\addBodeTFPlot}[3][thick]{% - \gdef\plot@macro{}% - \gdef\temp@macro{}% - \ifnum\pdfstrcmp{#2}{phase}=0 - \build@TF@plot{\temp@macro}{\plot@macro}{#3}% +\newcommand{\addBodeTFPlot}[3][thick]{ + \gdef\plot@macro{} + \gdef\temp@macro{} + \ifnum\pdf@strcmp{#2}{phase}=0 + \build@TF@plot{\temp@macro}{\plot@macro}{#3} \else - \build@TF@plot{\plot@macro}{\temp@macro}{#3}% + \build@TF@plot{\plot@macro}{\temp@macro}{#3} \fi + \edef\supplied@domain{\pgfkeysvalueof{/pgfplots/domain}} + \edef\domain@start{\expandafter\get@interval@start\supplied@domain\@nil} + \edef\domain@end{\expandafter\get@interval@end\supplied@domain\@nil} \if@pgfarg - \ifnum\pdfstrcmp{#2}{phase}=0 - \addplot[variable=t,#1]{\n@mod{\plot@macro}{2*pi}}; + \ifnum\pdf@strcmp{#2}{phase}=0 + \addplot [freq@filter, domain=\domain@start*\freq@scale:\domain@end*\freq@scale, variable=t, #1]{\n@mod{\plot@macro}{2*pi}}; \else - \addplot[variable=t,#1]{\plot@macro}; + \addplot [freq@filter, domain=\domain@start*\freq@scale:\domain@end*\freq@scale, variable=t, #1]{\plot@macro}; \fi \else - \stepcounter{gnuplot@id}% - \ifnum\pdfstrcmp{#2}{phase}=0 - \addplot[variable=t,#1] gnuplot[gnuplot@prefix] {'+' using (t):\plot@macro smooth unwrap} + \stepcounter{gnuplot@id} + \ifnum\pdf@strcmp{#2}{phase}=0 + \addplot [variable=t, #1] gnuplot [raw gnuplot, gnuplot@prefix] + { set table $meta; + set dummy t; + set logscale x 10; + set trange [\domain@start*\freq@scale:\domain@end*\freq@scale]; + set samples \pgfkeysvalueof{/pgfplots/samples}; + plot '+' using (t) : ((\plot@macro)/(\ph@scale)) smooth unwrap; + set table "\bodeplot@prefix\arabic{gnuplot@id}.table"; + plot "$meta" using ($1/(\freq@scale)):($2*\ph@scale); + }; \else - \addplot[variable=t,#1] gnuplot[gnuplot@prefix] {\plot@macro}; + \addplot [variable=t, #1] gnuplot [raw gnuplot, gnuplot@prefix] + { set table $meta; + set dummy t; + set logscale x 10; + set xrange [\domain@start*\freq@scale:\domain@end*\freq@scale]; + set samples \pgfkeysvalueof{/pgfplots/samples}; + plot \plot@macro; + set table "\bodeplot@prefix\arabic{gnuplot@id}.table"; + plot "$meta" using ($1/(\freq@scale)):($2); + }; \fi \fi } -\newcommand{\addBodeComponentPlot}[2][thick]{% +\newcommand{\addBodeComponentPlot}[2][thick]{ + \edef\supplied@domain{\pgfkeysvalueof{/pgfplots/domain}} + \edef\domain@start{\expandafter\get@interval@start\supplied@domain\@nil} + \edef\domain@end{\expandafter\get@interval@end\supplied@domain\@nil} \if@pgfarg - \addplot[variable=t,#1]{#2}; + \addplot [freq@filter, domain=\domain@start*\freq@scale:\domain@end*\freq@scale, variable=t, #1] {#2}; \else - \stepcounter{gnuplot@id}% - \addplot[variable=t,#1] gnuplot[gnuplot@prefix] {#2}; + \stepcounter{gnuplot@id} + \addplot [variable=t, #1] gnuplot [raw gnuplot, gnuplot@prefix] + { set table $meta; + set dummy t; + set logscale x 10; + set xrange [\domain@start*\freq@scale:\domain@end*\freq@scale]; + set samples \pgfkeysvalueof{/pgfplots/samples}; + plot #2; + set table "\bodeplot@prefix\arabic{gnuplot@id}.table"; + plot "$meta" using ($1/(\freq@scale)):($2); + }; \fi } -\newenvironment{BodePhPlot}[3][]{% - \parse@env@opt{#1}% +\newenvironment{BodePhPlot}[3][]{ + \parse@env@opt{#1} \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}] - \noexpand\begin{semilogxaxis}[% - ph@filter, + \noexpand\begin{semilogxaxis}[ + ph@y@label, + freq@label, bode@style, xmin={#2}, xmax={#3}, domain=#2:#3, height=2.5cm, - xlabel={Frequency (rad/s)}, \unexpanded\expandafter{\opt@axes} - ]% + ] } \temp@cmd }{ \end{semilogxaxis} \end{tikzpicture} } -\newenvironment{BodeMagPlot}[3][]{% - \parse@env@opt{#1}% +\newenvironment{BodeMagPlot}[3][]{ + \parse@env@opt{#1} \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}] - \noexpand\begin{semilogxaxis}[% + \noexpand\begin{semilogxaxis}[ bode@style, + freq@label, xmin={#2}, xmax={#3}, domain=#2:#3, height=2.5cm, - xlabel={Frequency (rad/s)}, ylabel={Gain (dB)}, - ytick distance=40, \unexpanded\expandafter{\opt@axes} - ]% + ] } \temp@cmd }{ \end{semilogxaxis} \end{tikzpicture} } -\newenvironment{BodePlot}[3][]{% - \PackageWarning{bodeplot}{Since v1.1.0, the BodePlot environment returns phase plots in radian units only. Please use the BodePhPlot environment if degree units are needed.}% - \parse@env@opt{#1}% +\newenvironment{BodePlot}[3][]{ + \parse@env@opt{#1} \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}] - \noexpand\begin{semilogxaxis}[% + \noexpand\begin{semilogxaxis}[ bode@style, + freq@label, xmin={#2}, xmax={#3}, domain=#2:#3, height=2.5cm, - xlabel={Frequency (rad/s)}, \unexpanded\expandafter{\opt@axes} - ]% + ] } \temp@cmd }{ \end{semilogxaxis} \end{tikzpicture} } -\newcommand*{\add@feature}[3]{% - \ifcat$\detokenize\expandafter{#1}$% - \xdef#1{\unexpanded\expandafter{#1 0+#2}}% +\newcommand*{\add@feature}[3]{ + \ifcat$\detokenize\expandafter{#1}$ + \xdef#1{\unexpanded\expandafter{#1 0+#2}} \else - \xdef#1{\unexpanded\expandafter{#1+#2}}% + \xdef#1{\unexpanded\expandafter{#1+#2}} \fi - \foreach \y [count=\n] in #3 {% - \xdef#1{\unexpanded\expandafter{#1}{\y}}% - \xdef\Last@LoopValue{\n}% - }% - \ifnum\Last@LoopValue=1% - \xdef#1{\unexpanded\expandafter{#1}{0}}% + \foreach \y [count=\n] in #3 { + \xdef#1{\unexpanded\expandafter{#1}{\y}} + \xdef\Last@LoopValue{\n} + } + \ifnum\Last@LoopValue=1 + \xdef#1{\unexpanded\expandafter{#1}{0}} \fi } -\newcommand{\build@ZPK@plot}[4]{% - \foreach \feature/\values in {#4} {% - \ifnum\pdfstrcmp{\feature}{z}=0 - \foreach \z in \values {% - \ifnum\pdfstrcmp{#3}{linear}=0 - \add@feature{#2}{\PhZeroLin}{\z}% - \add@feature{#1}{\MagZeroLin}{\z}% +\newcommand{\build@ZPK@plot}[4]{ + \foreach \feature/\values in {#4} { + \ifnum\pdf@strcmp{\feature}{z}=0 + \foreach \z in \values { + \ifnum\pdf@strcmp{#3}{linear}=0 + \add@feature{#2}{\PhZeroLin}{\z} + \add@feature{#1}{\MagZeroLin}{\z} \else - \ifnum\pdfstrcmp{#3}{asymptotic}=0 - \add@feature{#2}{\PhZeroAsymp}{\z}% - \add@feature{#1}{\MagZeroAsymp}{\z}% + \ifnum\pdf@strcmp{#3}{asymptotic}=0 + \add@feature{#2}{\PhZeroAsymp}{\z} + \add@feature{#1}{\MagZeroAsymp}{\z} \else - \add@feature{#2}{\PhZero}{\z}% - \add@feature{#1}{\MagZero}{\z}% + \add@feature{#2}{\PhZero}{\z} + \add@feature{#1}{\MagZero}{\z} \fi \fi - }% + } \fi - \ifnum\pdfstrcmp{\feature}{p}=0 - \foreach \p in \values {% - \ifnum\pdfstrcmp{#3}{linear}=0 - \add@feature{#2}{\PhPoleLin}{\p}% - \add@feature{#1}{\MagPoleLin}{\p}% + \ifnum\pdf@strcmp{\feature}{p}=0 + \foreach \p in \values { + \ifnum\pdf@strcmp{#3}{linear}=0 + \add@feature{#2}{\PhPoleLin}{\p} + \add@feature{#1}{\MagPoleLin}{\p} \else - \ifnum\pdfstrcmp{#3}{asymptotic}=0 - \add@feature{#2}{\PhPoleAsymp}{\p}% - \add@feature{#1}{\MagPoleAsymp}{\p}% + \ifnum\pdf@strcmp{#3}{asymptotic}=0 + \add@feature{#2}{\PhPoleAsymp}{\p} + \add@feature{#1}{\MagPoleAsymp}{\p} \else - \add@feature{#2}{\PhPole}{\p}% - \add@feature{#1}{\MagPole}{\p}% + \add@feature{#2}{\PhPole}{\p} + \add@feature{#1}{\MagPole}{\p} \fi \fi - }% + } \fi - \ifnum\pdfstrcmp{\feature}{k}=0 - \ifnum\pdfstrcmp{#3}{linear}=0 - \add@feature{#2}{\PhKLin}{\values}% - \add@feature{#1}{\MagKLin}{\values}% + \ifnum\pdf@strcmp{\feature}{k}=0 + \ifnum\pdf@strcmp{#3}{linear}=0 + \add@feature{#2}{\PhKLin}{\values} + \add@feature{#1}{\MagKLin}{\values} \else - \ifnum\pdfstrcmp{#3}{asymptotic}=0 - \add@feature{#2}{\PhKAsymp}{\values}% - \add@feature{#1}{\MagKAsymp}{\values}% + \ifnum\pdf@strcmp{#3}{asymptotic}=0 + \add@feature{#2}{\PhKAsymp}{\values} + \add@feature{#1}{\MagKAsymp}{\values} \else - \add@feature{#2}{\PhK}{\values}% - \add@feature{#1}{\MagK}{\values}% + \add@feature{#2}{\PhK}{\values} + \add@feature{#1}{\MagK}{\values} \fi \fi \fi - \ifnum\pdfstrcmp{\feature}{d}=0 - \ifnum\pdfstrcmp{#3}{linear}=0 + \ifnum\pdf@strcmp{\feature}{d}=0 + \ifnum\pdf@strcmp{#3}{linear}=0 \PackageError {bodeplot} {Linear approximation for pure delays is not supported.} {Plot the true Bode plot using `true' instead of `linear'.} \else - \ifnum\pdfstrcmp{#3}{asymptotic}=0 + \ifnum\pdf@strcmp{#3}{asymptotic}=0 \PackageError {bodeplot} {Asymptotic approximation for pure delays is not supported.} {Plot the true Bode plot using `true' instead of `asymptotic'.} \else \ifdim\values pt < 0pt \PackageError {bodeplot} {Delay needs to be a positive number.} \fi - \add@feature{#2}{\PhDel}{\values}% - \add@feature{#1}{\MagDel}{\values}% + \add@feature{#2}{\PhDel}{\values} + \add@feature{#1}{\MagDel}{\values} \fi \fi \fi - }% -} -\newcommand{\build@TF@plot}[3]{% - \gdef\num@real{0}% - \gdef\num@im{0}% - \gdef\den@real{0}% - \gdef\den@im{0}% - \gdef\loop@delay{0}% - \foreach \feature/\values in {#3} {% - \ifnum\pdfstrcmp{\feature}{num}=0 - \foreach \numcoeff [count=\numpow] in \values {% - \xdef\num@degree{\numpow}% - }% - \foreach \numcoeff [count=\numpow] in \values {% - \pgfmathtruncatemacro{\currentdegree}{\num@degree-\numpow}% + } +} +\newcommand{\build@TF@plot}[3]{ + \gdef\num@real{0} + \gdef\num@im{0} + \gdef\den@real{0} + \gdef\den@im{0} + \gdef\loop@delay{0} + \foreach \feature/\values in {#3} { + \ifnum\pdf@strcmp{\feature}{num}=0 + \foreach \numcoeff [count=\numpow] in \values { + \xdef\num@degree{\numpow} + } + \foreach \numcoeff [count=\numpow] in \values { + \pgfmathtruncatemacro{\currentdegree}{\num@degree-\numpow} \ifnum\currentdegree = 0 - \xdef\num@real{\num@real+\numcoeff}% + \xdef\num@real{\num@real+\numcoeff} \else \ifodd\currentdegree \xdef\num@im{\num@im+(\numcoeff*(\n@pow{-1}{(\currentdegree-1)/2})*% - (\n@pow{t}{\currentdegree}))}% + (\n@pow{t}{\currentdegree}))} \else \xdef\num@real{\num@real+(\numcoeff*(\n@pow{-1}{(\currentdegree)/2})*% - (\n@pow{t}{\currentdegree}))}% + (\n@pow{t}{\currentdegree}))} \fi \fi - }% + } \fi - \ifnum\pdfstrcmp{\feature}{den}=0 - \foreach \dencoeff [count=\denpow] in \values {% - \xdef\den@degree{\denpow}% - }% - \foreach \dencoeff [count=\denpow] in \values {% - \pgfmathtruncatemacro{\currentdegree}{\den@degree-\denpow}% + \ifnum\pdf@strcmp{\feature}{den}=0 + \foreach \dencoeff [count=\denpow] in \values { + \xdef\den@degree{\denpow} + } + \foreach \dencoeff [count=\denpow] in \values { + \pgfmathtruncatemacro{\currentdegree}{\den@degree-\denpow} \ifnum\currentdegree = 0 - \xdef\den@real{\den@real+\dencoeff}% + \xdef\den@real{\den@real+\dencoeff} \else \ifodd\currentdegree \xdef\den@im{\den@im+(\dencoeff*(\n@pow{-1}{(\currentdegree-1)/2})*% - (\n@pow{t}{\currentdegree}))}% + (\n@pow{t}{\currentdegree}))} \else \xdef\den@real{\den@real+(\dencoeff*(\n@pow{-1}{(\currentdegree)/2})*% - (\n@pow{t}{\currentdegree}))}% + (\n@pow{t}{\currentdegree}))} \fi \fi - }% + } \fi - \ifnum\pdfstrcmp{\feature}{d}=0 - \xdef\loop@delay{\values}% + \ifnum\pdf@strcmp{\feature}{d}=0 + \xdef\loop@delay{\values} \fi - }% - \xdef#2{(atan2((\num@im),(\num@real))-atan2((\den@im),% - (\den@real))-\loop@delay*t)}% + } + \xdef#2{((atan2((\num@im),(\num@real))-atan2((\den@im),% + (\den@real))-\loop@delay*t)*(\ph@scale))} \xdef#1{(20*log10(sqrt((\n@pow{\num@real}{2})+(\n@pow{\num@im}{2})))-% - 20*log10(sqrt((\n@pow{\den@real}{2})+(\n@pow{\den@im}{2}))))}% -} -\newcommand{\parse@opt}[1]{% - \gdef\optmag@axes{}% - \gdef\optph@axes{}% - \gdef\optph@plot{}% - \gdef\optmag@plot{}% - \gdef\opt@group{}% - \gdef\opt@approx{}% - \gdef\optph@commands{}% - \gdef\optmag@commands{}% - \gdef\opt@tikz{}% - \foreach \obj/\typ/\opt in {#1} {% - \ifnum\pdfstrcmp{\unexpanded\expandafter{\obj}}{plot}=0 - \ifnum\pdfstrcmp{\unexpanded\expandafter{\typ}}{mag}=0 - \xdef\optmag@plot{\unexpanded\expandafter{\opt}}% + 20*log10(sqrt((\n@pow{\den@real}{2})+(\n@pow{\den@im}{2}))))} +} +\newcommand{\parse@opt}[1]{ + \gdef\optmag@axes{} + \gdef\optph@axes{} + \gdef\optph@plot{} + \gdef\optmag@plot{} + \gdef\opt@group{} + \gdef\opt@approx{} + \gdef\optph@commands{} + \gdef\optmag@commands{} + \gdef\opt@tikz{} + \foreach \obj/\typ/\opt in {#1} { + \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{plot}=0 + \ifnum\pdf@strcmp{\unexpanded\expandafter{\typ}}{mag}=0 + \xdef\optmag@plot{\unexpanded\expandafter{\opt}} \else - \ifnum\pdfstrcmp{\unexpanded\expandafter{\typ}}{ph}=0 - \xdef\optph@plot{\unexpanded\expandafter{\opt}}% + \ifnum\pdf@strcmp{\unexpanded\expandafter{\typ}}{ph}=0 + \xdef\optph@plot{\unexpanded\expandafter{\opt}} \else - \xdef\optmag@plot{\unexpanded\expandafter{\opt}}% - \xdef\optph@plot{\unexpanded\expandafter{\opt}}% + \xdef\optmag@plot{\unexpanded\expandafter{\opt}} + \xdef\optph@plot{\unexpanded\expandafter{\opt}} \fi \fi \else - \ifnum\pdfstrcmp{\unexpanded\expandafter{\obj}}{axes}=0 - \ifnum\pdfstrcmp{\unexpanded\expandafter{\typ}}{mag}=0 - \xdef\optmag@axes{\unexpanded\expandafter{\opt}}% + \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{axes}=0 + \ifnum\pdf@strcmp{\unexpanded\expandafter{\typ}}{mag}=0 + \xdef\optmag@axes{\unexpanded\expandafter{\opt}} \else - \ifnum\pdfstrcmp{\unexpanded\expandafter{\typ}}{ph}=0 - \xdef\optph@axes{\unexpanded\expandafter{\opt}}% + \ifnum\pdf@strcmp{\unexpanded\expandafter{\typ}}{ph}=0 + \xdef\optph@axes{\unexpanded\expandafter{\opt}} \else - \xdef\optmag@axes{\unexpanded\expandafter{\opt}}% - \xdef\optph@axes{\unexpanded\expandafter{\opt}}% + \xdef\optmag@axes{\unexpanded\expandafter{\opt}} + \xdef\optph@axes{\unexpanded\expandafter{\opt}} \fi \fi \else - \ifnum\pdfstrcmp{\unexpanded\expandafter{\obj}}{group}=0 - \xdef\opt@group{\unexpanded\expandafter{\opt}}% + \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{group}=0 + \xdef\opt@group{\unexpanded\expandafter{\opt}} \else - \ifnum\pdfstrcmp{\unexpanded\expandafter{\obj}}{approx}=0 - \xdef\opt@approx{\unexpanded\expandafter{\opt}}% + \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{approx}=0 + \xdef\opt@approx{\unexpanded\expandafter{\opt}} \else - \ifnum\pdfstrcmp{\unexpanded\expandafter{\obj}}{commands}=0 - \ifnum\pdfstrcmp{\unexpanded\expandafter{\typ}}{ph}=0 - \xdef\optph@commands{\unexpanded\expandafter{\opt}}% + \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{commands}=0 + \ifnum\pdf@strcmp{\unexpanded\expandafter{\typ}}{ph}=0 + \xdef\optph@commands{\unexpanded\expandafter{\opt}} \else - \xdef\optmag@commands{\unexpanded\expandafter{\opt}}% + \xdef\optmag@commands{\unexpanded\expandafter{\opt}} \fi \else - \ifnum\pdfstrcmp{\unexpanded\expandafter{\obj}}{tikz}=0 - \xdef\opt@tikz{\unexpanded\expandafter{\opt}}% + \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{tikz}=0 + \xdef\opt@tikz{\unexpanded\expandafter{\opt}} \else \xdef\optmag@plot{\unexpanded\expandafter{\optmag@plot}, - \unexpanded\expandafter{\obj}}% + \unexpanded\expandafter{\obj}} \xdef\optph@plot{\unexpanded\expandafter{\optph@plot}, - \unexpanded\expandafter{\obj}}% + \unexpanded\expandafter{\obj}} \fi \fi \fi \fi \fi \fi - }% -} -\newcommand{\parse@env@opt}[1]{% - \gdef\opt@axes{}% - \gdef\opt@tikz{}% - \foreach \obj/\opt in {#1} {% - \ifnum\pdfstrcmp{\unexpanded\expandafter{\obj}}{axes}=0 - \xdef\opt@axes{\unexpanded\expandafter{\opt}}% + } +} +\newcommand{\parse@env@opt}[1]{ + \gdef\opt@axes{} + \gdef\opt@tikz{} + \foreach \obj/\opt in {#1} { + \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{axes}=0 + \xdef\opt@axes{\unexpanded\expandafter{\opt}} \else - \ifnum\pdfstrcmp{\unexpanded\expandafter{\obj}}{tikz}=0 - \xdef\opt@tikz{\unexpanded\expandafter{\opt}}% + \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{tikz}=0 + \xdef\opt@tikz{\unexpanded\expandafter{\opt}} \else \xdef\opt@axes{\unexpanded\expandafter{\opt@axes}, - \unexpanded\expandafter{\obj}}% + \unexpanded\expandafter{\obj}} \fi \fi - }% -} -\newcommand{\NyquistZPK}[4][]{% - \parse@N@opt{#1}% - \gdef\func@mag{}% - \gdef\func@ph{}% - \build@ZPK@plot{\func@mag}{\func@ph}{}{#2}% - \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]% - \noexpand\begin{axis}[% + } +} +\newcommand{\NyquistZPK}[4][]{ + \parse@N@opt{#1} + \gdef\func@mag{} + \gdef\func@ph{} + \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]} + \temp@cmd + \build@ZPK@plot{\func@mag}{\func@ph}{}{#2} + \edef\temp@cmd{\noexpand\begin{axis}[ bode@style, - domain=#3:#4, + domain=#3*\freq@scale:#4*\freq@scale, height=5cm, xlabel={$\Re$}, ylabel={$\Im$}, samples=500, \unexpanded\expandafter{\opt@axes} - ]% - }% - \temp@cmd + ]} + \temp@cmd \addplot [only marks,mark=+,thick,red] (-1 , 0); - \edef\temp@cmd{\noexpand\addplot[variable=t, thick, \unexpanded\expandafter{\opt@plot}]}% + \edef\temp@cmd{\noexpand\addplot [variable=t, thick, \unexpanded\expandafter{\opt@plot}]} \if@pgfarg - \temp@cmd ( {\n@pow{10}{((\func@mag)/20)}*cos(\func@ph)}, - {\n@pow{10}{((\func@mag)/20)}*sin(\func@ph)} ); + \temp@cmd ( {\n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale))}, + {\n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale))} ); \opt@commands \else - \stepcounter{gnuplot@id}% - \temp@cmd gnuplot[parametric,gnuplot@prefix] {% - \n@pow{10}{((\func@mag)/20)}*cos(\func@ph), - \n@pow{10}{((\func@mag)/20)}*sin(\func@ph)}; + \stepcounter{gnuplot@id} + \temp@cmd gnuplot [parametric, gnuplot@prefix] { + \n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale)), + \n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale)) + }; \opt@commands \fi \end{axis} \end{tikzpicture} } -\newcommand{\NyquistTF}[4][]{% - \parse@N@opt{#1}% - \gdef\func@mag{}% - \gdef\func@ph{}% - \build@TF@plot{\func@mag}{\func@ph}{#2}% - \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]% - \noexpand\begin{axis}[% +\newcommand{\NyquistTF}[4][]{ + \parse@N@opt{#1} + \gdef\func@mag{} + \gdef\func@ph{} + \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]} + \temp@cmd + \build@TF@plot{\func@mag}{\func@ph}{#2} + \edef\temp@cmd{\noexpand\begin{axis}[ bode@style, - domain=#3:#4, + domain=#3*\freq@scale:#4*\freq@scale, height=5cm, xlabel={$\Re$}, ylabel={$\Im$}, samples=500, \unexpanded\expandafter{\opt@axes} - ]% - }% - \temp@cmd - \addplot [only marks,mark=+,thick,red] (-1 , 0); - \edef\temp@cmd{\noexpand\addplot[variable=t, thick, \unexpanded\expandafter{\opt@plot}]}% + ]} + \temp@cmd + \addplot [only marks, mark=+, thick, red] (-1 , 0); + \edef\temp@cmd{\noexpand\addplot [variable=t, thick, \unexpanded\expandafter{\opt@plot}]} \if@pgfarg - \temp@cmd ( {\n@pow{10}{((\func@mag)/20)}*cos(\func@ph)}, - {\n@pow{10}{((\func@mag)/20)}*sin(\func@ph)} ); + \temp@cmd ( {\n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale))}, + {\n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale))} ); \opt@commands \else - \stepcounter{gnuplot@id}% - \temp@cmd gnuplot[parametric,gnuplot@prefix]{% - \n@pow{10}{((\func@mag)/20)}*cos(\func@ph), - \n@pow{10}{((\func@mag)/20)}*sin(\func@ph)}; + \stepcounter{gnuplot@id} + \temp@cmd gnuplot [parametric, gnuplot@prefix] { + \n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale)), + \n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale)) + }; \opt@commands \fi \end{axis} \end{tikzpicture} } -\newcommand{\addNyquistZPKPlot}[2][]{% - \gdef\func@mag{}% - \gdef\func@ph{}% - \build@ZPK@plot{\func@mag}{\func@ph}{}{#2}% +\newcommand{\addNyquistZPKPlot}[2][]{ + \gdef\func@mag{} + \gdef\func@ph{} + \build@ZPK@plot{\func@mag}{\func@ph}{}{#2} + \edef\supplied@domain{\pgfkeysvalueof{/pgfplots/domain}} + \edef\domain@start{\expandafter\get@interval@start\supplied@domain\@nil} + \edef\domain@end{\expandafter\get@interval@end\supplied@domain\@nil} \if@pgfarg - \addplot[variable=t,#1] ( {\n@pow{10}{((\func@mag)/20)}*cos(\func@ph)}, - {\n@pow{10}{((\func@mag)/20)}*sin(\func@ph)} ); + \addplot [domain=\domain@start*\freq@scale:\domain@end*\freq@scale, variable=t, #1] ( {\n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale))}, + {\n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale))} ); \else - \stepcounter{gnuplot@id}% - \addplot[variable=t,#1] gnuplot[parametric,gnuplot@prefix]{% - \n@pow{10}{((\func@mag)/20)}*cos(\func@ph), - \n@pow{10}{((\func@mag)/20)}*sin(\func@ph)}; + \stepcounter{gnuplot@id} + \addplot [domain=\domain@start*\freq@scale:\domain@end*\freq@scale, variable=t, #1] gnuplot [parametric, gnuplot@prefix] { + \n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale)), + \n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale)) + }; \fi } -\newcommand{\addNyquistTFPlot}[2][]{% - \gdef\func@mag{}% - \gdef\func@ph{}% - \build@TF@plot{\func@mag}{\func@ph}{#2}% +\newcommand{\addNyquistTFPlot}[2][]{ + \gdef\func@mag{} + \gdef\func@ph{} + \build@TF@plot{\func@mag}{\func@ph}{#2} + \edef\supplied@domain{\pgfkeysvalueof{/pgfplots/domain}} + \edef\domain@start{\expandafter\get@interval@start\supplied@domain\@nil} + \edef\domain@end{\expandafter\get@interval@end\supplied@domain\@nil} \if@pgfarg - \addplot[variable=t,#1] ( {\n@pow{10}{((\func@mag)/20)}*cos(\func@ph)}, - {\n@pow{10}{((\func@mag)/20)}*sin(\func@ph)} ); + \addplot [domain=\domain@start*\freq@scale:\domain@end*\freq@scale, variable=t, #1] ( {\n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale))}, + {\n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale))} ); \else - \stepcounter{gnuplot@id}% - \addplot[variable=t,#1] gnuplot[parametric,gnuplot@prefix]{% - \n@pow{10}{((\func@mag)/20)}*cos(\func@ph), - \n@pow{10}{((\func@mag)/20)}*sin(\func@ph)}; + \stepcounter{gnuplot@id} + \addplot [domain=\domain@start*\freq@scale:\domain@end*\freq@scale, variable=t, #1] gnuplot [parametric, gnuplot@prefix]{ + \n@pow{10}{((\func@mag)/20)}*cos((\func@ph)/(\ph@scale)), + \n@pow{10}{((\func@mag)/20)}*sin((\func@ph)/(\ph@scale)) + }; \fi } -\newenvironment{NyquistPlot}[3][]{% - \parse@env@opt{#1}% - \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]% - \noexpand\begin{axis}[% +\newenvironment{NyquistPlot}[3][]{ + \parse@env@opt{#1} + \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}] + \noexpand\begin{axis}[ bode@style, height=5cm, domain=#2:#3, xlabel={$\Re$}, ylabel={$\Im$}, \unexpanded\expandafter{\opt@axes} - ]% - }% + ] + } \temp@cmd \addplot [only marks,mark=+,thick,red] (-1 , 0); -}{% +}{ \end{axis} \end{tikzpicture} } -\newcommand{\parse@N@opt}[1]{% - \gdef\opt@axes{}% - \gdef\opt@plot{}% - \gdef\opt@commands{}% +\newcommand{\parse@N@opt}[1]{ + \gdef\opt@axes{} + \gdef\opt@plot{} + \gdef\opt@commands{} \gdef\opt@tikz{} - \foreach \obj/\opt in {#1} {% - \ifnum\pdfstrcmp{\unexpanded\expandafter{\obj}}{axes}=0 - \xdef\opt@axes{\unexpanded\expandafter{\opt}}% + \foreach \obj/\opt in {#1} { + \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{axes}=0 + \xdef\opt@axes{\unexpanded\expandafter{\opt}} \else - \ifnum\pdfstrcmp{\unexpanded\expandafter{\obj}}{plot}=0 - \xdef\opt@plot{\unexpanded\expandafter{\opt}}% + \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{plot}=0 + \xdef\opt@plot{\unexpanded\expandafter{\opt}} \else - \ifnum\pdfstrcmp{\unexpanded\expandafter{\obj}}{commands}=0 - \xdef\opt@commands{\unexpanded\expandafter{\opt}}% + \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{commands}=0 + \xdef\opt@commands{\unexpanded\expandafter{\opt}} \else - \ifnum\pdfstrcmp{\unexpanded\expandafter{\obj}}{tikz}=0 - \xdef\opt@tikz{\unexpanded\expandafter{\opt}}% + \ifnum\pdf@strcmp{\unexpanded\expandafter{\obj}}{tikz}=0 + \xdef\opt@tikz{\unexpanded\expandafter{\opt}} \else \xdef\opt@plot{\unexpanded\expandafter{\opt@plot}, - \unexpanded\expandafter{\obj}}% + \unexpanded\expandafter{\obj}} \fi \fi \fi \fi - }% -} -\newcommand{\NicholsZPK}[4][]{% - \parse@N@opt{#1}% - \gdef\func@mag{}% - \gdef\func@ph{}% - \build@ZPK@plot{\func@mag}{\func@ph}{}{#2}% - \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]% - \noexpand\begin{axis}[% - ph@x@filter, + } +} +\newcommand{\NicholsZPK}[4][]{ + \parse@N@opt{#1} + \gdef\func@mag{} + \gdef\func@ph{} + \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]} + \temp@cmd + \build@ZPK@plot{\func@mag}{\func@ph}{}{#2} + \edef\temp@cmd{\noexpand\begin{axis}[ + ph@x@label, bode@style, - domain=#3:#4, + domain=#3*\freq@scale:#4*\freq@scale, height=5cm, ylabel={Gain (dB)}, samples=500, \unexpanded\expandafter{\opt@axes} - ]% - }% - \temp@cmd - \edef\temp@cmd{\noexpand\addplot[variable=t,thick,\opt@plot]}% + ]} + \temp@cmd + \edef\temp@cmd{\noexpand\addplot [variable=t,thick,\opt@plot]} \if@pgfarg \temp@cmd ( {\func@ph} , {\func@mag} ); \opt@commands \else - \stepcounter{gnuplot@id}% - \temp@cmd gnuplot[parametric,gnuplot@prefix] - { \func@ph , \func@mag }; + \stepcounter{gnuplot@id} + \temp@cmd gnuplot [raw gnuplot, gnuplot@prefix] + { set table $meta; + set logscale x 10; + set dummy t; + set samples \pgfkeysvalueof{/pgfplots/samples}; + set trange [#3*\freq@scale:#4*\freq@scale]; + plot '+' using (\func@mag) : ((\func@ph)/(\ph@scale)); + unset logscale x; + set table "\bodeplot@prefix\arabic{gnuplot@id}.table"; + plot "$meta" using ($2*\ph@scale):($1); + }; \opt@commands \fi \end{axis} \end{tikzpicture} } -\newcommand{\NicholsTF}[4][]{% - \parse@N@opt{#1}% - \gdef\func@mag{}% - \gdef\func@ph{}% - \build@TF@plot{\func@mag}{\func@ph}{#2}% - \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]% - \noexpand\begin{axis}[% - ph@x@filter, +\newcommand{\NicholsTF}[4][]{ + \parse@N@opt{#1} + \gdef\func@mag{} + \gdef\func@ph{} + \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]} + \temp@cmd + \build@TF@plot{\func@mag}{\func@ph}{#2} + \edef\temp@cmd{\noexpand\begin{axis}[ + ph@x@label, bode@style, - domain=#3:#4, + domain=#3*\freq@scale:#4*\freq@scale, height=5cm, ylabel={Gain (dB)}, samples=500, \unexpanded\expandafter{\opt@axes} - ]% - }% - \temp@cmd - \edef\temp@cmd{\noexpand\addplot[variable=t,thick,\opt@plot]}% + ]} + \temp@cmd + \edef\temp@cmd{\noexpand\addplot [variable=t,thick, \opt@plot]} \if@pgfarg - \temp@cmd ( {\n@mod{\func@ph}{2*pi}} , {\func@mag} ); + \temp@cmd ( {\n@mod{\func@ph}{2*pi*\ph@scale}} , {\func@mag} ); \opt@commands \else - \stepcounter{gnuplot@id}% - \temp@cmd gnuplot[parametric,gnuplot@prefix] - { \n@mod{\func@ph}{2*pi} , \func@mag }; + \stepcounter{gnuplot@id} + \temp@cmd gnuplot [raw gnuplot, gnuplot@prefix] + { set table $meta1; + set logscale x 10; + set dummy t; + set samples \pgfkeysvalueof{/pgfplots/samples}; + set trange [#3*\freq@scale:#4*\freq@scale]; + plot '+' using (\func@mag) : ((\func@ph)/(\ph@scale)); + unset logscale x; + set table $meta2; + plot "$meta1" using ($1):($2) smooth unwrap; + set table "\bodeplot@prefix\arabic{gnuplot@id}.table"; + plot "$meta2" using ($2*\ph@scale):($1); + }; \opt@commands \fi \end{axis} \end{tikzpicture} } -\newenvironment{NicholsChart}[3][]{% - \parse@env@opt{#1}% - \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}]% - \noexpand\begin{axis}[% - ph@x@filter, +\newenvironment{NicholsChart}[3][]{ + \parse@env@opt{#1} + \edef\temp@cmd{\noexpand\begin{tikzpicture} [\unexpanded\expandafter{\opt@tikz}] + \noexpand\begin{axis}[ + ph@x@label, bode@style, domain=#2:#3, height=5cm, ylabel={Gain (dB)}, \unexpanded\expandafter{\opt@axes} - ]% - }% + ] + } \temp@cmd }{ \end{axis} \end{tikzpicture} } -\newcommand{\addNicholsZPKChart}[2][]{% - \gdef\func@mag{}% - \gdef\func@ph{}% - \build@ZPK@plot{\func@mag}{\func@ph}{}{#2}% +\newcommand{\addNicholsZPKChart}[2][]{ + \gdef\func@mag{} + \gdef\func@ph{} + \build@ZPK@plot{\func@mag}{\func@ph}{}{#2} + \edef\supplied@domain{\pgfkeysvalueof{/pgfplots/domain}} + \edef\domain@start{\expandafter\get@interval@start\supplied@domain\@nil} + \edef\domain@end{\expandafter\get@interval@end\supplied@domain\@nil} \if@pgfarg - \addplot[variable=t,#1] ( {\func@ph} , {\func@mag} ); + \addplot [variable=t, domain=\domain@start*\freq@scale:\domain@end*\freq@scale, #1] ( {\func@ph} , {\func@mag} ); \else - \stepcounter{gnuplot@id}% - \addplot[variable=t,#1] gnuplot[parametric,gnuplot@prefix] - {\func@ph , \func@mag}; + \stepcounter{gnuplot@id} + \addplot [#1] gnuplot [raw gnuplot, gnuplot@prefix] + { set table $meta; + set logscale x 10; + set dummy t; + set samples \pgfkeysvalueof{/pgfplots/samples}; + set trange [\domain@start*\freq@scale:\domain@end*\freq@scale]; + plot '+' using (\func@mag) : ((\func@ph)/(\ph@scale)); + unset logscale x; + set table "\bodeplot@prefix\arabic{gnuplot@id}.table"; + plot "$meta" using ($2*\ph@scale):($1); + }; \fi } -\newcommand{\addNicholsTFChart}[2][]{% - \gdef\func@mag{}% - \gdef\func@ph{}% - \build@TF@plot{\func@mag}{\func@ph}{#2}% +\newcommand{\addNicholsTFChart}[2][]{ + \gdef\func@mag{} + \gdef\func@ph{} + \build@TF@plot{\func@mag}{\func@ph}{#2} + \edef\supplied@domain{\pgfkeysvalueof{/pgfplots/domain}} + \edef\domain@start{\expandafter\get@interval@start\supplied@domain\@nil} + \edef\domain@end{\expandafter\get@interval@end\supplied@domain\@nil} \if@pgfarg - \addplot[variable=t,#1] ( {\n@mod{\func@ph}{2*pi}} , {\func@mag} ); + \addplot [variable=t, domain=\domain@start*\freq@scale:\domain@end*\freq@scale, #1] ( {\n@mod{\func@ph}{2*pi*\ph@scale}} , {\func@mag} ); \else - \stepcounter{gnuplot@id}% - \addplot[variable=t,#1] gnuplot[gnuplot@prefix] - {\n@mod{\func@ph}{2*pi} , \func@mag}; + \stepcounter{gnuplot@id} + \addplot [#1] gnuplot [raw gnuplot, gnuplot@prefix] + { set table $meta1; + set logscale x 10; + set dummy t; + set samples \pgfkeysvalueof{/pgfplots/samples}; + set trange [\domain@start*\freq@scale:\domain@end*\freq@scale]; + plot '+' using (\func@mag) : ((\func@ph)/(\ph@scale)); + unset logscale x; + set table $meta2; + plot "$meta1" using ($1):($2) smooth unwrap; + set table "\bodeplot@prefix\arabic{gnuplot@id}.table"; + plot "$meta2" using ($2*\ph@scale):($1); + }; \fi } \endinput -- cgit v1.2.3