建立方向盘项目初始版本
This commit is contained in:
75
scripts/build_fan_direct_motor_side_130.FCMacro
Normal file
75
scripts/build_fan_direct_motor_side_130.FCMacro
Normal file
@@ -0,0 +1,75 @@
|
||||
from pathlib import Path
|
||||
import os, math, json, time, traceback
|
||||
import FreeCAD as A, FreeCADGui as G, Part, Import
|
||||
V=A.Vector
|
||||
root=Path(r'C:\projects\wheel');out=root/'models'/'fan_direct_motor_side_130';out.mkdir(parents=True,exist_ok=True)
|
||||
try:
|
||||
d=A.openDocument(str(root/'models'/'integer_profiles'/'Assembly.FCStd'));d.recompute()
|
||||
rails=[d.getObject('Rail0'),d.getObject('Rail1')]; corners=[d.getObject('MotorBaseCorner0'),d.getObject('MotorBaseCorner1')]
|
||||
xs=[(o.Shape.BoundBox.XMin+o.Shape.BoundBox.XMax)/2 for o in rails];spacing=xs[1]-xs[0]
|
||||
theta=math.degrees(math.acos(spacing/(105*math.sqrt(2))))-45
|
||||
oldrails=[o.Shape.copy() for o in rails]
|
||||
for i,rail in enumerate(rails):
|
||||
rail.Placement=A.Placement();rail.Shape=Part.makeBox(20,130,20,V(xs[i]-10,-55,0));rail.Label='2020 motor support 130mm'
|
||||
for i,obj in enumerate(corners):
|
||||
orig=obj.Shape.copy();orig.rotate(V(xs[i],0,10),V(0,1,0),180);obj.Placement=A.Placement();obj.Shape=orig;obj.Label='Motor side 2020-3030 connecting corner'
|
||||
d.recompute()
|
||||
visible=[o for o in d.Objects if hasattr(o,'Shape') and not o.Shape.isNull() and o.ViewObject.Visibility]
|
||||
pairs=[];hits=[];skip={'Rail0','Rail1','MotorBaseCorner0','MotorBaseCorner1'}
|
||||
for i,c in enumerate(corners):
|
||||
for o in visible:
|
||||
if o==c:continue
|
||||
if c.Shape.BoundBox.intersect(o.Shape.BoundBox):
|
||||
vol=c.Shape.common(o.Shape).Volume
|
||||
if vol>1e-4:hits.append([c.Name,o.Name,vol])
|
||||
if o.Name in ('Motor','Rail%d'%i,'NewRail%d'%i,'Corner%d'%(i*2),'Corner%d'%(i*2+1)):
|
||||
pairs.append([c.Name,o.Name,c.Shape.distToShape(o.Shape)[0]])
|
||||
assert c.Shape.distToShape(rails[i].Shape)[0]<1e-5
|
||||
assert c.Shape.distToShape(d.getObject('NewRail%d'%i).Shape)[0]<1e-5
|
||||
for i,rail in enumerate(rails):
|
||||
extra=rail.Shape.cut(oldrails[i])
|
||||
for o in visible:
|
||||
if o in rails or o in corners:continue
|
||||
if extra.BoundBox.intersect(o.Shape.BoundBox):
|
||||
vol=extra.common(o.Shape).Volume
|
||||
if vol>1e-4:hits.append(['extra_'+rail.Name,o.Name,vol])
|
||||
fan=Part.makeBox(120,120,25,V(-60,-60,20)).cut(Part.makeCylinder(56,25.04,V(0,0,19.98)))
|
||||
for x in (-52.5,52.5):
|
||||
for y in (-52.5,52.5):fan=fan.cut(Part.makeCylinder(2.2,25.04,V(x,y,19.98)))
|
||||
fan=fan.removeSplitter();fan.rotate(V(0,0,0),V(0,0,1),theta);fan.translate(V(0,10,0))
|
||||
for o in visible:
|
||||
if fan.BoundBox.intersect(o.Shape.BoundBox):
|
||||
vol=fan.common(o.Shape).Volume
|
||||
if vol>1e-4:hits.append(['DirectFan',o.Name,vol])
|
||||
if hits: raise Exception('COLLISION '+str(hits))
|
||||
ff=d.addObject('PartDesign::Feature','DirectFan');ff.Shape=fan;ff.Label='120mm fan assumed geometry, rotated';ff.ViewObject.ShapeColor=(.22,.24,.27);ff.ViewObject.Transparency=18
|
||||
holes=[];alpha=math.radians(theta);bolts=[]
|
||||
for sign in (-1,1):
|
||||
px=sign*52.5*(math.cos(alpha)-math.sin(alpha));py=10+sign*52.5*(math.cos(alpha)+math.sin(alpha));idx=0 if sign<0 else 1
|
||||
assert abs(px-xs[idx])<1e-6 and -55<py<75
|
||||
screw=Part.makeCylinder(2,25,V(px,py,20)).fuse(Part.makeCylinder(3.5,3,V(px,py,45))).removeSplitter()
|
||||
assert screw.common(fan).Volume<1e-5
|
||||
for o in visible:
|
||||
if screw.BoundBox.intersect(o.Shape.BoundBox):
|
||||
vol=screw.common(o.Shape).Volume
|
||||
if vol>1e-4:hits.append(['bolt',idx,o.Name,vol])
|
||||
b=d.addObject('PartDesign::Feature','FanBolt'+str(idx));b.Shape=screw;b.Label='M4 fastener illustrative, T-nut not modelled';b.ViewObject.ShapeColor=(.65,.66,.68);bolts.append(b)
|
||||
holes.append({'x':px,'y':py,'distance_to_rail_end':min(py+55,75-py)})
|
||||
if hits:raise Exception('SCREW COLLISION '+str(hits))
|
||||
d.recompute();d.Label='Motor side corners, direct fan, 130mm profiles'
|
||||
d.saveAs(str(out/'Assembly.FCStd'));obj=[o for o in d.Objects if hasattr(o,'Shape') and not o.Shape.isNull() and o.ViewObject.Visibility];Import.export(obj,str(out/'Assembly.step'))
|
||||
view=G.activeDocument().activeView();view.viewAxonometric();G.updateGui();view.fitAll();time.sleep(.5);G.updateGui();view.saveImage(str(out/'assembly.png'),1800,1300,'White')
|
||||
vis={o.Name:o.ViewObject.Visibility for o in d.Objects if hasattr(o,'Shape')};show={'Rail0','Rail1','NewRail0','NewRail1','MotorBaseCorner0','MotorBaseCorner1','DirectFan','FanBolt0','FanBolt1','Motor','OpenPillarBracket','Holder','Magnet','PCB','Chip','Corner0','Corner1','Corner2','Corner3'}
|
||||
for o in d.Objects:
|
||||
if hasattr(o,'Shape'):o.ViewObject.Visibility=o.Name in show
|
||||
view.viewTop();G.updateGui();view.fitAll();time.sleep(.5);G.updateGui();view.saveImage(str(out/'fan_top.png'),1800,1300,'White')
|
||||
view.viewAxonometric();G.updateGui();view.fitAll();time.sleep(.5);G.updateGui();view.saveImage(str(out/'fan_detail.png'),1800,1300,'White')
|
||||
for o in d.Objects:
|
||||
if hasattr(o,'Shape'):o.ViewObject.Visibility=vis.get(o.Name,False)
|
||||
d.recompute();d.saveAs(str(out/'Assembly.FCStd'));A.closeDocument(d.Name)
|
||||
d=A.openDocument(str(out/'Assembly.FCStd'));d.recompute();assert all(d.getObject(n).Shape.isValid() for n in ['Rail0','Rail1','DirectFan','MotorBaseCorner0','MotorBaseCorner1']);assert all(abs(d.getObject('Rail%d'%i).Shape.BoundBox.YLength-130)<1e-6 for i in (0,1));step=Part.read(str(out/'Assembly.step'));assert step.isValid() and len(step.Solids)>0
|
||||
data={'rail_length':130,'rail_limits':[-55,75],'fan_center_y':10,'motor_center_y':10,'fan_rotation_degrees':theta,'holes':holes,'corner_contact_distance':pairs,'fan_screw_extension_collisions':hits,'note':'Simplified fan, motor geometry; T nut and T slot, actual screw insertion trajectory, tooling, wires and fan hub unmodelled.'}
|
||||
(out/'validation.json').write_text(json.dumps(data,ensure_ascii=False,indent=2),encoding='utf-8');A.closeDocument(d.Name);(out/'DONE.txt').write_text('ok');os._exit(0)
|
||||
except Exception:
|
||||
(out/'ERROR.txt').write_text(traceback.format_exc(),encoding='utf-8');os._exit(1)
|
||||
|
||||
Reference in New Issue
Block a user