from pathlib import Path import json import FreeCAD as A, Part, Mesh, MeshPart root=Path(r'C:\projects\wheel') out=root/'models'/'washer_two_panels' out.mkdir(parents=True,exist_ok=True) V=A.Vector reference=Part.read(str(root/'models'/'washer_panel_4x4'/'一体式4x4双厚垫片.step')) results={} for tag,thickness,orig_y in [('0.5mm',0.5,0),('1mm',1.0,24)]: d=A.newDocument('Panel'+tag.replace('.','')) params=d.addObject('Spreadsheet::Sheet','Parameters') params.set('A1','Thickness'); params.set('B1',str(thickness)+' mm'); params.setAlias('B1','Thickness') blank=d.addObject('Part::Box','Blank'); blank.Length=48; blank.Width=24; blank.setExpression('Height','Parameters.Thickness') tools=[] for row in range(2): for col in range(4): x,y=12*col+6,12*row+6 c=d.addObject('Part::Cylinder','Hole%d%d'%(row,col)); c.Radius=2.2; c.Height=3; c.Placement.Base=V(x,y,-1);tools.append(c) p=d.addObject('Part::Box','Opening%d%d'%(row,col));p.Length=6;p.Width=6;p.Height=3;p.Placement.Base=V(x,y,-1);tools.append(p) union=d.addObject('Part::MultiFuse','Cutters');union.Shapes=tools panel=d.addObject('Part::Cut','Panel');panel.Base=blank;panel.Tool=union panel.Label='4x2 continuous washer panel '+tag d.recompute();s=panel.Shape assert s.isValid() and len(s.Solids)==1 cells=[] for row in range(2): for col in range(4): cell=s.common(Part.makeBox(12,12,2,V(12*col,12*row,0))) old=reference.common(Part.makeBox(12,12,2,V(12*col,orig_y+12*row,0))) old.translate(V(0,-orig_y,0)) diff=(cell.cut(old).Volume,old.cut(cell).Volume) assert cell.isValid() and len(cell.Solids)==1 and max(diff)<1e-6 and abs(cell.BoundBox.ZLength-thickness)<1e-7 cells.append(diff) filename='一体垫片板_'+tag fc=out/(filename+'.FCStd'); step=out/(filename+'.step');stl=out/(filename+'.stl') d.saveAs(str(fc));Part.export([panel],str(step));MeshPart.meshFromShape(Shape=s,LinearDeflection=.025,AngularDeflection=.15,Relative=False).write(str(stl)) A.closeDocument(d.Name) reopened=A.openDocument(str(fc)); reopened.recompute();f=reopened.getObject('Panel').Shape ss=Part.read(str(step));m=Mesh.Mesh(str(stl));components=m.getSeparateComponents() diff=(f.cut(ss).Volume,ss.cut(f).Volume) assert max(diff)<1e-6 and len(ss.Solids)==1 and ss.isValid() and len(components)==1 and components[0].isSolid() bb=ss.BoundBox assert abs(bb.XLength-48)<1e-6 and abs(bb.YLength-24)<1e-6 and abs(bb.ZLength-thickness)<1e-6 results[tag]={'size_mm':[48,24,thickness],'quantity':8,'cells_diff_mm3':cells,'stl_components':len(components),'stl_closed':components[0].isSolid(),'step_fcstd_diff_mm3':diff,'step_valid':ss.isValid()} A.closeDocument(reopened.Name) (out/'几何验证.json').write_text(json.dumps(results,ensure_ascii=False,indent=2),encoding='utf8') print(json.dumps(results,ensure_ascii=False,indent=2))