Documentation

# `export`::`stl`

Export STL data

MuPAD® notebooks will be removed in a future release. Use MATLAB® live scripts instead.

MATLAB live scripts support most MuPAD functionality, though there are some differences. For more information, see Convert MuPAD Notebooks to MATLAB Live Scripts.

## Syntax

```export::stl(`filename`, `[x, y, z]`, `u = umin .. umax`, `v = vmin .. vmax`, `options`)
export::stl(`n`, `[x, y, z]`, `u = umin .. umax`, `v = vmin .. vmax`, `options`)
export::stl(`filename`, `object1`, <`object2, …`>, `options`)
export::stl(`n`, `object1`, <`object2, …`>, `options`)
```

## Description

`export::stl` is used to create a triangulation of a parametrized surface and write the triangulation data in STL format to an external file.

STL files contain triangulation data of 3D surfaces. Each triangle is stored as a unit normal and three vertices. The normal and the vertices are specified by three coordinates each, so there is a total of 12 numbers stored for each triangle. Read the “Background” section of this help page for further details.

If the surface is closed, it is regarded as the boundary of a 3D solid. The normals of the triangles written into the STL file should point from the inside of the body to the outside.

### Note

Note that the direction of the normals that `export::stl` writes into the STL file depend on the parametrization x(u, v), y(u, v), z(u, v)!

If ```p1 = (x(u, v), y(u, v), z(u, v))```, ```p2 = (x(u + du, v), y(u + du, v), z(u + du, v))```, ```p3 = (x(u, v + dv), y(u, v + dv), z(u, v + dv))``` are the corners of a triangle, the normal associated with this triangle is the cross product of the side `p2 - p1` times the side `p3 - p2`. The routine `export::stl` chooses neighboring values of the surface parameters with ```du = (`u_{max}` - `u_{min}`)/(n_u - 1)``` and `dv = (`v_{max}` - `v_{min}`)/(n_v - 1)`, respectively.

### Note

Thus, if your parametrization is such that the cross product of the vectors `p2 - p1` and ```p3 - p2``` does not point to the outside of your body, you just need to let one of the parameters (`u`, say) run from `umax` to `umin` instead of from `umin` to `umax`. Just replace your call

```export::stl(filename, [x,y,z], u = `u_{min}` .. `u_{max}`, v = `v_{min}` .. `v_{max}`)```

by

```export::stl(filename, [x,y,z], u = `u_{max}` .. `u_{min}`, v = `v_{min}` .. `v_{max}`)```.

Up to the irrelevant ordering in the STL file, the triangles generated by these calls are the same apart from the direction of the normal associated with each triangle.

If the file is specified by a character string, the corresponding file is opened and closed, automatically.

As an alternative to specifying the file by a string, the user may open the file herself via `fopen` in `Write` mode and pass the file descriptor returned by `fopen` to `export::stl`. If binary data are to be written to the file, make sure that it is opened with the `Raw`, i.e., call ```fopen(filename, Write, Raw)```.

### Note

Note that `export::stl` does not close the file automatically if it is specified by a file descriptor. It remains open after `export::stl` has finished its job. The file needs to be closed explicitly by the user using `fclose`.

If the file is specified by a character string, the name may correspond to an absolute or a relative path name. In particular, the environment variable `WRITEPATH` is taken into account. The details on the help page of `fopen` hold for `export::stl`, too.

### Note

With the option `Append`, the file is first opened for reading and, after reading of the data in the file, opened for writing. If no absolute pathname is used to specify the file, make sure that the environment variables `READPATH` and `WRITEPATH` point to the same folder. Alternatively, it is a good idea to place the file in the same folder as the MuPAD® notebook which you are currently using. If this notebook is saved on the disk of your computer, the absolute path is available as the environment variable `NOTEBOOKPATH`. Thus, specifying a file named “myfile.stl”, say, by the absolute path name `NOTEBOOKPATH."myfile.stl"` ensures that the file is found in the same folder as your notebook.

Text files generated with the option `Text` or the equivalent `Ascii` can be opened and read with any text editor. However, binary files generated with the option `Bin` or the equivalent options `Binary` or `Raw` are faster to create and to process.

The file generated by `export::stl` can be read and visualized in MuPAD using the plot primitive `plot::SurfaceSTL`.

If the file name given ends in “`.gz`”, `export::stl` writes a compressed file which can be read by any program supporting `gzip` compression.

## Environment Interactions

The function is sensitive to the environment variable `DIGITS` which determines the numerical working precision. The current value of `DIGITS` determines the number of significant decimal digits with which the STL data are written to the specified file. (This holds for text files. In binary STL files all numerical values have a precision of about 7 decimal digits.) For the internal computation of the data by MuPAD, the value of `DIGITS` is temporarily increased by 10 to minimize round-off effects.

The STL data generated by `export::stl` are written to the specified file.

## Examples

### Example 1

We generate a sphere given by the following parametrization:

```x:= cos(u)*sin(v): y:= sin(u)*sin(v): z:= cos(v):```

We call `export::stl` to generate the STL data and write them into a file named “sphere.stl”. The file is to be generated in the same directory as the current MuPAD notebook that we are using. Hence, we specify an absolute path name for the file using the path of the current notebook. If this notebook was saved to the disk of your computer, this path is available in the environment variable `NOTEBOOKPATH`:

```filename:= NOTEBOOKPATH."sphere.stl": export::stl(filename, [x, y, z], u = 0 .. 2*PI, v = 0 .. PI, Text)```

Since the file was created in `Text` format, it can be opened with any text editor. It should look like this:

```solid MuPADtoSTL1 facet normal -0.06540070486 -0.008610166138 -0.9978219344 outer loop vertex 100.0 100.0 300.0 vertex 112.607862 103.3782664 298.7167292 vertex 113.0526192 100.0 298.7167292 endloop endfacet facet normal -0.1950260058 -0.02567566076 -0.9804619409 outer loop vertex 113.0526192 100.0 298.7167292 vertex 112.607862 103.3782664 298.7167292 vertex 125.0 106.6987298 294.8888739 endloop endfacet ... endsolid MuPADtoSTL1 ```

We reimport the STL data and visualize the surface using `plot::SurfaceSTL`:

`plot(plot::SurfaceSTL(filename, MeshVisible))` We reduce the number of significant output digits to a reasonable size. Further, we specify a mesh size and request a specific output box:

```DIGITS:= 7: export::stl(filename, [x, y, z], u = 0..2*PI, v = 0..PI, Mesh = [10, 10], OutputBox = [-100..100, -100..100, -100..100], Text):```

The file now should look like this:

```solid MuPADtoSTL2 facet normal -0.1733024 -0.06307691 -0.9828467 outer loop vertex -3.10912 0.000000002143114 100.0 vertex 24.32249 22.66816 93.96926 vertex 32.7003 0.000000002143114 93.96926 endloop endfacet ... endsolid MuPADtoSTL2 ```

We visualize the new content of the file:

`plot(plot::SurfaceSTL(filename, MeshVisible))` `delete x, y, z, filename, DIGITS:`

### Example 2

We specify the parametrization of the surface by a mixture of expressions and procedures:

```x:= piecewise([0.1 < u < 0.9, u*cos(v)], [Otherwise, 0]): y:= (u, v) -> piecewise([0.1 < u < 0.9, u*sin(v)], [Otherwise, 0]): z:= (u, v) -> if u <= 0.1 then exp(-0.1) elif u < 0.9 then exp(-u) else exp(-0.9) end_if:```

This is the surface that we wish to export to STL:

```plot(plot::Surface([x, y, z], u = 0..1, v = 0..2*PI, Mesh = [100, 36])):``` We assume that there is no external file “sample.stl”. We create it by opening it in `Write` mode in the same directory as the current MuPAD notebook that we are using. Hence, we specify an absolute path name for the file using the path of the current notebook. If this notebook was saved to the disk drive of your computer, this path is available in the environment variable `NOTEBOOKPATH`. The file descriptor `n` returned by `fopen` is passed to `export::stl`:

```filename:= NOTEBOOKPATH."sample.stl": DIGITS:= 7: export::stl(filename, [x, y, z], u = 0..1, v = 0..2*PI, Mesh = [30, 36])```

We reimport the STL data and visualize the surface using `plot::SurfaceSTL`:

`plot(plot::SurfaceSTL(filename, MeshVisible))` We can append a further surface to the file using the option `Append`:

```export::stl(filename, [x, y, -z], u = 0..1, v = 0..2*PI, Mesh = [30, 36], OutputBox = [0..100, 0..100, -100..0], Append)```

We visualize the new content of the file via `plot::SurfaceSTL`:

`plot(plot::SurfaceSTL(filename, MeshVisible))` `delete x, y, z, filename, DIGITS:`

### Example 3

We wish to create a closed surface consisting of a “bowl” with a “lid”.

```bowl:= [u*cos(v), u*sin(v), u^2], u = 0 .. 1, v = 0 .. 2*PI: lid:= [u*cos(v), u*sin(v), 1 ], u = 0 .. 1, v = 0 .. 2*PI:```
```filename:= NOTEBOOKPATH."sample.stl": DIGITS:= 7: export::stl(filename, bowl, Mesh = [30, 36]): export::stl(filename, lid, Mesh = [30, 36], Append): plot(plot::SurfaceSTL(filename), Scaling = Constrained):``` `delete filename, DIGITS:`

### Example 4

We demonstrate the options `Scaling` = `Constrained` and `Scaling` = `Unconstrained`. With `Scaling` = `Constrained`, the coordinates given by the parametrization `x, y, z` are scaled by the same factor to fit the surface into the output box. Here, we create a sphere of radius 1. The output box is not a cube: the range for the `z` coordinate is notably larger than for `x` and `y`. Nevertheless, the sphere stays a sphere when using `Scaling` = `Constrained`. However, the output box is not completely filled by the sphere:

```x:= cos(u)*sin(v): y:= sin(u)*sin(v): z:= cos(v): DIGITS:= 7: filename:= NOTEBOOKPATH."sphere.stl": export::stl(filename, [x, y, z], u = 0 .. 2*PI, v = 0 .. PI, OutputBox = [-1 .. 1, -1 .. 1, -3 .. 3], Scaling = Constrained): plot(plot::SurfaceSTL(filename, Scaling = Constrained, MeshVisible))``` With `Scaling` = `Unconstrained`, the sphere is deformed to an ellipsoid filling the output box:

```export::stl(filename, [x, y, z], u = 0..2*PI, v = 0..PI, OutputBox = [-1..1, -1..1, -3..3], Scaling = Unconstrained): plot(plot::SurfaceSTL(filename, Scaling = Constrained, MeshVisible))``` `delete x, y, z, filename, DIGITS:`

## Parameters

 `filename` A file name: a non-empty character string `n` A file descriptor provided by `fopen`: a positive integer ```object1, object2, …``` 3D graphical objects of the `plot` library `x`, `y`, `z` The coordinate functions: arithmetical expressions or `piecewise` objects depending on the surface parameters u and v. Alternatively, procedures that accept 2 input parameters u, v and return a numerical value when the input parameters are numerical. `u` The first surface parameter: an identifier or an indexed identifier. `umin .. umax` The range for the parameter u: `umin`, `umax` must be numerical real values. `v` The second surface parameter: an identifier or an indexed identifier. `vmin .. vmax` The range for the parameter v: `vmin`, `vmax` must be numerical real values.

## Options

`Mesh`

Option, specified as `Mesh = [nu, nv]`

Sets the mesh size: the integer `nu` determines, how many equidistant points in the `u` direction are used to sample the parametrization `x, y, z` numerically. Correspondingly, the integer `nv` determines, how many equidistant points in the `v` direction are used. Thus, a regular mesh of (nu - 1) (nv - 1) rectangles is used. Each rectangle is split into 2 triangles, resulting in a triangulation consisting of 2 (nu - 1) (nv - 1) triangles. The default is ```Mesh = [25, 25]```.

`OutputBox`

Option, specified as ```OutputBox = [xmin .. xmax, ymin .. ymax, zmin .. zmax]```

By default, the coordinates of the mesh points defining the STL object are written into the file as provided by the parametrization of the surface. Thus, if several objects are written into the file via the option `Append`, the position of the objects in space is transparent and can be controlled by the user via a suitable parametrization. However, many devices such as Rapid Prototyping tools with which the STL file shall be processed, impose severe restrictions on the data in the STL file. E.g., the original STL specification requires that the x, y, z coordinates of the mesh points are positive. Many devices require that the coordinates must lie in a prescribed range (between 0 and 100, say). The option `OutputBox` provides a simple mean to shift and scale the coordinates given by the parametrization to a prescribed range.

The option ```OutputBox = [ xmin.. xmax, ymin.. ymax, zmin.. zmax]``` sets the output box defined by numerical values ```xmin, …, zmax```. The mathematical coordinates `x(u, v), y(u, v), z(u, v)` with `u`, `v` ranging from `umin` to `umax` and from `vmin` to `vmax`, respectively, are shifted and scaled such that the output coordinates written to the STL file range between the values `xmin` and `xmax`, `ymin` and `ymax`, `zmin` and `zmax`.

### Note

If several objects are written to the file via the option `Append`, only the very last call of `export::stl` should bear the option `OutputBox`!

This last call shifts and scales all coordinates of all surfaces inside the file such that the entire scene of objects fits into the output box. The relative size and positions of the objects are preserved.

See Example 3.

This option is rather expensive since all data in the STL file need to be modified!

This option is not available if the file was opened outside `export::stl` and passed by a file descriptor `n`.

`Scaling`

Option, specified as `Scaling = Unconstrained` or ```Scaling = Constrained```

With `Scaling = Unconstrained`, the surface is scaled by different factors in the x, y, and z direction, such that it fills the output box set by the option ```OutputBox - [`x_{min}` .. `x_{max}`, `y_{min}` .. `y_{max}`, `z_{min}` .. `z_{max}`] ```. Thus, the output coordinates of a sphere define an ellipsoid with diameters given by the side lengths of the output box. This is the default setting.

With `Scaling = Constrained`, the surface is scaled by the same factor in the x, y, and z direction such that it fits into the output box set by the option ```OutputBox = [`x_{min}` .. `x_{max}`, `y_{min}` .. `y_{max}`, `z_{min}` .. `z_{max}`] ```. A sphere will remain a sphere even if the sides of the output box have different lengths.

This option is ignored if not used in conjunction with the `OutputBox` option.

`Ascii`, `Bin`, `Binary`, `Raw`, `Text`

With the synonymous flags `Bin`, `Binary`, or `Raw`, respectively, the STL file is created as a binary file. If a binary file is specified by a file descriptor `n`, make sure that is was opened by the command `n:= fopen(filename, Write, Raw)`. With the synonymous flags `Text` and `Ascii`, respectively, the STL file is created as a text file. The default is `Bin`.

`Append`

With this flag, the STL data of the surface are appended to an existing STL file named “filename”. If no such file exists, it is created and processed as without `Append`. This option is not available if the file was opened outside `export::stl` and passed by a file descriptor `n`.

## Return Values

`null()` object.

## Algorithms

There are two storage formats available for STL files, which are ASCII and BINARY. ASCII files are human-readable while BINARY files are smaller and faster to process. Both ASCII as well as BINARY files can be generated by `export::stl`. A typical ASCII STL file looks like this:

``` solid sample facet normal -4.470293E-02 7.003503E-01 -7.123981E-01 outer loop vertex -2.812284E+00 2.298693E+01 0.000000E+00 vertex -2.812284E+00 2.296699E+01 -1.960784E-02 vertex -3.124760E+00 2.296699E+01 0.000000E+00 endloop endfacet ... endsolid sample ```

STL BINARY files have the following format:

``` Bytes Type Description 80 ASCII header, no data significance 4 uint number of facets in file 4 float normal x - start of facet 4 float normal y 4 float normal z 4 float vertex1 x 4 float vertex1 y 4 float vertex1 z 4 float vertex2 x 4 float vertex2 y 4 float vertex2 z 4 float vertex3 x 4 float vertex3 y 4 float vertex3 z 2 byte not used - end of facet ... ```

Facet orientation: The facets define the surface of a 3D object. As such, each facet is part of the boundary between the interior and the exterior of the object. The orientation of the facets (which way is "out" and which way is "in") is specified redundantly in two ways which should be consistent. First, the direction of the normal is outward. Second, which is most commonly used nowadays, the facet vertices are listed in counter-clockwise order when looking at the object from the outside (right-hand rule).

Vertex-to-vertex rule: Each triangle must share two vertices with each of its adjacent triangles. In other words, a vertex of one triangle cannot lie on the side of another.

Axes: The format specifies that all vertex coordinates must be strictly positive numbers. However, it seems that – with a few exceptions – most software used today (MuPAD included) allow negative coordinates as well.

Units: The STL file does not contain any scale information; the coordinates may be interpreted in arbitrary units.

Further details about the STL file format are available in the web, e.g., at:

• www.ennex.com/fabbers/StL.asp,

• www.math.iastate.edu/burkardt/data/stl/stl.html and

• rpdrc.ic.polyu.edu.hk/content/stl/stl_introduction.htm.

Collections of STL sample files can be found in the web, e.g., at:

• www.wohlersassociates.com/Software-for-Rapid-Prototyping.html and

• www.cs.duke.edu/~edels/Tubes.

Information about rapid prototyping technologies is available in the web, e.g., at: