from pathlib import Path import FreeCAD as A, Part, json, os, traceback V=A.Vector out=Path(r'C:\projects\wheel\models\symmetric_corner_18_concept') try: d=A.newDocument('SymmetricCorner');s=d.addObject('Spreadsheet::Sheet','Parameters');s.set('A1','Name');s.set('B1','Value') for n,(name,val) in enumerate([('Leg','20 mm'),('Width','16 mm'),('Thick','1.8 mm'),('Hole','5 mm'),('EndDistance','8 mm')],2): s.set('A%d'%n,name);s.set('B%d'%n,val);s.setAlias('B%d'%n,name) def expr(o,k,v):o.setExpression(k,v) def box(n,L,W,H,x,y,z): o=d.addObject('Part::Box',n) for k,v in [('Length',L),('Width',W),('Height',H),('Placement.Base.x',x),('Placement.Base.y',y),('Placement.Base.z',z)]:expr(o,k,v) return o def cyl(n,r,h,x,y,z,ax=False): o=d.addObject('Part::Cylinder',n) for k,v in [('Radius',r),('Height',h),('Placement.Base.x',x),('Placement.Base.y',y),('Placement.Base.z',z)]:expr(o,k,v) if ax:o.Placement.Rotation=A.Rotation(V(0,0,1),V(1,0,0)) return o r='Parameters.Width/2';v='Parameters.Leg-Parameters.Width/2';xx='-(Parameters.Leg-Parameters.Thick-Parameters.Width/2)';end='-(Parameters.Leg-Parameters.Thick)' a=box('FlatA',v,'Parameters.Width','Parameters.Thick',xx,'-Parameters.Width/2','0 mm') ca=cyl('RoundA',r,'Parameters.Thick',xx,'0 mm','0 mm') limA=box('LimitA',r,'Parameters.Width','Parameters.Thick',end,'-Parameters.Width/2','0 mm') capA=d.addObject('Part::Common','EndA');capA.Base=ca;capA.Tool=limA b=box('FlatB','Parameters.Thick','Parameters.Width',v,'0 mm','-Parameters.Width/2','0 mm') cb=cyl('RoundB',r,'Parameters.Thick','0 mm','0 mm',v,True) limB=box('LimitB','Parameters.Thick','Parameters.Width',r,'0 mm','-Parameters.Width/2',v) capB=d.addObject('Part::Common','EndB');capB.Base=cb;capB.Tool=limB body=d.addObject('Part::MultiFuse','Blank');body.Shapes=[a,capA,b,capB] h1=cyl('HoleA','Parameters.Hole/2','Parameters.Thick+0.2 mm','-(Parameters.Leg-Parameters.Thick-Parameters.EndDistance)','0 mm','-0.1 mm') h2=cyl('HoleB','Parameters.Hole/2','Parameters.Thick+0.2 mm','-0.1 mm','0 mm','Parameters.Leg-Parameters.EndDistance',True) hh=d.addObject('Part::MultiFuse','Holes');hh.Shapes=[h1,h2] result=d.addObject('Part::Cut','SymmetricCorner');result.Base=body;result.Tool=hh;result.Label='20×20×16 symmetrical angle — approximate bend' d.recompute();sh=result.Shape;assert sh.isValid() and len(sh.Solids)==1 for o in d.Objects: if hasattr(o,'ViewObject') and o.ViewObject:o.ViewObject.Visibility=False result.ViewObject.Visibility=True d.saveAs(str(out/'新角码_对称参数模型.FCStd'));Part.export([result],str(out/'新角码_对称参数模型.step')) original=A.openDocument(str(out/'Assembly_对称角码装配_概念.FCStd')); original.recompute();shape=original.getObject('NewMotorCorner10').Shape.copy() p=38/(2**.5);shape.translate(V(-(p+10.2),-(10-p),0)) diff1=shape.cut(sh).Volume;diff2=sh.cut(shape).Volume;assert diff1<1e-4 and diff2<1e-4,(diff1,diff2) checks={'valid':True,'solids':len(sh.Solids),'model_to_assembly_mm3':diff1,'assembly_to_model_mm3':diff2,'reference':'20 external, 8 from free ends, 1.8 thick, 10.2 to sharp-corner inner surface; bend radius and countersink omitted'} (out/'角码参数模型校验.json').write_text(json.dumps(checks,ensure_ascii=False,indent=2),encoding='utf8') A.closeDocument(original.Name);A.closeDocument(d.Name);os._exit(0) except Exception: (out/'角码参数模型_错误.txt').write_text(traceback.format_exc(),encoding='utf8');os._exit(1)