Functional line coloring
|Optional||Color function (see below)|
These options accept functions that define the color of a plot at arbitrary points.
the user can control the color of many graphical objects. The setting
providing the most detailed (and most complicated) control is
In this case, a color function must be provided
using one of
A color function can be a list of three or four expressions.
If three expressions are given, they specify RGB colors. If four expressions are given, they specify RGBA colors. See the introduction for more details on color specifications.
The expressions may contain the identifiers bound in the corresponding
object. For example, in a
the color function may refer to
x. More formally,
the expressions may contain the identifiers found in the attributes
the plot object they are found in.
All of these expressions must, for values in the given ranges, evaluate to real numbers in the range . Real values outside this range do not yield errors, they are simply clipped.
See also Example 1.
Alternatively, a color function can be a procedure or function environment.
A procedure (or a function environment) used as a color function must return lists of three or four real numbers in the range . Real values outside this range are clipped. (If this function ever returns a list of four numbers, it must always do so.) A list of three numbers is interpreted as an RGB color, while a list of four values is interpreted as an RGBA color. See the introduction for more details on color specifications.
The number and meaning of arguments a color function is called with depends on the object type. Informally, we have:
Additionally, for animated objects, the current value of the animation parameter is provided.
Tetrahedron are built from triangles;
the color functions are called once for each vertex of these triangles
and are passed the number of the triangle (an integer count starting
at 1), the coordinates of
the vertex and the animation parameter, if that is used.
the color functions are given the coordinates of the currently visited
point on the central curve, followed by the coordinates of the point
on the surface, followed by the animation parameter, if any. (That
makes seven arguments altogether.)
The examples below show different usage environments of color functions for some of the object types listed above.
By default, most 3D-objects in MuPAD® get "height coloring":
To change the direction of this color, you can use
xmin := -5: xmax := 5: color := zip(RGB::Red, RGB::CornflowerBlue, (a, b) -> (x-xmin)/(xmax-xmin)*a +(xmax-x)/(xmax-xmin)*b)
plot(plot::Function3d(sin(x)*y^3, FillColorFunction = color))
Animated color functions can be combined with static objects:
plot( plot::Curve2d([sin(3*x), sin(4*x + 1)], x = 0..2*PI, LineColorFunction = ((u, x, y, a) -> [(u-a)/5, (u-a)/5, 1]), a = -5..6) )
cf := (i, x, y, z, a) -> [RGB::Red, RGB::Green, RGB::Blue][(floor(a*i) mod 3) + 1]: plot(plot::Icosahedron(FillColorFunction = cf, a = 0..9))
rgb := (u, v, x, y, z) -> [x, y, z]: plot(plot::Surface(formula, u = 0..1, v = 0..1, FillColorFunction = rgb) $ formula in [[0, u, v], [1, u, v], [u, 0, v], [u, 1, v], [u, v, 0], [u, v, 1]], plot::Box(0..1, 0..1, 0..1, Filled = FALSE, LineColor = RGB::Black.[0.25]), Scaling = Constrained, Axes = None, ULinesVisible = FALSE, VLinesVisible = FALSE, Lighting = None, CameraDirection = [4, 7, 3])
RGB colors are a very technical way of defining a color. The HSV color space is more popular with designers, since there the "hue" (i.e., the perceived color type) is not a combination of three numbers but rather one of the numbers making up a color:
hsv := (u, v, r, phi, z) -> RGB::fromHSV([180/PI*phi, r, z]): plot(plot::Cylindrical([z, phi, z], z = 0..1, phi = 0..2*PI, FillColorFunction = hsv), plot::Cylindrical([r, phi, 1], r = 0..1, phi = 0..2*PI, FillColorFunction = hsv), plot::Circle3d(1, [0, 0, 1], [0, 0, 1], Color = RGB::Black.[0.25]), ZXRatio = 1.5, Scaling = Unconstrained, Axes = None, Lighting = None, ULinesVisible = FALSE, VLinesVisible = FALSE, CameraDirection = [-17, -12, 3])
hsv := (u, v, r, phi,thet) -> RGB::fromHSV([180/PI*(phi+(thet+2)^3/PI^2), 3/4+sin(u)/4, 1]): plot(plot::Spherical([1, u, v], u = 0..2*PI, v = 0..PI, FillColorFunction = hsv))
There are other examples, where the cyclic nature comes in handy, too:
hsv := (x, y, z) -> RGB::fromHSV([150*z, 1, 1]): plot(plot::Function3d(sin(x*y)*(x-y), x = -3..3, y = -3..3, Submesh = [2, 2], FillColorFunction = hsv))
The following example takes a long time to compute. Reducing
the values set for
Mesh results in a shorter computation,
while higher values lead to an image with finer details:
c := 0.377+0.2*I: julia := proc(x, y) local i, z; begin i := 0; z := float(x + I*y); while i < 1000 and abs(z) < 4 do z := z^2 + c; i := i + 1; end_while; i; end_proc: Jcol := (x, y, i) -> if i >= 1000 then RGB::Black else RGB::fromHSV([i, 1, 3/4+i/2000]) end: plot(plot::Density(julia, x = 0..0.5, y=0.25..0.75, FillColorFunction = Jcol, Mesh = [100,75]))
Another way of getting a smooth color transition is to use a
periodic function in between, for example trigonometric ones (note
(1+sin(a))/2: we need values between 0 and 1):
plot( plot::Polar([r*surd(r, 3), r], r = -4*PI..4*PI, AdaptiveMesh = 2, LineColorFunction = [(sin(r) + 1)/2, (cos(r/2) + 1)/2, 1/3], LineWidth = 1*unit::mm) )
This also applies for cyclic colors in terms of time:
plot(plot::Function3d(sin(x)+sin(y), x = -5..5, y = -5..5, FillColorFunction = [(x+5)/10, (y+5)/10, abs(x+y+5*cos(a))/15, (1+cos(x+y^2-a))/2], a = 0..2*PI), CameraDirection = [-1, -3, 3], Scaling = Constrained)
Animation is handled by the general framework, not the individual objects. Therefore, the framework also supplies the animation parameter to the color functions.