diff options
Diffstat (limited to 'Master/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code.tex')
-rw-r--r-- | Master/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code.tex | 3332 |
1 files changed, 3332 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code.tex b/Master/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code.tex new file mode 100644 index 00000000000..79a4e5a11de --- /dev/null +++ b/Master/texmf-dist/tex/generic/pgfplots/pgfplots.scaling.code.tex @@ -0,0 +1,3332 @@ +%-------------------------------------------- +% +% Package pgfplots +% +% Provides a user-friendly interface to create function plots (normal +% plots, semi-logplots and double-logplots). +% +% It is based on Till Tantau's PGF package. +% +% Copyright 2007-2012 by Christian Feuersänger. +% +% This program is free software: you can redistribute it and/or modify +% it under the terms of the GNU General Public License as published by +% the Free Software Foundation, either version 3 of the License, or +% (at your option) any later version. +% +% This program is distributed in the hope that it will be useful, +% but WITHOUT ANY WARRANTY; without even the implied warranty of +% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +% GNU General Public License for more details. +% +% You should have received a copy of the GNU General Public License +% along with this program. If not, see <http://www.gnu.org/licenses/>. +% +%-------------------------------------------- + +% PRECONDITION: +% - final axis limits are given in transformed range +% - \pgfplots@set@default@size@options has been invoked before +% POSTCONDITION: +% - the current x,y and z unit vectors are defined properly; +% - the fast-access registers are initialised for the axis limits, +% - the following macros are assigned: +% \pgfplots@[xyz]@veclength +% \pgfplots@[xyz]@inverseveclength +% \pgfplotspointxaxis +% \pgfplotspointyaxis +% \pgfplotspointzaxis +% \pgfplotspointcenter +% \pgfplotspointminminmin +% +\def\pgfplots@initsizes{% + % INIT. + % + % + \pgfplots@xmin@reg=\pgfplots@xmin pt % + \pgfplots@xmax@reg=\pgfplots@xmax pt % + \pgfplots@ymin@reg=\pgfplots@ymin pt % + \pgfplots@ymax@reg=\pgfplots@ymax pt % + \ifpgfplots@threedim + \pgfplots@zmin@reg=\pgfplots@zmin pt % + \pgfplots@zmax@reg=\pgfplots@zmax pt % + \fi + % + %----------------------------------------- + % PROCESS THE 'width' and 'height' options + %----------------------------------------- + % + % + \pgfkeysgetvalue{/pgfplots/view/az}{\pgfplots@view@az}% + \pgfkeysgetvalue{/pgfplots/view/el}{\pgfplots@view@el}% + \ifpgfplots@threedim + \else + \let\pgfplots@view@el=\pgfutil@empty + \let\pgfplots@view@az=\pgfutil@empty + \fi + \ifx\pgfplots@view@az\pgfutil@empty + % Note that in presence of "x,y,z" options, the + % \pgfplots@set@default@size@options RESETS /pgfplots/view/az. + % + %\let\pgfplots@rectangle@width=\pgfutil@empty + %\let\pgfplots@rectangle@height=\pgfutil@empty + \pgfplotsmathvectorfromstring{0,0,1}{default}% + \let\pgfplots@view@dir@threedim=\pgfplotsretval + % + \ifx\pgfplots@x\pgfutil@empty + \ifx\pgfplots@width\pgfutil@empty + \pgfplots@error{INTERNAL LOGIC ERROR! WIDTH NOT SET}% + \fi + \fi + % + \ifx\pgfplots@y\pgfutil@empty + \ifx\pgfplots@height\pgfutil@empty + \pgfplots@error{INTERNAL LOGIC ERROR! HEIGHT NOT SET}% + \fi + \fi + \ifpgfplots@threedim + \def\pgfplots@tmp@Zscale{1}% + \else + \def\pgfplots@tmp@Zscale{0}% + \fi + % + \pgfplots@initsizes@setunitvector{x}{0}{1}{\pgfplots@tmp@xisaxisparallel}% + \pgfplots@initsizes@setunitvector{y}{1}{1}{\pgfplots@tmp@yisaxisparallel}% + \pgfplots@initsizes@setunitvector{z}{2}{\pgfplots@tmp@Zscale}{\pgfplots@loc@TMPc}% + \pgfplots@scale@plotbox@to@widthheight + \ifpgfplots@threedim + \pgfplotsgetnormalforcurrentview + \fi + \else + % 3D case by `view': + \let\pgfplots@x=\pgfutil@empty + \let\pgfplots@y=\pgfutil@empty + \let\pgfplots@z=\pgfutil@empty + \pgfplotssetaxesfromazel{\pgfplots@view@az}{\pgfplots@view@el}{\pgfplots@tmp@xisaxisparallel}% + \pgfplots@scale@plotbox@to@widthheight + \if1\pgfplots@tmp@xisaxisparallel% + \def\pgfplots@tmp@yisaxisparallel{1}% + \fi + \fi +%\message{Pgfplots debug: initialised unit vectors to x=(\the\pgf@xx,\the\pgf@xy), y=(\the\pgf@yx,\the\pgf@yy), z=(\the\pgf@zx,\the\pgf@zy), n = (\pgfplots@view@dir@threedim).^^J }% + % + \let\pgfplotsmathfloatviewdepthxyz@=\pgfplotsmathfloatviewdepthxyz@infigure + \let\pgfplotsmathviewdepthxyz@=\pgfplotsmathviewdepthxyz@infigure + % + \pgfplotsmath@ifzero{\pgfplots@x@veclength}{\pgfplots@hide@xtrue\pgfplots@shownothingof@xtrue}{}% + \pgfplotsmath@ifzero{\pgfplots@y@veclength}{\pgfplots@hide@ytrue\pgfplots@shownothingof@ytrue}{}% + \ifpgfplots@threedim + \pgfplotsmath@ifzero{\pgfplots@z@veclength}{\pgfplots@hide@ztrue\pgfplots@shownothingof@ztrue}{}% + \else + \if1\pgfplots@tmp@xisaxisparallel% + \if1\pgfplots@tmp@yisaxisparallel% + % Optimize for axis-parallel case! + % puh. Did not make any measureable difference!? Ok... + \let\pgfplotsqpointxy=\pgfplotsqpointxy@orthogonal + \fi + \fi + \fi +} + +% Defines \pgfmathresult to be the desired width without axis labels. +% +\def\pgfplots@initsizes@get@width@withoutlabels{% + \pgfplots@initsizes@handle@label@const{\pgfplots@width}{45pt}{width}% +} + +% Defines \pgfmathresult to be the desired height without axis labels. +\def\pgfplots@initsizes@get@height@withoutlabels{% + \pgfplots@initsizes@handle@label@const{\pgfplots@height}{45pt}{height}% +} + +\def\pgfplots@initsizes@handle@label@const#1#2#3{% + \begingroup + \pgf@xa=#1\relax + % EXPECTED WIDTH = X = \pgfplots@width + % ACTUAL WIDTH = c + x * (xmax-xmin) + % where c is a CONSTANT (for the axis labels/tick labels). + % -> \pgfplots@tmpXscale = (X - c) / (x *(xmax-xmin)) + % + % \pgf@xa := X-c: + \ifpgfplots@scale@only@axis + \else + \advance\pgf@xa by-#2 % FIXME determine 'c' correctly! + \fi + \ifdim\pgf@xa<0pt + \pgfplots@error{Error: Plot #3 `#1' is too small. This cannot be implemented while maintaining constant size for labels. Sorry, label sizes are only approximate. You will need to adjust your #3.}% + \pgf@xa=0pt + \fi + \edef\pgfmathresult{\the\pgf@xa}% + \pgfmath@smuggleone\pgfmathresult + \endgroup +}% + +% #1: axis +\def\pgfplots@axis@apply@post@scale#1{% + % + \pgfkeysgetvalue{/pgfplots/#1 post scale}\pgfplots@loc@TMPd + \ifx\pgfplots@loc@TMPd\pgfutil@empty + \else + \pgfmathparse{\csname pgfplots@target@unit@scale@#1x\endcsname*\pgfplots@loc@TMPd}% + \expandafter\let\csname pgfplots@target@unit@scale@#1x\endcsname=\pgfmathresult + % + \pgfmathparse{\csname pgfplots@target@unit@scale@#1y\endcsname*\pgfplots@loc@TMPd}% + \expandafter\let\csname pgfplots@target@unit@scale@#1y\endcsname=\pgfmathresult + \fi +} + +% Takes azimuth (horizontal angle) '#1' and elongation (vertical +% angle) '#2' (both in degrees) and computes +% x,y and z vectors which define the view in the direction +% defined by '#1' and '#2'. +% +% 'azimuth' means a rotation around the viewport's x axis. 'elongation' means +% a rotation around the original coordinate system's z axis. +% +% The method works by computing +% Az = [ cos(azimuth) -sin(azimuth) 0; ... +% sin(azimuth) cos(azimuth) 0; ... +% 0 0 1 ]; +% +% +% Ax = [ 1 0 0; ... +% 0 cos(elevation) -sin(elevation) ;... +% 0 sin(elevation) cos(elevation) ]; +% +% v= Ax * Az; +% = [ ... +% cosaz -sinaz cosel sinaz sinel; ... +% sinaz cosaz cosel -sinel cosaz; ... +% 0 sinel cosel ]; +% +% Then, we use the rotated XZ plane as viewport, that means +% xvec = v * [1 0 0]' = <first column of v> +% zvec = v * [0 0 1]' = <third column of v> +% and we define the projection onto the twodimensional surface +% spanned by 'xvec' and 'zvec' as +% P( q ) = [ q^T xvec, q^T zvec ]' +% for q in R^3. +% As a consequence, we compute the three unit vectors as +% x = P( [1 0 0] ) +% = [ cosaz, sinaz sinel ]' +% y = P( [0 1 0] ) +% = [ sinaz, -sinel cosaz ]' +% z = P( [0 0 1] ) +% = [ 0, cosel]' +% +% Furthermore, the 3D view vector which points into the direction of the view +% is +% n = v * [0 1 0 ]' = <second column of v> = [-sinaz cosel, cosaz cosel, sinel]' +% because the normal view point was the XZ plane with y as its normal +% vector. +% The 3D vector n is returned by this routine as well - it is +% necessary for some kind of z buffering (determining what is +% foreground and what is background). +% +% INPUT: +% - #1 : azimuth ("yaw") +% - #2 : elevation ("pitch") +% OUTPUT: +% - #3 : a macro which will be set to '1' if and only if +% the viewport is the standard XY axis (i.e. azimuth=0, elevation=90). +% - [xyz] vectors, +% \pgfplots@view@dir@threedim will contain the three components +% of 'n' (without the suffix 'pt', but in units of 'pt') (see +% \pgfplotsmathvectorfromstring). +\def\pgfplotssetaxesfromazel#1#2#3{% + \begingroup + \pgfmathparse{#1}% + \let\pgfplots@az=\pgfmathresult + \pgfmathparse{#2}% + \edef\pgfplots@el{-\pgfmathresult}% + \pgfmathsin@{\pgfplots@az}% + \let\sinaz=\pgfmathresult + \pgfmathcos@{\pgfplots@az}% + \let\cosaz=\pgfmathresult + \pgfmathsin@{\pgfplots@el}% + \let\sinel=\pgfmathresult + \pgfmathcos@{\pgfplots@el}% + \let\cosel=\pgfmathresult + % x: + \pgfmathmultiply@{\sinaz}{\sinel}% + \xdef\pgfplots@glob@TMPa{\noexpand\pgfqpoint{\cosaz pt}{\pgfmathresult pt}}% + % y: + \pgfmathmultiply@{-\sinel}{\cosaz}% + \xdef\pgfplots@glob@TMPb{\noexpand\pgfqpoint{\sinaz pt}{\pgfmathresult pt}}% + % z: + \xdef\pgfplots@glob@TMPc{\noexpand\pgfqpoint{0pt}{\cosel pt}}% + % + \pgfkeysgetvalue{/pgfplots/x dir/value}\pgfplots@loc@dirvalue@x + \pgfkeysgetvalue{/pgfplots/y dir/value}\pgfplots@loc@dirvalue@y + \pgfkeysgetvalue{/pgfplots/z dir/value}\pgfplots@loc@dirvalue@z + \if r\pgfplots@loc@dirvalue@x + \t@pgfplots@toka=\expandafter{\pgfplots@glob@TMPa}% + \xdef\pgfplots@glob@TMPa{\noexpand\pgfqpointscale{-1}{\the\t@pgfplots@toka}}% + \fi + \if r\pgfplots@loc@dirvalue@y + \t@pgfplots@toka=\expandafter{\pgfplots@glob@TMPb}% + \xdef\pgfplots@glob@TMPb{\noexpand\pgfqpointscale{-1}{\the\t@pgfplots@toka}}% + \fi + \if r\pgfplots@loc@dirvalue@z + \t@pgfplots@toka=\expandafter{\pgfplots@glob@TMPc}% + \xdef\pgfplots@glob@TMPc{\noexpand\pgfqpointscale{-1}{\the\t@pgfplots@toka}}% + \fi + % + % Process 'plot box ratio': + \def\pgfplots@extract@plot@box@ratio##1##2##3##4\pgfplots@EOI{% + \pgfmathparse{##1}\let\pgfplots@plotboxratio@x=\pgfmathresult + \pgfmathparse{##2}\let\pgfplots@plotboxratio@y=\pgfmathresult + \pgfmathparse{##3}\let\pgfplots@plotboxratio@z=\pgfmathresult + }% + \def\pgfplots@extract@plot@box@ratio@spaces##1 ##2 ##3 ##4\pgfplots@EOI{% + \pgfplots@extract@plot@box@ratio{##1}{##2}{##3}{##4}\pgfplots@EOI + }% + \pgfkeysgetvalue{/pgfplots/plot box ratio}\pgfplots@loc@TMPa + % Auto-determine input format which is either '{x}{y}{z}' or 'x y z' + \def\pgfplots@loc@TMPb{% + \pgfutil@ifnextchar\bgroup{% + \pgfplots@loc@tmptrue + \pgfplots@gobble@until@EOI + }{% + \pgfplots@loc@tmpfalse + \pgfplots@gobble@until@EOI + }% + }% + \expandafter\pgfplots@loc@TMPb\pgfplots@loc@TMPa\pgfplots@EOI + \ifpgfplots@loc@tmp + % Ah- braces format. + \edef\pgfplots@loc@TMPa{\pgfplots@loc@TMPa{1}{1}{1}}% + \expandafter\pgfplots@extract@plot@box@ratio\pgfplots@loc@TMPa\pgfplots@EOI + \else + % Ah- space-separated + \edef\pgfplots@loc@TMPa{\pgfplots@loc@TMPa\space 1 1 1}% + \expandafter\pgfplots@extract@plot@box@ratio@spaces\pgfplots@loc@TMPa\pgfplots@EOI + \fi + % + % process it: + \ifdim\pgfplots@plotboxratio@x pt=1pt + \else + \t@pgfplots@toka=\expandafter{\pgfplots@glob@TMPa}% + \xdef\pgfplots@glob@TMPa{\noexpand\pgfqpointscale{\pgfplots@plotboxratio@x}{\the\t@pgfplots@toka}}% + \fi + \ifdim\pgfplots@plotboxratio@y pt=1pt + \else + \t@pgfplots@toka=\expandafter{\pgfplots@glob@TMPb}% + \xdef\pgfplots@glob@TMPb{\noexpand\pgfqpointscale{\pgfplots@plotboxratio@y}{\the\t@pgfplots@toka}}% + \fi + \ifdim\pgfplots@plotboxratio@z pt=1pt + \else + \t@pgfplots@toka=\expandafter{\pgfplots@glob@TMPc}% + \xdef\pgfplots@glob@TMPc{\noexpand\pgfqpointscale{\pgfplots@plotboxratio@z}{\the\t@pgfplots@toka}}% + \fi + % + % n (3D!) + \pgfmathmultiply@{-\sinaz}{\cosel}% + \let\pgfmathresultNx=\pgfmathresult + \pgfmathmultiply@{\cosaz}{\cosel}% + \xdef\pgfplots@glob@TMPd{{\pgfmathresultNx}{\pgfmathresult}{\sinel}}% + \endgroup +%\message{Setting x,y and z from {#1}{#2} to^^J x = \meaning\pgfplots@glob@TMPa,^^J y = \meaning\pgfplots@glob@TMPb,^^J z = \meaning\pgfplots@glob@TMPc,^^J n = \pgfplots@glob@TMPd.^^J}% + \pgfsetxvec{\pgfplots@glob@TMPa}% + \pgfsetyvec{\pgfplots@glob@TMPb}% + \pgfsetzvec{\pgfplots@glob@TMPc}% + \def\pgfplots@loc@TMPa##1##2##3{% + \pgfplotsmathvectorfromstring{##1,##2,##3}{default}% + \let\pgfplots@view@dir@threedim=\pgfplotsretval + }% + \expandafter\pgfplots@loc@TMPa\pgfplots@glob@TMPd\relax + \def#3{0}% +}% + +% Takes the current plot box, defined by the actual PGF x,y and z unit +% vectors, and re-scales it such that it fits into the +% width and height of the axis (as they have been provided by the +% user). +% +% @see \pgfplots@scale@axisbox@to@widthheight +% @see\pgfplots@scaleaxes@to@BB +\def\pgfplots@scale@plotbox@to@widthheight{% + \pgfplots@initsizes@get@width@withoutlabels + \let\pgfplots@loc@TMPa=\pgfmathresult + \pgfplots@initsizes@get@height@withoutlabels + % + \edef\pgfplots@loc@TMPa{{\pgfplots@loc@TMPa}{\pgfmathresult}}% + \expandafter\pgfplots@scaleaxes@to@BB\pgfplots@loc@TMPa +} + + +% Takes the current PGF x,y and z unit vectors and scales them such +% that the bounding box of the final image has width #1 and height #2. +% +% The relative length of the input vectors is important for the 3D case: it +% will be scaled as-is. +% +% PRECONDITION +% - the x, y and z unit vectors have been set to the proper +% DIRECTIONS. Their relative vector lengths are set-up properly +% (i.e. y is twice as large as x and half as large as z or so). +% - the \ifpgfplots@threedim boolean is set. +% - the data limits have been initialised and transformed according +% to the data transformation. +% - the data transformation has ONLY been applied to the axis limits +% (not other axis inputs). It may be changed by this method. +% +% POSTCONDITION +% - the unit vectors have been re-scaled such that the final plot +% has the desired dimensions. +% - the @veclength and @inverseveclength have been initialized +\def\pgfplots@scaleaxes@to@BB#1#2{% + \if0\pgfplots@scale@mode@choice + % scale mode=auto + \def\pgfplots@scale@mode@choice{2}% stretch to fill + \fi + \pgfplots@scaleaxes@to@BB@{#1}{#2}% + \pgfplots@computeunitvectorlengths + \pgfplots@rescale@view@dir +}% + +\def\pgfplots@rescale@view@dir{% + \expandafter\ifx\csname pgfplots@view@dir@threedim\endcsname\relax + \else + % At this point, we ALREADY HAVE a normal vector. However, it + % might be skewed due to the scaling. + % + % -> recompute normal vector. In earlier versions, I tried to + % rescale it - but that was too complicated (for me). This + % here produces correct results, and it is a correct approach + % anyway. + \pgfplotsgetnormalforcurrentview + \fi +}% + +% \pgfplots@BB@for@plotbox@get@unit@scales@for@limits{#1}{#2}{#3}: +% a helper tool which computes individual unit vector scales in order +% to respect the limits. +% +% This method ignores width/height; its purpose is only to make sure +% that [xmin,xmax] fits into the CURRENT plot box. +% +% In this context, each unit vector is supposed to be scaled such that +% width/height fit if xmin=0 and xmax=1. +% +% #1 [output] a macro name which will contain the INVERSE scale for x +% #2 [output] a macro name which will contain the INVERSE scale for y +% #3 [output] a macro name which will contain the INVERSE scale for z +% +\def\pgfplots@BB@for@plotbox@get@unit@scales@for@limits#1#2#3{% + \if1\b@pgfplots@plotbox@xisunit + % Consequently, we have to multiply with 1/(max-min): + % compute 1/(xmax - xmin) in float for more recent versions (see /pgfplots/compat/scaling). + % I observed that it is much more accurate + \pgfmathsubtract@{\pgfplots@xmax}{\pgfplots@xmin}% + \else + \def\pgfmathresult{1}% + \fi + \let#1=\pgfmathresult + % + \if1\b@pgfplots@plotbox@yisunit + \pgfmathsubtract@{\pgfplots@ymax}{\pgfplots@ymin}% + \else + \def\pgfmathresult{1}% + \fi + \let#2=\pgfmathresult + % + \ifpgfplots@threedim + \if1\b@pgfplots@plotbox@zisunit + \pgfmathsubtract@{\pgfplots@zmax}{\pgfplots@zmin}% + \else + \def\pgfmathresult{1}% + \fi + \else + \def\pgfmathresult{1}% + \fi + \let#3=\pgfmathresult +}% +\def\pgfplots@BB@for@plotbox{% + \ifpgfplots@threedim + \pgfpathmoveto{\pgfqpointxyz\pgfplots@plotbox@xmin\pgfplots@plotbox@ymin\pgfplots@plotbox@zmin}% + \pgfpathmoveto{\pgfqpointxyz\pgfplots@plotbox@xmin\pgfplots@plotbox@ymin\pgfplots@plotbox@zmax}% + \pgfpathmoveto{\pgfqpointxyz\pgfplots@plotbox@xmin\pgfplots@plotbox@ymax\pgfplots@plotbox@zmin}% + \pgfpathmoveto{\pgfqpointxyz\pgfplots@plotbox@xmin\pgfplots@plotbox@ymax\pgfplots@plotbox@zmax}% + \pgfpathmoveto{\pgfqpointxyz\pgfplots@plotbox@xmax\pgfplots@plotbox@ymin\pgfplots@plotbox@zmin}% + \pgfpathmoveto{\pgfqpointxyz\pgfplots@plotbox@xmax\pgfplots@plotbox@ymin\pgfplots@plotbox@zmax}% + \pgfpathmoveto{\pgfqpointxyz\pgfplots@plotbox@xmax\pgfplots@plotbox@ymax\pgfplots@plotbox@zmin}% + \pgfpathmoveto{\pgfqpointxyz\pgfplots@plotbox@xmax\pgfplots@plotbox@ymax\pgfplots@plotbox@zmax}% + \else + \pgfpathmoveto{\pgfqpointxy\pgfplots@plotbox@xmin\pgfplots@plotbox@ymin}% + \pgfpathmoveto{\pgfqpointxy\pgfplots@plotbox@xmin\pgfplots@plotbox@ymax}% + \pgfpathmoveto{\pgfqpointxy\pgfplots@plotbox@xmax\pgfplots@plotbox@ymin}% + \pgfpathmoveto{\pgfqpointxy\pgfplots@plotbox@xmax\pgfplots@plotbox@ymax}% + \fi +}% + + + +% Returns width and height of the current plot box +% (the path produced by \pgfplots@BB@for@plotbox). +% +% PRECONDITION: \pgfplots@BB@for@plotbox is defined to produce a path +% for the plot box +% +% POSTCONDITION: \pgfplotsretval contains the with and +% \pgfplotsretvalb contains the height +\def\pgfplots@get@dimension@of@BB{% + \begingroup + \pgfinterruptboundingbox + % + % the result of this call will be used to scale to target + % dimensions. If we omit \pgftransformreset here, we might + % accidentally UNDO the PGF transformation matrix (compare by + % writing \tikzpicture[scale=0.5] before the axis). + \pgftransformreset + % + % STEP 1: compute the bounding box for the plot box. + \pgfplots@BB@for@plotbox + % + % TMPa = width + \pgf@xa=\pgf@pathmaxx + \advance\pgf@xa by-\pgf@pathminx + % TMPb = height + \pgf@xb=\pgf@pathmaxy + \advance\pgf@xb by-\pgf@pathminy + \xdef\pgfplots@glob@TMPa{% + \def\noexpand\pgfplotsretval{\the\pgf@xa}% + \def\noexpand\pgfplotsretvalb{\the\pgf@xb}% + }% + \pgfusepath{discard}% + \endpgfinterruptboundingbox + \endgroup + \pgfplots@glob@TMPa +}% + +\def\pgfplots@scaleaxes@to@BB@prepare@plotbox@limits{% + \def\b@pgfplots@rescale@x{1}% + \def\b@pgfplots@rescale@y{1}% + \def\b@pgfplots@rescale@z{1}% + % + \pgfplots@scaleaxes@to@BB@prepare@plotbox@limits@ x% + \pgfplots@scaleaxes@to@BB@prepare@plotbox@limits@ y% + \pgfplots@scaleaxes@to@BB@prepare@plotbox@limits@ z% +}% + +\def\pgfplots@scaleaxes@to@BB@prepare@plotbox@limits@#1{% + \expandafter\ifx\csname pgfplots@#1\endcsname\pgfutil@empty + \expandafter\def\csname pgfplots@plotbox@#1min\endcsname{0}% + \expandafter\def\csname pgfplots@plotbox@#1max\endcsname{1}% + \expandafter\def\csname b@pgfplots@plotbox@#1isunit\endcsname{1}% + \else + \pgfutil@namelet{pgfplots@plotbox@#1min}{pgfplots@#1min}% + \pgfutil@namelet{pgfplots@plotbox@#1max}{pgfplots@#1max}% + \expandafter\def\csname b@pgfplots@plotbox@#1isunit\endcsname{0}% + \if2\pgfplots@scale@mode@choice + % scale mode=stretch to fill + \expandafter\def\csname b@pgfplots@rescale@#1\endcsname{0}% + \fi + \fi + \expandafter\def\csname b@pgfplots@unitvec@is@zero@#1\endcsname{0}% + \ifdim\csname pgf@#1x\endcsname=0pt % + \ifdim\csname pgf@#1y\endcsname=0pt % + \expandafter\def\csname b@pgfplots@unitvec@is@zero@#1\endcsname{1}% + \fi + \fi +} + +\def\pgfplots@scaleaxes@to@BB@#1#2{% + \begingroup + % + \pgfplots@scaleaxes@to@BB@prepare@plotbox@limits + \def\pgfplots@target@limitrescale@x{1}% + \def\pgfplots@target@limitrescale@y{1}% + \def\pgfplots@target@limitrescale@z{1}% + \if1\pgfplots@scale@mode@choice + % scale mode=none + \def\xscale{1}% + \def\yscale{1}% + \def\pgfplots@target@unit@scale@inv@x{1}% + \def\pgfplots@target@unit@scale@inv@y{1}% + \def\pgfplots@target@unit@scale@inv@z{1}% + \else + % + % This here CAN cause anisotropic (different) scaling factors. + \pgfplots@BB@for@plotbox@get@unit@scales@for@limits + {\pgfplots@target@unit@scale@inv@x} + {\pgfplots@target@unit@scale@inv@y} + {\pgfplots@target@unit@scale@inv@z}% + % +%\message{got scales to fit limits into BB: x=1/\pgfplots@target@unit@scale@inv@x, y=1/\pgfplots@target@unit@scale@inv@y, z=1/\pgfplots@target@unit@scale@inv@z^^J}% + % + \if3\pgfplots@scale@mode@choice + % scale mode=scale uniformly + % + % We need to recompensate in case the previous method chose + % different unit scaling scalings: + \pgfplots@BB@for@plotbox@get@unit@scales@compensated@axis@limits + {\pgfplots@target@unit@scale@inv@x} + {\pgfplots@target@unit@scale@inv@y} + {\pgfplots@target@unit@scale@inv@z} + {\pgfplots@target@limitrescale@x}{\pgfplots@target@limitrescale@y}{\pgfplots@target@limitrescale@z}% + % + %\pgfplots@BB@update@cumulative@limit@compensations + \fi +%\message{adjusted scales for 'scale mode': x=1/\pgfplots@target@unit@scale@inv@x, y=1/\pgfplots@target@unit@scale@inv@y, z=1/\pgfplots@target@unit@scale@inv@z; ^^J axis limit componsation scales x=\pgfplots@target@limitrescale@x, y=\pgfplots@target@limitrescale@y, z=\pgfplots@target@limitrescale@z^^J}% + % + % ATTENTION: this MODIFIES \pgfplots@target@limitrescale@x and its + % variants directly - and it needs the input values. + \pgfplots@get@scale@horiz@and@vert + {#1}% + {#2}% + {\xscale}% + {\yscale}% yscale + {\pgfplots@target@limitrescale@x}% + {\pgfplots@target@limitrescale@y}% + {\pgfplots@target@limitrescale@z}% +%\message{Got W/H scale for all x components: \xscale; for all y components: \xscale; ^^J axis limit componsation scales x=1/\pgfplots@target@limitrescale@x, y=1/\pgfplots@target@limitrescale@y, z=1/\pgfplots@target@limitrescale@z^^J}% + % Ok, we know the W,H scalings now. + % + % + % + \pgfplots@apply@unit@ratio + {\pgfplots@target@unit@scale@inv@x} + {\pgfplots@target@unit@scale@inv@y} + {\pgfplots@target@unit@scale@inv@z} + {\pgfplots@target@limitrescale@x@}{\pgfplots@target@limitrescale@y@}{\pgfplots@target@limitrescale@z@}% + \pgfplots@BB@update@cumulative@limit@compensations + % +%\message{adjusted scales for 'unit vector ratio': x=1/\pgfplots@target@unit@scale@inv@x, y=1/\pgfplots@target@unit@scale@inv@y, z=1/\pgfplots@target@unit@scale@inv@z; ^^J axis limit componsation scales x=\pgfplots@target@limitrescale@x, y=\pgfplots@target@limitrescale@y, z=\pgfplots@target@limitrescale@z^^J}% + \fi + % + % + \pgfplots@scaling@minimize@limitrescale% + % + % + \pgfplots@scaling@adjust@datascaling% +%\message{adjusted scales for data scale trafo: x=1/\pgfplots@target@unit@scale@inv@x, y=1/\pgfplots@target@unit@scale@inv@y, z=1/\pgfplots@target@unit@scale@inv@z; ^^J axis limit componsation scales x=\pgfplots@target@limitrescale@x, y=\pgfplots@target@limitrescale@y, z=\pgfplots@target@limitrescale@z;^^J data scale trafo exponents x=\pgfplots@target@datascaletrafo@x@exponent@old -> \pgfplots@target@datascaletrafo@x@exponent, y=\pgfplots@target@datascaletrafo@y@exponent@old -> \pgfplots@target@datascaletrafo@y@exponent, z=\pgfplots@target@datascaletrafo@z@exponent@old -> \pgfplots@target@datascaletrafo@z@exponent^^J}% + % + \pgfplots@scaling@compute@final@scales% + {\xscale}{\yscale}% + {\pgfplots@target@unit@scale@inv@x}% + {\pgfplots@target@unit@scale@inv@y}% + {\pgfplots@target@unit@scale@inv@z}% + % + \pgfplots@axis@apply@post@scale{x}% + \pgfplots@axis@apply@post@scale{y}% + \ifpgfplots@threedim + \pgfplots@axis@apply@post@scale{z}% + \fi + % and finally, resize limits appropriately and add all cumulative limit compensations: + \xdef\pgfplots@glob@TMPa{% + % + \pgf@xx=\pgfplots@target@unit@scale@xx\pgf@xx + \pgf@xy=\pgfplots@target@unit@scale@xy\pgf@xy + % + \pgf@yx=\pgfplots@target@unit@scale@yx\pgf@yx + \pgf@yy=\pgfplots@target@unit@scale@yy\pgf@yy + % + \ifpgfplots@threedim + \pgf@zx=\pgfplots@target@unit@scale@zx\pgf@zx + \pgf@zy=\pgfplots@target@unit@scale@zy\pgf@zy + \fi + % + \noexpand\pgfplots@apply@datascaletrafo@change@{x}{\pgfplots@target@datascaletrafo@x@exponent}% + \noexpand\pgfplots@apply@datascaletrafo@change@{y}{\pgfplots@target@datascaletrafo@y@exponent}% + \noexpand\pgfplots@apply@datascaletrafo@change@{z}{\pgfplots@target@datascaletrafo@z@exponent}% + % + \noexpand\pgfplots@apply@unit@vector@rescale@keep@size{x}{\pgfplots@target@limitrescale@x}% + \noexpand\pgfplots@apply@unit@vector@rescale@keep@size{y}{\pgfplots@target@limitrescale@y}% + \noexpand\pgfplots@apply@unit@vector@rescale@keep@size{z}{\pgfplots@target@limitrescale@z}% + % + \noexpand\pgfplots@notify@final@scalings{% + x unit scale=\pgfplots@target@unit@scale@x,% + y unit scale=\pgfplots@target@unit@scale@y,% + z unit scale=\pgfplots@target@unit@scale@z,% + x datatrafo exponent=\pgfplots@target@datascaletrafo@x@exponent,% + y datatrafo exponent=\pgfplots@target@datascaletrafo@y@exponent,% + z datatrafo exponent=\pgfplots@target@datascaletrafo@z@exponent,% + x limit rescale=\pgfplots@target@limitrescale@x,% + y limit rescale=\pgfplots@target@limitrescale@y,% + z limit rescale=\pgfplots@target@limitrescale@z,% + }% + }% + \endgroup + \pgfplots@glob@TMPa +}% + +% Checks for the case the ALL (visible) limit compensation scales are +% bigger than one (for example x = 1.22, y = 2). In such a case, we +% want to MINIMIZE the rescaling. This can happen if unit vector ratio +% is active. +% +% In our example, we want to use limit rescaling factors x = 1, y = 2/1.22 +% and, consequently, unit rescaling factors x *= 1.22, y *= 1.22 . +% +% This method checks for the case and applies the rescaling if +% necessary. +% +\def\pgfplots@scaling@minimize@limitrescale{% + % boolean allLimitScalesAreBiggerThanOne; + \pgfplots@loc@tmptrue + \if0\b@pgfplots@unitvec@is@zero@x + \ifdim\pgfplots@target@limitrescale@x pt<1.002pt % + \pgfplots@loc@tmpfalse + \fi + \fi + \if0\b@pgfplots@unitvec@is@zero@y + \ifdim\pgfplots@target@limitrescale@y pt<1.002pt % + \pgfplots@loc@tmpfalse + \fi + \fi + \if0\b@pgfplots@unitvec@is@zero@z + \ifdim\pgfplots@target@limitrescale@z pt<1.002pt % + \pgfplots@loc@tmpfalse + \fi + \fi + % + \ifpgfplots@loc@tmp + \begingroup + % Ah -- all non-vanishing limit rescaling factors are BIGGER + % THAN ONE. + % In this case, we can save some rescalings! + % + % Search for the smallest rescaling factor. + \let\pgfplots@smallest=\pgf@x + \pgfplots@smallest=16000pt % + \def\pgfplots@smallest@arg{}% + \if0\b@pgfplots@unitvec@is@zero@x + \pgf@xa=\pgfplots@target@limitrescale@x pt % + \ifdim\pgf@xa<\pgfplots@smallest% + \pgfplots@smallest=\pgf@xa + \def\pgfplots@smallest@arg{x}% + \fi + \fi + \if0\b@pgfplots@unitvec@is@zero@y + \pgf@xa=\pgfplots@target@limitrescale@y pt % + \ifdim\pgf@xa<\pgfplots@smallest% + \pgfplots@smallest=\pgf@xa + \def\pgfplots@smallest@arg{y}% + \fi + \fi + \if0\b@pgfplots@unitvec@is@zero@z + \pgf@xa=\pgfplots@target@limitrescale@z pt % + \ifdim\pgf@xa<\pgfplots@smallest% + \pgfplots@smallest=\pgf@xa + \def\pgfplots@smallest@arg{z}% + \fi + \fi + % + % OK. We have the smallest scaling factor. It is > 1. + \pgfplotscoordmath{default}{parsenumber}{\pgfplots@target@limitrescale@x}% + \let\pgfplots@target@limitrescale@x=\pgfmathresult + \pgfplotscoordmath{default}{parsenumber}{\pgfplots@target@limitrescale@y}% + \let\pgfplots@target@limitrescale@y=\pgfmathresult + % + % + \pgfplotscoordmath{default}{parsenumber}{\pgfplots@target@unit@scale@inv@x}% + \let\pgfplots@target@unit@scale@inv@x=\pgfmathresult + \pgfplotscoordmath{default}{parsenumber}{\pgfplots@target@unit@scale@inv@y}% + \let\pgfplots@target@unit@scale@inv@y=\pgfmathresult + % + \if0\b@pgfplots@unitvec@is@zero@z + \pgfplotscoordmath{default}{parsenumber}{\pgfplots@target@limitrescale@z}% + \let\pgfplots@target@limitrescale@z=\pgfmathresult + \pgfplotscoordmath{default}{parsenumber}{\pgfplots@target@unit@scale@inv@z}% + \let\pgfplots@target@unit@scale@inv@z=\pgfmathresult + \fi + % + \pgfplotscoordmath{default}{op}{reciprocal}{{\csname pgfplots@target@limitrescale@\pgfplots@smallest@arg\endcsname}}% + \let\scale=\pgfmathresult + % + \pgfplotsforeachentryinCSV\value{% + \pgfplots@target@unit@scale@inv@x,% + \pgfplots@target@unit@scale@inv@y,% + \pgfplots@target@limitrescale@x,% + \pgfplots@target@limitrescale@y% + }{% + \pgfplotscoordmath{default}{op}{multiply}{{\scale}{\value}}% + \pgfplotscoordmath{default}{tofixed}{\pgfmathresult}% + \expandafter\let\value=\pgfmathresult + }% + \if0\b@pgfplots@unitvec@is@zero@z + \pgfplotsforeachentryinCSV\value{% + \pgfplots@target@unit@scale@inv@z,% + \pgfplots@target@limitrescale@z% + }{% + \pgfplotscoordmath{default}{op}{multiply}{{\scale}{\value}}% + \pgfplotscoordmath{default}{tofixed}{\pgfmathresult}% + \expandafter\let\value=\pgfmathresult + }% + \fi + % + \xdef\pgfplots@glob@TMPa{% + \noexpand\def\noexpand\pgfplots@target@unit@scale@inv@x{\pgfplots@target@unit@scale@inv@x}% + \noexpand\def\noexpand\pgfplots@target@unit@scale@inv@y{\pgfplots@target@unit@scale@inv@y}% + \noexpand\def\noexpand\pgfplots@target@unit@scale@inv@z{\pgfplots@target@unit@scale@inv@z}% + \noexpand\def\noexpand\pgfplots@target@limitrescale@x{\pgfplots@target@limitrescale@x}% + \noexpand\def\noexpand\pgfplots@target@limitrescale@y{\pgfplots@target@limitrescale@y}% + \noexpand\def\noexpand\pgfplots@target@limitrescale@z{\pgfplots@target@limitrescale@z}% + }% + \endgroup + \pgfplots@glob@TMPa +% +%\message{adjusted scales by minimizing common scaling factors: x=1/\pgfplots@target@unit@scale@inv@x, y=1/\pgfplots@target@unit@scale@inv@y, z=1/\pgfplots@target@unit@scale@inv@z; ^^J axis limit componsation scales x=\pgfplots@target@limitrescale@x, y=\pgfplots@target@limitrescale@y, z=\pgfplots@target@limitrescale@z;^^J}% + \fi +}% + +% Defines +% \pgfplots@target@unit@scale@xx +% \pgfplots@target@unit@scale@xy +% \pgfplots@target@unit@scale@yx +% \pgfplots@target@unit@scale@yy +% \pgfplots@target@unit@scale@zx +% \pgfplots@target@unit@scale@zy +% % +% \pgfplots@target@unit@scale@x +% \pgfplots@target@unit@scale@y +% \pgfplots@target@unit@scale@z +% by combining the input args. +% +% #1: the scale to be applied to ALL x components +% #2: the scale to be applied to ALL y components +% #3: the scale to be applied to x unit +% #4: the scale to be applied to y unit +% #5: the scale to be applied to z unit +\def\pgfplots@scaling@compute@final@scales#1#2#3#4#5{% + \def\pgfplots@loc@TMPa##1##2##3##4{% + \pgfplotscoordmath{\pgfplots@compat@scaling@coordmath}{parsenumber}{##2}% + \let\xscale@@=\pgfmathresult + \pgfplotscoordmath{\pgfplots@compat@scaling@coordmath}{parsenumber}{##3}% + \let\yscale@@=\pgfmathresult + \pgfplotscoordmath{\pgfplots@compat@scaling@coordmath}{parsenumber}{##4}% + \let\unitscale@inv@@=\pgfmathresult + % + % NOTE : it *would* be more efficient to use + % 1/\unitscale@inv@@ in the routines above. BUT THAT IS NOT BACKWARDS COMPATIBLE. + % Leave it this way! + \pgfplotscoordmath{\pgfplots@compat@scaling@coordmath}{op}{reciprocal}{{\unitscale@inv@@}}% + \let\unitscale@@=\pgfmathresult + \pgfplotscoordmath{\pgfplots@compat@scaling@coordmath}{tofixed}{\pgfmathresult}% + \expandafter\let\csname pgfplots@target@unit@scale@##1\endcsname=\pgfmathresult + % + % + \ifx\pgfplots@compat@scaling@coordmath@final\pgfplots@compat@scaling@coordmath + \else + % backwards compatibility is such a burden.... :-( + % + % earlier versions relied on TeX's dimen arithmetics to + % multiply the final scales. Make sure we do the same - + % rounding errors on unit vectors are instable, i.e. the + % errors add up considerably. + \pgfplotscoordmath{\pgfplots@compat@scaling@coordmath@final}{parsenumber}{\xscale@@}% + \let\xscale@@=\pgfmathresult + \pgfplotscoordmath{\pgfplots@compat@scaling@coordmath@final}{parsenumber}{\yscale@@}% + \let\yscale@@=\pgfmathresult + \pgfplotscoordmath{\pgfplots@compat@scaling@coordmath@final}{parsenumber}{\unitscale@@}% + \let\unitscale@@=\pgfmathresult + \pgfplotscoordmath{\pgfplots@compat@scaling@coordmath@final}{parsenumber}{\unitscale@inv@@}% + \let\unitscale@inv@@=\pgfmathresult + \fi + % + \ifpgfplots@threedim + % backw. compatibility: this is how it used to be in 3d + % axes: + \pgfplotscoordmath{\pgfplots@compat@scaling@coordmath@final}{op}{multiply}{{\xscale@@}{\unitscale@@}}% + \pgfplotscoordmath{\pgfplots@compat@scaling@coordmath@final}{tofixed}{\pgfmathresult}% + \expandafter\let\csname pgfplots@target@unit@scale@##1x\endcsname=\pgfmathresult + % + \pgfplotscoordmath{\pgfplots@compat@scaling@coordmath@final}{op}{multiply}{{\yscale@@}{\unitscale@@}}% + \pgfplotscoordmath{\pgfplots@compat@scaling@coordmath@final}{tofixed}{\pgfmathresult}% + \expandafter\let\csname pgfplots@target@unit@scale@##1y\endcsname=\pgfmathresult + \else + % backw. compatibility: 2d axes used divide in earlier + % versions, not reciprocal. Believe it or not; for + % \pgfplots@compat@scaling@coordmath=pgfbasic, it makes a + % visible difference of about 2-3pt in the complete figure + % size. + \pgfplotscoordmath{\pgfplots@compat@scaling@coordmath@final}{op}{divide}{{\xscale@@}{\unitscale@inv@@}}% + \pgfplotscoordmath{\pgfplots@compat@scaling@coordmath@final}{tofixed}{\pgfmathresult}% + \expandafter\let\csname pgfplots@target@unit@scale@##1x\endcsname=\pgfmathresult + % + \pgfplotscoordmath{\pgfplots@compat@scaling@coordmath@final}{op}{divide}{{\yscale@@}{\unitscale@inv@@}}% + \pgfplotscoordmath{\pgfplots@compat@scaling@coordmath@final}{tofixed}{\pgfmathresult}% + \expandafter\let\csname pgfplots@target@unit@scale@##1y\endcsname=\pgfmathresult + \fi + % + }% + \if1\b@pgfplots@rescale@x + \pgfplots@loc@TMPa{x}{\xscale}{\yscale}{#3}% + \else + \pgfplots@loc@TMPa{x}{1}{1}{#3}% + \fi + % + \if1\b@pgfplots@rescale@y + \pgfplots@loc@TMPa{y}{\xscale}{\yscale}{#4}% + \else + \pgfplots@loc@TMPa{y}{1}{1}{#4}% + \fi + % + \ifpgfplots@threedim + \if1\b@pgfplots@rescale@z + \pgfplots@loc@TMPa{z}{\xscale}{\yscale}{#5}% + \else + \pgfplots@loc@TMPa{z}{1}{1}{#5}% + \fi + \else + \def\pgfplots@target@unit@scale@z{0}% + \def\pgfplots@target@unit@scale@zx{0}% + \def\pgfplots@target@unit@scale@zy{0}% + \def\pgfplots@target@unit@scale@inv@z{inf}% + \fi + % +}% + +\def\pgfplots@notify@final@scalings#1{% + \pgfkeys{/pgfplots/scaling/.cd, + .unknown/.code={% +%\message{setting key '\pgfkeyscurrentkey' to {##1}^^J} + \pgfkeyssetvalue{\pgfkeyscurrentkey}{##1}% + }, + #1% + }% +}% + +% #1: either x,y, or z +% #2: the new exponent +\def\pgfplots@apply@datascaletrafo@change@#1#2{% + \pgfplots@if{pgfplots@apply@datatrafo@#1}{% + \pgfplotscoordmath{#1}{datascaletrafo get params}% + \edef\pgfplots@loc@TMPa{\expandafter\pgfutil@firstoftwo\pgfmathresult}% + \edef\pgfplots@loc@TMPb{#2}% + \ifx\pgfplots@loc@TMPa\pgfplots@loc@TMPb + % ok; the data scale trafo did not change at all - we + % still have the same exponent. + \else + % Ah - we have a new data scale trafo! + \pgfplotscoordmath{#1}{datascaletrafo inverse}{\csname pgfplots@#1min\endcsname}% + \let\pgfplots@loc@TMPa=\pgfmathresult + \pgfplotscoordmath{#1}{datascaletrafo inverse}{\csname pgfplots@#1max\endcsname}% + \let\pgfplots@loc@TMPb=\pgfmathresult + % + % first: determine the optimal shift (which is the + % transformed lower limit): + \pgfplotscoordmath{#1}{datascaletrafo set params}{#2}{0}% + \pgfplotscoordmath{#1}{datascaletrafo}{\pgfplots@loc@TMPa}% + % + % ok, finalize the data trafo: + \pgfplotscoordmath{#1}{datascaletrafo set params}{#2}{\pgfmathresult}% + % + % ... and recompute axis limits: + \pgfplotscoordmath{#1}{datascaletrafo}{\pgfplots@loc@TMPa}% + \expandafter\let\csname pgfplots@#1min\endcsname=\pgfmathresult + \pgfplotscoordmath{#1}{datascaletrafo}{\pgfplots@loc@TMPb}% + \expandafter\let\csname pgfplots@#1max\endcsname=\pgfmathresult + \fi + }{}% +}% + +% Inspects the limit enlargement factors and reinitializes the data +% scale transformations. +% +% The purpose of this method is to avoid "dimension too large" if the +% factors exceed certain limits. +% +% INPUT: +% \pgfplots@target@limitrescale@x and its variants for y and z +% \pgfplots@target@unit@scale@inv@x and its variants for y and z +% +% OUTPUT: +% \pgfplots@target@datascaletrafo@x@exponent and its variants for y and z +% -> contains NEW datascaletrafo exponents +% \pgfplots@target@datascaletrafo@x@exponent@old and its variants for y and z +% -> contains OLD datascaletrafo exponents +% \pgfplots@target@unit@scale@inv@x and its variants for y and z +% -> contains (modified) unit vector scales +\def\pgfplots@scaling@adjust@datascaling{% + \pgfplots@scaling@adjust@datascaling@for x% + \pgfplots@scaling@adjust@datascaling@for y% + \pgfplots@scaling@adjust@datascaling@for z% +} +\def\pgfplots@scaling@adjust@datascaling@for#1{% + \pgfplots@if{pgfplots@apply@datatrafo@#1}{% + \pgfplotscoordmath{#1}{datascaletrafo get params}% + \def\pgfplots@loc@TMPa##1##2{% + \expandafter\def\csname pgfplots@target@datascaletrafo@#1@exponent\endcsname{##1}% + \expandafter\def\csname pgfplots@target@datascaletrafo@#1@exponent@old\endcsname{##1}% + }% + \expandafter\pgfplots@loc@TMPa\pgfmathresult + \pgf@xa=\csname pgfplots@target@limitrescale@#1\endcsname pt + \ifdim\pgf@xa>5pt % + % We want to enlarge axis limits considerably! + % + \pgfplots@scaling@adjust@datascaling@for@get@compensation{\pgf@xa}% + % + % Ok, make sure that we do not get "dimension too large" + % by adjusting the data scale trafo. + % + % Note that the data scale trafo has (only) been applied + % to axis limits, so we have to reapply it before these + % changes can take effect: + \pgf@xa=\csname pgfplots@target@unit@scale@inv@#1\endcsname pt + \divide\pgf@xa by\pgfplotsretval\relax % + \expandafter\edef\csname pgfplots@target@unit@scale@inv@#1\endcsname{\pgf@sys@tonumber\pgf@xa}% + % + \c@pgf@countd=\csname pgfplots@target@datascaletrafo@#1@exponent\endcsname\relax + \advance\c@pgf@countd by-\pgfplotsretvalb\relax % + \expandafter\edef\csname pgfplots@target@datascaletrafo@#1@exponent\endcsname{\the\c@pgf@countd}% + \fi + }{% + \expandafter\def\csname pgfplots@target@datascaletrafo@#1@exponent\endcsname{0}% + \expandafter\def\csname pgfplots@target@datascaletrafo@#1@exponent@old\endcsname{0}% + }% +} + +% Returns +% \pgfplotsretval -> the absolute scaling +% \pgfplotsretvalb -> the log10 of the scaling +\def\pgfplots@scaling@adjust@datascaling@for@get@compensation#1{ + \ifdim#1<100pt % + \def\pgfplotsretval{10}% + \def\pgfplotsretvalb{1}% + \else + \ifdim#1<1000pt % + \def\pgfplotsretval{100}% + \def\pgfplotsretvalb{2}% + \else + \ifdim#1<10000pt % + \def\pgfplotsretval{1000}% + \def\pgfplotsretvalb{3}% + \else + % too much for this approach anyway... and probably no + % use-case at all. + \def\pgfplotsretval{1000}% + \def\pgfplotsretvalb{3}% + \fi + \fi + \fi +}% + +% Computes the initial scale from a plot box of unit size to the +% desired with and height. +% +% #1 the desired width +% #2 the desired height +% #3 [output] a macro which will contain the horizontal (x) scale +% #4 [output] a macro which will contain the vertical (y) scale +% #5 [input/output] a macro which, on input, contains the x axis limit compensation scale +% which is required to select a single unit vector scale without +% reducing the plots dimension (without actually respecting the +% final dimension). On output, the input has been multiplied by +% some additional x limit componensation scale (selected by scale +% uniformly strategy). +% #6 [input/output] a macro which will contain a y axis limit +% compensation scale; it works in the same way as #5 +% #7 [input/output] a macro which will contain a z axis limit +% compensation scale; it works in the same way as #5 +\def\pgfplots@get@scale@horiz@and@vert#1#2#3#4#5#6#7{% + \begingroup + \edef\pgfplots@target@limitrescale@x{#5}% + \edef\pgfplots@target@limitrescale@y{#6}% + \edef\pgfplots@target@limitrescale@z{#7}% + \pgfplots@get@dimension@of@BB + \pgf@xa=\pgfplotsretval\relax + \pgf@xb=\pgfplotsretvalb\relax + \pgf@ya=#1\relax + \pgf@yb=#2\relax + \edef\w{\pgf@sys@tonumber\pgf@xa}% + \edef\h{\pgf@sys@tonumber\pgf@xb}% + \edef\W{\pgf@sys@tonumber\pgf@ya}% + \edef\H{\pgf@sys@tonumber\pgf@yb}% +%\message{PGFPLOTS: the current unit vectors result in a UNIT BB of (\the\pgf@xa,\the\pgf@xb). Scaling it to (\the\pgf@ya,\the\pgf@yb)...^^J}% + \ifcase\pgfplots@scale@mode@choice + % scale mode=auto does not happen here + \or + % scale mode=none does not happen here + \or + % scale mode=stretch to fill + % + % This is very simple: + % + % Compute individual scaling factors for X and Y + % such that the UNIT-BB will have size #1,#2. Keep limits. + \pgfmathdivide@{\W}{\w}% + \let\scalex=\pgfmathresult + % + \pgfmathdivide@{\H}{\h}% + \let\scaley=\pgfmathresult + % + % no changes to the axis limits - we only rescale units. + \def\pgfplots@target@limitrescale@x@{1}% + \def\pgfplots@target@limitrescale@y@{1}% + \def\pgfplots@target@limitrescale@z@{1}% + \pgfplots@BB@update@cumulative@limit@compensations + \or + % scale mode=scale uniformly + % compute ONE common scale for both, X and Y - and satisfy + % width/height constraints by adjusting the axis limits. + % + % The idea is as follows: + % we WANT to have width W and height H. + % The constraint is that each unit vector must get the same + % scale -- but the axis limits can receive individual + % compensation scales. But it should "look reasonable well". + % + % currently, we have + % w = r_x e_xx + r_y e_yx + rz e_zx (with e_zx = 0 typically) + % h = r_x e_xy + r_y e_yy + rz e_zy + % + % where r_x, r_y, r_z are the maximal range of the data in + % x,y,z respectively. Depending on the context of this method, + % they are either 1 (relative coords) or + % (xmax-xmin) (absolute coords). + % + % Now, search for a set of real numbers + % Rx, Ry, Rz, s + % such that + % W = (Rx r_x) (s e_xx) + (Ry r_y) (s e_yx) + (Rz r_z) (s e_zx) + % H = (Rx r_x) (s e_xy) + (Ry r_y) (s e_yy) + (Rz r_z) (s e_zy) + % + % clearly, the solution is not unique. + % ONE choice is to employ the fact that e_zx = 0 (or, for 2d + % plots, e_zx=0, e_zy=0 and e_yx=0): + % + % in that case, we can compute s such that the equation for W + % is satisfied and compensate only the limit r_z, i.e. to + % choose + % s := W / w, (scale to satisfy width constraint) + % Rx := Ry := 1 (keep limits in X and Y) + % Rz = ( H - s (w - r_z e_zy) ) / (s r_z e_zy) (adjust z limit to satisfy height constraint) + % + % This approach works well if W < H . If W > H, it will look + % bad: Rz will be less than 1, causing the limit to become + % smaller. This, in turn, will clip away parts of the image. + % + % + % + % Another solution is to make it the other way: to keep the + % limit r_z, but to reduce the size and enlarge the other + % limits to satisfy the size constraints. This solution is + % considerably more involved; it requires to solve a nonlinear + % set of equations. + % + % Formally, this second solution uses + % Rz := 1 (no limit componensation scale for z -- keep z limit) + % R:= Rx := Ry (same limit componensation scale for both X and Y) + % R and s still need to be determined from the two equations for W + % and H. + % + % Substituting the given choices into the equations for W and H, we find + % + % R = W / (s w) + % + % s = H * (R * (h-r_z e_zy) + r_z e_zy)^-1 + % + % Here, we employed the definition of 'h', see above. The + % equations are non-linear. + % + % ATTENTION: we assume that the datascaletrafo set params + % method has been called with THE SAME SCALE IN EACH + % DIRECTION. + \if0\pgfplots@scaleuniformly@choice + % scale uniformly strategy=auto + \pgfplots@get@scale@horiz@and@vert@scaleuniformly@of@optimal@strategy + \else + \pgfplots@get@scale@horiz@and@vert@scaleuniformly + \pgfplots@BB@update@cumulative@limit@compensations + \fi + \fi + % + \xdef\pgfplots@glob@TMPa{% + \noexpand\def\noexpand#3{\scalex}% + \noexpand\def\noexpand#4{\scaley}% + \noexpand\def\noexpand#5{\pgfplots@target@limitrescale@x}% + \noexpand\def\noexpand#6{\pgfplots@target@limitrescale@y}% + \noexpand\def\noexpand#7{\pgfplots@target@limitrescale@z}% + }% + \endgroup + \pgfplots@glob@TMPa +}% + +% This is the implementation for 'scale uniformly strategy=auto'. +% +% It works by finding the strategy which involves the minimal scaling +% overhead. +% +% To this end, it computes the result for each 'scale uniformly +% strategy', and computes a cost function. The one with optimal cost +% function wins, and its results are returned. +% +% The cost function is the overal scaling which is applied to AXIS +% LIMITS. It works as follows: +% 1. if a choice requires to REDUCE the axis limits in order to +% fulfill all constraints, it is neglected (using maximal cost 16000). +% Reducing axis limits may clip away information. +% +% 2. if a choice requires to ENLARGE some axis limits, its cost is the +% sum of the individual scaling factors (even if they are are one - +% who cares). +% +% Note that this method *is* relevant and the optimization appears to +% be necessary. +% Examples are +% unittest_scalemode_2d_standard_1.tex +% and perhaps +% unittest_scalemode_2d_standard_0.tex +% and more involved 3d examples are also available. +% +% My first guess was that it is sufficient to decide the optimal +% strategy in advance by comparing the target width and the target +% height - but that proved to be insufficient: it leads to correct +% results, but wastes too much space (i.e. enlarges limits too much). +% +% ATTENTION: the cost function INCLUDES RESULTS OF +% \pgfplots@BB@for@plotbox@get@unit@scales@for@limits and its +% corrector +% \pgfplots@BB@for@plotbox@get@unit@scales@compensated@axis@limits. +% +% More precisely, it relies on already computes limit compensation +% factors which do not depend on the target width/target height: both +% \pgfplots@BB@for@plotbox@get@unit@scales@compensated@axis@limits and +% this implementation of 'scale uniformly strategy' can be used to compute +% the cost of a strategy. +% +\def\pgfplots@get@scale@horiz@and@vert@scaleuniformly@of@optimal@strategy{% + \begingroup + \def\mathclass{default}% + \pgfplotscoordmath{\mathclass}{max limit}% + \let\pgfplots@cost@for@choice@superhigh=\pgfmathresult% + % + % private helpers to compute the cost. + \def\pgfplots@scalestrategy@compute@cost{% + \begingroup + % ATTENTION: this call changes + % '\pgfplots@target@limitrescale@x' and its variants. + % Restore its value after the iteration: + \pgfplots@BB@update@cumulative@limit@compensations + \pgfplotscoordmath{\mathclass}{one}% + \let\ONE=\pgfmathresult + \pgfplotscoordmath{\mathclass}{parsenumber}{\pgfplots@target@limitrescale@x}% + \let\X=\pgfmathresult + \pgfplotscoordmath{\mathclass}{parsenumber}{\pgfplots@target@limitrescale@y}% + \let\Y=\pgfmathresult + \ifpgfplots@threedim + \pgfplotscoordmath{\mathclass}{parsenumber}{\pgfplots@target@limitrescale@z}% + \let\Z=\pgfmathresult + \else + \let\Z=\pgfplots@target@limitrescale@z + \fi + % + % If one of the resulting limit compensation scales is + % less than 1, we can immediately skip it - we do not want + % to risk to clip away image content. + \pgfplotscoordmath{\mathclass}{if less than}{\X}{\ONE}{% + \let\pgfplots@cost@for@choice=\pgfplots@cost@for@choice@superhigh + }{% + \pgfplotscoordmath{\mathclass}{if less than}{\Y}{\ONE}{% + \let\pgfplots@cost@for@choice=\pgfplots@cost@for@choice@superhigh + }{% + \ifpgfplots@threedim + \pgfplotscoordmath{\mathclass}{if less than}{\Z}{\ONE}{% + \let\pgfplots@cost@for@choice=\pgfplots@cost@for@choice@superhigh + }{% + % ah - 3 limit scales >= 1. Good, assign cost: + \pgfplots@scalestrategy@compute@cost@ + }% + \else + % ah - all limit scales >=1. Good, assign cost: + \pgfplots@scalestrategy@compute@cost@ + \fi + }% + }% +%\message{scale uniformly strategy=auto: '\pgfplots@tostring@scaleuniformlystrategy{\pgfplots@scaleuniformly@choice}' has cost \pgfplots@cost@for@choice\space(limit rescaling factors x=\X, y=\Y, z=\Z)^^J}% + \xdef\pgfplots@glob@TMPa{% + \noexpand\def\noexpand\pgfplots@scaleuniformly@choice{\pgfplots@scaleuniformly@choice}% + \noexpand\def\noexpand\scalex{\scalex}% + \noexpand\def\noexpand\scaley{\scaley}% + \noexpand\def\noexpand\pgfplots@target@limitrescale@x{\pgfplots@target@limitrescale@x}% + \noexpand\def\noexpand\pgfplots@target@limitrescale@y{\pgfplots@target@limitrescale@y}% + \noexpand\def\noexpand\pgfplots@target@limitrescale@z{\pgfplots@target@limitrescale@z}% + }% + \pgfmath@smuggleone\pgfplots@cost@for@choice + % keep in mind that this scope IS NECESSARY: we have + % changed the target quantities + % \pgfplots@target@limitrescale@x and its variants! + \endgroup + \let\pgfplots@scalestrategy@values=\pgfplots@glob@TMPa + }% + \def\pgfplots@scalestrategy@compute@cost@{% + \pgfplotscoordmath{\mathclass}{op}{add}{{\X}{\Y}}% + \ifpgfplots@threedim + \pgfplotscoordmath{\mathclass}{op}{add}{{\pgfmathresult}{\Z}}% + \fi + \let\pgfplots@cost@for@choice=\pgfmathresult + }% + % + % compute initial cost: + \def\pgfplots@scaleuniformly@choice{3}% change horizontal limits + \pgfplots@get@scale@horiz@and@vert@scaleuniformly + \pgfplots@scalestrategy@compute@cost + % + % init minimum: + \let\pgfplots@cost@for@choice@arg=\pgfplots@scalestrategy@values + \let\pgfplots@cost@for@choice@sofar=\pgfplots@cost@for@choice% + % + % compute cost of next strategy: + \def\pgfplots@scaleuniformly@choice{2}% change vertical limits + \pgfplots@get@scale@horiz@and@vert@scaleuniformly + \pgfplots@scalestrategy@compute@cost + % + % update minimum: + \pgfplotscoordmath{\mathclass}{if less than}{\pgfplots@cost@for@choice}{\pgfplots@cost@for@choice@sofar}{% + \let\pgfplots@cost@for@choice@arg=\pgfplots@scalestrategy@values + \let\pgfplots@cost@for@choice@sofar=\pgfplots@cost@for@choice% + }{% + }% + % + \ifx\pgfplots@cost@for@choice@sofar\pgfplots@cost@for@choice@superhigh + % the algorithm discarded every available strategy. + \def\pgfplots@scaleuniformly@choice{1}% fall back to 'units only' + \pgfplots@get@scale@horiz@and@vert@scaleuniformly + \pgfplots@scalestrategy@compute@cost + \let\pgfplots@cost@for@choice@arg=\pgfplots@scalestrategy@values + \let\pgfplots@cost@for@choice@sofar=\pgfplots@cost@for@choice% + \fi + % + % + \global\let\pgfplots@glob@TMPa=\pgfplots@cost@for@choice@arg + \endgroup + \pgfplots@glob@TMPa +%\message{scale uniformly strategy=auto: choosing '\pgfplots@tostring@scaleuniformlystrategy{\pgfplots@scaleuniformly@choice}'^^J}% +} + +\def\pgfplots@tostring@scaleuniformlystrategy#1{% + % scale uniformly strategy: + \ifcase#1\relax + auto + \or + units only + \or + change vertical limits + \or + change horizontal limits + \fi +} +% Does the work for 'scale mode=scale uniformly' inside of +% \pgfplots@get@scale@horiz@and@vert. +% +% It returns its result into \pgfplots@target@limitrescale@x@ (i.e. +% with an extra '@') +\def\pgfplots@get@scale@horiz@and@vert@scaleuniformly{% + \ifcase\pgfplots@scaleuniformly@choice\relax + % scale uniformly strategy=auto does not happen here. + \or + % scale uniformly strategy=units only + \pgfplots@scaleuniformly@onlyunits + \or + % scale uniformly strategy=change vertical limits + % + % first, scale to the width ... + \pgfplots@scaleuniformly@onlyunits@{\w}{\W}% + % ... and change (only) vertical limits to get the "correct" + % height: + \ifdim\pgf@zy=0pt + \ifdim\pgf@yx=0pt + \pgfplots@prepare@vertical@rescaling@for@scale@uniformly@in@dir{y}\returninto\pgfplots@target@limitrescale@y@ + \else + \pgfplots@scale@uniformly@fallback + \fi + \else + \ifdim\pgf@zx=0pt + \pgfplots@prepare@vertical@rescaling@for@scale@uniformly@in@dir{z}\returninto\pgfplots@target@limitrescale@z@ + \else + \pgfplots@scale@uniformly@fallback + \fi + \fi + \or + % scale uniformly strategy=change horizontal limits + \ifdim\pgf@zy=0pt + \ifdim\pgf@yx=0pt + \ifdim\pgf@xy=0pt + % special 2d routine with explicit solution + \pgfplots@scaleuniformly@change@horizontal@limits@twodim + {\scalex} + {\pgfplots@target@limitrescale@x@} + {\pgfplots@target@limitrescale@y@} + {\pgfplots@target@limitrescale@z@}% + \else + \pgfplots@scale@uniformly@fallback + \fi + \else + \pgfplots@scale@uniformly@fallback + \fi + \else + \ifdim\pgf@zx=0pt + \pgfplots@scaleuniformly@change@horizontal@limits + {\scalex} + {\pgfplots@target@limitrescale@x@} + {\pgfplots@target@limitrescale@y@} + {\pgfplots@target@limitrescale@z@}% + \else + \pgfplots@scale@uniformly@fallback + \fi + \fi + \let\scaley=\scalex + \fi +} + +\def\pgfplots@scaleuniformly@onlyunits{% + % scale to the smaller target dimension: + \ifdim\W pt<\H pt % + \pgfplots@scaleuniformly@onlyunits@{\w}{\W}% + \else + \pgfplots@scaleuniformly@onlyunits@{\h}{\H}% + \fi +}% + +% #1 : the actual dimension +% #2 : the target dimension +\def\pgfplots@scaleuniformly@onlyunits@#1#2{% + \def\pgfplots@target@limitrescale@x@{1}% + \def\pgfplots@target@limitrescale@y@{1}% + \def\pgfplots@target@limitrescale@z@{1}% + \pgfmathdivide@{#2}{#1}% + \let\scalex=\pgfmathresult + \let\scaley=\scalex % we *need* the same unit scale. +}% + +% Computes 'scale uniformly strategy=change horizontal limits'. +% This is a complicated solution, see the documentation in the +% implementation for +% 'scale mode=scale uniformly' +% +% #1 [output] a macro which will contain the (uniform) scale for the +% unit vectors +% #2 [output] a macro which will contain a x axis limit compensation scale +% #3 [output] a macro which will contain a x axis limit compensation scale +% #4 [output] a macro which will contain a x axis limit compensation scale +\def\pgfplots@scaleuniformly@change@horizontal@limits#1#2#3#4{% + \begingroup + % + \pgfplots@BB@for@plotbox@getunitheight{\pgf@xc}{z}% + % + % compute the rest in floating point - intermediate results may + % become too huge for TeX. + \pgfplotscoordmath{default}{parsenumber}{\expandafter\pgf@sys@tonumber\csname pgf@xc\endcsname}% + \let\M=\pgfmathresult + % + \pgfplotscoordmath{default}{parsenumber}{\w}% + \let\w=\pgfmathresult + \pgfplotscoordmath{default}{parsenumber}{\W}% + \let\W=\pgfmathresult + \pgfplotscoordmath{default}{parsenumber}{\h}% + \let\h=\pgfmathresult + \pgfplotscoordmath{default}{parsenumber}{\H}% + \let\H=\pgfmathresult + \pgfplotscoordmath{default}{op}{divide}{{\W}{\w}}% + \let\Wwinv=\pgfmathresult + \pgfplotscoordmath{default}{op}{subtract}{{\h}{\M}}% + \let\hminusM=\pgfmathresult + % + \pgfplotscoordmath{default}{one}% + \let\S=\pgfmathresult% + \let\R=\pgfmathresult% + \let\Rx=\pgfmathresult + \def\Rz{1}% + % + \def\pgfplots@hold@S@get@R{% + \pgfplotscoordmath{default}{op}{divide}{{\Wwinv}{\S}}% + \let\R=\pgfmathresult +%\message{updated R = \R\space ( S = \S ) ^^J}% + }% + \def\pgfplots@hold@R@get@S{% + \pgfplotscoordmath{default}{op}{multiply}{{\R}{\hminusM}}% + \pgfplotscoordmath{default}{op}{add}{{\pgfmathresult}{\M}}% + \pgfplotscoordmath{default}{op}{divide}{{\H}{\pgfmathresult}}% + \let\S=\pgfmathresult +%\message{updated S = \S\space ( R = \R ) ^^J}% + }% + % + % This is the (most stupid) nonlinear method which is at hand: + % fix point iteration. + % choose R arbitrarily (R=1 seems adequate), solve for s. + % Then, fix s and solve for R. Then, fix R and + % solve for s until convergence. + \c@pgf@countc=0 + \pgfplotsloop{% + \ifnum\c@pgf@countc<\pgfkeysvalueof{/pgfplots/scale uniformly strategy iter} % + \pgfplotsloopcontinuetrue + \else + \pgfplotsloopcontinuefalse + \fi + }{% + \pgfplots@hold@R@get@S \pgfplots@hold@S@get@R + \advance\c@pgf@countc by1 % + }% + % + \pgfplotscoordmath{default}{tofixed}{\R}\let\R=\pgfmathresult + \pgfplotscoordmath{default}{tofixed}{\S}\let\S=\pgfmathresult + \xdef\pgfplots@glob@TMPa{% + \noexpand\def\noexpand#1{\S}% + \noexpand\def\noexpand#2{\R}% + \noexpand\def\noexpand#3{\R}% + \noexpand\def\noexpand#4{\Rz}% + }% + \endgroup + % + \pgfplots@glob@TMPa +}% + +% Computes 'scale uniformly strategy=change horizontal limits'. +% +% This is a simplified closed solution assuming that e_xy=0 and e_yx = 0 +% +% #1 [output] a macro which will contain the (uniform) scale for the +% unit vectors +% #2 [output] a macro which will contain a x axis limit compensation scale +% #3 [output] a macro which will contain a x axis limit compensation scale +% #4 [output] a macro which will contain a x axis limit compensation scale +\def\pgfplots@scaleuniformly@change@horizontal@limits@twodim#1#2#3#4{% + \begingroup + % Assuming that we have a standard 2d axis, i.e. + % e_zx = e_zy = 0, e_xy = 0, and e_yx =0, + % we can immediately compute a solution. + % + % In this case, we have the actual width + % w = r_x e_xx + r_y e_yx + rz e_zx + % = r_x e_xx + % and actual height + % h = r_x e_xy + r_y e_yy + rz e_zy + % = r_y e_yy + % and, consequently, desired width + % W = (Rx r_x) (s e_xx) + (Ry r_y) (s e_yx) + (Rz r_z) (s e_zx) + % = (Rx r_x) (s e_xx) + % and desired height + % H = (Rx r_x) (s e_xy) + (Ry r_y) (s e_yy) + (Rz r_z) (s e_zy) + % = (Ry r_y) (s e_yy). + % since this strategy changes horizontal limits (only), we have + % Ry := 1. + % We find + % s : = H/h + % and + % Rx : = W/w /s . + % + \pgfplotscoordmath{default}{parsenumber}{\w}% + \let\w=\pgfmathresult + \pgfplotscoordmath{default}{parsenumber}{\W}% + \let\W=\pgfmathresult + \pgfplotscoordmath{default}{parsenumber}{\h}% + \let\h=\pgfmathresult + \pgfplotscoordmath{default}{parsenumber}{\H}% + \let\H=\pgfmathresult + \pgfplotscoordmath{default}{op}{divide}{{\H}{\h}}% + \let\S=\pgfmathresult + \pgfplotscoordmath{default}{op}{divide}{{\W}{\w}}% + \pgfplotscoordmath{default}{op}{divide}{{\pgfmathresult}{\S}}% + \let\Rx=\pgfmathresult + \def\Ry{1}% + \def\Rz{1}% + % + \pgfplotscoordmath{default}{tofixed}{\Rx}\let\Rx=\pgfmathresult + \pgfplotscoordmath{default}{tofixed}{\S}\let\S=\pgfmathresult + \xdef\pgfplots@glob@TMPa{% + \noexpand\def\noexpand#1{\S}% + \noexpand\def\noexpand#2{\Rx}% + \noexpand\def\noexpand#3{\Ry}% + \noexpand\def\noexpand#4{\Rz}% + }% + \endgroup + % + \pgfplots@glob@TMPa +}% + +\def\pgfplots@BB@update@cumulative@limit@compensations{% +%\message{ -> additional limit componensation scales x=\pgfplots@target@limitrescale@x@, y=\pgfplots@target@limitrescale@y@, z=\pgfplots@target@limitrescale@z@^^J}% + % add limit compensation to what we have from earlier + % operations: + \pgfplotscoordmath{pgfbasic}{op}{multiply}{{\pgfplots@target@limitrescale@x@}{\pgfplots@target@limitrescale@x}}% + \let\pgfplots@target@limitrescale@x=\pgfmathresult + \pgfplotscoordmath{pgfbasic}{op}{multiply}{{\pgfplots@target@limitrescale@y@}{\pgfplots@target@limitrescale@y}}% + \let\pgfplots@target@limitrescale@y=\pgfmathresult + \pgfplotscoordmath{pgfbasic}{op}{multiply}{{\pgfplots@target@limitrescale@z@}{\pgfplots@target@limitrescale@z}}% + \let\pgfplots@target@limitrescale@z=\pgfmathresult +}% + +\def\pgfplots@scale@uniformly@fallback{% + \ifpgfplots@scaleuniformly@warning + \pgfplots@warning{Sorry, 'scale uniformly' failed because its actual implementation works only if y_x = 0 and x_y = 0 (for 2d axes) or if z_x = 0 (for 3d axes). The result will not fill the prescribed dimensions. Falling back to 'scale uniformly strategy=units only. (use scale uniformly warning=false to disable this warning)}% + \fi + \pgfplots@scaleuniformly@onlyunits +}% + +% This is part of the implementation of 'scale mode=scale uniformly'. +% +% Its purpose it to set up the initial scaling such that +% 1. each unit vector gets the same scale +% 2. the axis limits are resized (enlarged) to keep the plot box ratio +% (as far as possible) +% +% It repairs the outcome of +% \pgfplots@BB@for@plotbox@get@unit@scales@for@limits . +% +% The assumption is that on input #1, #2, and #3 are the factors which +% would be used by stretch-to-fill in order to squeze the axis limits +% into the plot box defined by e_x, e_y, and e_z (the unit vectors). +% +% On output, #1, #2, and #3 will be modified such that *each has the +% same value*. The value will be chosen with care. More precisely, it +% is the *minimum* of {#1,#2,#3}. +% +% Clearly, 'scale mode=scale uniformly' has less freedom than +% strech-to-fill. In order to keep the plot box ratio intact (as far +% as possible), the axis limits will be rescaled to componsate for the +% ignored scaling factors. More precisely, if direction i is not the +% extremal value (as discussed in the last paragraph), the axis limits +% will be rescaled by #i/extremum . +% +% +% +% #1: on input, it contains the x unit scale which would be taken without the +% compensation. On output, it contains the x unit scale which *will* be +% used. +% #2: same as #1, but for y +% #3: same as #1, but for z +% #4: [output] a scale for use as argument of \pgfplots@apply@unit@vector@rescale@keep@size{x}{<arg>} +% #5: [output] a scale for use as argument of \pgfplots@apply@unit@vector@rescale@keep@size{y}{<arg>} +% #6: [output] a scale for use as argument of \pgfplots@apply@unit@vector@rescale@keep@size{z}{<arg>} +% +% The output arguments need to be applied before they take effect. +\def\pgfplots@BB@for@plotbox@get@unit@scales@compensated@axis@limits#1#2#3#4#5#6{% + \begingroup + % ATTENTION : this code ASSUMES that the datascaling trafo is + % initialized with THE SAME SCALE IN EACH DIRECTION. + % The data scaling also leads to (potentially non-uniform) scaling per component. + % + % Note that we could handle the datascaling here -- but we would + % leave the supported number range easily. That's why that part of + % the 'scale mode=scale uniformly' implementation has been moved + % to \pgfplots@set@optimal@datatrafos@allaxes + % + % This here handles the limits only. + \edef\pgfplots@scale@unitx{#1}% + \edef\pgfplots@scale@unity{#2}% + \edef\pgfplots@scale@unitz{#3}% + % + % compute extreme + arg extreme of these scales: + \def\pgfplots@extreme@scale{-16300}% + \def\pgfplots@extreme@scale@arg{NONE}% + % + \if0\b@pgfplots@unitvec@is@zero@x + \ifdim\pgfplots@extreme@scale pt<\pgfplots@scale@unitx pt + \let\pgfplots@extreme@scale=\pgfplots@scale@unitx + \def\pgfplots@extreme@scale@arg{x}% + \fi + \fi + \if0\b@pgfplots@unitvec@is@zero@y + \ifdim\pgfplots@extreme@scale pt<\pgfplots@scale@unity pt + \let\pgfplots@extreme@scale=\pgfplots@scale@unity + \def\pgfplots@extreme@scale@arg{y}% + \fi + \fi + \if0\b@pgfplots@unitvec@is@zero@z + \ifdim\pgfplots@extreme@scale pt<\pgfplots@scale@unitz pt + \let\pgfplots@extreme@scale=\pgfplots@scale@unitz + \def\pgfplots@extreme@scale@arg{z}% + \fi + \fi + % + % Now, adjust axis limits to compensate for the effect: we still + % want to have a plot box which is as close as possible to the + % target plot box. + \def\pgfplots@loc@TMPa##1##2{% + \if0\csname b@pgfplots@unitvec@is@zero@##1\endcsname + \if1\pgfplots@scaleuniformly@choice % FIXME : this appears to be too much. Disable this!? + % ok, nothing to do for this direction. + \pgfplotscoordmath{pgfbasic}{one}% + \let##2=\pgfmathresult + \else + \if\pgfplots@extreme@scale@arg ##1% + % ok, nothing to do for this direction. + \pgfplotscoordmath{pgfbasic}{one}% + \let##2=\pgfmathresult + \else + \pgfplotscoordmath{pgfbasic}{op}{divide}{{\pgfplots@extreme@scale}{\csname pgfplots@scale@unit##1\endcsname}}% + % do not call apply@unit@rescale immediately because the + % unit vectors may not be in their final state. Postpone until + % they are final. + \edef##2{\pgfmathresult}% + \fi + \fi + \else + \def##2{1}% + \fi + }% + \pgfplots@loc@TMPa{x}{#4}% + \pgfplots@loc@TMPa{y}{#5}% + \pgfplots@loc@TMPa{z}{#6}% + % + \toks0=\expandafter{#4}% + \toks1=\expandafter{#5}% + \toks2=\expandafter{#6}% + \xdef\pgfplots@glob@TMPa{% + % same scale in each dir: + \def\noexpand#1{\pgfplots@extreme@scale}% + \def\noexpand#2{\pgfplots@extreme@scale}% + \def\noexpand#3{\pgfplots@extreme@scale}% + \def\noexpand#4{\the\toks0}% + \def\noexpand#5{\the\toks1}% + \def\noexpand#6{\the\toks2}% + }% + \endgroup + \pgfplots@glob@TMPa +} + +% #1 : a dimen register +% #2 : x, y, or z +\def\pgfplots@BB@for@plotbox@getunitheight#1#2{% + #1=\csname pgfplots@plotbox@#2max\endcsname\csname pgf@#2y\endcsname + \advance#1 by -\csname pgfplots@plotbox@#2min\endcsname\csname pgf@#2y\endcsname + \ifdim#1<0pt % + % we want to return a height. It is also bigger than 0. + % the difference above may be negative if the unit points + % downward (special combinations of view/h and view/v) + #1=-#1\relax + \fi +}% + + +% Modifies the AXIS LIMITS to ensure that a suitable width/height is +% achieved. +% +% This does NOT introduce a further scale to the unit vectors. +% +% #1: a direction (x,y, or z) +% #2: a macro name. It will be assigned globally. It will contain +% EXECUTABLE instructions which will modify the axis limits to fit the +% scaling. +% +% PRECONDITION: +% - \pgfplots@glob@TMPa contains the already computed +% scaling factor for 'scale uniformly' +% - \pgf@xb is the actual height and \pgf@yb is the desired height +% (set as in the scaling routine) +% +% POSTCONDITION: +% #2 will contain the argument <arg> for \pgfplots@apply@unit@vector@rescale@keep@size{#1}{<arg>} +\def\pgfplots@prepare@vertical@rescaling@for@scale@uniformly@in@dir#1\returninto#2{% + % The strategy is as follows: + % 1. I want to fit the axis into width #1 (\pgf@ya) and + % height #1 (\pgf@yb). + % 2. I want to MAINTAIN the unit vector ratio. + % 3. I want to MAINTAIN the unit vector directions. + % + % I already know the scaling factor to fit the width (it + % is stored in \scalex = \scaley). + % Let's call it "s". + % + % Consequently, a uniform scaling by "s" leads to the image + % height + % h = s* (r_x * e_xy + r_y * e_yy + r_z * e_zy) + % where r_i = (imax - imin). This here is essentially the + % same as the bounding box computation above (at least for + % standart orthographic 3D axes). + % + % What I want now is to enlarge the limits such that I + % have BOTH, width #1 AND height #2, without obscuring the + % unit vector ratio. Recall that width #1 is already + % given. + % + % This strategy achieves this goal by + % modifying axis limits for an axis whose unit vector is + % parallel to the canvas y axis, i.e. e_i = (0,*). + % + % That means I have to introduce a SECOND scale s_z which + % applies only to the Z unit vector (since e_z = (0,*) ). + % If H = #2 is the desired height, I find the target + % equation for s_z, + % + % H = s* r_x e_xy + s * r_y e_yy + s_z * s * r_z * e_zy + % => + % s_z = ( H- s*r_x e_xy - s*r_y e_yy) / ( s * r_z * e_zy). + % + % Remember that + % s = \scalex + % H = \H + % h = r_x * e_xy + r_y * e_yy + r_z * e_zy = \h + % => + % s_z = ( H- s*( h - r_z * e_zy) ) / ( s * r_z * e_zy). + % + \begingroup + \pgfplots@BB@for@plotbox@getunitheight{\pgf@xc}{#1}% + % + % compute the rest in floating point - intermediate results may + % become too huge for TeX. + \pgfplotscoordmath{default}{parsenumber}{\expandafter\pgf@sys@tonumber\csname pgf@xc\endcsname}% + \let\pgfplots@diff=\pgfmathresult + % + \pgfplotscoordmath{default}{parsenumber}{\scalex}% + \let\pgfplots@s=\pgfmathresult + % + % this is a precondition of this method: + \pgfplotscoordmath{default}{parsenumber}{\h}% + \let\h=\pgfmathresult + \pgfplotscoordmath{default}{parsenumber}{\H}% + \let\H=\pgfmathresult + % + % compute counter := H - s * (h - (max-min)) + \pgfplotscoordmath{default}{op}{subtract}{{\h}{\pgfplots@diff}}% + \pgfplotscoordmath{default}{op}{multiply}{{\pgfplots@s}{\pgfmathresult}}% + \pgfplotscoordmath{default}{op}{subtract}{{\H}{\pgfmathresult}}% + \let\pgfplots@counter=\pgfmathresult + % + % computer denom := s * (max-min) + \pgfplotscoordmath{default}{op}{multiply}{{\pgfplots@s}{\pgfplots@diff}}% + \let\pgfplots@denom=\pgfmathresult + % + \pgfplotscoordmath{default}{op}{divide}{{\pgfplots@counter}{\pgfplots@denom}}% + \pgfplotscoordmath{default}{tofixed}{\pgfmathresult}% + % + % Now, s_z = \pgfmathresult . + % + % Now, adjust the z limits. + % Note that \pgfplots@apply@unit@vector@rescale@keep@size + % has a slightly different context; it assumes that the + % unit vector has been rescaled, not the axis limits. + % Consequently, the inverse of the scaling factor enters. + % Since \pgfplots@apply@unit@vector@rescale@keep@size + % expects the inverse of the scale, we can provide + % \pgfmathresult: + \pgfmath@smuggleone\pgfmathresult + \endgroup + \let#2=\pgfmathresult +} + +\def\pgfplots@computeunitvectorlengths{% + \pgfplotsutil@edef@invoke\pgfmathveclen@{% + {\pgf@sys@tonumber\pgf@xx}% + {\pgf@sys@tonumber\pgf@xy}% + }% + \let\pgfplots@x@veclength=\pgfmathresult + \pgfplotsmath@ifzero{\pgfplots@x@veclength}{% + \def\pgfmathresult{infty}% + % this case will be caught in \pgfplots@initsizes + }{% + \expandafter\pgfmath@basic@reciprocal@\expandafter{\pgfmathresult}% + }% + \let\pgfplots@x@inverseveclength=\pgfmathresult + % + \pgfplotsutil@edef@invoke\pgfmathveclen@{% + {\pgf@sys@tonumber\pgf@yx}% + {\pgf@sys@tonumber\pgf@yy}% + }% + \let\pgfplots@y@veclength=\pgfmathresult + \pgfplotsmath@ifzero{\pgfplots@y@veclength}{% + \def\pgfmathresult{infty}% + % this case will be caught in \pgfplots@initsizes + }{% + \expandafter\pgfmath@basic@reciprocal@\expandafter{\pgfmathresult}% + }% + \let\pgfplots@y@inverseveclength=\pgfmathresult + % + \ifpgfplots@threedim + \pgfplotsutil@edef@invoke\pgfmathveclen@{% + {\pgf@sys@tonumber\pgf@zx}% + {\pgf@sys@tonumber\pgf@zy}% + }% + \let\pgfplots@z@veclength=\pgfmathresult + \pgfplotsmath@ifzero{\pgfplots@z@veclength}{% + \def\pgfmathresult{infty}% + % this case will be caught in \pgfplots@initsizes + }{% + \expandafter\pgfmath@basic@reciprocal@\expandafter{\pgfmathresult}% + }% + \let\pgfplots@z@inverseveclength=\pgfmathresult + \else + \def\pgfplots@z@veclength{0}% + \def\pgfplots@z@inverseveclength{infty}% + \fi +}% + +% Defines \pgfplots@view@dir@threedim according to the actual +% configuration of x,y,z (2d) unit vectors, assuming the associated +% unit vectors form a right-handed-system. +% +% The algorithm works for standard three dimensional axes. It works as +% follows: +% +% First, observe that we have a normal direction N if all its +% multiples are mapped onto the same point in 2D canvas +% coordinates. In other words: all 3D coordinates which are mapped +% onto an arbitrary point in 2D canvas coordinates (take, for example, +% the origin (0,0) ) are on a line in direction of N. +% +% We use this observation to compute the normal axis, i.e. we search +% for all points which are mapped onto the 2D canvas coordinate (0,0): +% N_x e_xx + N_y e_yx + N_z e_zx = 0 +% N_x e_xy + N_y e_yy + N_z e_zy = 0. +% All solutions make up a linear space of dimension 1 (up to special +% cases). In the general case, we can chose an arbitrary N_z != 0 +% and reduce the linear system to +% N_x e_xx + N_y e_yx = - N_z e_zx +% N_x e_xy + N_y e_yy = - N_z e_zy. +% Choosing *any* N_z != 0, say, N_z=-1 (which corresponds to view +% from above) will lead to a vector parallel to the normal direction. +% But it might have the wrong sign. +% +% FIXME : this fails if one of e_x or e_y is zero. +% +% To find the correct sign for N, I have made several case +% distinctions to identify the cases when we have to multiply with -1. +% The key idea is to assume a right-handed-system of unit vectors; +% this is the condition which allows to determine the sign. +% +% Furthermore, I assume that e_z points to the top, i.e. that e_zy >0. +% Then, there are (mainly) four conditions on the signs of e_x and e_y +% which indicate that we are viewing from below and should switch the +% sign of N (keep in mind that our initial choice was N_z =-1, see above). +% +% The conditions can be identified by drawing a 3D box and +% identifying the corner which represents the lower left 3D limits. +% +% You can visualize these cases using +%-------------------------------------------------- +% \pgfplotsset{ +% separate axis lines, +% every outer x axis line/.append style= {-stealth}, +% every outer y axis line/.append style= {-stealth}, +% every outer z axis line/.append style= {-stealth}, +% samples=2,shader=interp,title={view=\h,\v}, +% domain=0:1, +% enlargelimits=false, +% view=\h\v,xlabel=x,ylabel=y, +% extra description/.code={% +% \node[draw,fill=white] at (axis cs:0,0,0) {}; +% }, +% } +% +% \def\v{30} +% \foreach \h in {30,120,210,300} { +% \message{VIEW={\h}{\v}^^J} +% \begin{tikzpicture} +% \begin{axis} +% \addplot3[surf] {x}; +% \end{axis} +% \end{tikzpicture} +% +% } +% +% \def\v{-30} +% \foreach \h in {30,120,210,300} { +% \message{VIEW={\h}{\v}^^J} +% \begin{tikzpicture} +% \begin{axis} +% \addplot3[surf] {x}; +% \end{axis} +% \end{tikzpicture} +% +% } +%-------------------------------------------------- +% The precise formulas can be found below in the source code. +% +% You can override this function by the /pgfplots/view dir key. +\def\pgfplotsgetnormalforcurrentview{% + \pgfkeysgetvalue{/pgfplots/view dir}\pgfplots@loc@TMPc + \ifx\pgfplots@loc@TMPc\pgfutil@empty + \begingroup + % temporarily undo the effects of reversed axes -- we *really* + % need a right-handed-coordinate system here: + \if r\pgfkeysvalueof{/pgfplots/x dir/value}% + \pgf@xx=-\pgf@xx + \pgf@xy=-\pgf@xy + \fi + \if r\pgfkeysvalueof{/pgfplots/y dir/value}% + \pgf@yx=-\pgf@yx + \pgf@yy=-\pgf@yy + \fi + \if r\pgfkeysvalueof{/pgfplots/z dir/value}% + \pgf@zx=-\pgf@zx + \pgf@zy=-\pgf@zy + \fi + % FIRST: check for special cases. + \let\pgfplots@view@dir@threedim=\pgfutil@empty% + % Special case: + % e_xx = e_xy = 0 + % + % i.e.: + % + % ^ + % | |---| + % z | | + % |---| + % y-> + % + % In this case, N must be the x axis. + \ifdim\pgf@xx=0pt % + \ifdim\pgf@xy=0pt % + \def\pgfplots@view@dir@threedim{-1,0,0}% + \fi + \fi + % Special case: + % e_yx = e_yy = 0 + % + % i.e.: + % + % ^ + % | |---| + % z | | + % |---| + % x-> + % + % In this case, N must be the y axis. + \ifdim\pgf@yx=0pt % + \ifdim\pgf@yy=0pt % + \def\pgfplots@view@dir@threedim{0,1,0}% + \fi + \fi + % Special case: + % e_xy = e_yy = 0 (i.e. one row) + % + % that is hard to draw, use view={30}{0} to see it. + % + % In this case, N_z must be 0 and we have a different system. + \ifdim\pgf@xy=0pt % + \ifdim\pgf@yy=0pt % + \ifx\pgfplots@view@dir@threedim\pgfutil@empty + % we have N_x e_xx + N_y e_yx = 0 + % Note that e_xx != 0 and e_yx != 0 (otherwise one + % of our other special cases above would have + % caught the case) + % -> we have N_x = -N_y e_yx / e_xx and N_y + % arbitrary. only the sign needs to be fixed. + \def\pgfplots@view@dir@threedim@z{0}% + \def\pgfplots@view@dir@threedim@y{1}% fix it somehow. We correct the sign later. + \edef\pgfplots@loc@TMPa{-(\pgfplots@view@dir@threedim@y) * \pgf@sys@tonumber\pgf@yx / (\pgf@sys@tonumber\pgf@xx)}% + \pgfmathparse{\pgfplots@loc@TMPa}% + \let\pgfplots@view@dir@threedim@x=\pgfmathresult + % + \def\pgfplots@scale{1}% + % I identified these cases by comparing the + % results with \pgfplots@scale{1} with those of + % the view dir generated by + % \pgfplotssetaxesfromazel (which has the correct quality of solution) + \ifdim\pgf@zy>0pt % + \ifdim\pgf@xx<0pt % + \def\pgfplots@scale{-1}% + \fi + \else + \ifdim\pgf@xx>0pt % + \def\pgfplots@scale{-1}% + \fi + \fi + \pgfmathmultiply@{\pgfplots@scale}{\pgfplots@view@dir@threedim@x}% + \let\pgfplots@view@dir@threedim@x\pgfmathresult + \pgfmathmultiply@{\pgfplots@scale}{\pgfplots@view@dir@threedim@y}% + \let\pgfplots@view@dir@threedim@y\pgfmathresult + \pgfmathmultiply@{\pgfplots@scale}{\pgfplots@view@dir@threedim@z}% + \let\pgfplots@view@dir@threedim@z\pgfmathresult + % + \edef\pgfplots@view@dir@threedim{\pgfplots@view@dir@threedim@x,\pgfplots@view@dir@threedim@y,\pgfplots@view@dir@threedim@z}% + \else + % Ah - we already caught that special case above. + \fi + \fi + \fi + % + % NOTE : the case e_xx = e_yx = 0 IS NO USE-CASE (would + % require a rotated z axis which is forbidden currently) + % + \ifx\pgfplots@view@dir@threedim\pgfutil@empty + \def\pgfplots@view@dir@threedim@z{-1}% hold it at some arbitrary value + \pgf@xa=-\pgfplots@view@dir@threedim@z\pgf@zx + \pgf@ya=-\pgfplots@view@dir@threedim@z\pgf@zy + \edef\pgfplots@loc@TMPa{% + {% + {\pgf@sys@tonumber\pgf@xx}{\pgf@sys@tonumber\pgf@yx}% + {\pgf@sys@tonumber\pgf@xy}{\pgf@sys@tonumber\pgf@yy}% + }% + {% + {\pgf@sys@tonumber\pgf@xa}{\pgf@sys@tonumber\pgf@ya}% + }% + }% + \expandafter\pgfutilsolvetwotwoleq\pgfplots@loc@TMPa + \def\pgfplots@loc@TMPb##1##2{% + \def\pgfplots@view@dir@threedim@x{##1}% + \def\pgfplots@view@dir@threedim@y{##2}% + }% + \expandafter\pgfplots@loc@TMPb\pgfmathresult + % + % Identify if we need to switch the sign. + % To verify that these cases are useful, I suggest visualizing + % that stuff using the TeX code from above... + % + % I guess it is correct up to collapsing views (as you see, I + % did not properly identify the cases with "=0" ) + \def\pgfplots@scale{1}% + \ifdim\pgf@xx>0pt + \ifdim\pgf@yx<0pt + \else + % + \ifdim\pgf@xy<0pt + \else + \ifdim\pgf@yy<0pt + \def\pgfplots@scale{-1}% + \fi + \fi + % + \fi + \else + \ifdim\pgf@xx<0pt + \ifdim\pgf@yx>0pt + \else + % + \ifdim\pgf@xy>0pt + \else + \ifdim\pgf@yy>0pt + \def\pgfplots@scale{-1}% + \fi + \fi + % + \fi + \fi + \fi + \ifdim\pgf@xy>0pt + \ifdim\pgf@yy<0pt + \else + % + \ifdim\pgf@xx>0pt + \else + \ifdim\pgf@yx>0pt + \def\pgfplots@scale{-1}% + \fi + \fi + % + \fi + \else + \ifdim\pgf@xy<0pt + \ifdim\pgf@yy>0pt + \else + % + \ifdim\pgf@xx<0pt + \else + \ifdim\pgf@yx<0pt + \def\pgfplots@scale{-1}% + \fi + \fi + % + \fi + \fi + \fi + \pgfmathmultiply@{\pgfplots@scale}{\pgfplots@view@dir@threedim@x}% + \let\pgfplots@view@dir@threedim@x\pgfmathresult + \pgfmathmultiply@{\pgfplots@scale}{\pgfplots@view@dir@threedim@y}% + \let\pgfplots@view@dir@threedim@y\pgfmathresult + \pgfmathmultiply@{\pgfplots@scale}{\pgfplots@view@dir@threedim@z}% + \let\pgfplots@view@dir@threedim@z\pgfmathresult + % + \pgfplotsmathvectorfromstring{\pgfplots@view@dir@threedim@x,\pgfplots@view@dir@threedim@y,\pgfplots@view@dir@threedim@z}{default}% + \let\pgfplots@view@dir@threedim=\pgfplotsretval + % normalize. This is not absolutely required -- but it is used + % to accumulate point depth (for the mesh handler) in pgfmath + % arithmetics. At least \pgfplotsmathviewdepthxyz should use + % a properly scaled view dir. + \pgfplotsmathvectorlength{\pgfplotsretval}{default}% + \pgfplotscoordmath{default}{op}{reciprocal}{{\pgfplotsretval}}% + \pgfplotsmathvectorscale{\pgfplots@view@dir@threedim}{\pgfmathresult}{default}% + \else + \pgfplotsmathvectorfromstring{\pgfplots@view@dir@threedim}{default}% + \fi + % + \pgfmath@smuggleone\pgfplotsretval + \endgroup + \let\pgfplots@view@dir@threedim=\pgfplotsretval + \else + \def\pgfplots@loc@TMPb##1##2##3{% + \pgfplotsmathvectorfromstring{##1,##2,##3}{default}% + \let\pgfplots@view@dir@threedim=\pgfplotsretval + }% + \expandafter\pgfplots@loc@TMPb\pgfplots@loc@TMPc + \fi +%\message{\string\pgfplotsgetnormalforcurrentview: got (\pgfplots@view@dir@threedim)^^J}% +}% + +% PRECONDITION: +% none +% POSTCONDITION: +% \pgfplots@default@aspect@ratio is set. +\def\pgfplots@compute@default@aspect@ratio{% + \expandafter\pgfmath@x\axisdefaultwidth + \expandafter\pgfmath@y\axisdefaultheight + \pgfmathlog@invoke@expanded\pgfmathdivide@{% + {\pgf@sys@tonumber{\pgfmath@x}}% + {\pgf@sys@tonumber{\pgfmath@y}}% + }% + \let\pgfplots@default@aspect@ratio=\pgfmathresult +} + +\def\pgfplots@ifneeds@one@uniform@datascale#1#2{% + \if3\pgfplots@scale@mode@choice + % scale mode=scale uniformly + \def\pgfplots@loc@TMPa{1}% + % + % if we have at least one unit vector given explicitly, the + % meaning changes: in that case, we can (and probably should) + % use different data scale factors in each direction. + \ifx\pgfplots@x\pgfutil@empty + \else + \def\pgfplots@loc@TMPa{0}% + \fi + \ifx\pgfplots@y\pgfutil@empty + \else + \def\pgfplots@loc@TMPa{0}% + \fi + \ifx\pgfplots@z\pgfutil@empty + \else + \def\pgfplots@loc@TMPa{0}% + \fi + \else + \def\pgfplots@loc@TMPa{0}% + \fi + \if1\pgfplots@loc@TMPa + #1% + \else + #2% + \fi +}% + +\def\pgfplots@set@default@size@options{% + % 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. + % + \let\pgfplots@default@aspect@ratio=\pgfutil@empty + \pgfkeysgetvalue{/pgfplots/x}{\pgfplots@x}% + \pgfkeysgetvalue{/pgfplots/y}{\pgfplots@y}% + \pgfkeysgetvalue{/pgfplots/z}{\pgfplots@z}% + %\pgfkeysgetvalue{/pgfplots/viewdir}{\pgfplots@viewdir}% + \pgfkeysgetvalue{/pgfplots/width}{\pgfplots@width}% + \pgfkeysgetvalue{/pgfplots/height}{\pgfplots@height}% + \ifx\pgfplots@width\pgfutil@empty + \def\pgfplots@user@provided@width{0}% + \else + \def\pgfplots@user@provided@width{1}% + \pgfmathparse{\pgfplots@width}% + \edef\pgfplots@width{\pgfmathresult pt}% + \fi + \ifx\pgfplots@height\pgfutil@empty + \def\pgfplots@user@provided@height{0}% + \else + \def\pgfplots@user@provided@height{1}% + \pgfmathparse{\pgfplots@height}% + \edef\pgfplots@height{\pgfmathresult pt}% + \fi + % + % CASES: + % W := 'width' option non-empty + % H := 'height' option non-empty + % + % W H + % 0 0 -> \axisdefaultwidth + % 0 1 -> determine width out of H and the default aspect ratio + % 1 X -> ok, use the user parameter. + % -> KEEP ASPECT RATIO if just one W, or H is given! + \ifx\pgfplots@width\pgfutil@empty + \ifx\pgfplots@height\pgfutil@empty + % The case W=0 H=0: + \let\pgfplots@width=\axisdefaultwidth + \let\pgfplots@height=\axisdefaultheight + \else + % The case W=0 H=1: + \pgfplots@compute@default@aspect@ratio + \expandafter\pgfmath@y\pgfplots@height + \pgfmathlog@invoke@expanded\pgfmathmultiply@{% + {\pgf@sys@tonumber{\pgfmath@y}}% + {\pgfplots@default@aspect@ratio}% + }% + \edef\pgfplots@width{\pgfmathresult pt}% + \fi + \else + \ifx\pgfplots@height\pgfutil@empty + % The case W=1 H=0: + \pgfplots@compute@default@aspect@ratio + \expandafter\pgfmath@x\pgfplots@width + \pgfmathlog@invoke@expanded\pgfmathdivide@{% + {\pgf@sys@tonumber{\pgfmath@x}}% + {\pgfplots@default@aspect@ratio}% + }% + \edef\pgfplots@height{\pgfmathresult pt}% + \else + % The case W=1 H=1: + \fi + \fi + \pgfkeyslet{/pgfplots/width}{\pgfplots@width}% + \pgfkeyslet{/pgfplots/height}{\pgfplots@height}% + % + \ifpgfplots@threedim + \pgfplots@set@default@size@options@threedim + \fi + % + \pgfplots@set@scale@mode +} + +% This method must be called BEFORE THE DATASCALING is initialized. +\def\pgfplots@set@scale@mode{% + \pgfkeysgetvalue{/pgfplots/unit vector ratio}\pgfplots@loc@TMPb + \ifx\pgfplots@loc@TMPb\pgfutil@empty + \else + \ifcase\pgfplots@scale@mode@choice + % 'scale mode'=auto + \def\pgfplots@scale@mode@choice{3}% set to 'scale uniformly' + % + \if1\pgfplots@compat@scale@mode@compatible@mode + % backwards compatibility mode... + \ifpgfplots@threedim + % ... for 3d: there is no backwards compatibility + % mode here; it was plain wrong for 3d axes: + % neither lengths nor angles have been correct. + \pgfplots@compat@scale@mode@compatible@mode@warning + \fi + \fi + \or + % scale mode=none: keep it this way. + \immediate\write-1{PGFPlots: scale mode=none and unit vector ratio is incompatible. Ignoring unit vector ratio.^^J}% + \or + % scale mode=stretch to fill + \immediate\write-1{PGFPlots: scale mode=stretch to fill and unit vector ratio might produce unexpected results. Consider using scale mode=auto^^J}% + \fi + \fi + % +} + +\def\pgfplots@compat@scale@mode@compatible@mode@warning{% + \pgfplots@warning{The content of your 3d axis has CHANGED compared to previous versions of pgfplots. Please review it. ^^J % + [continued] Explanation: you have a 3d axis with 'axis equal' and/or 'unit vector ratio' which has (probably) been optimized for an older version of pgfplots. Any version older than 1.6 produced wrong output.^^J % + [continued] To remove this warning, write \string\pgfplotsset{compat=1.6} (or newer) in your preamble (may change all figures in your document) or by adding that to the affected axis.}% +}% + +\def\pgfplots@set@default@size@options@threedim{% + \pgfplots@loc@tmpfalse + \ifx\pgfplots@x\pgfutil@empty + \else + \pgfplots@loc@tmptrue + \fi + \ifx\pgfplots@y\pgfutil@empty + \else + \pgfplots@loc@tmptrue + \fi + \ifx\pgfplots@z\pgfutil@empty + \else + \pgfplots@loc@tmptrue + \fi + \ifpgfplots@loc@tmp + % oh - we have at least one of the [xyz] unit vectors! + % make sure all of them are there + \ifx\pgfplots@x\pgfutil@empty + \pgfplots@set@default@size@options@threedim@{x}{(1pt,0pt)}% + \fi + \ifx\pgfplots@y\pgfutil@empty + \pgfplots@set@default@size@options@threedim@{y}{(0pt,1pt)}% + \fi + \ifx\pgfplots@z\pgfutil@empty + \pgfplots@set@default@size@options@threedim@{z}{(0pt,1pt)}% + \fi + \pgfkeyslet{/pgfplots/view/az}\pgfutil@empty + \pgfkeyslet{/pgfplots/view/el}\pgfutil@empty + \fi +} +\def\pgfplots@set@default@size@options@threedim@#1#2{% + \pgfplots@error{Sorry, a 3D axis needs either NONE or ALL of "x,y,z". I found partial information, but (at least) '#1' is lacking... please add '#1'}% + \expandafter\def\csname pgfplots@#1\endcsname{#2}% +} + +% A helper method for \pgfplots@initsizes which +% - applies the data scaling trafo to user arguments +% - sets calls pgfset#1vec +% +% #1: the vector to set (either 'x' or 'y') +% #2: the index of the vector to set (either 0 or 1) +% #3: the already precomputed temporary scale (see pgfplots@initsizes) +% #4: an output argument. It is a macro name which will be defined to +% '1' if and only if the finally set vector is parallel to the #1 axis +% of PGF, that means (x,0) for #1=x and (0,y) for #2=y. +\def\pgfplots@initsizes@setunitvector#1#2#3#4{% + \pgfkeysgetvalue{/pgfplots/#1 dir/value}\pgfplots@loc@dirvalue + \expandafter\let\expandafter\pgfplots@loc@TMPb\csname pgfplots@#1\endcsname + \ifx\pgfplots@loc@TMPb\pgfutil@empty + \def#4{1}% we have (#1,0) or (0,#1) + % +%\message{Setting unitvector(#1) to auto-computed multiple of e_#2 ...}% + \edef\pgfplots@loc@TMPa{#3}% + \if r\pgfplots@loc@dirvalue + \edef\pgfplots@loc@TMPa{-#3}% + \fi + \ifcase#2\relax + \pgfsetxvec{\pgfqpoint{\pgfplots@loc@TMPa pt}{0pt}}% + \or + \pgfsetyvec{\pgfqpoint{0pt}{\pgfplots@loc@TMPa pt}}% + \or + \pgfsetzvec{\pgfqpoint{\pgfplots@loc@TMPa pt}{\pgfplots@loc@TMPa pt}}% + \fi + \else + % Ok, we have a user-defined unit vector. + % + % That means we also need to apply the scaling trafo! + % + % 1. Check whether we have a complete vector of type (x,y): + \expandafter\pgfutil@in@\expandafter(\expandafter{\pgfplots@loc@TMPb}% + \ifpgfutil@in@ + % YES: we have (x,y): + % + \def#4{0}% we DON'T have (#1,0) or (0,#1). At least I think so. + % +%\message{Setting unitvector(#1) to non-standard \csname pgfplots@#1\endcsname ...}% + \def\pgfplots@loc@TMPa(##1,##2){% + \pgfplotscoordmath{default}{parse}{##1}% + \pgfplotscoordmath{default}{tofixed}{\pgfmathresult}% + \let\pgfplots@loc@TMPb=\pgfmathresult + \pgfplotscoordmath{default}{parse}{##2}% + \pgfplotscoordmath{default}{tofixed}{\pgfmathresult}% + \let\pgfplots@loc@TMPc=\pgfmathresult + % + \pgfplots@if{pgfplots@apply@datatrafo@#1}{% + \pgfplotscoordmath{#1}{datascaletrafo noshift inverse to fixed}{\pgfplots@loc@TMPb}% + \let\pgfplots@loc@TMPb=\pgfmathresult + \pgfplotscoordmath{#1}{datascaletrafo noshift inverse to fixed}{\pgfplots@loc@TMPc}% + \let\pgfplots@loc@TMPc=\pgfmathresult + }{}% + \csname pgfset#1vec\endcsname{% + \pgfqpoint + {\if r\pgfplots@loc@dirvalue -\fi\pgfplots@loc@TMPb pt} + {\if r\pgfplots@loc@dirvalue -\fi\pgfplots@loc@TMPc pt}}% + }% + \expandafter\pgfplots@loc@TMPa\pgfplots@loc@TMPb% + % + \else + % NO we simply have a scalar value. + \def#4{1}% we have (#1,0) or (0,#1) +%\message{Setting unitvector(#1) to \csname pgfplots@#1\endcsname * e_{#2}...}% + \pgfplots@if{pgfplots@apply@datatrafo@#1}{% + \pgfplotscoordmath{default}{parse}{\csname pgfplots@#1\endcsname}% + \pgfplotscoordmath{default}{tofixed}{\pgfmathresult}% + \pgfplotscoordmath{#1}{datascaletrafo noshift inverse to fixed}{\pgfmathresult}% + \edef\pgfplots@loc@TMPb{\pgfmathresult pt}% + }{\relax}% + \edef\pgfplots@loc@TMPb{\if r\pgfplots@loc@dirvalue -\fi\pgfplots@loc@TMPb}% + \begingroup + \pgf@xa=\pgfplots@loc@TMPb\relax + \xdef\pgfplots@glob@TMPb{\pgf@sys@tonumber{\pgf@xa}}% + \endgroup + \ifcase#2\relax + \pgfsetxvec{\pgfqpoint{\pgfplots@loc@TMPb}{0pt}}% + \or + \pgfsetyvec{\pgfqpoint{0pt}{\pgfplots@loc@TMPb}}% + \or + \pgfsetzvec{\pgfqpoint{\pgfplots@loc@TMPb}{\pgfplots@loc@TMPb}}% + \fi + \fi + \fi +%\message{-> got unitvector(#1) = (\the\csname pgf@#1x\endcsname, \the\csname pgf@#1y\endcsname).^^J}% +}% + +% Applies the 'axis equal' feature. +% +% PRECONDITION: +% - #1, #2, #3 contains the current scaling +% factors in x,y, z, resp. which are to be applied to unit vectors +% - neither unit vectors nor limits are in their final shape +% - \pgfplots@set@default@size@options has been invoked before +% +% POSTCONDITION: +% - #1, #2, #3 have been changed to accomodate unit vector ratio +% - #4, #5, #6 [output] contain axis limit compensation scales +% +% There is just one algorithmic difficulty: the data scaling +% transformation. All unit vector length above are only meaningful in +% the UNTRANSFORMED range, so we have to mingle with the scaling +% transformation. +\def\pgfplots@apply@unit@ratio#1#2#3#4#5#6{% + \begingroup + \edef\pgfplots@target@unit@scale@inv@x{#1}% + \edef\pgfplots@target@unit@scale@inv@y{#2}% + \edef\pgfplots@target@unit@scale@inv@z{#3}% + \def\pgfplots@target@limitrescale@x@{1}% + \def\pgfplots@target@limitrescale@y@{1}% + \def\pgfplots@target@limitrescale@z@{1}% + % + \pgfkeysgetvalue{/pgfplots/unit vector ratio}\pgfplots@unit@vector@ratio + \ifx\pgfplots@unit@vector@ratio\pgfutil@empty + \else + \edef\pgfplots@unit@vector@ratio{\pgfplots@unit@vector@ratio\space1 1 }% + % + \expandafter\pgfplots@unit@vector@ratio@check@nop\pgfplots@unit@vector@ratio\pgfplots@EOI + \ifpgfplots@loc@tmp + % + % Step 1: compute the unit vector which STAYS CONSTANT. + % + \pgfkeysgetvalue{/pgfplots/unit vector ratio axis}\pgfplots@apply@unit@ratio@reference + \ifx\pgfplots@apply@unit@ratio@reference\pgfutil@empty + \pgfplots@apply@unit@ratio@find@reference% + \fi + % + % FIXME : I could spent some attention here to save work: + % both, unit ratios and the resulting scales are computed at + % least twice (once in \pgfplots@apply@unit@ratio@find@reference and once in the + % following). + \expandafter\pgfplots@apply@unit@ratio@prepareratios\pgfplots@unit@vector@ratio\pgfplots@EOI + % +%\message{USING REFERENCE UNIT VECTOR FROM \pgfplots@apply@unit@ratio@reference; ratio \pgfplots@unit@ratio@x\space \pgfplots@unit@ratio@y\space \pgfplots@unit@ratio@z.^^J}% + % + % Step 2: apply the scaling: + \pgfplots@rescale@unit@vector@reltoreference{x}{\pgfplots@unit@ratio@x}% + \pgfplots@rescale@unit@vector@reltoreference{y}{\pgfplots@unit@ratio@y}% + \ifpgfplots@threedim + \pgfplots@rescale@unit@vector@reltoreference{z}{\pgfplots@unit@ratio@z}% + \fi + % + \else +%\message{Skipped application of 'unit vector ratio=\pgfkeysvalueof{/pgfplots/unit vector ratio}': it is already done by 'scale uniformly'.^^J}% + \fi + \fi + \xdef\pgfplots@glob@TMPa{% + \noexpand\def\noexpand#1{\pgfplots@target@unit@scale@inv@x}% + \noexpand\def\noexpand#2{\pgfplots@target@unit@scale@inv@y}% + \noexpand\def\noexpand#3{\pgfplots@target@unit@scale@inv@z}% + \noexpand\def\noexpand#4{\pgfplots@target@limitrescale@x@}% + \noexpand\def\noexpand#5{\pgfplots@target@limitrescale@y@}% + \noexpand\def\noexpand#6{\pgfplots@target@limitrescale@z@}% + }% + \endgroup + \pgfplots@glob@TMPa +}% + +\def\pgfplots@appy@unit@ratio@reciprocal#1{% + \pgfplotscoordmath{default}{parsenumber}{#1}% + \pgfplotscoordmath{default}{op}{reciprocal}{{\pgfmathresult}}% + \pgfplotscoordmath{default}{tofixed}{\pgfmathresult}% +}% + +% Defines \ifpgfplots@loc@tmp := need to modify scaling factors +\def\pgfplots@unit@vector@ratio@check@nop#1 #2 #3 #4\pgfplots@EOI{% + \pgfplots@loc@tmptrue + \if3\pgfplots@scale@mode@choice + % scale mode=scale uniformly + \ifpgfplots@threedim + \ifdim#1pt=#2pt + \ifdim#1pt=#3pt + % 'axis equal' is implicitly done by 'scale mode=scale + % uniformly' anyway + \pgfplots@loc@tmpfalse + \fi + \fi + \else + \ifdim#1pt=#2pt + % 'axis equal' is implicitly done by 'scale mode=scale + % uniformly' anyway + \pgfplots@loc@tmpfalse + \fi + \fi + \fi + % activate the following line to deactivate optimization: [FIXME] + %\pgfplots@loc@tmpfalse +}% + +% This macro determines the reference axis for unit vector rescaling. +% The reference axis remains unscaled (it gets scaling factor 1 if you +% want it this way). +% +% The other axes are scaled such that the desired unit vector ratios +% are fulfilled. +% +% The idea to select a reference axis is as follows: +% 1. Every unit vector scaling factor s should fulfill s <= 1. +% 2. Choose the reference axis such that the minimal amount of scaling +% is performed. +% +% The motivation for (1) is: if all involved scaling factors are at +% most 1, the resulting picture will only become *smaller*. +% Consequently, we can simply enlarge axis limits to restore the +% original width/height! +% +% The motivation for (2) is: a huge amount of scaling might reduce the +% size of the image too much. Of course, the figure will be enlarged +% to fit the original width/height, but most of it will be empty. So, +% use the smallest scaling. +% +% @POSTCONDITION The reference axis is stored in +% \pgfplots@apply@unit@ratio@reference . +% +% @see the key 'unit vector ratio axis=y' which allows to manually +% select the reference axis. This will illustrate what happens here. +\def\pgfplots@apply@unit@ratio@find@reference{% + % + \begingroup + \let\pgfplots@ONE=\pgf@x + \global\pgfplots@ONE=1.002pt + % + \def\pgfplots@optimum@sofar@axis{}% + \let\pgfplots@optimum@sofar@value=\pgf@y + \global\pgfplots@optimum@sofar@value=16000pt + % + %\pgfplots@apply@unit@ratio@find@reference@checkexplicitlimits + % + \ifx\pgfplots@optimum@sofar@axis\pgfutil@empty + % set \pgfplots@loc@TMPa := 1 if and only if the axis is 3d + \def\pgfplots@loc@TMPa{0}% + \if0\b@pgfplots@unitvec@is@zero@z + % ah, it IS 3d! + \def\pgfplots@loc@TMPa{1}% + \else + % ok, 2d mode (includes view={0}{90}) + \def\pgfplots@loc@TMPa{0}% + \fi + \if1\pgfplots@loc@TMPa + % 3D is more complicated than 2D: + % for every fixed reference axis, we have to check *two* + % scaling factors. + % + % Furthermore, the optimality condition (2) needs to be + % performed on the maximum max{1-s_a, 1-s_b} provided both of + % these numbers are positive. + % + \def\pgfplots@check@##1##2{% + % PRECONDITION: \pgfplots@apply@unit@ratio@reference is defined. + % + % renormalize \pgfplots@unit@[xyz] : + \expandafter\pgfplots@apply@unit@ratio@prepareratios\pgfplots@unit@vector@ratio\pgfplots@EOI + % + % compute s_a : + \pgfplots@getscale@unit@vector@reltoreference ##1{\csname pgfplots@unit@ratio@##1\endcsname}% + \let\pgfplots@scale@a=\pgfmathresult + % + % compute s_b : + \pgfplots@getscale@unit@vector@reltoreference ##2{\csname pgfplots@unit@ratio@##2\endcsname}% + \let\pgfplots@scale@b=\pgfmathresult + % + % check if the actual choice of + % \pgfplots@apply@unit@ratio@reference is FEASIBLE. + % That is the case if s_a <= 1 && s_b <= 1. + % We check + % (1 - s_a >= 0 ) && ( 1 - s_b >= 0 ) + % instead, since I need the value + % max( 1-s_a, 1-s_b ) + % anyway. + \def\pgfplots@ref@is@feasible{1}% + \pgf@xa=\pgfplots@ONE \advance\pgf@xa by-\pgfplots@scale@a pt + \ifdim\pgf@xa<0sp + \def\pgfplots@ref@is@feasible{0}% + \else + \pgf@xb=\pgfplots@ONE \advance\pgf@xb by-\pgfplots@scale@b pt + \ifdim\pgf@xb<0sp + \def\pgfplots@ref@is@feasible{0}% + \fi + \fi + % compute max(1-s_a,1-s_b) into \pgf@xa: + % pgf@xa= max(pgf@xa,pgf@xb): + \ifdim\pgf@xb>\pgf@xa \pgf@xa=\pgf@xb \fi + \if1\pgfplots@ref@is@feasible + \ifdim\pgf@xa<\pgfplots@optimum@sofar@value + % Ah, ok. The actual choice is BETTER as it + % involves less scaling. + % + % Remember it! + \let\pgfplots@optimum@sofar@axis=\pgfplots@apply@unit@ratio@reference + \global\pgfplots@optimum@sofar@value=\pgf@xa + \fi + \fi +%\message{^^Junit vector ratio 3D searching reference: checking \pgfplots@apply@unit@ratio@reference. feasable=\pgfplots@ref@is@feasible. \if1\pgfplots@ref@is@feasible max=\the\pgf@xa. \fi Optimum so far: value =\the\pgfplots@optimum@sofar@value\space for axis \pgfplots@optimum@sofar@axis.^^J}% + }% + % + % Check 'x' as reference : + \def\pgfplots@apply@unit@ratio@reference{x}% + \pgfplots@check@ yz% + % + % Check 'y' as reference : + \def\pgfplots@apply@unit@ratio@reference{y}% + \pgfplots@check@ xz% + % + % Check 'z' as reference : + \def\pgfplots@apply@unit@ratio@reference{z}% + \pgfplots@check@ xy% + % + \else + % 2D is much simpler: find the scale s which fulfills s <= 1. + % One of them MUST fulfill it. + % + % try 'x' axis as reference: + \def\pgfplots@apply@unit@ratio@reference{x}% + % + % renormalize: + \expandafter\pgfplots@apply@unit@ratio@prepareratios\pgfplots@unit@vector@ratio\pgfplots@EOI + % + % compute scaling factor: + \pgfplots@getscale@unit@vector@reltoreference y\pgfplots@unit@ratio@y% + % +%\message{^^Junit vector ratio 2D searching reference: checking \pgfplots@apply@unit@ratio@reference. feasable=\pgfmathresult < 1: \ifdim\pgfmathresult pt <\pgfplots@ONE YES-> use x\else NO->use y\fi^^J}% + % and check (1). The condition (2) is irrelevant; it is met + % anyway. + \ifdim\pgfmathresult pt<\pgfplots@ONE + \def\pgfplots@optimum@sofar@axis{x}% + \else + \def\pgfplots@optimum@sofar@axis{y}% + \fi + \fi + \else +%\message{^^Junit vector ratio chose \pgfplots@optimum@sofar@axis\space to fulfill explicitly provided limits (at least partially).^^J}% + \fi + % + \ifx\pgfplots@optimum@sofar@axis\pgfutil@empty + \if1\b@pgfplots@unitvec@is@zero@z + \def\pgfplots@optimum@sofar@axis{y}% + \else + \def\pgfplots@optimum@sofar@axis{z}% + \fi + \pgfplots@warning{The algorithm to implement 'unit vector ratio' failed! It could not determine the axis which shall be scaled and decided to use 'unit vector ratio axis=\pgfplots@optimum@sofar@axis'.}% + \fi + \let\pgfplots@apply@unit@ratio@reference=\pgfplots@optimum@sofar@axis + \pgfmath@smuggleone\pgfplots@apply@unit@ratio@reference + \endgroup +}% +\def\pgfplots@apply@unit@ratio@find@reference@checkexplicitlimits{% + \ifpgfplots@autocompute@ymax \else \def\pgfplots@optimum@sofar@axis{y}\fi + \ifpgfplots@autocompute@ymin \else \def\pgfplots@optimum@sofar@axis{y}\fi + \ifpgfplots@autocompute@xmax \else \def\pgfplots@optimum@sofar@axis{x}\fi + \ifpgfplots@autocompute@xmin \else \def\pgfplots@optimum@sofar@axis{x}\fi + \ifpgfplots@threedim + \ifpgfplots@autocompute@zmax \else \def\pgfplots@optimum@sofar@axis{z}\fi + \ifpgfplots@autocompute@zmin \else \def\pgfplots@optimum@sofar@axis{z}\fi + \fi +}% + +% This is ONLY applied to the value of 'unit vector ratio'. It does +% not touch the current axis scaling factors. +\def\pgfplots@apply@unit@ratio@prepareratios#1 #2 #3 #4\pgfplots@EOI{% + \def\pgfplots@unit@ratio@x{#1}% + \def\pgfplots@unit@ratio@y{#2}% + \def\pgfplots@unit@ratio@z{#3}% + % + % 'unit vector ratio' is measured relative to the y axis for 2d + % and relative to the z axis for 3d plots. + % renormalize such that it is relative to + % \pgfplots@apply@unit@ratio@reference. + % + % Furthermore, renormalize such that + % unit@ratio@\pgfplots@apply@unit@ratio@reference is 1. + \pgfmathreciprocal@{\csname pgfplots@unit@ratio@\pgfplots@apply@unit@ratio@reference\endcsname}% + \let\pgfplots@loc@TMPa=\pgfmathresult + \ifpgfplots@threedim + \if z\pgfplots@apply@unit@ratio@reference + \else + \pgfmathmultiply@{\pgfplots@loc@TMPa}{\pgfplots@unit@ratio@z}% + \let\pgfplots@loc@TMPa=\pgfmathresult + \fi + % + \pgfmathmultiply@{\pgfplots@loc@TMPa}{\pgfplots@unit@ratio@x}% + \let\pgfplots@unit@ratio@x=\pgfmathresult + % + \pgfmathmultiply@{\pgfplots@loc@TMPa}{\pgfplots@unit@ratio@y}% + \let\pgfplots@unit@ratio@y=\pgfmathresult + % + \pgfmathmultiply@{\pgfplots@loc@TMPa}{\pgfplots@unit@ratio@z}% + \let\pgfplots@unit@ratio@z=\pgfmathresult + \else + \if y\pgfplots@apply@unit@ratio@reference + \else + \pgfmathmultiply@{\pgfplots@loc@TMPa}{\pgfplots@unit@ratio@y}% + \let\pgfplots@loc@TMPa=\pgfmathresult + \fi + % + \pgfmathmultiply@{\pgfplots@loc@TMPa}{\pgfplots@unit@ratio@x}% + \let\pgfplots@unit@ratio@x=\pgfmathresult + % + \pgfmathmultiply@{\pgfplots@loc@TMPa}{\pgfplots@unit@ratio@y}% + \let\pgfplots@unit@ratio@y=\pgfmathresult + % + \def\pgfplots@unit@ratio@z{<unused>}% + \fi + % +}% + + +% Computes a new unit vector E_#1 for direction #1 such that +% ||E_#1|| = #2 * ||e_reference||. +% Here, #2 is a scaling factor and e_reference is a reference axis. +% The reference axis is stored in +% \pgfplots@apply@unit@ratio@reference, the macro contains one of +% {x,y,z}. +% +% The data limits for '#1' will be enlarged as well (for 'unit rescale +% keep size'). +% +% #1 is the axis which should be scaled (i.e. #1 in {x,y,z}). +% It is allowed if #1 = \pgfplots@apply@unit@ratio@reference. In this +% case, you can provide a scale '#2' to rescale the axis. +% +% #2 is a desired scale, relative to +% \pgfplots@apply@unit@ratio@reference. #2 should be a number without +% unit. +% +% The parameter \pgfplots@apply@unit@ratio@reference is also one of +% {x,y,z}. +% +\def\pgfplots@rescale@unit@vector@reltoreference#1#2{% + \def\pgfplots@loc@TMPa{0}% + \if#1\pgfplots@apply@unit@ratio@reference + \pgfplotsmath@ifapproxequal@dim{#2pt}{1pt}{0.0002pt}{% + }{% + \def\pgfplots@loc@TMPa{1}% + }% + \else + \def\pgfplots@loc@TMPa{1}% + \fi + \if1\csname b@pgfplots@unitvec@is@zero@#1\endcsname + \def\pgfplots@loc@TMPa{0}% + \fi + \if1\pgfplots@loc@TMPa + % + \pgfplots@getscale@unit@vector@reltoreference{#1}{#2}% + \global\let\pgfplots@glob@TMPa=\pgfmathresult + % +%\message{Rescaling '#1' by \pgfplots@glob@TMPa.^^J}% + % + \pgfmathdivide@{\csname pgfplots@target@unit@scale@inv@#1\endcsname}{\pgfplots@glob@TMPa}% + \expandafter\let\csname pgfplots@target@unit@scale@inv@#1\endcsname=\pgfmathresult + % + \pgfmathreciprocal@\pgfplots@glob@TMPa + \expandafter\let\csname pgfplots@target@limitrescale@#1@\endcsname=\pgfmathresult + % + \fi +} + +% Updates the #1 axis limits such that the axis' dimensions +% stay the same after scaling the #1 unit vector by a scale 's'. +% +% PRECONDITION: +% - the #1 unit vector has been rescaled by a factor s. +% For example, e_xnew := e_x * 0.5 . +% +% POSTCONDITION: +% - the axis limits are enlarged by a factor 1/s such that +% 1/s (#1max - #1min) * e_xnew = (#1max- #1min) * e_x. +% +% In other words, the unit vector rescale is componensated by +% modifying the axis limits: we want to add an absolute component 'd' +% to the range: +% 1/s (xmax - xmin ) = xmax - xmin +d +% => +% d = (1/s - 1) * (xmax - xmin) +% +% The only remaining thing to do is to distribute 'd' to 'xmax' and +% 'xmin'. Typically, 50% to each will be fine, I guess... +% +% #1: either x, y or z. It denotes the direction which has been +% modified. +% #2: the INVERSE of the scaling factor, #2 = 1/s . +% +\def\pgfplots@apply@unit@vector@rescale@keep@size#1#2{% + \ifdim#2pt=1pt + \else + \if0\pgfplots@unit@vector@rescale@keep@size + % unit rescale keep size=false : do nothing. Ignore the + % scaling request. + \else + % unit rescale keep size=true|unless limits declared + % +%\message{'unit rescale keep size': Resizing data range for #1 by #2: from \csname pgfplots@#1min\endcsname:\csname pgfplots@#1max\endcsname\ to}% + \pgfmathsubtract@{\csname pgfplots@#1max\endcsname}{\csname pgfplots@#1min\endcsname}% + \begingroup + \pgf@xa=\pgfmathresult pt + \pgfmathsubtract@{#2}{1.0}% + \pgf@xa=\pgfmathresult \pgf@xa% this is 'd' + % + % \pgfplots@glob@TMPb : will be subtracted from #1min + % \pgfplots@glob@TMPc : will be added to #1max + \pgfplots@if{pgfplots@autocompute@#1min}{% + \pgfplots@if{pgfplots@autocompute@#1max}{% + \pgf@xa=0.5 \pgf@xa + \xdef\pgfplots@glob@TMPb{\pgf@sys@tonumber{\pgf@xa}}% + \xdef\pgfplots@glob@TMPc{\pgfplots@glob@TMPb}% + }{% + \xdef\pgfplots@glob@TMPb{\pgf@sys@tonumber{\pgf@xa}}% + \xdef\pgfplots@glob@TMPc{0.0}% + }% + }{% + \pgfplots@if{pgfplots@autocompute@#1max}{% + \xdef\pgfplots@glob@TMPb{0.0}% + \xdef\pgfplots@glob@TMPc{\pgf@sys@tonumber{\pgf@xa}}% + }{% + \if1\pgfplots@unit@vector@rescale@keep@size + % unit rescale keep size=true : FORCE + % enlargement! + \pgf@xa=0.5 \pgf@xa + \xdef\pgfplots@glob@TMPb{\pgf@sys@tonumber{\pgf@xa}}% + \xdef\pgfplots@glob@TMPc{\pgfplots@glob@TMPb}% + \else + % unit rescale keep size=unless limits declared: + % do not scale - all limits are declared + % explicitly + \xdef\pgfplots@glob@TMPb{0.0}% + \xdef\pgfplots@glob@TMPc{0.0}% + \fi + }% + }% + \endgroup + \pgfmathsubtract@{\csname pgfplots@#1min\endcsname}{\pgfplots@glob@TMPb}% + \expandafter\global\expandafter\let\csname pgfplots@#1min\endcsname=\pgfmathresult + \pgfmathadd@{\csname pgfplots@#1max\endcsname}{\pgfplots@glob@TMPc}% + \expandafter\global\expandafter\let\csname pgfplots@#1max\endcsname=\pgfmathresult +%\message{\csname pgfplots@#1min\endcsname:\csname pgfplots@#1max\endcsname. [- \pgfplots@glob@TMPb; + \pgfplots@glob@TMPc]^^J}% + % + % Update auxiliary data members: + \pgfplots@visphase@notify@changeofcanvaslimits{#1}% + \fi + \fi +}% + +% #1: an axis which should be scaled +% #2: the desired final ratio ||e_#1||/||e_ref|| +\def\pgfplots@getscale@unit@vector@reltoreference#1#2{% + % + % If the datascaling transformation is active (which is almost + % everytime the case here), we have a transformation + % T^{-1}(x)= 10^scale * x + % with different scales for every axis. + % + % If the datascaling transformation is NOT active, scale is 0 + % and T^{-1} = Identity. + % + % Note that the datascaling transformation also has + % translations (shifts). These are not important here. + % + % Goal: + % compute E_#1 such that + % #2* || T^{-1} e_ref || = || T^{-1} E_#1 || + % where T^{-1} is the data scaling transformation and e_ref the + % reference unit vector. Keep in mind that there are + % *different* data scaling transformations for each axis. + % + % We are given e_ref and e_#1 and the desired aspect ratio + % between e_ref and E_#1, which is available as #2. + % + % So: T^{-1} E_#1 := s* T^{-1} e_#1 where + % s = #2 * ||T^{-1} e_ref|| / || T^{-1} e_#1 || + % = |10^{scale_ref}| / |10^{scale_#1}| * #2 * || e_ref|| / ||e_#1||. + % + % Then, E_#1 = T ( T^{-1} E_#1 ) = s * e_#1. + % + % -> compute 's'! + % + % Part 1: compute + % #2 * ||e_ref|| / ||e_#1||. + % + \def\pgfplots@loc@TMPa{1}% + \if1\csname b@pgfplots@unitvec@is@zero@#1\endcsname + \def\pgfplots@loc@TMPa{0}% + \else + \if1\csname b@pgfplots@unitvec@is@zero@\pgfplots@apply@unit@ratio@reference\endcsname + \def\pgfplots@loc@TMPa{0}% + \fi + \fi + \if0\pgfplots@loc@TMPa + \def\pgfmathresult{16001}% + \else + % note that x^{-1} / y^{-1} == ( x/y )^{-1} == y/x . + % consequently, we can use our @inv@[xyz] values here: + \pgfmathdivide@ + {\csname pgfplots@target@unit@scale@inv@#1\endcsname}% + {\csname pgfplots@target@unit@scale@inv@\pgfplots@apply@unit@ratio@reference\endcsname} + \pgfmathmultiply@ + {\pgfmathresult}% + {#2}% + \global\let\pgfplots@glob@TMPa=\pgfmathresult + % + % also compute 1/s, required as temporary value: + %\pgfmathmultiply@ + % {\csname pgfplots@\pgfplots@apply@unit@ratio@reference @inverseveclength\endcsname} + % {\csname pgfplots@target@unit@scale@#1\endcsname}% + %\ifdim#2pt=1pt + %\else + % \pgfmathdivide@{\pgfmathresult}{#2}% + %\fi + %\global\let\pgfplots@glob@TMPb=\pgfmathresult + % + % Part 2: handle data scaling trafo scales: + \begingroup + \def\pgfplots@tmp@exponentref{0}% + \def\pgfplots@tmp@exponentK{0}% + \pgfplots@if{pgfplots@apply@datatrafo@\pgfplots@apply@unit@ratio@reference }{% + \pgfplots@letcsname{pgfplots@tmp@exponentref}={pgfplots@data@scale@trafo@EXPONENT@\pgfplots@apply@unit@ratio@reference }% + }{}% + \pgfplots@if{pgfplots@apply@datatrafo@#1}{% + \pgfplots@letcsname{pgfplots@tmp@exponentK}={pgfplots@data@scale@trafo@EXPONENT@#1}% + }{}% + \c@pgf@counta=\pgfplots@tmp@exponentref\relax + \advance\c@pgf@counta by-\pgfplots@tmp@exponentK\relax + \ifnum\c@pgf@counta=0 + \else + \pgfplotsmathmultiplypowten@{\pgfplots@glob@TMPa}{\c@pgf@counta}% + \global\let\pgfplots@glob@TMPa=\pgfmathresult + % \pgfplotsmathmultiplypowten@{\pgfplots@glob@TMPb}{-\c@pgf@counta}% + % \global\let\pgfplots@glob@TMPb=\pgfmathresult + \fi + \xdef\pgfplots@glob@TMPc{\the\c@pgf@counta}% + \endgroup + \let\pgfmathresult=\pgfplots@glob@TMPa + \fi +%\message{\string\pgfplots@getscale@unit@vector@reltoreference{#1}{#2} (reference \pgfplots@apply@unit@ratio@reference) = \pgfmathresult.^^J}% +} + +% helper for \pgfplots@check@and@apply@datatrafo@for. +\def\pgfplots@compute@number@order@for@trafo@isdimen#1\tocount#2{% + \edef\pgfplots@loc@TMPa{\pgf@sys@tonumber{#1}}% + \pgfmathfloatparsenumber{\pgfplots@loc@TMPa}% + \expandafter\pgfmathfloat@decompose@E\pgfmathresult\relax#2 + \advance#2 by1\relax +} + +% helper for \pgfplots@check@and@apply@datatrafo@for. +% +\def\pgfplots@compute@number@order@for@trafo@isfloat#1\tocount#2{% + \pgfmathfloatparsenumber{#1}% + \expandafter\pgfmathfloat@decompose@E\pgfmathresult\relax#2\relax + \advance#2 by1\relax +} + +% Initialises the data scale transformation such that it is optimal +% for direction #1 (using its axis limits and the target scaling size). +% +% Note that it will not be applied in any way; and it may still be +% modified. +% +% PRECONDITION: +% - all axis limits are available in float representation +% - \pgfplots@set@default@size@options has been called before +% POSTCONDITION: +% - the scaling transformation is set up, +\def\pgfplots@set@optimal@datatrafo@for@#1{% + \pgfplots@if{pgfplots@apply@datatrafo@#1}{% + % initialise data scale transformation + % T(x) = 10^{q-m} * x + % + \ifpgfplots@disabledatascaling + % this here is a waste of time, because the NO-OP trafo + % will be applied to all coordinates. One could really + % safe a lot of CPU time when disabledatascaling is enabled... + % but it requires so much extra cases; I really don't want + % that! + \gdef\pgfplots@glob@TMPa{0}% + \gdef\pgfplots@glob@TMPb{0}% + \else + \begingroup + \let\data@max@order=\c@pgf@counta + \let\data@cur@order=\c@pgf@countb + \let\data@dimen=\pgf@xa + \let\data@tmp=\pgf@xb + \let\data@dimen@order=\c@pgf@countc + \let\data@EXPONENT=\c@pgf@countd + \expandafter\let\expandafter\pgfplots@display@min@float\csname pgfplots@#1min\endcsname + \expandafter\let\expandafter\pgfplots@display@max@float\csname pgfplots@#1max\endcsname + \expandafter\let\expandafter\pgfplots@data@min@float\csname pgfplots@data@#1min\endcsname + \expandafter\let\expandafter\pgfplots@data@max@float\csname pgfplots@data@#1max\endcsname + \ifpgfplots@autocompute@all@limits + \else + \pgfplotscoordmath{#1}{max}{\pgfplots@display@max@float}{\pgfplots@data@max@float}% + \let\pgfplots@data@max@float=\pgfmathresult + \pgfplotscoordmath{#1}{min}{\pgfplots@display@min@float}{\pgfplots@data@min@float}% + \let\pgfplots@data@min@float=\pgfmathresult + \fi + % +%\message{minmax = [\pgfplots@data@min@float,\pgfplots@data@max@float]}% + % Step 1: compute 'm', the data order + \pgfplots@compute@number@order@for@trafo@isfloat + \pgfplots@data@min@float + \tocount\data@cur@order + % + \data@max@order=\data@cur@order + % + \pgfplots@compute@number@order@for@trafo@isfloat + \pgfplots@data@max@float + \tocount\data@cur@order + % + \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 pgfplots@#1\endcsname\pgfutil@empty + % We have 'width' or 'height' (I always have them). + % + % Use the order of these parameters. + \def\pgfplots@loc@TMPa{#1}% + \def\pgfplots@loc@TMPb{x}% + \ifx\pgfplots@loc@TMPa\pgfplots@loc@TMPb + \data@dimen=\pgfplots@width\relax + \else + \if1\pgfplots@compat@scaling@zunitfix@enable + \data@dimen=\pgfplots@height\relax + \else + % this code here belongs to versions up to + % 1.3.1. + % It is now deprecated and produces small + % pixel differences. + \def\pgfplots@loc@TMPb{y}% + \ifx\pgfplots@loc@TMPa\pgfplots@loc@TMPb + \data@dimen=\pgfplots@height\relax + \else + \data@dimen=42pt % this is actually different from 1.3.1: there, it was UNDEFINED. + \fi + \fi + \fi + \pgfplots@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 \pgfplots@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. }% + \data@EXPONENT=\data@dimen@order + \advance\data@EXPONENT by-\data@max@order + % Now, I introduce a loop which shall avoid cancellation of + % significant digits. + % + % Harmless Example: + % if we have data shift = -3 and + % max = 2e6, min = 1e6, then max-min = 1e6; T(max)-T(min) = 1e3 which is ok. + % In this case, the loop won't change anything. + % + % Critical Example: + % if we have data shift = -3 and + % max = 1980, min = 1930 then + % T(max) = 1.98 and T(min) = 1.93 + % and thus T(max)-T(min) = 0.05 . + % Considering that this is the axis range + % in which tick labels and plot points need to be computed, we + % only have two or three digits left! That happens because the + % prefix '19' is common and is cancelled in the subtraction. + % Idea: while T(max)-T(min) < O(10^2) -> increase shift by +1 + % (and make sure that T(max) < MAX_VALID_TEX_NUMBER). + % + \def\pgfplotscoordmathnotifydatascalesetfor##1{}% disable temporarily. We are just testing it. + \pgfplots@loop@CONTINUEtrue + \pgfutil@loop + \pgfplotscoordmath{#1}{datascaletrafo set params}{\the\data@EXPONENT}{0}% + \pgfplotscoordmath{#1}{datascaletrafo}{\pgfplots@data@min@float}% + \let\pgfplots@min@fixed=\pgfmathresult + \ifpgfplots@loop@CONTINUE + \pgfplotscoordmath{#1}{datascaletrafo}{\pgfplots@data@max@float}% + \let\pgfplots@max@fixed=\pgfmathresult + \data@tmp=\pgfplots@max@fixed pt +%\message{Current trafo EXPONENT for #1 direction: \the\data@EXPONENT; original #1 data limits: [\pgfplots@data@min@float:\pgfplots@data@max@float]; current transformed #1 limits: [\pgfplots@min@fixed:\pgfplots@max@fixed]; cancellation check max-min running...}% + \ifdim\data@tmp<0pt + % I need absolute values here: + \multiply\data@tmp by-1\relax + \fi + \pgfmathsubtract@{\pgfplots@max@fixed}{\pgfplots@min@fixed}% + \data@dimen=\pgfmathresult pt + \pgfplots@loop@CONTINUEfalse + \ifdim\data@tmp<1500pt % a multiplication with '10' results in max = 15000 which is the upper limit. + \ifdim\data@dimen<100pt % I guess if max-min = O(100), we have quite good accuracy + \ifdim\data@dimen<0.0001pt + \else + \advance\data@EXPONENT by1 + \pgfplots@loop@CONTINUEtrue + \fi + \fi + \fi + %-------------------------------------------------- + % \ifdim\data@dimen>1200pt% FIXME : is this here ok!? CHECK IT! + % \ifdim\data@dimen>7999pt + % \advance\data@EXPONENT by-2 + % \else + % \advance\data@EXPONENT by-1 + % \fi + % \pgfplots@loop@CONTINUEfalse + % \fi + %-------------------------------------------------- + \pgfutil@repeat + \xdef\pgfplots@glob@TMPa{\the\data@EXPONENT}% + \xdef\pgfplots@glob@TMPb{\pgfplots@min@fixed}% + \endgroup + \fi + % COMPLETE INITIALISATION: +%\message{Initialising the data scale transformation in direction #1 to 10^\pgfplots@glob@TMPa*#1 - \pgfplots@glob@TMPb...^^J}% + \pgfplotscoordmath{#1}{datascaletrafo set params}{\pgfplots@glob@TMPa}{\pgfplots@glob@TMPb}% + }{% + % case apply trafo == false: + \pgfplotscoordmath{#1}{datascaletrafo set params}{0}{0}% + }% +} + + +\def\pgfplots@set@optimal@datatrafos@allaxes{% + \pgfplots@letcsname pgfplots@xmin@unscaled@as@float={pgfplots@xmin}% + \pgfplots@letcsname pgfplots@xmax@unscaled@as@float={pgfplots@xmax}% + % + \pgfplots@letcsname pgfplots@ymin@unscaled@as@float={pgfplots@ymin}% + \pgfplots@letcsname pgfplots@ymax@unscaled@as@float={pgfplots@ymax}% + % + \pgfplots@letcsname pgfplots@zmin@unscaled@as@float={pgfplots@zmin}% + \pgfplots@letcsname pgfplots@zmax@unscaled@as@float={pgfplots@zmax}% + % + \pgfplots@ifneeds@one@uniform@datascale{% + % Ah - we have to ensure that there is ONE common scale for + % each unit (x, y, and z have the same). + % + % In this case, we need to choose one of the transformations + % and apply it to all axes -- such that each axis gets the + % same scale. + % + % this mode is used for axis equal and its variants. + % + % The strategy to fix the transformation is as follows: + % 1. we assume that axis limits will be enlarged in order to + % satisfy 'scale uniformly'. + % 2. we assume that the LARGEST axis limit dominates the + % others. + % 3. if one of the axes does not have datascaling (i.e. is + % log scale), we disable all other datascalings. + % + % Consequently, we search for the axis with the largest limit + % - and copy its data scaling to all other axes. If one of the + % axes is log, that one overrules it and all data scaling + % effects are disabled.. + \begingroup + \let\pgfplots@data@scale@trafo@EXPONENT@common=\pgfutil@empty + \def\pgfplots@data@scale@trafo@EXPONENT@common@arg{-}% this should not match anything in this context. + \pgfplots@if{pgfplots@apply@datatrafo@x}{% + }{% + \def\pgfplots@data@scale@trafo@EXPONENT@common{{0}{0}}% disable scaling! + }% + \pgfplots@if{pgfplots@apply@datatrafo@y}{% + }{% + \def\pgfplots@data@scale@trafo@EXPONENT@common{{0}{0}}% disable scaling! + }% + \ifpgfplots@threedim + \pgfplots@if{pgfplots@apply@datatrafo@z}{% + }{% + \def\pgfplots@data@scale@trafo@EXPONENT@common{{0}{0}}% disable scaling! + }% + \fi + \ifx\pgfplots@data@scale@trafo@EXPONENT@common\pgfutil@empty + % ah - we still need to compute one. ok, search for the + % largest limit. + % + \pgfplots@get@axis@with@largest@limits + \let\pgfplots@data@scale@trafo@EXPONENT@common@arg=\pgfplotsretval + % + % ok, compute data scaling transformation for the target axis: + \expandafter\pgfplots@set@optimal@datatrafo@for@\pgfplots@data@scale@trafo@EXPONENT@common@arg% + % + \pgfplotscoordmath{\pgfplots@data@scale@trafo@EXPONENT@common@arg}{datascaletrafo get params}% + \let\pgfplots@data@scale@trafo@EXPONENT@common=\pgfmathresult% + \else + % hm. early-out - we already have the scaling trafo. + % return it. + \fi + \global\let\pgfplots@glob@TMPa=\pgfplots@data@scale@trafo@EXPONENT@common + \global\let\pgfplots@glob@TMPb=\pgfplots@data@scale@trafo@EXPONENT@common@arg + \endgroup + % + \xdef\pgfplots@glob@TMPc{\expandafter\pgfutil@firstoftwo\pgfplots@glob@TMPa}% +%\message{using datascaletrafo of axis '\pgfplots@glob@TMPb' for each axis.^^J}% + % + \def\pgfplots@loc@TMPd##1{% + \if ##1\pgfplots@glob@TMPb + % we need to set the scaling trafo for the target direction + % (was lost after \endgroup) + \def\pgfplots@loc@TMPa{\pgfplotscoordmath{##1}{datascaletrafo set params}}% + \expandafter\pgfplots@loc@TMPa\pgfplots@glob@TMPa% + \else + \pgfplotscoordmath{##1}{datascaletrafo set params}{\pgfplots@glob@TMPc}{0}% + \pgfplotscoordmath{##1}{datascaletrafo}{\csname pgfplots@##1min\endcsname}% +%\message{Initialising the data scale transformation in direction ##1 to 10^\pgfplots@glob@TMPc*##1 - \pgfmathresult...^^J}% + \pgfplotscoordmath{##1}{datascaletrafo set params}{\pgfplots@glob@TMPc}{\pgfmathresult}% + \fi + }% + \pgfplots@loc@TMPd x% + \pgfplots@loc@TMPd y% + \ifpgfplots@threedim + \pgfplots@loc@TMPd z% + \fi + }{% + % optimize individually: + \pgfplots@set@optimal@datatrafo@for@ x% + \pgfplots@set@optimal@datatrafo@for@ y% + \ifpgfplots@threedim + \pgfplots@set@optimal@datatrafo@for@ z% + \fi + }% + % +}% + +% Defines \pgfplotsretval to be one of x, y, or z, such that the +% return value indicates the axis with largest untransformed axis +% limits. +\def\pgfplots@get@axis@with@largest@limits{% + \begingroup + \let\pgfplotsretval@extreme=\pgfutil@empty + \let\pgfplotsretval@extreme@arg=\pgfutil@empty + \def\pgfplots@@##1{% + % compute axis range for axis ##1 ... + \pgfplotscoordmath{default}{parsenumber}{\csname pgfplots@##1min\endcsname}% + \let\pgfplots@loc@TMPa=\pgfmathresult + \pgfplotscoordmath{default}{parsenumber}{\csname pgfplots@##1max\endcsname}% + \pgfplotscoordmath{default}{op}{subtract}{{\pgfmathresult}{\pgfplots@loc@TMPa}}% + % ... ok, it is in \pgfmathresult. + \let\candidate=\pgfmathresult + \ifx\pgfplotsretval@extreme@arg\pgfutil@empty + % ah: no extreme value so far. use ours. + \def\pgfplotsretval@extreme@arg{##1}% + \let\pgfplotsretval@extreme=\candidate + \else + \pgfplotscoordmath{default}{if less than}{\pgfplotsretval@extreme}{\candidate}{% + % update extreme value: + \def\pgfplotsretval@extreme@arg{##1}% + \let\pgfplotsretval@extreme=\candidate + }{% + }% + \fi + }% + \pgfplots@@ x% + \pgfplots@@ y% + \ifpgfplots@threedim + \pgfplots@@ z% + \fi + \let\pgfplotsretval=\pgfplotsretval@extreme@arg + \pgfmath@smuggleone\pgfplotsretval + \endgroup +}% + +% Initialises the data scale transformation and applies it to any +% user specified options. +% +% PRECONDITION: +% - all axis limits are available in float representation +% - \pgfplots@set@default@size@options has been called before +% - the scaling transformation for direction x is set up +% (\pgfplots@set@optimal@datatrafo@for@), +% POSTCONDITION: +% - all axis limits are transformed, but no other axis inputs. +% +% Unit vectors and other axis input parameters will be scaled later. +% +% @see \pgfplots@check@and@apply@datatrafo@for +\def\pgfplots@apply@datatrafo@to@axis@limits#1{% + \pgfplots@if{pgfplots@apply@datatrafo@#1}{% + % Transform axis limits: +%\message{#1- display limits BEFORE data transformation: [\csname pgfplots@#1min\endcsname:\csname pgfplots@#1max\endcsname]^^J}% + \pgfplotscoordmath{#1}{datascaletrafo}{\csname pgfplots@#1min\endcsname}% + \expandafter\global\expandafter\let\csname pgfplots@#1min\endcsname=\pgfmathresult + % + \pgfplotscoordmath{#1}{datascaletrafo}{\csname pgfplots@#1max\endcsname}% + \expandafter\global\expandafter\let\csname pgfplots@#1max\endcsname=\pgfmathresult +%\message{#1- display limits after data transformation: [\csname pgfplots@#1min\endcsname:\csname pgfplots@#1max\endcsname]^^J}% + }{% + % case apply trafo == false: + \expandafter\let\csname pgfplots@#1min@unscaled@as@float\endcsname=\pgfutil@empty + \expandafter\let\csname pgfplots@#1max@unscaled@as@float\endcsname=\pgfutil@empty + }% +} |