fix: media thumbnails, product dimensions, inline 3D viewer, GLB export
Bug A: Media Library thumbnails were gray because <img src> cannot send JWT auth headers. Added useAuthBlob() hook (fetch + createObjectURL) in MediaBrowser.tsx. Also fixed publish_asset Celery task to populate product_id + cad_file_id on MediaAsset for thumbnail fallback resolution. Bug B: Product dimensions now shown in Product Details card with Ruler icon and "from CAD" label when cad_mesh_attributes.dimensions_mm exists. Bug C: Replaced 128×128 CAD thumbnail with InlineCadViewer component. Queries gltf_geometry MediaAssets, fetches GLB via auth fetch → blob URL → Three.js Canvas with OrbitControls. Falls back to thumbnail + "Load 3D Model" button. Polling when GLB generation is in progress. Bug D: trimesh was in [cad] optional extra but Dockerfile only installed [dev]. Changed to pip install -e ".[dev,cad]" — trimesh now available in backend container, GLB + Colors export works. Also added bbox extraction (STL-first numpy parsing) in render_step_thumbnail and admin "Re-extract CAD Metadata" bulk endpoint. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -293,8 +293,33 @@ def extract_mesh_edge_data(step_path: str) -> dict:
|
||||
except Exception:
|
||||
continue
|
||||
|
||||
# Bounding box extraction (OCC Bnd_Box)
|
||||
from OCC.Core.Bnd import Bnd_Box
|
||||
from OCC.Core.BRepBndLib import brepbndlib
|
||||
try:
|
||||
bbox = Bnd_Box()
|
||||
brepbndlib.Add(shape, bbox)
|
||||
xmin, ymin, zmin, xmax, ymax, zmax = bbox.Get()
|
||||
dimensions_mm = {
|
||||
"x": round(xmax - xmin, 2),
|
||||
"y": round(ymax - ymin, 2),
|
||||
"z": round(zmax - zmin, 2),
|
||||
}
|
||||
bbox_center_mm = {
|
||||
"x": round((xmin + xmax) / 2, 2),
|
||||
"y": round((ymin + ymax) / 2, 2),
|
||||
"z": round((zmin + zmax) / 2, 2),
|
||||
}
|
||||
except Exception:
|
||||
dimensions_mm = None
|
||||
bbox_center_mm = None
|
||||
|
||||
if not dihedral_angles:
|
||||
return {}
|
||||
result: dict = {}
|
||||
if dimensions_mm:
|
||||
result["dimensions_mm"] = dimensions_mm
|
||||
result["bbox_center_mm"] = bbox_center_mm
|
||||
return result
|
||||
|
||||
import statistics
|
||||
median_angle = statistics.median(dihedral_angles)
|
||||
@@ -307,11 +332,15 @@ def extract_mesh_edge_data(step_path: str) -> dict:
|
||||
else:
|
||||
suggested = 30.0
|
||||
|
||||
return {
|
||||
result = {
|
||||
"suggested_smooth_angle": round(suggested, 1),
|
||||
"has_mechanical_edges": max_angle > 45,
|
||||
"sharp_edge_midpoints": sharp_midpoints[:500],
|
||||
}
|
||||
if dimensions_mm:
|
||||
result["dimensions_mm"] = dimensions_mm
|
||||
result["bbox_center_mm"] = bbox_center_mm
|
||||
return result
|
||||
except ImportError:
|
||||
# OCC not available (e.g. in backend container)
|
||||
return {}
|
||||
|
||||
Reference in New Issue
Block a user