From 1da164bf9c4fed03b30b98439a239f5a1873f9ae Mon Sep 17 00:00:00 2001 From: Karl Berry Date: Wed, 6 Aug 2014 22:47:59 +0000 Subject: pgfplots (6aug14) git-svn-id: svn://tug.org/texlive/trunk@34851 c570f23f-e606-0410-a88d-b1316a301751 --- .../pgfcontrib/pgflibraryfillbetween.code.tex | 122 ++++++++++++++++++--- 1 file changed, 106 insertions(+), 16 deletions(-) (limited to 'Master/texmf-dist/tex/generic/pgfplots/pgfcontrib/pgflibraryfillbetween.code.tex') diff --git a/Master/texmf-dist/tex/generic/pgfplots/pgfcontrib/pgflibraryfillbetween.code.tex b/Master/texmf-dist/tex/generic/pgfplots/pgfcontrib/pgflibraryfillbetween.code.tex index bf2ebd6b64d..2b1eebdcb58 100644 --- a/Master/texmf-dist/tex/generic/pgfplots/pgfcontrib/pgflibraryfillbetween.code.tex +++ b/Master/texmf-dist/tex/generic/pgfplots/pgfcontrib/pgflibraryfillbetween.code.tex @@ -48,7 +48,8 @@ % ... % end % - % 'begin' has no arguments. + % 'begin' has one arguments: the number of following single + % streams. /pgf/fill between/result stream/begin/.code=,% % % 'next ready' has macro arguments, but the macro \pgfretval @@ -108,15 +109,15 @@ \ifx#3\pgfutil@empty \pgfpathfillbetween@warning{second}% \else - \pgfpathfillbetween@invoke{result stream/begin}% % \ifpgfpathfillbetween@split \pgfpathfillbetween@compute@splitted{#2}{#3}% \else + \pgfkeys{/pgf/fill between/result stream/begin=1}% \pgfpathfillbetween@compute{#2}{#3}% \pgfpathfillbetween@invoke{result stream/next ready}% + \pgfpathfillbetween@invoke{result stream/end}% \fi - \pgfpathfillbetween@invoke{result stream/end}% \fi \fi % @@ -132,19 +133,84 @@ % 'lineto'. This excludes the first moveto. % % The motivation is that fillbetween should ignore inner movetos. +% +% UPDATE: it turned out that replacing inner movetos is necessary, but +% not sufficient. Now, this macro does more: +% - it replaces isolated inner movetos by lineto +% - if two successive inner movetos occur, it throws away the first +% one replaces the second by lineto +% - if one or more trailing movetos occur in a path, these will be +% thrown away. \def\pgfpathfillbetween@connect@inner@movetos#1{% \expandafter\pgfpathfillbetween@connect@inner@movetos@#1\pgf@stop% \let#1=\pgfretval } \def\pgfpathfillbetween@connect@inner@movetos@#1#2\pgf@stop{% \ifx#1\pgfsyssoftpath@movetotoken - \pgfutilstrreplace{\pgfsyssoftpath@movetotoken}{\pgfsyssoftpath@linetotoken}{#2}% + \pgfpathfillbetween@connect@inner@movetos@@{#2}% \expandafter\def\expandafter\pgfretval\expandafter{\expandafter\pgfsyssoftpath@movetotoken\pgfretval}% \else - \pgfutilstrreplace{\pgfsyssoftpath@movetotoken}{\pgfsyssoftpath@linetotoken}{#1#2}% + \pgfpathfillbetween@connect@inner@movetos@@{#1#2}% \fi }% +% Substitute all movetotokens by linetotokens. +% +% In addition, it should *deduplicate* movetos, i.e. +% "moveto{}{}{}" +% -> "moveto{}{}" +% +% and: trailing movetos should be discarded. +\def\pgfpathfillbetween@connect@inner@movetos@@#1{% + % this implementation is derived from \pgfutilstrreplace - it does + % almost the same as + % s/\pgfsyssoftpath@movetotoken/pgfsyssoftpath@linetotoken/g + % -> but with the extra additions of deduplication and trailing + % moveto removal. + \def\pgfretval{}% + \pgfpathfillbetween@search@and@replace@loop{#1}% +} +\def\pgfpathfillbetween@connect@inner@moveto@foundit@#1\pgfsyssoftpath@movetotoken#2#3#4{% + \ifx#4\pgf@EOI + % ah - a trailing moveto. + % In this case, we remember all until the moveto, but we omit + % the trailing moveto and its arguments. + \expandafter\def\expandafter\pgfretval\expandafter{\pgfretval #1}% + % + % ... and stop searching. + \let\pgf@loc@TMPa\relax + \else + \ifx#4\pgfsyssoftpath@movetotoken + % DEDUPLICATE: we have at least two successive movetos. + % silently skip the first moveto and its arguments and go on + % with the second moveto. + \def\pgf@loc@TMPa{\pgfpathfillbetween@connect@inner@moveto@foundit@#1\pgfsyssoftpath@movetotoken}% + \else + % substitute it by a lineto. + \expandafter\def\expandafter\pgfretval\expandafter{\pgfretval #1\pgfsyssoftpath@linetotoken{#2}{#3}}% + % + % ... continue the standard loop which skips over paths + % until the next moveto. Remember to re-insert '#4': + \def\pgf@loc@TMPa{\pgfpathfillbetween@connect@inner@moveto@foundit@@ #4}% + \fi + \fi + \pgf@loc@TMPa +}% +\def\pgfpathfillbetween@connect@inner@moveto@foundit@@#1\pgf@EOI{% + \pgfpathfillbetween@search@and@replace@loop{#1}% +}% + +\def\pgfpathfillbetween@search@and@replace@loop#1{% + \pgfutil@in@{\pgfsyssoftpath@movetotoken}{#1}% + \ifpgfutil@in@ + \def\pgf@loc@TMPa{\pgfpathfillbetween@connect@inner@moveto@foundit@ #1\pgf@EOI}% + \else + \expandafter\def\expandafter\pgfretval\expandafter{\pgfretval #1}% + \let\pgf@loc@TMPa=\relax + \fi + \pgf@loc@TMPa +}% + \def\pgfpathfillbetween@invoke#1{\pgfkeysvalueof{/pgf/fill between/#1/.@cmd}\pgfeov} \def\pgfpathfillbetween@replace@first@moveto#1#2\pgf@stop{% @@ -216,6 +282,7 @@ \pgferror{Illegal internal state encountered: the number segments induced by the intersection points of the two paths DIFFER between the first and the second path: first path has \pgfpathfilled@a@segments\space whereas the second has \pgfpathfilled@b@segments.}% \fi % + \pgfkeys{/pgf/fill between/result stream/begin=\pgfpathfilled@a@segments}% % Recombine the pairs of segments (a_i, b_i), i = 0,..., N-1 in a % filled way: \def\c@pgfpathfilled@counter{0}% @@ -230,6 +297,7 @@ % \pgfutil@advancestringcounter\c@pgfpathfilled@counter \repeatpgfmathloop + \pgfpathfillbetween@invoke{result stream/end}% } \def\pgfpathfillbetween@compute#1#2{% @@ -307,8 +375,11 @@ % % #1 a macro containing a softpath (i.e. something returned by % \pgfgetpath) +% +% SIDE--EFFECT: defines \pgfpointlastofsetpath to be the last point of path #1 \def\pgfsetpathandBB#1{% - \expandafter\pgfsetpath@protocolsizes@loop#1\pgf@stop + \let\pgfpointlastofsetpath=\pgfutil@empty + \expandafter\pgfsetpath@loop#1\pgf@stop % \pgfsetpath{#1}% }% @@ -318,8 +389,10 @@ % % #1 a macro containing a softpath (i.e. something returned by % \pgfgetpath) +% SIDE--EFFECT: defines \pgfpointlastofsetpath to be the last point of path #1 \def\pgfaddpathandBB#1{% - \expandafter\pgfsetpath@protocolsizes@loop#1\pgf@stop + \let\pgfpointlastofsetpath=\pgfutil@empty + \expandafter\pgfsetpath@loop#1\pgf@stop \pgfaddpath#1% } @@ -410,12 +483,14 @@ }% } -\def\pgfsetpath@protocolsizes@loop#1{% +% Accumulates the path's bounding box, the last moveto, and the last +% coord. +\def\pgfsetpath@loop#1{% \ifx#1\pgf@stop% \let\pgfsetpathBB@protocolsizesnext=\relax% \else% \ifx#1\pgfsyssoftpath@movetotoken% - \let\pgfsetpathBB@protocolsizesnext=\pgfsetpathBB@protocolsizestoken@simple% + \let\pgfsetpathBB@protocolsizesnext=\pgfsetpathBB@protocolsizestoken@moveto% \else% \ifx#1\pgfsyssoftpath@linetotoken% \let\pgfsetpathBB@protocolsizesnext=\pgfsetpathBB@protocolsizestoken@simple% @@ -436,16 +511,27 @@ \fi% \pgfsetpathBB@protocolsizesnext} +\def\pgfsetpathBB@protocol@lastmoveto#1#2{% + \gdef\pgfsyssoftpath@lastmoveto{{#1}{#2}}% +} + +\def\pgfsetpathBB@protocolsizestoken@moveto#1#2{% + % required for --cycle, among others: + \pgfsetpathBB@protocol@lastmoveto{#1}{#2}% + \pgfsetpathBB@protocolsizestoken@simple{#1}{#2}% +} \def\pgfsetpathBB@protocolsizestoken@simple#1#2{% + \def\pgfpointlastofsetpath{\pgfqpoint{#1}{#2}}% \pgf@protocolsizes{#1}{#2}% - \pgfsetpath@protocolsizes@loop% + \pgfsetpath@loop% } \def\pgfsetpathBB@protocolsizestoken@curveto#1#2\pgfsyssoftpath@curvetosupportbtoken#3#4\pgfsyssoftpath@curvetotoken#5#6{% + \def\pgfpointlastofsetpath{\pgfqpoint{#5}{#6}}% \pgf@protocolsizes{#1}{#2}% \pgf@protocolsizes{#3}{#4}% \pgf@protocolsizes{#5}{#6}% - \pgfsetpath@protocolsizes@loop + \pgfsetpath@loop } \def\pgfsetpathBB@protocolsizestoken@rect#1#2\pgfsyssoftpath@rectsizetoken#3#4{% @@ -455,7 +541,7 @@ \pgf@ya=#2\relax% \advance\pgf@ya by#4\relax% \pgf@protocolsizes{\pgf@xa}{\pgf@ya}% - \pgfsetpath@protocolsizes@loop + \pgfsetpath@loop }% % Defines \pgfretval to be the reversed path of #1. @@ -606,7 +692,7 @@ % the current scope), this command computes the intersection segments % for one of the input arguments. % -% On output, \pgfretval contains the number of computed segments. The +% On output, both \pgfretval and \pgfintersectionsegments contain the number of computed segments. The % segments as such can be accessed via \pgfgetintersectionsegmentpath. % % #1 : should be '1' if the FIRST argument of @@ -689,6 +775,7 @@ \pgfutil@advancestringcounter\c@pgf@path@result% \let\pgfretval=\c@pgf@path@result% \fi + \let\pgfintersectionsegments=\pgfretval }% % Defines \pgfretval to contain the desired path segment as softpath. @@ -701,12 +788,15 @@ % \pgfintersectionofpaths are requested or '2' if results for the % SECOND path are requested (compare \pgfcomputeintersectionsegments). % #2: the segment index (a number 0<= #2 < numbersegments). -% The number of segments is returned by -% \pgfcomputeintersectionsegments. +% The number of segments is \pgfintersectionsegments \def\pgfgetintersectionsegmentpath#1#2{% \pgfcomputeintersectionsegments@set@src{#1}% + \pgfmathparse{#2}% \afterassignment\pgfcomputeintersectionsegments@set@src@gobble - \c@pgf@countc=#2\relax% + \c@pgf@countc=\pgfmathresult\relax% + \ifnum\c@pgf@countc<0 + \advance\c@pgf@countc by \pgfintersectionsegments\relax + \fi \expandafter\let\expandafter\pgfretval\csname pgf@intersect@path@split@\pgf@insert@intersections@src @\the\c@pgf@countc\endcsname \ifx\pgfretval\relax \pgferror{There is no intersection segment '#2' in path '#1'}% -- cgit v1.2.3