日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

基于约束的装配设计【CadQuery】

發布時間:2023/12/14 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于约束的装配设计【CadQuery】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本教程介紹在CadQuery中如何使用裝配約束功能來構建逼真的模型,我們將組裝一個由 20x20 V 型槽型材制成的門組件。

1、定義參數

我們希望從定義模型參數開始,以便以后可以輕松更改尺寸:

import cadquery as cq# Parameters H = 400 W = 200 D = 350PROFILE = cq.importers.importDXF("vslot-2020_1.dxf").wires()SLOT_D = 5 PANEL_T = 3HANDLE_D = 20 HANDLE_L = 50 HANDLE_W = 4

值得注意的是,v 槽輪廓是從 DXF 文件導入的。 這樣就很容易更換為其他鋁型材,例如博世或其他供應商提供的 DXF 文件。

2、定義可重用組件

接下來我們要定義根據指定參數生成裝配組件的函數。

def make_vslot(l):return PROFILE.toPending().extrude(l)def make_connector():rv = (cq.Workplane().box(20, 20, 20).faces("<X").workplane().cboreHole(6, 15, 18).faces("<Z").workplane(centerOption="CenterOfMass").cboreHole(6, 15, 18))# tag mating facesrv.faces(">X").tag("X").end()rv.faces(">Z").tag("Z").end()return rvdef make_panel(w, h, t, cutout):rv = (cq.Workplane("XZ").rect(w, h).extrude(t).faces(">Y").vertices().rect(2*cutout,2*cutout).cutThruAll().faces("<Y").workplane().pushPoints([(-w / 3, HANDLE_L / 2), (-w / 3, -HANDLE_L / 2)]).hole(3))# tag mating edgesrv.faces(">Y").edges("%CIRCLE").edges(">Z").tag("hole1")rv.faces(">Y").edges("%CIRCLE").edges("<Z").tag("hole2")return rvdef make_handle(w, h, r):pts = ((0, 0), (w, 0), (w, h), (0, h))path = cq.Workplane().polyline(pts)rv = (cq.Workplane("YZ").rect(r, r).sweep(path, transition="round").tag("solid").faces("<X").workplane().faces("<X", tag="solid").hole(r / 1.5))# tag mating facesrv.faces("<X").faces(">Y").tag("mate1")rv.faces("<X").faces("<Y").tag("mate2")return rv

3、初始裝配

接下來我們要實例化所有組件并將它們添加到組件中。

# define the elements door = (cq.Assembly().add(make_vslot(H), name="left").add(make_vslot(H), name="right").add(make_vslot(W), name="top").add(make_vslot(W), name="bottom").add(make_connector(), name="con_tl", color=cq.Color("black")).add(make_connector(), name="con_tr", color=cq.Color("black")).add(make_connector(), name="con_bl", color=cq.Color("black")).add(make_connector(), name="con_br", color=cq.Color("black")).add(make_panel(W + SLOT_D, H + SLOT_D, PANEL_T, SLOT_D),name="panel",color=cq.Color(0, 0, 1, 0.2),).add(make_handle(HANDLE_D, HANDLE_L, HANDLE_W),name="handle",color=cq.Color("yellow"),) )

4、約束定義

然后我們要定義所有的約束:

# define the constraints (door# left profile.constrain("left@faces@<Z", "con_bl?Z", "Plane").constrain("left@faces@<X", "con_bl?X", "Axis").constrain("left@faces@>Z", "con_tl?Z", "Plane").constrain("left@faces@<X", "con_tl?X", "Axis")# top.constrain("top@faces@<Z", "con_tl?X", "Plane").constrain("top@faces@<Y", "con_tl@faces@>Y", "Axis")# bottom.constrain("bottom@faces@<Y", "con_bl@faces@>Y", "Axis").constrain("bottom@faces@>Z", "con_bl?X", "Plane")# right connectors.constrain("top@faces@>Z", "con_tr@faces@>X", "Plane").constrain("bottom@faces@<Z", "con_br@faces@>X", "Plane").constrain("left@faces@>Z", "con_tr?Z", "Axis").constrain("left@faces@<Z", "con_br?Z", "Axis")# right profile.constrain("right@faces@>Z", "con_tr@faces@>Z", "Plane").constrain("right@faces@<X", "left@faces@<X", "Axis")# panel.constrain("left@faces@>X[-4]", "panel@faces@<X", "Plane").constrain("left@faces@>Z", "panel@faces@>Z", "Axis")# handle.constrain("panel?hole1", "handle?mate1", "Plane").constrain("panel?hole2", "handle?mate2", "Point") )

如果你需要做一些基于字符串的選擇器不可能做的不尋常的事情,例如使用 cadquery.selectors.BoxSelector 或用戶定義的選擇器類,可以直接將 cadquery.Shape 對象傳遞給 cadquery.Assembly.constrain( ) 方法。 例如,上面的

.constrain('part1@faces@>Z','part3@faces@<Z','Axis')

等效于:

.constrain('part1',part1.faces('>z').val(),'part3',part3.faces('<Z').val(),'Axis')

此方法需要一個 cadquery.Shape 對象,因此請記住使用 cadquery.Workplane.val() 方法傳遞單個 cadquery.Shape 而不是整個 cadquery.Workplane 對象。

5、最終結果

下面是完整的代碼,包括最后的求解步驟。

import cadquery as cq# Parameters H = 400 W = 200 D = 350PROFILE = cq.importers.importDXF("vslot-2020_1.dxf").wires()SLOT_D = 6 PANEL_T = 3HANDLE_D = 20 HANDLE_L = 50 HANDLE_W = 4def make_vslot(l):return PROFILE.toPending().extrude(l)def make_connector():rv = (cq.Workplane().box(20, 20, 20).faces("<X").workplane().cboreHole(6, 15, 18).faces("<Z").workplane(centerOption="CenterOfMass").cboreHole(6, 15, 18))# tag mating facesrv.faces(">X").tag("X").end()rv.faces(">Z").tag("Z").end()return rvdef make_panel(w, h, t, cutout):rv = (cq.Workplane("XZ").rect(w, h).extrude(t).faces(">Y").vertices().rect(2*cutout,2*cutout).cutThruAll().faces("<Y").workplane().pushPoints([(-w / 3, HANDLE_L / 2), (-w / 3, -HANDLE_L / 2)]).hole(3))# tag mating edgesrv.faces(">Y").edges("%CIRCLE").edges(">Z").tag("hole1")rv.faces(">Y").edges("%CIRCLE").edges("<Z").tag("hole2")return rvdef make_handle(w, h, r):pts = ((0, 0), (w, 0), (w, h), (0, h))path = cq.Workplane().polyline(pts)rv = (cq.Workplane("YZ").rect(r, r).sweep(path, transition="round").tag("solid").faces("<X").workplane().faces("<X", tag="solid").hole(r / 1.5))# tag mating facesrv.faces("<X").faces(">Y").tag("mate1")rv.faces("<X").faces("<Y").tag("mate2")return rv# define the elements door = (cq.Assembly().add(make_vslot(H), name="left").add(make_vslot(H), name="right").add(make_vslot(W), name="top").add(make_vslot(W), name="bottom").add(make_connector(), name="con_tl", color=cq.Color("black")).add(make_connector(), name="con_tr", color=cq.Color("black")).add(make_connector(), name="con_bl", color=cq.Color("black")).add(make_connector(), name="con_br", color=cq.Color("black")).add(make_panel(W + 2*SLOT_D, H + 2*SLOT_D, PANEL_T, SLOT_D),name="panel",color=cq.Color(0, 0, 1, 0.2),).add(make_handle(HANDLE_D, HANDLE_L, HANDLE_W),name="handle",color=cq.Color("yellow"),) )# define the constraints (door# left profile.constrain("left@faces@<Z", "con_bl?Z", "Plane").constrain("left@faces@<X", "con_bl?X", "Axis").constrain("left@faces@>Z", "con_tl?Z", "Plane").constrain("left@faces@<X", "con_tl?X", "Axis")# top.constrain("top@faces@<Z", "con_tl?X", "Plane").constrain("top@faces@<Y", "con_tl@faces@>Y", "Axis")# bottom.constrain("bottom@faces@<Y", "con_bl@faces@>Y", "Axis").constrain("bottom@faces@>Z", "con_bl?X", "Plane")# right connectors.constrain("top@faces@>Z", "con_tr@faces@>X", "Plane").constrain("bottom@faces@<Z", "con_br@faces@>X", "Plane").constrain("left@faces@>Z", "con_tr?Z", "Axis").constrain("left@faces@<Z", "con_br?Z", "Axis")# right profile.constrain("right@faces@>Z", "con_tr@faces@>Z", "Plane").constrain("right@faces@<X", "left@faces@<X", "Axis")# panel.constrain("left@faces@>X[-4]", "panel@faces@<X", "Plane").constrain("left@faces@>Z", "panel@faces@>Z", "Axis")# handle.constrain("panel?hole1", "handle?mate1", "Plane").constrain("panel?hole2", "handle?mate2", "Point") )# solve door.solve()show_object(door,name='door')

6、數據導出

生成的程序集可以導出為 STEP 文件或內部 OCCT XML 格式。

STEP 可以加載到所有 CAD 工具中,例如在 FreeCAD 中,XML 可用于其他使用 OCCT 的應用程序。

door.save('door.step')door.save('door.xml')

當保存為STEP格式時,顏色被保留但不透明。

7、對象位置

可以將對象添加到具有提供的初始位置的裝配中,例如:

import cadquery as cqcone = cq.Solid.makeCone(1, 0, 2)assy = cq.Assembly() assy.add(cone,loc=cq.Location(cq.Vector(0, 0, 0), cq.Vector(1, 0, 0), 180),name="cone0",color=cq.Color("green") ) assy.add(cone, name="cone1", color=cq.Color("blue"))show_object(assy)

作為用戶計算位置的替代方法,約束的 solve() 方法可用于在裝配結果中定位對象。

如果同時使用初始位置和 solve() 方法,求解器將用它的解覆蓋這些初始位置,但是初始位置仍然會影響最終解。 在欠約束系統中,如果對象對成本函數沒有貢獻,或者如果存在多個解決方案(即成本函數最小的多個實例),求解器可能不會移動對象,初始位置可能導致求解器收斂于一個特定的解決方案。 對于非常復雜的組件,設置近似正確的初始位置也可以減少所需的計算時間。

8、約束

約束通常比直接提供位置更好地表示用戶想要建模的現實世界關系。 在上面的例子中,真實世界的關系是每個圓錐體的底面應該接觸,這可以用平面約束建模。 當用戶提供明確的位置(而不是約束)時,也會進行更新,例如,當 cone1 的位置發生變化時。

當至少提供一個約束并運行方法 solve() 時,就定義了一個優化問題。 每個約束都提供一個成本函數,該函數取決于創建約束時指定的兩個對象的位置和方向(由 Location 表示)。 解算器改變裝配子項的位置并嘗試最小化所有成本函數的總和。 因此,通過閱讀下面的成本函數公式,你可以準確理解每個約束的作用。

9、點約束

點約束是一種經常使用的約束,它可以最小化兩點之間的距離。 一些示例用途是居中面或對齊頂點,但它也可用于虛擬頂點以在兩個部件之間創建偏移。

成本函數是:

其中:

  • param是約束的參數,默認為0,
  • ci是第 i 個對象的中心,并且
  • |vi|是 vi 的模,即其長度

創建點約束時, param 參數可用于指定兩個中心之間的所需偏移量。 這個偏移量沒有與之關聯的方向,如果你想指定一個特定方向的偏移量,那么你應該使用一個虛擬頂點。

點約束使用 Center() 來查找參數的中心。 因此它適用于 Shape 的所有子類。

import cadquery as cq# Use the Point constraint to position boxes relative to an arc line = cq.Edge.makeCircle(radius=10, angle1=0, angle2=90) box = cq.Workplane().box(1, 1, 1)assy = cq.Assembly() assy.add(line, name="line")# position the red box on the center of the arc assy.add(box, name="box0", color=cq.Color("red")) assy.constrain("line", "box0", "Point")# position the green box at a normalized distance of 0.8 along the arc position0 = line.positionAt(0.8) assy.add(box, name="box1", color=cq.Color("green")) assy.constrain("line", cq.Vertex.makeVertex(*position0.toTuple()), "box1", box.val(), "Point", )# position the orange box 2 units in any direction from the green box assy.add(box, name="box2", color=cq.Color("orange")) assy.constrain("line",cq.Vertex.makeVertex(*position0.toTuple()),"box2",box.val(),"Point",param=2, )# position the blue box offset 2 units in the x direction from the green box position1 = position0 + cq.Vector(2, 0, 0) assy.add(box, name="box3", color=cq.Color("blue")) assy.constrain("line", cq.Vertex.makeVertex(*position1.toTuple()), "box3", box.val(), "Point", )assy.solve() show_object(assy)

10、軸約束

軸約束最小化兩個向量之間的角度。 它經常用于對齊面和控制對象的旋轉。

成本函數是:

其中:

  • kdir是方向約束的比例因子,
  • param是約束的參數,默認為弧度,
  • di是從第 i 個對象參數創建的方向,如下所述,并且
  • d1<d2是 d1 和 d2之間的弧度角

參數 param默認為π弧度,它將兩個方向設置為彼此相反。 這代表了通常所說的“配對”關系,即兩個物體的外表面接觸。

import cadquery as cqcone = cq.Solid.makeCone(1, 0, 2)assy = cq.Assembly() assy.add(cone, name="cone0", color=cq.Color("green")) assy.add(cone, name="cone1", color=cq.Color("blue")) assy.constrain("cone0@faces@<Z", "cone1@faces@<Z", "Axis")assy.solve() show_object(assy)

如果 param 參數設置為零,則兩個對象將指向同一方向。 這通常在一個物體穿過另一個物體時使用,例如一根釘進入板上的孔:

import cadquery as cqplate = cq.Workplane().box(10, 10, 1).faces(">Z").workplane().hole(2) cone = cq.Solid.makeCone(0.8, 0, 4)assy = cq.Assembly() assy.add(plate, name="plate", color=cq.Color("green")) assy.add(cone, name="cone", color=cq.Color("blue")) # place the center of the flat face of the cone in the center of the upper face of the plate assy.constrain("plate@faces@>Z", "cone@faces@<Z", "Point")# set both the flat face of the cone and the upper face of the plate to point in the same direction assy.constrain("plate@faces@>Z", "cone@faces@<Z", "Axis", param=0)assy.solve() show_object(assy)

在創建軸約束時,將根據對象的類型以三種不同方式之一提取方向矢量:

  • 面:使用 normalAt()
  • Edge 和 geomType() 是“CIRCLE”:使用 normal()
  • Edge 和 geomType() 不是“CIRCLE”:使用 tangentAt()

使用任何其他類型的對象都會引發 ValueError。 到目前為止,最常見的用例是從面定義軸約束。

import cadquery as cq from math import cos, sin, pi# Create a sinusoidal surface: surf = cq.Workplane().parametricSurface(lambda u, v: (u, v, 5 * sin(pi * u / 10) * cos(pi * v / 10)),N=40,start=0,stop=20, )# Create a cone with a small, flat tip: cone = (cq.Workplane().add(cq.Solid.makeCone(1, 0.1, 2))# tag the tip for easy reference in the constraint:.faces(">Z").tag("tip").end() )assy = cq.Assembly() assy.add(surf, name="surf", color=cq.Color("lightgray")) assy.add(cone, name="cone", color=cq.Color("green")) # set the Face on the tip of the cone to point in # the opposite direction of the center of the surface: assy.constrain("surf", "cone?tip", "Axis") # to make the example clearer, move the cone to the center of the face: assy.constrain("surf", "cone?tip", "Point") assy.solve()show_object(assy)

11、平面約束

平面約束只是 點約束和 軸約束的組合。 它是常用約束組合的便捷快捷方式。 它可用于將前面的示例從兩個約束縮短為一個:

assy = cq.Assembly() assy.add(surf, name="surf", color=cq.Color("lightgray")) assy.add(cone, name="cone", color=cq.Color("green")) -# set the Face on the tip of the cone to point in -# the opposite direction of the center of the surface: -assy.constrain("surf", "cone?tip", "Axis") -# to make the example clearer, move the cone to the center of the face: -assy.constrain("surf", "cone?tip", "Point") +assy.constrain("surf", "cone?tip", "Plane") assy.solve()show_object(assy)

此代碼的結果與上述兩個約束示例相同。

面約束的成本函數,請參見 點約束 和 軸約束 部分。 param 參數應用于 Axis 并且應該保留為“mate”樣式約束(兩個表面接觸)的默認值,或者可以設置為 0 用于通過表面約束(參見 軸約束部分中的描述)。

12、點平面約束

點平面約束將第一個對象的中心定位在第二個對象定義的平面內。 成本函數是:

其中:

  • c是第一個對象的中心,
  • poffset是從第二個對象創建的平面,在平面的法線方向上偏移 param參數,并且
  • dist(a,b)是點 a 和 平面 b之間的距離
import cadquery as cq# Create an L-shaped object: bracket = (cq.Workplane("YZ").hLine(1).vLine(0.1).hLineTo(0.2).vLineTo(1).hLineTo(0).close().extrude(1)# tag some faces for easy reference:.faces(">Y[1]").tag("inner_vert").end().faces(">Z[1]").tag("inner_horiz").end() )box = cq.Workplane().box(0.5, 0.5, 0.5)assy = cq.Assembly() assy.add(bracket, name="bracket", color=cq.Color("gray")) assy.add(box, name="box", color=cq.Color("green"))# lock bracket orientation: assy.constrain("bracket@faces@>Z", "box@faces@>Z", "Axis", param=0) assy.constrain("bracket@faces@>X", "box@faces@>X", "Axis", param=0)# constrain the bottom of the box to be on the plane defined by inner_horiz: assy.constrain("box@faces@<Z", "bracket?inner_horiz", "PointInPlane") # constrain the side of the box to be 0.2 units from the plane defined by inner_vert assy.constrain("box@faces@<Y", "bracket?inner_vert", "PointInPlane", param=0.2) # constrain the end of the box to be 0.1 units inside the end of the bracket assy.constrain("box@faces@>X", "bracket@faces@>X", "PointInPlane", param=-0.1)assy.solve() show_object(assy)

13、點線約束

點線約束將第一個對象的中心定位在第二個對象定義的線上。 成本函數是:

其中:

  • c是第一個參數的中心,
  • l是從第二個對象創建的一條線
  • param是約束的參數,默認為0,
  • dist(a,b)是點 a 和線 l之間的距離
import cadquery as cqb1 = cq.Workplane().box(1,1,1) b2 = cq.Workplane().sphere(0.15)assy = (cq.Assembly().add(b1,name='b1').add(b2, loc=cq.Location(cq.Vector(0,0,4)), name='b2', color=cq.Color('red')) )# fix the position of b1 assy.constrain('b1','Fixed') # b2 on one of the edges of b1 assy.constrain('b2','b1@edges@>>Z and >>Y','PointOnLine') # b2 on another of the edges of b1 assy.constrain('b2','b1@edges@>>Z and >>X','PointOnLine') # effectively b2 will be constrained to be on the intersection of the two edgesassy.solve() show_object(assy)

14、固定點約束

固定點約束將給定參數的位置固定為等于通過約束參數指定的給定點。 此約束鎖定參數的所有平移自由度。 成本函數是:

其中:

  • c是對象的中心,
  • param是約束參數 - 指定目標位置的元組,
  • dist(a,b)是點 a 和線 l之間的距離

import cadquery as cqb1 = cq.Workplane().box(1,1,1) b2 = cq.Workplane().sphere(0.15)assy = (cq.Assembly().add(b1,name='b1').add(b2, loc=cq.Location(cq.Vector(0,0,4)), name='b2', color=cq.Color('red')) )# fix the position of b1 assy.constrain('b1','Fixed') # b2 on one of the edges of b1 assy.constrain('b2','b1@edges@>>Z and >>Y','PointOnLine') # b2 on another of the edges of b1 assy.constrain('b2','b1@edges@>>Z and >>X','PointOnLine') # effectively b2 will be constrained to be on the intersection of the two edgesassy.solve() show_object(assy)

15、固定旋轉約束

固定旋轉約束將給定對象的旋轉固定為等于通過約束參數指定的值。 對象首先繞原點旋轉 Z 角,然后是 Y,最后是 X。

該約束鎖定對象的所有旋轉自由度。 成本函數是:

其中:

  • R 向量應用于對象的旋轉角度
  • param是約束參數 - 指定目標旋轉的元組。

import cadquery as cqb1 = cq.Workplane().box(1,1,1) b2 = cq.Workplane().rect(0.1, 0.1).extrude(1,taper=-15)assy = (cq.Assembly().add(b1,name='b1').add(b2, loc=cq.Location(cq.Vector(0,0,4)), name='b2', color=cq.Color('red')) )# fix the position of b1 assy.constrain('b1','Fixed') # fix b2 bottom face position (but not rotation) assy.constrain('b2@faces@<Z','FixedPoint',(0,0,0.5)) # fix b2 rotational degrees of freedom too assy.constrain('b2','FixedRotation',(45,0,45))assy.solve() show_object(assy)

16、固定軸約束

固定軸約束將給定參數的法線或切線的方向固定為等于通過約束參數指定的矢量的方向。 此約束鎖定參數的兩個旋轉自由度。 成本函數是:

其中:

  • a 表示對象的法向量或切向量,
  • param是約束的參數 - 指定目標方向的元組。
import cadquery as cqb1 = cq.Workplane().box(1,1,1) b2 = cq.Workplane().rect(0.1, 0.1).extrude(1,taper=-15)assy = (cq.Assembly().add(b1,name='b1').add(b2, loc=cq.Location(cq.Vector(0,0,4)), name='b2', color=cq.Color('red')) )# fix the position of b1 assy.constrain('b1','Fixed') # fix b2 bottom face position (but not rotation) assy.constrain('b2@faces@<Z','FixedPoint',(0,0,0.5)) # fix b2 some rotational degrees of freedom too assy.constrain('b2@faces@>Z','FixedAxis',(1,0,2))assy.solve() show_object(assy)

原文鏈接:CadQuery裝配約束教程 — BimAnt

總結

以上是生活随笔為你收集整理的基于约束的装配设计【CadQuery】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。