Python预览3D打印格式STL的脚本

安装依赖

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()

Snipaste_2025-11-24_10-24-33

posted @ 2025-11-21 18:39  _迷途  阅读(28)  评论(0)    收藏  举报