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.
- Install
- Import
- Read STL
- Save STL
- Translate STL
- 4×4 Matrix rotation
- Rotation around a vector
- Point Cloud from STL
- Property of STL
pip install numpy-stl
from stl import mesh
stl_data = mesh.Mesh.from_file(‘stl_file_name’)
stl_data.save(‘target_stl_file_name’)
stl_data.translate(translate vector :numpy.array)
stl_data.transform(4×4 matrix)
stl_data.rotate(axis_data, rotation_angle(radian))
stl_data.points.reshape([-1, 3])
volume, center_of_mass, inertial_tensor = stl_data.get_mass_properties()