Welcome to the reference for Koval's 3D Grapher! Here you can find help on everything involving usage of this application, from how to navigate the interface to fine tuning the plot to troubleshooting. Select a topic from the left side of this window to get started.
This is a short guide to plotting a simple function, \(z=\sin{x}+\sin{y}\).
Start with a fresh start by navigating to alankoval.com/3dgrapher. Be sure the expression input is empty and the domain input (the box below "enter expression") contains "\(x, y, z \in [-10, 10]\)" (type "in" for \(\in\) symbol).
In the box immediately above "enter expression," type the following: "z=sin(x)+sin(y)". It will render as such:
With the cursor in the expression input, press the enter key. The plot will take a few seconds to complete.
Click and drag to rotate the plot about the center of view, use the mouse wheel to zoom, and right-click and drag to pan.
This section outlines how to view different sections of the plot by changing the domain of the input variables.
There are 11 separate variables in Koval's 3D Grapher, three for each coordinate system and two parametric variables. Each variable has a domain associated with it, written in the form \(a \in [b, c]\), where \(a\) is a variable and \(b\) and \(c\) are real numbers with \(b < c\). (In order to get the \(\in\) symbol, type "in".)
Above you can see six variables' domains defined, with \(a, b, c \in [i, j]\) being shorthand for \(a \in [i, j], b \in [i, j], c \in [i, j]\). The relevant domains will automatically appear based on the equation typed in the expression input.
In order to change a domain definition, simply click on the definition and edit normally. Domain definitions may go in any order. However, Do not mix domain definitions of different coordinate systems. Since some coordinate systems share variable names, mixing definitions would result in ambiguity.
In general, the domain specifies the extent to which the plot will reach in that variable. For example, if \(x\) is bounded between -5 and 5 (\(x \in [-5, 5]\), no section of the plot will be plotted before \(x=-5\) or after \(x=5\). Likewise, for \(r \in [1, 2]\), no plotted point will satisfy \(x^2 + y^2 + z^2 < 1\) or \(x^2 +y^2 +z^2 > 4\).
However, as one might notice, while the \(r, \theta, \phi, u, v\) and \(\rho\) domain definitions come and go depending on the expression input, the \(x, y,\) and \(z\) definitions never leave. This is because these domain definitions also specify the viewing area. For example, a combination of \(r \in [0, 1]\) and \(x,y,z \in [-10, 10]\) would result in a tiny plot, since \(x^2 +y^2 +z^2 < 1\) is such a small volume in a 20 by 20 by 20 cube.
It is also possible for the viewing area to be non-cubic, for example \(x,y \in [-10, 10], z \in [-5, 5]\). Note that this is distinct from the bounding box shown on screen being rectangular. A non-cubic domain will result in a stretched graph, in this case a two-times stretch in the \(z\) direction only. See the result of this stretching on a sphere, \(r = 7\):
Each plot has its own separate domain definitions. On switching plots (via the tabs above the expression input), the domain input automatically updates values.
However, since the \(x,y,z\) domain definitions also specify viewing area (and clearly there can only be one of them), the viewing area is decided by the extreme values of the domain definitions across all plots. For example, if in plot one there exists a definition \(x,y,z \in [-10, 10]\) and in plot two there is \(x,y \in [-20, -5], z \in [-12, 5]\), the final viewing are would be \( x,y \in [-20, 10], z \in [-12, 10]\).
This section gives a basic overview of the three types of supported coordinate systems (cartesian, cylindrical and spherical) and how to use them in Koval's 3D Grapher.
Variables: \(x, y, z\)
The three coordinates of the cartesian coordinate system relate the perpendicular distance to the \(yz\), \(xz\) and \(xy\) planes, respectively. It is a natural extension of the \(xy\) plane in 2D, with a \(z\) axis coming out of the page.
To use cartesian coordinates, type an equation governed by cartesian coordinates, such as \(z=\sin \left(\sqrt{x^2-y^2}\right)\).
Variables: \(\rho, \phi, z\)
("rho", "phi", "z") in input
The cylindrical coordinate system is defined by the following transformations to cartesian coordinates: \[x = \rho \cos{\phi}\] \[y = \rho \sin{\phi}\] \[z = z\] Thus the cylindrical system is a direct extension of polar coordinates in 2D, where \(r = 1\) is a circle in polar, \(\rho = 1\) is an infinite-length hollow cylinder (hence the name "cylindrical coordinates").
To use cylindrical coordinates, type an equation governed by cylindrical variables, such as \(\rho=3+\phi+\text{abs}(z)\).
Variables: \(r, \theta, \phi\)
("r", "theta", "phi") in input
The spherical coordinate system is defined by the following transformations to cartesian coordinates: \[x=r\cos \left(\theta \right)\sin \left(\phi \right)\] \[y=r\sin \left(\theta \right)\sin \left(\phi \right)\] \[z=r\cos \left(\phi \right)\] Spherical coordinates are another extension of the 2D polar coordinates, but \(\phi\) specifies an angle with the \(z\) axis, as opposed to height in cylindrical coordinates. Where \(r = 1\) is the unit circle in polar coordinates, \(r = 1\) is the unit sphere in spherical coordinates (hence the name).
To use spherical coordinates, type an equation governed by the three spherical variables, such as \(r=\sin 4\theta +\sin 8\phi +5\)
This section defines the usage of parametrically defined plots using the extra variables \(u\) and \(v\).
Koval's 3D Grapher supports both one dimensional lines and two dimensional surfaces. For a line, set a coordinate vector (one of \([x,y,z]\), \([\rho, \phi, z]\) and \([r, \theta, \phi]\)) equal to a vector of equal size comprised of a single variable ((\u\) or \(v\)). For example, \([x,y,z]=u[1,1,1]\) is a line passing through \((0,0,0)\) and \((1,1,1)\):
For a surface, set a coordinate vector equal to a vector of equal size comprised of both \(u\) and \(v\). Here's \(\left[x,y,z\right]=\frac{1}{3}\left[\sin u,0,\cos u\right]+\left[0,v,\sin v+\frac{\cos 4v}{3}\right]\):
This section outlines all the acceptable equation forms that may be entered into Koval's 3D Grapher, such as \(y = 4x + z\) and \([r,\theta,\phi]=[u,v,\sin{u}]\).
Form | Coordinate System | Examples | Notes |
---|---|---|---|
\(z=f(x,y)\) | cartesian, non-parametric |
\(z=\sqrt{x}+y^2\)
\(\sin{x}+e^{xy}=z\)
|
|
\(x=f(y,z)\) | cartesian, non-parametric |
\(x=y+z\)
\(\text{floor}(z) = x\)
|
|
\(y=f(x,z)\) | cartesian, non-parametric |
\(y=\log{x+z}\)
\(e^{-x^2-z^2}=y\)
|
|
\([x,y,z]=f(u,v)\) | cartesian, parametric |
\([x,y,z]=[1,1,1]+u[2,0,0]\)
\(\left[\cos \left(u\right)\cos \left(v\right),\sin \left(u\right)\cos \left(v\right),\sin \left(v\right)\right]=\left[x,y,z\right]\)
\(\left[z,x,y\right]=\left[u,v,u\right]\)
|
Vector arithmetic is supported. See Function and Operator Reference. |
\(\rho=f(\phi,z)\) | cylindrical, non-parametric |
\(\rho=3+\phi+\text{abs}(z)\)
\(\frac{1}{1+\phi ^2}\left(\sin z+2\right)=\rho\)
|
Type "rho" for \(\rho\), "phi" for \(\phi\) |
\(\phi = f(\rho, z)\) | cylindrical, non-parametric |
\(\phi =z+\sin \rho \)
\(\phi =\frac{\rho z}{5}\)
|
Type "rho" for \(\rho\), "phi" for \(\phi\) |
\(z=f(\rho, \phi)\) | cylindrical, non-parametric |
\(z=\cos \rho +\sin 4\phi \)
\(\operatorname{floor}\rho +\phi =z\)
|
Type "rho" for \(\rho\), "phi" for \(\phi\) |
\([\rho,\phi,z]=f(u,v)\) | cylindrical, parametric |
\(\left[\rho ,\phi ,z\right]=\left[v+u,v+\sin u,\sin u\right]\)
\(5\left[u,u,u\right]=\left[z,\rho ,\phi \right]\)
|
Type "rho" for \(\rho\), "phi" for \(\phi\).
Vector arithmetic is supported. See Function and Operator Reference. |
\(r=f(\theta,\phi)\) | spherical, non-parametric |
\(r=\theta +\sin 3\phi \)
\(\operatorname{abs}\left(\operatorname{floor}\phi \right)+5+\sin 3\theta =r\)
|
Type "theta" for \(\theta\), "phi" for \(\phi\). |
\(\theta=f(r,\phi)\) | spherical, non-parametric |
\(\theta =\sqrt{r}+\sqrt{\phi }\)
\(\frac{r}{\frac{1}{2}+\phi ^2}=\theta \)
|
Type "theta" for \(\theta\), "phi" for \(\phi\). |
\(\phi=f(\theta,r)\) | spherical, non-parametric |
\(\phi =\sin r\)
\(\operatorname{floor}\frac{\left(r-\theta \right)}{4}=\phi \)
|
Type "theta" for \(\theta\), "phi" for \(\phi\). |
\([r,\theta,\phi]=f(u,v)\) | spherical, parametric |
\(\left[r,\phi ,\theta \right]=\left[7,u,\sin 5u\right]+\left[\cos v,0,\frac{\sin v}{6}\right]\)
\(\operatorname{cross}\left(\left[1,0,3\right],\left[u,v,u\right]\right)=\left[\theta ,r,\phi \right]\)
|
Type "theta" for \(\theta\), "phi" for \(\phi\). Vector arithmetic is supported. See Function and Operator Reference. |
This section provides background about the rendering of the 3D plotted surface and how the "invert normals" button illuminates the opposite side of the surface.
Koval's 3D Grapher relies heavily on the partial derivatives with respect to \(u\) and \(v\), that is, \(\left(\frac{\partial x}{\partial u},\frac{\partial y}{\partial u},\frac{\partial z}{\partial u}\right)\) and \(\left(\frac{\partial x}{\partial v},\frac{\partial y}{\partial v},\frac{\partial z}{\partial v}\right)\). Since every function (that can be plotted here) can be represented as a parametric function in cartesian coordinates, these values are universal. They give an indication of the amount that each of the coordinate values change as \(u\) and \(v\) changes.
With these vectors, one can derive a normal vector, \(\left(\frac{\partial x}{\partial u},\frac{\partial y}{\partial u},\frac{\partial z}{\partial u}\right) \times \left(\frac{\partial x}{\partial v},\frac{\partial y}{\partial v},\frac{\partial z}{\partial v}\right)\), that is perpendicular to the surface when evaluated at a point \((x,y,z)\). This normal gives a way to compute directional lighting via the Phong Reflection Model. Due to the nature of this model, the "back" of the surface (the normal vector is pointing away from the screen) appears differently from the front.
Hence there exists a button to flip all the normal vectors in a plot, to make the "back" the front and vice versa.
However in the case where both sides of the surface must be lit equally, there is an option to ignore the normal direction in the settings menu ("Ignore Normal when Shading").
This section addresses some common misunderstandings and pitfalls when using Koval's 3D Grapher.
Unfortunately, although a great effort has been made to prevent hangups, occasionally a function never seems to finish plotting. This often is an unforeseen breakdown of the mesh at a discontinuity or other feature. Try changing the mesh quality slightly to "retry" with a different mesh structure.
Perhaps like this?
Congratulations, you have discovered a superposition of two surfaces, one face up and one face down. Usually this is caused by incorrect domain bounds (in this above case, \(r=7\), \(\phi\) had a maximum of \(\pi\) instead of \(\pi/2\)). You can negate its effects by checking the "Ignore Normals" checkbox in the settings menu.
One can create multiple plots on the same set of axes by adding a tab with the plus icon above the equation input. Global options apply to all plots rather than the selected plot.
This is a direct consequence of the setting. For example, a perspective-enabled plot displayed with a perspective-disabled plot would result in identical points mapping to different screen coordinates.
Yes. Type "\random(1)" to get a random number between zero and one.
However, there is a reason this function isn't listed in the function reference. If the random function is used, Koval's 3D Grapher will crash and burn. It is a core assumption that the plotting process is deterministic. This way, sampling can be used to find out more local information about a plot (the input is re-evaluated at every point). If a random function is used, Koval's 3D Grapher can't agree with itself, and so fails miserably.
This section enumerates a list of operators and functions and their definitions that may be used in expressions.
Operator | Description | Example | Notes |
---|---|---|---|
\(+\) | Addition | \(x+y\) | |
\(-\) | Subtraction | \(x-y\) | |
\(*\) | Multiplication | \(x*y\) | \(xy\) also works |
\(/\) | Division | \(\frac{x}{y}\) | |
\(\wedge\) | Exponentiation | \(x^y\) | |
\(<<\) | Bit shift left | \(x<<y\) | \(x\) and \(y\) must be integers. See leftShift below. |
\(>>\) | Bit shift right | \(x>>y\) | \(x\) and \(y\) must be integers. See rightShift below. |
\(!\) | Factorial | \(x!\) | \(x\) must be a positive integer. |
\(\%\) | Modulus | \(x\%y\) | \(y\) must be positive |
Function | Description | Notes |
---|---|---|
\(\text{abs}(x)\) | Absolute Value | |
\(\text{acos}(x)\) | Arccosine (or inverse cosine) | |
\(\text{acosh}(x)\) | Inverse hyperbolic cosine function | |
\(\text{acot}(x)\) | Inverse cotangent function | |
\(\text{acoth}(x)\) | Inverse hyperbolic cotangent function | |
\(\text{acsc}(x)\) | Inverse cosecant function | |
\(\text{acsch}(x)\) | Inverse hyperbolic cosecant function | |
\(\text{asec}(x)\) | Inverse secant function | |
\(\text{asech}(x)\) | Inverse hyperbolic secant function | |
\(\text{asin}(x)\) | Inverse sine function | |
\(\text{asinh}(x)\) | Inverse hyperbolic sine function | |
\(\text{atan}(x)\) | Inverse tangent function | |
\(\text{atan2}(y,x)\) | Inverse tangent function, extends \(\text{atan}(x)\) function to account for all angles. | One must type a backslash, followed by "atan2" followed by a space to use this function. |
\(\text{atanh}(x)\) | Inverse hyperbolic tangent function | |
\(\text{bellNumbers}(n)\) | Returns the \(n^{\text{th}}\) Bell Number. This function only accepts positive integers. | |
\(\text{bitAnd}(x,y)\) | Bitwise AND function. | |
\(\text{bitNot}(x,y)\) | Bitwise NOT function. | |
\(\text{bitOr}(x,y)\) | Bitwise OR function. | |
\(\text{bitXor}(x,y)\) | Bitwise XOR function. | |
\(\text{catalan}(n)\) | Returns the \(n^{\text{th}}\) Catalan Number. This function only accepts positive integers. | |
\(\text{cbrt}(x)\) | Cube root function. Equivalent to raising to the \(1/3\) power. | |
\(\text{ceil}(x)\) | Ceiling function. Returns the smallest integer greater than \(x\) | |
\(\text{combinations}(n,k)\) | Number of combinations of picking \(k\) items from \(n\) items. Note that \(k\leq n\) and both \(k\) and \(n\) are positive integers. | |
\(\text{complex}(r, im)\) | creates a complex number from a real and imaginary part. | |
\(\text{composition}(n,k)\) | The number of ways to represent \(n\) as the sum of \(k\) numbers. | |
\(\text{concat}(x,y,z...)\) | Concatenates two or more matrices together. | |
\(\text{conj}(x)\) | Returns the conjugate of a complex number. | |
\(\text{cos}(x)\) | Cosine function | |
\(\text{cosh}(x)\) | Hyperbolic cosine function | |
\(\text{cot}(x)\) | Cotangent function | |
\(\text{coth}(x)\) | Hyperbolic cotangent function | |
\(\text{cross}(x,y)\) | Returns the cross product of two vectors. | |
\(\text{csc}(x)\) | Cosecant function | |
\(\text{csch}(x)\) | Hyperbolic cosecant function. | |
\(\text{det}(x)\) | Calculates the determinant of a matrix. The matrix must be square. | |
\(\text{distance}(x,y)\) | Calculates the Euclidean distance between two points. The points may be two or three dimensional. | |
\(\text{dot}(x)\) | Calculates the dot product of two vectors. | |
\(\text{dotDivide}(x,y)\) | Calculates the element-wise division of two matrices. | |
\(\text{dotMultiply}(x,y)\) | Calculates the element-wise multiplication of two matrices. | |
\(\text{dotPow}(x,y)\) | Calculates the element-wise power (\(x^y\)) of two matrices. | |
\(\text{exp}(x)\) | Calculates \(e^x\). | |
\(\text{factorial}(x)\) | Calculates the factorial of a number. This is the same as the \(!\) operator. \(x\) must be positive | |
\(\text{fix}(x)\) | Rounds \(x\) toward zero. | |
\(\text{floor}(x)\) | Rounds \(x\) toward negative infinity. | |
\(\text{gamma}(x)\) | The Gamma function. An extension of the factorial function. | |
\(\text{gcd}(x,y)\) | Computes the greatest common divisor among \(x\) and \(y\) | |
\(\text{hypot}(x,y,...)\) | Calculates the hypotenuse of the values. This is equal to \(\sqrt{x^2+y^2...}\) | |
\(\text{im}(x)\) | Returns the imaginary portion of \(x\). | |
\(\text{inv}(x)\) | Calculates the inverse of a matrix. The matrix must be square. | |
\(\text{kldivergence}(x,y)\) | Computes the Kullback-Leibler divergence between two distributions | |
\(\text{lcm}(x)\) | Calculates the least common multiple of two numbers. | |
\(\text{leftShift}(x, y)\) | Bitwise shifts \(x\) left by \(y\) bits. For all you programmers it is equal to \(x << y\) | |
\(\text{log}(x, y)\) | Calculates \(\log_y{x}\). If \(y\) is omitted, then it defaults to \(\log_{e}{x}\). | |
\(\text{max}(x, y, ...)\) | Calculates the maximum value out of the inputs. | |
\(\text{mean}(x, y,...)\) | Calculates the mean of the inputs. | |
\(\text{median}(x, y,...)\) | Calculates the median of the inputs. | |
\(\text{min}(x, y, ...)\) | Calculates the minimum value out of the inputs. | |
\(\text{mod}(x, y)\) | Calculates \(x\,\%\,y\) (for programmers), also known as the modulus. | |
\(\text{mode}(x, y, ...)\) | Calculates the most common value among the inputs. | |
\(\text{nthRoot}(x, n)\) | Calculates the \(n^{\text{th}}\) root of \(x\). \(n\) defaults to two if not provided. | |
\(\text{re}(x)\) | Returns the real part of the complex number \(x\) | |
\(\text{rightArithShift}(x, y)\) | Bitwise shifts \(x\) right arithmetically by \(y\) bits. For all you programmers it is equal to \(x >> y\) | |
\(\text{rightLogShift}(x, y)\) | Bitwise shifts \(x\) right logically by \(y\) bits. It is equal to \(x >>> y\) | |
\(\text{round}(x, n)\) | Rounds \(x\) to \(n\) decimal places. Default for \(n\) is zero. | |
\(\text{sec}(x)\) | Calculates the secant of \(x\). | |
\(\text{sech}(x)\) | Calculates the hyperbolic secant of \(x\). | |
\(\text{sign}(x)\) | Calculates the sign of \(x\). This is \(-1\) when \(x<1\), \(1\) when \(x>1\) and \(0\) when \(x=0\). | |
\(\text{sin}(x)\) | Calculates the sine of \(x\) | |
\(\text{sinh}(x)\) | Calculates the hyperbolic sine of \(x\) | |
\(\text{sqrt}(x)\) | Calculates the square root of \(x\) | |
\(\text{std}(x,y,...)\) | Calculates the standard deviation of the inputs. | |
\(\text{stirlingS2}(x,y)\) | Calculates the stirling number of the second kind | One must type a backslash, followed by "stirlingS2", then a space to use this function. |
\(\text{tan}(x)\) | Calculates tangent of \(x\). | |
\(\text{tanh}(x)\) | Calculates hyperbolic tangent of \(x\). | |
\(\text{trace}(x)\) | Calculates trace of matrix \(x\), the sum of the elements on the main diagonal. \(x\) must be square. | |
\(\text{transpose}(x)\) | Reflects each element of the square matrix \(x\) over its main diagonal. | |
\(\text{var}(x,y,...)\) | Computes the variance of the inputs as a list. |
Don't see the function you'd like? Check out the full list of functions from mathjs.org, at your own risk, of course.
This sections illuminates some of the algorithms that drive the mesh generation and graphing mechanism of Koval's 3D Grapher. So what happens when you press enter?
Based on the type of equation, the expression is converted into a parametric form via straightforward transformations between coordinate systems. For example \(r=1\) becomes \(\left[x,y,z\right]=\left[\cos u\sin v,\sin u\sin v,\cos v\right]\).
All domain definitions are read. The bounds of parametric variables, if not explicitly defined, are computed based on the domains of the dependant variables in the equation.
The domain is separated into nine square (in \(uv\) coordinates) chunks, which are sent to web workers to plot separately in the background. This is why one can see a 3 by 3 grid if "show mesh while rendering" is checked.
Each worker plots a few points in the center of the domain. If the numerically calculated value of \(\left(\frac{\partial x}{\partial u},\frac{\partial y}{\partial u},\frac{\partial z}{\partial u}\right)\) or \(\left(\frac{\partial x}{\partial v},\frac{\partial y}{\partial v},\frac{\partial z}{\partial v}\right)\) is equal to \((0,0,0)\), a one dimensional line is constructed, else a surface.
A front is created of active points -- the points on the edge of the surface. These points are dealt with in order of \(uv\) distance from the seed point.
As each point is considered, the partial derivatives at that point are calculated and used to judge the \(uv\) distance at which new neighbors are to be created. The angle formed by the surrounding front is used to determine how many neighbors to add. These neighbors are tentatively plotted, and the result is used to compute a value indicating how small the distance to the neighbors should be.
All of the neighbors are then replotted at this newly calculated distance, and a several-pass spacing algorithm is used to spread out neighbors that may be compressed by curvature. Crucially, some neighbors are added or culled to prevent an excess or shortage of connecting points over time.
These neighbors are then officially plotted and added to the point front. They will later compute their own neighbors, and the cycle continues until the entire domain has been covered.
Using a carefully chosen function, points outside the \(xyz\) domain are mapped into a region just outside the domain, so that the mesh can quickly spread past regions outside the domain and back into important territory.
Functions like \(z=\operatorname{round}x\) are unique in that there are discontinuities between successive integers in the \(x\) direction. After plotting is finished, edges that have a length greater than expected are re-examined. If successively tests fail to find a point that bisects the distance between the nodes at the end of the edge, the edge is removed as a discontinuity.
Points which have an imaginary component are also removed at roughly the same time.
Removing edges and points can leave ugly, rough surfaces. A binary search is used to find the boundaries between real points and imaginary points and at discontinuities.
The mesh is compiled into a polygon buffer and sent back to the main thread. When drawing, perspective and directional lighting are applied as the point is rotated and scaled to the correct position, as specified by the view point. If there is transparency, all the partially opaque polygons are sorted and compiled into a single buffer for rendering by WebGL.
My name is Alan Koval, a freshmen at the University of Minnesota. I am currently studying mathematics and computer science. You can find more about me on my website homepage, alankoval.com
Math library: math.js
Latex rendering and input boxes: Mathquill
Font: Frank Grießhammer
Link icon: Danilo De Marco