diff options
Diffstat (limited to 'Master/texmf-dist/tex/latex/pgfplots/pgfplots.sty')
-rw-r--r-- | Master/texmf-dist/tex/latex/pgfplots/pgfplots.sty | 2385 |
1 files changed, 1661 insertions, 724 deletions
diff --git a/Master/texmf-dist/tex/latex/pgfplots/pgfplots.sty b/Master/texmf-dist/tex/latex/pgfplots/pgfplots.sty index 394cf16be6d..114db197b55 100644 --- a/Master/texmf-dist/tex/latex/pgfplots/pgfplots.sty +++ b/Master/texmf-dist/tex/latex/pgfplots/pgfplots.sty @@ -23,17 +23,33 @@ % along with this program. If not, see <http://www.gnu.org/licenses/>. % %-------------------------------------------- -\def\pgfplotsversion{0.92} -\ProvidesPackage{pgfplots}[2008/31/01 Version \pgfplotsversion] +\def\pgfplotsversion{0.92.4} +\ProvidesPackage{pgfplots}[2008/02/17 Version \pgfplotsversion] + +% ATTENTION: +% you MAY need one of +% \def\pgfsysdriver{pgfsys-dvipdfm.def} +% \def\pgfsysdriver{pgfsys-pdftex.def} +% \def\pgfsysdriver{pgfsys-dvips.def} +% +% BEFORE the first \usepackage{pgf}, \usepackage{tikz} or +% \usepackage{pgfplots}. +% Default is +% 'dvips' for 'latex' +% 'pdftex' for 'pdflatex' +% -> dvipdfm needs special attention. + \RequirePackage{xkeyval}[2006/11/18] \RequirePackage{ifthen} \RequirePackage{liststructure} \RequirePackage{tikz}[2007/06/07] +\RequirePackage{sciformat} \RequirePackage{pgfmathlog} \usetikzlibrary{plotmarks} \def\prefix{pgfplots} +% FIXME: reduce number of variables! \newcount\axisticknum \newcount\axis@tickposnum \newcount\axis@xmode @@ -46,14 +62,19 @@ \newdimen\axis@tmpa \newdimen\axis@tmpb \newif\ifaxis@isuniformtick +\newif\ifaxis@enlargelimits +\newif\ifaxis@enlargelimits@rel@thresh +\newif\ifaxis@enlargelimits@auto \let\axis@TMP=\empty \let\axis@TMPB=\empty +\let\axis@TMPC=\empty \def\axis@leftover{} \def\axis@rightover{} \def\axisdefaultwidth{240pt} \def\axisdefaultheight{207pt} \def\axisdefaulttickwidth{35}% the maximum space between adjacent ticks (in pt, but don't specify the unit 'pt') +\def\axisdefaulttryminticks{4} \listnew{\blackwhiteplotspeclist}{% mark options={fill=gray},mark=*\\% @@ -84,56 +105,6 @@ \listcopy\coloredplotspeclist\to\autoplotspeclist% %\listcopy\blackwhiteplotspeclist\to\autoplotspeclist% -%-------------------------------------------------- -% -% MARKERS: -% mark repeat=3,mark phase=2 -% mark options={color=blue,rotate=180} -% ball,ball color=blue -% {*} -% {x} -% {+} -% \usetikzlibrary{plotmarks} -% {-} -% {|} -% {o} -% {asterisk} -% {star} -% {oplus} -% {oplus*} -% {otimes} -% {otimes*} -% {square} -% {square*} -% {triangle} -% {triangle*} -% {diamond} -% {diamond*} -% {pentagon} -% {pentagon*} -% -% LINES: -% line width=2cm -% [snake=zigzag] -% [snake=brace] -% [snake=triangles] -% [snake=coil,segment length=4pt] -% [snake=coil,segment aspect=0] -% [snake=expanding waves,segment angle=7] -% style=solid -% style=dotted -% style=densely dotted -% style=loosely dotted -% style=dashed -% style=densely dashed -% style=loosely dashed -% dash pattern=on 2pt off 3pt on 4pt off 4pt -% dash phase=10pt -% Mit der 'double' und 'double distance' option gibts lustige effekte: -% \draw[draw=white,double=red,very thick] (0,1) -- (1,0); -% \draw[very thick,double distance=2pt] (1,0) arc (180:90:1cm); -%-------------------------------------------------- - \tikzstyle{every axis}=[] \tikzstyle{every axis plot}=[] \tikzstyle{every axis label}=[] @@ -142,6 +113,10 @@ \tikzstyle{every axis title}=[at={(0.5,1)},above,yshift=6pt] \tikzstyle{every tick}=[very thin,gray] \tikzstyle{every minor tick}=[] +\tikzstyle{every major tick}=[] +\tikzstyle{every axis grid}=[style=help lines] +\tikzstyle{every minor grid}=[] +\tikzstyle{every major grid}=[] \tikzstyle{every tick label}=[] \tikzstyle{every x tick label}=[] \tikzstyle{every y tick label}=[] @@ -163,6 +138,8 @@ % - \tikzstyle{every axis legend}+=[at={(1,0.5)},anchor=east,outer sep=0.5cm] % draws the legend INSIDE MIDDLE RIGHT, separated by 0.5cm from the axis. \tikzstyle{every axis legend}=[% + cells={anchor=center}, + inner xsep=3pt,inner ysep=2pt,nodes={inner sep=2pt,text depth=0.15em}, anchor=north east,% shape=rectangle,% fill=white,% @@ -173,32 +150,49 @@ % outer sep=0.1cm] -% -% xticklabel: -% im argument kann man '\axisticknum' und '\tick' verwenden. -% '\tick' ist der eintrag aus '\xtick', der gerade bearbeitet wird, -% '\axisticknum' seine nummer. -% -% yticklabel: -% analog zu xticklabel. -% -% xfilter/yfilter -% \def\meinxfilter#1\to#2{\def#2{1.4}} -% xfilter=\meinxfilter -% -% if the filtered coordinate is empty string, it will be skipped. \define@cmdkeys[\prefix]{axis}[axis@]{% xmin,xmax,xticklabel,xtick,xtickten,xlabel,% ymin,ymax,yticklabel,ytick,ytickten,ylabel,% - trimxmin,trimxmax,trimymin,trimymax,% subtickwidth,tickwidth,% xfilter,yfilter,% width,height,% title,% execute at begin plot,% execute at end plot,% + enlargelimits,% + legend columns,% x,y}% +\long\def\axis@foreach@to@list#1\to#2{% + \listnewempty\axis@TMP + \begingroup + \foreach \i in {#1} {% + \globaldefs=1 + \expandafter\listpushback\i\to\axis@TMP + \globaldefs=0 + }% + \endgroup + \listcopy\axis@TMP\to#2\relax +} + +\define@cmdkey[\prefix]{axis}[axis@]{xticklabels}{% + \expandafter\axis@foreach@to@list\axis@xticklabels\to\axis@xticklabels + %\expandafter\listnew\expandafter\axis@xticklabels\expandafter{\axis@xticklabels}% + \let\axis@xticklabel=\axis@user@ticklabel@list@x +} +\define@cmdkey[\prefix]{axis}[axis@]{yticklabels}{% + \expandafter\axis@foreach@to@list\axis@yticklabels\to\axis@yticklabels + %\expandafter\listnew\expandafter\axis@yticklabels\expandafter{\axis@yticklabels}% + \let\axis@yticklabel=\axis@user@ticklabel@list@y +} + +\define@cmdkey[\prefix]{axis}[axis@]{minor tick length}{% + \expandafter\let\expandafter\axis@subtickwidth\csname axis@minor tick length\endcsname +} +\define@cmdkey[\prefix]{axis}[axis@]{major tick length}{% + \expandafter\let\expandafter\axis@tickwidth\csname axis@major tick length\endcsname +} + % sets \axis@tickposnum to % left=0 % right=1 @@ -206,11 +200,75 @@ \define@choicekey[\prefix]{axis}{tickpos}[\val\nr]{left,right,both}{% \axis@tickposnum=\nr\relax } +\define@choicekey[\prefix]{axis}{legend plot pos}[\val\nr]{left,right,none}{% + \edef\axis@legend@plot@pos{\nr}% +} + +\define@choicekey[\prefix]{axis}{anchor}[\val\nr]{north,north west,west,south west,south,south east,east,north east,center}{% + \edef\axis@anchorchoicenum{\nr}% +} + +\define@choicekey[\prefix]{axis}{ticks}[\val\nr]{none,major,minor,both}{% + \expandafter\ifcase\nr\relax + \axis@xminorticksfalse + \axis@yminorticksfalse + \axis@xmajorticksfalse + \axis@ymajorticksfalse + \or + \axis@xminorticksfalse + \axis@yminorticksfalse + \axis@xmajortickstrue + \axis@ymajortickstrue + \or + \axis@xminortickstrue + \axis@yminortickstrue + \axis@xmajorticksfalse + \axis@ymajorticksfalse + \or + \axis@xminortickstrue + \axis@yminortickstrue + \axis@xmajortickstrue + \axis@ymajortickstrue + \fi +} +\define@choicekey[\prefix]{axis}{grid}[\val\nr]{none,major,minor,both}{% + \expandafter\ifcase\nr\relax + \axis@xminorgridsfalse + \axis@yminorgridsfalse + \axis@xmajorgridsfalse + \axis@ymajorgridsfalse + \or + \axis@xminorgridsfalse + \axis@yminorgridsfalse + \axis@xmajorgridstrue + \axis@ymajorgridstrue + \or + \axis@xminorgridstrue + \axis@yminorgridstrue + \axis@xmajorgridsfalse + \axis@ymajorgridsfalse + \or + \axis@xminorgridstrue + \axis@yminorgridstrue + \axis@xmajorgridstrue + \axis@ymajorgridstrue + \fi +} + + \define@boolkeys[\prefix]{axis}[axis@]{% xminorticks,% + xmajorticks,% yminorticks,% + ymajorticks,% + xminorgrids,% + xmajorgrids,% + yminorgrids,% + ymajorgrids,% disablelogfilter,% - enlargelimits}[true] + disabledatascaling,% + hide axis,% + scale only axis}[true] % sets \axis@xmode to % normal=0 @@ -226,63 +284,59 @@ \axis@ymode=\nr\relax } -% Options to legend: -% textwidth=auto -% textwidth=none -% textwidth=DIMENSION -\define@cmdkey[\prefix]{legend}[axis@legend@]{textwidth}[auto]{}% - -\define@cmdkey[\prefix]{legend}[axis@legend@]{font}[]{} - \long\def\axispreset#1{% \presetkeys[\prefix]{axis}{#1}{}% } \long\def\legendpreset#1{% - \presetkeys[\prefix]{legend}{#1}{}% + \errmessage{Sorry, legendpreset is now deprecated, along with the legend options text width and font. Legends are now TikZ-matrizes which provide better alignment and can be placed horizontally. See the manual for details.}% } \presetkeys[\prefix]{axis}{% xmode=normal, xmin=, xmax=, - trimxmin=, - trimxmax=, xlabel=, xtick=, xtickten=, xticklabel=, xminorticks=true, + xmajorticks=true, + xminorgrids=false, + xmajorgrids=false, ymode=normal, ymin=, ymax=, - trimymin=, - trimymax=, ylabel=, ytick=, ytickten=, yticklabel=, yminorticks=true, + ymajorticks=true, + yminorgrids=false, + ymajorgrids=false, + grid=none,% tickpos=both, xfilter=, yfilter=, title=, width=, height=, + anchor=south west, subtickwidth=0.1cm, tickwidth=0.15cm, + scale only axis=false, + hide axis=false, + legend columns=1, + legend plot pos=left, x=,% is implicitly set by 'width' and/or '\axisdefaultwidth' y=,% is implicitly set by 'height' and/or '\axisdefaultheight' execute at begin plot=,% execute at end plot=,% - enlargelimits=false, + enlargelimits=auto, disablelogfilter=false}{} -\presetkeys[\prefix]{legend}{% - textwidth=auto, - font=}{} - - -\def\logten{2.302585} +\def\logten{2.3025851} +\def\reciproc@logten{0.434294481903252} \newcommand{\logi}[1]{% \ifcase#1 @@ -300,7 +354,14 @@ \newcommand{\show@yticklabel}[2]{{% \let\ticknum=#1% - \def\tick{#2}% + \ifaxis@float@numerics@mode@y + % this here stores \\tick@S, \\tick@M, \\tick@E + \axis@inverse@datascaletrafo@y{#2}\to\tick + % .. and this here provides \tick as fixed point repr: + \scitofixedsingle\tick\tick + \else + \def\tick{#2}% + \fi \axis@yticklabel }} @@ -309,10 +370,26 @@ % #2: der x wert dafuer \newcommand{\show@xticklabel}[2]{{% \let\ticknum=#1% - \def\tick{#2}% + \ifaxis@float@numerics@mode@x + % this here stores \\tick@S, \\tick@M, \\tick@E + \axis@inverse@datascaletrafo@x{#2}\to\tick + % .. and this here provides \tick as fixed point repr: + \scitofixedsingle\tick\tick + \else + \def\tick{#2}% + \fi \axis@xticklabel }} +\def\axis@user@ticklabel@list@x{% + \listselect\ticknum\of\axis@xticklabels\to\tick + \tick +} +\def\axis@user@ticklabel@list@y{% + \listselect\ticknum\of\axis@yticklabels\to\tick + \tick +} + \newcommand{\axisdefaultticklabel}[0]{% $\prettyprintnumber{\tick}$% } @@ -344,147 +421,184 @@ % Y-Achsen und Achsenbeschriftung LOG: % 1: Ticks -\newcommand{\yachse}[1]{% +\newcommand{\axis@drawyaxis}[1]{% + \begingroup + \newif\ifneedsminorloop \axisticknum=0 - \foreach \y in {#1} { - %\pgfextracty{\axis@tmpa}{\pgfpointxy{0}{\logten*\y}}% - \pgfextracty{\axis@tmpa}{\pgfpointxy{0}{\y}}% - % - \ifdim\axis@tmpa<\axis@ycoordminTEX - \else - \ifdim\axis@tmpa>\axis@ycoordmaxTEX - \else - % Achsenbeschriftung: - \ifnum\axis@tickposnum=1 - \node at - (\axis@xcoordmaxTEX\axis@leftover,\axis@tmpa) - [right,style=every tick label,style=every y tick label] - {\show@yticklabel\axisticknum\y}; - \else - \node at - (\axis@xcoordminTEX\axis@leftover,\axis@tmpa) - [left,style=every tick label,style=every y tick label] - {\show@yticklabel\axisticknum\y}; - \fi - \global\advance\axisticknum by1 - \fi - \fi - \begin{scope} - \clip (\axis@xcoordminTEX\axis@leftover, \axis@ycoordminTEX\axis@leftover) - rectangle (\axis@xcoordmaxTEX\axis@rightover, \axis@ycoordmaxTEX\axis@rightover); - % Y-Achsenticks links und rechts - % in log: - % beachte: log( i*10^k ) = log\i + k\log10 -> male ticks für i=1..9 + \edef\axis@TMP{#1}% + \ifx\axis@TMP\empty + \else \ifaxis@yminorticks - \foreach \i in {1,...,9} { - \pgfextracty{\axis@tmpb}{\pgfpointxy{0}{\logi\i}}% - \advance\axis@tmpa by\axis@tmpb - \draw[style=every tick,style=every minor tick] + \needsminorlooptrue + \fi + \ifaxis@yminorgrids + \needsminorlooptrue + \fi + \def\axis@placecomputedtick##1[##2]{% + \draw[##2] \ifcase\axis@tickposnum (\axis@xcoordminTEX\axis@leftover, \axis@tmpa) - -- (\axis@xcoordminTEX+\axis@subtickwidth, \axis@tmpa) + -- (\axis@xcoordminTEX+##1, \axis@tmpa) \or (\axis@xcoordmaxTEX\axis@rightover, \axis@tmpa) - -- (\axis@xcoordmaxTEX-\axis@subtickwidth, \axis@tmpa) + -- (\axis@xcoordmaxTEX-##1, \axis@tmpa) \or (\axis@xcoordminTEX\axis@leftover, \axis@tmpa) - -- (\axis@xcoordminTEX+\axis@subtickwidth, \axis@tmpa) + -- (\axis@xcoordminTEX+##1, \axis@tmpa) (\axis@xcoordmaxTEX\axis@rightover, \axis@tmpa) - -- (\axis@xcoordmaxTEX-\axis@subtickwidth, \axis@tmpa) + -- (\axis@xcoordmaxTEX-##1, \axis@tmpa) \fi ; }% - \fi - \draw[style=every tick] - \ifcase\axis@tickposnum - (\axis@xcoordminTEX\axis@leftover,\axis@tmpa) - -- (\axis@xcoordminTEX+\axis@tickwidth,\axis@tmpa) - \or - (\axis@xcoordmaxTEX\axis@rightover,\axis@tmpa) - -- (\axis@xcoordmaxTEX-\axis@tickwidth,\axis@tmpa) - \or - (\axis@xcoordminTEX\axis@leftover,\axis@tmpa) - -- (\axis@xcoordminTEX+\axis@tickwidth,\axis@tmpa) - (\axis@xcoordmaxTEX\axis@rightover,\axis@tmpa) - -- (\axis@xcoordmaxTEX-\axis@tickwidth,\axis@tmpa) - \fi - ; - \end{scope} - } -} - -% X-Achsen und Achsenbeschriftung -% 1: Ticks -\newcommand{\xachse}[1]{% - \axisticknum=0 - \foreach \x in {#1} { - % \pgfextractx{\axis@tmpa}{\pgfpointxy{\logten*\x}{0}}% - \pgfextractx{\axis@tmpa}{\pgfpointxy{\x}{0}}% - % - \ifdim\axis@tmpa<\axis@xcoordminTEX - \else - \ifdim\axis@tmpa>\axis@xcoordmaxTEX + \def\placecomputedgridline[##1]{% + \draw[##1] + (\axis@xcoordminTEX\axis@leftover, \axis@tmpa) + -- (\axis@xcoordmaxTEX\axis@rightover, \axis@tmpa) + ; + }% + \foreach \y in {#1} { + \pgfextracty{\axis@tmpa}{\pgfpointxy{0}{\y}}% + % + \ifdim\axis@tmpa<\axis@ycoordminTEX \else - % Achsenbeschriftung: - \ifnum\axis@tickposnum=1 - \node at - (\axis@tmpa,\axis@ycoordmaxTEX\axis@leftover) - [above,style=every tick label,style=every x tick label] - {\show@xticklabel\axisticknum\x}; + \ifdim\axis@tmpa>\axis@ycoordmaxTEX \else - \node at - (\axis@tmpa,\axis@ycoordminTEX\axis@leftover) - [below,style=every tick label,style=every x tick label] - {\show@xticklabel\axisticknum\x}; + % Achsenbeschriftung: + \ifnum\axis@tickposnum=1 + \node at + (\axis@xcoordmaxTEX\axis@leftover,\axis@tmpa) + [right,style=every tick label,style=every y tick label] + {\show@yticklabel\axisticknum\y}; + \else + \node at + (\axis@xcoordminTEX\axis@leftover,\axis@tmpa) + [left,style=every tick label,style=every y tick label] + {\show@yticklabel\axisticknum\y}; + \fi \fi - \global\advance\axisticknum by1 \fi - \fi + \global\advance\axisticknum by1 + \begin{scope} + \clip (\axis@xcoordminTEX\axis@leftover, \axis@ycoordminTEX\axis@leftover) + rectangle (\axis@xcoordmaxTEX\axis@rightover, \axis@ycoordmaxTEX\axis@rightover); + % Y-ticks left and/or right + % in log: + % log( i*10^k ) = log\i + k\log10 -> draw ticks for i=1..9 + \ifneedsminorloop + \foreach \i in {1,...,9} { + % this code here is scoped inside of \foreach. + \pgfextracty{\axis@tmpb}{\pgfpointxy{0}{\logi\i}}% + \advance\axis@tmpa by\axis@tmpb + \ifaxis@yminorgrids + \placecomputedgridline[style=every axis grid,style=every minor grid]% + \fi + \ifaxis@yminorticks + \axis@placecomputedtick\axis@subtickwidth[style=every tick,style=every minor tick]% + \fi + }% + \fi + \ifaxis@ymajorgrids + \placecomputedgridline[style=every axis grid,style=every major grid]% + \fi + \ifaxis@ymajorticks + \axis@placecomputedtick\axis@tickwidth[style=every tick,style=every major tick]% + \fi + \end{scope} + }% + \fi + \endgroup +} - \begin{scope} - \clip (\axis@xcoordminTEX\axis@leftover, \axis@ycoordminTEX\axis@leftover) - rectangle (\axis@xcoordmaxTEX\axis@rightover, \axis@ycoordmaxTEX\axis@rightover); - % Y-Achsenticks links und rechts - % in log: - % beachte: log( i*10^k ) = log\i + k\log10 -> male ticks für i=1..9 +% X-Achsen und Achsenbeschriftung +% 1: Ticks +\newcommand{\axis@drawxaxis}[1]{% + \begingroup + \axisticknum=0 + \newif\ifneedsminorloop + \edef\axis@TMP{#1}% + \ifx\axis@TMP\empty + \else \ifaxis@xminorticks - \foreach \i in {1,...,9} { - \pgfextractx{\axis@tmpb}{\pgfpointxy{\logi\i}{0}}% - \advance\axis@tmpa by\axis@tmpb - \draw[style=every tick,style=every minor tick] + \needsminorlooptrue + \fi + \ifaxis@xminorgrids + \needsminorlooptrue + \fi + \def\axis@placecomputedtick##1[##2]{% + \draw[##2] \ifcase\axis@tickposnum (\axis@tmpa, \axis@ycoordminTEX\axis@leftover) - -- (\axis@tmpa, \axis@ycoordminTEX+\axis@subtickwidth) + -- (\axis@tmpa, \axis@ycoordminTEX+##1) \or (\axis@tmpa, \axis@ycoordmaxTEX\axis@rightover) - -- (\axis@tmpa, \axis@ycoordmaxTEX-\axis@subtickwidth) + -- (\axis@tmpa, \axis@ycoordmaxTEX-##1) \or (\axis@tmpa, \axis@ycoordminTEX\axis@leftover) - -- (\axis@tmpa, \axis@ycoordminTEX+\axis@subtickwidth) + -- (\axis@tmpa, \axis@ycoordminTEX+##1) (\axis@tmpa, \axis@ycoordmaxTEX\axis@rightover) - -- (\axis@tmpa, \axis@ycoordmaxTEX-\axis@subtickwidth) + -- (\axis@tmpa, \axis@ycoordmaxTEX-##1) \fi ; }% - \fi - \draw[style=every tick] - \ifcase\axis@tickposnum - (\axis@tmpa, \axis@ycoordminTEX\axis@leftover) - -- (\axis@tmpa, \axis@ycoordminTEX+\axis@tickwidth) - \or - (\axis@tmpa, \axis@ycoordmaxTEX\axis@rightover) - -- (\axis@tmpa, \axis@ycoordmaxTEX-\axis@tickwidth) - \or - (\axis@tmpa, \axis@ycoordminTEX\axis@leftover) - -- (\axis@tmpa, \axis@ycoordminTEX+\axis@tickwidth) - (\axis@tmpa, \axis@ycoordmaxTEX\axis@rightover) - -- (\axis@tmpa, \axis@ycoordmaxTEX-\axis@tickwidth) - \fi - ; - \end{scope} - } + \def\placecomputedgridline[##1]{% + \draw[##1] + (\axis@tmpa, \axis@ycoordminTEX\axis@leftover) + -- (\axis@tmpa, \axis@ycoordmaxTEX\axis@rightover) + ; + }% + \foreach \x in {#1} { + \pgfextractx{\axis@tmpa}{\pgfpointxy{\x}{0}}% + % + \ifdim\axis@tmpa<\axis@xcoordminTEX + \else + \ifdim\axis@tmpa>\axis@xcoordmaxTEX + \else + % Achsenbeschriftung: + \ifnum\axis@tickposnum=1 + \node at + (\axis@tmpa,\axis@ycoordmaxTEX\axis@leftover) + [above,style=every tick label,style=every x tick label] + {\show@xticklabel\axisticknum\x}; + \else + \node at + (\axis@tmpa,\axis@ycoordminTEX\axis@leftover) + [below,style=every tick label,style=every x tick label] + {\show@xticklabel\axisticknum\x}; + \fi + \fi + \fi + \global\advance\axisticknum by1 + % + \begin{scope} + \clip (\axis@xcoordminTEX\axis@leftover, \axis@ycoordminTEX\axis@leftover) + rectangle (\axis@xcoordmaxTEX\axis@rightover, \axis@ycoordmaxTEX\axis@rightover); + % X-Axis ticks bottom and top + % in log: + % log( i*10^k ) = log\i + k\log10 -> draw ticks for i=1..9 + \ifneedsminorloop + \foreach \i in {1,...,9} { + \pgfextractx{\axis@tmpb}{\pgfpointxy{\logi\i}{0}}% + \advance\axis@tmpa by\axis@tmpb + \ifaxis@xminorgrids + \placecomputedgridline[style=every axis grid,style=every minor grid]% + \fi + \ifaxis@xminorticks + \axis@placecomputedtick\axis@subtickwidth[style=every tick,style=every minor tick]% + \fi + }% + \fi + \ifaxis@xmajorgrids + \placecomputedgridline[style=every axis grid,style=every major grid]% + \fi + \ifaxis@xmajorticks + \axis@placecomputedtick\axis@tickwidth[style=every tick,style=every major tick]% + \fi + \end{scope} + }% + \fi + \endgroup } \def\axis@rememberplotspec#1{{% @@ -505,7 +619,7 @@ \advance\c@pgf@countb by-\c@pgf@counta \repeat \listselect\c@pgf@countb\of\autoplotspeclist\to#1 - %\message{pgfplots.sty: using \string\autoplotspeclist\ specification no\#\the\c@pgf@countb (of \the\c@pgf@counta): #1}% +%\message{pgfplots.sty: using \string\autoplotspeclist\ specification no\#\the\c@pgf@countb (of \the\c@pgf@counta): #1}% \fi } @@ -532,135 +646,297 @@ % % The linespec. will be used in the legend. \long\def\addplot{% - \@ifnextchar[{% - \axis@addplotimpl% - }{% + \@ifnextchar+{% \axis@getautoplotspec into\nextplotspec - % the space after ']' is required here: - % FIXME: - % - \addplot[]plot coordinates is NOT allowed!? - \expandafter\axis@addplotimpl\expandafter[\nextplotspec] + \axis@addplotimplAPPEND + }{% + \@ifnextchar[{% + \axis@addplotimpl% + }{% + \axis@getautoplotspec into\nextplotspec + % the space after ']' is required here: + % FIXME: + % - \addplot[]plot coordinates is NOT allowed!? + \expandafter\axis@addplotimpl\expandafter[\nextplotspec] + }% }% } +\long\def\axis@addplotimplAPPEND+[{% + \expandafter\axis@addplotimpl\expandafter[\nextplotspec, +} + \long\def\axis@addplotimpl[#1] #2;{% +%\tracingmacros=2\tracingcommands=2 % #2 = plot coordinates {...} \ifx\csname axis@execute at begin plot\endcsname\empty \else \csname axis@execute at begin plot\endcsname \fi - \axis@rememberplotspec{[#1]} + \axis@rememberplotspec{[#1]}% \ifaxis@filtercoords % FIXME : FREE THIS VARIABLE: - \axis@filtercoords#2\newplotcmdto\axis@filteredcoordinateplotcmd - \ifaxis@draw@at@end - \expandafter\axis@update@limits\axis@filteredcoordinateplotcmd;% - \fi - \def\axis@TMP{\axispath\draw[style=every axis plot,#1] }% - \expandafter\axis@TMP\axis@filteredcoordinateplotcmd;% - %\tracingmacros=2\tracingcommands=2 - %\tracingmacros=0\tracingcommands=0 + \axis@filtercoords@and@up@limits#2;\newplotcmdto\axis@filteredcoordinateplotcmd + \def\axis@TMP{\axispath@impl{\draw[style=every axis plot,#1]}}% + \expandafter\axis@TMP\axis@filteredcoordinateplotcmd% \else \ifaxis@draw@at@end - \axis@update@limits#2;% + \axis@update@limits{#2;}% \fi - \axispath\draw[style=every axis plot,#1] #2;% + \axispath@impl{\draw[style=every axis plot,#1]}#2;% \fi \ifx\csname axis@execute at end plot\endcsname\empty \else \csname axis@execute at end plot\endcsname \fi +%\tracingmacros=0\tracingcommands=0 }% -\long\def\axis@update@limits plot coordinates #1;{% -%\axis@update@limits@forpoint#1\axis@restinto\axis@TMP - \def\axis@TMP{#1}% - \def\axis@TMPB{ }% - \ifx\axis@TMPB\axis@TMP% FIXME isn't there a better way to exclude spaces!? - \let\axis@TMP=\empty - \fi - \loop - \ifx\axis@TMP\empty - \else - \expandafter\axis@update@limits@forpoint\axis@TMP\axis@restinto\axis@TMP - \ifx\axis@TMPB\axis@TMP% FIXME isn't there a better way to exclude spaces!? - \let\axis@TMP=\empty - \fi - \repeat +\long\def\axis@update@limits#1{% + \axis@foreach@plot@coord@do% + \axis@update@limits@for@one@point + \for + #1% + \EOI } -% #1: optional white spaces (will be ignored). FIXME is there a better -% way? I could not get \ignorespaces into this ... -\long\def\axis@update@limits@forpoint#1(#2,#3)#4\axis@restinto#5{% +% PRECONDITIONS: +% - 'floating point numerics active' +% => coordinate filtering is active +% => #1 and #2 are MACRO names +% => these macros are encoded with \scisetcomponents +% - no coordinate filters active +% => #1 and #2 MAY be macros, but they must be valid TeX +% length (without unit). +\long\def\axis@update@limits@for@one@point#1#2{% +%\tracingmacros=2\tracingcommands=2 +%\message{Updating limits for (#1,#2) ...}% \ifaxis@autocompute@xlim - \pgfmathlog@invoke@expanded\pgfmathmin@{{\axis@xmin}{#2}}% - \let\axis@xmin=\pgfmathresult - \pgfmathlog@invoke@expanded\pgfmathmax@{{\axis@xmax}{#2}}% - \let\axis@xmax=\pgfmathresult + \ifaxis@float@numerics@mode@x +%\scitofixedsingle\axis@xmin\axis@TMP +%\scitofixedsingle\axis@xmax\axis@TMPB +%\message{current limits: xmin=\axis@TMP, xmax=\axis@TMPB}% + \scigetcomponents#1\axis@tmp@S\axis@tmp@M\axis@tmp@E + \scigetcomponents\axis@xmin\axis@lim@S\axis@lim@M\axis@lim@E + \scimathmin% + \axis@lim@S\axis@lim@M\axis@lim@E + \and% + \axis@tmp@S\axis@tmp@M\axis@tmp@E + \to% + \axis@lim@S\axis@lim@M\axis@lim@E + \scisetcomponents\axis@xmin\axis@lim@S\axis@lim@M\axis@lim@E + % + \scigetcomponents\axis@xmax\axis@lim@S\axis@lim@M\axis@lim@E + \scimathmax% + \axis@lim@S\axis@lim@M\axis@lim@E + \and% + \axis@tmp@S\axis@tmp@M\axis@tmp@E + \to% + \axis@lim@S\axis@lim@M\axis@lim@E + \scisetcomponents\axis@xmax\axis@lim@S\axis@lim@M\axis@lim@E +%\scitofixedsingle\axis@xmin\axis@TMP +%\scitofixedsingle\axis@xmax\axis@TMPB +%\message{updated limits: xmin=\axis@TMP, xmax=\axis@TMPB}% + \else + \pgfmathmin{\axis@xmin}{#1}% + \let\axis@xmin=\pgfmathresult + \pgfmathmax{\axis@xmax}{#1}% + \let\axis@xmax=\pgfmathresult + \fi \fi \ifaxis@autocompute@ylim - \pgfmathlog@invoke@expanded\pgfmathmin@{{\axis@ymin}{#3}}% - \let\axis@ymin=\pgfmathresult - \pgfmathlog@invoke@expanded\pgfmathmax@{{\axis@ymax}{#3}}% - \let\axis@ymax=\pgfmathresult + \ifaxis@float@numerics@mode@y +%\scitofixedsingle\axis@ymin\axis@TMP +%\scitofixedsingle\axis@ymax\axis@TMPB +%\message{current limits: ymin=\axis@TMP, ymax=\axis@TMPB}% + \scigetcomponents#2\axis@tmp@S\axis@tmp@M\axis@tmp@E + \scigetcomponents\axis@ymin\axis@lim@S\axis@lim@M\axis@lim@E + \scimathmin% + \axis@lim@S\axis@lim@M\axis@lim@E + \and% + \axis@tmp@S\axis@tmp@M\axis@tmp@E + \to% + \axis@lim@S\axis@lim@M\axis@lim@E + \scisetcomponents\axis@ymin\axis@lim@S\axis@lim@M\axis@lim@E + % + \scigetcomponents\axis@ymax\axis@lim@S\axis@lim@M\axis@lim@E + \scimathmax% + \axis@lim@S\axis@lim@M\axis@lim@E + \and% + \axis@tmp@S\axis@tmp@M\axis@tmp@E + \to% + \axis@lim@S\axis@lim@M\axis@lim@E + \scisetcomponents\axis@ymax\axis@lim@S\axis@lim@M\axis@lim@E +%\scitofixedsingle\axis@ymin\axis@TMP +%\scitofixedsingle\axis@ymax\axis@TMPB +%\message{updated limits: ymin=\axis@TMP, ymax=\axis@TMPB}% + \else + \pgfmathmin{\axis@ymin}{#2}% + \let\axis@ymin=\pgfmathresult + \pgfmathmax{\axis@ymax}{#2}% + \let\axis@ymax=\pgfmathresult + \fi \fi - \def#5{#4}% \axis@limits@are@computedtrue +%\tracingmacros=0\tracingcommands=0 } % Filters coordinates and writes a new, modified 'plot coordinates' % command to macro #2. -\long\def\axis@filtercoords plot coordinates #1\newplotcmdto#2{% - %\edef#2{plot coordinates \verb|}|}% +\long\def\axis@filtercoords@and@up@limits#1\newplotcmdto#2{% \let#2=\empty - \def\axis@TMP{#1}% - \def\axis@TMPB{ }% - \ifx\axis@TMPB\axis@TMP% FIXME isn't there a better way to exclude spaces!? - \let\axis@TMP=\empty - \fi - \loop - \ifx\axis@TMP\empty - \else - \expandafter\axis@filter@point\axis@TMP\appendto#2\axis@restinto\axis@TMP - \ifx\axis@TMPB\axis@TMP% FIXME isn't there a better way to exclude spaces!? - \let\axis@TMP=\empty - \fi - \repeat - \edef#2{plot coordinates {#2}}% -} + \let\axis@filter@output=#2 + \axis@foreach@plot@coord@do% + \axis@filter@one@coord@pair + \for + #1% + \EOI + \edef#2{plot coordinates {\axis@filter@output};}% +}% -% #1: optional white spaces (will be ignored). FIXME is there a better -% way? I could not get \ignorespaces into this ... -\long\def\axis@filter@point#1(#2,#3)#4\appendto#5\axis@restinto#6{% +\def\axis@filter@one@coord@pair#1#2{% \ifx\axis@xfilter\empty - \def\axis@filter@tmpx{#2}% + \def\axis@filter@tmp@x{#1}% \else - \let\axis@filter@tmpx=\empty - \axis@xfilter#2\to\axis@filter@tmpx\relax + \let\axis@filter@tmp@x=\empty + \axis@xfilter#1\to\axis@filter@tmp@x \fi \ifx\axis@yfilter\empty - \def\axis@filter@tmpy{#3}% + \def\axis@filter@tmp@y{#2}% \else - \let\axis@filter@tmpy=\empty - \axis@yfilter#3\to\axis@filter@tmpy\relax + \let\axis@filter@tmp@y=\empty + \axis@yfilter#2\to\axis@filter@tmp@y \fi - \ifx\axis@filter@tmpx\empty - \message{NOTE: coordinate (#2,#3) has been dropped because of the x-coordinate filter.}% + \ifx\axis@filter@tmp@x\empty + \message{NOTE: coordinate (#1,#2) has been dropped because of the x-coordinate filter.}% \else - \ifx\axis@filter@tmpy\empty - \message{NOTE: coordinate (#2,#3) has been dropped because of the y-coordinate filter.}% + \ifx\axis@filter@tmp@y\empty + \message{NOTE: coordinate (#1,#2) has been dropped because of the y-coordinate filter.}% \else - \edef#5{#5 (\axis@filter@tmpx,\axis@filter@tmpy)}% + \ifaxis@draw@at@end + % update also axis limits: + \axis@update@limits@for@one@point{\axis@filter@tmp@x}{\axis@filter@tmp@y}% + \else + % apply data transformation directly. + \ifaxis@float@numerics@mode@x + \axis@datascaletrafo@x\axis@filter@tmp@x\to\axis@filter@tmp@x + \fi + \ifaxis@float@numerics@mode@y + \axis@datascaletrafo@y\axis@filter@tmp@y\to\axis@filter@tmp@y + \fi + \fi + % remind: + % \the\tokenregister + % will yield the contents of the token register, it will + % NOT expand recursively (like \expandafter)! + % + % Employ that here to maintain macros inside of + % \axis@filter@tmp[xy] + % (macros inside of those things are used by the floating + % point numerics to scale input data to TeX-lengths) + \pgfplots@toka=\expandafter{\axis@filter@output}% + \TOKL@ta=\expandafter{\axis@filter@tmp@x}% + \TOKL@tb=\expandafter{\axis@filter@tmp@y}% + \edef\axis@filter@output{\the\pgfplots@toka (\the\TOKL@ta,\the\TOKL@tb)}% +%\message{FILTERING: appended \axis@filter@tmp@x,\axis@filter@tmp@y}% -> results in \axis@filter@output}% \fi \fi - \def#6{#4}% } + +% A looping command to loop through plot coordinates. +% For every point, #3{X}{Y} will be invoked. +% +% No scoping is used during this operation, so you can access outer +% variables. +\long\def\axis@foreach@plot@coord@do#1\for plot coordinates #2;\EOI{% + \axis@foreach@plot@coord@ITERATE#1\n#2\EOI% +} + +\def\axis@foreach@plot@coord@ITERATE#1\n{% + \@ifnextchar;{% + \axis@foreach@plot@coord@FINISH@SEMICOLON% + }{% + \@ifnextchar\EOI{% + \axis@foreach@plot@coord@FINISH% + }{% + \axis@foreach@plot@coord@NEXT#1\n% + }% + }% +} + +\def\axis@foreach@plot@coord@NEXT#1\n(#2,#3){% + #1{#2}{#3}% + \axis@foreach@plot@coord@ITERATE#1\n +} + +\def\axis@foreach@plot@coord@FINISH\EOI{} +\def\axis@foreach@plot@coord@FINISH@SEMICOLON;\EOI{} + +% INPUT: +% a sequence of points (SMeE,SMeE) (terminated with ';') +% where S=sign, M=mantisse, E = exponent. +% Such input is generated in the case axis@float@numerics@modetrue +% by the coordinate filters. +% OUTPUT: +% proper sequence of fixed point coordinates which are the result of the +% data scaling transformation (\axis@datascaletrafo@x). +% +% The output will be written into the macro #1. +\long\def\axis@apply@data@scaletrafo@to@plot@data#1\to#2{% + \let#2=\empty + \let\axis@data@scaletrafo@result=\empty + \axis@foreach@plot@coord@do + \axis@apply@data@scaletrafo@to@one@point + \for + #1% + \EOI + \edef#2{plot coordinates {\axis@data@scaletrafo@result};}% + %\axis@apply@data@scaletrafo@to@plot@data@ITERATE\to#2 #1;% +} + +\def\axis@apply@data@scaletrafo@to@one@point#1#2{% + \ifaxis@float@numerics@mode@x + \axis@decode@filtered@float@numerics#1\to\axis@filter@tmp@x + \axis@datascaletrafo@x\axis@filter@tmp@x\to\axis@filter@tmp@x + \else + \def\axis@filter@tmp@x{#1}% + \fi + \ifaxis@float@numerics@mode@y + \axis@decode@filtered@float@numerics#2\to\axis@filter@tmp@y + \axis@datascaletrafo@y\axis@filter@tmp@y\to\axis@filter@tmp@y + \else + \def\axis@filter@tmp@y{#2}% + \fi + \edef\axis@data@scaletrafo@result{\axis@data@scaletrafo@result (\axis@filter@tmp@x,\axis@filter@tmp@y)}% +} + + +\def\axis@decode@filtered@float@numerics#1#2e#3\to#4{% + \scisetcomponents#4{#1}{#2}{#3}% +} + + \long\def\axispath#1;{% + \axispath@impl{}#1; +} + +% low-level \axispath implementation. +% #1: +% the command which is responsable for drawing. +% - If #1 is NOT '\empty', we expect #2 to contain only +% EXPANDABLE DATA. +% That's important for postponed floating point arithmetics in #2. +% - If #1='\empty', we don't make any assumption about #2 +% and process it as-is. +% +% #2: see above. +\long\def\axispath@impl#1#2;{% \ifaxis@draw@at@end - \listpushback{#1;}\to\axis@draw@stored@plots% + \listpushback{#1}\to\axis@stored@plot@cmds + \listpushback{#2;}\to\axis@stored@plot@data \else - #1;% + #1#2;% \fi } @@ -668,27 +944,14 @@ % Assigns a legend. % Syntax: % \legend{entry 1\\entry2\\entry3} -% or -% \legend[OPTIONS]{entry 1\\entry2\\} -% -% where OPTIONS is -% - textwidth=auto | DIMEN | none -% like -% \legend[textwidth=auto]{entry 1\\entry2\\} -% \legend[textwidth=2cm}{...} -% \legend[textwidth=none}{...} -% -% The option "textwidth=auto" chooses the correct width automatically; -% the option "textwidth=none" does not perform any line breaking and -% "textwidth=DIMEN" uses the fixed dimenion DIMEN for the (total) -% width of the legend. -% -% - font={...} -% \legend[font=\Huge}{...} \newcommand{\legend}[2][]{ {% \globaldefs=1% this will ONLY store the options and the legend into global variables - \setkeys[\prefix]{legend}{#1}% + \def\axis@TMP{#1}% + \ifx\axis@TMP\empty + \else + \errmessage{Sorry, legend are now deprecated. Legends are now TikZ-matrizes which provide better alignment and can be placed horizontally. See the manual for details.}% + \fi \def\axis@TMP{#2}% \ifx\axis@TMP\empty \else @@ -704,7 +967,7 @@ }% } -\def\getnextlegend{{% +\def\axis@pop@next@legend{{% \globaldefs=1 \listcheckempty\axis@plotspeclist \iflistempty @@ -722,116 +985,109 @@ \advance\axis@numplots by-1 }} -\def\axis@setlegendfont{% - \tikz@textfont - \axis@legend@font -} - -% Helper function for \axis@createlegend -% It assigns the TOTAL width of the legend node to -% the dimension register #1 and the option to #2 as macro. -% Arguments: -% #1 a temporary dimension register which will be filled with the -% width. -% #2 a macro name which will be filled with 'text width=XXXX'. -% WARNING: -% this function use the variables -% - \axis@legend@textwidth (from keyval, see above) -% - \axis@TMP -% - \legendCOORDC -% - \legendHSEP -\def\axis@legend@determinewidth\to#1\optionto#2{% - \def\axis@TMP{auto}% - \ifx\axis@legend@textwidth\axis@TMP - % OPTION - % \legend[textwidth=auto] +\long\def\axis@show@small@legendplots#1{ + \draw#1 + [mark repeat=2,mark phase=2] + plot coordinates { + (0cm,0cm) + (0.3cm,0cm) + (0.6cm,0cm)% + };% +} + +% Typesets a legend node. +% +% It will either typeset a previously computed legend (which needs to be +% stored in the macro \axis@already@computed@legend@node) +% +% or it creates a legend, stores the commands into the macro named +% above and typesets it. +\newcommand\axis@createlegend{% + \ifx\axis@already@computed@legend@node\empty + \listcheckempty\axis@legend + \iflistempty + \else % - % STEP 1: maximum width legend entries - #1=0cm + % \begingroup - \listforeach\axis@legend\as\axis@curlegend{% - \setbox0=\hbox{{% - \pgfutil@selectfont% RESTORE normal fonts (have been resetted by PGF) - \axis@setlegendfont - \axis@curlegend% - }}% - \ifdim\wd0>#1 - \global#1=\wd0 - \fi - }% + % assemble a + % \matrix { + % small plot & legend1\\ + % small plot & legend2\\ + % ... + % }; + % command [and using the 'legend columns' option] + % + % \TOKL@ta={ + % small plot & legend1\\ + % small plot & legend2\\ + % ... + % } + % ( I have allocated the token register in my simplelist.sty) + % + % \global\def\axis@TMP{ + % \matrix { + % \TOKL@TA + % }; + % } + % -> finally, \axis@TMP will contain the complete command. + \TOKL@ta={}% + \let\curcolumnNum=\c@pgf@counta + \let\maxcolumnCount=\c@pgf@countb + \let\legendplotpos=\c@pgf@countc + \legendplotpos\expandafter=\axis@legend@plot@pos + \curcolumnNum=0 + \maxcolumnCount\expandafter=\csname axis@legend columns\endcsname\relax + % + \loop + \ifnum0<\axis@numplots\relax + \axis@pop@next@legend + \ifx\axis@curlegend\empty + \else + \advance\curcolumnNum by1 + \edef\axis@TMP{% + \the\TOKL@ta + \ifcase\legendplotpos + % legend plot pos=left + \noexpand\axis@show@small@legendplots{\axis@curplotlist}% + \noexpand\pgfmatrixnextcell + \noexpand\node {\axis@curlegend}; + \or + % legend plot pos=right + \noexpand\node {\axis@curlegend}; + \noexpand\pgfmatrixnextcell + \noexpand\axis@show@small@legendplots{\axis@curplotlist}% + \or + % legend plot pos=none + \noexpand\node {\axis@curlegend}; + \fi + \ifnum\curcolumnNum=\maxcolumnCount + \noexpand\\ + \else + \ifnum\axis@numplots=0 + \noexpand\\ + \else + \noexpand\pgfmatrixnextcell + \fi + \fi + }% + \ifnum\curcolumnNum=\maxcolumnCount + \curcolumnNum=0 + \fi + \expandafter\TOKL@ta\expandafter{\axis@TMP}% + \fi + \repeat + \TOKL@tb={\matrix[style=every axis legend]}% + \xdef\axis@TMP{% + \the\TOKL@tb {% + \the\TOKL@ta + };% + }% \endgroup - % STEP 2: add plot spec width: - \expandafter\axis@tmpb\legendCOORDC - \advance#1 by\axis@tmpb - % STEP 3: hspace between plot spec and legend: - \advance#1 by\legendHSEP - %\advance#1 by1pt% FIXME I don't know why there was to few place!? - \def#2{text width=\the#1,}% - \else - \def\axis@TMP{none}% - \ifx\axis@legend@textwidth\axis@TMP - % OPTION - % \legend[textwidth=none] - % don't make a '\node[text width=XX]' option: - #1=0cm - \def#2{}% - \else - % OPTION - % \legend[textwidth=2cm] - % just use it: - \expandafter#1\axis@legend@textwidth - \def#2{text width=\the#1,}% + \let\axis@already@computed@legend@node=\axis@TMP \fi \fi - % -} - -\newcommand\axis@createlegend{% - \listcheckempty\axis@legend - \iflistempty - \else - % - \def\legendHSEP{5pt}% - \def\legendCOORDB{0.3cm}% - \def\legendCOORDC{0.6cm}% - % - \axis@legend@determinewidth\to\pgf@xa\optionto\axis@TMP - % - % - % This code here invokes - % \node[<CONTENTS OF \axis@TMP>, - % ... - % ] - % where \axis@TMP contains a "text width=XXX" option. - %DEBUG: - %\draw[red] (0,0) rectangle (1,1); - \expandafter\node\expandafter[\axis@TMP% - style=every axis legend] - {% - \loop\ifnum0<\axis@numplots - \getnextlegend - \ifx\axis@curlegend\empty - \else - \vbox{% - \noindent - \begin{minipage}[c]{\legendCOORDC}% - \tikz - \expandafter\draw\axis@curplotlist - [mark repeat=2,mark phase=2] - plot coordinates { - (0cm,0cm) - (\legendCOORDB,0cm) - (\legendCOORDC,0cm)};% - \hss - \end{minipage} - %\expandafter\hskip\legendHSEP - \axis@setlegendfont - \axis@curlegend - }% - \fi - \repeat - }; - \fi + \axis@already@computed@legend@node } % Checks whether the argument to xtick or ytick is a UNIFORM tick @@ -857,18 +1113,19 @@ \begingroup \global\axis@isuniformticktrue \newif\ifisfirst + \newif\iftwo@are@equal \isfirsttrue \foreach \x in {#1}{% - \pgfmathlog@invoke@expanded\pgfmathdivide@{{\x}{\logten}}% + \pgfmathmultiply@\x\reciproc@logten \let\cur=\pgfmathresult % check whether % \cur - last == 1 (last = \axis@TMPB) \ifisfirst \global\isfirstfalse \else - \pgfmathlog@invoke@expanded\pgfmathsubtract@{{\cur}{\axis@TMPB}}% - \def\axis@TMP{1.0}% - \ifx\axis@TMP\pgfmathresult + \pgfmathsubtract@\cur\axis@TMPB% + \pgfmathlog@approxequalto@macro\pgfmathresult{1.0}{two@are@equal}% + \iftwo@are@equal \else \global\axis@isuniformtickfalse \breakforeach @@ -892,14 +1149,14 @@ } \def\logtologtentomacro#1#2{% - \pgfmathlog@invoke@expanded\pgfmathdivide@{{#1}{\logten}}% + \pgfmathmultiply@{#1}\reciproc@logten% \expandafter\skipsuffixzero\pgfmathresult|% \let#2=\pgfmathresult } % Expands to #1/log(10). It will also skip a suffix '.0' \def\logtologten#1{% - \pgfmathlog@invoke@expanded\pgfmathdivide@{{#1}{\logten}}% + \pgfmathmultiply@{#1}\reciproc@logten% \expandafter\skipsuffixzero\pgfmathresult|% \pgfmathresult } @@ -909,7 +1166,7 @@ \def\axis@compute@tick@times@logten#1\to#2{% \global\let#2=\empty \foreach \axis@TMPB in {#1} {% - \pgfmathlog@invoke@expanded\pgfmathmultiply@{{\axis@TMPB}{\logten}}% + \pgfmathmultiply@\axis@TMPB\logten% \ifx#2\empty \xdef#2{\pgfmathresult}% \else @@ -918,43 +1175,77 @@ }% } -\def\axis@enlarge@xlim{% - \ifcase\axis@xmode - \pgfmathlog@invoke@expanded\pgfmathsubtract@{{\axis@xmin}{0.5}}% - \let\axis@xmin=\pgfmathresult - \pgfmathlog@invoke@expanded\pgfmathadd@{{\axis@xmax}{0.5}}% - \let\axis@xmax=\pgfmathresult +\def\axis@init@enlarge@limit@booleans{% + \axis@enlargelimits@autofalse + \axis@enlargelimitsfalse + \axis@enlargelimits@rel@threshfalse + \edef\axis@TMP{\axis@enlargelimits}% + % + \def\axis@TMPB{true}% + \ifx\axis@TMP\axis@TMPB + \axis@enlargelimitstrue + \else + \def\axis@TMPB{false}% + \ifx\axis@TMP\axis@TMPB + \else + \def\axis@TMPB{auto}% + \ifx\axis@TMP\axis@TMPB + \axis@enlargelimits@autotrue + \else + \begingroup + % try to read it as number: + \expandafter\pgf@xa\axis@enlargelimits pt\relax + \endgroup + \axis@enlargelimitstrue + \axis@enlargelimits@rel@threshtrue + \fi + \fi + \fi +} + +\def\axis@enlarge@limit@for#1{% + \begingroup + \expandafter\let\expandafter\min\expandafter=\csname axis@#1min\endcsname + \expandafter\let\expandafter\max\expandafter=\csname axis@#1max\endcsname + \ifcase\csname axis@#1mode\endcsname + \ifaxis@enlargelimits@rel@thresh + \edef\enlargepercent{\axis@enlargelimits}% + \else + \def\enlargepercent{0.1}% FIXME : pack 10% as default into option 'enlargelimits' or so + \fi + \pgfmathsubtract@\max\min% + \expandafter\pgf@xa\pgfmathresult pt + \expandafter\pgf@xb\enlargepercent\pgf@xa + \ifdim\pgf@xb>0.001pt + % the case with + % enlargeabsolute ~= 0 + % means that \min ~= \max. + % It is handled in another method. + \edef\enlargeabsolute{\pgf@sys@tonumber{\pgf@xb}}% + % + % compute xmin := xmin - enlargeabsolute + \pgfmathsubtract@\min\enlargeabsolute% + \let\min=\pgfmathresult + \pgfmathadd@\max\enlargeabsolute% + \let\max=\pgfmathresult + \fi \or % compute - % \pgfmathsetmacro{\axis@xmin}{\axis@xmin - 0.5*\logten}% - % \pgfmathsetmacro{\axis@xmax}{\axis@xmax + 0.5*\logten}% + % \pgfmathsetmacro{\min}{\min - 0.5*\logten}% + % \pgfmathsetmacro{\max}{\max + 0.5*\logten}% % just a more efficiently (I hope so): \expandafter\pgfmath@x\logten pt \divide\pgfmath@x by2 - \pgfmathlog@invoke@expanded\pgfmathsubtract@{{\axis@xmin}{\pgf@sys@tonumber{\pgfmath@x}}}% - \let\axis@xmin=\pgfmathresult - \pgfmathlog@invoke@expanded\pgfmathadd@{{\axis@xmax}{\pgf@sys@tonumber{\pgfmath@x}}}% - \let\axis@xmax=\pgfmathresult - \fi -} -\def\axis@enlarge@ylim{% - \ifcase\axis@ymode - \pgfmathlog@invoke@expanded\pgfmathsubtract@{{\axis@ymin}{0.5}}% - \let\axis@ymin=\pgfmathresult - \pgfmathlog@invoke@expanded\pgfmathadd@{{\axis@ymax}{0.5}}% - \let\axis@ymax=\pgfmathresult - \or - % compute - % \pgfmathsetmacro{\axis@ymin}{\axis@ymin - 0.5*\logten}% - % \pgfmathsetmacro{\axis@ymax}{\axis@ymax + 0.5*\logten}% - % just a more efficiently (I hope so): - \expandafter\pgfmath@y\logten pt - \divide\pgfmath@y by2 - \pgfmathlog@invoke@expanded\pgfmathsubtract@{{\axis@ymin}{\pgf@sys@tonumber{\pgfmath@y}}}% - \let\axis@ymin=\pgfmathresult - \pgfmathlog@invoke@expanded\pgfmathadd@{{\axis@ymax}{\pgf@sys@tonumber{\pgfmath@y}}}% - \let\axis@ymax=\pgfmathresult + \pgfmathlog@invoke@expanded\pgfmathsubtract@{{\min}{\pgf@sys@tonumber{\pgfmath@x}}}% + \let\min=\pgfmathresult + \pgfmathlog@invoke@expanded\pgfmathadd@{{\max}{\pgf@sys@tonumber{\pgfmath@x}}}% + \let\max=\pgfmathresult \fi + \xdef\axis@TMP{\min}% + \xdef\axis@TMPB{\max}% + \endgroup + \expandafter\let\csname axis@#1min\endcsname=\axis@TMP + \expandafter\let\csname axis@#1max\endcsname=\axis@TMPB } % Computes tick positions using the current axis limits. @@ -963,13 +1254,32 @@ % \axisdefaulttickwidth % Determines the maximum space which is not filled by at least one % tick label (approximate, there is some rounding internally) +% \axisdefaulttryminticks +% see manual +% +% Idea: +% We want ticks at each +% { i*H, i in \Z }. +% Of course, there shouldn't be TOO MUCH ticks. +% +% Our heuristics is to set +% desirednumticks = round(ACTUAL WIDTH / axisdefaulttickwidth) +% and generate H = (axis range) / desirednumticks. % -% Heuristics: -% Set desirednumticks = trunc(ACTUAL WIDTH / axisdefaulttickwidth) +1 +% Since not all step sizes H look well, restrict H to a set of allowed +% step sizes such as +% { 1, 1/2, 1/5, 1/10 }, +% or, to be more precise: +% { 1*10^e, 2*10^e, 5*10^e } +% -> round to the nearest matching number! % -% and generate STEPSIZE = (axis range)/ desirednumticks +% Then, the resulting tick is +% TICK={MIN,MIN+H,...,MAX} +% where +% MIN = I*H +% is chosen such that +% axis minimum limit = I*H + rest; |rest| < H. % -% We actually restrict STEPSIZE to { 1, 1/2, 1/5, 1/10 } % % PRECONDITION: % - limits are correct @@ -980,6 +1290,11 @@ % - \ifaxis@needs@check@uniformtick is set \def\axis@assign@default@tick@foraxis#1{% \begingroup + % Shortcut-names: + \expandafter\let\expandafter\ifaxis@is@datascaled\csname ifaxis@float@numerics@mode@#1\endcsname + \expandafter\let\expandafter\axis@data@scale@trafo\csname axis@datascaletrafo@#1\endcsname + \expandafter\let\expandafter\axis@data@scale@inverse@trafo\csname axis@inverse@datascaletrafo@#1\endcsname + % \let\desirednumticks=\c@pgf@countd \let\Wr=\pgf@xc \Wr=\csname axis@#1coordmaxTEX\endcsname @@ -988,48 +1303,89 @@ \expandafter\expandafter\divide\Wr\axisdefaulttickwidth \pgfmathsetcount{\desirednumticks}{\Wr}% \advance\desirednumticks by1 + \expandafter\ifnum\axisdefaulttryminticks>\desirednumticks + \expandafter\desirednumticks\axisdefaulttryminticks + \fi \ifcase\csname axis@#1mode\endcsname - % compute tick := MIN-h,MIN,....,MAX+h - % where h is a determined step size and MIN and MAX are - % (truncated) axis limits. - % - % The MIN-h and MAX+h is to support compatibility with the - % enlargelimits option - there should be ticks in the - % enlarged place. - \pgfmathsetcount{\c@pgf@counta}{\csname axis@#1min\endcsname}% - %\pgfmathsetcount{\c@pgf@countb}{\csname axis@#1max\endcsname}% - \expandafter\ifdim\csname axis@#1min\endcsname pt<0pt - % the truncation round TOWARDS 0 which is not what I want. - \advance\c@pgf@counta by-1 - \fi + % compute tick := MIN,MIN+H,....,MAX \let\MINH=\pgf@xa \let\H=\pgf@xb \let\MAX=\axis@tmpa \let\MIN=\axis@tmpb - % compute step size 'h': + % compute step size 'H': \expandafter\MAX\csname axis@#1max\endcsname pt \advance\MAX by0.001pt% avoid round errors - \expandafter\MIN\the\c@pgf@counta pt + %\expandafter\MIN\the\c@pgf@counta pt + \expandafter\MIN\csname axis@#1min\endcsname pt \H=\MAX \advance\H by-\MIN \c@pgf@counta=\desirednumticks \advance\c@pgf@counta by-1 \divide\H by\c@pgf@counta - %\message{Wr\the\Wr, desirednumticks=\the\desirednumticks, H=\the\H}% - \ifdim\H<0.10001pt - \H=0.1pt +%\message{determining ticks for #1-axis: Wr := (width/max space between ticks) = \the\Wr, desirednumticks=max(\axisdefaulttryminticks, trunc(Wr)) = \the\desirednumticks, H=(axis range/(desirednumticks-1)) = \the\H}% + % + % SEARCH for the NEXT FEASABLE H. + % + \edef\Hmacro{\pgf@sys@tonumber\H}% + \ifaxis@is@datascaled + \expandafter\axis@data@scale@inverse@trafo\Hmacro\to\Hmacro + \else + \expandafter\sciparsesignsingle\expandafter{\Hmacro}\Hmacro + \fi + \scigetcomponents\Hmacro\H@S\H@M\H@E +%\message{Got T^{-1}(H) = [\H@S] \H@M * 10^\H@E}% + % modify the mantisse: + \expandafter\H\H@M pt + \ifdim\H<2pt + \ifdim\H<1.5pt + \def\H@M{1.0}% + \else + \def\H@M{2.0}% + \fi \else - \ifdim\H<0.20001pt - \H=0.2pt + \ifdim\H<4.9999pt + \ifdim\H<3.5pt + \def\H@M{2.0}% + \else + \def\H@M{5.0}% + \fi \else - \ifdim\H<0.5001pt - \H=0.5pt + \ifdim\H<7.5pt + \def\H@M{5.0}% \else - \H=1pt + \def\H@M{1.0}% + \expandafter\c@pgf@counta\H@E + \advance\c@pgf@counta by1 + \edef\H@E{\the\c@pgf@counta}% \fi \fi \fi - %\message{final H=\the\H}% + \scisetcomponents\Hmacro\H@S\H@M\H@E + \ifaxis@is@datascaled + \axis@data@scale@trafo\Hmacro\to\Hmacro + \else + \scitofixedsingle\Hmacro\Hmacro + \fi +%\message{I have computed H=\Hmacro}% + \expandafter\H\Hmacro pt +%\message{final H=\the\H}% + % + % Now, we want to activate the Tick set {i*H, i in \Z} + % compute I such that + % xmin = I * H + rest; |rest| < H + % -> I = round(xmin/H) + % -> MIN = I * H + \pgfmathlog@invoke@expanded\pgfmathdivide@{% + {\pgf@sys@tonumber\MIN}% + {\pgf@sys@tonumber\H}% + }% + \pgfmathsetcount{\c@pgf@counta}{\pgfmathresult}% + \ifdim\MIN<0pt + % the truncation rounds TOWARDS 0 which is not what I want. + \advance\c@pgf@counta by-1 + \fi + \MIN=\H + \multiply\MIN by\c@pgf@counta \MINH=\MIN \advance\MINH by\H \xdef\axis@TMP{\pgf@sys@tonumber{\MIN},\pgf@sys@tonumber{\MINH},...,\pgf@sys@tonumber{\MAX}}% @@ -1037,9 +1393,11 @@ \or \expandafter\ifx\csname axis@#1tickten\endcsname\empty % I want ticks at 10^k. So determine k_min and k_max. - \pgfmathsetcount{\c@pgf@counta}{\csname axis@#1min\endcsname/\logten-1}% + % + % FIXME: optimize! + \pgfmathsetcount{\c@pgf@counta}{\csname axis@#1min\endcsname*\reciproc@logten-1}% \pgfmathsetmacro{\tmp@min}{\c@pgf@counta*\logten}% - \pgfmathsetcount{\c@pgf@counta}{\csname axis@#1max\endcsname/\logten}% + \pgfmathsetcount{\c@pgf@counta}{\csname axis@#1max\endcsname*\reciproc@logten}% \pgfmathsetmacro{\tmp@max}{\c@pgf@counta*\logten}% \pgfmathadd\tmp@min\logten% \xdef\axis@TMP{\tmp@min,\pgfmathresult,...,\tmp@max}% @@ -1052,55 +1410,182 @@ \fi \endgroup \expandafter\let\csname axis@#1tick\endcsname=\axis@TMP - %\message{pgfplots.sty: #1tick set to \csname axis@#1tick\endcsname [#1mode=\the\csname axis@#1mode\endcsname, #1min=\csname axis@#1min\endcsname, #1max=\csname axis@#1max\endcsname].}% +%\message{pgfplots.sty: #1tick set to \csname axis@#1tick\endcsname [#1mode=\the\csname axis@#1mode\endcsname, #1min=\csname axis@#1min\endcsname, #1max=\csname axis@#1max\endcsname].}% } -\def\axis@determinedefaultvalues{% - % NOTIZ: +% Helper method for +% \axis@apply@data@scale@trafo@to@options@for +% #1: the ticks +% #2: the trafo macro name (the form taking three args) +% #3: the output macro name +\long\def\axis@apply@data@scale@trafo@to@user@ticks#1#2\to#3{% + \let#3=\empty + \foreach \axis@TMPB in {#1} {% + \expandafter\sciparsesign\expandafter{\axis@TMPB}\sci@S\sci@M\sci@E + #2\sci@S\sci@M\sci@E\to\axis@TMPB + \ifx#3\empty + \xdef#3{\axis@TMPB}% + \else + \xdef#3{#3,\axis@TMPB}% + \fi + }% + % +}% + +% helper for \axis@apply@data@scale@trafo@to@options@for. +\def\axis@compute@number@order@for@trafo@isdimen#1\tocount#2{% + \edef\axis@TMP{\pgf@sys@tonumber{#1}}% + \expandafter\sciparsesign\expandafter{\axis@TMP}\S\M\E + \expandafter#2\E\relax + \advance#2 by1 +} + +% helper for \axis@apply@data@scale@trafo@to@options@for. +% +\def\axis@compute@number@order@for@trafo@isfloat#1\tocount#2{% + \scigetcomponents#1\S\M\E + \expandafter#2\E\relax + \advance#2 by1 +} + +% Initialises the data scale transformation and applies it to any +% user specified options. +% +% PRECONDITION: +% - all axis limits are available in float representation +% (i.e. with \scisetcomponents) +% - \axis@set@default@size@options has been called before +% POSTCONDITION: +% - the scaling transformation is set up, +% - all axis limits are transformed, +% - any user input (like ticks and tick labels) +% will reflect the changes. +\def\axis@apply@data@scale@trafo@to@options@for#1{% + % initialise data scale transformation + % T(x) = 10^{q-m} * x + % + \begingroup + \let\data@max@order=\c@pgf@counta + \let\data@cur@order=\c@pgf@countb + \let\data@dimen=\pgf@xa + \let\data@dimen@order=\c@pgf@countc + % + % Step 1: compute 'm', the data order + \expandafter\axis@compute@number@order@for@trafo@isfloat + \csname axis@#1min\endcsname + \tocount\data@cur@order + % + \data@max@order=\data@cur@order + % + \expandafter\axis@compute@number@order@for@trafo@isfloat + \csname axis@#1max\endcsname + \tocount\data@cur@order % - % wenn ich AUTOMATISCH aus (x_i,y_i) - % [xy]min und [xy]max ausrechnen will, muss ich - % ggf. - % xmin = min_{i} { untere_gaussklammer(log(x_i) / log10) } - % rechnen + \ifnum\data@cur@order>\data@max@order + \data@max@order=\data@cur@order + \fi + % + % Step 2: compute 'q', the #1-size of the axis. + \expandafter\ifx\csname axis@#1\endcsname\empty + % We have 'width' or 'height'. + % + % Use the order of these parameters. + \def\axis@TMP{#1}% + \def\axis@TMPB{x}% + \ifx\axis@TMP\axis@TMPB + \expandafter\data@dimen\axis@width\relax + \else + \def\axis@TMPB{y}% + \ifx\axis@TMP\axis@TMPB + \expandafter\data@dimen\axis@height\relax + \fi + \fi + \axis@compute@number@order@for@trafo@isdimen + \data@dimen + \tocount\data@dimen@order + % This here is to avoid inaccuracies in the final + % axis rectangle size, see \axis@initsizes: + \advance\data@dimen@order by-1 + \else + % FIXME: + % we have either the 'x=1cm' or 'y=1cm' option! + % How should I initialise the trafo!? + \data@dimen@order=3 + \fi + % +%\message{Direction #1: data max order=\the\data@max@order; data dimen order=\the\data@dimen@order. }% + \advance\data@dimen@order by-\data@max@order + \xdef\axis@TMP{\the\data@dimen@order}% + \endgroup +%\message{Initialising the data scale transformation in direction #1 to \axis@TMP...}% + % COMPLETE INITIALISATION: + \ifaxis@EMERGENCY@FORCE@DATA@TRAFO@TO@IDENTITY + \message{WARNING: the automatic scaling of input data has been DISABLED to allow axispath commands [otherwise, axispath commands would not know of the pgfplots scalings - leading to wrong images). DISABLING THE DATA SCALING LIMITS THE DATA RANGE! I hope I can fix this issue as soon as possible. Please take a look at the manual for more information. If you get 'OVERFLOW' or 'UNDERFLOW' errors, you may need to disable the axispath.}% + \def\axis@TMP{0}% + \expandafter\let\csname axis@data@scale@trafo@SHIFT@#1\endcsname\axis@TMP + \else + \expandafter\let\csname axis@data@scale@trafo@SHIFT@#1\endcsname\axis@TMP + \fi + % + % ... and apply transformation to any user input + % + % Transform axis limits: + \expandafter\expandafter\csname axis@datascaletrafo@#1\endcsname\csname axis@#1min\endcsname\to\axis@TMP + \expandafter\let\csname axis@#1min\endcsname=\axis@TMP + % + \expandafter\expandafter\csname axis@datascaletrafo@#1\endcsname\csname axis@#1max\endcsname\to\axis@TMP + \expandafter\let\csname axis@#1max\endcsname=\axis@TMP + % + % Convert any user-specified ticks: + \edef\axis@TMP{\csname axis@#1tick\endcsname}% + % this here should also work with 'xtick=\empty', the "No tick" command. + \ifx\axis@TMP\empty + \else +%\message{Converting #1tick='\csname axis@#1tick\endcsname'}% + \pgfplots@toka=\expandafter{\csname axis@datascaletrafo@#1@three\endcsname}% + \edef\axis@TMP{{\csname axis@#1tick\endcsname}\the\pgfplots@toka}% + \expandafter\axis@apply@data@scale@trafo@to@user@ticks\axis@TMP\to\axis@TMPC + \expandafter\let\csname axis@#1tick\endcsname=\axis@TMPC + \fi % + % Transform any explicit axis unit scalings: + \expandafter\ifx\csname axis@#1\endcsname\empty + \else +%\message{Converting #1 unit scale='\csname axis@#1\endcsname' ... }% + \expandafter\pgfmathparse\expandafter{\csname axis@#1\endcsname}% + \expandafter\expandafter\csname axis@inverse@datascaletrafo@tofixed@#1\endcsname\pgfmathresult\to\axis@TMP + \edef\axis@TMP{\axis@TMP pt}% + \expandafter\edef\csname axis@#1\endcsname{\axis@TMP}% +%\message{to #1='\csname axis@#1\endcsname'.}% + \fi +} + +\def\axis@determinedefaultvalues{% \ifx\axis@xmin\empty \errmessage{Sorry, the argument 'xmin=NUM' is mandatory to draw axes }% + \def\axis@xmin{0}% \fi \ifx\axis@xmax\empty \errmessage{Sorry, the argument 'xmax=NUM' is mandatory to draw axes }% + \def\axis@xmax{1}% \fi \ifx\axis@ymin\empty \errmessage{Sorry, the argument 'ymin=NUM' is mandatory to draw axes }% + \def\axis@ymin{0}% \fi \ifx\axis@ymax\empty \errmessage{Sorry, the argument 'ymax=NUM' is mandatory to draw axes }% + \def\axis@ymax{1}% \fi % + \axis@set@default@size@options % - \ifx\axis@trimxmin\empty - \else - \pgfmathlog@invoke@expanded\pgfmathmax@{{\axis@xmin}{\axis@trimxmin}}% - \let\axis@xmin=\pgfmathresult + \ifaxis@float@numerics@mode@x + \axis@apply@data@scale@trafo@to@options@for x% \fi - \ifx\axis@trimxmax\empty - \else - \pgfmathlog@invoke@expanded\pgfmathmin@{{\axis@xmax}{\axis@trimxmax}}% - \let\axis@xmax=\pgfmathresult - \fi - \ifx\axis@trimymin\empty - \else - \pgfmathlog@invoke@expanded\pgfmathmax@{{\axis@ymin}{\axis@trimymin}}% - %\pgfmathmax\axis@ymin\axis@trimymin% - \let\axis@ymin=\pgfmathresult + \ifaxis@float@numerics@mode@y + \axis@apply@data@scale@trafo@to@options@for y% \fi - \ifx\axis@trimymax\empty - \else - \pgfmathlog@invoke@expanded\pgfmathmin@{{\axis@ymax}{\axis@trimymax}}% - %\pgfmathmin\axis@ymax\axis@trimymax% - \let\axis@ymax=\pgfmathresult - \fi - % % \ifnum\axis@xmode=0 \axis@xminorticksfalse @@ -1108,23 +1593,35 @@ \ifnum\axis@ymode=0 \axis@yminorticksfalse \fi + % + \axis@init@enlarge@limit@booleans \ifaxis@enlargelimits % relax the sizes. % % Idea: if the user chose his xmin,xmax tight to his data, % this here will look better. - \axis@enlarge@xlim - \axis@enlarge@ylim + \axis@enlarge@limit@for x + \axis@enlarge@limit@for y \else - % FIXME : this here should be user-configurable! - \ifaxis@autocompute@xlim - \axis@enlarge@xlim - \fi - \ifaxis@autocompute@ylim - \axis@enlarge@ylim + \ifaxis@enlargelimits@auto + \ifaxis@hide + % there is no axis, so skip this enlargement (unless + % the user explizitly requests it) + \else + % FIXME : this here should be user-configurable! + \ifaxis@autocompute@xlim + \axis@enlarge@limit@for x + \fi + \ifaxis@autocompute@ylim + \axis@enlarge@limit@for y + \fi + \fi \fi \fi % + \axis@avoid@empty@axis@range@for x% + \axis@avoid@empty@axis@range@for y% + % \axis@initsizes % \newif\ifaxis@xisuniform @@ -1187,6 +1684,7 @@ \fi } + % Helper method for initsizes. % % It computes a scaling such that \axis@width = SCALE * ACTUAL WIDTH. @@ -1208,7 +1706,14 @@ % -> \axis@tmpXscale = (X - c) / (x *(xmax-xmin)) % % \axis@tmpa := X-c: - \advance\axis@tmpa by-45pt% FIXME determine 'c' correctly! + \ifaxis@scale@only@axis + \else + \advance\axis@tmpa by-45pt% FIXME determine 'c' correctly! + \fi + \ifdim\axis@tmpa<0pt + \errmessage{Error: Plot width `\axis@width' is too small. This can't be realised while maintaining constant width for y-labels. Sorry, label width are only approximate. You will need to adjust your width.}% + \axis@tmpa=0pt + \fi % \axis@tmpb := x*(xmax-xmin): \axis@tmpb=\axis@xcoordmaxTEX \advance\axis@tmpb by-\axis@xcoordminTEX @@ -1217,13 +1722,11 @@ {\pgf@sys@tonumber\axis@tmpb}% }% \let#1=\pgfmathresult - %-------------------------------------------------- - % \message{pgfplots.sty: Computing 'x' such that 'width = c + x*(xmax-xmin)'; - % c=estimated, - % width-c =\the\axis@tmpa, - % x*(xmax[=\the\axis@xcoordmaxTEX] - xmin[=\the\axis@xcoordminTEX)]) = \the\axis@tmpb - % -> x-scale =#1 }% - %-------------------------------------------------- +%\message{pgfplots.sty: Computing 'x' such that 'width = c + x*(xmax-xmin)'; +% c=estimated, +% width-c =\the\axis@tmpa, +% x*(xmax[=\the\axis@xcoordmaxTEX] - xmin[=\the\axis@xcoordminTEX)]) = \the\axis@tmpb +% -> x-scale =#1 }% } % The same as \axis@initsizes@getXscale, just for the height. @@ -1235,7 +1738,14 @@ % -> \axis@tmpXscale = (X - c) / (x *(xmax-xmin)) % % \axis@tmpa := X-c: - \advance\axis@tmpa by-45pt% FIXME determine 'c' correctly! + \ifaxis@scale@only@axis + \else + \advance\axis@tmpa by-45pt\relax% FIXME determine 'c' correctly! + \fi + \ifdim\axis@tmpa<0pt + \errmessage{Error: Plot height `\axis@height' is too small. This can't be realised while maintaining constant height for x-labels. Sorry, label heights are only approximate. You will need to adjust your height.}% + \axis@tmpa=0pt + \fi % \axis@tmpb := x*(xmax-xmin): \axis@tmpb=\axis@ycoordmaxTEX \advance\axis@tmpb by-\axis@ycoordminTEX @@ -1244,28 +1754,110 @@ {\pgf@sys@tonumber\axis@tmpb}% }% \let#1=\pgfmathresult - %-------------------------------------------------- - % \message{pgfplots.sty: Computing 'y' such that 'height = c + y*(ymax-ymin)'; - % %height=\axis@height, - % c=estimated, - % height-c =\the\axis@tmpa, - % y*(ymax[=\the\axis@ycoordmaxTEX] - ymin[=\the\axis@ycoordminTEX)]) = \the\axis@tmpb - % -> y-scale =#1 }% - %-------------------------------------------------- -} - -% PRECONDITION: correct axis limits -% POSTCONDITION: the current x- and y unit vectors are changed; -% \axis@[xy]coord{min,max}TEX are set +%\message{pgfplots.sty: Computing 'y' such that 'height = c + y*(ymax-ymin)'; +% height=\axis@height, +% c=estimated, +% height-c =\the\axis@tmpa, +% y*(ymax[=\the\axis@ycoordmaxTEX] - ymin[=\the\axis@ycoordminTEX)]) = \the\axis@tmpb +% -> y-scale =#1 }% +} + + +% Checks whether axis limits in coordinate #1 are approximately equal. % -\def\axis@initsizes{% - % INIT. - % - % The axes 'x' and 'y' vectors will be scaled such that the total - % size is (\axisdefaultwidth, \axisdefaultheight). - % - % If the user specifies ONE of width OR height, - % the plot will be resized; keeping the aspect ratio. +% If that is the case, force a non-zero width of the range. +% +\def\axis@avoid@empty@axis@range@for#1{% + % Check if axis limits are empty: + \begingroup + \expandafter\let\expandafter\if@cur@is@scaled\csname ifaxis@float@numerics@mode@#1\endcsname + \expandafter\let\expandafter\min\csname axis@#1min\endcsname + \expandafter\let\expandafter\max\csname axis@#1max\endcsname + \let\min@d=\pgf@xa + \let\max@d=\pgf@xb + \let\diff=\pgf@xc + \newif\ifrange@is@approx@equal + \expandafter\min@d\min pt + \expandafter\max@d\max pt + \diff=\max@d + \advance\diff by-\min@d + % FIXME : I need a RELATIVE check here! + % but: real number point division is expensive + \if@cur@is@scaled + % this here should be sufficient because the axis + % has absolute values of order O( 10^3 ) or so. + \ifdim\diff<1pt + \range@is@approx@equaltrue + \fi + \else + % there is no data scaling, so I should be much more defensive + % with absolute thresholds... + \ifdim\diff<0.05pt + \range@is@approx@equaltrue + \fi + \fi + \ifrange@is@approx@equal +%\message{avoid range is approx equal for coord #1: MODIFYING (\min,\max)...}% + % the case \min ~= \max + % + % enlarge \max and shrink \min: + \ifdim\max@d<0pt + \ifdim\max@d<-1pt + \max@d=0.8\max@d + \min@d=1.2\min@d + \else + \advance\max@d by-1pt + \advance\min@d by1pt + \fi + \else + \ifdim\max@d>1pt + \max@d=1.2\max@d + \min@d=0.8\min@d + \else + \ifdim\max@d=0pt + \if@cur@is@scaled + % we can't simply add a constant in the + % transformed range. + % + % So: set limits to [-1,1] = [-1.0e0,+1.0e0] + \def\sci@S{2}% + \def\sci@M{1.0}% + \def\sci@E{0}% + \csname axis@datascaletrafo@#1@three\endcsname\sci@S\sci@M\sci@E\to\min + \def\sci@S{1}% + \def\sci@M{1.0}% + \def\sci@E{0}% + \csname axis@datascaletrafo@#1@three\endcsname\sci@S\sci@M\sci@E\to\max +%\message{[trafo shift = \csname axis@data@scale@trafo@SHIFT@#1\endcsname; setting limits -1:1]}% + \expandafter\min@d\min pt + \expandafter\max@d\max pt + \else + \advance\max@d by1pt + \advance\min@d by-1pt + \fi + \else + \advance\max@d by1pt + \advance\min@d by-1pt + \fi + \fi + \fi + \xdef\axis@TMP{\pgf@sys@tonumber{\min@d}}% + \xdef\axis@TMPB{\pgf@sys@tonumber{\max@d}}% +%\message{ -> #1 = \axis@TMP : \axis@TMPB;}% + \else + \global\let\axis@TMP=\min% + \global\let\axis@TMPB=\max% + \fi + \endgroup + \expandafter\let\csname axis@#1min\endcsname=\axis@TMP + \expandafter\let\csname axis@#1max\endcsname=\axis@TMPB +} + +% PRECONDITION: +% none +% POSTCONDITION: +% \axis@default@aspect@ratio is set. +\def\axis@compute@default@aspect@ratio{% \expandafter\pgfmath@x\axisdefaultwidth \expandafter\pgfmath@y\axisdefaultheight \pgfmathlog@invoke@expanded\pgfmathdivide@{% @@ -1273,52 +1865,70 @@ {\pgf@sys@tonumber{\pgfmath@y}}% }% \let\axis@default@aspect@ratio=\pgfmathresult +} + +\def\axis@set@default@size@options{% + % The axes 'x' and 'y' vectors will be scaled such that the total + % size is (\axisdefaultwidth, \axisdefaultheight). % - \pgfpointxy{\axis@xmin}{\axis@ymin}% - \axis@xcoordminTEX=\pgf@x - \axis@ycoordminTEX=\pgf@y - \pgfpointxy{\axis@xmax}{\axis@ymax}% - \axis@xcoordmaxTEX=\pgf@x - \axis@ycoordmaxTEX=\pgf@y - % - %----------------------------------------- - % PROCESS THE 'width' and 'height' options - %----------------------------------------- + % If the user specifies ONE of width OR height, + % the plot will be resized; keeping the aspect ratio. % - % FIXME: make these variables LOCAL: - \let\axis@tmpXscale=\empty% - \let\axis@tmpYscale=\empty% + \let\axis@default@aspect@ratio=\empty % CASES: % hasx := 'x' option non-empty % hasy := 'y' option non-empty % W := 'width' option non-empty % H := 'height' option non-empty % - % hasx hasy - % 0 0 -> work depend on W and H: - % W H - % 0 0 -> use \axisdefaultwidth and \axisdefaultheight - % 0 1 -> determine s:=\axis@tmpYscale and y*=s, x*=s (aspect ratio) - % 1 0 -> determine s:=\axis@tmpXscale and " " " - % 1 1 -> use specified width and height - % 0 1 -> use specified y vector, xscale by 'W' option (NO ASPECT RATIO) - % W - % 0 -> use \axisdefaultwidth - % 1 -> determine s:=\axis@tmpXscale - % 1 0 -> use specified x vector, yscale by 'H' option (NO ASPECT RATIO) - % H - % 0 -> use \axisdefaultheight - % 1 -> determine s:=\axis@tmpYscale - % 1 1 -> use specified x AND y vector (ignore W and H) + % hasx = 1 -> width is not interesting; we use 'x' option. + % hasx = 0 -> determine final width: + % W H + % 0 0 -> \axisdefaultwidth + % 0 1 -> determine width out of H and the default aspect ratio + % 1 X -> ok, use the user parameter. + % + % hasy = 1 -> height is not interesting, we use 'y' option. + % hasy = 0 -> determine final height: + % W H + % 0 0 -> \axisdefaultheight + % X 1 -> ok, use the user parameter + % 1 0 -> determine height out of W and the default aspect ratio % \ifx\axis@x\empty \ifx\axis@y\empty - % The case hasx=0, hasy=0, W=0 H=0: - % the other cases for hasx=0, hasy=0 follow below. - \ifx\axis@width\empty\ifx\axis@height\empty - \let\axis@width=\axisdefaultwidth - \let\axis@height=\axisdefaultheight - \fi\fi + % hasx=0, hasy=0 + % + % -> KEEP ASPECT RATIO if just one W, or H is given! + \ifx\axis@width\empty + \ifx\axis@height\empty + % The case hasx=0, hasy=0, W=0 H=0: + \let\axis@width=\axisdefaultwidth + \let\axis@height=\axisdefaultheight + \else + % The case hasx=0, hasy=0, W=0 H=1: + \axis@compute@default@aspect@ratio + \expandafter\pgfmath@y\axis@height + \pgfmathlog@invoke@expanded\pgfmathmultiply@{% + {\pgf@sys@tonumber{\pgfmath@y}}% + {\axis@default@aspect@ratio}% + }% + \edef\axis@width{\pgfmathresult pt}% + \fi + \else + \ifx\axis@height\empty + % The case hasx=0, hasy=0, W=1 H=0: + \axis@compute@default@aspect@ratio + \expandafter\pgfmath@x\axis@width + \pgfmathlog@invoke@expanded\pgfmathdivide@{% + {\pgf@sys@tonumber{\pgfmath@x}}% + {\axis@default@aspect@ratio}% + }% + \edef\axis@height{\pgfmathresult pt}% + \else + % The case hasx=0, hasy=0, W=1 H=1: + \fi + \fi \else % hasx=0, hasy=1, W=0: \ifx\axis@width\empty @@ -1333,12 +1943,43 @@ \fi \fi \fi +} + +% PRECONDITION: +% - final axis limits are given in transformed range +% - \axis@set@default@size@options has been invoked before +% POSTCONDITION: +% - the current x- and y unit vectors are changed; +% - \axis@[xy]coord{min,max}TEX are set +% +\def\axis@initsizes{% + % INIT. + % + % + \pgfpointxy{\axis@xmin}{\axis@ymin}% + \axis@xcoordminTEX=\pgf@x + \axis@ycoordminTEX=\pgf@y + \pgfpointxy{\axis@xmax}{\axis@ymax}% + \axis@xcoordmaxTEX=\pgf@x + \axis@ycoordmaxTEX=\pgf@y + % + % + %----------------------------------------- + % PROCESS THE 'width' and 'height' options + %----------------------------------------- + % + % FIXME: make these variables LOCAL: + % + \let\axis@rectangle@width=\empty + \let\axis@rectangle@height=\empty % - % common code for the cases if one of W,H is 1: \ifx\axis@x\empty \ifx\axis@width\empty - \else - \axis@initsizes@getXscale\into\axis@tmpXscale + \errmessage{INTERNAL LOGIC ERROR! WIDTH NOT SET}% + \fi + \axis@initsizes@getXscale\into\axis@tmpXscale + \ifaxis@scale@only@axis + \let\axis@rectangle@width=\axis@width \fi \else \def\axis@tmpXscale{1}% @@ -1346,45 +1987,18 @@ % \ifx\axis@y\empty \ifx\axis@height\empty - \else - \axis@initsizes@getYscale\into\axis@tmpYscale + \errmessage{INTERNAL LOGIC ERROR! HEIGHT NOT SET}% + \fi + \axis@initsizes@getYscale\into\axis@tmpYscale + \ifaxis@scale@only@axis + \let\axis@rectangle@height=\axis@height \fi \else \def\axis@tmpYscale{1}% \fi % - \ifx\axis@x\empty\ifx\axis@y\empty - % hasx=0, hasy=0 and ... - % - % -> KEEP ASPECT RATIO! - % - % CASE W=0 H=1: - \ifx\axis@width\empty - \ifx\axis@height\empty - \else - \expandafter\pgfmath@y\axis@height - \pgfmathlog@invoke@expanded\pgfmathmultiply@{% - {\pgf@sys@tonumber{\pgfmath@y}}% - {\axis@default@aspect@ratio}% - }% - \edef\axis@width{\pgfmathresult pt}% - \axis@initsizes@getXscale\into\axis@tmpXscale - \fi - \else% CASE W=1 H=0: - \ifx\axis@height\empty - \expandafter\pgfmath@x\axis@width - \pgfmathlog@invoke@expanded\pgfmathdivide@{% - {\pgf@sys@tonumber{\pgfmath@x}}% - {\axis@default@aspect@ratio}% - }% - \edef\axis@height{\pgfmathresult pt}% - \axis@initsizes@getYscale\into\axis@tmpYscale - \fi - \fi - \fi\fi - % IMPLEMENTATION NOTE: - % if(Xscale=empty or Yscale=empty) - % -> LOGIC ERROR above. + % + % assert( \axis@tmpXscale != \empty && \axis@tmpYscale != \empty ) % % Apply scaling: \pgfpointxy{\axis@tmpXscale}{\axis@tmpYscale}% @@ -1401,34 +2015,127 @@ \pgfsetyvec{\pgfpoint{0pt}{\axis@y}}% \fi % + % Determine final rectangle dimensions. + % There are the following cases: + % 1. the user really wants a fixed dimension, + % i.e. he used 'scale only axis'. + % Then, we have to work to get the correct dimension! + % + % Up to now, the scaling mechanism looses to many significant + % digits such that the final width/height differs by 1-2 pt. + % + % If I am not mistaken, this does ONLY affect the final size, + % not the relative plot precision. + % + % FIXME : really compute the plot precision! + % + % 2. The use specified width and/or height, but not 'scale only + % axis'. Accept inaccurate final widths/heights (see above). + % + % 3. The user supplied 'x' and or 'y'. Simply use them, its + % accurate. + % \pgfpointxy{\axis@xmin}{\axis@ymin}% \axis@xcoordminTEX=\pgf@x \axis@ycoordminTEX=\pgf@y \pgfpointxy{\axis@xmax}{\axis@ymax}% - \axis@xcoordmaxTEX=\pgf@x - \axis@ycoordmaxTEX=\pgf@y - %----------------------------------------- + \ifx\axis@rectangle@width\empty + \axis@xcoordmaxTEX=\pgf@x + \else + % this 'if' here should only make a difference of about + % 1-2pt, not more. + % + % and I am quite sure that this inaccuracy (and this + % work-around) only affects the + % final size, not the relative plot accuracy. + \axis@xcoordmaxTEX=\axis@xcoordminTEX + \expandafter\advance\expandafter\axis@xcoordmaxTEX\axis@width + \fi + \ifx\axis@rectangle@height\empty + \axis@ycoordmaxTEX=\pgf@y + \else + \axis@ycoordmaxTEX=\axis@ycoordminTEX + \expandafter\advance\expandafter\axis@ycoordmaxTEX\axis@height + \fi +%-------------------------------------------------- +% \begingroup +% \pgf@x=\axis@xcoordmaxTEX\advance\pgf@x by-\axis@xcoordminTEX +% \pgf@y=\axis@ycoordmaxTEX\advance\pgf@y by-\axis@ycoordminTEX +% \message{Axis scaling x=\axis@tmpXscale, y=\axis@tmpYscale\ yields lower-left-corner (\axis@xmin,\axis@ymin) = (\the\axis@xcoordminTEX,\the\axis@ycoordminTEX) and upper right (\axis@xmax,\axis@ymax) = (\the\axis@xcoordmaxTEX,\the\axis@ycoordmaxTEX). Axis dimensions are width=\the\pgf@x, height=\the\pgf@y.}% +% \endgroup +%-------------------------------------------------- } \def\axis@BEGIN@init@and@draw@axis{% \axis@determinedefaultvalues - % X-Achsenbeschriftung: - % LADE DIE \axis@xtick -variable REIN - \expandafter\xachse\expandafter{\axis@xtick} - % - % Y-Achsen und Achsenbeschriftung: - \expandafter\yachse\expandafter{\axis@ytick}% - - % Äußerer Rahmen: - \draw - (\axis@xcoordminTEX, \axis@ycoordminTEX) - rectangle (\axis@xcoordmaxTEX, \axis@ycoordmaxTEX); + % move the anchor to (0,0): + \expandafter\ifcase\axis@anchorchoicenum + % north: + \begin{scope}[ + yshift=-\axis@ycoordmaxTEX, + xshift=-0.5\axis@xcoordminTEX-0.5\axis@xcoordmaxTEX + ] + \or% north west: + \begin{scope}[ + yshift=-\axis@ycoordmaxTEX, + xshift=-\axis@xcoordminTEX + ] + \or% west: + \begin{scope}[ + yshift=-0.5\axis@ycoordminTEX-0.5\axis@ycoordmaxTEX, + xshift=-\axis@xcoordminTEX + ] + \or% south west: + \begin{scope}[ + yshift=-\axis@ycoordminTEX, + xshift=-\axis@xcoordminTEX + ] + \or% south: + \begin{scope}[ + yshift=-\axis@ycoordminTEX, + xshift=-0.5\axis@xcoordminTEX-0.5\axis@xcoordmaxTEX + ] + \or% south east: + \begin{scope}[ + yshift=-\axis@ycoordminTEX, + xshift=-\axis@xcoordmaxTEX + ] + \or% east: + \begin{scope}[ + yshift=-0.5\axis@ycoordminTEX-0.5\axis@ycoordmaxTEX, + xshift=-\axis@xcoordmaxTEX + ] + \or% north east: + \begin{scope}[ + yshift=-\axis@ycoordmaxTEX, + xshift=-\axis@xcoordmaxTEX + ] + \or% center + \begin{scope}[ + yshift=-0.5\axis@ycoordminTEX-0.5\axis@ycoordmaxTEX, + xshift=-0.5\axis@xcoordminTEX-0.5\axis@xcoordmaxTEX + ] + \fi \begin{scope} - \clip - (\axis@xcoordminTEX, \axis@ycoordminTEX) - rectangle (\axis@xcoordmaxTEX, \axis@ycoordmaxTEX); + \ifaxis@hide + \clip + (\axis@xcoordminTEX, \axis@ycoordminTEX) + rectangle (\axis@xcoordmaxTEX, \axis@ycoordmaxTEX); + \else + + % X-Achsenbeschriftung: + % LADE DIE \axis@xtick -variable REIN + \expandafter\axis@drawxaxis\expandafter{\axis@xtick} + % + % Y-Achsen und Achsenbeschriftung: + \expandafter\axis@drawyaxis\expandafter{\axis@ytick}% + \draw[clip] + (\axis@xcoordminTEX, \axis@ycoordminTEX) + rectangle (\axis@xcoordmaxTEX, \axis@ycoordmaxTEX); + + \fi } \def\axis@END@init@and@draw@axis{% @@ -1448,6 +2155,34 @@ }% } +\tikzdeclarecoordinatesystem{axis}{\axis@evalute@tikz@coord@system@interface#1\axis@coord@end} + + +% Assigns \pgfmathresult := canvas coordinate (#2) for axis #1. +\long\def\axis@evalute@tikz@coord@system@interface@for#1#2{% + \expandafter\let\expandafter\if@datascaled@cur\csname ifaxis@float@numerics@mode@#1\endcsname + \expandafter\ifcase\csname axis@#1mode\endcsname + \if@datascaled@cur + \csname axis@datascaletrafo@fromfixed@#1\endcsname#2\to\pgfmathresult + \else + \def\pgfmathresult{#2}% + \fi + \or + \pgfmathlog@{#2}% + \fi +} + +\long\def\axis@evalute@tikz@coord@system@interface#1,#2\axis@coord@end{% + \begingroup + \axis@evalute@tikz@coord@system@interface@for{x}{#1}% + \let\axis@evaluate@tikz@coord@x=\pgfmathresult + \axis@evalute@tikz@coord@system@interface@for{y}{#2}% + \xdef\axis@TMP{\axis@evaluate@tikz@coord@x pt}% + \xdef\axis@TMPB{\pgfmathresult pt}% + \endgroup + \pgfpointxy{\axis@TMP}{\axis@TMPB}% +} + % In case of (semi-) logplots, this command will % - assign a filter which invokes \pgfmathlog@{} for each coordinate % - replace any user-specified coordinate by its log. @@ -1455,105 +2190,285 @@ % All subsequent commands will then work with logarithmic coordinates. % % @see pgfmathlog.sty for details about the implementation of log(). -\def\axis@preparelog@filtering{% - \ifnum\axis@xmode=1 - % any user-specified axis limits: - \ifx\axis@xmin\empty - \else - \expandafter\pgfmathlog@\expandafter{\axis@xmin}% - \let\axis@xmin=\pgfmathresult - \fi - \ifx\axis@xmax\empty +% +% PRECONDITION: +% - The user input options have been set correctly, +% - the option processing has not yet begun +% +% POSTCONDITION: +% - any user input for log-axis has been replaced by its log +% - coordinate filters to compute logs are installed +% +% See also: +% \axis@apply@data@scale@trafo@to@options@for +\def\axis@prepare@coord@filtering@for#1{% + \expandafter\ifcase\csname axis@#1mode\endcsname + \ifaxis@disabledatascaling + \csname axis@float@numerics@mode@#1false\endcsname + \axis@float@numerics@modefalse \else - \expandafter\pgfmathlog@\expandafter{\axis@xmax}% - \let\axis@xmax=\pgfmathresult + \csname axis@float@numerics@mode@#1true\endcsname + \axis@float@numerics@modetrue \fi - % - % any user specified axis ticks: - \ifx\axis@xtick\empty - \else - \expandafter\axis@filter@input@ticks@with@log\expandafter{\axis@xtick}% - \edef\axis@xtick{\axis@TMP}% + \ifaxis@float@numerics@mode + % Install coordinate filters that + % - read input as normalised floating point numbers, + % - return [SIGN][MANTISSE]eEXPONENT + % Motivation: + % 1. we can compute axis limits using such data + % 2. we can remember the floating point representation for + % the data scaling transformation. + % ATTENTION: + % this here is a preprocessing step! You will need to + % apply the data scaling later! + % see + % \axis@apply@data@scaletrafo@to@plot@data + \expandafter\let\expandafter\axis@TMP\csname axis@#1filter\endcsname + \ifx\axis@TMP\empty + \expandafter\def\csname addplot@float@numerics@#1filter\endcsname##1\to##2{% + \sciparsesign{##1}\axis@tmp@S\axis@tmp@M\axis@tmp@E + \scisetcomponents{##2}\axis@tmp@S\axis@tmp@M\axis@tmp@E + \edef##2{\axis@tmp@S\axis@tmp@M e\axis@tmp@E}% + }% + \else + \expandafter\let\csname axis@#1filter@orig\endcsname=\axis@TMP + \expandafter\def\csname addplot@float@numerics@#1filter\endcsname##1\to##2{% + \csname axis@#1filter@orig\endcsname##1\to##2\relax + \ifx##2\empty + \else + \expandafter\sciparsesign\expandafter{##2}\axis@tmp@S\axis@tmp@M\axis@tmp@E + \scisetcomponents{##2}\axis@tmp@S\axis@tmp@M\axis@tmp@E + \edef##2{\axis@tmp@S\axis@tmp@M e\axis@tmp@E}% + \fi + }% + \fi + \expandafter\let\expandafter\axis@TMP\csname addplot@float@numerics@#1filter\endcsname + \expandafter\let\csname axis@#1filter\endcsname\axis@TMP + % + % Check for any existing axis limits: + \expandafter\let\expandafter\axis@TMP\csname axis@#1min\endcsname + \ifx\axis@TMP\empty + \else + \expandafter\sciparsesign\expandafter{\axis@TMP}\axis@tmp@S\axis@tmp@M\axis@tmp@E + \expandafter\scisetcomponents\csname axis@#1min\endcsname\axis@tmp@S\axis@tmp@M\axis@tmp@E + \fi + \expandafter\let\expandafter\axis@TMP\csname axis@#1max\endcsname + \ifx\axis@TMP\empty + \else + \expandafter\sciparsesign\expandafter{\axis@TMP}\axis@tmp@S\axis@tmp@M\axis@tmp@E + \expandafter\scisetcomponents\csname axis@#1max\endcsname\axis@tmp@S\axis@tmp@M\axis@tmp@E + \fi \fi - \ifx\axis@xfilter\empty - \def\addplot@log@compute@xfilter##1\to##2{% - \pgfmathlog@{##1}% - \let##2=\pgfmathresult - }% + \or + \ifaxis@disablelogfilter \else - \let\axis@xfilter@orig=\axis@xfilter - \def\addplot@log@compute@xfilter##1\to##2{% - \pgfmathlog@{##1}% - \ifx\pgfmathresult\empty - \let##2=\empty - \else - \expandafter\axis@xfilter@orig\pgfmathresult\to##2\relax - \fi - }% + % any user-specified axis limits: + \expandafter\let\expandafter\axis@TMP\csname axis@#1min\endcsname + \ifx\axis@TMP\empty + \else + \expandafter\pgfmathlog@\expandafter{\axis@TMP}% + \expandafter\let\csname axis@#1min\endcsname=\pgfmathresult + \fi + \expandafter\let\expandafter\axis@TMP\csname axis@#1max\endcsname + \ifx\axis@TMP\empty + \else + \expandafter\pgfmathlog@\expandafter{\axis@TMP}% + \expandafter\let\csname axis@#1max\endcsname=\pgfmathresult + \fi + % + % any user specified axis ticks: + \expandafter\let\expandafter\axis@TMP\csname axis@#1tick\endcsname + \ifx\axis@TMP\empty + \else + \expandafter\axis@filter@input@ticks@with@log\expandafter{\axis@TMP}% + \expandafter\edef\csname axis@#1tick\endcsname{\axis@TMP}% + \fi + % + \expandafter\let\expandafter\axis@TMP\csname axis@#1filter\endcsname + \ifx\axis@TMP\empty + \expandafter\def\csname addplot@log@compute@#1filter\endcsname##1\to##2{% + \pgfmathlog@{##1}% + \let##2=\pgfmathresult + }% + \else + \expandafter\let\csname axis@#1filter@orig\endcsname=\axis@TMP + \expandafter\def\csname addplot@log@compute@#1filter\endcsname##1\to##2{% + \pgfmathlog@{##1}% + \ifx\pgfmathresult\empty + \let##2=\empty + \else + \expandafter\expandafter\csname axis@#1filter@orig\endcsname\pgfmathresult\to##2\relax + \fi + }% + \fi + \expandafter\let\expandafter\axis@TMP\csname addplot@log@compute@#1filter\endcsname + \expandafter\let\csname axis@#1filter\endcsname\axis@TMP \fi - \def\axis@xfilter{\addplot@log@compute@xfilter}% \fi - % - \ifnum\axis@ymode=1 - % any user-specified axis limits: - \ifx\axis@ymin\empty - \else - \expandafter\pgfmathlog@\expandafter{\axis@ymin}% - \let\axis@ymin=\pgfmathresult - \fi - \ifx\axis@ymax\empty - \else - \expandafter\pgfmathlog@\expandafter{\axis@ymax}% - \let\axis@ymax=\pgfmathresult - \fi - % - % any user specified axis ticks: - \ifx\axis@ytick\empty +} + +\def\axis@create@axis@descriptions{% + \ifaxis@hide + \else + \ifx\axis@xlabel\empty \else - \expandafter\axis@filter@input@ticks@with@log\expandafter{\axis@ytick}% - \edef\axis@ytick{\axis@TMP}% + \axisshowxlabel \fi - \ifx\axis@yfilter\empty - \def\addplot@log@compute@yfilter##1\to##2{% - \pgfmathlog@{##1}% - \let##2=\pgfmathresult - }% + \ifx\axis@ylabel\empty \else - \let\axis@yfilter@orig=\axis@yfilter - \def\addplot@log@compute@yfilter##1\to##2{% - \pgfmathlog@{##1}% - \ifx\pgfmathresult\empty - \let##2=\empty - \else - \expandafter\axis@yfilter@orig\pgfmathresult\to##2\relax - \fi - }% + \axisshowylabel \fi - \def\axis@yfilter{\addplot@log@compute@yfilter}% \fi + \ifx\axis@title\empty + \else + \axisshowtitle + \fi + \axis@createlegend +} + +% DATA TRANSFORMATION T(x) = X +% +% Input: +% a number in the original data range, given in **floating** point representation +% Output: +% a fixed point number in transformed range +% @see +% \axis@datascaletrafo@x@three +% \axis@datascaletrafo@fromfixed@x +\def\axis@datascaletrafo@x#1\to#2{% + \scigetcomponents#1\axis@tmp@S\axis@tmp@M\axis@tmp@E + \axis@datascaletrafo@x@three\axis@tmp@S\axis@tmp@M\axis@tmp@E\to#2 +} + +% Overloaded function. +% Input: +% The same as above, but with Sign, Mantisse, Exponent. +% #1,#2 and #3 are expected to be MACRO NAMES. +\def\axis@datascaletrafo@x@three#1#2#3\to#4{% + \def\axis@TMP{\scimathshift{#1}{#2}{#3}}% + \expandafter\axis@TMP\expandafter{\axis@data@scale@trafo@SHIFT@x}% + \scitofixed{#1}{#2}{#3}{#4}% +} + +% Overloaded function. +% Input: +% a FIXED point number instead of a floating point one. +% @see \axis@datascaletrafo@x +\def\axis@datascaletrafo@fromfixed@x#1\to#2{% + \begingroup + \sciparsesign{#1}\axis@S\axis@M\axis@E + \axis@datascaletrafo@x@three\axis@S\axis@M\axis@E\to{#2}% + \global\let\axis@TMP=#2\relax + \endgroup + \let#2=\axis@TMP +} + +\def\axis@datascaletrafo@y#1\to#2{% + \scigetcomponents#1\axis@tmp@S\axis@tmp@M\axis@tmp@E + \axis@datascaletrafo@y@three\axis@tmp@S\axis@tmp@M\axis@tmp@E\to#2 +} +\def\axis@datascaletrafo@y@three#1#2#3\to#4{% + \def\axis@TMP{\scimathshift{#1}{#2}{#3}}% + \expandafter\axis@TMP\expandafter{\axis@data@scale@trafo@SHIFT@y}% + \scitofixed{#1}{#2}{#3}{#4}% +} +\def\axis@datascaletrafo@fromfixed@y#1\to#2{% + \begingroup + \sciparsesign{#1}\axis@S\axis@M\axis@E + \axis@datascaletrafo@y@three\axis@S\axis@M\axis@E\to{#2}% + \global\let\axis@TMP=#2\relax + \endgroup + \let#2=\axis@TMP +} + +% INVERSE transformation x = T^{-1}( X ) +% Input: +% a fixed point number in transformed domain +% Output: +% a number in the data domain, given in floating point +% representation +\def\axis@inverse@datascaletrafo@x#1\to#2{% + \expandafter\sciparsesignsingle\expandafter{#1}#2 + \edef\axis@TMP{\noexpand#2{-\axis@data@scale@trafo@SHIFT@x}}% + \expandafter\scimathshiftsingle\axis@TMP +} + +\def\axis@inverse@datascaletrafo@y#1\to#2{% + \expandafter\sciparsesignsingle\expandafter{#1}#2 + \edef\axis@TMP{\noexpand#2{-\axis@data@scale@trafo@SHIFT@y}}% + \expandafter\scimathshiftsingle\axis@TMP +} + +% Overloaded function. +% +% In contrast to \axis@inverse@datascaletrafo@x, this method +% returns a number in FIXED point representation. +% @see \axis@inverse@datascaletrafo@x +\def\axis@inverse@datascaletrafo@tofixed@x#1\to#2{% + \axis@inverse@datascaletrafo@x#1\to{#2}% + \scitofixedsingle{#2}{#2}% +} +\def\axis@inverse@datascaletrafo@tofixed@y#1\to#2{% + \axis@inverse@datascaletrafo@y#1\to{#2}% + \scitofixedsingle{#2}{#2}% } \newenvironment{axis}[1][]{% \begingroup - \begin{scope}[style=every axis] +% \def\axis@setkeys{\setkeys*[\prefix]{axis}}% +%\tracingmacros=2\tracingcommands=2 +% \message{Der every-axis-style ist gerade \csname tikz@st@every axis\endcsname}% +%\tracingmacros=0\tracingcommands=0 +% \expandafter\expandafter\expandafter\axis@setkeys + % \expandafter\expandafter\expandafter{\csname tikz@st@every axis\endcsname}% + \begin{scope}[style=every axis,% + x=1pt,y=1pt% see below + ] + % The explicit specification of 'x' and 'y' as 1pt is to avoid + % numeric overflow/underflow during scale computations: + % + % The scaling (i.e. proper values for 'x' and 'y') will be + % determined later-on, dependend on the axis limits. Since axis + % limits are implicitly in units of 1pt, it is reasonable to use + % '1pt' here as well. + % + % %-------------------------------------------------- % \draw[very thin,color=gray,xstep=1,ystep=\logten] % (\xcoordmin\axis@leftover,\ycoordmin) % grid (\xcoordmax\axis@rightover,\ycoordmax); %-------------------------------------------------- \setkeys[\prefix]{axis}{#1}% - \setkeys[\prefix]{legend}{}% % + % -------------------- + % Allocations: + % -------------------- \listnewempty\axis@plotspeclist \listnewempty\axis@legend - \listnewempty\axis@draw@stored@plots + \listnewempty\axis@stored@plot@cmds + \listnewempty\axis@stored@plot@data + \newif\ifaxis@autocompute@xlim + \newif\ifaxis@autocompute@ylim + \newif\ifaxis@filtercoords + \newif\ifaxis@float@numerics@mode@x + \newif\ifaxis@float@numerics@mode@y + \newif\ifaxis@float@numerics@mode + % rename '\ifaxis@hide axis' to mask the white space: + \expandafter\let\expandafter\ifaxis@hide\csname ifaxis@hide axis\endcsname + % the same for other options with white spaces: + \expandafter\let\expandafter\ifaxis@scale@only@axis\csname ifaxis@scale only axis\endcsname + \newif\ifaxis@draw@at@end + \newif\ifaxis@limits@are@computed + \newif\ifaxis@EMERGENCY@FORCE@DATA@TRAFO@TO@IDENTITY + \axis@numplots=0 + \let\axis@already@computed@legend@node=\empty % - \ifaxis@disablelogfilter - \else - \axis@preparelog@filtering - \fi + % -------------------- + % Option preprocessing + % -------------------- + \axis@prepare@coord@filtering@for x + \axis@prepare@coord@filtering@for y % - \newif\ifaxis@filtercoords \ifx\axis@xfilter\empty \else \axis@filtercoordstrue @@ -1562,46 +2477,66 @@ \else \axis@filtercoordstrue \fi - % - \axis@numplots=0 - % - \newif\ifaxis@autocompute@xlim - \newif\ifaxis@autocompute@ylim - \newif\ifaxis@draw@at@end - \newif\ifaxis@limits@are@computed - \axis@limits@are@computedtrue + % \ifx\axis@xmin\empty \axis@autocompute@xlimtrue \def\axis@xmin{16300}% + \ifaxis@float@numerics@mode@x + \scisetcomponents\axis@xmin{1}{1.0}{324}% + \fi \fi \ifx\axis@xmax\empty \axis@autocompute@xlimtrue \def\axis@xmax{-16300}% + \ifaxis@float@numerics@mode@x + \scisetcomponents\axis@xmax{2}{1.0}{324}% + \fi \fi \ifx\axis@ymin\empty \axis@autocompute@ylimtrue \def\axis@ymin{16300}% + \ifaxis@float@numerics@mode@y + \scisetcomponents\axis@ymin{1}{1.0}{324}% + \fi \fi \ifx\axis@ymax\empty \axis@autocompute@ylimtrue \def\axis@ymax{-16300}% + \ifaxis@float@numerics@mode@y + \scisetcomponents\axis@ymax{2}{1.0}{324}% + \fi \fi % \ifaxis@autocompute@xlim \axis@draw@at@endtrue \axis@limits@are@computedfalse + \else + \axis@limits@are@computedtrue \fi \ifaxis@autocompute@ylim \axis@draw@at@endtrue \axis@limits@are@computedfalse + \else + \axis@limits@are@computedtrue \fi % % + % -------------------- + % Start axis: + % either postponed to \end or directly. + % -------------------- + % \ifaxis@draw@at@end \else \axis@BEGIN@init@and@draw@axis \fi }{% + %\end{axis}: + % -------------------- + % All plotting commands + % have been done. + % -> apply postponed drawing commands! + % -------------------- \ifaxis@draw@at@end \ifaxis@limits@are@computed \else @@ -1612,7 +2547,20 @@ \def\axis@ymax{1}% \fi \axis@BEGIN@init@and@draw@axis - \listforeach\axis@draw@stored@plots\as\plotcmd{\plotcmd}% + \listforeach\axis@stored@plot@cmds\as\plotcmd{% + \listpopfront\axis@stored@plot@data\to\plotdata + \ifaxis@float@numerics@mode + \ifx\plotcmd\empty + \plotdata + \else + % Apply the data scaling transformation + \expandafter\axis@apply@data@scaletrafo@to@plot@data\plotdata\to\plotdata + \expandafter\plotcmd\plotdata + \fi + \else + \expandafter\plotcmd\plotdata + \fi + }% \fi \axis@END@init@and@draw@axis % @@ -1622,20 +2570,9 @@ x={\axis@xcoordmaxTEX-\axis@xcoordminTEX}, y={\axis@ycoordmaxTEX-\axis@ycoordminTEX} ]% - \ifx\axis@xlabel\empty - \else - \axisshowxlabel - \fi - \ifx\axis@ylabel\empty - \else - \axisshowylabel - \fi - \ifx\axis@title\empty - \else - \axisshowtitle - \fi - \axis@createlegend + \axis@create@axis@descriptions \end{scope}% + \end{scope}% this scope starts inside of \axis@BEGIN@init@and@draw@axis % \end{scope}% \endgroup |