File: mkStlInertial.py

package info (click to toggle)
yade 2026.1.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 34,448 kB
  • sloc: cpp: 97,645; python: 52,173; sh: 677; makefile: 162
file content (39 lines) | stat: -rw-r--r-- 2,431 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
def mkStlInertial(stlFileName, verbose=False):
	'''Maps a stl mesh into one of its inertial frame. The new .stl will be saved, appending '_madeI.stl' to *stlFileName*. Requires stl Python module, see https://pypi.org/project/numpy-stl/.
    :stlFileName: path to the .stl to consider, wo the .stl extension (string)
    :verbose: boolean to control informative message outputs about the function process
    '''
	import numpy, time
	try:
		import stl  # = https://pypi.org/project/numpy-stl/. Alternate choice https://python-stl.readthedocs.io/en/latest/ is no longer maintained on https://github.com/apparentlymart/python-stl
	except ModuleNotFoundError:  # using except just for a print, not really avoiding the error
		print('****Python module stl is required, see the doc****')
		import stl  # we still repeat the same command for the error to appear to the user
	t1 = time.time()
	stlMesh = stl.mesh.Mesh.from_file(stlFileName + '.stl')
	t2 = time.time()
	if verbose:
		print('\nReading given file in', t2 - t1, 'seconds')
	volume, cog, inertia = stlMesh.get_mass_properties()  # cog being a numpy array
	t1 = time.time()
	if verbose:
		print('Computing mass properties in ~', t1 - t2, 'seconds')
		print('Initially, stl is centered at', cog, 'with inertia\n', inertia)

	# Getting eigenbasis information:
	[val, vect] = numpy.linalg.eig(inertia)  # vect is the eigenvectors basis in current basis
	if numpy.linalg.det(vect) < 0:  # eg (x,z,y)
		if verbose:
			print('Non right-handed basis, modifying vect, which is for now\n', vect)
		vect[:, 2] = -vect[:, 2]  # making it (x,z,-y) which is a more suitable basis
		if verbose:
			print('And now\n', vect, '\nwith determinant', numpy.linalg.det(vect))
	rot = vect.T  # taking the transpose that will be useful for changing basis
	# Applying the transformation, avoiding to use eg stlMesh.transform or stlMesh.rotate on purpose (with source code at https://github.com/WoLpH/numpy-stl/tree/develop/stl/base.py) because of https://github.com/WoLpH/numpy-stl/issues/166:
	for fIdx in range(len(stlMesh.vectors)):  # loop over facets
		for vIdx in range(3):  # loop over 3 vertices in each facet
			stlMesh.vectors[fIdx][vIdx] = rot @ (stlMesh.vectors[fIdx][vIdx] - cog)
	if verbose:
		volume, cog, inertia = stlMesh.get_mass_properties()
		print('\nAfter transformation, stl is centered at', cog, 'and has following inertia\n', inertia)
	stlMesh.save(stlFileName + '_madeI.stl')