着脱式ケーブルトレイ
着脱式プローブホルダーにオシロスコープのプローブをセットしたときに垂れ下がったケーブルを受ける、ケーブルトレイも着脱式で作ってみました。
import FreeCAD as App
import Draft
# パラメーター
wt = 1.6 #肉厚
filletR = 2 #フィレット半径
fillet2R = wt*0.49 #フィレット(小)半径
fillet3R = filletR + wt #フィレット(大)半径
sizeX = 120 #外形(x)
sizeY = 30 #外形(y)
sizeZ = 25 #外形(z)
bsPosX = [(15+(30*i)) for i in range(4)] #着脱ソケット位置(x)
bsSizeX = 10 #着脱ベース底部幅/2
bsSizeY = 3 #着脱ベース厚み
bsSizeZ = 20 #着脱ベース高さ
bsGrdXZ = 1/10 #着脱ベース斜面の傾き(x/z)
bsGrdXY = 1/1 #着脱ベース斜面の傾き(x/y)
bsfilletR = 0.5 #着脱ベース部フィレット半径
scSizeX = bsSizeX + wt #着脱ソケット幅/2
scSizeY = 3 + wt #着脱ベース厚み
scfilletR = 0.2 #着脱ソケット部フィレット半径
def box(
body, #追加先ボディ
name = 'Box', #名前
size = (10, 20, 30), #サイズ
):
feature = App.ActiveDocument.addObject('PartDesign::AdditiveBox', name)
feature.Length = size[0]
feature.Width = size[1]
feature.Height = size[2]
b = body.addObject(feature)
doc.recompute()
return b[0]
#加算ロフト
def aloft(
body,
sections,
name = 'AdditiveLoft'
):
lf = body.newObject('PartDesign::AdditiveLoft',name)
lf.Profile = sections[0]
lf.Sections += sections[1:]
for s in sections:
s.Visibility = False
return lf
#加算ロフトによる多面体
def aloft_hedron(
body,
l_vertices, #頂点リスト[[]]
name = 'alhedron'
):
l_w = [Draft.make_wire([App.Vector(p) for p in lp], closed=True) for lp in l_vertices]
[body.addObject(w) for w in l_w]
lf = aloft(body, l_w, name)
return lf
#ブーリアン演算
def pd_boolean(
body, #演算を受けるボディ
l_obj, #演算するボディ
type = 'Fuse',
name = 'Boolean',
):
bl = body.newObject('PartDesign::Boolean', name)
bl.addObjects(l_obj)
bl.Type = type
for o in l_obj:
o.Visibility = False
return bl
# 厚みツール
def thickness(
body,
shape, #適用対象図形
face,
name = 'Thickness',
wth = 1 #厚み
):
th = body.newObject('PartDesign::Thickness', name)
th.Base = shape, face
th.Value = wth
return th
# 押し出し
def pad(
body,
profile,
name = 'Pad',
len = 10 #押し出し長
):
pd = body.newObject('PartDesign::Pad', name)
pd.Profile = profile
pd.Length = len
if type(profile) != list:
profile.Visibility = False
return pd
doc = App.activeDocument()
if doc == None:
#アクティブドキュメントが存在しなければ新規作成
doc = App.newDocument()
#着脱ベース
for i in range(2): #0:肉抜きなし 1:あり
bd_bs = doc.addObject('PartDesign::Body',f'base{i}')
x = sizeX + (30 * (i+1))
bx0 = x - bsSizeX
bx1 = x + bsSizeX
xdy = bsSizeY * bsGrdXY #背面と内側のxサイズの差
xdz = bsSizeZ * bsGrdXZ #上下のxサイズの差
bz0 = 0
bz1 = bsSizeZ
l2_p = [
[(bx0+xdy, 0, bz0), (bx1-xdy, 0, bz0), (bx1-xdz-xdy, 0, bz1), (bx0+xdz+xdy, 0, bz1)]
,[(bx0, bsSizeY, bz0), (bx1, bsSizeY, bz0), (bx1-xdz, bsSizeY, bz1), (bx0+xdz, bsSizeY, bz1)]
]
bs = aloft_hedron(bd_bs, l2_p, f'pg{i}')
doc.recompute()
#肉厚分の箱にくり抜く
if i > 0:
faces = bs.Shape.Faces
bf = [f'Face{i+1}' for i,f in enumerate(faces) if (bsSizeY-0.1) < f.CenterOfMass.y < (bsSizeY+0.1)]
bs = thickness(bd_bs, bs, bf, f'bs_ol{i}', wt)
doc.recompute()
#フィレット
edges = bs.Shape.Edges
fil_edges = []
for i, ed in enumerate(edges):
sel = False
for vx in ed.Vertexes:
if (
((0+0.1) < vx.Y)
):
sel = True
break
if sel:
fil_edges.append(f'Edge{i+1}')
fil = bd_bs.newObject('PartDesign::Fillet',f'bsfil{i}')
fil.Radius = bsfilletR
fil.Base = (bs, fil_edges)
doc.recompute()
#ケーブルトレイのボディ
bd_ct = doc.addObject('PartDesign::Body','cabletray')
#外形の箱
ct = box(bd_ct, 'outline', (sizeX, sizeY, sizeZ))
#肉厚分の箱にくり抜く
faces = ct.Shape.Faces
bf = [f'Face{i+1}' for i,f in enumerate(faces) if (sizeZ-0.1) < f.CenterOfMass.z < (sizeZ+0.1)]
ct = thickness(bd_ct, ct, bf, 'box_ol', wt)
doc.recompute()
#着脱ソケット用に背面の厚みを増やす
faces = ct.Shape.Faces
bf = [f'Face{i+1}' for i,f in enumerate(faces) if (wt-0.1) < f.CenterOfMass.y < (wt+0.1)]
ct = pad(bd_ct, [ct, bf],'socketwall', (bsSizeY))
#着脱ソケット
for i, x in enumerate(bsPosX):
bd_sc = doc.addObject('PartDesign::Body',f'socket{i}')
bx0 = x - bsSizeX
bx1 = x + bsSizeX
xdy = bsSizeY * bsGrdXY #背面と内側のxサイズの差
xdz = sizeZ * bsGrdXZ #上下のxサイズの差
bz0 = 0
bz1 = sizeZ
l2_p = [
[(bx0+xdy, 0, bz0), (bx1-xdy, 0, bz0), (bx1-xdz-xdy, 0, bz1), (bx0+xdz+xdy, 0, bz1)]
,[(bx0, bsSizeY, bz0), (bx1, bsSizeY, bz0), (bx1-xdz, bsSizeY, bz1), (bx0+xdz, bsSizeY, bz1)]
]
sc = aloft_hedron(bd_sc, l2_p, f'sc{i}')
ct = pd_boolean(bd_ct, [bd_sc], 'Cut', f'bsc{i}')
doc.recompute()
#フィレット(大)
edges = ct.Shape.Edges
fil_edges = []
for i, ed in enumerate(edges):
sel = False
if (
((sizeY-0.1) < ed.CenterOfGravity.y < (sizeY+0.1)) and
(((sizeZ/2)-0.1) < ed.CenterOfGravity.z < ((sizeZ/2)+0.1))
):
sel = True
fil_edges.append(f'Edge{i+1}')
fil = bd_ct.newObject('PartDesign::Fillet','Fillet')
fil.Radius = fillet3R
fil.Base = (ct, fil_edges)
doc.recompute()
ct = fil
#フィレット
edges = ct.Shape.Edges
fil_edges = []
for i, ed in enumerate(edges):
sel = False
for vx in ed.Vertexes:
if (
((wt-0.1) < vx.Z < (wt+0.1))
):
sel = True
break
if sel:
fil_edges.append(f'Edge{i+1}')
fil = bd_ct.newObject('PartDesign::Fillet','Fillet')
fil.Radius = filletR
fil.Base = (ct, fil_edges)
doc.recompute()
ct = fil
#フィレット(小)
edges = ct.Shape.Edges
fil_edges = []
for i, ed in enumerate(edges):
sel = False
for vx in ed.Vertexes:
if (
((wt+0.1) < vx.Z) and (bsSizeY < vx.Y)
):
sel = True
break
if sel:
fil_edges.append(f'Edge{i+1}')
fil = bd_ct.newObject('PartDesign::Fillet','Fillet')
fil.Radius = fillet2R
fil.Base = (ct, fil_edges)
doc.recompute()
ct = fil
##着脱ソケット部のフィレット
edges = ct.Shape.Edges
fil_edges = []
for i, ed in enumerate(edges):
sel = False
for vx in ed.Vertexes:
if (
#着脱ソケット部
(((0-0.1) < vx.Y < (bsSizeY+0.1)) and ((0+0.1) < vx.Z))
):
sel = True
break
if sel:
fil_edges.append(f'Edge{i+1}')
fil = bd_ct.newObject('PartDesign::Fillet','Fillet')
fil.Radius = scfilletR
fil.Base = (ct, fil_edges)
doc.recompute()
ct = fil