Vista 3D del modello in una pagina HTML autonoma

Aggiunge --3d: genera un file HTML che si apre con un doppio clic e
permette di ruotare il pezzo col mouse, ingrandire con la rotella e
spostare col tasto destro. Mesh, stile e codice sono dentro la pagina:
nessuna libreria esterna e nessuna connessione, cosi' funziona anche da
una cartella di rete. Il disegno usa una canvas 2D con ordinamento per
profondita' invece di WebGL, che su alcune postazioni e' disattivato.

La forma non viene dal .prt ma da una mesh STL esportata da Creo, cercata
accanto al modello per nome (9258400207.prt.11 -> 9258400207.stl). Se
manca, il comando lo dice invece di fallire.

Perche' serve la mesh: la geometria nel .prt e' scritta nel formato del
kernel Granite di PTC ed e' compressa. Verificato con un attacco a testo
noto, presi da un export STEP i 22 valori esatti del modello (raggi 1,6 /
2,1 / 2,5 / 2,75 / 5,25 e coordinate fino a 75,0) e cercati nel file in
cinque codifiche su tutti i blocchi: nessun riscontro. La via ufficiale
per leggere i .prt nativi senza Creo e' il Granite Interoperability
Kernel di PTC, che si innesterebbe al posto di mesh.py senza toccare il
resto.

Quando la mesh c'e', il record guadagna un blocco "geometry" con
ingombro, volume e area. Il peso NON viene calcolato: servirebbe la
densita', che dipende dal materiale, e il materiale e' testo libero.
Sul 9258400207 il parametro dice "Anticordal 100", che e' alluminio:
applicare la densita' dell'acciaio darebbe 0,686 kg invece di 0,237.

Gli export (stl, dxf, dwg, iges, pdf) sono esclusi dal repository come i
modelli: sono geometria e tavole complete dei pezzi.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-08-06 16:04:46 +02:00
co-authored by Claude Opus 5
parent b59380fcab
commit 0410266334
7 changed files with 493 additions and 2 deletions
+36 -1
View File
@@ -10,7 +10,8 @@ import sys
from . import ugc
from .extract import extract as extract_file
from .extract import latest_versions, read_preview, split_filename
from .extract import (find_mesh, latest_versions, read_mesh,
read_preview, split_filename)
CREO_EXTENSIONS = (".prt", ".asm", ".drw", ".frm", ".lay")
@@ -140,6 +141,32 @@ def _save_previews(paths: "list[str]", dest: str, stream) -> None:
file=stream)
def _save_viewers(paths: "list[str]", dest: str, stream) -> None:
from . import viewer
single = len(paths) == 1
for source in paths:
name = os.path.basename(source)
try:
mesh = read_mesh(source)
except (OSError, ValueError) as error:
print(f"{name}: mesh illeggibile ({error})", file=stream)
continue
if mesh is None:
print(f"{name}: nessuna mesh accanto al file. Esportare il "
f"modello in STL da Creo per vederlo in 3D.", file=stream)
continue
stem = split_filename(name)[0]
page = viewer.build(mesh, stem, viewer.describe(mesh))
target = _preview_path(source, dest, single)
target = target[:-4] + ".html" if target.endswith(".jpg") else target
with open(target, "w", encoding="utf-8") as handle:
handle.write(page)
print("Vista 3D di %s (%d triangoli) salvata in %s"
% (stem, len(mesh), target), file=stream)
def _write_csv(records: "list[dict]", path: str, include_system: bool = False,
include_features: bool = False) -> None:
names = sorted({n for r in records for n in _visible(r, include_system, include_features)})
@@ -182,6 +209,11 @@ def build_parser() -> argparse.ArgumentParser:
parser.add_argument("--preview", nargs="?", const="", metavar="FILE|CARTELLA",
help="salva l'anteprima incorporata come JPEG. Senza "
"argomento la scrive accanto al file di origine")
parser.add_argument("--3d", dest="three_d", nargs="?", const="",
metavar="FILE|CARTELLA",
help="genera una pagina HTML per ruotare il modello "
"nel browser, leggendo la mesh (.stl) esportata "
"accanto al file")
parser.add_argument("-r", "--recursive", action="store_true",
help="esplora le sottocartelle")
parser.add_argument("--all-versions", action="store_true",
@@ -240,6 +272,9 @@ def main(argv: "list[str] | None" = None) -> int:
_write_csv(records, args.csv, args.system, args.features)
print(f"CSV scritto in {args.csv}", file=sys.stderr)
if args.three_d is not None:
_save_viewers([r["source_file"] for r in records], args.three_d, sys.stderr)
if args.preview is not None:
_save_previews(
[r["source_file"] for r in records], args.preview, sys.stderr