1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

FreeCADのPythonスクリプトで着脱式ケーブルトレイも作ってみた

Posted at

着脱式ケーブルトレイ

着脱式プローブホルダーにオシロスコープのプローブをセットしたときに垂れ下がったケーブルを受ける、ケーブルトレイも着脱式で作ってみました。

image.png

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
1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?