安装依赖
numpy
matplotlib
numpy-stl
运行脚本
import sys
import os
import numpy as np
# 强制使用 TkAgg 后端,弹出独立窗口,支持鼠标交互
import matplotlib
matplotlib.use("TkAgg")
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection
from stl import mesh
# 文件选择对话框(Windows)
try:
import tkinter as tk
from tkinter import filedialog
except ImportError:
tk = None
def open_file_dialog() -> str:
"""打开文件资源管理器并选择一个 STL 文件"""
if tk is None:
return None
root = tk.Tk()
root.withdraw()
filepath = filedialog.askopenfilename(
title="选择一个 STL 文件",
filetypes=[("STL files", "*.stl")]
)
root.destroy()
return filepath
def load_stl(filepath: str) -> mesh.Mesh:
"""加载 STL 文件并返回 mesh 对象"""
if not os.path.isfile(filepath):
raise FileNotFoundError(f"文件不存在: {filepath}")
return mesh.Mesh.from_file(filepath)
def plot_stl(stl_mesh: mesh.Mesh, title: str = "STL Viewer"):
"""使用 matplotlib 3D 显示 STL 模型(支持鼠标拖拽旋转)"""
vectors = stl_mesh.vectors # (n_faces, 3, 3)
fig = plt.figure()
ax = fig.add_subplot(111, projection="3d")
ax.set_title(title)
poly3d = Poly3DCollection(vectors, linewidths=0.2, alpha=0.8)
poly3d.set_edgecolor("k")
ax.add_collection3d(poly3d)
# 自动缩放
x = vectors[:, :, 0].flatten()
y = vectors[:, :, 1].flatten()
z = vectors[:, :, 2].flatten()
max_range = np.array([
x.max() - x.min(),
y.max() - y.min(),
z.max() - z.min()
]).max() / 2.0
mid_x = (x.max() + x.min()) / 2.0
mid_y = (y.max() + y.min()) / 2.0
mid_z = (z.max() + z.min()) / 2.0
ax.set_xlim(mid_x - max_range, mid_x + max_range)
ax.set_ylim(mid_y - max_range, mid_y + max_range)
ax.set_zlim(mid_z - max_range, mid_z + max_range)
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")
# 这一行会弹出交互式窗口:
# 左键拖拽旋转,滚轮缩放,中键平移(具体看系统)
plt.tight_layout()
plt.show()
def main():
# 无参数 → 弹出文件选择框
if len(sys.argv) < 2:
print("未传入 STL 文件,正在打开文件选择对话框...")
filepath = open_file_dialog()
if not filepath:
print("未选择文件,退出。")
return
else:
filepath = sys.argv[1]
try:
stl_mesh = load_stl(filepath)
except Exception as e:
print(f"加载 STL 失败: {e}")
return
filename = os.path.basename(filepath)
plot_stl(stl_mesh, title=f"STL Viewer - {filename}")
if __name__ == "__main__":
main()
