Overview
A script can bring geometry into MeshInspector, select it, process it and write the result back to disk without the Open and Export dialogs. Two modules share the work:
mrmeshpy(MeshLib) loads, processes and saves meshes;mrviewerpyputs meshes into the scene, selects them and returns the selected ones.
Run the scripts in the Python window (Home › Python). In the examples, replace the paths with files on your computer. On Windows write paths with forward slashes, for example C:/Data/part.stl; on macOS, for example /Users/you/Desktop/part.stl.
Loading Meshes into Memory
loadMesh() reads a mesh file (STL, OBJ, PLY and the other mesh formats MeshInspector opens):
from meshlib import mrmeshpy as mm
mesh = mm.loadMesh("C:/Data/part.stl")
print(mesh)
print("Triangles:", mesh.topology.numValidFaces(), "| Holes:", mesh.topology.findNumHoles())
Example output:
<meshlib.mrmeshpy.Mesh object at 0x1314ea3b0>
Triangles: 1022 | Holes: 2
The mesh is now in memory but not yet in the scene. If the file does not exist, the script stops with RuntimeError: Cannot open file for reading and the path.
Adding a Mesh to the Scene
addMeshToScene() adds a mesh to the scene under the name you give:
from meshlib import mrmeshpy as mm
from meshlib import mrviewerpy as mv
mesh = mm.loadMesh("C:/Data/part.stl")
mv.addMeshToScene(mesh, "Part")
mv.Viewer().preciseFitDataViewport()
addMeshToScene(mesh, "Part")adds a copy of the mesh to the scene; it appears in the scene tree as Part.preciseFitDataViewport()fits the view so that the scene is visible.
The object now looks exactly as if you had opened the file with Open Files. For other kinds of objects there are addPointCloudToScene(), addLinesToScene() and addVoxelsToScene().
Listing Current UI Elements
uiListEntries([]) lists the top of the interface tree. It shows the interface (Ribbon, toolbars, open windows), not the objects of the scene:
from meshlib import mrviewerpy as mv
print([e.name for e in mv.uiListEntries([])])
The output contains QuickAccess, Ribbon, RibbonTabs, Toolbar and the other groups of the interface. How to use them is explained in Navigating MeshInspector’s UI Tree Programmatically.
Selecting Objects in the Scene
Select objects by name, just as if you clicked them in the scene tree:
from meshlib import mrviewerpy as mv
# Select the object named "Part" (all other objects are unselected)
mv.selectByName("Part")
# Check which meshes are selected
selected = mv.getSelectedMeshes()
print(len(selected), "mesh(es) selected")
Example output:
1 mesh(es) selected
selectByName("Part")selects every object with exactly this name and unselects all others.getSelectedMeshes()returns the meshes of the selected objects as a list. These are copies: changing them does not change the scene.
Other selection functions: unselectAll(), selectByType("Meshes") (also "Points" and "Voxels"), getSelectedObjects(), getSelectedPointClouds(), getSelectedPolylines() and getSelectedVoxels().
Changing the Mesh of a Selected Object
Because getSelectedMeshes() returns copies, process the copy and put it back with modifySelectedMesh(). Exactly one object must be selected. This script simplifies the selected mesh with MeshLib and replaces it in the scene:
from meshlib import mrmeshpy as mm
from meshlib import mrviewerpy as mv
mesh = mv.getSelectedMeshes()[0]
settings = mm.DecimateSettings()
settings.maxError = 0.05
mm.decimateMesh(mesh, settings)
mv.modifySelectedMesh(mesh)
print("Triangles now:", mesh.topology.numValidFaces())
maxError is the largest allowed deviation from the original surface, in the units of the model.
Exporting Meshes to Files
saveMesh() writes a mesh to a file. The format is chosen by the extension of the file name:
from meshlib import mrmeshpy as mm
from meshlib import mrviewerpy as mv
# "Part" is in the scene and selected
selected = mv.getSelectedMeshes()
# Save the first selected mesh as an OBJ file
mm.saveMesh(selected[0], "C:/Data/part_out.obj")
print("Export complete.")
mv.getSelectedMeshes()returns the selected meshes in their current state, including the changes made by tools.mm.saveMesh(mesh, path)writes the file; use.stl,.obj,.plyor another mesh extension.
If nothing is selected, the list is empty and selected[0] stops the script with IndexError.
Combining the Steps
This script loads a mesh, adds it to the scene, repairs it with Mesh Healer and saves the result:
import time
from meshlib import mrmeshpy as mm
from meshlib import mrviewerpy as mv
def wait_progress_bar():
mv.Viewer().skipFrames(2)
while any(e.name == "ProgressBar" for e in mv.uiListEntries([])):
time.sleep(0.2)
# Load, add and select the mesh
mesh = mm.loadMesh("C:/Data/part.stl")
mv.addMeshToScene(mesh, "Part")
mv.Viewer().preciseFitDataViewport()
mv.selectByName("Part")
# Open Mesh Healer and repair the checked problem types
mv.uiPressButton(['RibbonTabs', 'Mesh Repair'])
mv.uiPressButton(['Ribbon', 'Mesh Healer'])
wait_progress_bar()
mv.uiPressButton(['Mesh Healer', '##Local Repair']) # the mode with Repair Selected
mv.uiPressButton(['Mesh Healer', 'Repair Selected'])
wait_progress_bar()
# Save the repaired result
repaired = mv.getSelectedMeshes()[0]
mm.saveMesh(repaired, "C:/Data/part_repaired.stl")
print("Holes before:", mesh.topology.findNumHoles(), "after:", repaired.topology.findNumHoles())
Example output for a test mesh with two small holes:
Holes before: 2 after: 0
Repair Selected belongs to the Local Repair mode of Mesh Healer and fixes the problem types whose check boxes are checked; see Controlling Tools and Parameters in MeshInspector for how to set them from a script.
Additional Notes
- Mesh and scene.
loadMesh()only reads the file. To see and edit the mesh, add it withaddMeshToScene(). - Clearing the scene.
clearScene()removes all objects from the scene, which is useful between files in a batch. It does not ask to save changes. - Batch work. Loop over the files of a folder with
os.listdir(); see Advanced Automation with MeshInspector and MeshLib.