66 lines
3.7 KiB
Plaintext
66 lines
3.7 KiB
Plaintext
from pathlib import Path
|
|
import os, time, traceback, math
|
|
import FreeCAD as A, FreeCADGui as G, Part, Import
|
|
from pivy import coin
|
|
R=Path(r'C:\projects\wheel'); O=R/'models'/'switch_2020_direct_profiles';O.mkdir(parents=True,exist_ok=True)
|
|
try:
|
|
d=A.openDocument(str(R/'models'/'switch_2020_raise10_concept'/'Assembly.FCStd'))
|
|
for n in ('Rail0','Rail1','MotorBaseCorner0','MotorBaseCorner1'):
|
|
o=d.getObject(n);p=o.Placement;p.Base.y-=10;o.Placement=p
|
|
for n in ('MotorShim0','MotorShim1'):
|
|
if d.getObject(n):d.removeObject(n)
|
|
d.Label='Switch crossbeam - raised shaft, direct profile contact'
|
|
d.recompute()
|
|
checks=[]
|
|
def compare(a,b):
|
|
aa=d.getObject(a).Shape;bb=d.getObject(b).Shape
|
|
volume=aa.common(bb).Volume if aa.BoundBox.intersect(bb.BoundBox) else 0
|
|
distance=aa.distToShape(bb)[0]
|
|
checks.append('%s / %s: overlap=%.9f distance=%.6f'%(a,b,volume,distance))
|
|
return volume,distance
|
|
for i in range(2):
|
|
compare('Rail%d'%i,'NewRail%d'%i)
|
|
compare('Rail%d'%i,'MotorBaseCorner%d'%i)
|
|
compare('NewRail%d'%i,'MotorBaseCorner%d'%i)
|
|
for i in range(4):
|
|
q=d.getObject('Corner%d'%i); rail=d.getObject('Rail%d'%(i//2));bb=q.Shape.BoundBox
|
|
compare(q.Name,rail.Name); compare(q.Name,'Motor')
|
|
centers=[]
|
|
for face in q.Shape.Faces:
|
|
s=face.Surface
|
|
if hasattr(s,'Radius') and abs(s.Radius-2.75)<1e-5 and hasattr(s,'Axis') and abs(abs(s.Axis.x)-1)<1e-5:
|
|
centers.append((s.Center.y,s.Center.z))
|
|
checks.append('%s side-hole cylinders %s bbox=%s rail_y=%s..%s'%(q.Name,str(centers),str(bb),rail.Shape.BoundBox.YMin,rail.Shape.BoundBox.YMax))
|
|
if not centers:raise Exception('Missing profile side hole in '+q.Name)
|
|
for y,z in centers:
|
|
if not (rail.Shape.BoundBox.YMin < y < rail.Shape.BoundBox.YMax and abs(z-10)<1e-5):raise Exception('Profile side hole outside rail slot: '+q.Name)
|
|
checks.append('%s hole y=%.5f z=%.5f near_end=%.5f'%(q.Name,y,z,min(y-rail.Shape.BoundBox.YMin,rail.Shape.BoundBox.YMax-y)))
|
|
for name in ('Rail0','Rail1','MotorBaseCorner0','MotorBaseCorner1'):
|
|
x=d.getObject(name)
|
|
for o in d.Objects:
|
|
if o==x or not hasattr(o,'Shape') or o.Shape.isNull() or not o.ViewObject.Visibility:continue
|
|
if o.Name in ('Rail0','Rail1','MotorBaseCorner0','MotorBaseCorner1'):continue
|
|
if x.Shape.BoundBox.intersect(o.Shape.BoundBox):
|
|
vol=x.Shape.common(o.Shape).Volume
|
|
if vol>.001:checks.append('POSITIVE %s / %s volume=%.8f'%(name,o.Name,vol))
|
|
(O/'检查.txt').write_text('\n'.join(checks)+'\n',encoding='utf8')
|
|
d.saveAs(str(O/'Assembly.FCStd'))
|
|
Import.export([o for o in d.Objects if hasattr(o,'Shape') and not o.Shape.isNull() and o.ViewObject.Visibility],str(O/'Assembly.step'))
|
|
G.activateWorkbench('PartWorkbench');view=G.activeDocument().activeView()
|
|
def snap(name,mode):
|
|
if mode=='top':view.viewTop()
|
|
else:view.viewAxonometric();G.updateGui();view.getCameraNode().orientation.setValue(coin.SbRotation(.880476,.115917,-.279848,-.364705))
|
|
G.updateGui();time.sleep(.3);view.fitAll();G.updateGui();time.sleep(.4);view.saveImage(str(O/name),1800,1250,'White')
|
|
snap('assembly.png','axon')
|
|
vis={o.Name:o.ViewObject.Visibility for o in d.Objects if hasattr(o,'Shape')}
|
|
show=set(['Motor','Rail0','Rail1','NewRail0','NewRail1','MotorBaseCorner0','MotorBaseCorner1','Corner0','Corner1','Corner2','Corner3','OpenPillarBracket','PCB','Holder','Magnet'])
|
|
for o in d.Objects:
|
|
if hasattr(o,'Shape'):o.ViewObject.Visibility=o.Name in show
|
|
snap('motor_detail.png','axon');snap('motor_top.png','top')
|
|
for o in d.Objects:
|
|
if hasattr(o,'Shape'):o.ViewObject.Visibility=vis.get(o.Name,True)
|
|
d.recompute();d.saveAs(str(O/'Assembly.FCStd'));A.closeDocument(d.Name)
|
|
(O/'DONE.txt').write_text('ok',encoding='utf8');os._exit(0)
|
|
except Exception:
|
|
(O/'ERROR.txt').write_text(traceback.format_exc(),encoding='utf8');os._exit(1)
|