rushabhcodes/desk-fidget-counter

A desk knob assembly combining a circuit board with PETG-printed mechanical parts and vendor CAD-modeled hardware.

Version
5.6.1
License
MIT
Stars
0

mechanical/step-mesh.py

#!/usr/bin/env python3
# SPDX-License-Identifier: MIT
# Tessellate unchanged STEP geometry at 0.03mm deflection; OCP 8.0.1.
import sys,json
import numpy as np,trimesh
from OCP.STEPControl import STEPControl_Reader
from OCP.BRepBndLib import BRepBndLib
from OCP.Bnd import Bnd_Box
from OCP.TopExp import TopExp_Explorer
from OCP.TopAbs import TopAbs_FACE,TopAbs_REVERSED
from OCP.TopoDS import TopoDS
from OCP.TopLoc import TopLoc_Location
from OCP.BRep import BRep_Tool
from OCP.BRepMesh import BRepMesh_IncrementalMesh
r=STEPControl_Reader();r.ReadFile(sys.argv[1]);r.TransferRoots();s=r.OneShape()
BRepMesh_IncrementalMesh(s,.03,False,.15,True)
e=TopExp_Explorer(s,TopAbs_FACE);vs=[];fs=[];groups=[];fi=0
while e.More():
 face=TopoDS.Face(e.Current());loc=TopLoc_Location();tri=BRep_Tool.Triangulation_s(face,loc)
 if tri:
  start=len(vs);matrix=loc.Transformation()
  for i in range(1,tri.NbNodes()+1):
   p=tri.Node(i).Transformed(matrix);vs.append([p.X(),p.Y(),p.Z()])
  for i in range(1,tri.NbTriangles()+1):
   a,b,c=tri.Triangle(i).Get()
   if face.Orientation()==TopAbs_REVERSED:b,c=c,b
   fs.append([start+a-1,start+b-1,start+c-1]);groups.append(fi)
 fi+=1;e.Next()
if '--preserve-seams' in sys.argv[3:]:
 # Coincident but topologically distinct edges in the valid STEP must stay
 # distinct. Manifold pairs the original open half-edges without moving any
 # tessellation vertex; ordinary coordinate welding loses that information.
 import manifold3d as manifold
 raw=manifold.Mesh64(np.ascontiguousarray(vs,dtype=np.float64),np.ascontiguousarray(fs,dtype=np.uint64))
 raw.merge();solid=manifold.Manifold(raw);assert str(solid.status()).endswith('NoError')
 raw=solid.to_mesh64();m=trimesh.Trimesh(np.asarray(raw.vert_properties)[:,:3],np.asarray(raw.tri_verts),process=False)
else:m=trimesh.Trimesh(vs,fs,process=True)
m.export(sys.argv[2]);np.savez(sys.argv[2]+'.faces.npz',vertices=np.array(vs),faces=np.array(fs),groups=np.array(groups))
print(json.dumps({'bounds_mm':m.bounds.tolist(),'faces':len(m.faces),'volume':m.volume,'watertight':m.is_watertight,'components':len(m.split())}))