Add workflow to convert PLY files to STL

This workflow automates the conversion of PLY files to STL format, optimizing the output size while maintaining quality. It includes steps for checking out the repository, setting up Python, installing dependencies, and committing the generated STL files.
This commit is contained in:
Alex38Lyon
2026-08-28 09:55:01 +02:00
committed by GitHub
parent 4b24224e5c
commit fe21631616
+248
View File
@@ -0,0 +1,248 @@
```yaml
name: Convert PLY to STL
on:
push:
paths:
- '**/*.ply'
workflow_dispatch:
permissions:
contents: write
jobs:
convert:
runs-on: ubuntu-latest
steps:
# ------------------------------------------------------------
# Récupération du dépôt
# ------------------------------------------------------------
- name: Checkout repository
uses: actions/checkout@v6
# ------------------------------------------------------------
# Installation de Python
# ------------------------------------------------------------
- name: Setup Python
uses: actions/setup-python@v7
with:
python-version: '3.13'
# ------------------------------------------------------------
# Installation des bibliothèques
# ------------------------------------------------------------
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install trimesh numpy fast-simplification
# ------------------------------------------------------------
# Conversion PLY -> STL
# Recherche automatique du meilleur compromis qualité/taille
# ------------------------------------------------------------
- name: Convert PLY files to STL
run: |
python <<'PY'
import trimesh
import glob
import os
import tempfile
# Taille maximale autorisée.
# 50 MiB = 50 * 1024 * 1024 octets
MAX_SIZE = 50 * 1024 * 1024
# Marge de sécurité :
# on vise légèrement sous 50 MiB afin d'éviter
# tout dépassement lié aux métadonnées ou différences
# de calcul.
TARGET_SIZE = 49 * 1024 * 1024
# Ratios testés, du meilleur au moins bon.
# Le script s'arrête dès qu'il trouve un fichier
# suffisamment petit.
RATIOS = [
1.00,
0.90,
0.80,
0.70,
0.60,
0.50,
0.40,
0.30,
0.20,
0.10
]
ply_files = glob.glob('**/*.ply', recursive=True)
if not ply_files:
print("Aucun fichier PLY trouvé.")
exit(0)
for ply in ply_files:
print()
print("=" * 70)
print(f"Fichier : {ply}")
print("=" * 70)
# ----------------------------------------------------
# Chargement du maillage
# ----------------------------------------------------
mesh = trimesh.load(ply, force='mesh')
if mesh.is_empty:
print("ERREUR : maillage vide")
continue
if not isinstance(mesh, trimesh.Trimesh):
print("ERREUR : le fichier ne contient pas un maillage triangulaire.")
continue
original_faces = len(mesh.faces)
print(f"Triangles initiaux : {original_faces:,}")
# ----------------------------------------------------
# Fichier STL temporaire
# ----------------------------------------------------
base = os.path.splitext(ply)[0]
stl = base + '.stl'
best_mesh = None
best_size = None
best_ratio = None
# ----------------------------------------------------
# Essai des différents niveaux de simplification
# ----------------------------------------------------
for ratio in RATIOS:
target_faces = max(
1000,
int(original_faces * ratio)
)
print()
print(
f"Test : {ratio * 100:.0f}% "
f"({target_faces:,} triangles)"
)
# ------------------------------------------------
# Pas de simplification pour 100 %
# ------------------------------------------------
if ratio >= 1.0:
test_mesh = mesh.copy()
else:
try:
test_mesh = mesh.simplify_quadric_decimation(
face_count=target_faces
)
except Exception as e:
print(
"Erreur lors de la simplification : "
f"{e}"
)
continue
# ------------------------------------------------
# Export STL temporaire
# ------------------------------------------------
with tempfile.NamedTemporaryFile(
suffix='.stl',
delete=False
) as tmp:
temp_stl = tmp.name
try:
test_mesh.export(temp_stl)
size = os.path.getsize(temp_stl)
finally:
if os.path.exists(temp_stl):
os.remove(temp_stl)
size_mb = size / (1024 * 1024)
print(
f" -> {len(test_mesh.faces):,} triangles"
)
print(
f" -> {size_mb:.2f} MiB"
)
# ------------------------------------------------
# On conserve le premier résultat sous 49 MiB.
#
# Comme les ratios sont testés du plus grand
# au plus petit, c'est le meilleur résultat
# possible parmi les valeurs testées.
# ------------------------------------------------
if size < TARGET_SIZE:
best_mesh = test_mesh
best_size = size
best_ratio = ratio
print(" -> Taille acceptable")
break
# ----------------------------------------------------
# Aucun résultat suffisamment petit
# ----------------------------------------------------
if best_mesh is None:
print()
print(
"ERREUR : impossible d'obtenir un STL "
f"inférieur à {TARGET_SIZE / (1024 * 1024):.0f} MiB."
)
continue
# ----------------------------------------------------
# Export définitif
# ----------------------------------------------------
best_mesh.export(stl)
final_size = os.path.getsize(stl)
final_size_mb = final_size / (1024 * 1024)
print()
print("-" * 70)
print("RESULTAT")
print("-" * 70)
print(f"Fichier STL : {stl}")
print(f"Triangles : {len(best_mesh.faces):,}")
print(f"Ratio : {best_ratio * 100:.0f}%")
print(f"Taille : {final_size_mb:.2f} MiB")
print(f"Taille limite : 50.00 MiB")
if final_size >= MAX_SIZE:
print("ATTENTION : fichier supérieur à 50 MiB !")
else:
print("OK : fichier inférieur à 50 MiB.")
print("-" * 70)
PY
# ------------------------------------------------------------
# Commit des STL générés
# ------------------------------------------------------------
- name: Commit converted STL files
uses: stefanzweifel/git-auto-commit-action@v7
with:
commit_message: "Auto-convert PLY to reduced STL"
```