texlive[59132] Master/texmf-dist: pgfplots (8may21)

commits+karl at tug.org commits+karl at tug.org
Sat May 8 23:05:43 CEST 2021


Revision: 59132
          http://tug.org/svn/texlive?view=revision&revision=59132
Author:   karl
Date:     2021-05-08 23:05:43 +0200 (Sat, 08 May 2021)
Log Message:
-----------
pgfplots (8may21)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/generic/pgfplots/README
    trunk/Master/texmf-dist/doc/latex/pgfplots/TeX-programming-notes.pdf
    trunk/Master/texmf-dist/doc/latex/pgfplots/pgfplots.doc.src.tar.bz2
    trunk/Master/texmf-dist/doc/latex/pgfplots/pgfplots.pdf
    trunk/Master/texmf-dist/doc/latex/pgfplots/pgfplotstable.pdf
    trunk/Master/texmf-dist/doc/latex/pgfplots/pgfplotstodo.pdf
    trunk/Master/texmf-dist/source/context/third/pgfplots/pgfplotstests.context.tar.bz2
    trunk/Master/texmf-dist/source/latex/pgfplots/pgfplotstests.tar.bz2
    trunk/Master/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable.code.tex
    trunk/Master/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrarydecorations.softclip.code.tex
    trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplots.code.tex
    trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex
    trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplotimage.code.tex
    trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplotsplothandlers.code.tex
    trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplotsstackedplots.code.tex
    trunk/Master/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.code.tex

Added Paths:
-----------
    trunk/Master/texmf-dist/doc/generic/pgfplots/license_prepcontour/
    trunk/Master/texmf-dist/doc/generic/pgfplots/license_prepcontour/COPYING
    trunk/Master/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplots.contourlua.code.tex
    trunk/Master/texmf-dist/tex/generic/pgfplots/lua/prepcontour.lua
    trunk/Master/texmf-dist/tex/generic/pgfplots/lua/prepcontour_cli.lua

Modified: trunk/Master/texmf-dist/doc/generic/pgfplots/README
===================================================================
--- trunk/Master/texmf-dist/doc/generic/pgfplots/README	2021-05-07 23:57:39 UTC (rev 59131)
+++ trunk/Master/texmf-dist/doc/generic/pgfplots/README	2021-05-08 21:05:43 UTC (rev 59132)
@@ -23,7 +23,7 @@
 and
   doc/latex/pgfplots/pgfplotstable.pdf.
 
-Copyright 2007-2020 by Christian Feuersaenger.
+Copyright 2007-2021 by Christian Feuersaenger.
 
 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
@@ -40,6 +40,13 @@
 
 
 HISTORY:
+1.18
+- new feature: 'contour lua', implemented and contributed by Francesco Poli
+- new feature: ignore empty coordinates when computing regression lines
+- new feature: improve log-regression fitting of exponential functions (using variance format=linear)
+- fixed bug #390: image plots in log mode failed to work. Also fixed issues with mesh/ordering=y varies
+- fixed bug #219: handle NaN in stacked plots
+
 1.17
 - fixed bug: restore compatibility with pgf/tikz circle syntax inside of pgfplots
 - new feature #62: 'coordinate style' which allows to associate options with individual coordinates.

Added: trunk/Master/texmf-dist/doc/generic/pgfplots/license_prepcontour/COPYING
===================================================================
--- trunk/Master/texmf-dist/doc/generic/pgfplots/license_prepcontour/COPYING	                        (rev 0)
+++ trunk/Master/texmf-dist/doc/generic/pgfplots/license_prepcontour/COPYING	2021-05-08 21:05:43 UTC (rev 59132)
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    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 2 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, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.

Modified: trunk/Master/texmf-dist/doc/latex/pgfplots/TeX-programming-notes.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/pgfplots/pgfplots.doc.src.tar.bz2
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/pgfplots/pgfplots.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/pgfplots/pgfplotstable.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/latex/pgfplots/pgfplotstodo.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/source/context/third/pgfplots/pgfplotstests.context.tar.bz2
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/source/latex/pgfplots/pgfplotstests.tar.bz2
===================================================================
(Binary files differ)

Added: trunk/Master/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplots.contourlua.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplots.contourlua.code.tex	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplots.contourlua.code.tex	2021-05-08 21:05:43 UTC (rev 59132)
@@ -0,0 +1,91 @@
+%--------------------------------------------
+%
+% 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-2021 by Christian Feuersänger.
+%
+% This program is free software: you can redistribute it and/or modify
+% it under the terms of the GNU General Public License as published by
+% the Free Software Foundation, either version 3 of the License, or
+% (at your option) any later version.
+% 
+% This program is distributed in the hope that it will be useful,
+% but WITHOUT ANY WARRANTY; without even the implied warranty of
+% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+% GNU General Public License for more details.
+% 
+% You should have received a copy of the GNU General Public License
+% along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+\ifpgfplots at LUA@supported
+	\pgfplotsutil at directlua{require("prepcontour");}
+	\pgfplotsset{
+		contour lua/.style={
+			contour external={%
+				% we decided to NOT precompute contour/levels:
+				% @before cmd=\pgfplotscontourpopulateallkeys,
+				scanline marks=required,
+				script type=lua,
+				%
+				% this library consumes FOUR coordinates...
+				script input format=x y z meta,
+				% ... and it also generates FOUR. Always read the last one
+				% as it is never subject to rounding issues within the
+				% same contour line:
+				output point meta=explicit,
+				%
+				script={
+					copylines = 0;
+					nblocks   = \if 0\ordering \pgfkeysvalueof{/pgfplots/mesh/rows}\else \pgfkeysvalueof{/pgfplots/mesh/cols}\fi;
+					nlines    = \if 0\ordering \pgfkeysvalueof{/pgfplots/mesh/cols}\else \pgfkeysvalueof{/pgfplots/mesh/rows}\fi;
+					if copylines == nil or nblocks == nil or nlines == nil then
+						io.stderr:write("failed to parse arguments");
+						os.exit(2);
+					end;
+					yvaries = \if 0\ordering 'x'\else 'y'\fi;
+					yvaries = (yvaries == 'y');
+					infile = io.open(\"\infile\", \"r\");
+					outfile = io.open(\"\outfile\", \"w\");
+					mesh = PrepcMesh.new(yvaries, nblocks, nlines, copylines, infile, outfile);
+					\ifpgfplotsplothandlercontour at corners
+					corners = true;
+					\else
+					corners = false;
+					\fi
+					\ifx\thecontourlevels\pgfutil at empty
+					mesh:autocontour(\thecontournumber, \pgfplotsmetamin, \pgfplotsmetamax, corners);
+					\else
+					levels = {\thecontourlevels};
+					for n = 1, \#levels do
+						level = tonumber(levels[n]);
+						if level then
+							mesh:contour(level, corners);
+						end;
+					end;
+					\fi
+					io.close(infile);
+					mesh:printcontours();
+					io.close(outfile);
+				},%
+				#1,%
+			},
+		}
+	}
+\else
+	% do not throw the exception at load time ... this library is
+	% included as default
+	\pgfplotsset{
+		contour lua/.code={
+			\pgfplots at error{Library 'contour lua' requires you to run in LUA mode (i.e. lualatex instead of pdflatex)}%
+		}
+	}
+\fi
+
+
+


Property changes on: trunk/Master/texmf-dist/tex/generic/pgfplots/libs/tikzlibrarypgfplots.contourlua.code.tex
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/generic/pgfplots/lua/prepcontour.lua
===================================================================
--- trunk/Master/texmf-dist/tex/generic/pgfplots/lua/prepcontour.lua	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/generic/pgfplots/lua/prepcontour.lua	2021-05-08 21:05:43 UTC (rev 59132)
@@ -0,0 +1,708 @@
+#!/usr/bin/luatex
+
+--[[
+
+prepcontour [Lua variant] - prepare contour lines (for pgfplots)
+
+Version:  1.4 (2021-02-22)
+
+Copyright (C) 2020-2021  Francesco Poli <invernomuto at paranoici.org>
+
+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 2 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, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+--]]
+
+-- class creation function
+function FpolyCreateClass()
+    local newclass = {}   -- this table is the created class (which will act
+                          -- as metatable for the instantiated objects)
+
+    newclass.__index = newclass   -- set the __index metamethod (so that
+                                  -- members missing from objects are searched
+                                  -- for in the class)
+
+    newclass.new = function (...)   -- member function that will be used to
+                                    -- instantiate a new object of this class
+        local object = setmetatable({}, newclass)   -- a table with this class
+                                                    -- set as metatable
+
+        if object.init then
+            object:init(...)   -- run the init method, if present
+        end
+
+        return object
+    end
+
+    return newclass
+end
+
+-- class for the coordinates (and meta value) of a point in 3D space
+Coord = FpolyCreateClass()
+
+function Coord:init()
+    self.x = { nil, nil, nil }  -- point x,y,z coordinates
+    self.meta = nil             -- point meta value
+end
+
+-- class for a 2D mesh of points in 3D space
+PrepcMesh = FpolyCreateClass()
+
+function PrepcMesh:init(yvaries, nblocks, nlines, copylines,
+                        input, output)
+    if yvaries then
+        self.ni = nblocks - 1  -- number of cells in the i direction
+        self.nj = nlines  - 1  -- number of cells in the j direction
+    else
+        self.ni = nlines  - 1  -- number of cells in the i direction
+        self.nj = nblocks - 1  -- number of cells in the j direction
+    end
+    self.st = self.nj + 1  -- stride (number of nodes in the j direction)
+    self.si = self.nj + 1  -- stride for done_i
+    self.sj = self.nj      -- stride for done_j
+    local cl = tonumber(copylines) or 0
+    self.is =  input or io.stdin
+    self.os = output or io.stdout
+
+    self.debug = false
+
+    local st = self.st    -- shorter name
+
+    self.coords = {}  -- mesh of nodes
+                      -- use single-index table for efficiency
+                      -- (i,j) will be mapped to [i*st+j]
+    --[[
+        The mesh of nodes represented by this table is:
+
+            nj    o  o  o  o  o  o  o  o  o  o  o  o
+
+              ^   o  o  o  o  o  o  o  o  o  o  o  o
+              |
+             2|   o  o  o  o  o  o  o  o  o  o  o  o
+              |
+             1|   o  o  o  o  o  o  o  o  o  o  o  o
+              |
+           j=0+   o  o  o  o  o  o  o  o  o  o  o  o
+
+                  +----------------------------->
+                i=0  1  2                          ni
+    --]]
+
+    -- copy the first "cl" text lines from self.is to self.os
+    for l = 1, cl do
+        self.os:write(self.is:read('L'))
+    end
+
+    -- read all the nodes
+    for bl = 0, nblocks - 1 do
+        if bl > 0 then
+            self.is:read('L')  -- this text line should be empty
+        end
+        for ln = 0, nlines - 1 do
+            if yvaries then
+                i, j = bl, ln
+            else
+                i, j = ln, bl
+            end
+            n = Coord.new()
+            n.x[1], n.x[2], n.x[3], n.meta = self.is:read('n', 'n', 'n', 'n')
+            self.coords[i*st+j] = n
+        end
+    end
+end
+
+
+--[[ begin core of the program logic ]]--
+
+-- build N contour lines between meta_min and meta_max
+function PrepcMesh:autocontour(N, meta_min, meta_max, corners, tolerance)
+    -- subdivide the meta_min÷meta_max interval into N equal sub-intervals
+    -- and pick the midpoints of those sub-intervals
+    meta_min = tonumber(meta_min)
+    meta_max = tonumber(meta_max)
+    local step     = (meta_max - meta_min)/N
+    local meta_mid = (meta_max + meta_min)/2
+    local n_mid    = (N + 1)/2
+    for n = 1, N do
+        local isoval = meta_mid + (n - n_mid)*step
+        self:contour(isoval, corners, tolerance)
+    end
+end
+
+-- build contour lines for meta==isoval
+function PrepcMesh:contour(isoval, corners, tolerance)
+    -- set relative tolerance
+    local tol = tolerance or 1e-3
+
+    -- short names
+    local st = self.st
+    local si = self.si
+    local sj = self.sj
+
+    -- local variables
+    local i, j
+
+    if self.done_i == nil then
+        self.done_i = {}  -- table of markers for i-sides
+                          -- again single-index table
+                          -- (i,j) will be mapped to [i*si+j]
+        --[[
+            The corresponding i-sides are:
+
+                nj    o--o--o--o--o--o--o--o--o--o--o--
+
+                  ^   o--o--o--o--o--o--o--o--o--o--o--
+                  |
+                 2|   o--o--o--o--o--o--o--o--o--o--o--
+                  |
+                 1|   o--o--o--o--o--o--o--o--o--o--o--
+                  |
+               j=0+   o--o--o--o--o--o--o--o--o--o--o--
+
+                      +-------------------------->
+                    i=0  1  2                      ni-1
+        --]]
+    end
+
+    if self.done_j == nil then
+        self.done_j = {}  -- table of markers for j-sides
+                          -- again single-index table
+                          -- (i,j) will be mapped to [i*sj+j]
+        --[[
+            The corresponding j-sides are:
+
+                      |  |  |  |  |  |  |  |  |  |  |  |
+              nj-1    o  o  o  o  o  o  o  o  o  o  o  o
+                      |  |  |  |  |  |  |  |  |  |  |  |
+                  ^   o  o  o  o  o  o  o  o  o  o  o  o
+                  |   |  |  |  |  |  |  |  |  |  |  |  |
+                 1|   o  o  o  o  o  o  o  o  o  o  o  o
+                  |   |  |  |  |  |  |  |  |  |  |  |  |
+               j=0+   o  o  o  o  o  o  o  o  o  o  o  o
+
+                      +----------------------------->
+                    i=0  1  2                          ni
+        --]]
+    end
+
+    if self.newcoords == nil then
+        self.newcoords = {}  -- nodes for contour lines will be placed here
+    end
+
+    -- scan all the i-sides, searching for
+    -- intersections with the level surface
+    for i = 0, self.ni - 1 do
+        for j = 0, self.nj do
+            self.done_i[i*si+j] = ((self.coords[    i*st+j].meta > isoval) ==
+                                   (self.coords[(i+1)*st+j].meta > isoval))
+            --[[
+                This is equivalent to testing the two nodes of the i-side:
+
+                    j o-----o
+                      i    i+1
+
+                If meta > isoval in both nodes, or in none of them, then
+                set done_i to true (never look again at this i-side).
+                Otherwise, set done_i to false (we have not finished with
+                this i-side, since it contains one point of a contour line).
+           --]]
+        end
+    end
+
+    -- scan all the j-sides, searching for
+    -- intersections with the level surface
+    for i = 0, self.ni do
+        for j = 0, self.nj - 1 do
+            self.done_j[i*sj+j] = ((self.coords[i*st+j  ].meta > isoval) ==
+                                   (self.coords[i*st+j+1].meta > isoval))
+            --[[
+                This is equivalent to testing the two nodes of the j-side:
+
+                  j+1 o
+                      |
+                      |
+                    j o
+                      i
+
+                Similarly, set done_j accordingly...
+           --]]
+        end
+    end
+
+    if self.debug then
+        self:show_sides(isoval)
+    end
+
+    --[[
+        We now have all the sides containing points of the meta==isoval
+        contour lines. We need to connect the points into distinct lines.
+
+        First of all, scan all the boundary sides, searching for sides
+        with done==false. For each boundary side with done==false, set
+        its done to true and build one contour line, starting from
+        the side itself and the real cell adjacent to it.
+
+        How can we specify a cell and one of its sides?
+        We can specify cell (i,j) and a side (South, West, North, East)
+
+                       N
+                 j o-------o
+                   |       |
+                 W | (i,j) | E
+                   |       |
+               j-1 o-------o
+                  i-1  S   i
+    --]]
+
+    j = 0  -- i-sides with j=0
+    for i = 0, self.ni - 1 do
+        if not self.done_i[i*si+j] then
+            self.done_i[i*si+j] = true
+            self:build_line(isoval, tol, i+1, j+1, 'S', corners)
+            if self.debug then
+                self:show_sides(isoval)
+            end
+        end
+    end
+
+    i = 0  -- j-sides with i=0
+    for j = 0, self.nj - 1 do
+        if not self.done_j[i*sj+j] then
+            self.done_j[i*sj+j] = true
+            self:build_line(isoval, tol, i+1, j+1, 'W', corners)
+            if self.debug then
+                self:show_sides(isoval)
+            end
+        end
+    end
+
+    j = self.nj  -- i-sides with j=nj
+    for i = 0, self.ni - 1 do
+        if not self.done_i[i*si+j] then
+            self.done_i[i*si+j] = true
+            self:build_line(isoval, tol, i+1, j  , 'N', corners)
+            if self.debug then
+                self:show_sides(isoval)
+            end
+        end
+    end
+
+    i = self.ni  -- j-sides with i=ni
+    for j = 0, self.nj - 1 do
+        if not self.done_j[i*sj+j] then
+            self.done_j[i*sj+j] = true
+            self:build_line(isoval, tol, i  , j+1, 'E', corners)
+            if self.debug then
+                self:show_sides(isoval)
+            end
+        end
+    end
+
+    --[[
+        Finally, scan all the internal sides, again searching for sides
+        with done==false. For each internal side with done==false, do _not_
+        alter its done value and build one contour line, starting from
+        the side itself and one of the two real cells adjacent to it.
+    --]]
+
+    -- i-sides with j=1,...,nj-1  (i-sides with j=0 are already done)
+    -- j-sides with i=1,...,ni-1  (j-sides with i=0 are already done)
+    for j = 0, self.nj - 1 do
+        for i = 0, self.ni - 1 do
+            if not self.done_i[i*si+j] then
+                self:build_line(isoval, tol, i+1, j+1, 'S', corners)
+                if self.debug then
+                    self:show_sides(isoval)
+                end
+            end
+            if not self.done_j[i*sj+j] then
+                self:build_line(isoval, tol, i  , j+1, 'E', corners)
+                if self.debug then
+                    self:show_sides(isoval)
+                end
+            end
+        end
+    end
+end
+
+-- build a single contour line
+function PrepcMesh:build_line(isoval, tol, ic, jc, side, corners)
+    -- short names
+    local st = self.st
+    local si = self.si
+    local sj = self.sj
+
+    -- local variables
+    local ia, ja, na, wa
+    local ib, jb, nb, wb
+    local ie, je, ne
+    local id, jd, nd
+    local pt, k, count, next_side
+    local cc, xi_k, eta_k, ck, above, sign_ck
+    local xi_v, eta_v, xi_0, xi_1, eta_0, eta_1
+    local next_done, next_done_idx
+
+    while true do
+        --[[
+            Start from cell (ic,jc) and its South, West, North, or East side
+
+              e         d    b         d    a    N    b    d         b
+               o-------o      o-------o      o-*-----o      o-------o
+               |       |      |       |      |       |      |       *
+               |   c   |    W |   c   |      |   c   |      |   c   | E
+               |       |      *       |      |       |      |       |
+               o----*--o      o-------o      o-------o      o-------o
+              a    S    b    a         e    e         d    e         a
+        --]]
+
+        -- find nodes a and b
+        if side == 'E' then ia = ic     else ia = ic - 1 end
+        if side == 'N' then ja = jc     else ja = jc - 1 end
+        if side == 'W' then ib = ic - 1 else ib = ic     end
+        if side == 'S' then jb = jc - 1 else jb = jc     end
+        if ia < 0 or ib > self.ni or ja < 0 or jb > self.nj then
+            self.newcoords[#self.newcoords + 1] = Coord.new()
+            break  -- out of range: abort
+        end
+        na = self.coords[ia*st+ja]                   -- node a
+        nb = self.coords[ib*st+jb]                   -- node b
+
+        -- compute the intersection point between the side
+        -- and the meta==isoval level surface
+        wa = (isoval - nb.meta)/(na.meta - nb.meta)  -- weights
+        wb = 1 - wa
+
+        pt = Coord.new()
+        for k = 1, 3 do
+            pt.x[k] = wa*na.x[k] + wb*nb.x[k]        -- intersection point
+        end
+        pt.meta = isoval
+        -- add the intersection point to the contour line
+        self.newcoords[#self.newcoords + 1] = pt
+
+        -- check the cell: if it is a phantom cell, then stop
+        if ic < 1 or ic > self.ni or jc < 1 or jc > self.nj then
+            self.newcoords[#self.newcoords + 1] = Coord.new()
+            break  -- the contour line is finished
+        end
+
+        -- find nodes e and d
+        if side == 'W' then ie = ic     else ie = ic - 1 end
+        if side == 'S' then je = jc     else je = jc - 1 end
+        if side == 'E' then id = ic - 1 else id = ic     end
+        if side == 'N' then jd = jc - 1 else jd = jc     end
+        ne = self.coords[ie*st+je]                   -- node e
+        nd = self.coords[id*st+jd]                   -- node d
+
+        -- look at the other three sides of the cell:
+        -- how many of them have done==false ?
+        count = 0
+        if side ~= 'S' and not self.done_i[(ic-1)*si+(jc-1)] then
+            count = count + 1
+            next_side = 'N'  -- next side could be the North side of the
+                             -- adjacent south cell
+        end
+        if side ~= 'W' and not self.done_j[(ic-1)*sj+(jc-1)] then
+            count = count + 1
+            next_side = 'E'  -- next side could be the East side of the
+                             -- adjacent west cell
+        end
+        if side ~= 'N' and not self.done_i[(ic-1)*si+ jc   ] then
+            count = count + 1
+            next_side = 'S'  -- next side could be the South side of the
+                             -- adjacent north cell
+        end
+        if side ~= 'E' and not self.done_j[ ic   *sj+(jc-1)] then
+            count = count + 1
+            next_side = 'W'  -- next side could be the West side of the
+                             -- adjacent east cell
+        end
+
+        --[[
+            if zero other sides have done==false, then stop
+
+                 o     o
+
+
+                 o---*-o
+        --]]
+        if count == 0 then
+            self.newcoords[#self.newcoords + 1] = Coord.new()
+            break  -- the contour line is finished
+        end
+
+        --[[
+            if exactly one other side has done==false, then
+            next_side already specifies the next side to start from
+
+                 o-*---o
+                   |
+                    \
+                 o---*-o
+
+            nothing to be done for the time being...
+        --]]
+
+        --[[
+            the surface inside the cell is thought as the bilinear
+            interpolation of the four nodes and hence mapped onto
+            a unit square in the xi,eta plane:
+
+               eta ^
+                   |               pt.x[k] = (1-xi)*(1-eta)*na.x[k] +
+                  1+------+                     xi *(1-eta)*nb.x[k] +
+                   |e    d|                  (1-xi)*   eta *ne.x[k] +
+                   |      |                     xi *   eta *nd.x[k]
+                   |a    b|
+                  0+------+------>
+                   0      1      xi
+
+            the equation of the contour line is therefore:
+            cc*xi*eta - eta_k*xi - xi_k*eta == ck
+        --]]
+        cc    = na.meta - nb.meta + nd.meta - ne.meta
+        eta_k = na.meta - nb.meta
+        xi_k  = na.meta - ne.meta
+        ck    = isoval  - na.meta
+
+        if math.abs(cc) <=
+           math.max(math.abs(tol*eta_k), math.abs(tol*xi_k)) then
+            --[[
+                cc is negligible and the contour line is
+                basically a straight line:
+                eta_k*xi + xi_k*eta + ck == 0
+            --]]
+            cc = 0
+        else
+            --[[
+                cc is non-zero (and non-negligible) and we can divide
+                both sides of the equation by cc:
+                xi*eta - (eta_k/cc)*xi - (xi_k/cc)*eta == ck/cc
+            --]]
+            xi_k  = xi_k /cc        -- let's rename the coefficients
+            eta_k = eta_k/cc
+            ck    = xi_k*eta_k + ck/cc
+            --[[
+                the contour line is an equilateral hyperbola (in the
+                xi,eta plane) with asymptotes xi == xi_k and eta == eta_k
+                and constant product ck:
+                (xi - xi_k)*(eta - eta_k) == ck
+            --]]
+            if math.abs(ck) <= math.abs(tol/2) then
+                --[[
+                    ck is negligible and the hyperbola basically
+                    degenerates into its asymptotes
+                --]]
+                ck = 0
+            end
+        end
+
+        --[[
+            if two or three other sides have done==false, then
+            choose the next side
+
+                   ?
+                 o-*---o
+                 |     * ?
+               ? *     |
+                 o---*-o
+
+        --]]
+        if count >= 2 then
+            -- how can we choose the next side?
+            --[[
+                if there's more than one side to choose from, cc is
+                necessarily non-zero (a straight line could not cross
+                more than two sides of the unit square) and the
+                center k of the hyperbola is necessarily inside the
+                cell (otherwise one hyperbola branch would be completely
+                outside the cell and the other branch could not cross
+                more than two sides)
+
+                hence, choose the next side by checking the quadrant
+                where the hyperbola branch crossing side a-b lies
+
+                   eta ^
+                       |  :
+                      1+--:---+
+                       |e :  d|
+                    ······+k······
+                       |a :  b|
+                      0+--:---+------>
+                       0  :   1      xi
+            --]]
+            if ck == 0 then      -- math.abs(ck) <= math.abs(tol/2)
+                -- choose side e-d
+                next_side = side
+            elseif ck < 0 then   -- ck < -tol/2
+                -- choose side b-d
+                if side == 'N' or side == 'S' then
+                    next_side = 'W'
+                else
+                    next_side = 'S'
+                end
+            else                 -- ck > +tol/2
+                -- choose side a-e
+                if side == 'N' or side == 'S' then
+                    next_side = 'E'
+                else
+                    next_side = 'N'
+                end
+            end
+        end
+
+        if corners then   -- enhanced corner algorithm
+
+            --[[
+                if, within the cell, the contour line is not straight
+                we can improve its representation by computing an
+                additional point: the vertex v of the hyperbola branch,
+                as long as it lies inside the cell
+            --]]
+            if cc ~= 0 then
+                -- depending on where the center k is, consider the
+                -- vertex above or below k
+                if eta_k < 0 then above = 1 else above = -1 end
+                -- also check the sign of ck
+                if ck < 0 then sign_ck = -1 else sign_ck = 1 end
+                -- compute the vertex v
+                xi_v  =  xi_k + sign_ck*above*math.sqrt(math.abs(ck))
+                eta_v = eta_k +         above*math.sqrt(math.abs(ck))
+
+                --[[
+                    the vertex will be considered inside the cell, as long as
+                    xi_0 <= xi_v <= xi_1   and    eta_0 <= eta_v <= eta_1
+                --]]
+                xi_0  =   - math.abs(tol/10)
+                xi_1  = 1 + math.abs(tol/10)
+                eta_0 =     math.abs(tol)
+                eta_1 = 1 + math.abs(tol/10)
+                -- eta_0 is meant to reject a vertex too close to side a-b
+                -- (which already has a contour line point!)
+                -- we should also reject a vertex too close to the next side
+                if next_side == side then
+                  -- next side is e-d
+                  eta_1 = 1 - math.abs(tol)
+                elseif next_side == 'W' or next_side == 'S' then
+                  -- next side is b-d
+                  xi_1  = 1 - math.abs(tol)
+                else  -- next_side == 'E' or next_side == 'N'
+                  -- next side is a-e
+                  xi_0  =     math.abs(tol)
+                end
+
+                if xi_0  <= xi_v  and xi_v  <= xi_1  and
+                   eta_0 <= eta_v and eta_v <= eta_1 then
+                    -- v is inside the cell: compute its actual coordinates
+                    pt = Coord.new()
+                    for k = 1, 3 do
+                        pt.x[k] = (1-xi_v)*(1-eta_v)*na.x[k] +
+                                     xi_v *(1-eta_v)*nb.x[k] +
+                                  (1-xi_v)*   eta_v *ne.x[k] +
+                                     xi_v *   eta_v *nd.x[k]
+                    end
+                    pt.meta = isoval
+                    -- add the vertex to the contour line
+                    self.newcoords[#self.newcoords + 1] = pt
+                end
+            end
+
+        end
+
+        -- point to done value for the next side and
+        -- determine indexes for the next cell
+        -- (the other cell adjacent to the next side)
+        if next_side == 'W' then ic = ic + 1 end
+        if next_side == 'S' then jc = jc + 1 end
+        if next_side == 'N' or next_side == 'S' then
+            next_done = self.done_i
+            next_done_idx = (ic-1)*si+(jc-1)
+        else
+            next_done = self.done_j
+            next_done_idx = (ic-1)*sj+(jc-1)
+        end
+        if next_side == 'E' then ic = ic - 1 end
+        if next_side == 'N' then jc = jc - 1 end
+
+        -- if next side is already done, then stop
+        if next_done[next_done_idx] then
+            self.newcoords[#self.newcoords + 1] = Coord.new()
+            break  -- the contour line is finished
+        end
+
+        -- set next side done to true and
+        -- iterate starting from this new side and the next cell
+        next_done[next_done_idx] = true
+        side = next_side
+    end
+end
+
+--[[ end core of the program logic ]]--
+
+
+-- print out all the contour lines
+function PrepcMesh:printcontours()
+    for n = 1, #self.newcoords do
+        if self.newcoords[n].x[1] then
+            self.os:write(string.format("%14.6g%14.6g%14.6g%14.6g\n",
+                          self.newcoords[n].x[1],
+                          self.newcoords[n].x[2],
+                          self.newcoords[n].x[3],
+                          self.newcoords[n].meta))
+        else
+            self.os:write('\n')
+        end
+    end
+end
+
+-- print a debug representation of mesh and not-done sides
+function PrepcMesh:show_sides(isoval)
+    -- short names
+    local st = self.st
+    local si = self.si
+    local sj = self.sj
+
+    self.os:write(string.format("# contour level = %.6g \n#\n", isoval))
+    for j = self.nj, 0, -1 do
+        if j <= self.nj - 1 then
+            self.os:write("#    ")
+            for i = 0, self.ni do
+                if self.done_j[i*sj+j] then
+                    self.os:write("  ")
+                else
+                    self.os:write(" *")
+                end
+            end
+            self.os:write("\n")
+        end
+        self.os:write("#     ")
+        for i = 0, self.ni do
+            if self.coords[i*st+j].meta > isoval then
+                self.os:write("•")
+            else
+                self.os:write("o")
+            end
+            if i <= self.ni - 1 then
+                if self.done_i[i*si+j] then
+                    self.os:write(" ")
+                else
+                    self.os:write("*")
+                end
+            end
+        end
+        self.os:write("\n")
+    end
+    self.os:write("#\n")
+end
+


Property changes on: trunk/Master/texmf-dist/tex/generic/pgfplots/lua/prepcontour.lua
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Added: trunk/Master/texmf-dist/tex/generic/pgfplots/lua/prepcontour_cli.lua
===================================================================
--- trunk/Master/texmf-dist/tex/generic/pgfplots/lua/prepcontour_cli.lua	                        (rev 0)
+++ trunk/Master/texmf-dist/tex/generic/pgfplots/lua/prepcontour_cli.lua	2021-05-08 21:05:43 UTC (rev 59132)
@@ -0,0 +1,97 @@
+#!/usr/bin/luatex
+
+--[[
+
+prepcontour_cli [Lua variant] - prepare contour lines (for pgfplots)
+
+Version:  1.4 (2021-02-22)
+
+Copyright (C) 2020-2021  Francesco Poli <invernomuto at paranoici.org>
+
+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 2 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, write to the Free Software Foundation, Inc.,
+51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+--]]
+
+-- directory separator ('\' for Windows, '/' for all other OSes)
+dsep = package.config:sub(1, 1)
+-- directory where the script lives
+mydir = arg[0]:match("(.*" .. dsep .. ")")
+-- add mydir to the search path for Lua loaders
+package.path = package.path .. ";" .. mydir .. "?.lua"
+-- load the module
+require "prepcontour"
+
+-- main program
+usage = "Usage: " .. arg[0] .. [[
+ CL NB NL {x|y} [VAL]... < IN > OUT
+
+where:
+CL  number of text lines to be copied from the input beginning to the output
+NB  number of text blocks to be read from the input
+NL  number of text lines included in each input block
+x|y ordering ('x' if x varies, 'y' if y varies)
+VAL level for contour lines or
+    min:n:max for n levels between min and max or
+    corners=true  to enable enhanced corner algorithm or
+    corners=false to disable it (this is the default initial state)
+IN  input file
+OUT output file
+]]
+    
+-- simplistic command-line argument parsing
+-- TODO: use a better approach (argparse? some other library?)
+if arg[4] == nil then
+    io.stderr:write(arg[0] .. ": too few arguments\n" .. usage)
+    os.exit(1)
+end
+copylines = tonumber(arg[1])
+nblocks   = tonumber(arg[2])
+nlines    = tonumber(arg[3])
+if copylines == nil or nblocks == nil or nlines == nil then
+    io.stderr:write(arg[0] .. ": failed to parse arguments\n" .. usage)
+    os.exit(2)
+end
+yvaries = arg[4]:sub(1, 1)
+if yvaries ~= 'x' and yvaries ~= 'y' then
+    io.stderr:write(arg[0] .. ": failed to parse argument '"
+                 .. arg[4] .. "'!\n" .. usage)
+    os.exit(3)
+end
+yvaries = (yvaries == 'y')
+
+mesh = PrepcMesh.new(yvaries, nblocks, nlines, copylines)
+corners = false
+for n = 5, #arg do
+    if arg[n] == 'corners=true' then
+        corners = true
+    elseif arg[n] == 'corners=false' then
+        corners = false
+    else
+        level = tonumber(arg[n])
+        if level then
+            mesh:contour(level, corners)
+        else
+            lmin, nlevels, lmax = arg[n]:match('([^%:]+)%:([^%:]+)%:([^%:]+)')
+            nlevels = math.tointeger(tonumber(nlevels))
+            lmin = tonumber(lmin)
+            lmax = tonumber(lmax)
+            if nlevels and lmin and lmax then
+                mesh:autocontour(nlevels, lmin, lmax, corners)
+            end
+        end
+    end
+end
+
+mesh:printcontours()


Property changes on: trunk/Master/texmf-dist/tex/generic/pgfplots/lua/prepcontour_cli.lua
___________________________________________________________________
Added: svn:eol-style
## -0,0 +1 ##
+native
\ No newline at end of property
Added: svn:executable
## -0,0 +1 ##
+*
\ No newline at end of property
Modified: trunk/Master/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable.code.tex	2021-05-07 23:57:39 UTC (rev 59131)
+++ trunk/Master/texmf-dist/tex/generic/pgfplots/numtable/pgfplotstable.code.tex	2021-05-08 21:05:43 UTC (rev 59132)
@@ -675,6 +675,10 @@
 	/pgfplots/table/create col/linear regression/variance/.initial=,%
 	/pgfplots/table/create col/linear regression/variance list/.initial=,%
 	/pgfplots/table/create col/linear regression/variance src/.initial=,%
+	/pgfplots/table/create col/linear regression/variance format/.is choice,%
+	/pgfplots/table/create col/linear regression/variance format/linear/.code={\def\pgfplotstable at regression@variance at format{l}},%
+	/pgfplots/table/create col/linear regression/variance format/log/.code={\def\pgfplotstable at regression@variance at format{m}},%
+	/pgfplots/table/create col/linear regression/variance format/log,%
 	/pgfplots/table/create col/linear regression/xmode/.initial=,% auto
 	/pgfplots/table/create col/linear regression/ymode/.initial=,% auto
 	/pgfplots/table/create col/quotient/.style={%
@@ -2789,48 +2793,83 @@
 		\pgfplotslistpopfront\pgfplotstable at X\to\pgfplotstable at x
 		\pgfplotslistpopfront\pgfplotstable at Y\to\pgfplotstable at y
 		%
-		\pgfplotstableparsex{\pgfplotstable at x}%
-		\let\pgfplotstable at x=\pgfmathresult
-		\expandafter\pgfplotslistpushback\pgfmathresult\to\pgfplotstable at Xparsed
-		\pgfplotstableparsey{\pgfplotstable at y}%
-		\let\pgfplotstable at y=\pgfmathresult
-		%
-		\pgfplotslistcheckempty\pgfplotstable at VARIANCE
-		\ifpgfplotslistempty
-			\pgfmathfloatcreate{1}{1.0}{0}%
-			\let\pgfplotstable at invsqr=\pgfmathresult
+		% if either the x or y entry is empty, skip this point
+		\ifx\pgfplotstable at x\pgfutil at empty
+		\else\ifx\pgfplotstable at y\pgfutil at empty
 		\else
-			\pgfplotslistpopfront\pgfplotstable at VARIANCE\to\pgfplotstable at variance
-			\pgfmathfloatparsenumber{\pgfplotstable at variance}%
-			\let\pgfplotstable at variance=\pgfmathresult
+			\pgfplotstableparsex{\pgfplotstable at x}%
+			\let\pgfplotstable at x=\pgfmathresult
+			\expandafter\pgfplotslistpushback\pgfmathresult\to\pgfplotstable at Xparsed
+			\pgfplotstableparsey{\pgfplotstable at y}%
+			\let\pgfplotstable at y=\pgfmathresult
+			%
+			\pgfplotslistcheckempty\pgfplotstable at VARIANCE
+			\ifpgfplotslistempty
+				\pgfmathfloatcreate{1}{1.0}{0}%
+				\let\pgfplotstable at variance=\pgfmathresult
+			\else
+				\pgfplotslistpopfront\pgfplotstable at VARIANCE\to\pgfplotstable at variance
+				\pgfmathfloatparsenumber{\pgfplotstable at variance}%
+				\let\pgfplotstable at variance=\pgfmathresult
+			\fi
+			%
+			% if we're in y log mode, then instead of y +- dy, we have log_b(y +- dy)
+			% which Taylor expands to log_b(y) +- dy/(y ln(b)) + O(dy^2)
+			% However, this might introduce a division-by-zero in the exceptional case
+			% where b=1 or log_b(0) = -infinity, so instead of computing 1/(dy/(y ln b))^2
+			% we will compute (y ln b)^2*1/dy^2.  Note that we don't factor out the ^2
+			% because floating point operations don't commute and the historical behavior
+			% was to compute 1/dy^2.
+			%
 			\pgfmathfloatmultiply@{\pgfplotstable at variance}{\pgfplotstable at variance}%
 			\let\pgfplotstable at sqr=\pgfmathresult
 			\pgfmathfloatreciprocal@{\pgfplotstable at sqr}%
 			\let\pgfplotstable at invsqr=\pgfmathresult
-		\fi
-		%
-		\pgfmathfloatadd@{\pgfplotstable at S}{\pgfplotstable at invsqr}%
-		\let\pgfplotstable at S=\pgfmathresult
-		%
-		\pgfmathfloatmultiply@{\pgfplotstable at x}{\pgfplotstable at invsqr}%
-		\let\pgfplots at table@accum=\pgfmathresult
-		\pgfmathfloatadd@{\pgfplotstable at Sx}{\pgfplots at table@accum}%
-		\let\pgfplotstable at Sx=\pgfmathresult
-		%
-		\pgfmathfloatmultiply@{\pgfplotstable at x}{\pgfplots at table@accum}%
-		\let\pgfplots at table@accum=\pgfmathresult
-		\pgfmathfloatadd@{\pgfplotstable at Sxx}{\pgfplots at table@accum}%
-		\let\pgfplotstable at Sxx=\pgfmathresult
-		%
-		\pgfmathfloatmultiply@{\pgfplotstable at y}{\pgfplotstable at invsqr}%
-		\let\pgfplots at table@accum=\pgfmathresult
-		\pgfmathfloatadd@{\pgfplotstable at Sy}{\pgfplots at table@accum}%
-		\let\pgfplotstable at Sy=\pgfmathresult
-		%
-		\pgfmathfloatmultiply@{\pgfplotstable at x}{\pgfplots at table@accum}%
-		\let\pgfplots at table@accum=\pgfmathresult
-		\pgfmathfloatadd@{\pgfplotstable at Sxy}{\pgfplots at table@accum}%
-		\let\pgfplotstable at Sxy=\pgfmathresult
+			\ifx\pgfplotstableparseylogbase\pgfutil at empty
+			\else
+				\if m\pgfplotstable at regression@variance at format
+					% variance format=log
+				\else
+					% variance format=linear
+					% N.B. at this point, \pgfplotstable at invsqr, \pgfplotstable at sqr, and \pgfplotstable at variance are
+					% all missing log-scaling.  We update \pgfplotstable at invsqr now, but leave \pgfplotstable at sqr
+					% and \pgfplotstable at variance alone because they are not used below this point.
+					\pgfplotstableparseyinv@{\pgfplotstable at y}% y
+					\let\pgfplotstable at tmp=\pgfmathresult
+					\pgfmathfloatmultiply@{\pgfplotstable at tmp}{\pgfplotstableparseylogofbasefloat}% y * ln(b)
+					\let\pgfplotstable at ylnb=\pgfmathresult
+					\pgfmathfloatmultiply@{\pgfplotstable at ylnb}{\pgfplotstable at ylnb}% (y * ln(b))^2
+					\let\pgfplotstable at ylnbsqr=\pgfmathresult
+					% since \pgfplotstable at invsqr is used, but \pgfplotstable at sqr and \pgfplotstable at variance are not
+					% we only need to update \pgfplotstable at invsqr
+					\pgfmathfloatmultiply@{\pgfplotstable at invsqr}{\pgfplotstable at ylnbsqr}% (y * ln(b))^2 / dy^2
+					\let\pgfplotstable at invsqr=\pgfmathresult
+				\fi
+			\fi
+			%
+			\pgfmathfloatadd@{\pgfplotstable at S}{\pgfplotstable at invsqr}%
+			\let\pgfplotstable at S=\pgfmathresult
+			%
+			\pgfmathfloatmultiply@{\pgfplotstable at x}{\pgfplotstable at invsqr}%
+			\let\pgfplots at table@accum=\pgfmathresult
+			\pgfmathfloatadd@{\pgfplotstable at Sx}{\pgfplots at table@accum}%
+			\let\pgfplotstable at Sx=\pgfmathresult
+			%
+			\pgfmathfloatmultiply@{\pgfplotstable at x}{\pgfplots at table@accum}%
+			\let\pgfplots at table@accum=\pgfmathresult
+			\pgfmathfloatadd@{\pgfplotstable at Sxx}{\pgfplots at table@accum}%
+			\let\pgfplotstable at Sxx=\pgfmathresult
+			%
+			\pgfmathfloatmultiply@{\pgfplotstable at y}{\pgfplotstable at invsqr}%
+			\let\pgfplots at table@accum=\pgfmathresult
+			\pgfmathfloatadd@{\pgfplotstable at Sy}{\pgfplots at table@accum}%
+			\let\pgfplotstable at Sy=\pgfmathresult
+			%
+			\pgfmathfloatmultiply@{\pgfplotstable at x}{\pgfplots at table@accum}%
+			\let\pgfplots at table@accum=\pgfmathresult
+			\pgfmathfloatadd@{\pgfplotstable at Sxy}{\pgfplots at table@accum}%
+			\let\pgfplotstable at Sxy=\pgfmathresult
+		\fi\fi
 	\pgfutil at repeat
 	%
 	\pgfmathparse{\pgfplotstable at S * \pgfplotstable at Sxx - \pgfplotstable at Sx *\pgfplotstable at Sx}%

Modified: trunk/Master/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrarydecorations.softclip.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrarydecorations.softclip.code.tex	2021-05-07 23:57:39 UTC (rev 59131)
+++ trunk/Master/texmf-dist/tex/generic/pgfplots/pgfcontrib/tikzlibrarydecorations.softclip.code.tex	2021-05-08 21:05:43 UTC (rev 59132)
@@ -433,6 +433,8 @@
 }
 
 \def\tikzlibsoftclip at setkey@@{%
+	\edef\tikzlibsoftclip at setkey@@reset{\noexpand\tikz at expandcount=\the\tikz at expandcount\relax}%
+	\tikz at resetexpandcount
 	%
 	\tikz at scan@one at point\tikzlibsoftclip at setkey@bb at scan@a
 }%
@@ -455,6 +457,7 @@
 \def\tikzlibsoftclip at setkey@bb at scan@b#1{%
 	\def\tikzlibsoftclip at setkey@bb at b{#1}%
 	\pgfutil at ifnextchar \pgf at stop{%
+		\tikzlibsoftclip at setkey@@reset
 		\tikzlibsoftclip at setkey@@activate
 		\tikz at gobble@until at stop
 	}{%

Modified: trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplots.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplots.code.tex	2021-05-07 23:57:39 UTC (rev 59131)
+++ trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplots.code.tex	2021-05-08 21:05:43 UTC (rev 59132)
@@ -45,6 +45,7 @@
 
 
 \usetikzlibrary{decorations,decorations.pathmorphing,decorations.pathreplacing}
+\usepgfplotslibrary{contourlua}%
 
 % FIXME: reduce number of variables!
 
@@ -4318,8 +4319,10 @@
 	/pgfplots/compat/anchors/1.15/.style= 	{/pgfplots/compat/anchors/1.13},%
 	/pgfplots/compat/anchors/1.16/.style= 	{/pgfplots/compat/anchors/1.13},%
 	/pgfplots/compat/anchors/1.17/.style= 	{/pgfplots/compat/anchors/1.13},%
+	/pgfplots/compat/anchors/1.18/.style= 	{/pgfplots/compat/anchors/1.13},%
 	/pgfplots/compat/anchors/default/.style={/pgfplots/compat/anchors/1.3},%
 	%
+	%
 	/pgfplots/compat/empty line/.is choice,
 	/pgfplots/compat/empty line/pre 1.3/.code={\pgfplots at emptyline@compattrue},% FIXME: WAS \global
 	/pgfplots/compat/empty line/1.3/.style= {/pgfplots/compat/empty line/pre 1.3},%
@@ -4338,6 +4341,7 @@
 	/pgfplots/compat/empty line/1.15/.style= 	{/pgfplots/compat/empty line/1.4},%
 	/pgfplots/compat/empty line/1.16/.style= 	{/pgfplots/compat/empty line/1.4},%
 	/pgfplots/compat/empty line/1.17/.style= 	{/pgfplots/compat/empty line/1.4},%
+	/pgfplots/compat/empty line/1.18/.style= 	{/pgfplots/compat/empty line/1.4},%
 	/pgfplots/compat/empty line/default/.style=	{/pgfplots/compat/empty line/1.4},%
 	%
 	/pgfplots/compat/path replacement/.is choice,
@@ -4358,6 +4362,7 @@
 	/pgfplots/compat/path replacement/1.15/.style=   	{/pgfplots/compat/path replacement/1.5.1},
 	/pgfplots/compat/path replacement/1.16/.style=   	{/pgfplots/compat/path replacement/1.5.1},
 	/pgfplots/compat/path replacement/1.17/.style=   	{/pgfplots/compat/path replacement/1.5.1},
+	/pgfplots/compat/path replacement/1.18/.style=   	{/pgfplots/compat/path replacement/1.5.1},
 	/pgfplots/compat/path replacement/default/.style=	{/pgfplots/compat/path replacement/pre 1.3},%
 	%
 	/pgfplots/compat/pgfpoint substitution/.is choice,
@@ -4378,6 +4383,7 @@
 	/pgfplots/compat/pgfpoint substitution/1.15/.style=   	{/pgfplots/compat/pgfpoint substitution/1.11},
 	/pgfplots/compat/pgfpoint substitution/1.16/.style=   	{/pgfplots/compat/pgfpoint substitution/1.11},
 	/pgfplots/compat/pgfpoint substitution/1.17/.style=   	{/pgfplots/compat/pgfpoint substitution/1.11},
+	/pgfplots/compat/pgfpoint substitution/1.18/.style=   	{/pgfplots/compat/pgfpoint substitution/1.11},
 	/pgfplots/compat/pgfpoint substitution/default/.style=	{/pgfplots/compat/pgfpoint substitution/pre 1.3},%
 	%ellipse/.is if=pgfplots at path@replace at ellipse,
 	%
@@ -4408,6 +4414,7 @@
 	/pgfplots/compat/labels/1.15/.style=		{/pgfplots/compat/labels/1.8},%
 	/pgfplots/compat/labels/1.16/.style=		{/pgfplots/compat/labels/1.8},%
 	/pgfplots/compat/labels/1.17/.style=		{/pgfplots/compat/labels/1.8},%
+	/pgfplots/compat/labels/1.18/.style=		{/pgfplots/compat/labels/1.8},%
 	/pgfplots/compat/labels/default/.style=	{/pgfplots/compat/labels/pre 1.3},% maintain backwards compatibility
 	%
 	/pgfplots/compat/bar nodes/.is choice,
@@ -4463,6 +4470,7 @@
 	/pgfplots/compat/bar nodes/1.15/.style=		{/pgfplots/compat/bar nodes/1.13},%
 	/pgfplots/compat/bar nodes/1.16/.style=		{/pgfplots/compat/bar nodes/1.13},%
 	/pgfplots/compat/bar nodes/1.17/.style=		{/pgfplots/compat/bar nodes/1.13},%
+	/pgfplots/compat/bar nodes/1.18/.style=		{/pgfplots/compat/bar nodes/1.13},%
 	/pgfplots/compat/bar nodes/default/.style=	{/pgfplots/compat/bar nodes/pre 1.3},% maintain backwards compatibility
 	/pgfplots/compat/bar nodes/default,
 	%
@@ -4498,6 +4506,7 @@
 	/pgfplots/compat/scaling/1.15/.style={/pgfplots/compat/scaling/1.6},
 	/pgfplots/compat/scaling/1.16/.style={/pgfplots/compat/scaling/1.6},
 	/pgfplots/compat/scaling/1.17/.style={/pgfplots/compat/scaling/1.6},
+	/pgfplots/compat/scaling/1.18/.style={/pgfplots/compat/scaling/1.6},
 	/pgfplots/compat/scaling/default/.style={/pgfplots/compat/scaling/1.4},
 	%
 	/pgfplots/compat/scale mode/.is choice,
@@ -4518,6 +4527,7 @@
 	/pgfplots/compat/scale mode/1.15/.style={/pgfplots/compat/scale mode/1.6},
 	/pgfplots/compat/scale mode/1.16/.style={/pgfplots/compat/scale mode/1.6},
 	/pgfplots/compat/scale mode/1.17/.style={/pgfplots/compat/scale mode/1.6},
+	/pgfplots/compat/scale mode/1.18/.style={/pgfplots/compat/scale mode/1.6},
 	/pgfplots/compat/scale mode/default/.style={/pgfplots/compat/scale mode/1.5},
 	%
 	%
@@ -4539,6 +4549,7 @@
 	/pgfplots/compat/plot3graphics/1.15/.style=	{/pgfplots/compat/plot3graphics/1.6},%
 	/pgfplots/compat/plot3graphics/1.16/.style=	{/pgfplots/compat/plot3graphics/1.6},%
 	/pgfplots/compat/plot3graphics/1.17/.style=	{/pgfplots/compat/plot3graphics/1.6},%
+	/pgfplots/compat/plot3graphics/1.18/.style=	{/pgfplots/compat/plot3graphics/1.6},%
 	/pgfplots/compat/plot3graphics/default/.style=	{/pgfplots/compat/plot3graphics/1.5},%
 	%
 	% ATTENTION: there is a compatibility issue which slipped through
@@ -4586,6 +4597,7 @@
 	/pgfplots/compat/bar width by units/1.15/.style=		{/pgfplots/compat/bar width by units/1.7},
 	/pgfplots/compat/bar width by units/1.16/.style=		{/pgfplots/compat/bar width by units/1.7},
 	/pgfplots/compat/bar width by units/1.17/.style=		{/pgfplots/compat/bar width by units/1.7},
+	/pgfplots/compat/bar width by units/1.18/.style=		{/pgfplots/compat/bar width by units/1.7},
 	/pgfplots/compat/bar width by units/default/.style={/pgfplots/compat/bar width by units/pre 1.3},
 	%
 	/pgfplots/compat/BB/.is choice,
@@ -4606,6 +4618,7 @@
 	/pgfplots/compat/BB/1.15/.style=	{/pgfplots/compat/BB/1.8},%
 	/pgfplots/compat/BB/1.16/.style=	{/pgfplots/compat/BB/1.8},%
 	/pgfplots/compat/BB/1.17/.style=	{/pgfplots/compat/BB/1.8},%
+	/pgfplots/compat/BB/1.18/.style=	{/pgfplots/compat/BB/1.8},%
 	/pgfplots/compat/BB/default/.style={/pgfplots/compat/BB/pre 1.3},
 	%
 	/pgfplots/compat/general/.is choice,
@@ -4670,6 +4683,7 @@
 		/pgfplots/compat/general/1.15,
 		%/pgfplots/table/percent is letter=true,
 	},%
+	/pgfplots/compat/general/1.18/.style=	{/pgfplots/compat/general/1.17},%
 	/pgfplots/compat/general/default/.style={/pgfplots/compat/general/1.11},
 	%
 	/pgfplots/enable tick line clipping/.is if=pgfplots at enable@tick at line@clipping,
@@ -4687,7 +4701,7 @@
 	/pgfplots/compat/show suggested version/.is if=pgfplots at show@suggested at version,
 	/pgfplots/compat/show suggested version=true,
 	/pgfplots/compat/current/.initial=,
-	/pgfplots/compat/mostrecent/.initial=1.17,
+	/pgfplots/compat/mostrecent/.initial=1.18,
 	/utils/exec={%
 		\pgfplotsutilforeachcommasep{%
 			/pgfplots/compat/current,%
@@ -7925,13 +7939,13 @@
 			{\csname pgfplots at environment@#2axis@\endcsname[]}%
 	}%
 	\expandafter\long\expandafter\def\csname pgfplots at environment@#2axis@\endcsname[##1]{%
-		\begin{axis}[%
+		\axis[%
 			##1,%
 			data cs=#1,%  assume that coordinates provided by \addplot are in the correct coordsystem
 			axis type=#2% active the correct axis type
 		]%
 	}%
-	\expandafter\def\csname endpgfplots at environment@#2axis\endcsname{\end{axis}}%
+	\expandafter\def\csname endpgfplots at environment@#2axis\endcsname{\endaxis}%
 	\edef\pgfplots at glob@TMPc{\expandafter\noexpand\csname #2axis\endcsname\expandafter\noexpand\csname pgfplots at environment@#2axis\endcsname}%
 	\expandafter
 	\tikzaddtikzonlycommandshortcutlet\pgfplots at glob@TMPc
@@ -11571,7 +11585,7 @@
 			\pgfplotsutil at directlua{%
 				pgfplots.gca = pgfplots.Axis.new();
 				pgfplots.gca.is3d = \pgfplots at boolval{pgfplots at threedim};
-				pgfplots.gca.clipLimits = { 
+				pgfplots.gca.clipLimits = {
 					\pgfplots at boolval{pgfplots at clip@limits at x},
 					\pgfplots at boolval{pgfplots at clip@limits at y},
 					\pgfplots at boolval{pgfplots at clip@limits at z} };

Modified: trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex	2021-05-07 23:57:39 UTC (rev 59131)
+++ trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplots.revision.tex	2021-05-08 21:05:43 UTC (rev 59132)
@@ -5,10 +5,10 @@
 \catcode`\:=12
 \catcode`\+=12
 \catcode`\-=12
-\gdef\pgfplotsrevision{1.17}
-\gdef\pgfplotsversion{1.17}
-\gdef\pgfplotsversiondatetime{2020-02-29 09:43:25 +0100}
-\gdef\pgfplotsrevisiondatetime{2020-02-29 09:43:25 +0100}
+\gdef\pgfplotsrevision{1.18}
+\gdef\pgfplotsversion{1.18}
+\gdef\pgfplotsversiondatetime{2021-05-08 12:48:32 +0200}
+\gdef\pgfplotsrevisiondatetime{2021-05-08 12:48:32 +0200}
 \gdef\pgfplots at glob@TMPa#1-#2-#3 #4\relax{#1/#2/#3}
 \xdef\pgfplotsversiondate{\expandafter\pgfplots at glob@TMPa\pgfplotsversiondatetime\relax}
 \xdef\pgfplotsrevisiondate{\expandafter\pgfplots at glob@TMPa\pgfplotsrevisiondatetime\relax}

Modified: trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplotimage.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplotimage.code.tex	2021-05-07 23:57:39 UTC (rev 59131)
+++ trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplotsmeshplotimage.code.tex	2021-05-08 21:05:43 UTC (rev 59132)
@@ -106,7 +106,10 @@
 		\else
 			\ifx\pgfplotsplothandlermesh at image@lastA\pgfutil at empty
 			\else
-				\pgfplotscoordmath{x}{parse}{\pgfplotsplothandlermesh at image@lastA - 0.5*(\pgfplotsplothandlermesh at cur - \pgfplotsplothandlermesh at image@lastA)}%
+				\pgfplotscoordmath{\pgfplotsplothandlermesh at image@A at dir}{parse}{\pgfplotsplothandlermesh at image@lastA - 0.5*(\pgfplotsplothandlermesh at cur - \pgfplotsplothandlermesh at image@lastA)}%
+				\pgfplots at if{pgfplots@\pgfplotsplothandlermesh at image@A at dir islinear}{}{%
+					\pgfplotscoordmath{\pgfplotsplothandlermesh at image@A at dir}{parsenumber}{\pgfmathresult}%
+				}
 				\let\pgfplots at current@point at xh=\pgfmathresult
 				\pgfplotsplothandlermesh at image@updatelimits at AB\pgfplots at current@point at xh\pgfplotsplothandlermesh at cur@B\pgfplots at current@point at z
 				%
@@ -120,12 +123,18 @@
 		\else
 			\ifx\pgfplotsplothandlermesh at image@lastB\pgfutil at empty
 			\else
-				\pgfplotscoordmath{y}{parse}{\pgfplotsplothandlermesh at image@lastB - 0.5*(\pgfplotsplothandlermesh at cur@B - \pgfplotsplothandlermesh at image@lastB)}%
+				\pgfplotscoordmath{\pgfplotsplothandlermesh at image@B at dir}{parse}{\pgfplotsplothandlermesh at image@lastB - 0.5*(\pgfplotsplothandlermesh at cur@B - \pgfplotsplothandlermesh at image@lastB)}%
+				\pgfplots at if{pgfplots@\pgfplotsplothandlermesh at image@B at dir islinear}{}{%
+					\pgfplotscoordmath{\pgfplotsplothandlermesh at image@B at dir}{parsenumber}{\pgfmathresult}%
+				}
 				\let\pgfplots at current@point at yh=\pgfmathresult
 				\pgfplotsplothandlermesh at image@updatelimits at AB\pgfplotsplothandlermesh at cur\pgfplots at current@point at yh\pgfplots at current@point at z
 				%
 				%
-				\pgfplotscoordmath{y}{parse}{\pgfplotsplothandlermesh at cur@B + 0.5*(\pgfplotsplothandlermesh at cur@B - \pgfplotsplothandlermesh at image@lastB)}%
+				\pgfplotscoordmath{\pgfplotsplothandlermesh at image@B at dir}{parse}{\pgfplotsplothandlermesh at cur@B + 0.5*(\pgfplotsplothandlermesh at cur@B - \pgfplotsplothandlermesh at image@lastB)}%
+				\pgfplots at if{pgfplots@\pgfplotsplothandlermesh at image@B at dir islinear}{}{%
+					\pgfplotscoordmath{\pgfplotsplothandlermesh at image@B at dir}{parsenumber}{\pgfmathresult}%
+				}
 				\let\pgfplots at current@point at yh=\pgfmathresult
 				\pgfplotsplothandlermesh at image@updatelimits at AB\pgfplotsplothandlermesh at cur\pgfplots at current@point at yh\pgfplots at current@point at z
 				%
@@ -145,7 +154,10 @@
 		\ifx\pgfplotsplothandlermesh at image@lastA\pgfutil at empty
 		\else
 			\expandafter\let\expandafter\pgfplotsplothandlermesh at cur@B\csname pgfplots at current@point@\pgfplotsplothandlermesh at image@B at dir\endcsname
-			\pgfplotscoordmath{x}{parse}{\pgfplotsplothandlermesh at image@lastA + 0.5*(\pgfplotsplothandlermesh at image@lastA - \pgfplotsplothandlermesh at image@lastlastA)}%
+			\pgfplotscoordmath{\pgfplotsplothandlermesh at image@A at dir}{parse}{\pgfplotsplothandlermesh at image@lastA + 0.5*(\pgfplotsplothandlermesh at image@lastA - \pgfplotsplothandlermesh at image@lastlastA)}%
+			\pgfplots at if{pgfplots@\pgfplotsplothandlermesh at image@A at dir islinear}{}{%
+				\pgfplotscoordmath{\pgfplotsplothandlermesh at image@A at dir}{parsenumber}{\pgfmathresult}%
+			}
 			\let\pgfplots at current@point at xh=\pgfmathresult
 			\pgfplotsplothandlermesh at image@updatelimits at AB\pgfplots at current@point at xh\pgfplotsplothandlermesh at cur@B\pgfplots at current@point at z
 		\fi

Modified: trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplotsplothandlers.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplotsplothandlers.code.tex	2021-05-07 23:57:39 UTC (rev 59131)
+++ trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplotsplothandlers.code.tex	2021-05-08 21:05:43 UTC (rev 59132)
@@ -1952,6 +1952,7 @@
 
 \newif\ifpgfplotsplothandlercontour at labels
 \newif\ifpgfplotsplothandlercontour at filled
+\newif\ifpgfplotsplothandlercontour at corners
 
 \def\pgfplotsplothandlercontour at axis@set at inverse#1#2#3#4{%
 	\pgfplotsutilifstringequal{#1}{#4}{%
@@ -2041,6 +2042,8 @@
 	contour/contour label style/.style={
 		/pgfplots/contour/every contour label/.append style={#1}},
 	%
+	contour/corners/.is if=pgfplotsplothandlercontour at corners,
+	contour/corners=false,
 	%
 	%  Styles to actually *compute* the contour.
 	%  These are mostly placeholders here: As long as the
@@ -2090,6 +2093,16 @@
 	contour external/script extension/.initial=script,
 	contour external/script/.initial=,% not yet initialised
 	contour external/cmd/.initial=,% not yet initialised
+	contour external/script type/.is choice=,%
+	contour external/script type/system call/.code={\def\pgfplotsplothandlercontourexternal at script@type{S}},%
+	contour external/script type/lua/.code={\def\pgfplotsplothandlercontourexternal at script@type{L}\pgfkeyssetvalue{/pgfplots/contour external/script extension}{lua}},%
+	contour external/script type/system call,%
+	contour external/script input format/.is choice,%
+	contour external/script input format/x y meta meta/.code={\def\pgfplotsplothandlercontourexternal at script@input at format{M}},%
+	contour external/script input format/x y z meta/.code={\def\pgfplotsplothandlercontourexternal at script@input at format{Z}},%
+	contour external/script input format=x y meta meta,%
+	contour external/@before cmd/.initial=,
+	contour external/@after cmd/.initial=,
 	contour external/.search also=/pgfplots/contour,
 	contour gnuplot/.style={
 		contour external={%
@@ -2684,6 +2697,7 @@
 	\else
 		\pgfplotsset{plot to file/scanline marks/if in input}% the choice 'always' is unaware of existing end-of-scanline marks
 	\fi
+	%
 	\pgfplotsplothandlertofile{\pgfplotsplothandlercontourexternal at file.dat}%
 	\pgfplotsplothandlersurveystart
 	\let\pgfplotsplothandlersurveypoint at tofile=\pgfplotsplothandlersurveypoint
@@ -2694,6 +2708,10 @@
 	\pgfplotsplothandlersurveypoint at contour@prepare at axes x%
 	\pgfplotsplothandlersurveypoint at contour@prepare at axes y%
 	\pgfplotsplothandlersurveypoint at contour@prepare at axes z%
+	%
+	\global\let\pgfplotsplothandlercontourexternal at metamin=\relax
+	\global\let\pgfplotsplothandlercontourexternal at metamax=\relax
+	%
 }%
 
 % #1: either x, y, or z
@@ -2745,22 +2763,39 @@
 }%
 
 \def\pgfplotsplothandlersurveypoint at contourexternal{%
-	% temporarily disable updates to point meta limits. They should be
-	% updated during the contour prepared processing.
-	\let\pgfplotsplothandlercontourexternal at orig@perpointlimits at limits=\pgfplots at set@perpointmeta at limits
-	\let\pgfplots at set@perpointmeta at limits=\relax
+	\ifx\pgfplotsplothandlercontourexternal at metamin\relax
+		% remember values. We want to restore them right before we parse the output of contour external:
+		\global\let\pgfplotsplothandlercontourexternal at metamin=\pgfplots at metamin
+		\global\let\pgfplotsplothandlercontourexternal at metamax=\pgfplots at metamax
+	\fi
+	\pgfplotsplothandlersurveypoint at contour@axes at std@to at reordered
 	%
 	\pgfplotsaxissurveysetpointmeta
-	\let\pgfplots at current@point at z=\pgfplots at current@point at meta
 	%
-	\let\pgfplots at set@perpointmeta at limits=\pgfplotsplothandlercontourexternal at orig@perpointlimits at limits
+	\if M\pgfplotsplothandlercontourexternal at script@input at format
+		\let\pgfplots at current@point at z=\pgfplots at current@point at meta
+	\fi
 	%
-	\pgfplotsplothandlersurveypoint at contour@axes at std@to at reordered
 	%
-%\message{contour gnuplot: collecting point (\pgfplots at current@point at x,\pgfplots at current@point at y,\pgfplots at current@point at z) [\pgfplots at current@point at meta]...}%
+%\message{contour external collecting point (\pgfplots at current@point at x,\pgfplots at current@point at y,\pgfplots at current@point at z) [\pgfplots at current@point at meta]...}%
 	\pgfplotsplothandlersurveypoint at tofile
 }%
 
+% Utility function which is NOT normally invoked. It can be invoked inside of 'contour external/@before cmd'. Should it become the default?
+\def\pgfplotscontourpopulateallkeys{%
+	\pgfkeysgetvalue{/pgfplots/contour/levels}\pgfplots at loc@TMPa
+	\ifx\pgfplots at loc@TMPa\pgfutil at empty
+		\ifx\pgfplots at metamax\pgfutil at empty
+		\else
+			\edef\pgfplots at loc@TMPa{\pgfplots at metamin:\pgfplots at metamax}%
+			\edef\thecontournumber{\pgfkeysvalueof{/pgfplots/contour/number}}%
+			\expandafter\pgfplots at domain@to at foreach\pgfplots at loc@TMPa\relax{\thecontournumber}%
+			\expandafter\pgfplots at foreach@to at list@macro\expandafter{\pgfplotsretval}%
+			\pgfkeyslet{/pgfplots/contour/levels}\pgfplotsretval
+		\fi
+	\fi
+}%
+
 {
 \catcode`\`=12
 \catcode`\'=12
@@ -2777,6 +2812,7 @@
 		\fi
 	\fi
 	%
+	\pgfkeysvalueof{/pgfplots/contour external/@before cmd}\relax%
 	\begingroup
 	\let\numcoords=\pgfplots at current@point at coordindex%
 	\pgfplotsautocompletemeshkeys
@@ -2790,7 +2826,25 @@
 	\edef\ordering{\pgfplots at plot@mesh at ordering}%
 	\edef\infile{\pgfplotsplothandlercontourexternal at file.dat}%
 	\edef\outfile{\pgfplotsplothandlercontourexternal at file.table}%
-	\edef\script{\pgfplotsplothandlercontourexternal at file.\pgfkeysvalueof{/pgfplots/contour external/script extension}}%
+	%
+	\pgfkeysgetvalue{/pgfplots/contour external/cmd}\cmd
+	\pgfkeysgetvalue{/pgfplots/contour external/script extension}\scriptext
+	\if S\pgfplotsplothandlercontourexternal at script@type
+	\else
+		% script type=lua
+		\ifx\cmd\pgfutil at empty
+			\pgfkeyssetvalue{/pgfplots/contour external/cmd}{require(\"\scriptbase\")}%
+			\pgfkeysgetvalue{/pgfplots/contour external/cmd}\cmd
+		\fi
+	\fi
+	%
+	\pgfplotscoordmath{meta}{tofixed}{\pgfplots at metamin}%
+	\let\pgfplotsmetamin=\pgfmathresult
+	\pgfplotscoordmath{meta}{tofixed}{\pgfplots at metamax}%
+	\let\pgfplotsmetamax=\pgfmathresult
+	%
+	\edef\script{\pgfplotsplothandlercontourexternal at file.\scriptext}%
+	\edef\scriptbase{\pgfplotsplothandlercontourexternal at file}%
 	\edef\thecontourlevels{\pgfkeysvalueof{/pgfplots/contour/levels}}%
 	\edef\thecontournumber{\pgfkeysvalueof{/pgfplots/contour/number}}%
 	\immediate\openout\w at pgf@writea=\script
@@ -2797,9 +2851,21 @@
 	\immediate\write\w at pgf@writea{\pgfkeysvalueof{/pgfplots/contour external/script}}%
 	\immediate\closeout\w at pgf@writea
 	%
-	\pgfplots at shellescape{\pgfkeysvalueof{/pgfplots/contour external/cmd}}%
+	\if S\pgfplotsplothandlercontourexternal at script@type
+		\pgfplots at shellescape{\cmd}%
+	\else
+		\ifpgfplots at LUA@supported
+			\pgfplotsutil at directlua{\pgfkeysvalueof{/pgfplots/contour external/cmd}}%
+		\else
+			\pgfplots at error{Calls to 'lua' are currently unsupported. Please invoke lualatex instead.}%
+		\fi
+	\fi
+	\pgfkeysvalueof{/pgfplots/contour external/@after cmd}\relax%
 	\endgroup
 	%
+	% RESET point meta computation here such that it can be collected from the 'contour prepared' stream (i.e. the output of contour external):
+	\global\let\pgfplots at metamin=\pgfplotsplothandlercontourexternal at metamin
+	\global\let\pgfplots at metamax=\pgfplotsplothandlercontourexternal at metamax
 	%
 	\pgfplotsplothandlercontourprepared
 	% the PREPARE steps in the coord stream start/end have already

Modified: trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplotsstackedplots.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplotsstackedplots.code.tex	2021-05-07 23:57:39 UTC (rev 59131)
+++ trunk/Master/texmf-dist/tex/generic/pgfplots/pgfplotsstackedplots.code.tex	2021-05-08 21:05:43 UTC (rev 59132)
@@ -686,3 +686,8 @@
 	\def\pgf at plotyzerolevelstreamend{%
 	}%
 }%
+
+% Initialize \pgfplots at stacked@diff to 0
+% Otherwise, if the first point in a plot is NaN \pgfplots at stacked@diff will be
+% undefined and an error is raised, see issue #219
+\def\pgfplots at stacked@diff{0}

Modified: trunk/Master/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.code.tex
===================================================================
--- trunk/Master/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.code.tex	2021-05-07 23:57:39 UTC (rev 59131)
+++ trunk/Master/texmf-dist/tex/generic/pgfplots/util/pgfplotsutil.code.tex	2021-05-08 21:05:43 UTC (rev 59132)
@@ -412,7 +412,29 @@
 	\pgfplotslistcopy\pgfplots at glob@TMPa\to#2\relax
 }
 
+% converts a foreach list to a fully expanded comma-separated list and assigns the result to \pgfplotsretval
+\long\def\pgfplots at foreach@to at list@macro#1{%
+	\begingroup
+	\pgfplotsapplistXnewempty\pgfplots at tmpa
+	\pgfplots at loc@tmptrue
+	\pgfkeys{/pgf/fpu}%
+	%
+	\pgfplotsforeachungrouped \pgfplots at i in {#1} {%
+		\ifpgfplots at loc@tmp
+			\pgfplots at loc@tmpfalse
+		\else
+			\pgfplotsapplistXpushback,\to\pgfplots at tmpa
+		\fi
+		\pgfmathfloattosci\pgfplots at i
+		\expandafter\pgfplotsapplistXpushback\pgfmathresult\to\pgfplots at tmpa
+	}%
+	\pgfplotsapplistXlet\pgfplots at loc@TMPa=\pgfplots at tmpa
+	\global\let\pgfplots at glob@TMPa=\pgfplots at loc@TMPa
+	\endgroup
+	\let\pgfplotsretval=\pgfplots at glob@TMPa
+}
 
+
 % Removes duplicates in a comma separated list and creates a new list
 % into the macro \pgfplotsretval. The list doesn't need to be sorted,
 % but it should not contain too much elements as the runtime for this



More information about the tex-live-commits mailing list.