ace-mini-1 / scripts /prepare_prediction_step.py
ConnorKapoor's picture
Deploy isolated Ace-Mini research preview
b1b1e02 verified
Raw History Blame Contribute Delete
2.48 kB
"""Prepare an uploaded single-solid STEP for the casting prediction sandbox."""
import sys,json,time
from pathlib import Path
import numpy as np
import inspect_step_parts as geo
from OCC.Core.BRepCheck import BRepCheck_Analyzer
from OCC.Core.BRepClass3d import BRepClass3d_SolidClassifier
from OCC.Core.TopAbs import TopAbs_IN
from OCC.Core.gp import gp_Pnt
from OCC.Core.ShapeFix import ShapeFix_Shape
from OCC.Core.BRepGProp import brepgprop
from OCC.Core.GProp import GProp_GProps
folder=Path(sys.argv[1]); shape=geo.read(folder/'input.step')
def volume(s):
p=GProp_GProps();brepgprop.VolumeProperties(s,p);return p.Mass()
original=volume(shape);repaired=False
if not BRepCheck_Analyzer(shape).IsValid():
fix=ShapeFix_Shape(shape);fix.Perform();shape=fix.Shape();repaired=True
if not BRepCheck_Analyzer(shape).IsValid():raise ValueError('STEP solid is invalid after repair. Please heal it in CAD.')
ss=geo.solids(shape)
if len(ss)!=1:raise ValueError(f'This pilot supports one closed solid; file contains {len(ss)} solids.')
if original<=0 or abs(volume(shape)-original)/original>.001:raise ValueError('Invalid volume or repair changed volume by more than 0.1%.')
mesh,_=geo.mesh_shape(shape,.2);v=np.asarray(mesh.vertices);f=np.asarray(mesh.faces)
if len(f)>150000:raise ValueError('Tessellation exceeds pilot limit of 150,000 triangles.')
lo=v.min(0);hi=v.max(0);rng=np.random.default_rng(1742026);classifier=BRepClass3d_SolidClassifier(ss[0]);points=[];start=time.monotonic()
for batch in range(150):
for p in rng.uniform(lo,hi,(2048,3)):
classifier.Perform(gp_Pnt(*p),1e-7)
if classifier.State()==TopAbs_IN:points.append(p)
if len(points)==2048:break
if len(points)==2048:break
if time.monotonic()-start>100:break
if len(points)<2048:raise ValueError('Part is too thin or sparse for this pilot sampler; could not obtain 2,048 interior points.')
n=np.cross(v[f[:,1]]-v[f[:,0]],v[f[:,2]]-v[f[:,0]]);areas=np.linalg.norm(n,axis=1);n/=np.maximum(areas[:,None],1e-12);cent=v[f].mean(1)
ix=rng.choice(len(f),1024,p=areas/areas.sum(),replace=True)
np.savez_compressed(folder/'geometry.npz',vertices=v,triangles=f,centers=cent,normals=n,areas=areas,points=np.array(points),surface=cent[ix],encoder_normals=n[ix])
(folder/'geometry.json').write_text(json.dumps({'dimensions_mm':(hi-lo).tolist(),'volume_mm3':volume(shape),'repair_applied':repaired,'repair_relative_volume_change':abs(volume(shape)-original)/original,'units':'mm (STEP reader conversion)','solid_count':1}))