%-------------------------------------------- % % 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/2008 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 . % %-------------------------------------------- \newif\ifpgfplots@log@tick@isminor@tick@pos % Checks whether the tick position given as #1.#2=log10(T) belongs to % T=i*10^j with an integer i>1. % % If T=i*10^j, \ifpgfplots@log@tick@isminor@tick@pos will be set to true and % \pgfmathresult will contain T. % % Otherwise, \ifpgfplots@log@tick@isminor@tick@pos will be set to false and % pgfmathresult to #1.#2 % % Arguments: % #1.#2 the value log10(T) % % Implementation: % if T = i*10^j, log10(T) = log10(i) + j. % That means if log10(T) in \Z, we have T = 10^j. If not, we need to % check wether i is an integer. Please note that log10(i) < 1. % % Further note: log(T) < 0 <=> j<0. % In case j<0, we have % #1.#2 = j + log(i) % = - ( -j - log(i) ) % = - ( -j - 1 + (1-log(i)) ) % = #1 '.' #2 [ up to the '0.' % that means #1 = j-1 and #2 = 1-log(i). \def\pgfplots@is@log@tick@a@minor@tick@pos#1.#2\relax{% \pgfmathapproxequalto@{#1.#2}{#1.0}% \ifpgfmathcomparison % in MOST cases, this here will be true: \pgfplots@log@tick@isminor@tick@posfalse \def\pgfmathresult{#1.#2}% \else % I guess this won't happen too often. In fact, it's a very % special case. \begingroup \c@pgf@counta=#1\relax \ifnum\c@pgf@counta<0 \advance\c@pgf@counta by-1 \pgfmathsubtract@{1}{0.#2}% \expandafter\pgfplots@is@log@tick@a@minor@tick@pos@IDENTIFY@LOGi\pgfmathresult\relax \ifpgfplots@log@tick@isminor@tick@pos \aftergroup\pgfplots@log@tick@isminor@tick@postrue \edef\pgfmathresult{\pgfmathresult e\the\c@pgf@counta}% \else \aftergroup\pgfplots@log@tick@isminor@tick@posfalse \def\pgfmathresult{#1.#2}% \fi \else \pgfplots@is@log@tick@a@minor@tick@pos@IDENTIFY@LOGi0.#2\relax \ifpgfplots@log@tick@isminor@tick@pos \aftergroup\pgfplots@log@tick@isminor@tick@postrue \edef\pgfmathresult{\pgfmathresult e\the\c@pgf@counta}% \else \aftergroup\pgfplots@log@tick@isminor@tick@posfalse \def\pgfmathresult{#1.#2}% \fi \fi \pgfmath@smuggleone\pgfmathresult \endgroup \fi } % expects a positive number. \def\pgfplots@is@log@tick@a@minor@tick@pos@IDENTIFY@LOGi0.#1\relax{% \pgfplots@log@tick@isminor@tick@postrue \pgfmathapproxequalto@{0.#1}{0.3010299956639}% \ifpgfmathcomparison \def\pgfmathresult{2}% \else \pgfmathapproxequalto@{0.#1}{0.4771212547196}% \ifpgfmathcomparison \def\pgfmathresult{3}% \else \pgfmathapproxequalto@{0.#1}{0.6020599913279}% \ifpgfmathcomparison \def\pgfmathresult{4}% \else \pgfmathapproxequalto@{0.#1}{0.698970004}% \ifpgfmathcomparison \def\pgfmathresult{5}% \else \pgfmathapproxequalto@{0.#1}{0.7781512503}% \ifpgfmathcomparison \def\pgfmathresult{6}% \else \pgfmathapproxequalto@{0.#1}{0.8450980400}% \ifpgfmathcomparison \def\pgfmathresult{7}% \else \pgfmathapproxequalto@{0.#1}{0.9030899869}% \ifpgfmathcomparison \def\pgfmathresult{8}% \else \pgfmathapproxequalto@{0.#1}{0.954242509439}% \ifpgfmathcomparison \def\pgfmathresult{9}% \else \pgfplots@log@tick@isminor@tick@posfalse \fi \fi \fi \fi \fi \fi \fi \fi } % Checks whether we need to create a separate 'tick scale label', % a node with ' * 10^3' on the side of the axis: % % PRECONDITION: % Axis limits for #1 are given. I need their values before any data % scale transformation has been applied. % If % \pgfplots@#1min@unscaled@as@float % and % \pgfplots@#1max@unscaled@as@float % exist; I will use these macros. % Otherwise, I will use \pgfplots@#1min and \pgfplots@#1max; % assuming that no data scale transformation is active. % FIXME : does that need further attention? \def\pgfplots@init@scaled@tick@for#1{% \global\def\pgfplots@glob@TMPa{0}% \begingroup \ifcase\csname pgfplots@scaled@ticks@#1@choice\endcsname % CASE 0 : scaled #1 ticks=false: do nothing here. \or % CASE 1 : scaled #1 ticks=true: %-------------------------------- % the \pgfplots@xmin@unscaled@as@float is set just before the data % scale transformation is initialised. % % The variables are empty if there is no datascale transformation. \expandafter\let\expandafter\pgfplots@cur@min@unscaled\csname pgfplots@#1min@unscaled@as@float\endcsname \expandafter\let\expandafter\pgfplots@cur@max@unscaled\csname pgfplots@#1max@unscaled@as@float\endcsname % \ifx\pgfplots@cur@min@unscaled\pgfutil@empty \edef\pgfplots@loc@TMPa{\csname pgfplots@#1min\endcsname}% \expandafter\pgfmathfloatparsenumber\expandafter{\pgfplots@loc@TMPa}% \let\pgfplots@cur@min@unscaled=\pgfmathresult \edef\pgfplots@loc@TMPa{\csname pgfplots@#1max\endcsname}% \expandafter\pgfmathfloatparsenumber\expandafter{\pgfplots@loc@TMPa}% \let\pgfplots@cur@max@unscaled=\pgfmathresult \fi % \expandafter\pgfmathfloat@decompose@E\pgfplots@cur@min@unscaled\relax\pgfmathfloat@a@E \expandafter\pgfmathfloat@decompose@E\pgfplots@cur@max@unscaled\relax\pgfmathfloat@b@E \ifnum\pgfmathfloat@b@E<\pgfmathfloat@a@E \pgfmathfloat@b@E=\pgfmathfloat@a@E \fi \xdef\pgfplots@glob@TMPa{\pgfplots@scale@ticks@above@exponent}% \expandafter\ifnum\pgfplots@glob@TMPa<\pgfmathfloat@b@E % ok, scale it: \multiply\pgfmathfloat@b@E by-1 \xdef\pgfplots@glob@TMPa{\the\pgfmathfloat@b@E}% \else \xdef\pgfplots@glob@TMPa{\pgfplots@scale@ticks@below@exponent}% \expandafter\ifnum\pgfplots@glob@TMPa>\pgfmathfloat@b@E % ok, scale it: \multiply\pgfmathfloat@b@E by-1 \xdef\pgfplots@glob@TMPa{\the\pgfmathfloat@b@E}% \else % no scaling necessary: \xdef\pgfplots@glob@TMPa{0}% \fi \fi \or % CASE 2 : scaled #1 ticks=base 10: %-------------------------------- \c@pgf@counta=\csname pgfplots@scaled@ticks@#1@arg\endcsname\relax %\multiply\c@pgf@counta by-1 \xdef\pgfplots@glob@TMPa{\the\c@pgf@counta}% \or % CASE 3 : scaled #1 ticks=real: %-------------------------------- \pgfmathfloatparsenumber{\csname pgfplots@scaled@ticks@#1@arg\endcsname}% \global\let\pgfplots@glob@TMPa=\pgfmathresult \or % CASE 4 : scaled #1 ticks=manual: \expandafter\global\expandafter\let\expandafter\pgfplots@glob@TMPa\csname pgfplots@scaled@ticks@#1@arg\endcsname \fi \endgroup \expandafter\let\csname pgfplots@tick@scale@#1\endcsname=\pgfplots@glob@TMPa% } % x-axis tick labels for #1th tick % #1: the axis (x or y) % #2: the value % #3,#4: coordinates for \pgfplotspointonorientedsurfaceab % #5: ticknumber \def\pgfplots@show@ticklabel#1#2(#3,#4)#5{{% \csname ifpgfplots@#1ticklabel@interval\endcsname \pgfmathparse{#3}% \edef\pgfplots@show@ticklabel@coord@x@new{\pgfmathresult}% \pgfmathparse{#4}% \edef\pgfplots@show@ticklabel@coord@y@new{\pgfmathresult}% % \pgfplots@show@ticklabel@{#1}{#2}% \let\nexttick=\tick \ifx\pgfplots@show@ticklabel@LASTTICK\pgfutil@empty % its the first call. Simply remember arguments and wait % for interval boundary before proceeding. \else % acquire options of first interval boundary: \pgfplots@show@ticklabel@LASTTICK % compute new node position: \pgfmathparse{0.5*(\csname pgfplots@show@ticklabel@coord@#1\endcsname + \csname pgfplots@show@ticklabel@coord@#1@new\endcsname)}% \expandafter\edef\csname pgfplots@show@ticklabel@coord@#1\endcsname{\pgfmathresult}% \let\ticknum=\pgfplots@show@ticklabel@num\relax% \let\tick=\pgfplots@show@ticklabel@tick% \edef\pgfplots@loc@TMPa{at (\pgfplots@show@ticklabel@coord@x,\pgfplots@show@ticklabel@coord@y)}% \begingroup \pgftransformshift{\pgfplotspointonorientedsurfaceab{\pgfplots@show@ticklabel@coord@x}{\pgfplots@show@ticklabel@coord@y}}% \node at (0pt,0pt) {\csname pgfplots@#1ticklabel\endcsname};% \endgroup \fi \xdef\pgfplots@show@ticklabel@LASTTICK{% \noexpand\def\noexpand\pgfplots@show@ticklabel@tick{\nexttick}% \noexpand\def\noexpand\pgfplots@show@ticklabel@coord@x{\pgfplots@show@ticklabel@coord@x@new}% \noexpand\def\noexpand\pgfplots@show@ticklabel@coord@y{\pgfplots@show@ticklabel@coord@y@new}% \noexpand\edef\noexpand\pgfplots@show@ticklabel@num{#5}% }% \else \let\ticknum=#5\relax% \pgfplots@show@ticklabel@{#1}{#2}% \begingroup \pgftransformshift{\pgfplotspointonorientedsurfaceab{#3}{#4}}% % %-------------------------------------------------- % \iffalse % %\iftrue % % The following code is experimental and contains automatically % % aligned tick labels (especially for 3D axes). It's not quite % % finished. % % % %\tracingmacros=2\tracingcommands=2 % \message{HIER}% % \if x\pgfplotspointonorientedsurfaceB % \if y\pgfplotspointonorientedsurfaceN % \def\pgfplotspointonorientedsurfbN##1##2{\pgfplotsqpointxyz{##1}{##2}{0}}% % \else% N == z: % \def\pgfplotspointonorientedsurfbN##1##2{\pgfplotsqpointxyz{##1}{0}{##2}}% % \fi % \else % \if y\pgfplotspointonorientedsurfaceB % \if x\pgfplotspointonorientedsurfaceN % \def\pgfplotspointonorientedsurfbN##1##2{\pgfplotsqpointxyz{##2}{##1}{0}}% % \else% N == z: % \def\pgfplotspointonorientedsurfbN##1##2{\pgfplotsqpointxyz{0}{##1}{##2}}% % \fi % \else % % B == z % \if y\pgfplotspointonorientedsurfaceN % \def\pgfplotspointonorientedsurfbN##1##2{\pgfplotsqpointxyz{0}{##2}{##1}}% % \else% N == x: % \def\pgfplotspointonorientedsurfbN##1##2{\pgfplotsqpointxyz{##2}{0}{##1}}% % \fi % \fi % \fi % %\message{a == \pgfplotspointonorientedsurfaceA, b == \pgfplotspointonorientedsurfaceB, N == \pgfplotspointonorientedsurfaceN. zeug=\meaning\pgfplotspointonorientedsurfbN.}% % \if0\pgfplots@ticklabelside % % this means : the 'b' axis of the surface is on the lower axis % % limit. Since we want tick labels OUTSIDE of the axis, we need % % sign = -1. % \def\pgfplots@loc@TMPa{-}% % \else % % in this case, we the OUTSIDE area requires a plus sign - the b % % axis already points to the outside. % \def\pgfplots@loc@TMPa{}% % \fi % \if0\pgfplotspointonorientedsurfaceabsetupfor@fixedsymbol % % same as before: the N axis is on the lower axis limit. % % So: sign -1 % \def\pgfplots@loc@TMPb{-}% % \else % \def\pgfplots@loc@TMPb{}% % \fi % \pgfmathparse{\csname pgfplots@\pgfplotspointonorientedsurfaceB @inverseveclength\endcsname * \pgfplots@loc@TMPa 0.2cm}% % \let\pgfplots@loc@TMPa=\pgfmathresult % \pgfmathparse{\csname pgfplots@\pgfplotspointonorientedsurfaceN @inverseveclength\endcsname * \pgfplots@loc@TMPb 0.2cm}% % \let\pgfplots@loc@TMPb=\pgfmathresult % %-------------------------------------------------- % % \pgfpathmoveto{\pgfqpoint{0pt}{0pt}}% % % \pgfpathlineto{\pgfplotspointonorientedsurfbN{\pgfplots@loc@TMPa}{\pgfplots@loc@TMPb}}% % % \pgfusepath{stroke} % %-------------------------------------------------- % \pgftransformshift{\pgfplotspointonorientedsurfbN{\pgfplots@loc@TMPa}{\pgfplots@loc@TMPb}}% % \tikzset{every node/.append style={anchor=center}}% % \fi %-------------------------------------------------- % \node at (0pt,0pt) {\csname pgfplots@#1ticklabel\endcsname};% \endgroup \fi }} % Defines \tick by applying any necessary math to the (possibly % transformed) tick value #2. % % #1: axis (x or y) % #2: tick value. \def\pgfplots@show@ticklabel@#1#2{% \csname ifpgfplots@apply@datatrafo@#1\endcsname \csname pgfplots@inverse@datascaletrafo@#1\endcsname{#2}% \ifcase\csname pgfplots@scaled@ticks@#1@choice\endcsname \or \expandafter\pgfmathfloatshift@\expandafter{\pgfmathresult}{\csname pgfplots@tick@scale@#1\endcsname}% \or \expandafter\pgfmathfloatshift@\expandafter{\pgfmathresult}{\csname pgfplots@tick@scale@#1\endcsname}% \or \expandafter\pgfmathfloatdivide@\expandafter{\pgfmathresult}{\csname pgfplots@tick@scale@#1\endcsname}% \or % scaled #1 ticks=manual. Invoke manual tick scaling code: \expandafter\let\expandafter\pgfplots@loc@TMPa\csname pgfplots@tick@scale@#1\endcsname \expandafter\pgfplots@loc@TMPa\expandafter{\pgfmathresult}% \fi % .. and this here provides \tick as fixed point repr: \expandafter\pgfmathfloattofixed\expandafter{\pgfmathresult}% \let\tick=\pgfmathresult \else \edef\tick{#2}% \pgfplots@if{pgfplots@#1islinear}{% \ifnum\csname pgfplots@scaled@ticks@#1@choice\endcsname=0 \else \pgfmathfloatparsenumber{#2}% \ifnum\csname pgfplots@scaled@ticks@#1@choice\endcsname=3 \expandafter\pgfmathfloatdivide@\expandafter{\pgfmathresult}{\csname pgfplots@tick@scale@#1\endcsname}% \else \expandafter\pgfmathfloatshift@\expandafter{\pgfmathresult}{\csname pgfplots@tick@scale@#1\endcsname}% \fi \expandafter\pgfmathfloattofixed\expandafter{\pgfmathresult}% \let\tick=\pgfmathresult \fi }{}% \fi \pgfkeysgetvalue{/pgfplots/#1 coord inv trafo/.@cmd}\pgfplots@loc@TMPa \ifx\pgfplots@loc@TMPa\pgfplots@empty@command@key \else \let\pgfmathresult=\tick% \expandafter\pgfplots@loc@TMPa\expandafter{\tick}\pgfeov \let\tick=\pgfmathresult \fi }% \def\pgfplots@user@ticklabel@list@x{% \pgfplotslistselectorempty\ticknum\of\pgfplots@xticklabels\to\tick \tick } \def\pgfplots@user@ticklabel@list@y{% \pgfplotslistselectorempty\ticknum\of\pgfplots@yticklabels\to\tick \tick } \def\pgfplots@user@ticklabel@list@z{% \pgfplotslistselectorempty\ticknum\of\pgfplots@zticklabels\to\tick \tick } \def\pgfplots@user@extra@ticklabel@list@x{% \pgfplotslistselectorempty\ticknum\of\pgfplots@extra@xticklabels\to\tick \tick } \def\pgfplots@user@extra@ticklabel@list@y{% \pgfplotslistselectorempty\ticknum\of\pgfplots@extra@yticklabels\to\tick \tick } \def\pgfplots@user@extra@ticklabel@list@z{% \pgfplotslistselectorempty\ticknum\of\pgfplots@extra@zticklabels\to\tick \tick } % Check if a label does not cross the x-axis \def\pgfplots@ytick@check@tickshow{% \pgfplots@tickshowtrue \ifnum\pgfplots@yaxislinesnum=2 % \ifcase\pgfplots@xaxislinesnum\relax \ifdim\pgfplots@tmpa=\pgfplots@ymin@reg\relax \pgfplots@tickshowfalse \fi \ifdim\pgfplots@tmpa=\pgfplots@ymax@reg\relax \pgfplots@tickshowfalse \fi \or \ifdim\pgfplots@tmpa=\pgfplots@ymin@reg\relax \pgfplots@tickshowfalse \fi \or \ifdim\pgfplots@tmpa=\pgfplots@logical@ZERO@y pt \pgfplots@tickshowfalse \fi \or \ifdim\pgfplots@tmpa=\pgfplots@ymax@reg\relax \pgfplots@tickshowfalse \fi \fi \fi } \def\pgfplots@ztick@check@tickshow{% \pgfplots@tickshowtrue % FIXME }% % Fills the macros % \pgfplots@tick@beg@a \pgfplots@tick@end@a % \pgfplots@tick@beg@b \pgfplots@tick@end@b % with coordinates such that % (\pgfplots@tick@beg@a,\pgfplots@tmpa) -- (\pgfplots@tick@end@a,\pgfplots@tmpa) % produces a correct tick line. % % The '@b' variant is only used in case of \pgfplots@ytickposnum = 0 % % #1 : the current axis (x or y). % #2 : the current tick width % \def\pgfplots@prepare@tick@offsets@for@#1#2{% \ifcase\csname pgfplots@#1tickposnum\endcsname\relax %(\pgfplots@xcoordminTEX-\pgfplots@tick@offset, \pgfplots@tmpa) -- ++( #2, 0pt) \edef\pgfplots@tick@beg@a{\csname pgfplots@\pgfplotspointonorientedsurfaceB min\endcsname}% \pgfmathsubtract@{\pgfplots@tick@beg@a}{\pgfplots@tick@offset}% \let\pgfplots@tick@beg@a=\pgfmathresult \pgfmathadd@{\pgfplots@tick@beg@a}{#2}% \let\pgfplots@tick@end@a=\pgfmathresult % %(\pgfplots@xcoordmaxTEX+\pgfplots@tick@offset, \pgfplots@tmpa) -- ++(-#2, 0pt) \edef\pgfplots@tick@beg@b{\csname pgfplots@\pgfplotspointonorientedsurfaceB max\endcsname}% \pgfmathadd@{\pgfplots@tick@beg@b}{\pgfplots@tick@offset}% \let\pgfplots@tick@beg@b=\pgfmathresult \pgfmathsubtract@{\pgfplots@tick@beg@b}{#2}% \let\pgfplots@tick@end@b=\pgfmathresult% \or % (\pgfplots@xcoordminTEX-\pgfplots@tick@offset, \pgfplots@tmpa) -- ++( #2, 0pt); \edef\pgfplots@tick@beg@a{\csname pgfplots@\pgfplotspointonorientedsurfaceB min\endcsname}% \pgfmathsubtract@{\pgfplots@tick@beg@a}{\pgfplots@tick@offset}% \let\pgfplots@tick@beg@a=\pgfmathresult \pgfmathadd@{\pgfplots@tick@beg@a}{#2}% \let\pgfplots@tick@end@a=\pgfmathresult \or % (\pgfplots@ZERO@x -\pgfplots@tick@offset, \pgfplots@tmpa) -- ++( #2, 0pt); \pgfmathsubtract@{\csname pgfplots@logical@ZERO@\pgfplotspointonorientedsurfaceB \endcsname}{\pgfplots@tick@offset}% \let\pgfplots@tick@beg@a=\pgfmathresult \pgfmathadd@{\pgfplots@tick@beg@a}{#2}% \let\pgfplots@tick@end@a=\pgfmathresult% \or % (\pgfplots@xcoordmaxTEX+\pgfplots@tick@offset, \pgfplots@tmpa) -- ++(-#2, 0pt); \edef\pgfplots@tick@beg@a{\csname pgfplots@\pgfplotspointonorientedsurfaceB max\endcsname}% \pgfmathadd@{\pgfplots@tick@beg@a}{\pgfplots@tick@offset}% \let\pgfplots@tick@beg@a=\pgfmathresult \pgfmathsubtract@{\pgfplots@tick@beg@a}{#2}% \let\pgfplots@tick@end@a=\pgfmathresult% \else % FALL BACK % (\pgfplots@xcoordminTEX-\pgfplots@tick@offset, \pgfplots@tmpa) -- ++( #2, 0pt); \edef\pgfplots@tick@beg@a{\csname pgfplots@\pgfplotspointonorientedsurfaceB min\endcsname}% \pgfmathsubtract@{\pgfplots@tick@beg@a}{\pgfplots@tick@offset}% \let\pgfplots@tick@beg@a=\pgfmathresult \pgfmathadd@{\pgfplots@tick@beg@a}{#2}% \let\pgfplots@tick@end@a=\pgfmathresult \fi }% \newif\ifpgfplots@needsminorloop \def\pgfplots@draw@tick@scale@label@for#1{% \csname ifpgfplots@#1islinear\endcsname \begingroup \def\pgfplots@temp@isbaseten{0}% \ifcase\csname pgfplots@scaled@ticks@#1@choice\endcsname \global\let\pgfplots@glob@TMPa=\pgfutil@empty \or \xdef\pgfplots@glob@TMPa{\csname pgfplots@tick@scale@#1\endcsname}% \def\pgfplots@temp@isbaseten{1}% \or \xdef\pgfplots@glob@TMPa{\csname pgfplots@tick@scale@#1\endcsname}% \def\pgfplots@temp@isbaseten{1}% \or \xdef\pgfplots@glob@TMPa{\csname pgfplots@tick@scale@#1\endcsname}% % real: \or % manual: \global\def\pgfplots@glob@TMPa{dummyargument}% \fi \if1\pgfplots@temp@isbaseten \expandafter\c@pgf@counta\pgfplots@glob@TMPa\relax \multiply\c@pgf@counta by-1 \ifnum\c@pgf@counta=0\relax \global\let\pgfplots@glob@TMPa=\pgfutil@empty \else \xdef\pgfplots@glob@TMPa{\the\c@pgf@counta}% \fi \fi \endgroup \ifx\pgfplots@glob@TMPa\pgfutil@empty \else \begingroup \pgfkeysgetvalue{/pgfplots/#1tick scale label code/.@cmd}\pgfplots@loc@TMPa \ifx\pgfplots@loc@TMPa\pgfplots@empty@command@key \else \edef\pgfplots@tick@scale@labels{\noexpand\pgfplots@invoke@pgfkeyscode{/pgfplots/#1tick scale label code/.@cmd}{\pgfplots@glob@TMPa}}% \pgftransformshift{\pgfplotspointsouthwest}% \pgfsetxvec{\pgfplotspointxaxis}% \pgfsetyvec{\pgfplotspointyaxis}% % FIXME : do I need the fix for 'current axis.origin' % here!? \node[% /pgfplots/every tick label,% /pgfplots/every #1 tick label,% /pgfplots/every #1 tick scale label] {\pgfplots@tick@scale@labels}; \fi \endgroup \fi \fi } % Check if the current tick position, stored in \pgfplots@tmpa, % does not cross the y-axis. % % This is just a special case for centered axis lines. \def\pgfplots@xtick@check@tickshow{% \pgfplots@tickshowtrue \ifnum\pgfplots@xaxislinesnum=2 % \ifcase\pgfplots@yaxislinesnum\relax \ifdim\pgfplots@tmpa=\pgfplots@xmin@reg\relax \pgfplots@tickshowfalse \fi \ifdim\pgfplots@tmpa=\pgfplots@xmax@reg\relax \pgfplots@tickshowfalse \fi \or \ifdim\pgfplots@tmpa=\pgfplots@xmin@reg\relax \pgfplots@tickshowfalse \fi \or \ifdim\pgfplots@tmpa=\pgfplots@logical@ZERO@x pt % \pgfplots@tickshowfalse \fi \or \ifdim\pgfplots@tmpa=\pgfplots@xmax@reg\relax \pgfplots@tickshowfalse \fi \fi \fi } % Draws extra ticks including grid lines, tick lines and tick labels % along the current oriented surface. % % See \pgfplots@drawticklines@onorientedsurf@ for a description of the % oriented surface. % % #1 : tick position list \def\pgfplots@draw@extra@ticks@onorientedsurf{% \expandafter\pgfplots@draw@extra@ticks@onorientedsurf@\pgfplotspointonorientedsurfaceA }% % #1: axis (x or y) % #2: tick position list \def\pgfplots@draw@extra@ticks@onorientedsurf@#1#2{% \begingroup \def\pgfplots@scaled@ticks@x@choice{0}% \def\pgfplots@scaled@ticks@y@choice{0}% \csname pgfplots@#1minorticksfalse\endcsname \csname pgfplots@#1minorgridsfalse\endcsname \expandafter\let\expandafter\axis@TMP\csname pgfplots@extra@#1ticklabel\endcsname \expandafter\let\csname pgfplots@#1ticklabel\endcsname=\axis@TMP \pgfplotsset{/pgfplots/every extra #1 tick}% \expandafter\pgfplots@prepare@tick@coordlists@for\pgfplotspointonorientedsurfaceA{#2}% \pgfplots@drawgridlines@onorientedsurf% \pgfplots@drawticklines@onorientedsurf% \pgfplots@drawticklabels@onorientedsurf% \endgroup } % Computes final major and minor tick positions into global lists % \pgfplots@prepared@tick@positions@major@x % and % \pgfplots@prepared@tick@positions@minor@x. % % The major tick list contains tuples (canvas position,logical position) % while the minor tick list contains just the canvas position. % % #1: the axis % #2: the tick list. % % PRECONDITION: % - \pgfplots@determinedefaultvalues has been executed. % That means particularly that \pgfplots@[xy][min,max] are available in TeX point % range (after datascaling and logs). \def\pgfplots@prepare@tick@coordlists@for#1#2{% \begingroup \expandafter\let\expandafter\ifpgfplots@islinear\csname ifpgfplots@#1islinear\endcsname \expandafter\let\expandafter\ifpgfplots@minorticks\csname ifpgfplots@#1minorticks\endcsname \expandafter\let\expandafter\ifpgfplots@minorgrids\csname ifpgfplots@#1minorgrids\endcsname % these lists need to be global such that I can fill them inside % of \foreach statements. And, yes: I have also added a TeX group % on my own (but that's not the problem). \global\pgfplotslistnewempty\pgfplots@prepared@tick@positions@major \global\pgfplotslistnewempty\pgfplots@prepared@tick@positions@minor \edef\pgfplots@loc@TMPa{#2}% \ifx\pgfplots@loc@TMPa\pgfutil@empty \else \ifpgfplots@minorticks \pgfplots@needsminorlooptrue \else \ifpgfplots@minorgrids \pgfplots@needsminorlooptrue \else \pgfplots@needsminorloopfalse \fi \fi \ifpgfplots@needsminorloop \ifpgfplots@islinear \expandafter\let\expandafter\pgfplots@minor@tick@num\csname pgfplots@minor@#1tick@num\endcsname \begingroup \c@pgf@counta=\pgfplots@minor@tick@num\relax \advance\c@pgf@counta by1\relax \pgfplots@tmpa=\csname pgfplots@tick@distance@#1\endcsname pt % \divide\pgfplots@tmpa by\c@pgf@counta \edef\pgfmathresult{\pgf@sys@tonumber{\pgfplots@tmpa}}% \pgfmath@smuggleone\pgfmathresult \endgroup \let\pgfplots@minor@tick@dist=\pgfmathresult \else \def\pgfplots@minor@tick@num{9}% \fi \fi % % Prepare the [xy]tick[min|max] key processing: \let\pgfplots@checktickminmax=\pgfutil@empty \expandafter\ifx\csname pgfplots@#1tickmin\endcsname\pgfutil@empty \else \expandafter\def\expandafter\pgfplots@checktickminmax\expandafter{% \pgfplots@checktickminmax \ifdim\pgfplots@tmpa<\csname pgfplots@#1tickmin\endcsname pt \pgfplots@tickshowfalse \fi }% \fi \expandafter\ifx\csname pgfplots@#1tickmax\endcsname\pgfutil@empty \else \expandafter\def\expandafter\pgfplots@checktickminmax\expandafter{% \pgfplots@checktickminmax \ifdim\pgfplots@tmpa>\csname pgfplots@#1tickmax\endcsname pt \pgfplots@tickshowfalse \fi }% \fi % % \foreach \x in {#2} {% \pgfplots@tmpa=\x pt % \csname pgfplots@#1tick@check@tickshow\endcsname \pgfplots@checktickminmax % \ifpgfplots@tickshow \ifdim\pgfplots@tmpa<\csname pgfplots@#1min@reg\endcsname \else \ifdim\pgfplots@tmpa>\csname pgfplots@#1max@reg\endcsname \else \expandafter\pgfplotslistpushbackglobal\x\to\pgfplots@prepared@tick@positions@major \fi \fi \fi % X-Axis ticks bottom and top % in log: % log( i*10^k ) = log\pgfplots@i + k\log10 -> draw ticks for i=1..9 \ifpgfplots@needsminorloop \foreach \pgfplots@i in {1,...,\pgfplots@minor@tick@num} {% \begingroup \ifpgfplots@islinear \pgfplots@tmpa=\pgfplots@minor@tick@dist pt % \pgfplots@tmpa=\pgfplots@i\pgfplots@tmpa \else \pgfplots@tmpa=\logi\pgfplots@i pt % \fi \edef\pgfmathresult{\the\pgfplots@tmpa}% \pgfmath@smuggleone\pgfmathresult \endgroup \advance\pgfplots@tmpa by\pgfmathresult\relax \pgfplots@tickshowtrue \pgfplots@checktickminmax \ifpgfplots@tickshow \ifdim\pgfplots@tmpa<\csname pgfplots@#1min@reg\endcsname \else \ifdim\pgfplots@tmpa>\csname pgfplots@#1max@reg\endcsname \else \edef\pgfmathresult{\pgf@sys@tonumber{\pgfplots@tmpa}}% \expandafter\pgfplotslistpushbackglobal\pgfmathresult\to\pgfplots@prepared@tick@positions@minor \fi \fi \fi }% \fi }% \fi \endgroup \expandafter\let\csname pgfplots@prepared@tick@positions@minor@#1\endcsname=\pgfplots@prepared@tick@positions@minor \expandafter\let\csname pgfplots@prepared@tick@positions@major@#1\endcsname=\pgfplots@prepared@tick@positions@major \global\let\pgfplots@prepared@tick@positions@major=\relax \global\let\pgfplots@prepared@tick@positions@minor=\relax }% % Draws grid lines at the a-positions of the currently set oriented % surface. % % Tick positions are taken out of the already precomputed list % \pgfplots@prepared@tick@positions@major@... % % See \pgfplots@drawticklines@onorientedsurf@ for a description of the % oriented surface. % % #1 : the verbatim axis name (either 'x' or 'y') % #2 : the index of the axis (either 0 or 1) \def\pgfplots@drawgridlines@onorientedsurf{% \expandafter\pgfplots@drawgridlines@onorientedsurf@\pgfplotspointonorientedsurfaceA }% \def\pgfplots@drawgridlines@onorientedsurf@#1{% \begingroup \expandafter\let\expandafter\ifpgfplots@major\csname ifpgfplots@#1majorgrids\endcsname \expandafter\let\expandafter\ifpgfplots@minor\csname ifpgfplots@#1minorgrids\endcsname % grid lines shall be drawn % if and only if BOTH adjacent axis lines shall be drawn: \pgfplots@ifaxisline@B@onorientedsurf@should@be@drawn{0}{% % remark: this is ALWAYS true for 2D plots. \pgfplots@ifaxisline@B@onorientedsurf@should@be@drawn{1}{% \def\pgfplots@drawgridlines@onorientedsurf@OK{1}% }{% \def\pgfplots@drawgridlines@onorientedsurf@OK{0}% }% }{% \def\pgfplots@drawgridlines@onorientedsurf@OK{0}% }% \if1\pgfplots@drawgridlines@onorientedsurf@OK \expandafter\let\expandafter\pgfplots@prepared@tick@positions@major@\csname pgfplots@prepared@tick@positions@major@#1\endcsname \expandafter\let\expandafter\pgfplots@prepared@tick@positions@minor@\csname pgfplots@prepared@tick@positions@minor@#1\endcsname \pgfplots@loop@CONTINUEfalse \ifpgfplots@major \pgfplots@loop@CONTINUEtrue \fi \ifpgfplots@minor \pgfplots@loop@CONTINUEtrue \fi \ifpgfplots@loop@CONTINUE \scope \pgfplots@drawtickgridlines@INSTALLCLIP@onorientedsurf#1 \ifpgfplots@major \draw[% /pgfplots/every axis grid, /pgfplots/every major grid, /pgfplots/every axis #1 grid, /pgfplots/every major #1 grid]% \pgfextra \pgfplotslistforeach\pgfplots@prepared@tick@positions@major@\as\pgfplots@curgridpos{% \pgfpathmoveto{\pgfplotspointonorientedsurfaceab{\pgfplots@curgridpos}{\csname pgfplots@\pgfplotspointonorientedsurfaceB min\endcsname}}% \pgfpathlineto{\pgfplotspointonorientedsurfaceab{\pgfplots@curgridpos}{\csname pgfplots@\pgfplotspointonorientedsurfaceB max\endcsname}}% }% \endpgfextra; \fi % \ifpgfplots@minor \draw[% /pgfplots/every axis grid, /pgfplots/every minor grid, /pgfplots/every axis #1 grid, /pgfplots/every minor #1 grid]% \pgfextra \pgfplotslistforeach\pgfplots@prepared@tick@positions@minor@\as\pgfplots@curgridpos{% \pgfpathmoveto{\pgfplotspointonorientedsurfaceab{\pgfplots@curgridpos}{\csname pgfplots@\pgfplotspointonorientedsurfaceB min\endcsname}}% \pgfpathlineto{\pgfplotspointonorientedsurfaceab{\pgfplots@curgridpos}{\csname pgfplots@\pgfplotspointonorientedsurfaceB max\endcsname}}% }% \endpgfextra; \fi \endscope \fi \fi \endgroup } % Draws ticks on the currently active "oriented surface". % % The oriented surface is two dimensional and has been initialised % with \pgfplotspointonorientedsurfaceabsetupfor*** somehow. % % The idea is now the following: % - the tick positions change along the FIRST coordinate of this % surface: % % x ---- x ---- x ---- x % --> FIRST --> % % - the tick lines are drawn along the SECOND coordinate of this % surface: % % | ---- | ---- | ---- | | SECOND % | | | | v % % for example, % \pgfplotspointonorientedsurfaceab@setupfor@xyZ{1} % \pgfplots@drawticklines@onorientedsurf % will draw ticks at x-positions designated by \pgfplots@xtick. The % small tick lines will be drawn along the y axis. For each processed % point, the z coordinate will be fixed to '1'. % % Another example: % \pgfplotspointonorientedsurfaceab@setupfor@yxZ{-1} % \pgfplots@drawticklines@onorientedsurf % will draw ticks at y-positions designated by \pgfplots@ytick. The % small tick lines will be drawn along the x axis. For each processed % point, the z coordinate will be fixed to '-1'. % % Tick positions are taken out of the already precomputed list % \pgfplots@prepared@tick@positions@major@... \def\pgfplots@drawticklines@onorientedsurf{% \expandafter\pgfplots@drawticklines@onorientedsurf@\pgfplotspointonorientedsurfaceA }% % Avoids tick lines which are too thick by introducing a clipping % region. Tick lines (and grid lines) won't extend to the left or % right of axis #1. \def\pgfplots@drawtickgridlines@INSTALLCLIP@onorientedsurf#1{% \pgfinterruptboundingbox% \begingroup \pgf@xa=5cm \edef\pgfplots@loc@TMPc{\pgf@sys@tonumber{\pgf@xa}}% \pgfmathmultiply@{\pgfplots@loc@TMPc}{\csname pgfplots@\pgfplotspointonorientedsurfaceB @inverseveclength\endcsname}% \let\pgfplots@loc@LENGTH=\pgfmathresult \pgfmathsubtract@{\csname pgfplots@\pgfplotspointonorientedsurfaceB min\endcsname}{\pgfplots@loc@LENGTH}% \let\pgfplots@loc@MIN=\pgfmathresult \pgfmathadd@{\csname pgfplots@\pgfplotspointonorientedsurfaceB max\endcsname}{\pgfplots@loc@LENGTH}% \let\pgfplots@loc@MAX=\pgfmathresult \pgfpathmoveto{\pgfplotspointonorientedsurfaceab{\csname pgfplots@#1min\endcsname}{\pgfplots@loc@MIN}}% \pgfpathlineto{\pgfplotspointonorientedsurfaceab{\csname pgfplots@#1max\endcsname}{\pgfplots@loc@MIN}}% \pgfpathlineto{\pgfplotspointonorientedsurfaceab{\csname pgfplots@#1max\endcsname}{\pgfplots@loc@MAX}}% \pgfpathlineto{\pgfplotspointonorientedsurfaceab{\csname pgfplots@#1min\endcsname}{\pgfplots@loc@MAX}}% \pgfusepath{clip}% \endgroup \endpgfinterruptboundingbox% }% \def\pgfplots@drawticklines@onorientedsurf@#1{% \scope \pgfplots@ifaxisline@B@onorientedsurf@should@be@drawn{0}{% \def\pgfplots@drawticklines@for@placecomputedtick@LOWEROK{1}% }{% \def\pgfplots@drawticklines@for@placecomputedtick@LOWEROK{0}% }% \pgfplots@ifaxisline@B@onorientedsurf@should@be@drawn{1}{% \def\pgfplots@drawticklines@for@placecomputedtick@UPPEROK{1}% }{% \def\pgfplots@drawticklines@for@placecomputedtick@UPPEROK{0}% }% \begingroup % Assemble the \pgfplots@drawticklines@for@placecomputedtick % command. \let\E=\noexpand \xdef\pgfplots@drawticklines@for@placecomputedtick{% \if\pgfplots@drawticklines@for@placecomputedtick@LOWEROK1% \E\pgfpathmoveto{\E\pgfplotspointonorientedsurfaceab{\E\pgfplots@curtickpos}{\E\pgfplots@tick@beg@a}}% \E\pgfpathlineto{\E\pgfplotspointonorientedsurfaceab{\E\pgfplots@curtickpos}{\E\pgfplots@tick@end@a}}% \fi \if\pgfplots@drawticklines@for@placecomputedtick@UPPEROK1% \ifnum\csname pgfplots@\pgfplotspointonorientedsurfaceA tickposnum\endcsname=0\relax \E\pgfpathmoveto{\E\pgfplotspointonorientedsurfaceab{\E\pgfplots@curtickpos}{\E\pgfplots@tick@beg@b}}% \E\pgfpathlineto{\E\pgfplotspointonorientedsurfaceab{\E\pgfplots@curtickpos}{\E\pgfplots@tick@end@b}}% \fi \fi }% \endgroup \expandafter\let\expandafter\ifpgfplots@major\csname ifpgfplots@#1majorticks\endcsname \expandafter\let\expandafter\ifpgfplots@minor\csname ifpgfplots@#1minorticks\endcsname \expandafter\let\expandafter\pgfplots@prepared@tick@positions@major@\csname pgfplots@prepared@tick@positions@major@#1\endcsname \expandafter\let\expandafter\pgfplots@prepared@tick@positions@minor@\csname pgfplots@prepared@tick@positions@minor@#1\endcsname \pgfplots@drawtickgridlines@INSTALLCLIP@onorientedsurf#1 \ifpgfplots@major \draw[% /pgfplots/every tick, /pgfplots/every major tick, /pgfplots/every #1 tick, /pgfplots/every major #1 tick]% \pgfextra \pgfmathparse{\pgfplots@tickwidth}% \let\pgfplots@tickwidth@=\pgfmathresult \pgfmathmultiply@{\pgfplots@tickwidth@}{\csname pgfplots@\pgfplotspointonorientedsurfaceB @inverseveclength\endcsname}% \let\pgfplots@tickwidth@=\pgfmathresult \let\pgfplots@tickwidth=\pgfmathresult \ifcase\csname pgfplots@#1tickalignnum\endcsname\relax \def\pgfplots@tick@offset{0}% \or \let\pgfplots@tick@offset=\pgfplots@tickwidth@% \or \pgfmathmultiply@{0.5}{\pgfplots@tickwidth@}% \let\pgfplots@tick@offset=\pgfmathresult% \fi \pgfplots@prepare@tick@offsets@for@{#1}{\pgfplots@tickwidth@}% \pgfplotslistforeach\pgfplots@prepared@tick@positions@major@\as\pgfplots@curtickpos{% \pgfplots@drawticklines@for@placecomputedtick }% \endpgfextra; \fi % \ifpgfplots@minor \draw[% /pgfplots/every tick, /pgfplots/every minor tick, /pgfplots/every #1 tick, /pgfplots/every minor #1 tick]% \pgfextra \pgfmathparse{\pgfplots@subtickwidth}% \let\pgfplots@subtickwidth@=\pgfmathresult \pgfmathmultiply@{\pgfplots@subtickwidth@}{\csname pgfplots@\pgfplotspointonorientedsurfaceB @inverseveclength\endcsname}% \let\pgfplots@subtickwidth@=\pgfmathresult \let\pgfplots@subtickwidth=\pgfmathresult \ifcase\csname pgfplots@#1tickalignnum\endcsname\relax \def\pgfplots@tick@offset{0}% \or \let\pgfplots@tick@offset=\pgfplots@subtickwidth@% \or \pgfmathmultiply@{0.5}{\pgfplots@subtickwidth@}% \let\pgfplots@tick@offset=\pgfmathresult% \fi \pgfplots@prepare@tick@offsets@for@{#1}{\pgfplots@subtickwidth@}% \pgfplotslistforeach\pgfplots@prepared@tick@positions@minor@\as\pgfplots@curtickpos{% \pgfplots@drawticklines@for@placecomputedtick }% \endpgfextra; \fi \endscope } % Draws tick labels at the A positions of the currently set oriented % surface. % % Tick positions are taken out of the already precomputed list % \pgfplots@prepared@tick@positions@major@... % % See \pgfplots@drawticklines@onorientedsurf@ for a description of the % oriented surface. % % #1 : the verbatim axis name (either 'x' or 'y') \def\pgfplots@drawticklabels@onorientedsurf{% \expandafter\pgfplots@drawticklabels@onorientedsurf@\pgfplotspointonorientedsurfaceA } \def\pgfplots@drawticklabels@onorientedsurf@#1{% \begingroup \expandafter\let\expandafter\ifpgfplots@major\csname ifpgfplots@#1majorticks\endcsname \expandafter\let\expandafter\ifpgfplots@islinear\csname ifpgfplots@#1islinear\endcsname \expandafter\let\expandafter\pgfplots@prepared@tick@positions@major@\csname pgfplots@prepared@tick@positions@major@#1\endcsname \pgfplotspointonorientedsurfaceabmatchaxisline{\csname pgfplots@#1ticklabelaxisspec\endcsname}{\pgfplots@ticklabelside}% \ifx\pgfplots@ticklabelside\pgfutil@empty % SKIP. The current oriented surface shall not get tick labels % for #1. \else \ifpgfplots@major \ifpgfplots@islinear \pgfplots@init@scaled@tick@for{#1}% \fi \begingroup \if\pgfplotspointonorientedsurfaceB x \def\pgfplots@tickposchoicea{\tikzset{right}}% \def\pgfplots@tickposchoiceb{\tikzset{left}}% \else \if\pgfplotspointonorientedsurfaceB y \def\pgfplots@tickposchoicea{\tikzset{above}}% \def\pgfplots@tickposchoiceb{\tikzset{below}}% \else \def\pgfplots@tickposchoicea{\tikzset{anchor=north east}}% \def\pgfplots@tickposchoiceb{\tikzset{anchor=south east}}% \fi \fi % \pgfkeys{/tikz/every node/.append style={/pgfplots/every tick label,/pgfplots/every #1 tick label}}% \ifcase\csname pgfplots@#1tickalignnum\endcsname\relax \def\pgfmathresult{0}% \or \pgfmathparse{\pgfplots@tickwidth}% \or \pgfmathmultiply{0.5}{\pgfplots@tickwidth}% \fi \expandafter\pgfmathmultiply@\expandafter{\pgfmathresult}{\csname pgfplots@\pgfplotspointonorientedsurfaceB @inverseveclength\endcsname}% \let\pgfplots@tick@offset=\pgfmathresult %-------------------------------------------------- % \ifnum\csname pgfplots@#1ticklabelaxisspec\endcsname=0 % % the choice '[xy]ticklabel pos=default': % \expandafter\let\expandafter\pgfplots@tmpposnum\csname pgfplots@#1tickposnum\endcsname % \else % \expandafter\let\expandafter\pgfplots@tmpposnum\csname pgfplots@#1ticklabelaxisspec\endcsname % \fi % \ifcase\pgfplots@tmpposnum\relax % \expandafter\let\expandafter\pgfplots@tick@origin\csname pgfplots@\pgfplotspointonorientedsurfaceB min\endcsname% % \or % \expandafter\let\expandafter\pgfplots@tick@origin\csname pgfplots@\pgfplotspointonorientedsurfaceB min\endcsname% % \or % \expandafter\let\expandafter\pgfplots@tick@origin\csname pgfplots@logical@ZERO@\pgfplotspointonorientedsurfaceB\endcsname% % \or % \expandafter\let\expandafter\pgfplots@tick@origin\csname pgfplots@\pgfplotspointonorientedsurfaceB max\endcsname% % \fi %-------------------------------------------------- \ifnum\csname pgfplots@#1axislinesnum\endcsname=2 % Centered axis lines? \expandafter\let\expandafter\pgfplots@tick@origin\csname pgfplots@logical@ZERO@\pgfplotspointonorientedsurfaceB\endcsname% % FIXME : that stuff here does not respect % '[xyz]tickpos num' keys! \pgfplots@tickposchoiceb \pgfmathsubtract@{\pgfplots@tick@origin}{\pgfplots@tick@offset}% \else \if0\pgfplots@ticklabelside \expandafter\let\expandafter\pgfplots@tick@origin\csname pgfplots@\pgfplotspointonorientedsurfaceB min\endcsname% \pgfplots@tickposchoiceb \pgfmathsubtract@{\pgfplots@tick@origin}{\pgfplots@tick@offset}% \else \if1\pgfplots@ticklabelside \expandafter\let\expandafter\pgfplots@tick@origin\csname pgfplots@\pgfplotspointonorientedsurfaceB max\endcsname% \pgfplots@tickposchoicea \pgfmathadd@{\pgfplots@tick@origin}{\pgfplots@tick@offset}% \else \pgfplots@error{Internal logic error during tick label placement (got placement character '\pgfplots@ticklabelside'). Please report this as a bug or verify your input arguments to #1ticklabel pos.}% \expandafter\let\expandafter\pgfplots@tick@origin\csname pgfplots@\pgfplotspointonorientedsurfaceB min\endcsname% \pgfplots@tickposchoiceb \pgfmathsubtract@{\pgfplots@tick@origin}{\pgfplots@tick@offset}% \fi \fi \fi % \let\pgfplots@tick@origin=\pgfmathresult% \def\pgfplots@ticknum{0}% \xdef\pgfplots@show@ticklabel@LASTTICK{}% \pgfplotslistforeachungrouped\pgfplots@prepared@tick@positions@major@\as\pgfplots@curtickpos{% \pgfplots@show@ticklabel {#1}{\pgfplots@curtickpos}(\pgfplots@curtickpos,\pgfplots@tick@origin)% {\pgfplots@ticknum}% \begingroup \c@pgf@counta=\pgfplots@ticknum\relax \advance\c@pgf@counta by1 \edef\pgfplots@ticknum{\the\c@pgf@counta}% \pgfmath@smuggleone\pgfplots@ticknum \endgroup }% \endgroup \pgfplots@draw@tick@scale@label@for #1% \fi \fi \endgroup } \newif\ifpgfplots@checkuniform@isfirst % Checks whether the argument to xtick or ytick is a UNIFORM tick % sequence. % % A uniform tick sequence is 0,...,10 and 3,4,5 and -5,-4,-2 but % NOT 0,2,4 or 4,10. % % Furthermore, any NON-integer tick arguments are also assumed to be % NOT uniform. % % INPUT: % #1: a tick argument (i.e. something which can be put to % \foreach \x in {#1}) % % OUTPUT: % \pgfplots@isuniformticktrue % or % \pgfplots@isuniformtickfalse % depending on the check. % This variable will be set globally. \def\pgfplots@checkisuniformLOGtick#1{% \begingroup \global\pgfplots@isuniformticktrue \pgfplots@checkuniform@isfirsttrue \foreach \x in {#1}{% \pgfmathmultiply@\x\reciproclogten \let\cur=\pgfmathresult % check whether % \cur - last == 1 (last = \pgfplots@glob@TMPb) \ifpgfplots@checkuniform@isfirst \global\pgfplots@checkuniform@isfirstfalse \else \pgfmathsubtract@\cur\pgfplots@glob@TMPb% \pgfmathapproxequalto@\pgfmathresult{1.0}% \ifpgfmathcomparison \else \global\pgfplots@isuniformtickfalse \breakforeach \fi \fi \global\let\pgfplots@glob@TMPb=\cur }% \endgroup } % Checks whether the linear tick sequence #1 is a uniform tick. % % It also assigns pgfplots@tick@distance@#1 as the distance. % % see \pgfplots@checkisuniformLOGtick for details. % % #1: a tick sequence (expanded) % #2: a macro which will be filled with the tick distance. This is % only valid if \pgfplots@isuniformticktrue. \def\pgfplots@checkisuniformLINEARtick#1#2{% \begingroup \global\pgfplots@isuniformticktrue \pgfplots@checkuniform@isfirsttrue \global\let\pgfplots@glob@TMPb=\pgfutil@empty \global\def\pgfplots@glob@TMPa{1}% \foreach \x in {#1}{% \ifx\pgfplots@glob@TMPb\pgfutil@empty \else \pgfmathsubtract@\x\pgfplots@glob@TMPb \ifpgfplots@checkuniform@isfirst % remember first distance h = x_1 - x_0 \global\let\pgfplots@glob@TMPa=\pgfmathresult \global\pgfplots@checkuniform@isfirstfalse \else % check whether x_i - x_{i-1} = h \pgfmathapproxequalto@\pgfmathresult\pgfplots@glob@TMPa% \ifpgfmathcomparison \else \global\pgfplots@isuniformtickfalse \breakforeach \fi \fi \fi \global\let\pgfplots@glob@TMPb=\x% }% \endgroup \let#2=\pgfplots@glob@TMPa } % helper method which computes log10*\x foreach \x in {#1}. % The result will be \xdef'ed into #2. \def\pgfplots@compute@tick@times@logten#1\to#2{% \global\let#2=\pgfutil@empty \foreach \pgfplots@loc@TMPb in {#1} {% \pgfmathmultiply@\pgfplots@loc@TMPb\logten% \ifx#2\pgfutil@empty \xdef#2{\pgfmathresult}% \else \xdef#2{#2,\pgfmathresult}% \fi }% } % Computes tick positions using the current axis limits. % % Parameters: % /pgfplots/max space between ticks % Determines the maximum space which is not filled by at least one % tick label (approximate, there is some rounding internally) % /pgfplots/try min ticks % see manual % % Idea: % We want ticks at each % { i*H, i in \Z }. % Of course, there shouldn't be TOO MUCH ticks. % % Our heuristics is to set % desirednumticks = round(ACTUAL WIDTH / (max space between ticks) ) % and generate H = (axis range) / (desirednumticks). % % Since not all step sizes H look well, restrict H to a set of allowed % step sizes such as % { 1, 1/2, 1/5, 1/10 }, % or, to be more precise: % { 1*10^e, 2*10^e, 5*10^e } % -> round to the nearest matching number! % This yields H (for example as 2*10^e). Then, compute i*H, i \in \Z % % The data scaling transformation T(x) makes things more complicated. % Now, T(x) = q * x - p and we need to check for problems with large % numbers: % - q* H = ( T(Max) - T(Min) ) / desirednumticks = q * (Max - Min) / desirednumticks. % - Using floating point arithmetics, (Max-Min)/desirednumticks (unscaled!) % is analysed to restrict H to {1*10^e, 2*10^e, 5*10^e}. % - So, we get q * H (we can't use the 'p' shift of the affine trafo here). % - The next problem is to compute { I*H, I in \Z } because % I = trunc( Min / H ) = trunc( ( T(Min) + p ) / (q*H) ). % This can be seen by Min = I*H + rest and thus T(Min) = I*q*H + q*rest -p. % The Problem: (T(min)+p ) / (q*H) can be TOO BIG for pgfmath. % -> for the data scaling case, I will use floating point % arithmetics to compute that last step. % I will acquire \pgfplots@[xy]min@unscaled@as@float here. % % % % % % For log-plots, % H in { j*log(10), j=1,2,3,... } % where the usual case should be j = 1. % % Then, the resulting tick is % TICK={MIN,MIN+H,...,MAX} % where % MIN = I*H % is chosen such that % axis minimum limit = I*H + rest; |rest| < H. % % Again, log plots follow a slightly different approach: here, % MIN = I * log(10) % is chosen such that % axis minimum limit = I*log(10) + rest; |rest| < log(10) % while H = j*log(10), j>=1. % % % PRECONDITION: % - limits are correct % - axis width/height is set correctly % % POSTCONDITION: % - Tick for axis #1 is assigned % - \ifpgfplots@determinedefaultvalues@needs@check@uniformtick is set % % REMARKS: % - this algorithms works also if the data range has been transformed % with a LINEAR transformation. % ATTENTION: as of 2008-05-15, the scaling trafo is AFFINE LINEAR. % That means we have to eliminate the 'affine' shifting before the % algorithms works correctly. \def\pgfplots@assign@default@tick@foraxis#1{% \begingroup % Shortcut-names: \expandafter\let\expandafter\ifpgfplots@is@datascaled\csname ifpgfplots@apply@datatrafo@#1\endcsname % Attention here: use UNSHIFTET scalings, see remark above \expandafter\let\expandafter\pgfplots@data@scale@trafo\csname pgfplots@datascaletrafo@#1@noshift\endcsname \expandafter\let\expandafter\pgfplots@data@scale@inverse@trafo\csname pgfplots@inverse@datascaletrafo@#1@noshift\endcsname \expandafter\let\expandafter\ifpgfplots@cur@is@linear\csname ifpgfplots@#1islinear\endcsname % \let\desirednumticks=\c@pgf@countd \let\Wr=\pgf@xc \Wr=\csname pgfplotspoint#1axislength\endcsname % r = max place without ticks in pt -> choose desirednumticks >= W/r \expandafter\expandafter\divide\Wr\axisdefaulttickwidth \pgfmathsetcount{\desirednumticks}{\Wr}% \advance\desirednumticks by1 \csname ifpgfplots@#1islinear\endcsname \expandafter\ifnum\axisdefaulttryminticks>\desirednumticks \desirednumticks=\axisdefaulttryminticks \fi \else \expandafter\ifnum\pgfplots@default@try@minticks@log>\desirednumticks \desirednumticks=\pgfplots@default@try@minticks@log\relax \fi \expandafter\ifx\csname pgfplots@#1tickten\endcsname\pgfutil@empty \else % log plot and tickten-option: provide special processing. \edef\pgfplots@loc@TMPa{\csname pgfplots@#1tickten\endcsname}% \expandafter\pgfplots@compute@tick@times@logten\pgfplots@loc@TMPa\to\pgfplots@glob@TMPa \expandafter\let\csname pgfplots@#1tick\endcsname=\pgfplots@glob@TMPa \fi \fi % \expandafter\ifx\csname pgfplots@#1tick\endcsname\pgfutil@empty % Ok, we have either log or linear axis and need default % ticks MIN,MIN+H,...,MAX. \let\MINH=\pgf@xa \let\H=\pgf@xb \let\MAX=\pgf@ya \let\MIN=\pgf@yb % compute step size 'H': \expandafter\MAX\csname pgfplots@#1max\endcsname pt \advance\MAX by0.001pt % avoid round errors %\expandafter\MIN\the\c@pgf@counta pt \expandafter\MIN\csname pgfplots@#1min\endcsname pt \H=\MAX \advance\H by-\MIN %\message{Axis limit #1: [\the\MIN:\the\MAX], diff = \the\H.}% \c@pgf@counta=\desirednumticks \advance\c@pgf@counta by-1 \divide\H by\c@pgf@counta %\message{determining ticks for #1-axis: Wr := (width/max space between ticks) = \the\Wr, desirednumticks=max(\axisdefaulttryminticks, trunc(Wr)) = \the\desirednumticks, H#1=(axis range/(desirednumticks-1)) = \the\H}% % % SEARCH for the NEXT FEASABLE H. \edef\Hmacro{\pgf@sys@tonumber\H}% \ifpgfplots@cur@is@linear % CASE LINEAR AXIS \ifpgfplots@is@datascaled % This here works if the scaling trafo is linear. \expandafter\pgfplots@data@scale@inverse@trafo\expandafter{\Hmacro}% \let\Hmacro=\pgfmathresult \else \pgfmathfloatparsenumber{\Hmacro}% \let\Hmacro=\pgfmathresult \fi \expandafter\pgfmathfloat@decompose\pgfmathresult\relax\pgfmathfloat@a@S\H\pgfmathfloat@a@E %\message{Got T^{-1}(H#1) = \Hmacro}% % modify the mantisse: \ifdim\H<2pt \ifdim\H<1.5pt \H=1.0pt \else \H=2.0pt \fi \else \ifdim\H<4.9999pt \ifdim\H<3.5pt \H=2.0pt\relax \else \H=5.0pt\relax \fi \else \ifdim\H<7.5pt \H=5.0pt\relax \else \H=1.0pt\relax \advance\pgfmathfloat@a@E by1 \fi \fi \fi \aftergroup\pgfplots@isuniformticktrue \pgfmathfloatcreate{\the\pgfmathfloat@a@S}{\pgf@sys@tonumber{\H}}{\the\pgfmathfloat@a@E}% \let\Hmacro=\pgfmathresult % The following code is carried out in floating point % arithmetics because it requires large data ranges. % % I want to compute MIN@new := I*H where I is chosen % such that MIN = I*H + rest with rest < H. % The problem is the possibly large range of MIN. I % can't work completely in the transformed datarange, % so numbers get too large. % % So, compute I := int( MIN / H ) (integer truncation) % in float arithmetics and then MIN@new := I*H \pgfmathfloatdivide@{\csname pgfplots@#1min@unscaled@as@float\endcsname}{\Hmacro}% \pgfmathfloatint@{\pgfmathresult}% \pgfmathfloatmultiply@{\pgfmathresult}{\Hmacro}% \let\MIN@new=\pgfmathresult % Ok, we are ready. % Now, convert everything into the fixed point data % range: \ifpgfplots@is@datascaled \csname pgfplots@datascaletrafo@#1\endcsname{\MIN@new}% \MIN=\pgfmathresult pt \pgfplots@data@scale@trafo\Hmacro \H=\pgfmathresult pt \else \pgfmathfloattofixed\MIN@new \MIN=\pgfmathresult pt \pgfmathfloattofixed\Hmacro \H=\pgfmathresult pt \fi % % And, since we have used finite precision, I is most % likely to large. So: subtract one H. In the worst % case, this produces one tick position too much (but % it won't be printed). \advance\MIN by-\H \else % CASE LOG AXIS % % search for the "best" H= j* log(10), j an integer. % % And prefer j=1 if that is possible (otherwise minor % ticks are not useful). \pgfmathmultiply@{\Hmacro}{\reciproclogten}% \let\Hmacrobaseten=\pgfmathresult \expandafter\H\pgfmathresult pt %\message{ [ H / log(10) = \pgfmathresult ]}% \ifdim\H<2pt \H=1pt \else \ifnum\H<1pt \H=1pt \else \expandafter\pgfmathfloor\expandafter{\pgfmathresult}% \expandafter\H\pgfmathresult pt \fi \fi \ifdim\H=1pt \aftergroup\pgfplots@isuniformticktrue \pgfplots@isuniformticktrue \else \aftergroup\pgfplots@isuniformtickfalse \pgfplots@isuniformtickfalse \fi %\message{final H=\pgf@sys@tonumber{\H} * log(10)}% \H=\logten\H\relax % Now, we want to activate the Tick set % {lowest, lowest+H, ..., highest} % % Where % lowest = I * log(10) + rest, |rest| < log(10). % this is conceptionally different from the approach for % linear axes, because H = j*log(10). % % remember the original xmin in MINH: \MINH=\MIN % % and compute I and I*log(10) here: \expandafter\MIN\reciproclogten\MIN\relax \edef\pgfmathresult{\pgf@sys@tonumber{\MIN}}% \pgfmathsetcount{\c@pgf@counta}{\pgfmathresult}% \ifdim\MIN<0pt % the truncation rounds TOWARDS 0 which is not what I want. \advance\c@pgf@counta by-1 \fi \expandafter\MIN\logten pt \multiply\MIN by\c@pgf@counta \ifpgfplots@isuniformtick \else % This here is a special case to move the first tick % near the lower axis limit. % % "Near" means either directly above or directly below ymin. % % My application example is as follows: % Let H = 2*log(10). % Furthermore, ymin = 3e-6, ymax= 8e-2. That means we can choose either % 10^{-5}, 10^{-3}, 10^{-1} % or % 10^{-4}, 10^{-2} % as ticks. Well, I prefer the first one. % % HEURISTICS: start as near to ymin as possible! % % We check here if we can come nearer to ymin if we % shift the current tick by log(10): % if( ymin - I * log(10) < 0.5*H -> use I+1, that means add log(10). % % that's equivalent to % 2*(ymin - I * log(10)) - H < 0. \advance\MINH by-\MIN \multiply\MINH by2 \advance\MINH by-\H % \ifdim\MINH<0pt \expandafter\advance\expandafter\MIN\logten pt \fi \fi \fi \MINH=\MIN \advance\MINH by\H % Ok, now it can happen that only ONE tick label is placed in % this range. % That's useless, so check for it. % % That's the case if % MIN < ORIGMIN && MAX < MIN+2 H % MIN < ORIGMIN by construction (ok, MIN <= ORIGMIN by % construction, but I don't care about this case). % So: check only the second condition. \pgfplots@tmpa=\MINH \advance\pgfplots@tmpa by\H \ifdim\MAX<\pgfplots@tmpa \aftergroup\pgfplots@isuniformtickfalse % ok, do something special. % % The idea is now to place ticks at % 10^{i*h} with properly choosen 'h'. % % So: apply basically the SAME code as above for linear % axis, just everything log 10! And keep in mind that all % coordinates are actually given as natural logarithms. \expandafter\MIN\csname pgfplots@#1min\endcsname pt \H=\MAX \advance\H by-\MIN \H=\reciproclogten\H %\message{Axis limit #1: [\the\MIN:\the\MAX], diff/log(10) = \the\H.}% \c@pgf@counta=\desirednumticks\relax \advance\c@pgf@counta by-1 \ifnum\c@pgf@counta>2 % subtract one more. This algorithm here produces more % ticks than the normal one which is designed for 10^i \advance\c@pgf@counta by-1 \fi \divide\H by\c@pgf@counta\relax %\message{determining ticks for #1-axis: Wr := (width/max space between ticks) = \the\Wr, desirednumticks=max(\axisdefaulttryminticks, trunc(Wr)) = \the\desirednumticks, H#1=(axis range/(desirednumticks-1)) = \the\H}% % % SEARCH for the NEXT FEASABLE H. \edef\Hmacro{\pgf@sys@tonumber\H}% \pgfmathfloatparsenumber{\Hmacro}% \expandafter\pgfmathfloat@decompose\pgfmathresult\relax\pgfmathfloat@a@S\H\pgfmathfloat@a@E % Determine properly snapped mantisse... \ifdim\H<2pt \ifdim\H<1.5pt \H=1.0pt \else \H=2.0pt \fi \else \ifdim\H<4.9999pt \ifdim\H<3.5pt \H=2.0pt\relax \else \H=5.0pt\relax \fi \else \ifdim\H<7.5pt \H=5.0pt\relax \else \H=1.0pt\relax \advance\pgfmathfloat@a@E by1 \fi \fi \fi \pgfmathfloatcreate{\the\pgfmathfloat@a@S}{\pgf@sys@tonumber{\H}}{\the\pgfmathfloat@a@E}% \expandafter\pgfmathfloattofixed\expandafter{\pgfmathresult}% \let\Hmacro=\pgfmathresult \H=\Hmacro pt % % Ok, our step size h for 10^{i*h} is ready! %\message{determined step size 10^{\Hmacro}}% % Now, we want to activate the Tick set {10^{i*H}, i in \Z} % compute I such that % 10^{min} = 10^{I * H + rest}; |rest| < H % -> I = round(xmin/H) % -> MIN = I * H % BUT EVERYTHING to log(10) basis! \MIN=\reciproclogten\MIN\relax \pgfmathlog@invoke@expanded\pgfmathdivide@{% {\pgf@sys@tonumber\MIN}% {\Hmacro}% }% \pgfmathsetcount{\c@pgf@counta}{\pgfmathresult}% \ifdim\MIN<0pt % the truncation rounds TOWARDS 0 which is not what I want. \advance\c@pgf@counta by-1 \fi \MIN=\H\relax \multiply\MIN by\c@pgf@counta\relax % % convert back to basis 'e': \MIN=\logten\MIN\relax \H=\logten\H\relax \MINH=\MIN\relax \advance\MINH by\H\relax \fi %\pgfplots@message{final H=\the\H.}% \xdef\pgfplots@glob@TMPa{\pgf@sys@tonumber{\MIN},\pgf@sys@tonumber{\MINH},...,\pgf@sys@tonumber{\MAX}}% \xdef\pgfplots@glob@TMPb{\pgf@sys@tonumber{\H}}% \aftergroup\pgfplots@determinedefaultvalues@needs@check@uniformtickfalse \else \expandafter\global\expandafter\let\expandafter\pgfplots@glob@TMPa\csname pgfplots@#1tick\endcsname \gdef\pgfplots@glob@TMPb{}% will be computed later, in 'check uniform tick' \aftergroup\pgfplots@determinedefaultvalues@needs@check@uniformticktrue \fi \endgroup \expandafter\let\csname pgfplots@#1tick\endcsname=\pgfplots@glob@TMPa \expandafter\let\csname pgfplots@tick@distance@#1\endcsname=\pgfplots@glob@TMPb %\pgfplots@message{pgfplots.sty: #1tick set to \csname pgfplots@#1tick\endcsname [#1min=\csname pgfplots@#1min\endcsname, #1max=\csname pgfplots@#1max\endcsname].}% } % Helper method for % \pgfplots@apply@data@scale@trafo@to@options@for % #1: the ticks % #2: the trafo macro name % #3: the output macro name \long\def\pgfplots@apply@data@scale@trafo@to@user@ticks#1#2\to#3{% \let#3=\pgfutil@empty \foreach \pgfplots@loc@TMPb in {#1} {% \pgfmathfloatparsenumber{\pgfplots@loc@TMPb}% \expandafter#2\expandafter{\pgfmathresult}% \ifx#3\pgfutil@empty \xdef#3{\pgfmathresult}% \else \xdef#3{#3,\pgfmathresult}% \fi }% % }% % Helper method for % \pgfplots@apply@data@scale@trafo@to@options@for % #1: the ticks ALREADY IN FLOAT FORMAT % #2: the trafo macro name % #3: the output macro name \long\def\pgfplots@apply@data@scale@trafo@to@user@ticks@isfloat#1#2\to#3{% \let#3=\pgfutil@empty \foreach \pgfplots@loc@TMPb in {#1} {% #2{\pgfplots@loc@TMPb}% \ifx#3\pgfutil@empty \xdef#3{\pgfmathresult}% \else \xdef#3{#3,\pgfmathresult}% \fi }% % }%