texlive[47977] Master: bezierplot (10jun18)

commits+karl at tug.org commits+karl at tug.org
Sun Jun 10 22:51:02 CEST 2018


Revision: 47977
          http://tug.org/svn/texlive?view=revision&revision=47977
Author:   karl
Date:     2018-06-10 22:51:02 +0200 (Sun, 10 Jun 2018)
Log Message:
-----------
bezierplot (10jun18)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/lualatex/bezierplot/README
    trunk/Master/texmf-dist/doc/lualatex/bezierplot/bezierplot-doc.pdf
    trunk/Master/texmf-dist/doc/lualatex/bezierplot/bezierplot-doc.tex
    trunk/Master/texmf-dist/tex/lualatex/bezierplot/bezierplot.lua
    trunk/Master/texmf-dist/tex/lualatex/bezierplot/bezierplot.sty
    trunk/Master/tlpkg/libexec/ctan2tds

Modified: trunk/Master/texmf-dist/doc/lualatex/bezierplot/README
===================================================================
--- trunk/Master/texmf-dist/doc/lualatex/bezierplot/README	2018-06-10 20:50:06 UTC (rev 47976)
+++ trunk/Master/texmf-dist/doc/lualatex/bezierplot/README	2018-06-10 20:51:02 UTC (rev 47977)
@@ -8,7 +8,7 @@
 number of used points.
 
 VERSION:
-1.0 2018-04-12
+1.1 2018-06-10
 
 LICENSE:
 The package and the program are distributed on CTAN under the terms of 

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

Modified: trunk/Master/texmf-dist/doc/lualatex/bezierplot/bezierplot-doc.tex
===================================================================
--- trunk/Master/texmf-dist/doc/lualatex/bezierplot/bezierplot-doc.tex	2018-06-10 20:50:06 UTC (rev 47976)
+++ trunk/Master/texmf-dist/doc/lualatex/bezierplot/bezierplot-doc.tex	2018-06-10 20:51:02 UTC (rev 47977)
@@ -130,7 +130,10 @@
 \begin{verbatim}
 lua bezierplot.lua "FUNCTION" 0 1
 \end{verbatim}
-will set $0\leq x\leq 1$ and leave the default $-5\leq y\leq 5$.
+will set $0\leq x\leq 1$ and leave the default $-5\leq y\leq 5$. The variables \verb|XMIN|, \verb|XMAX|, \verb|YMIN| and \verb|YMAX| may also be computable expressions like \verb|2*pi+6|:
+\begin{verbatim}
+lua bezierplot.lua "sin(x)" -pi pi
+\end{verbatim}
 \subsection{Notation Of Functions}
 The function term given to \verb|bezierplot| must contain at most one variable: $x$. E.g. \verb|"2.3*(x-1)^2-3"|. You must not omit \verb|*| operators:
 \begin{center}

Modified: trunk/Master/texmf-dist/tex/lualatex/bezierplot/bezierplot.lua
===================================================================
--- trunk/Master/texmf-dist/tex/lualatex/bezierplot/bezierplot.lua	2018-06-10 20:50:06 UTC (rev 47976)
+++ trunk/Master/texmf-dist/tex/lualatex/bezierplot/bezierplot.lua	2018-06-10 20:51:02 UTC (rev 47977)
@@ -1,6 +1,6 @@
 #!/usr/bin/env lua
 -- Linus Romer, published 2018 under LPPL Version 1.3c
--- version 1.0 2018-04-12
+-- version 1.1 2018-06-10
 abs = math.abs
 acos = math.acos
 asin = math.asin
@@ -33,7 +33,7 @@
 	end
 end
 
-function round(num, decimals)
+local function round(num, decimals)
 	local result = tonumber(string.format("%." .. (decimals or 0) .. "f", num))
 	if abs(result) == 0 then
 		return 0
@@ -45,77 +45,86 @@
 -- 5-stencil method
 -- return from a graph from f in the form {{x,y},...}
 -- the derivatives in form {{x,y,dy/dx,ddy/ddx},...}
-function diffgraph(func,graph,h)
+local function diffgraph(func,graph,h)
 	local dgraph = {}	
-	local yh = func(graph[1][1]-h)
-	local yhh = func(graph[1][1]-2*h)
-	if yhh > -math.huge and yhh < math.huge  -- if defined at all
-	and yh > -math.huge and yh < math.huge then
-		dgraph[1] = {graph[1][1],graph[1][2],
-		(yhh-8*yh+8*graph[2][2]-graph[3][2])/(12*h),
-		(-yhh+16*yh-30*graph[1][2]+16*graph[2][2]-graph[3][2])
-		/(12*h^2)}
-		dgraph[2] = {graph[2][1],graph[2][2],
-		(yh-8*graph[1][2]+8*graph[3][2]-graph[4][2])/(12*h),
-		(-yh+16*graph[1][2]-30*graph[2][2]+16*graph[3][2]-graph[4][2])
-		/(12*h^2)}
-	else -- take neighbour values
-		dgraph[1] = {graph[1][1],graph[1][2],
-		(graph[1][2]-8*graph[2][2]+8*graph[4][2]-graph[5][2])/(12*h),
-		(-graph[1][2]+16*graph[2][2]-30*graph[3][2]
-		+16*graph[4][2]-graph[5][2])/(12*h^2)}
-		dgraph[2] = {graph[2][1],graph[2][2],
-		(graph[1][2]-8*graph[2][2]+8*graph[4][2]-graph[5][2])/(12*h),
-		(-graph[1][2]+16*graph[2][2]-30*graph[3][2]
-		+16*graph[4][2]-graph[5][2])/(12*h^2)}
-	end
 	local l = #graph
-	for i = 3, l-2 do 
-		table.insert(dgraph,{graph[i][1],graph[i][2],
-		(graph[i-2][2]-8*graph[i-1][2]+8*graph[i+1][2]-graph[i+2][2])
-		/(12*h),
-		(-graph[i-2][2]+16*graph[i-1][2]-30*graph[i][2]
-		+16*graph[i+1][2]-graph[i+2][2])
-		/(12*h^2)})
-	end
-	yh = func(graph[l][1]+h)
-	yhh = func(graph[l][1]+2*h)
-	if yhh > -math.huge and yhh < math.huge  -- if defined at all
-	and yh > -math.huge and yh < math.huge then
-		dgraph[l-1] = {graph[l-1][1],graph[l-1][2],
-		(graph[l-3][2]-8*graph[l-2][2]+8*graph[l][2]-yh)/(12*h),
-		(-graph[l-3][2]+16*graph[l-2][2]-30*graph[l-1][2]
-		+16*graph[l][2]-yh)/(12*h^2)}
-		dgraph[l] = {graph[l][1],graph[l][2],
-		(graph[l-2][2]-8*graph[l-1][2]+8*yh-yhh)/(12*h),
-		(-graph[l-2][2]+16*graph[l-1][2]-30*graph[l][2]
-		+16*yh-yhh)/(12*h^2)}
-	else	
-		-- take neighbour values
-		dgraph[l] = {graph[l][1],graph[l][2],
-		(graph[l-4][2]-8*graph[l-3][2]+8*graph[l-1][2]-graph[l][2])
-		/(12*h),
-		(-graph[l-4][2]+16*graph[l-3][2]-30*graph[l-2][2]
-		+16*graph[l-1][2]-graph[l][2])/(12*h^2)}
-		dgraph[l-1] = {graph[l-1][1],graph[l-2][2],
-		(graph[l-4][2]-8*graph[l-3][2]+8*graph[l-1][2]-graph[l][2])
-		/(12*h),
-		(-graph[l-4][2]+16*graph[l-3][2]-30*graph[l-2][2]
-		+16*graph[l-1][2]-graph[l][2])/(12*h^2)}
-	end
-	-- add information about being extremum / inflection point (true/false)
-	for i = 1, l do 
-		dgraph[i][5] = false -- dy/dx == 0 ? default, may change later
-		dgraph[i][6] = false -- ddy/ddx == 0 ? default, may change later
-	end
-	for i = 1, l-1 do 
-		-- if no gap is inbetween
-		if not (dgraph[i+1][1] - dgraph[i][1] > 1.5*h) then
-			-- check for dy/dx == 0 
-			-- if not already determined as near dy/dx=0
-			if not dgraph[i][5] then 
+	if l < 4 then -- this is not worth the pain...
+		for i = 1, l do 
+			table.insert(dgraph,{graph[i][1],graph[i][2],0,0})
+		end
+	else
+		local yh = func(graph[1][1]-h)
+		local yhh = func(graph[1][1]-2*h)
+		if yhh > -math.huge and yhh < math.huge  -- if defined at all
+		and yh > -math.huge and yh < math.huge then
+			dgraph[1] = {graph[1][1],graph[1][2],
+			(yhh-8*yh+8*graph[2][2]-graph[3][2])/(12*h),
+			(-yhh+16*yh-30*graph[1][2]+16*graph[2][2]-graph[3][2])
+			/(12*h^2)}
+			dgraph[2] = {graph[2][1],graph[2][2],
+			(yh-8*graph[1][2]+8*graph[3][2]-graph[4][2])/(12*h),
+			(-yh+16*graph[1][2]-30*graph[2][2]+16*graph[3][2]-graph[4][2])
+			/(12*h^2)}
+		else -- take neighbour values
+			dgraph[1] = {graph[1][1],graph[1][2],
+			(graph[1][2]-8*graph[2][2]+8*graph[4][2]-graph[5][2])/(12*h),
+			(-graph[1][2]+16*graph[2][2]-30*graph[3][2]
+			+16*graph[4][2]-graph[5][2])/(12*h^2)}
+			dgraph[2] = {graph[2][1],graph[2][2],
+			(graph[1][2]-8*graph[2][2]+8*graph[4][2]-graph[5][2])/(12*h),
+			(-graph[1][2]+16*graph[2][2]-30*graph[3][2]
+			+16*graph[4][2]-graph[5][2])/(12*h^2)}
+		end
+		for i = 3, l-2 do 
+			table.insert(dgraph,{graph[i][1],graph[i][2],
+			(graph[i-2][2]-8*graph[i-1][2]+8*graph[i+1][2]-graph[i+2][2])
+			/(12*h),
+			(-graph[i-2][2]+16*graph[i-1][2]-30*graph[i][2]
+			+16*graph[i+1][2]-graph[i+2][2])
+			/(12*h^2)})
+		end
+		yh = func(graph[l][1]+h)
+		yhh = func(graph[l][1]+2*h)
+		if yhh > -math.huge and yhh < math.huge  -- if defined at all
+		and yh > -math.huge and yh < math.huge then
+			dgraph[l-1] = {graph[l-1][1],graph[l-1][2],
+			(graph[l-3][2]-8*graph[l-2][2]+8*graph[l][2]-yh)/(12*h),
+			(-graph[l-3][2]+16*graph[l-2][2]-30*graph[l-1][2]
+			+16*graph[l][2]-yh)/(12*h^2)}
+			dgraph[l] = {graph[l][1],graph[l][2],
+			(graph[l-2][2]-8*graph[l-1][2]+8*yh-yhh)/(12*h),
+			(-graph[l-2][2]+16*graph[l-1][2]-30*graph[l][2]
+			+16*yh-yhh)/(12*h^2)}
+		else	
+			-- take neighbour values
+			dgraph[l] = {graph[l][1],graph[l][2],
+			(graph[l-4][2]-8*graph[l-3][2]+8*graph[l-1][2]-graph[l][2])
+			/(12*h),
+			(-graph[l-4][2]+16*graph[l-3][2]-30*graph[l-2][2]
+			+16*graph[l-1][2]-graph[l][2])/(12*h^2)}
+			dgraph[l-1] = {graph[l-1][1],graph[l-2][2],
+			(graph[l-4][2]-8*graph[l-3][2]+8*graph[l-1][2]-graph[l][2])
+			/(12*h),
+			(-graph[l-4][2]+16*graph[l-3][2]-30*graph[l-2][2]
+			+16*graph[l-1][2]-graph[l][2])/(12*h^2)}
+		end
+		-- add information about being extremum / inflection point (true/false)
+		for i = 1, l do 
+			dgraph[i][5] = false -- dy/dx == 0 ? default, may change later
+			dgraph[i][6] = false -- ddy/ddx == 0 ? default, may change later
+		end
+		for i = 1, l-1 do 
+			-- if no gap is inbetween
+			if not (dgraph[i+1][1] - dgraph[i][1] > 1.5*h) then
+				-- check for dy/dx == 0 
+				-- if not already determined as near dy/dx=0
 				if dgraph[i][3] == 0 then
-					dgraph[i][5] = true
+					if dgraph[i+1][3] == 0 then --take the later
+						dgraph[i+1][5] = true
+						dgraph[i][5] = false
+					else
+						dgraph[i][5] = true
+					end
 				elseif abs(dgraph[i][3]*dgraph[i+1][3]) 
 				~= dgraph[i][3]*dgraph[i+1][3] then -- this must be near
 					if abs(dgraph[i][4]) <= abs(dgraph[i+1][4]) then
@@ -124,12 +133,10 @@
 						dgraph[i+1][5] = true
 					end
 				end
-			end
-			-- check for ddy/ddx == 0 
-			-- if not already determined as near ddy/ddx=0
-			if not dgraph[i][6] then 
-				if abs(dgraph[i][4]*dgraph[i+1][4]) 
-				~= dgraph[i][4]*dgraph[i+1][4] then -- this must be near
+				-- check for ddy/ddx == 0 
+				-- if not already determined as near ddy/ddx=0
+				if (not dgraph[i][6]) and (abs(dgraph[i][4]*dgraph[i+1][4]) 
+					~= dgraph[i][4]*dgraph[i+1][4]) then -- this must be near
 					if abs(dgraph[i][4]) <= abs(dgraph[i+1][4]) then
 						dgraph[i][6] = true
 					else
@@ -146,7 +153,11 @@
 -- fits the graph g (up to maxerror) after filling in
 -- the parameters a, b, c, d
 -- if the graph is inverted, then isinverse has to be set true
-function do_parameters_fit(a,b,c,d,funcstring,funcgraph,maxerror,isinverse)
+local function do_parameters_fit(a,b,c,d,funcstring,funcgraph,maxerror,isinverse)
+	if not (a > -math.huge and a < math.huge and b > -math.huge and b < math.huge  and
+	c > -math.huge and c < math.huge and d > -math.huge and d < math.huge) then
+		return false
+	end
 	local funcx = string.gsub(funcstring, "a", a)
 	local funcx = string.gsub(funcx, "b", b)
 	local funcx = string.gsub(funcx, "c", c)
@@ -169,7 +180,7 @@
 end
 
 -- f(x)=a*x^3+b*x+c
-function parameters_cubic(xp,yp,xq,yq,xr,yr,xs,ys)
+local function parameters_cubic(xp,yp,xq,yq,xr,yr,xs,ys)
 	local a = (((xp^2 * xq) * yr) - ((xp^2 * xq) * ys) 
 	- ((xp^2 * xr) * yq) + ((xp^2 * xr) * ys) + ((xp^2 * xs) * yq)
 	- ((xp^2 * xs) * yr) - ((xp * xq^2) * yr) + ((xp * xq^2) * ys) 
@@ -266,7 +277,7 @@
 end
 
 -- f(x)=a*x+b
-function parameters_affine(xp,yp,xq,yq)
+local function parameters_affine(xp,yp,xq,yq)
 	local a = (yp - yq) / (xp - xq)
 	local b = ((xp * yq) - (xq * yp)) / (xp - xq)
 	return a, b
@@ -274,14 +285,18 @@
 
 -- returns true iff the function is of type f(x)=a*x^3+b*x^2+c*x+d
 -- a, b, c, d being real numbers
-function is_cubic(graph,maxerror)
+local function is_cubic(graph,maxerror)
 	local l = #graph
-	local a, b, c, d = parameters_cubic(graph[1][1],graph[1][2],
-	graph[math.floor(l/3)][1],graph[math.floor(l/3)][2],
-	graph[math.floor(2*l/3)][1],graph[math.floor(2*l/3)][2],
-	graph[l][1],graph[l][2])
-	return do_parameters_fit(a,b,c,d,"a*x^3+b*x^2+c*x+d",graph,
-	maxerror,false)
+	if l < 2 then
+		return false
+	else
+		local a, b, c, d = parameters_cubic(graph[1][1],graph[1][2],
+		graph[math.floor(l/3)][1],graph[math.floor(l/3)][2],
+		graph[math.floor(2*l/3)][1],graph[math.floor(2*l/3)][2],
+		graph[l][1],graph[l][2])
+		return do_parameters_fit(a,b,c,d,"a*x^3+b*x^2+c*x+d",graph,
+		maxerror,false)
+	end
 end
 
 -- returns true iff the function is of type f(x)=a*x^3+b*x^2+c*x+d
@@ -288,7 +303,7 @@
 -- a, b, c, d being real numbers
 -- this takes several graph parts
 -- the idea is to have a possibility to avoid tan(x)
-function are_cubic(graphs,maxerror)
+local function are_cubic(graphs,maxerror)
 	if is_cubic(graphs[1],maxerror) then
 		if #graphs < 2 then
 			return true
@@ -310,14 +325,18 @@
 -- returns true iff the inverse function is of type 
 -- f(x)=a*x^3+b*x^2+c*x+d
 -- a, b, c, d being real numbers
-function is_cuberoot(graph,maxerror)
+local function is_cuberoot(graph,maxerror)
 	local l = #graph
-	local a, b, c, d = parameters_cubic(graph[1][2],graph[1][1],
-	graph[math.floor(l/3)][2],graph[math.floor(l/3)][1],
-	graph[math.floor(2*l/3)][2],graph[math.floor(2*l/3)][1],
-	graph[l][2],graph[l][1])
-	return do_parameters_fit(a,b,c,d,"a*x^3+b*x^2+c*x+d",graph,
-	maxerror,true)
+	if l < 2 then
+		return false
+	else
+		local a, b, c, d = parameters_cubic(graph[1][2],graph[1][1],
+		graph[math.floor(l/3)][2],graph[math.floor(l/3)][1],
+		graph[math.floor(2*l/3)][2],graph[math.floor(2*l/3)][1],
+		graph[l][2],graph[l][1])
+		return do_parameters_fit(a,b,c,d,"a*x^3+b*x^2+c*x+d",graph,
+		maxerror,true)
+	end
 end
 
 -- returns true iff the function is of type f(x)=a*x^3+b*x^2+c*x+d
@@ -324,7 +343,7 @@
 -- a, b, c, d being real numbers
 -- this takes several graph parts
 -- the idea is to have a possibility to avoid tan(x)
-function are_cuberoot(graphs,maxerror)
+local function are_cuberoot(graphs,maxerror)
 	if is_cuberoot(graphs[1],maxerror) then
 		if #graphs < 2 then
 			return true
@@ -345,7 +364,7 @@
 
 -- returns true iff function is of type f(x)=a*x+b
 -- a, b being real numbers
-function is_affine(graph,maxerror)
+local function is_affine(graph,maxerror)
 	l = #graph
 	local a, b = parameters_affine(graph[1][1],graph[1][2],
 	graph[l][1],graph[l][2])
@@ -357,7 +376,7 @@
 -- p.. control q and r .. s
 -- with the graph g from index starti to endi
 -- (looking at the points at roughly t=.33 and t=.67)
-function squareerror(f,g,starti,endi,qx,qy,rx,ry)
+local function squareerror(f,g,starti,endi,qx,qy,rx,ry)
 	local result = 0
 	for t = .33, .7, .34 do
 		x = (1-t)^3*g[starti][1]+3*t*(1-t)^2*qx+3*t^2*(1-t)*rx+t^3*g[endi][1]
@@ -367,13 +386,105 @@
 	return result
 end
 
-function pointstobezier(qx,qy,rx,ry,sx,sy,rndx,rndy)
-	return " .. controls (" .. round(qx,rndx) .. "," 
-	.. round(qy,rndy) ..") and ("
-	.. round(rx,rndx) .. "," 
-	.. round(ry,rndy) .. ") .. (" 
-	.. round(sx,rndx) .. "," 
-	.. round(sy,rndy)..")"
+-- converts a table with bezier point information
+-- to a string with rounded values 
+-- the path is reversed, if rev is true
+-- e.g. if b = {{0,1},{2,3,4,5,6,7},{8,9,10,11,12,13}}
+-- then 
+-- (0,1) .. controls (2,3) and (4,5) .. (6,7) .. controls 
+-- (8,9) and (10,11) .. (12,13)
+-- will be returned
+-- the notation "pgfplots" will change the notation to
+-- YES: \addplot coordinates {(0,1) (6,7) (2,3) (4,5) (6,7) (12,13) (8,9) (10,11)}
+-- NO: 0  1 \\ 6  7 \\ 2  3 \\ 4  5 \\ \\ 6  7 \\ 12 13 \\ 8  9 \\ 10 11 \\
+-- As pgfplots does not connect the bezier segments
+-- reverse paths are not implemented 
+local function beziertabletostring(b,rndx,rndy,rev,notation)
+	local bezierstring = ""
+	if #b > 1 then -- if not empty or single point
+		if #b == 2 and #b[2] == 2 then -- straight line
+			if rev then
+				bezierstring = "(" .. round(b[2][1],rndx) .. "," 
+					.. round(b[2][2],rndy) ..")"
+					.. " -- (" .. round(b[1][1],rndx) .. "," 
+					.. round(b[1][2],rndy) ..")"
+			else
+				if notation == "pgfplots" then
+					bezierstring = "\\addplot coordinates {(" 
+						.. round(b[1][1],rndx) .. "," 
+						.. round(b[1][2],rndy) .. ") (" 
+						.. round(b[2][1],rndx) .. "," 
+						.. round(b[2][2],rndy) .. ") (" 
+						.. round(b[1][1],rndx) .. ","  
+						.. round(b[1][2],rndy) .. ") (" 
+						.. round(b[2][1],rndx) .. "," 
+						.. round(b[2][2],rndy) .. ") }" 
+				else -- notation = tikz
+					bezierstring = "(" .. round(b[1][1],rndx) .. "," 
+						.. round(b[1][2],rndy) ..")"
+						.. " -- (" .. round(b[2][1],rndx) .. "," 
+						.. round(b[2][2],rndy) ..")"
+				end	
+			end
+		else
+			if rev then
+				bezierstring = "(" .. round(b[#b][#b[#b]-1],rndx) .. "," 
+				.. round(b[#b][#b[#b]],rndy) ..")" -- initial point
+				for i = #b, 2, -1 do
+					if #b[i] >= 6 then -- cubic bezier spline
+						bezierstring = bezierstring .. " .. controls (" 
+						.. round(b[i][3],rndx) .. "," 
+						.. round(b[i][4],rndy) ..") and ("
+						.. round(b[i][1],rndx) .. "," 
+						.. round(b[i][2],rndy) .. ") .. (" 
+						.. round(b[i-1][#b[i-1]-1],rndx) .. "," 
+						.. round(b[i-1][#b[i-1]],rndy)..")"
+					else
+						bezierstring = bezierstring .. " (" 
+						.. round(b[i-1][#b[i-1]-1],rndx) .. "," 
+						.. round(b[i-1][#b[i-1]],rndy) ..")"
+					end
+				end
+			else
+				if notation == "pgfplots" then
+					bezierstring = "\\addplot coordinates {"
+					for i = 1, #b-1 do
+						if #b[i+1] >= 6 then -- cubic bezier spline
+							bezierstring = bezierstring .. "("
+							.. round(b[i][#b[i]-1],rndx) .. "," 
+							.. round(b[i][#b[i]],rndy) .. ") (" 
+							.. round(b[i+1][5],rndx) .. "," 
+							.. round(b[i+1][6],rndy) .. ") ("  
+							.. round(b[i+1][1],rndx) .. "," 
+							.. round(b[i+1][2],rndy) .. ") (" 
+							.. round(b[i+1][3],rndx) .. "," 
+							.. round(b[i+1][4],rndy) .. ") " 
+						end
+					end
+					bezierstring = bezierstring .. "}"
+				else -- notation = tikz
+					bezierstring = "(" .. round(b[1][1],rndx) .. "," 
+					.. round(b[1][2],rndy) ..")" -- initial point
+					for i = 2, #b do
+						if #b[i] >= 6 then -- cubic bezier spline
+							bezierstring = bezierstring .. " .. controls (" 
+							.. round(b[i][1],rndx) .. "," 
+							.. round(b[i][2],rndy) ..") and ("
+							.. round(b[i][3],rndx) .. "," 
+							.. round(b[i][4],rndy) .. ") .. (" 
+							.. round(b[i][5],rndx) .. "," 
+							.. round(b[i][6],rndy)..")"
+						else
+							bezierstring = bezierstring .. " (" 
+							.. round(b[i][1],rndx) .. "," 
+							.. round(b[i][2],rndy) ..")"
+						end
+					end
+				end
+			end
+		end
+	end
+	return bezierstring
 end
 
 -- take end points of a graph g of the function f
@@ -381,7 +492,7 @@
 -- without extrema or inflection points inbetween 
 -- and try to approximate it with a cubic bezier curve
 -- (round to rndx and rndy when printing)
-function graphtobezierapprox(f,g,starti,endi,rndx,rndy,maxerror)
+local function graphtobezierapprox(f,g,starti,endi,maxerror)
 	local px = g[starti][1]
 	local py = g[starti][2]
 	local dp = g[starti][3]
@@ -427,7 +538,7 @@
 		end
 	end
 	if err <= maxerror then
-		return pointstobezier(qx,qy,rx,ry,sx,sy,rndx,rndy)
+		return {qx,qy,rx,ry,sx,sy}
 	else
 		-- search for an intermediate point where the graph has the same
 		-- slope as the line from the start point to the end point:
@@ -440,14 +551,18 @@
 				interindex = i
 			end
 		end
-		return graphtobezierapprox(f,g,starti,interindex,rndx,rndy,maxerror)
-		.. graphtobezierapprox(f,g,interindex,endi,rndx,rndy,maxerror)
+		local left = graphtobezierapprox(f,g,starti,interindex,maxerror)
+		local right = graphtobezierapprox(f,g,interindex,endi,maxerror)
+		for i=1, #right do --now append the right to the left:
+			left[#left+1] = right[i]
+		end
+		return left
 	end
 end
 
 -- like above but exact for quadratic and cubic (if not inverse)
 -- resp. exact for squareroot and cuberoot (if inverse)
-function graphtobezier(g,starti,endi,rndx,rndy,isinverse)
+local function graphtobezier(g,starti,endi,isinverse)
 	local px = g[starti][1]
 	local py = g[starti][2]
 	local dp = g[starti][3]
@@ -459,48 +574,24 @@
 	local qy = py+(qx-px)*dp
 	local ry = sy+(rx-sx)*ds
 	if isinverse then
-		return pointstobezier(qy,qx,ry,rx,sy,sx,rndy,rndx)
+		return {qy,qx,ry,rx,sy,sx}
 	else
-		return pointstobezier(qx,qy,rx,ry,sx,sy,rndx,rndy)
+		return {qx,qy,rx,ry,sx,sy}
 	end
 end
 
--- reverses a path p e.g. when p = "(0,1) -- (2,3)"
--- it returns "(2,3) -- (0,1)"
--- or when p = "(0,1) .. controls (2,3) and (4,5) .. (6,7)"
--- it returns "(6,7) .. controls (4,5) and (2,3) .. (0,1)"
-function reversepath(p)
-	local r = "" -- will become the reverse path
-	local temppoint  ="" -- will store temporal points like "(0,1)"
-	local tempbetween = "" -- will store things like " .. controls "
-	for i = 1, #p do
-		local c = string.sub(p,i,i)
-		if c == "(" then
-			if tempbetween == " .. " then
-				r = " .. controls " .. r
-			elseif tempbetween == " .. controls " then
-				r = " .. " .. r
-			else
-				r = tempbetween .. r
-			end
-			tempbetween = ""
-			temppoint = "("
-		elseif c == ")" then
-			r = temppoint .. ")" .. r
-			temppoint = ""
-		else
-			if temppoint == "" then -- not reading a point
-				tempbetween = tempbetween .. c
-			else
-				temppoint = temppoint .. c
-			end
+-- just for debugging:
+local function printtable(t)
+	for i = 1,#t do
+		for j = 1, #t[i] do
+			io.write(t[i][j].." ")
 		end
+		io.write("\n")
 	end
-	return r
 end
 
 -- main function
-function bezierplot(functionstring,xmin,xmax,ymin,ymax)
+function bezierplot(functionstring,xmin,xmax,ymin,ymax,notation)
 	local fstringreplaced = string.gsub(functionstring, "%*%*", "^")
 	local f = assert(load("local x = ...; return " .. fstringreplaced)) 
 	local isreverse = false
@@ -539,11 +630,19 @@
 	end
 
 	local functiontype = "unknown"
-	local bezierstring = ""
+	local bezierpoints = {}
+	-- the bezier path (0,1) .. controls 
+	-- (2,3) and (4,5) .. (6,7) .. controls 
+	-- (8,9) and (10,11) .. (12,13)
+	-- will be stored as
+	-- bezierpoints={{0,1},{2,3,4,5,6,7},{8,9,10,11,12,13}}
 
 	-- go through the connected parts
 	for part = 1, #graphs do 
 		local d = diffgraph(f,graphs[part],xstep)
+		--for i = 1, #d do -- just for debugging
+		-- 	print(d[i][1],d[i][2],d[i][3],d[i][4],d[i][5],d[i][6])
+		--end
 		-- check for type of function (only for the first part)
 		if part == 1 then
 			if is_affine(d,yerror) then
@@ -555,12 +654,12 @@
 			end
 		end
 		if functiontype ~= "cuberoot" then -- start with initial point
-			bezierstring = bezierstring .. "(" .. round(d[1][1],rndx) 
-			.. "," 	.. round(d[1][2],rndy) .. ")"
+			bezierpoints[#bezierpoints+1] = {round(d[1][1],rndx),
+			round(d[1][2],rndy)}
 		end
 		if functiontype == "affine" then 
-			bezierstring = bezierstring .. " -- (" .. round(d[#d][1],
-			rndx) .. "," .. round(d[#d][2],rndy) ..")"
+			bezierpoints[#bezierpoints+1] = {round(d[#d][1],rndx),
+			round(d[#d][2],rndy)}
 		elseif functiontype == "cubic" then 
 			local startindex = 1
 			local extremainbetween = false
@@ -567,8 +666,8 @@
 			for k = 2, #d do
 				if d[k][5] then -- extrema 
 					extremainbetween = true
-					bezierstring = bezierstring 
-					.. graphtobezier(d,startindex,k,rndx,rndy,false)
+					bezierpoints[#bezierpoints+1] = graphtobezier(d,
+					startindex,k,false)
 					startindex = k
 				end
 			end
@@ -584,8 +683,8 @@
 						local ry = d[#d][2]+(rx-d[#d][1])*d[#d][3]
 						if math.max(qy,ry) > ymax 
 						or math.min(qy,ry) < ymin then
-							bezierstring = bezierstring ..graphtobezier(
-							d,startindex,k,rndx,rndy,false)
+							bezierpoints[#bezierpoints+1] = graphtobezier(
+							d,startindex,k,false)
 							startindex = k
 						end
 					end
@@ -592,8 +691,8 @@
 				end
 			end
 			if startindex ~= #d then -- if no special points inbetween
-				bezierstring = bezierstring 
-				.. graphtobezier(d,startindex,#d,rndx,rndy,false)
+				bezierpoints[#bezierpoints+1] = graphtobezier(d,
+				startindex,#d,false)
 			end
 		elseif functiontype == "cuberoot" then 
 			-- we determine a, b, c, d and then
@@ -619,8 +718,7 @@
 				end
 			end
 			d = diffgraph(finverse,graphinverse,xstep)
-			bezierstring = bezierstring .. "(" .. round(d[1][2],rndy) 
-			.. "," .. round(d[1][1],rndx) .. ")" -- initial point
+			bezierpoints[#bezierpoints+1] = {d[1][2],d[1][1]} -- initial point
 			local startindex = 1
 			for k = 2, #d do
 				if d[k][6] then -- inflection point
@@ -633,15 +731,15 @@
 					local ry = d[#d][2]+(rx-d[#d][1])*d[#d][3]
 					if math.max(qy,ry) > xmax 
 					or math.min(qy,ry) < xmin then
-						bezierstring = bezierstring..graphtobezier(
-						d,startindex,k,rndx,rndy,true)
+						bezierpoints[#bezierpoints+1] = graphtobezier(
+						d,startindex,k,true)
 						startindex = k
 					end
 				end
 			end
 			if startindex ~= #d then -- if no special points inbetween
-				bezierstring = bezierstring 
-				.. graphtobezier(d,startindex,#d,rndx,rndy,true)
+				bezierpoints[#bezierpoints+1] = graphtobezier(d,
+				startindex,#d,true)
 			end
 		else	
 			-- standard case (nothing special)			
@@ -648,22 +746,41 @@
 			local startindex = 1
 			for k = 2, #d do
 				if d[k][5] or d[k][6] then -- extrema and inflection points
-					bezierstring = bezierstring .. graphtobezierapprox(
-					f,d,startindex,k,rndx,rndy,(ymax-ymin)/(0.5*10^rndy))
+					local tobeadded = graphtobezierapprox(
+					f,d,startindex,k,(ymax-ymin)/(0.5*10^rndy))
+					-- tobeadded may contain a multiple of 6 entries
+				-- e.g. {1,2,3,4,5,6,7,8,9,10,11,12}
+					for i = 1, math.floor(#tobeadded/6) do
+						bezierpoints[#bezierpoints+1] = {}
+						for j = 1, 6 do
+							bezierpoints[#bezierpoints][j] = tobeadded[(i-1)*6+j]
+						end
+					end
 					startindex = k
 				end
 			end
 			if startindex ~= #d then -- if no special points inbetween
-				bezierstring = bezierstring .. graphtobezierapprox(f,d,
-				startindex,#d,rndx,rndy,(ymax-ymin)/(0.5*10^rndy))
+				local tobeadded = graphtobezierapprox(f,d,
+				startindex,#d,(ymax-ymin)/(0.5*10^rndy))
+				-- tobeadded may contain a multiple of 6 entries
+				-- e.g. {1,2,3,4,5,6,7,8,9,10,11,12}
+				for i = 1, math.floor(#tobeadded/6) do
+					bezierpoints[#bezierpoints+1] = {}
+					for j = 1, 6 do
+						bezierpoints[#bezierpoints][j] = tobeadded[(i-1)*6+j]
+					end
+				end
 			end
 		end
 	end
-	if isreverse then
-		return reversepath(bezierstring)
-	else
-		return bezierstring
-	end
+	-- only for debugging:
+	--for i = 1, #bezierpoints do
+	-- 	for j = 1, #bezierpoints[i] do
+	-- 		print(bezierpoints[i][j])
+	-- 	end
+	---print("\n")
+	--end
+	return beziertabletostring(bezierpoints,rndx,rndy,isreverse,notation)
 end
 
 -- main program --
@@ -672,25 +789,38 @@
 	if #arg >= 1 then
 		local xmin = -5
 		local xmax = 5
-		if #arg >= 2 then xmin = arg[2] end
+		if #arg >= 2 then 
+			local tempfunc = assert(load("return " .. arg[2]))
+			xmin = tempfunc()
+		end
 		if #arg >= 3 then
 			if arg[3] == arg[2] then
 				xmax = xmin + 10
 			else
-				xmax = arg[3]
+				local tempfunc = assert(load("return " .. arg[3]))
+				xmax = tempfunc()
 			end
 		end
 		local ymin = -5
 		local ymax = 5
-		if #arg >= 4 then ymin = arg[4] end
+		if #arg >= 4 then 
+			local tempfunc = assert(load("return " .. arg[4]))
+			ymin = tempfunc()
+		end
 		if #arg >= 5 then 
 			if arg[5] == arg[4] then
 				ymax = ymin + 10
 			else
-				ymax = arg[5]
+				local tempfunc = assert(load("return " .. arg[5]))
+				ymax = tempfunc()
 			end
 		end
-		print(bezierplot(arg[1],xmin,xmax,ymin,ymax))
+		if #arg >= 6 then 
+			notation = arg[6] 
+		else
+			notation = "tikz"
+		end
+		print(bezierplot(arg[1],xmin,xmax,ymin,ymax,notation))
 	end
 end
 

Modified: trunk/Master/texmf-dist/tex/lualatex/bezierplot/bezierplot.sty
===================================================================
--- trunk/Master/texmf-dist/tex/lualatex/bezierplot/bezierplot.sty	2018-06-10 20:50:06 UTC (rev 47976)
+++ trunk/Master/texmf-dist/tex/lualatex/bezierplot/bezierplot.sty	2018-06-10 20:51:02 UTC (rev 47977)
@@ -1,16 +1,16 @@
 \NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{bezierplot}[2018/04/12 bezierplot]
+\ProvidesPackage{bezierplot}[2018/06/10 bezierplot]
 \RequirePackage{xparse}
 \RequirePackage{iftex}
 \ifLuaTeX
  \directlua{require("bezierplot")}
- \DeclareExpandableDocumentCommand{\xbezierplot}{O{-5} O{5} O{-5} O{5} m}{%
-  \directlua{tex.sprint(bezierplot("#5",#1,#2,#3,#4))}
+ \DeclareExpandableDocumentCommand{\xbezierplot}{O{-5} O{5} O{-5} O{5} O{tikz} m}{%
+  \directlua{tex.sprint(bezierplot("#6",#1,#2,#3,#4,"#5"))}
   }
 \else
  \let\xpandblinpt\@@input
- \DeclareExpandableDocumentCommand{\xbezierplot}{O{-5} O{5} O{-5} O{5} m}{%
-  \xpandblinpt|"bezierplot '#5' #1 #2 #3 #4"
+ \DeclareExpandableDocumentCommand{\xbezierplot}{O{-5} O{5} O{-5} O{5} O{tikz} m}{%
+  \xpandblinpt|"bezierplot '#6' #1 #2 #3 #4 '#5'"
  }
 \fi
 \providecommand\bezierplot{\romannumeral`\^^@\xbezierplot}

Modified: trunk/Master/tlpkg/libexec/ctan2tds
===================================================================
--- trunk/Master/tlpkg/libexec/ctan2tds	2018-06-10 20:50:06 UTC (rev 47976)
+++ trunk/Master/tlpkg/libexec/ctan2tds	2018-06-10 20:51:02 UTC (rev 47977)
@@ -1579,6 +1579,7 @@
  'bbold',       'bbold.sty|\.fd',       # no fonttabl.sty
  'bclogo',      'bc[^l].*\.(tex|pdf|eps|mps)|bclogo\.sty',
  'beamer2thesis','\.jpg|' . $standardtex,
+ 'bezierplot',	'\.lua|' . $standardtex,
  'bghyphen',    '\.tex',
 # 'bgteubner',   '\.sty|\.cls|[^c]\.cfg',        # not ltxdoc.cfg
  'biblatex-gost', '\.(.bx|def|)$',      # not .cfg



More information about the tex-live-commits mailing list