summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/metapost/bpolynomial
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/metapost/bpolynomial')
-rw-r--r--Master/texmf-dist/metapost/bpolynomial/bpolynomial.mp307
1 files changed, 262 insertions, 45 deletions
diff --git a/Master/texmf-dist/metapost/bpolynomial/bpolynomial.mp b/Master/texmf-dist/metapost/bpolynomial/bpolynomial.mp
index f1c0129bb94..e4f27a434a1 100644
--- a/Master/texmf-dist/metapost/bpolynomial/bpolynomial.mp
+++ b/Master/texmf-dist/metapost/bpolynomial/bpolynomial.mp
@@ -7,73 +7,152 @@
% license is in http://www.latex-project.org/lppl.txt
%
+%%% Identify yourself.
if known bpolynomial_fileversion: endinput fi;
string bpolynomial_fileversion;
-bpolynomial_fileversion := "v0.4 (2007/11/28)";
+bpolynomial_fileversion := "v0.5 (2007/12/12)";
message "Loading bpolynomial " & bpolynomial_fileversion;
+%%% Main user macro for defining polynomials.
+%%% Arguments are a suffix and the coefficients
+%%% of the function a*x^3 + b*x^2 + c*x + d.
vardef newBPolynomial@#(expr a, b, c, d)=
- defineBPolynomial.@#(a, b, c, d);
- defineBPolynomial.@#'(0, 3a, 2b, c);
- defineBPolynomial.@#''(0, 0, 6a, 2b);
- defineBPolynomial.@#'''(0, 0, 0, 6a);
+ bpolynomial__defineBPolynomial.@#(a, b, c, d);
+ bpolynomial__defineBPolynomial.@#'(0, 3a, 2b, c);
+ bpolynomial__defineBPolynomial.@#''(0, 0, 6a, 2b);
+ bpolynomial__defineBPolynomial.@#'''(0, 0, 0, 6a);
enddef;
-%%% This macro defines two macros @#.eval and @#.getPath.
-%%% Parameters are the coefficients of the polynomial a*x^3 + b*x^2 + c*x + d.
-vardef defineBPolynomial@#(expr ca,cb,cc,cd)=
+
+%%% This macro returns the path of a Bezier curve that matches
+%%% a function a*x^3 + b*x^2 + c*x + d between two points A and D.
+%%% This macro is the heart of this package and is used by
+%%% several other macros.
+%%% Arguments are the coefficients of the polynomial and the
+%%% start and end point of the graph/path.
+vardef bpolynomial__getBezierFromPolynomial(expr a, b, c, d, A, D)=
+save xA,xB,xC,xD,yA,yB,yC,yD;
+save xl,yl,xr,yr,dx;
+numeric xA,xB,xC,xD,yA,yB,yC,yD;
+numeric xl,yl,xr,yr,dx;
+ xl := xpart A;
+ yl := ypart A;
+ xr := xpart D;
+ yr := ypart D;
+ dx := xpart D - xpart A;
+ %%% Original equation system for x values.
+% xA = xl;
+% 3(xB - xA) = dx;
+% 3(xC - 2xB + xA) = 0;
+% xD - 3xC + 3xB - xA = 0;
+ %%% Modified equation system.
+ xA := xl;
+ xB := xl + dx/3;
+ xC := xr - dx/3;
+ xD := xr;
+ %%% Original equation system for y values.
+% yA = ((a*xl + b)*xl + c)*xl + d;
+% 3(yB - yA) = dx*((3a*xl + 2b)*xl + c);
+% 3(yC - 2yB + yA) = dx*dx*(3a*xl + b);
+% yD - 3yC + 3yB - yA = a*dx*dx*dx;
+ %%% Modified equation system.
+ yA := yl;
+ 3(yB - yA) = dx*((3a*xl + 2b)*xl + c);
+ 3(yC - 2yB + yA) = dx*dx*(3a*xl + b);
+ yD := yr;
+ %%% Return path A..controls B and C..D.
+ (xA,yA)..controls (xB,yB) and (xC,yC)..(xD,yD)
+enddef;
+
+
+%%% This macro returns the path of a Bezier curve that matches
+%%% a function a*x^3 + b*x^2 + c*x + d in the range [xl, xr].
+%%% Arguments are the coefficients of the polynomial and the
+%%% range boundaries of the graph/path.
+vardef getBezierFromPolynomial(expr a, b, c, d, xl, xr)=
+ bpolynomial__getBezierFromPolynomial(a, b, c, d,
+ (xl, ((a*xl+b)*xl+c)*xl+d),
+ (xr, ((a*xr+b)*xr+c)*xr+d))
+enddef;
+
+
+%%% This macro returns the path of a Bezier curve that matches
+%%% a function a*x^3 + b*x^2 + c*x + d in the range [xl, xr].
+%%% Arguments are the coefficients of the polynomial and the
+%%% range boundaries of the graph/path.
+vardef getBezierFromSqrRoot(expr u, v, w, xl, xr)=
+save yl, yr;
+numeric yl,yr;
+ if (xl >= -v):
+ yl := xl;
+ else:
+ message "Package bpolynomial warning: Replacing lower range boundary " & decimal xl & " by " & decimal -v & "!";
+ yl := -v;
+ fi
+ if (xr >= -v):
+ yr := xr;
+ else:
+ message "Package bpolynomial warning: Replacing upper range boundary " & decimal xr & " by " & decimal -v & "!";
+ yr := -v;
+ fi
+ bpolynomial__getBezierFromPolynomial(0, 1/u/u, -2*w/u/u, (w/u)*(w/u)-v,
+ (u*sqrt(yl+v)+w, yl),
+ (u*sqrt(yr+v)+w, yr)) reflectedabout ((0,0),(1,1))
+enddef;
+
+
+%%% This macro returns the path of a Bezier curve that matches
+%%% a function a*x^3 + b*x^2 + c*x + d in the range [xl, xr].
+%%% Arguments are the coefficients of the polynomial and the
+%%% range boundaries of the graph/path.
+vardef getBezierFromCubRoot(expr u, v, w, xl, xl)=
+save yl, yr;
+numeric yl,yr;
+ if (xl >= -v):
+ yl := xl;
+ else:
+ message "Package bpolynomial warning: Replacing lower range boundary " & decimal xl & " by " & decimal -v & "!";
+ yl := -v;
+ fi
+ if (xr >= -v):
+ yr := xr;
+ else:
+ message "Package bpolynomial warning: Replacing upper range boundary " & decimal xr & " by " & decimal -v & "!";
+ yr := -v & "!";
+ fi
+ bpolynomial__getBezierFromPolynomial(1/u/u/u, -3w/u/u/u, 3(w/u)*(w/u)/u, (w/u)*(w/u)*(w/u)-v,
+ (u*((yl+v)**(1/3))+w, yl),
+ (u*((yr+v)**(1/3))+w, yr)) reflectedabout ((0,0),(1,1))
+enddef;
+
+
+%%% This internal macro defines a new polynomial.
+%%% Arguments are a suffix macro and the coefficients
+%%% of the polynomial a*x^3 + b*x^2 + c*x + d.
+vardef bpolynomial__defineBPolynomial@#(expr ca,cb,cc,cd)=
numeric @#.a, @#.b, @#.c, @#.d;
%%% Save coefficients for later access.
- %%% For instance, variable @#.a refers to coefficient a of polynomial @#.
+ %%% Variable @#.a refers to coefficient a of polynomial @#.
@#.a := ca;
@#.b := cb;
@#.c := cc;
@#.d := cd;
-
- %%% Define macro that returns values of polynomial @#.
- %%% Parameter is an x value.
+ %%% This macro returns values of polynomial @#.
+ %%% Argument is an x value.
vardef @#.eval(expr x)=
(((@#.a*x + @#.b)*x + @#.c)*x + @#.d)
enddef;
-
- %%% Define a macro that returns a path of the polynomial
- %%% on a given intervall [xl, xr].
+ %%% This macro returns the path corresponding to polynomial @#
+ %%% on the intervall [xl, xr].
vardef @#.getPath(expr xl,xr)=
- save xA,xB,xC,xD,yA,yB,yC,yD;
- save dx;
- numeric xA,xB,xC,xD,yA,yB,yC,yD;
- numeric dx;
- dx := xr - xl;
- %%% Original equation system for x values.
-% xA = xl;
-% 3(xB - xA) = dx;
-% 3(xC - 2xB + xA) = 0;
-% xD - 3xC + 3xB - xA = 0;
- %%% Modified equation system.
- xA := xl;
- xB := xl + dx/3;
- xC := xr - dx/3;
- xD := xr;
- %%% Original equation system for y values.
-% yA = ((@#.a*xl + @#.b)*xl + @#.c)*xl + @#.d;
-% 3(yB - yA) = dx*((3@#.a*xl + 2@#.b)*xl + @#.c);
-% 3(yC - 2yB + yA) = dx*dx*(3@#.a*xl + @#.b);
-% yD - 3yC + 3yB - yA = @#.a*dx*dx*dx;
- %%% Modified equation system.
- yA := @#.eval(xl);
- 3(yB - yA) = dx*((3@#.a*xl + 2@#.b)*xl + @#.c);
- 3(yC - 2yB + yA) = dx*dx*(3@#.a*xl + @#.b);
- yD := @#.eval(xr);
- %%% Return path A..controls B and C..D.
- (xA,yA)..controls (xB,yB) and (xC,yC)..(xD,yD)
+ bpolynomial__getBezierFromPolynomial(@#.a, @#.b, @#.c, @#.d, (xl, @#.eval(xl)), (xr, @#.eval(xr)))
enddef;
-
- %%% Define macro that returns a path tangent to @# at point (x, f(x))
- %%% covering interval (x+xm, x+xp).
+ %%% This macro returns a path tangent to @# at point (x, f(x))
+ %%% covering the interval [x+xm, x+xp].
vardef @#.getTangent(expr x, xm, xp)=
save m, y;
numeric m, y;
@@ -83,3 +162,141 @@ numeric @#.a, @#.b, @#.c, @#.d;
enddef;
enddef;
+
+
+%%% This macro defines a new square root.
+%%% Arguments are a suffix macro and the parameters
+%%% of the function u*(x + v)^(1/2) + w.
+vardef newBSqrRoot@#(expr cu,cv,cw)=
+numeric @#.a, @#.b, @#.c, @#.d;
+numeric @#.u, @#.v, @#.w;
+ %%% Save parameters for later access.
+ %%% Variable @#.v refers to parameters of square root @#.
+ %%% Variables @#.a to @#.d store the coefficients of the
+ %%% corresponding polynomial.
+ @#.u := cu;
+ @#.v := cv;
+ @#.w := cw;
+ @#.a := 0;
+ @#.b := 1/cu/cu;
+ @#.c := -2*cw/cu/cu;
+ @#.d := (cw/cu)*(cw/cu)-cv;
+
+ %%% This macro returns values of polynomial @#.
+ %%% Argument is an x value.
+ vardef @#.eval(expr x)=
+ if (x >= -@#.v):
+ @#.u*sqrt(x + @#.v) + @#.w
+ else:
+ message "Package bpolynomial warning: Cannot evaluate function at x = " & decimal x & "!";
+ @#.w
+ fi
+ enddef;
+
+ %%% This macro returns the path corresponding to square root @#
+ %%% on the intervall [yl, yr]. The path of the corresponing
+ %%% polynomial is computed and then transformed.
+ vardef @#.getPath(expr xl,xr)=
+ save yl, yr;
+ numeric yl, yr;
+ if (xl >= -@#.v):
+ yl := xl;
+ else:
+ message "Package bpolynomial warning: Replacing lower range boundary " & decimal xl & " by " & decimal -@#.v & "!";
+ yl := -@#.v;
+ fi
+ if (xr >= -@#.v):
+ yr := xr;
+ else:
+ message "Package bpolynomial warning: Replacing upper range boundary " & decimal xr & " by " & decimal -@#.v & "!";
+ yr := -@#.v;
+ fi
+ bpolynomial__getBezierFromPolynomial(@#.a, @#.b, @#.c, @#.d, (@#.eval(yl), yl), (@#.eval(yr), yr))
+ reflectedabout ((0,0),(1,1))
+ enddef;
+
+ %%% This macro returns a path tangent to square root @#
+ %%% at point (x, f(x)) covering the interval [x+xm, x+xp].
+ vardef @#.getTangent(expr x, epsl, epsr)=
+ save m, y;
+ numeric m, y;
+ if (x >= -@#.v):
+ m := @#.u/(2sqrt(x + @#.v));
+ y := @#.eval(x);
+ (x+epsl, y + m*epsl) -- (x+epsr, y + m*epsr)
+ else:
+ message "Package bpolynomial warning: Cannot draw tangent at x = " & decimal x & "!";
+ (-@#.v, @#.w)--(-@#.v, @#.w+1)
+ fi
+ enddef;
+
+enddef;
+
+
+%%% This macro defines a new cubic root.
+%%% Arguments are a suffix macro and the parameters
+%%% of the function u*(x + v)^(1/3) + w.
+vardef newBCubRoot@#(expr cu,cv,cw)=
+numeric @#.a, @#.b, @#.c, @#.d;
+numeric @#.u, @#.v, @#.w;
+ %%% Save parameters for later access.
+ %%% Variable @#.v refers to parameters of cubic root @#.
+ %%% Variables @#.a to @#.d store the coefficients of the
+ %%% corresponding polynomial.
+ @#.u := cu;
+ @#.v := cv;
+ @#.w := cw;
+ @#.a := 1/cu/cu/cu;
+ @#.b := -3cw/cu/cu/cu;
+ @#.c := 3(cw/cu)*(cw/cu)/cu;
+ @#.d := (cw/cu)*(cw/cu)*(cw/cu)-cv;
+
+ %%% This macro returns values of polynomial @#.
+ %%% Argument is an x value.
+ vardef @#.eval(expr x)=
+ if (x >= -@#.v):
+ @#.u*((x+@#.v)**(1/3)) + @#.w
+ else:
+ message "Package bpolynomial warning: Cannot evaluate function at x = " & decimal x & "!";
+ @#.w
+ fi
+ enddef;
+
+ %%% This macro returns the path corresponding to cubic root @#
+ %%% on the intervall [yl, yr]. The path of the corresponing
+ %%% polynomial is computed and then transformed.
+ vardef @#.getPath(expr xl,xr)=
+ save yl, yr;
+ numeric yl, yr;
+ if (xl >= -@#.v):
+ yl := xl;
+ else:
+ message "Package bpolynomial warning: Replacing lower range boundary " & decimal xl & " by " & decimal -@#.v & "!";
+ yl := -@#.v;
+ fi
+ if (xr >= -@#.v):
+ yr := xr;
+ else:
+ message "Package bpolynomial warning: Replacing upper range boundary " & decimal xr & " by " & decimal -@#.v & "!";
+ yr := -@#.v;
+ fi
+ bpolynomial__getBezierFromPolynomial(@#.a, @#.b, @#.c, @#.d, (@#.eval(yl), yl), (@#.eval(yr), yr))
+ reflectedabout ((0,0),(1,1))
+ enddef;
+
+ %%% This macro returns a path tangent to cubic root @#
+ %%% at point (x, f(x)) covering the interval [x+xm, x+xp].
+ vardef @#.getTangent(expr x, epsl, epsr)=
+ save m, y;
+ numeric m, y;
+ if (x >= -@#.v):
+ m := @#.u/3/((x + @#.v)**(2/3));
+ y := @#.eval(x);
+ (x+epsl, y + m*epsl) -- (x+epsr, y + m*epsr)
+ else:
+ message "Package bpolynomial warning: Cannot draw tangent at x = " & decimal x & "!";
+ (-@#.v, @#.w)--(-@#.v, @#.w+1)
+ fi
+ enddef;
+
+enddef;