diff options
author | Karl Berry <karl@freefriends.org> | 2016-01-08 00:02:17 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2016-01-08 00:02:17 +0000 |
commit | 4e668f51370a93cc9dc26b1a11a949b50493b353 (patch) | |
tree | 85ab6891036f9a348e68f83e31c56b069332a9ca /Master/texmf-dist/tex/generic/pgfplots/pgfplotsticks.code.tex | |
parent | f2995718d3db02b5ff46d4552b9281b9761327ae (diff) |
pgfplots (7jan16)
git-svn-id: svn://tug.org/texlive/trunk@39303 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/generic/pgfplots/pgfplotsticks.code.tex')
-rw-r--r-- | Master/texmf-dist/tex/generic/pgfplots/pgfplotsticks.code.tex | 829 |
1 files changed, 544 insertions, 285 deletions
diff --git a/Master/texmf-dist/tex/generic/pgfplots/pgfplotsticks.code.tex b/Master/texmf-dist/tex/generic/pgfplots/pgfplotsticks.code.tex index facc28cbe67..76abf78a92d 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/pgfplotsticks.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/pgfplotsticks.code.tex @@ -301,6 +301,8 @@ % #5: ticknumber \def\pgfplots@show@ticklabel#1#2(#3,#4+#5)#6{% \begingroup% + \edef\pgfmathresult{#2}% + \pgfkeyslet{/pgfplots/sloped/at position}\pgfmathresult% \csname ifpgfplots@#1ticklabel@interval\endcsname % Special case for the INTERVAL feature: % we have to do additional work here. @@ -639,6 +641,11 @@ % Check if a label does not cross the x-axis \def\pgfplots@ytick@check@tickshow{% \pgfplots@tickshowtrue + % + \pgfplots@if@has@axis@shift x{% + \pgfplots@hide@obscured@ytickfalse + }{}% + % \ifpgfplots@hide@obscured@ytick \if\pgfplots@yaxislinesnum2% center \ifcase\pgfplots@xaxislinesnum\relax @@ -682,6 +689,13 @@ } \def\pgfplots@ztick@check@tickshow{% \pgfplots@tickshowtrue + % + \pgfplots@if@has@axis@shift x{% + \pgfplots@if@has@axis@shift y{% + \pgfplots@hide@obscured@ztickfalse + }{}% + }{}% + % \ifpgfplots@hide@obscured@ztick \if\pgfplots@zaxislinesnum2% center \pgfplotsmath@ifapproxequal@dim @@ -755,15 +769,13 @@ % % Assemble the \pgfplots@drawticklines@for@placecomputedtick % command. - \def\pgfplots@drawticklines@for@placecomputedtick{% - \if\pgfplots@drawticklines@for@placecomputedtick@LOWEROK1% - \pgfpathmoveto{\pgfplotspointonorientedsurfaceabwithbshift{\pgfplots@curtickpos}{\pgfplots@tick@LOWER@b}{\pgfplots@tick@LOWER@shiftbeg pt}}% - \pgfpathlineto{\pgfplotspointonorientedsurfaceabwithbshift{\pgfplots@curtickpos}{\pgfplots@tick@LOWER@b}{\pgfplots@tick@LOWER@shiftend pt}}% - \fi - \if\pgfplots@drawticklines@for@placecomputedtick@UPPEROK1% - \pgfpathmoveto{\pgfplotspointonorientedsurfaceabwithbshift{\pgfplots@curtickpos}{\pgfplots@tick@UPPER@b}{\pgfplots@tick@UPPER@shiftbeg pt}}% - \pgfpathlineto{\pgfplotspointonorientedsurfaceabwithbshift{\pgfplots@curtickpos}{\pgfplots@tick@UPPER@b}{\pgfplots@tick@UPPER@shiftend pt}}% - \fi + \def\pgfplots@drawticklines@for@placecomputedtick@LOWER{% + \pgfpathmoveto{\pgfplotspointonorientedsurfaceabwithbshift{\pgfplots@curtickpos}{\pgfplots@tick@LOWER@b}{\pgfplots@tick@LOWER@shiftbeg pt}}% + \pgfpathlineto{\pgfplotspointonorientedsurfaceabwithbshift{\pgfplots@curtickpos}{\pgfplots@tick@LOWER@b}{\pgfplots@tick@LOWER@shiftend pt}}% + }% + \def\pgfplots@drawticklines@for@placecomputedtick@UPPER{% + \pgfpathmoveto{\pgfplotspointonorientedsurfaceabwithbshift{\pgfplots@curtickpos}{\pgfplots@tick@UPPER@b}{\pgfplots@tick@UPPER@shiftbeg pt}}% + \pgfpathlineto{\pgfplotspointonorientedsurfaceabwithbshift{\pgfplots@curtickpos}{\pgfplots@tick@UPPER@b}{\pgfplots@tick@UPPER@shiftend pt}}% }% %\message{place computed tick: LOWEROK=\pgfplots@drawticklines@for@placecomputedtick@LOWEROK; UPPEROK=\pgfplots@drawticklines@for@placecomputedtick@UPPEROK.}% }% @@ -827,6 +839,11 @@ % This is just a special case for centered axis lines. \def\pgfplots@xtick@check@tickshow{% \pgfplots@tickshowtrue + % + \pgfplots@if@has@axis@shift y{% + \pgfplots@hide@obscured@xtickfalse + }{}% + % \ifpgfplots@hide@obscured@xtick \if\pgfplots@xaxislinesnum2% center \ifcase\pgfplots@yaxislinesnum\relax @@ -1217,6 +1234,64 @@ \pgfpathlineto{\pgfplotspointonorientedsurfaceab{#1}{\csname pgfplots@\pgfplotspointonorientedsurfaceB max\endcsname}}% }% +% Implements 'axis x line shift' and its friends. +% +% It is called by grid line drawing instructions, tick lines, and tick +% labels and installs a common shift. The purpose is to shift the +% _entire_ axis along the outer normal. +% +% The operation is supposed to be used when an oriented surf is +% installed. +% +% #1 used to determine the axis for which the outer normal is to be +% determined. #1 is the 'a' value of the current oriented surf, i.e. +% one of 0, 1, 2, or v. +% +% #2 same as '#1', but this here determines the 'b' value of the +% current oriented surf. +% +% exactly one of '#1' or '#2' must be 'v' such that a unique line can +% be identified. +\def\pgfplots@transformshift@along@outer@normal@on@line@of@oriented@surf#1#2{% + \if v#1% + \let\pgfplots@loc@TMPa=\pgfplotspointonorientedsurfaceA% + \if v#2% + \pgfplots@error{Exactly one of '#1' or '#2' must be 'v', not both}% + \fi + \else + \if v#2% + \let\pgfplots@loc@TMPa=\pgfplotspointonorientedsurfaceB% + \else + \pgfplots@error{One of '#1' or '#2' must be 'v'}% + \fi + \fi + % + \pgfkeysgetvalue{/pgfplots/axis \pgfplots@loc@TMPa\space line shift}\pgfplots@loc@TMPb + \ifx\pgfplots@loc@TMPb\pgfutil@empty + \else + % in this case, we KNOW that is is + % (a) parsed and + % (b) nonzero and + % (c) a dimension WITHOUT unit + % See \pgfplots@init@axis@shift + \ifpgfplots@separate@axis@lines + \else + \pgfplots@error{Internal error encountered: separate axis lines=false but axis shift found}% + \fi + \pgftransformshift{% + \expandafter\pgfqpointscale\expandafter{\pgfplots@loc@TMPb}{% + \begingroup + \pgf@process{% + \pgfplotspointonorientedsurfaceabtolinespec{#1}{#2}% + \expandafter\pgfplotspointouternormalvectorofaxis\expandafter{\pgfplotsretval}% + }% + \endgroup + }% + }% + \fi +}% +\let\pgfplots@transformshift@along@outer@normal@on@line@of@oriented@surf@orig=\pgfplots@transformshift@along@outer@normal@on@line@of@oriented@surf + % Draws ticks on the currently active "oriented surface". % % The oriented surface is two dimensional and has been initialised @@ -1384,12 +1459,29 @@ \let\pgfplots@subtickwidth@=\pgfmathresult \let\pgfplots@subtickwidth=\pgfmathresult \pgfplots@prepare@tick@offsets@for@{#1}{\pgfplots@subtickwidth@}% - \pgfplotslistforeach\pgfplots@prepared@tick@positions@minor@\as\pgfplots@curtickpos{% - \expandafter\pgfplots@prepared@tick@pos@unpack\pgfplots@curtickpos - \let\pgfplots@curtickpos=\pgfplots@tick - \pgfplotspointouternormalvectorofaxissetv{}{\pgfplots@curtickpos}% - \pgfplots@drawticklines@for@placecomputedtick - }% + \if\pgfplots@drawticklines@for@placecomputedtick@LOWEROK1% + \begingroup + \pgfplots@transformshift@along@outer@normal@on@line@of@oriented@surf v0% + \pgfplotslistforeach\pgfplots@prepared@tick@positions@minor@\as\pgfplots@curtickpos{% + \expandafter\pgfplots@prepared@tick@pos@unpack\pgfplots@curtickpos + \let\pgfplots@curtickpos=\pgfplots@tick + \pgfplotspointouternormalvectorofaxissetv{}{\pgfplots@curtickpos}% + \pgfplots@drawticklines@for@placecomputedtick@LOWER + }% + \endgroup + \fi + % + \if\pgfplots@drawticklines@for@placecomputedtick@UPPEROK1% + \begingroup + \pgfplots@transformshift@along@outer@normal@on@line@of@oriented@surf v1% + \pgfplotslistforeach\pgfplots@prepared@tick@positions@minor@\as\pgfplots@curtickpos{% + \expandafter\pgfplots@prepared@tick@pos@unpack\pgfplots@curtickpos + \let\pgfplots@curtickpos=\pgfplots@tick + \pgfplotspointouternormalvectorofaxissetv{}{\pgfplots@curtickpos}% + \pgfplots@drawticklines@for@placecomputedtick@UPPER + }% + \endgroup + \fi \endpgfextra; }{}% % @@ -1405,12 +1497,29 @@ \let\pgfplots@tickwidth@=\pgfmathresult \let\pgfplots@tickwidth=\pgfmathresult \pgfplots@prepare@tick@offsets@for@{#1}{\pgfplots@tickwidth@}% - \pgfplotslistforeach\pgfplots@prepared@tick@positions@major@\as\pgfplots@curtickpos{% - \expandafter\pgfplots@prepared@tick@pos@unpack\pgfplots@curtickpos - \let\pgfplots@curtickpos=\pgfplots@tick - \pgfplotspointouternormalvectorofaxissetv{}{\pgfplots@curtickpos}% - \pgfplots@drawticklines@for@placecomputedtick - }% + \if\pgfplots@drawticklines@for@placecomputedtick@LOWEROK1% + \begingroup + \pgfplots@transformshift@along@outer@normal@on@line@of@oriented@surf v0% + \pgfplotslistforeach\pgfplots@prepared@tick@positions@major@\as\pgfplots@curtickpos{% + \expandafter\pgfplots@prepared@tick@pos@unpack\pgfplots@curtickpos + \let\pgfplots@curtickpos=\pgfplots@tick + \pgfplotspointouternormalvectorofaxissetv{}{\pgfplots@curtickpos}% + \pgfplots@drawticklines@for@placecomputedtick@LOWER + }% + \endgroup + \fi + % + \if\pgfplots@drawticklines@for@placecomputedtick@UPPEROK1% + \begingroup + \pgfplots@transformshift@along@outer@normal@on@line@of@oriented@surf v1% + \pgfplotslistforeach\pgfplots@prepared@tick@positions@major@\as\pgfplots@curtickpos{% + \expandafter\pgfplots@prepared@tick@pos@unpack\pgfplots@curtickpos + \let\pgfplots@curtickpos=\pgfplots@tick + \pgfplotspointouternormalvectorofaxissetv{}{\pgfplots@curtickpos}% + \pgfplots@drawticklines@for@placecomputedtick@UPPER + }% + \endgroup + \fi \endpgfextra; }{}% % @@ -1551,6 +1660,7 @@ \def\pgfmathlogtologten@{\pgfplotscoordmath{#1}{log to log 10}}% % \xdef\pgfplots@show@ticklabel@LASTTICK{}% + \pgfplots@transformshift@along@outer@normal@on@line@of@oriented@surf{v}{\pgfplots@ticklabelside}% \pgfplotslistforeachungrouped\pgfplots@prepared@tick@positions@major@\as\pgfplots@curtickpos{% \expandafter\pgfplots@prepared@tick@pos@unpack\pgfplots@curtickpos \let\pgfplots@curtickpos=\pgfplots@tick @@ -1684,9 +1794,18 @@ \fi \fi \fi + % + % + % + % suppress this warning. We cannot avoid it currently. + \pgfkeysgetvalue{/pgfplots/warning/missing near ticklabel at/.@cmd}\pgfplots@loc@neartickllabel@at + \pgfkeysdef{/pgfplots/warning/missing near ticklabel at}{}% + % \pgfplots@ticklabel@maxtickdimen@prepare@for@normalvec {#1}% {\pgfplotspointouternormalvectorofticklabelaxis{#1}}% + % + \pgfkeyslet{/pgfplots/warning/missing near ticklabel at/.@cmd}\pgfplots@loc@neartickllabel@at% }% \newif\ifpgfplots@checkuniform@isfirst @@ -1792,6 +1911,400 @@ }% } +% This is part of \pgfplots@assign@default@tick@foraxis and relies on +% its temporary variables. +% +% INPUT: +% \MIN : the lower axis limit of #1 (a TeX register, in transformed range) +% \MAX : same with upper axis limit of #1 +% OUTPUT: +% \H : will contain the (transformed) distance between adjacent ticks +% \aftergroup\pgfplots@isuniformticktrue set if it applies +% +% +\def\pgfplots@ticks@compute@tick@distance#1{% + % compute step size 'H': + \H=\MAX + \advance\H by-\MIN + \ifdim\H<0pt \H=-1\H \fi +%\message{Axis limit #1: [\the\MIN:\the\MAX], diff = \the\H.^^J}% + \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^^J}% + % + % 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. + \pgfplotscoordmath{#1}{datascaletrafo noshift inverse}{\Hmacro}% + \let\Hmacro=\pgfmathresult + \else + \pgfmathfloatparsenumber{\Hmacro}% + \let\Hmacro=\pgfmathresult + \fi +%\message{Got T^{-1}(H#1) = \Hmacro^^J}% + % + \pgfplots@assign@default@tick@foraxis@normalizetickdist#1\Hmacro + \let\Hmacro=\pgfmathresult + % + % Ok, we are ready. + % Now, convert everything into the fixed point data + % range: + \ifpgfplots@is@datascaled + \pgfplotscoordmath{#1}{datascaletrafo noshift}{\Hmacro}% + \H=\pgfmathresult pt + \else + \pgfmathfloattofixed\Hmacro + \H=\pgfmathresult pt + \fi + % +%\message{snapped-to-nicest = \Hmacro^^J}% + \aftergroup\pgfplots@isuniformticktrue + \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). + \pgfmath@basic@multiply@{\Hmacro}{\pgfplots@loc@log@from@display@log@scale}% + \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=\pgfplots@loc@log@to@display@log@scale\H + \fi + % +} + +% This is part of \pgfplots@assign@default@tick@foraxis +% +% It overwrites the internal macros of +% \pgfplots@assign@default@tick@foraxis +\def\pgfplots@assign@default@tick@foraxis@autoadjust@result#1{% + \pgfplots@if{pgfplots@#1islinear}{% + \begingroup + \def\pgfplots@tick@returnval@ready{1}% + \pgfutil@ifundefined{pgfplots@assign@default@tick@foraxis@recurselevel}{% + \def\pgfplots@assign@default@tick@foraxis@recurselevel{1}% + }{% + \pgfplotsutil@advancestringcounter\pgfplots@assign@default@tick@foraxis@recurselevel + }% + \ifnum\pgfplots@assign@default@tick@foraxis@recurselevel<15 + \c@pgf@counta=\axisdefaulttryminticks\relax + \advance\c@pgf@counta by1 + \edef\axisdefaulttryminticks{\the\c@pgf@counta}% +%\message{**TOO FEW TICK LABELS FOR #1. RECURSION with try min ticks=\axisdefaulttryminticks.**^^J}% + % recurse. + \pgfplots@assign@default@tick@foraxis{#1}% + \expandafter\global\expandafter\let\expandafter\pgfplots@glob@TMPa\csname pgfplots@#1tick\endcsname + \expandafter\global\expandafter\let\expandafter\pgfplots@glob@TMPb\csname pgfplots@tick@distance@#1\endcsname + \else + \pgfplotswarning{tick computation failed}{#1}{\axisdefaulttryminticks}\pgfeov% + \def\pgfplots@tick@returnval@ready{0}% + \fi + \pgfmath@smuggleone\pgfplots@tick@returnval@ready + \endgroup + }{% + % Case logarithmic axes and too few ticks. + \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. + \MIN\csname pgfplots@#1min\endcsname pt + \H=\MAX + \advance\H by-\MIN + \ifdim\H<0pt \H=-1\H \fi + \H=\pgfplots@loc@log@from@display@log@scale \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}% + \pgfplots@assign@default@tick@foraxis@normalizetickdist#1\pgfmathresult + % + \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=\pgfplots@loc@log@from@display@log@scale \MIN + \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=\pgfplots@loc@log@to@display@log@scale\MIN\relax + \H=\pgfplots@loc@log@to@display@log@scale\H\relax + \MINH=\MIN\relax + \advance\MINH by\H\relax + }% +}% + +% The key 'xtick distance' can have any value. This routine avoids +% 'dimension too large' programmatically +\def\pgfplots@assign@default@tick@foraxis@cap#1#2{% + \ifpgfplots@is@datascaled + \pgfplotscoordmath{#1}{datascaletrafo noshift inverse}{16000}% + \let\pgfplots@loc@TMPb=\pgfmathresult + \pgfplotscoordmath{#1}{min}{\pgfplots@loc@TMPb}{#2}% + \edef\pgfplots@loc@TMPc{#2}% + \ifx\pgfplots@loc@TMPc\pgfmathresult + \def\pgfplotsretval{0}% + \else + \def\pgfplotsretval{1}% + \fi + \else + \pgfplotscoordmath{#1}{parsenumber}{16000}% + \let\pgfplots@loc@TMPb=\pgfmathresult + \pgfplotscoordmath{#1}{parsenumber}{#2}% + \let\pgfplots@loc@TMPc=\pgfmathresult + \pgfplotscoordmath{#1}{min}{\pgfplots@loc@TMPb}{\pgfplots@loc@TMPc}% + % + \ifx\pgfplots@loc@TMPc\pgfmathresult + \def\pgfplotsretval{0}% + \else + \def\pgfplotsretval{1}% + \fi + \fi + % + \ifx1\pgfplotsretval + \pgfplotswarning{dimension too large in ticks}{#1}{#2}{\pgfmathresult}\pgfeov% + \fi +} + +% This macro is NECESSARILY part of +% \pgfplots@assign@default@tick@foraxis: +% +% OUTPUT: +% \csname pgfplots@#1tick\endcsname +% \csname pgfplots@tick@distance@#1\endcsname +% FIXME : some \aftergroup trickery... +\def\pgfplots@assign@default@tick@foraxis@compute#1{% + % 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 + % + \MAX=\csname pgfplots@#1max\endcsname pt % + \advance\MAX by0.001pt % avoid round errors + %\expandafter\MIN\the\c@pgf@counta pt + \MIN=\csname pgfplots@#1min\endcsname pt % + % + \pgfkeysgetvalue{/pgfplots/#1tick distance}\Hmacro + \ifx\Hmacro\pgfutil@empty + \pgfplots@ticks@compute@tick@distance#1% + \def\b@pgfplots@ticks@computed@tick@distance@is@final{0}% + \else + % ah - a user argument. OK, prefer that one over the default: + \pgfplotscoordmath{default}{parse}{abs(\Hmacro)}% + \let\Hmacro=\pgfmathresult + \pgfplots@assign@default@tick@foraxis@cap{#1}{\Hmacro}% + \let\Hmacro=\pgfmathresult + \ifpgfplots@cur@is@linear + \ifpgfplots@is@datascaled + \pgfplotscoordmath{#1}{datascaletrafo noshift}{\pgfmathresult}% + \else + \pgfplotscoordmath{#1}{tofixed}{\pgfmathresult}% + \fi + \H=\pgfmathresult pt + \pgfplots@isuniformticktrue + \aftergroup\pgfplots@isuniformticktrue + \else + \pgfplotscoordmath{#1}{log}{\pgfmathresult}% + \let\Hmacro=\pgfmathresult + \H=\pgfmathresult pt + % + % we don't know it. check it. + \pgfplots@isuniformtickfalse + \aftergroup\pgfplots@isuniformtickfalse + \fi + \def\b@pgfplots@ticks@computed@tick@distance@is@final{1}% + \fi +%\message{Got H=\the\H\space(\Hmacro)^^J}% + % + % OK, now compute MIN/MAX : + \ifpgfplots@cur@is@linear + % 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 + % + % Now, convert everything into the fixed point data + % range: + \ifpgfplots@is@datascaled + \pgfplotscoordmath{#1}{datascaletrafo}{\MIN@new}% + \MIN=\pgfmathresult pt + \else + \pgfmathfloattofixed\MIN@new + \MIN=\pgfmathresult pt + \fi + % + % And, since we have used finite precision, I is most + % likely to be 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\relax + \else + % 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: + \MIN=\pgfplots@loc@log@from@display@log@scale \MIN + \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 + \MIN=\pgfplots@loc@log@to@display@log@scale 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 + \advance\MIN \pgfplots@loc@log@to@display@log@scale 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. +%\message{Got MIN=\pgf@sys@tonumber\MIN; H=\pgf@sys@tonumber\H; MAX=\pgf@sys@tonumber\MAX.^^J}% + \def\pgfplots@tick@returnval@ready{0}% + % + \pgfplots@tmpa=\MINH + \advance\pgfplots@tmpa by\H + \ifdim\MAX<\pgfplots@tmpa + \if1\b@pgfplots@ticks@computed@tick@distance@is@final + % OK, we cannot auto adjust tick labels -- if if there are + % too few of them. + \else + \pgfplots@assign@default@tick@foraxis@autoadjust@result#1% + \fi + \fi + % + % assert that we have at least a minimal tick distance. + % FIXME :this minimum might actually be too small... + \ifdim\MINH=\MIN + \pgfplotsthrow{dimension too small in ticks}{#1}\pgfeov% + % + % make sure that the compilation succeeds: + \H=1pt % + \advance\MINH by\H + \fi + % + \if0\pgfplots@tick@returnval@ready + \xdef\pgfplots@glob@TMPb{\pgf@sys@tonumber{\H}}% + \advance\MAX by0.5\H % avoid rounding inaccuracies: + \xdef\pgfplots@glob@TMPa{\pgf@sys@tonumber{\MIN},\pgf@sys@tonumber{\MINH},...,\pgf@sys@tonumber{\MAX}}% + \fi +%\message{final H=\the\H; returning \pgfplots@glob@TMPa.}% + \expandafter\let\csname pgfplots@#1tick\endcsname=\pgfplots@glob@TMPa + \expandafter\let\csname pgfplots@tick@distance@#1\endcsname=\pgfplots@glob@TMPb +}% + % Computes tick positions using the current axis limits. % % Parameters: @@ -1884,7 +2397,7 @@ \afterassignment\pgfplots@gobble@until@relax \desirednumticks=\the\Wr\relax \advance\desirednumticks by1 - \csname ifpgfplots@#1islinear\endcsname + \ifpgfplots@cur@is@linear \ifnum\axisdefaulttryminticks>\desirednumticks\relax \desirednumticks=\axisdefaulttryminticks\relax \fi @@ -1914,272 +2427,18 @@ \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': - \MAX=\csname pgfplots@#1max\endcsname pt % - \advance\MAX by0.001pt % avoid round errors - %\expandafter\MIN\the\c@pgf@counta pt - \MIN=\csname pgfplots@#1min\endcsname pt % - \H=\MAX - \advance\H by-\MIN - \ifdim\H<0pt \H=-1\H \fi -%\message{Axis limit #1: [\the\MIN:\the\MAX], diff = \the\H.^^J}% - \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^^J}% % - % 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. - \pgfplotscoordmath{#1}{datascaletrafo noshift inverse}{\Hmacro}% - \let\Hmacro=\pgfmathresult - \else - \pgfmathfloatparsenumber{\Hmacro}% - \let\Hmacro=\pgfmathresult - \fi -%\message{Got T^{-1}(H#1) = \Hmacro^^J}% - % - \pgfplots@assign@default@tick@foraxis@normalizetickdist#1\Hmacro - \let\Hmacro=\pgfmathresult - % -%\message{snapped-to-nicest = \Hmacro^^J}% - \aftergroup\pgfplots@isuniformticktrue - % 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 - \pgfplotscoordmath{#1}{datascaletrafo}{\MIN@new}% - \MIN=\pgfmathresult pt - \pgfplotscoordmath{#1}{datascaletrafo noshift}{\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 be 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\relax - \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). - \pgfmath@basic@multiply@{\Hmacro}{\pgfplots@loc@log@from@display@log@scale}% - \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=\pgfplots@loc@log@to@display@log@scale\H - % 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: - \MIN=\pgfplots@loc@log@from@display@log@scale \MIN - \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 - \MIN=\pgfplots@loc@log@to@display@log@scale 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 - \advance\MIN \pgfplots@loc@log@to@display@log@scale 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. + % OK, automatically compute ticks: + \pgfplots@assign@default@tick@foraxis@compute#1% % - % 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. -%\message{Got MIN=\pgf@sys@tonumber\MIN; H=\pgf@sys@tonumber\H; MAX=\pgf@sys@tonumber\MAX.^^J}% - \def\pgfplots@tick@returnval@ready{0}% - \pgfplots@tmpa=\MINH - \advance\pgfplots@tmpa by\H - \ifdim\MAX<\pgfplots@tmpa - \pgfplots@if{pgfplots@#1islinear}{% - \begingroup - \def\pgfplots@tick@returnval@ready{1}% - \pgfutil@ifundefined{pgfplots@assign@default@tick@foraxis@recurselevel}{% - \def\pgfplots@assign@default@tick@foraxis@recurselevel{1}% - }{% - \pgfplotsutil@advancestringcounter\pgfplots@assign@default@tick@foraxis@recurselevel - }% - \ifnum\pgfplots@assign@default@tick@foraxis@recurselevel<15 - \c@pgf@counta=\axisdefaulttryminticks\relax - \advance\c@pgf@counta by1 - \edef\axisdefaulttryminticks{\the\c@pgf@counta}% -%\message{**TOO FEW TICK LABELS FOR #1. RECURSION with try min ticks=\axisdefaulttryminticks.**^^J}% - % recurse. - \pgfplots@assign@default@tick@foraxis{#1}% - \expandafter\global\expandafter\let\expandafter\pgfplots@glob@TMPa\csname pgfplots@#1tick\endcsname - \expandafter\global\expandafter\let\expandafter\pgfplots@glob@TMPb\csname pgfplots@tick@distance@#1\endcsname - \else - \pgfplotswarning{tick computation failed}{#1}{\axisdefaulttryminticks}\pgfeov% - \def\pgfplots@tick@returnval@ready{0}% - \fi - \pgfmath@smuggleone\pgfplots@tick@returnval@ready - \endgroup - }{% - % Case logarithmic axes and too few ticks. - \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. - \MIN\csname pgfplots@#1min\endcsname pt - \H=\MAX - \advance\H by-\MIN - \ifdim\H<0pt \H=-1\H \fi - \H=\pgfplots@loc@log@from@display@log@scale \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}% - \pgfplots@assign@default@tick@foraxis@normalizetickdist#1\pgfmathresult - % - \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=\pgfplots@loc@log@from@display@log@scale \MIN - \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=\pgfplots@loc@log@to@display@log@scale\MIN\relax - \H=\pgfplots@loc@log@to@display@log@scale\H\relax - \MINH=\MIN\relax - \advance\MINH by\H\relax - }% - \fi -%\message{final H=\the\H.}% - \if0\pgfplots@tick@returnval@ready - \xdef\pgfplots@glob@TMPb{\pgf@sys@tonumber{\H}}% - \advance\MAX by0.5\H % avoid rounding inaccuracies: - \xdef\pgfplots@glob@TMPa{\pgf@sys@tonumber{\MIN},\pgf@sys@tonumber{\MINH},...,\pgf@sys@tonumber{\MAX}}% + \expandafter\global\expandafter\let\expandafter\pgfplots@glob@TMPa\csname pgfplots@#1tick\endcsname + \expandafter\global\expandafter\let\expandafter\pgfplots@glob@TMPb\csname pgfplots@tick@distance@#1\endcsname + \ifpgfplots@isuniformtick + \aftergroup\pgfplots@determinedefaultvalues@needs@check@uniformtickfalse + \else + % in this case, we better check... + \aftergroup\pgfplots@determinedefaultvalues@needs@check@uniformticktrue \fi - \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' |