English

Numpy-stl – a Python Library for STL data manipulation –

Python has a good library for STL control.

“numpy-stl”

numpy-stl needs to be installed by

pip install numpy-stl

This page explains how to control STL data with numpy-stl.

As an example, a dog stl data is used.


“dog.stl” downloaded fromfree3d.com

0. Install numpy-stl

Numpy-stl is distributed by pip.

pip install numpy-stl

finishes the installation.

In python script, numpy-stl is generally imported by

from stl import mesh

import numpy as np
from stl import mesh

1. Read STL file

stl_data = mesh.Mesh.from_file(‘stl_file_name’)

stl_data = mesh.Mesh.from_file('dog.stl')
# the data of the stl file is input in stl_data

This ‘stl_data’ is an object of numpy-stl.

2. Save STL data

stl_data.save(‘target_stl_file_name’)

This command save numpy-stl object as a stl data file.

stl_data.save('dog_copied.stl')

3. Translate or Rotate STL data

Translate STL data

stl_data.translate(a vector of translation :numpy.array)

For example, move ‘dog.stl’ file
+10 along the X axis, +20 along the Y axis and +30 along the Z axis.

import numpy as np
from stl import mesh

stl_data = mesh.Mesh.from_file('dog.stl')

t = np.array([10, 20, 30])
stl_data.translate(t)
stl_data.save('dog_translated.stl')

Gray:dog.stl(pre-translation) Green:dog_translated.stl(post-translation)

Rotate STL data

stl_data.transform(4×4 matrix)

This transformation can be used in many ways.
Translation and rotation can be performed at the same time.

4×4 matrix which contains 3×3 rotatio nmatrix “M” and \((t_x, t_y, t_z)\) translation is described as,

\(R =
\left(
\begin{array}{ccc|c}
& & & t_x\\
& \Large{M} & & t_y\\
& & & t_z\\
\hline
& \large{0} & & 1
\end{array}
\right)\)

Script transformation script

stl_data.transform(R)

overwrite the object data in “stl_data”.

For example,

let’s rotate the dog model 60° around the Z axis.

\(\theta\) rotation around the Z axis is described as

\(
\begin{pmatrix}
\cos \theta & – \sin \theta & 0 \\
\sin \theta & \cos \theta & 0 \\
0 & 0 & 1
\end{pmatrix}\)
(\(\theta\) : radian)

stl_data = mesh.Mesh.from_file('dog.stl')

matrix = np.array([[np.cos(np.deg2rad(60)), - np.sin(np.deg2rad(60)), 0],
                   [np.sin(np.deg2rad(60)), np.cos(np.deg2rad(60)), 0],
                   [0, 0, 1]])
#np.deg2rad() changes the angles from degrees to radians. 

R[:3, :3] = matrix
print(R)
stl_data.transform(R)
stl_data.save('dog_z_rotated60.stl')

Gray: dog.stl Green: dog_z_rotated60.stl

The model has been rotated aound the Z axis.

4. Rotate STL data around a given axis

stl_data.rotate(axis vector, angle(radian))

Rotation around a given axis vector is performed by this script type.

For example,
let’s rotate the model around a vector,
x, y, z = [1, -1, 1].

import numpy as np
from stl import mesh

stl_data = mesh.Mesh.from_file('dog.stl')

stl_data.rotate(np.array([1, -1, 1]), np.deg2rad(30))
#np.deg2rad() is a function to change angles from degrees to radians
stl_data.save('dog_axis_rotated30.stl')

stl_data.rotate(np.array([1, -1, 1]), np.deg2rad(30))
stl_data.save('dog_axis_rotated60.stl')

stl_data.rotate(np.array([1, -1, 1]), np.deg2rad(30))
stl_data.save('dog_axis_rotated90.stl')

Gray: dog.stl Yellow: dog_axis_rotation30.stl
Green: dog_axis_rotation60.stl Red: dog_axis_rotation90.stl

5. Get Properties of STL Data

Point Cloud from a STL data

points = stl_data.points.reshape([-1, 3])
# extract vertices of the triangle faces
point_list = numpy.unique(points, axis=0)
# delete overlapped points

stl_data has “.points” property.


stl_data = mesh.Mesh.from_file('dog.stl')
print(stl_data.points)

[[15.047313 8.529594 -0.49951768 … 14.859968 8.67889
-0.73027855]
[15.047313 8.529594 -0.49951768 … 14.820316 8.625533
-0.5090847 ]
[15.000342 8.477547 -0.26739568 … 14.820316 8.625533
-0.5090847 ]

[21.150438 0.15598121 16.239843 … 21.205637 0.23986353
16.229225 ]
[21.205637 0.23986353 16.229225 … 21.260057 0.31812167
16.235666 ]
[21.205637 0.23986353 16.229225 … 21.255892 0.32407686
16.221685 ]]

# 9 numbers in a raw

stl_data.points consists of 9 numbers which represent xyz of the 3 points of one mesh triangle.
These numbers should be reshaped to get point cloud.

points = stl_data.points.reshape([-1, 3])
print(points)

[[15.047313 8.529594 -0.49951768]
[15.090207 8.585484 -0.7257249 ]
[14.859968 8.67889 -0.73027855]

[21.205637 0.23986353 16.229225 ]
[21.260057 0.31812167 16.235666 ]
[21.255892 0.32407686 16.221685 ]]

#points are the vertices of the triangle faces.

Verteces are overlapped because some triangles have the common vertices.

Delete these overlaps by numpy.unique.


print(len(points))
# 298272
point_list = np.unique(points, axis=0)
print(len(point_list))
# 49714
print(point_list)

[[-5.7769 16.6657 0.4585]
[-5.7701 16.8729 0.5121]
[-5.7679 16.8331 0.6828]

[ 5.7679 16.8331 0.6828]
[ 5.7701 16.8729 0.5121]
[ 5.7769 16.6657 0.4585]]

Properties like Center of Mass, Volume, Inertial Tensor

Volume, Center of Mass, Inertial tensor = stl_data.get_mass_properties()

stl_data = mesh.Mesh.from_file('dog.stl')
volume, cog, inertia = dog_stl.get_mass_properties()
print(volume)
# Volume
# 1768.901177949426
print(cog)
# Center of Mass
# [-4.68314523e-08,  8.22629170e-01,  1.35953082e+01]
print(inertia)
# Inertial Tensor
# [[ 1.58685377e+05  6.46135023e-04 -1.40242942e-04]
# [ 6.46135023e-04  4.95679782e+04  3.62822773e+04]
# [-1.40242942e-04  3.62822773e+04  1.29808852e+05]]

Let’s set the origin at the center of mass of the object.

stl_data.translate(-com)
stl_data.save('dog_centered.stl')


Gray: dog.stl Green: dog_centered.stl

The origin is moved to the center of the dog model.

Summary of useful numpy-stl tools

  • Install
  •    pip install numpy-stl

  • Import
  •    from stl import mesh

  • Read STL
  •    stl_data = mesh.Mesh.from_file(‘stl_file_name’)

  • Save STL
  •    stl_data.save(‘target_stl_file_name’)

  • Translate STL
  •    stl_data.translate(translate vector :numpy.array)

  • 4×4 Matrix rotation
  •    stl_data.transform(4×4 matrix)

  • Rotation around a vector
  •    stl_data.rotate(axis_data, rotation_angle(radian))

  • Point Cloud from STL
  •    stl_data.points.reshape([-1, 3])

  • Property of STL
  •    volume, center_of_mass, inertial_tensor = stl_data.get_mass_properties()