33个CadQuery程序化建模实例

news2025/6/9 20:11:08

本文介绍的33个建模示例可以帮助你了解如何使用 CadQuery 构建3D对象。示例是从简单到复杂组织起来的,因此按顺序学习它们是吸收它们的最佳方式。
在这里插入图片描述

1、简易矩形板

最简单的例子,一个矩形盒子:
在这里插入图片描述

result = cadquery.Workplane("front").box(2.0, 2.0, 0.5)

2、带孔板

一个矩形框,但添加了一个孔。

“>Z”选择盒子的最顶面。 孔位于中心,因为工作平面的默认原点是最后一个工作平面的投影原点,最后一个工作平面的原点为 (0,0,0),投影位于面的中心。 默认孔深贯穿整个零件。

在这里插入图片描述

# The dimensions of the box. These can be modified rather than changing the
# object's code directly.
length = 80.0
height = 60.0
thickness = 10.0
center_hole_dia = 22.0

# Create a box based on the dimensions above and add a 22mm center hole
result = (cq.Workplane("XY").box(length, height, thickness)
    .faces(">Z").workplane().hole(center_hole_dia))

3、挤压棱柱体

使用挤压构建棱柱体。 一次绘制操作后,将前一个对象的中心放入栈中,作为下一次操作的参考。 所以在这种情况下, rect() 以先前绘制的圆为中心绘制。

默认情况下,矩形和圆形以前一个工作点为中心。
在这里插入图片描述

result = cq.Workplane("front").circle(2.0).rect(0.5, 0.75).extrude(0.5)

4、使用线和弧构建轮廓

有时你需要使用直线和圆弧构建复杂的轮廓。 此示例通过 2D 操作构建棱柱实体。

2D 操作维护当前点,该点最初位于原点。 使用 close() 完成闭合曲线。
在这里插入图片描述

result = (cq.Workplane("front").lineTo(2.0, 0).lineTo(2.0, 1.0).threePointArc((1.0, 1.5), (0.0, 1.0))
    .close().extrude(0.25))

5、移动当前工作点

在这个例子中,需要一个封闭的轮廓,以及一些内部特征。

此示例还演示了使用多行代码而不是较长的链式命令,当然在这种情况下也可以在一长行中完成。

可以在任何一点建立一个新的工作平面中心。
在这里插入图片描述

result = cq.Workplane("front").circle(3.0)  # current point is the center of the circle, at (0, 0)
result = result.center(1.5, 0.0).rect(0.5, 0.5)  # new work center is (1.5, 0.0)

result = result.center(-1.5, 1.5).circle(0.25)  # new work center is (0.0, 1.5).
# The new center is specified relative to the previous center, not global coordinates!

result = result.extrude(0.25)

6、使用点列表

有时你需要在不同位置创建多个特征,使用 Workplane.center() 太麻烦了。

可以使用点列表一次构造多个对象。 大多数构造方法,如 Workplane.circle() 和 Workplane.rect(),如果它们在栈上,将对多个点进行操作。
在这里插入图片描述

r = cq.Workplane("front").circle(2.0)                           # make base
r = r.pushPoints([(1.5, 0), (0, 1.5), (-1.5, 0), (0, -1.5)])    # now four points are on the stack
r = r.circle(0.25)                                              # circle will operate on all four points
result = r.extrude(0.125)                                       # make prism

7、多边形

如果愿意,你可以为栈上的每个点创建多边形。 适用于固件无法修正小孔尺寸的 3d 打印机。
在这里插入图片描述

result = (cq.Workplane("front").box(3.0, 4.0, 0.25)
    .pushPoints([(0, 0.75), (0, -0.75)])
    .polygon(6, 1.0).cutThruAll())

8、折线

Workplane.polyline() 允许用连线的大量点创建形状。

此示例使用多段线创建工字梁形状的一半,对其进行镜像以创建最终轮廓。

在这里插入图片描述

(L, H, W, t) = (100.0, 20.0, 20.0, 1.0)
pts = [
    (0, H/2.0),
    (W/2.0, H/2.0),
    (W/2.0, (H/2.0 - t)),
    (t/2.0, (H/2.0 - t)),
    (t/2.0, (t - H/2.0)),
    (W/2.0, (t - H/2.0)),
    (W/2.0, H/-2.0),
    (0, H/-2.0)
]
result = cq.Workplane("front").polyline(pts).mirrorY().extrude(L)

9、用样条曲线定义边

此示例使用点集定义的样条曲线来定义边。 当边需要复杂的轮廓时很有用。
在这里插入图片描述

s = cq.Workplane("XY")
sPnts = [
    (2.75, 1.5),
    (2.5, 1.75),
    (2.0, 1.5),
    (1.5, 1.0),
    (1.0, 1.25),
    (0.5, 1.0),
    (0, 1.0)
]
r = s.lineTo(3.0, 0).lineTo(3.0, 1.0).spline(sPnts, includeCurrent=True).close()
result = r.extrude(0.5)

10、镜像几何形状

当你的几何形状是对称的时,可以镜像 2D 几何体。 在这个例子中,我们还引入了水平线和垂直线,这使得编码稍微容易一些。
在这里插入图片描述

r = cq.Workplane("front").hLine(1.0)                       # 1.0 is the distance, not coordinate
r = r.vLine(0.5).hLine(-0.25).vLine(-0.25).hLineTo(0.0)    # hLineTo allows using xCoordinate not distance
result = r.mirrorY().extrude(0.25)                         # mirror the geometry and extrude

11、镜像三维对象

在这里插入图片描述

result0 = (cadquery.Workplane("XY")
           .moveTo(10, 0)
           .lineTo(5, 0)
           .threePointArc((3.9393, 0.4393), (3.5, 1.5))
           .threePointArc((3.0607, 2.5607), (2, 3))
           .lineTo(1.5, 3)
           .threePointArc((0.4393, 3.4393), (0, 4.5))
           .lineTo(0, 13.5)
           .threePointArc((0.4393, 14.5607), (1.5, 15))
           .lineTo(28, 15)
           .lineTo(28, 13.5)
           .lineTo(24, 13.5)
           .lineTo(24, 11.5)
           .lineTo(27, 11.5)
           .lineTo(27, 10)
           .lineTo(22, 10)
           .lineTo(22, 13.2)
           .lineTo(14.5, 13.2)
           .lineTo(14.5, 10)
           .lineTo(12.5, 10)
           .lineTo(12.5, 13.2)
           .lineTo(5.5, 13.2)
           .lineTo(5.5, 2)
           .threePointArc((5.793, 1.293), (6.5, 1))
           .lineTo(10, 1)
           .close())
result = result0.extrude(100)

result = result.rotate((0, 0, 0), (1, 0, 0), 90)

result = result.translate(result.val().BoundingBox().center.multiply(-1))

mirXY_neg = result.mirror(mirrorPlane="XY", basePointVector=(0, 0, -30))
mirXY_pos = result.mirror(mirrorPlane="XY", basePointVector=(0, 0, 30))
mirZY_neg = result.mirror(mirrorPlane="ZY", basePointVector=(-30, 0, 0))
mirZY_pos = result.mirror(mirrorPlane="ZY", basePointVector=(30, 0, 0))

result = result.union(mirXY_neg).union(mirXY_pos).union(mirZY_neg).union(mirZY_pos)

12、参考面镜像

此示例显示如何围绕选定的面进行镜像。 示例还展示了如何将生成的镜像对象立即与引用的几何体合并。
在这里插入图片描述

result = (cq.Workplane("XY")
          .line(0, 1)
          .line(1, 0)
          .line(0, -.5)
          .close()
          .extrude(1))

result = result.mirror(result.faces(">X"), union=True)

13、在面上创建工作平面

此示例说明如何在先前创建的特征的面上定位新工作平面。

以这种方式使用工作平面是 CadQuery 的一个关键特性。 与典型的 3d 脚本语言不同,使用工作平面使你无需跟踪变量中各种特征的位置,并允许模型通过删除冗余尺寸进行自我调整。

Workplane.faces() 方法允许你选择生成的实体的面。 它接受一个选择器字符串或对象,允许你以单个面为目标,并使工作平面朝向该面。

请记住,默认情况下,新工作平面的原点是通过从所选面形成一个平面并将先前的原点投影到该平面上来计算的。 可以通过 Workplane.workplane() 的 centerOption 参数更改此行为。
在这里插入图片描述

result = cq.Workplane("front").box(2, 3, 0.5)  # make a basic prism
result = result.faces(">Z").workplane().hole(0.5)  # find the top-most face and make a hole

14、在顶点上定位工作平面

通常, Workplane.workplane() 方法需要选择一个面。 但是,如果在选中一个面后立即选择顶点,则将 centerOption 参数设置为 CenterOfMass 的 Workplane.workplane() 会将工作平面定位在面上,原点位于顶点而不是面的中心。

本示例还介绍了 Workplane.cutThruAll(),它对整个零件进行切割,无论零件有多深。

在这里插入图片描述

result = cq.Workplane("front").box(3,2, 0.5)  # make a basic prism
result = result.faces(">Z").vertices("<XY").workplane(centerOption="CenterOfMass")  # select the lower left vertex and make a workplane
result = result.circle(1.0).cutThruAll()  # cut the corner out

15、偏移工作平面

工作平面不必正好位于面上。 创建工作平面时,可以在距现有面一定偏移处定义。

本示例使用偏移工作平面制作复合对象,完全有效!
在这里插入图片描述

result = cq.Workplane("front").box(3, 2, 0.5)         # make a basic prism
result = result.faces("<X").workplane(offset=0.75)    # workplane is offset from the object surface
result = result.circle(1.0).extrude(0.5)              # disc

16、复制工作平面

现有的 CQ 对象可以从另一个 CQ 对象复制工作平面。
在这里插入图片描述

result = (cq.Workplane("front").circle(1).extrude(10)  # make a cylinder
          # We want to make a second cylinder perpendicular to the first,
          # but we have no face to base the workplane off
          .copyWorkplane(
              # create a temporary object with the required workplane
              cq.Workplane("right", origin=(-5, 0, 0))
          ).circle(1).extrude(10))

17、旋转工作平面

可以通过指定相对于另一个工作平面的旋转角度来创建旋转的工作平面。

在这里插入图片描述

result = (cq.Workplane("front").box(4.0, 4.0, 0.25).faces(">Z").workplane()
     .transformed(offset=cq.Vector(0, -1.5, 1.0),rotate=cq.Vector(60, 0, 0))
     .rect(1.5, 1.5, forConstruction=True).vertices().hole(0.25))

18、使用构造几何

你可以绘制形状以将顶点用作定位其他特征的点。 用于定位其他特征而不是创建它们的特征称为构造几何。

在下面的示例中,绘制了一个矩形,其顶点用于定位一组孔。

在这里插入图片描述

result = (cq.Workplane("front").box(2, 2, 0.5).faces(">Z").workplane()
    .rect(1.5, 1.5, forConstruction=True).vertices().hole(0.125))

19、抽壳创建薄壁特征

抽壳将实体对象转换为厚度均匀的壳。

要给对象脱壳并“挖空”内部,请将负厚度参数传递给形状的 Workplane.shell() 方法。

在这里插入图片描述

result = cq.Workplane("front").box(2, 2, 2).shell(-0.1)

正的厚度参数用圆角外边缘包裹对象,原始对象将是“挖空”部分。
在这里插入图片描述

result = cq.Workplane("front").box(2, 2, 2).shell(0.1)

使用面选择器选择要从生成的空心形状中删除的面。

在这里插入图片描述

result = cq.Workplane("front").box(2, 2, 2).faces("+Z").shell(0.1)

可以使用更复杂的选择器删除多个面。

在这里插入图片描述

result = (
     cq.Workplane("front")
     .box(2, 2, 2)
     .faces("+Z or -X or +X")
     .shell(0.1)
)

20、放样

放样是一组线扫掠得到实体。 此示例在矩形和圆形截面之间创建放样截面。

在这里插入图片描述

result = (cq.Workplane("front").box(4.0, 4.0, 0.25).faces(">Z").circle(1.5)
    .workplane(offset=3.0).rect(0.75, 0.5).loft(combine=True))

21、挤压至指定面

有时你会想要挤出一条线直到给定的面,这个面可能不是平面,或者你可能不容易知道必须挤出到的距离。 在这种情况下,可以使用 next、 last 甚至为 extrude() 的 until 参数提供一个 面对象。

在这里插入图片描述

result = (cq.Workplane(origin = (20,0,0))
    .circle(2)
    .revolve(180, (-20,0,0),(-20,-1,0))
    .center(-20,0)
    .workplane()
    .rect(20,4)
    .extrude("next")
)

cutBlind() 也有相同的行为,如你所见,也可以一次处理多个 Wire 对象, extrude() 也是如此。

在这里插入图片描述

skyscrapers_locations = [(-16,1),(-8,0),(7,0.2),(17,-1.2)]
angles = iter([15,0,-8,10])
skyscrapers = (cq.Workplane()
    .pushPoints(skyscrapers_locations)
    .eachpoint(lambda loc: (cq.Workplane()
                            .rect(5,16)
                            .workplane(offset=10)
                            .ellipse(3,8)
                            .workplane(offset=10)
                            .slot2D(20,5, 90)
                            .loft()
                            .rotateAboutCenter((0,0,1),next(angles))
                            .val().located(loc)
                            )
    )
)

result = (skyscrapers
    .transformed((0,-90,0))
    .moveTo(15,0)
    .rect(3,3, forConstruction=True)
    .vertices()
    .circle(1)
    .cutBlind("last")
)

这是一个典型的情况,其中挤压和切割直到给定的表面非常方便。 它允许我们挤压或切割直到曲面而不会出现重叠问题。
在这里插入图片描述

import cadquery as cq

sphere = cq.Workplane().sphere(5)
base = (cq.Workplane(origin=(0,0,-2))
    .box(12,12,10)
    .cut(sphere)
    .edges("|Z")
    .fillet(2)
)
sphere_face = base.faces(">>X[2] and (not |Z) and (not |Y)").val()
base = (base
    .faces("<Z")
    .workplane()
    .circle(2)
    .extrude(10)
)

shaft = (cq.Workplane()
    .sphere(4.5)
    .circle(1.5)
    .extrude(20)
)

spherical_joint = (base.union(shaft)
    .faces(">X")
    .workplane(centerOption="CenterOfMass")
    .move(0,4)
    .slot2D(10,2,90)
    .cutBlind(sphere_face)
    .workplane(offset=10)
    .move(0,2)
    .circle(0.9)
    .extrude("next")
)

result = spherical_joint

22、制作沉头孔和埋头孔

沉头孔和埋头孔非常常见,以至于 CadQuery 专门创建宏以在一个步骤中创建它们。

与 Workplane.hole() 类似,这些函数对点列表以及单个点进行操作。

在这里插入图片描述

result = (
    cq.Workplane(cq.Plane.XY())
    .box(4, 2, 0.5)
    .faces(">Z")
    .workplane()
    .rect(3.5, 1.5, forConstruction=True)
    .vertices()
    .cboreHole(0.125, 0.25, 0.125, depth=None)
)

23、2D 中的偏移线

可以使用 Workplane.offset2D() 转换二维线。 它们可以向内或向外偏移,并使用不同的技术来扩展角落。
在这里插入图片描述

original = cq.Workplane().polygon(5, 10).extrude(0.1).translate((0, 0, 2))
arc = (
    cq.Workplane()
    .polygon(5, 10)
    .offset2D(1, "arc")
    .extrude(0.1)
    .translate((0, 0, 1))
)
intersection = cq.Workplane().polygon(5, 10).offset2D(1, "intersection").extrude(0.1)
result = original.add(arc).add(intersection)

使用 forConstruction 参数,你可以执行从对象轮廓偏移一系列螺栓孔的常见任务。 这是上面的沉孔示例,但螺栓孔从边缘偏移。
在这里插入图片描述

result = (
    cq.Workplane()
    .box(4, 2, 0.5)
    .faces(">Z")
    .edges()
    .toPending()
    .offset2D(-0.25, forConstruction=True)
    .vertices()
    .cboreHole(0.125, 0.25, 0.125, depth=None)
)

请注意, Workplane.edges() 用于选择对象。 它不会将选定的边添加到建模上下文中的待定边,因为这会导致你的下一次挤压包括除了绘制的线条之外选择的所有内容。 如果希望这些边在 Workplane.offset2D() 中使用,可以调用 Workplane.toPending() 以明确地将它们放入待定边列表中。

24、圆角

圆角是通过选择实体的边并使用圆角功能完成的。

在这里,我们对一个简单板的所有边缘进行圆角处理。
在这里插入图片描述

result = cq.Workplane("XY").box(3, 3, 0.5).edges("|Z").fillet(0.125)

25、标记对象

Workplane.tag() 方法可用于用字符串标记链中的特定对象,以便稍后在链中引用它。

Workplane.workplaneFromTagged() 方法将 Workplane.copyWorkplane() 应用于标记对象。 例如,当从一个表面挤出两个不同的实体时,在第一个实体被挤出后,很难用 CadQuery 的其他选择器重新选择原始表面。

在这里插入图片描述

result = (cq.Workplane("XY")
          # create and tag the base workplane
          .box(10, 10, 10).faces(">Z").workplane().tag("baseplane")
          # extrude a cylinder
          .center(-3, 0).circle(1).extrude(3)
          # to reselect the base workplane, simply
          .workplaneFromTagged("baseplane")
          # extrude a second cylinder
          .center(3, 0).circle(1).extrude(2))

标签也可以与大多数选择器一起使用,包括 Workplane.vertices()、 Workplane.faces()、 Workplane.edges()、 Workplane.wires()、 Workplane.shells()、 Workplane.solids() 和 Workplane.compounds( ) 。
在这里插入图片描述

result = (cq.Workplane("XY")
          # create a triangular prism and tag it
          .polygon(3, 5).extrude(4).tag("prism")
          # create a sphere that obscures the prism
          .sphere(10)
          # create features based on the prism's faces
          .faces("<X", tag="prism").workplane().circle(1).cutThruAll()
          .faces(">X", tag="prism").faces(">Y").workplane().circle(1).cutThruAll())

26、参数化轴承座

结合一些基本功能,只需几行代码就可以制作出非常好的参数化轴承座。

在这里插入图片描述

(length, height, bearing_diam, thickness, padding) = (30.0, 40.0, 22.0, 10.0, 8.0)

result = (cq.Workplane("XY").box(length, height, thickness).faces(">Z").workplane().hole(bearing_diam)
        .faces(">Z").workplane()
        .rect(length-padding, height-padding, forConstruction=True)
        .vertices().cboreHole(2.4, 4.4, 2.1))

27、拆分对象

可以使用工作平面拆分对象,并保留其中一个或两个部分。

在这里插入图片描述

c = cq.Workplane("XY").box(1, 1, 1).faces(">Z").workplane().circle(0.25).cutThruAll()

# now cut it in half sideways
result = c.faces(">Y").workplane(-0.5).split(keepTop=True)

28、经典 OCC 瓶

CadQuery 基于 OpenCascade.org (OCC) 建模内核。 熟悉 OCC 的人都知道著名的瓶子示例。

此处列出了 pythonOCC 版本 的实现。

当然,此示例与 OCC 版本之间的一个区别是长度。 这个示例是 13 行的较长示例之一,但与 pythonOCC 版本相比非常短,后者长 10 倍!

在这里插入图片描述

(L, w, t) = (20.0, 6.0, 3.0)
s = cq.Workplane("XY")

# Draw half the profile of the bottle and extrude it
p = (s.center(-L/2.0, 0).vLine(w/2.0)
    .threePointArc((L/2.0, w/2.0 + t), (L, w/2.0)).vLine(-w/2.0)
    .mirrorX().extrude(30.0, True))

# Make the neck
p = p.faces(">Z").workplane(centerOption="CenterOfMass").circle(3.0).extrude(2.0, True)

# Make a shell
result = p.faces(">Z").shell(0.3)

29、参数化外壳

在这里插入图片描述

# parameter definitions
p_outerWidth = 100.0  # Outer width of box enclosure
p_outerLength = 150.0  # Outer length of box enclosure
p_outerHeight = 50.0  # Outer height of box enclosure

p_thickness = 3.0  # Thickness of the box walls
p_sideRadius = 10.0  # Radius for the curves around the sides of the box
p_topAndBottomRadius = 2.0  # Radius for the curves on the top and bottom edges of the box

p_screwpostInset = 12.0  # How far in from the edges the screw posts should be place.
p_screwpostID = 4.0  # Inner Diameter of the screw post holes, should be roughly screw diameter not including threads
p_screwpostOD = 10.0  # Outer Diameter of the screw posts.\nDetermines overall thickness of the posts

p_boreDiameter = 8.0  # Diameter of the counterbore hole, if any
p_boreDepth = 1.0  # Depth of the counterbore hole, if
p_countersinkDiameter = 0.0  # Outer diameter of countersink. Should roughly match the outer diameter of the screw head
p_countersinkAngle = 90.0  # Countersink angle (complete angle between opposite sides, not from center to one side)
p_flipLid = True  # Whether to place the lid with the top facing down or not.
p_lipHeight = 1.0  # Height of lip on the underside of the lid.\nSits inside the box body for a snug fit.

# outer shell
oshell = cq.Workplane("XY").rect(p_outerWidth, p_outerLength).extrude(p_outerHeight + p_lipHeight)

# weird geometry happens if we make the fillets in the wrong order
if p_sideRadius > p_topAndBottomRadius:
    oshell = oshell.edges("|Z").fillet(p_sideRadius)
    oshell = oshell.edges("#Z").fillet(p_topAndBottomRadius)
else:
    oshell = oshell.edges("#Z").fillet(p_topAndBottomRadius)
    oshell = oshell.edges("|Z").fillet(p_sideRadius)

# inner shell
ishell = (oshell.faces("<Z").workplane(p_thickness, True)
    .rect((p_outerWidth - 2.0*p_thickness), (p_outerLength - 2.0*p_thickness))
    .extrude((p_outerHeight - 2.0*p_thickness), False)  # set combine false to produce just the new boss
)
ishell = ishell.edges("|Z").fillet(p_sideRadius - p_thickness)

# make the box outer box
box = oshell.cut(ishell)

# make the screw posts
POSTWIDTH = (p_outerWidth - 2.0*p_screwpostInset)
POSTLENGTH = (p_outerLength - 2.0*p_screwpostInset)

box = (box.faces(">Z").workplane(-p_thickness)
    .rect(POSTWIDTH, POSTLENGTH, forConstruction=True)
    .vertices().circle(p_screwpostOD/2.0).circle(p_screwpostID/2.0)
    .extrude(-1.0*(p_outerHeight + p_lipHeight - p_thickness),True))

# split lid into top and bottom parts
(lid, bottom) = box.faces(">Z").workplane(-p_thickness - p_lipHeight).split(keepTop=True, keepBottom=True).all()  # splits into two solids

# translate the lid, and subtract the bottom from it to produce the lid inset
lowerLid = lid.translate((0, 0, -p_lipHeight))
cutlip = lowerLid.cut(bottom).translate((p_outerWidth + p_thickness, 0, p_thickness - p_outerHeight + p_lipHeight))

# compute centers for screw holes
topOfLidCenters = (cutlip.faces(">Z").workplane(centerOption="CenterOfMass")
    .rect(POSTWIDTH, POSTLENGTH, forConstruction=True).vertices())

# add holes of the desired type
if p_boreDiameter > 0 and p_boreDepth > 0:
    topOfLid = topOfLidCenters.cboreHole(p_screwpostID, p_boreDiameter, p_boreDepth, 2.0*p_thickness)
elif p_countersinkDiameter > 0 and p_countersinkAngle > 0:
    topOfLid = topOfLidCenters.cskHole(p_screwpostID, p_countersinkDiameter, p_countersinkAngle, 2.0*p_thickness)
else:
    topOfLid = topOfLidCenters.hole(p_screwpostID, 2.0*p_thickness)

# flip lid upside down if desired
if p_flipLid:
    topOfLid = topOfLid.rotateAboutCenter((1, 0, 0), 180)

# return the combined result
result = topOfLid.union(bottom)

30、乐高积木

此脚本将生成任何尺寸的常规矩形 Lego™ 积木。 唯一棘手的是关于砖块底部的逻辑。
在这里插入图片描述

#####
# Inputs
######
lbumps = 6     # number of bumps long
wbumps = 2     # number of bumps wide
thin = True    # True for thin, False for thick

#
# Lego Brick Constants-- these make a Lego brick a Lego :)
#
pitch = 8.0
clearance = 0.1
bumpDiam = 4.8
bumpHeight = 1.8
if thin:
    height = 3.2
else:
    height = 9.6

t = (pitch - (2 * clearance) - bumpDiam) / 2.0
postDiam = pitch - t  # works out to 6.5
total_length = lbumps*pitch - 2.0*clearance
total_width = wbumps*pitch - 2.0*clearance

# make the base
s = cq.Workplane("XY").box(total_length, total_width, height)

# shell inwards not outwards
s = s.faces("<Z").shell(-1.0 * t)

# make the bumps on the top
s = (s.faces(">Z").workplane().
    rarray(pitch, pitch, lbumps, wbumps, True).circle(bumpDiam / 2.0)
    .extrude(bumpHeight))

# add posts on the bottom. posts are different diameter depending on geometry
# solid studs for 1 bump, tubes for multiple, none for 1x1
tmp = s.faces("<Z").workplane(invert=True)

if lbumps > 1 and wbumps > 1:
    tmp = (tmp.rarray(pitch, pitch, lbumps - 1, wbumps - 1, center=True).
        circle(postDiam / 2.0).circle(bumpDiam / 2.0).extrude(height - t))
elif lbumps > 1:
    tmp = (tmp.rarray(pitch, pitch, lbumps - 1, 1, center=True).
        circle(t).extrude(height - t))
elif wbumps > 1:
    tmp = (tmp.rarray(pitch, pitch, 1, wbumps - 1, center=True).
        circle(t).extrude(height - t))
else:
    tmp = s

31、盲文示例

在这里插入图片描述

from collections import namedtuple


# text_lines is a list of text lines.
# Braille (converted with braille-converter:
# https://github.com/jpaugh/braille-converter.git).
text_lines = ['⠠ ⠋ ⠗ ⠑ ⠑ ⠠ ⠉ ⠠ ⠁ ⠠ ⠙']
# See http://www.tiresias.org/research/reports/braille_cell.htm for examples
# of braille cell geometry.
horizontal_interdot = 2.5
vertical_interdot = 2.5
horizontal_intercell = 6
vertical_interline = 10
dot_height = 0.5
dot_diameter = 1.3

base_thickness = 1.5

# End of configuration.
BrailleCellGeometry = namedtuple('BrailleCellGeometry',
                                 ('horizontal_interdot',
                                  'vertical_interdot',
                                  'intercell',
                                  'interline',
                                  'dot_height',
                                  'dot_diameter'))


class Point(object):
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

    def __len__(self):
        return 2

    def __getitem__(self, index):
        return (self.x, self.y)[index]

    def __str__(self):
        return '({}, {})'.format(self.x, self.y)


def brailleToPoints(text, cell_geometry):
    # Unicode bit pattern (cf. https://en.wikipedia.org/wiki/Braille_Patterns).
    mask1 = 0b00000001
    mask2 = 0b00000010
    mask3 = 0b00000100
    mask4 = 0b00001000
    mask5 = 0b00010000
    mask6 = 0b00100000
    mask7 = 0b01000000
    mask8 = 0b10000000
    masks = (mask1, mask2, mask3, mask4, mask5, mask6, mask7, mask8)

    # Corresponding dot position
    w = cell_geometry.horizontal_interdot
    h = cell_geometry.vertical_interdot
    pos1 = Point(0, 2 * h)
    pos2 = Point(0, h)
    pos3 = Point(0, 0)
    pos4 = Point(w, 2 * h)
    pos5 = Point(w, h)
    pos6 = Point(w, 0)
    pos7 = Point(0, -h)
    pos8 = Point(w, -h)
    pos = (pos1, pos2, pos3, pos4, pos5, pos6, pos7, pos8)

    # Braille blank pattern (u'\u2800').
    blank = '⠀'
    points = []
    # Position of dot1 along the x-axis (horizontal).
    character_origin = 0
    for c in text:
        for m, p in zip(masks, pos):
            delta_to_blank = ord(c) - ord(blank)
            if (m & delta_to_blank):
                points.append(p + Point(character_origin, 0))
        character_origin += cell_geometry.intercell
    return points


def get_plate_height(text_lines, cell_geometry):
    # cell_geometry.vertical_interdot is also used as space between base
    # borders and characters.
    return (2 * cell_geometry.vertical_interdot +
            2 * cell_geometry.vertical_interdot +
            (len(text_lines) - 1) * cell_geometry.interline)


def get_plate_width(text_lines, cell_geometry):
    # cell_geometry.horizontal_interdot is also used as space between base
    # borders and characters.
    max_len = max([len(t) for t in text_lines])
    return (2 * cell_geometry.horizontal_interdot +
            cell_geometry.horizontal_interdot +
            (max_len - 1) * cell_geometry.intercell)


def get_cylinder_radius(cell_geometry):
    """Return the radius the cylinder should have
    The cylinder have the same radius as the half-sphere make the dots (the
    hidden and the shown part of the dots).
    The radius is such that the spherical cap with diameter
    cell_geometry.dot_diameter has a height of cell_geometry.dot_height.
    """
    h = cell_geometry.dot_height
    r = cell_geometry.dot_diameter / 2
    return (r ** 2 + h ** 2) / 2 / h


def get_base_plate_thickness(plate_thickness, cell_geometry):
    """Return the height on which the half spheres will sit"""
    return (plate_thickness +
            get_cylinder_radius(cell_geometry) -
            cell_geometry.dot_height)


def make_base(text_lines, cell_geometry, plate_thickness):
    base_width = get_plate_width(text_lines, cell_geometry)
    base_height = get_plate_height(text_lines, cell_geometry)
    base_thickness = get_base_plate_thickness(plate_thickness, cell_geometry)
    base = cq.Workplane('XY').box(base_width, base_height, base_thickness,
                                  centered=False)
    return base


def make_embossed_plate(text_lines, cell_geometry):
    """Make an embossed plate with dots as spherical caps
    Method:
        - make a thin plate on which sit cylinders
        - fillet the upper edge of the cylinders so to get pseudo half-spheres
        - make the union with a thicker plate so that only the sphere caps stay
          "visible".
    """
    base = make_base(text_lines, cell_geometry, base_thickness)

    dot_pos = []
    base_width = get_plate_width(text_lines, cell_geometry)
    base_height = get_plate_height(text_lines, cell_geometry)
    y = base_height - 3 * cell_geometry.vertical_interdot
    line_start_pos = Point(cell_geometry.horizontal_interdot, y)
    for text in text_lines:
        dots = brailleToPoints(text, cell_geometry)
        dots = [p + line_start_pos for p in dots]
        dot_pos += dots
        line_start_pos += Point(0, -cell_geometry.interline)

    r = get_cylinder_radius(cell_geometry)
    base = (base.faces('>Z').vertices('<XY').workplane()
        .pushPoints(dot_pos).circle(r)
        .extrude(r))
    # Make a fillet almost the same radius to get a pseudo spherical cap.
    base = (base.faces('>Z').edges()
        .fillet(r - 0.001))
    hidding_box = cq.Workplane('XY').box(
        base_width, base_height, base_thickness, centered=False)
    result = hidding_box.union(base)
    return result

_cell_geometry = BrailleCellGeometry(
    horizontal_interdot,
    vertical_interdot,
    horizontal_intercell,
    vertical_interline,
    dot_height,
    dot_diameter)

if base_thickness < get_cylinder_radius(_cell_geometry):
    raise ValueError('Base thickness should be at least {}'.format(dot_height))

result = make_embossed_plate(text_lines, _cell_geometry)

32、带各种连接孔的面板

在这里插入图片描述

# The dimensions of the model. These can be modified rather than changing the
# object's code directly.
width = 400
height = 500
thickness = 2

# Create a plate with two polygons cut through it
result = cq.Workplane("front").box(width, height, thickness)

h_sep = 60
for idx in range(4):
    result = result.workplane(offset=1, centerOption="CenterOfBoundBox").center(157, 210 - idx*h_sep).moveTo(-23.5, 0).circle(1.6).moveTo(23.5, 0).circle(1.6).moveTo(-17.038896, -5.7).threePointArc((-19.44306, -4.70416), (-20.438896, -2.3)).lineTo(-21.25, 2.3).threePointArc((-20.25416, 4.70416), (-17.85, 5.7)).lineTo(17.85, 5.7).threePointArc((20.25416, 4.70416), (21.25, 2.3)).lineTo(20.438896, -2.3).threePointArc((19.44306, -4.70416), (17.038896, -5.7)).close().cutThruAll()

for idx in range(4):
    result = result.workplane(offset=1, centerOption="CenterOfBoundBox").center(157, -30 - idx*h_sep).moveTo(-16.65, 0).circle(1.6).moveTo(16.65, 0).circle(1.6).moveTo(-10.1889, -5.7).threePointArc((-12.59306, -4.70416), (-13.5889, -2.3)).lineTo(-14.4, 2.3).threePointArc((-13.40416, 4.70416), (-11, 5.7)).lineTo(11, 5.7).threePointArc((13.40416, 4.70416), (14.4, 2.3)).lineTo(13.5889, -2.3).threePointArc((12.59306, -4.70416), (10.1889, -5.7)).close().cutThruAll()

h_sep4DB9 = 30
for idx in range(8):
    result = result.workplane(offset=1, centerOption="CenterOfBoundBox").center(91, 225 - idx*h_sep4DB9).moveTo(-12.5, 0).circle(1.6).moveTo(12.5, 0).circle(1.6).moveTo(-6.038896, -5.7).threePointArc((-8.44306, -4.70416), (-9.438896, -2.3)).lineTo(-10.25, 2.3).threePointArc((-9.25416, 4.70416), (-6.85, 5.7)).lineTo(6.85, 5.7).threePointArc((9.25416, 4.70416), (10.25, 2.3)).lineTo(9.438896, -2.3).threePointArc((8.44306, -4.70416), (6.038896, -5.7)).close().cutThruAll()

for idx in range(4):
    result = result.workplane(offset=1, centerOption="CenterOfBoundBox").center(25, 210 - idx*h_sep).moveTo(-23.5, 0).circle(1.6).moveTo(23.5, 0).circle(1.6).moveTo(-17.038896, -5.7).threePointArc((-19.44306, -4.70416), (-20.438896, -2.3)).lineTo(-21.25, 2.3).threePointArc((-20.25416, 4.70416), (-17.85, 5.7)).lineTo(17.85, 5.7).threePointArc((20.25416, 4.70416), (21.25, 2.3)).lineTo(20.438896, -2.3).threePointArc((19.44306, -4.70416), (17.038896, -5.7)).close().cutThruAll()

for idx in range(4):
    result = result.workplane(offset=1, centerOption="CenterOfBoundBox").center(25, -30 - idx*h_sep).moveTo(-16.65, 0).circle(1.6).moveTo(16.65, 0).circle(1.6).moveTo(-10.1889, -5.7).threePointArc((-12.59306, -4.70416), (-13.5889, -2.3)).lineTo(-14.4, 2.3).threePointArc((-13.40416, 4.70416), (-11, 5.7)).lineTo(11, 5.7).threePointArc((13.40416, 4.70416), (14.4, 2.3)).lineTo(13.5889, -2.3).threePointArc((12.59306, -4.70416), (10.1889, -5.7)).close().cutThruAll()

for idx in range(8):
    result = result.workplane(offset=1, centerOption="CenterOfBoundBox").center(-41, 225 - idx*h_sep4DB9).moveTo(-12.5, 0).circle(1.6).moveTo(12.5, 0).circle(1.6).moveTo(-6.038896, -5.7).threePointArc((-8.44306, -4.70416), (-9.438896, -2.3)).lineTo(-10.25, 2.3).threePointArc((-9.25416, 4.70416), (-6.85, 5.7)).lineTo(6.85, 5.7).threePointArc((9.25416, 4.70416), (10.25, 2.3)).lineTo(9.438896, -2.3).threePointArc((8.44306, -4.70416), (6.038896, -5.7)).close().cutThruAll()

for idx in range(4):
    result = result.workplane(offset=1, centerOption="CenterOfBoundBox").center(-107, 210 - idx*h_sep).moveTo(-23.5, 0).circle(1.6).moveTo(23.5, 0).circle(1.6).moveTo(-17.038896, -5.7).threePointArc((-19.44306, -4.70416), (-20.438896, -2.3)).lineTo(-21.25, 2.3).threePointArc((-20.25416, 4.70416), (-17.85, 5.7)).lineTo(17.85, 5.7).threePointArc((20.25416, 4.70416), (21.25, 2.3)).lineTo(20.438896, -2.3).threePointArc((19.44306, -4.70416), (17.038896, -5.7)).close().cutThruAll()

for idx in range(4):
    result = result.workplane(offset=1, centerOption="CenterOfBoundBox").center(-107, -30 - idx*h_sep).circle(14).rect(24.7487, 24.7487,  forConstruction=True).vertices().hole(3.2).cutThruAll()

for idx in range(8):
    result = result.workplane(offset=1, centerOption="CenterOfBoundBox").center(-173, 225 - idx*h_sep4DB9).moveTo(-12.5, 0).circle(1.6).moveTo(12.5, 0).circle(1.6).moveTo(-6.038896, -5.7).threePointArc((-8.44306, -4.70416), (-9.438896, -2.3)).lineTo(-10.25, 2.3).threePointArc((-9.25416, 4.70416), (-6.85, 5.7)).lineTo(6.85, 5.7).threePointArc((9.25416, 4.70416), (10.25, 2.3)).lineTo(9.438896, -2.3).threePointArc((8.44306, -4.70416), (6.038896, -5.7)).close().cutThruAll()

for idx in range(4):
    result = result.workplane(offset=1, centerOption="CenterOfBoundBox").center(-173, -30 - idx*h_sep).moveTo(-2.9176, -5.3).threePointArc((-6.05, 0), (-2.9176, 5.3)).lineTo(2.9176, 5.3).threePointArc((6.05, 0), (2.9176, -5.3)).close().cutThruAll()

33、摆线齿轮

可以使用 parametricCurve 定义复杂的几何图形。 本实例生成螺旋摆线齿轮。

在这里插入图片描述

import cadquery as cq
from math import sin, cos, pi, floor

# define the generating function
def hypocycloid(t, r1, r2):
    return ((r1-r2)*cos(t)+r2*cos(r1/r2*t-t), (r1-r2)*sin(t)+r2*sin(-(r1/r2*t-t)))

def epicycloid(t, r1, r2):
    return ((r1+r2)*cos(t)-r2*cos(r1/r2*t+t), (r1+r2)*sin(t)-r2*sin(r1/r2*t+t))

def gear(t, r1=4, r2=1):
    if (-1)**(1+floor(t/2/pi*(r1/r2))) < 0:
        return epicycloid(t, r1, r2)
    else:
        return hypocycloid(t, r1, r2)

# create the gear profile and extrude it
result = (cq.Workplane('XY').parametricCurve(lambda t: gear(t*2*pi, 6, 1))
    .twistExtrude(15, 90).faces('>Z').workplane().circle(2).cutThruAll())

原文链接:33个CadQuery建模示例 — BimAnt

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/104884.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

食品加工企业自营商城小程序开发,帮助企业增加销售渠道,提高销量

随着生活水平的不断提高&#xff0c;人们对于食品质量提出了更高的要求。传统人们购买食品时只能到超市或者市场进行食品采购&#xff0c;需要花费一定的时间和精力&#xff0c;而且经过多层中间商赚取差价的原因性价比也并不高。在移动电商的时代发展下&#xff0c;很多企业商…

『 canvas 动画』为了让老婆彻底理解正弦和余弦,我连夜制作了这个效果

前言 最近在做 canvas 相关的效果时&#xff0c;经常用到三角函数以及正/余弦相关的数字知识&#xff0c;这些知识点都是我们在初中的时候就学过的&#xff0c;但是这么多年基本已经忘的差不多了&#xff0c;刚好最近又学到了一个用 canvas 来实现的正/余弦动画效果&#xff0…

成功转行Python工程师,年薪30W+,经验总结都在这

这是给转行做Python的小白的参考&#xff0c;无论是从零开始&#xff0c;或者是转行的朋友来说&#xff0c;这都是值得一看的&#xff0c;也是可以作为一种借鉴吧。 而且我决定转行IT&#xff08;互联网&#xff09;行业&#xff0c;其实理由也很简单&#xff0c;不用动体力&a…

循环冗余编码(CRC编码)与海明码(考研前突击一下QAQ)

循环冗余编码&#xff08;CRC编码&#xff09;与海明码 一.环冗余编码 1.循环冗余编码的形成 生成多项式&#xff1a;G1011 表示成生成多项式为G(x)X3X1X^3X1X3X1 示例&#xff1a; 假设信息字节为&#xff1a;F1001010 选取生成多项式&#xff08;默认&#xff09;G1011 将…

2022年下半年部分团队的总结

这是 2021 年年底的汇报。 这是 2022 年上半年的汇报。 踏石留印 抓铁有痕 CSDN 是中国 IT 人士学习&#xff0c;成长&#xff0c;成功的平台。除了一些创新的探索之外&#xff0c; 20 多年来&#xff0c;CSDN 团队为这个平台开发和维护着各种基本功能和服务&#xff0c;还进…

自动化测试技术笔记(一):前期调研怎么做

昨天下午在家整理书架&#xff0c;把很多看完的书清理打包好&#xff0c;预约了公益捐赠机构上门回收。 整理的过程中无意翻出了几年前的工作记事本&#xff0c;里面记录了很多我刚开始做自动化和性能测试时的笔记。虽然站在现在的角度来看&#xff0c;那个时候无论是技术细节…

“ 这片绿茵从不缺乏天才,努力才是最终的入场券——梅西 ”

前言 想了又想还是忍不住想发布一篇文章来纪念一下2022年的卡塔尔世界杯&#xff0c;这伟大的诸神黄昏之战。4年一届的世界杯像是一把衡量时间的坐标&#xff0c;正所谓青春不过几届世界杯&#xff01;2014巴西世界杯在上初一&#xff0c;2018俄罗斯世界杯在上高二&#xff0c;…

如何成为一名合格的互联网大厂Python工程师?

Python开发工程师&#xff0c;是一个在IT行业圈子里一直都很热门的话题&#xff0c;无论是像腾讯、百度这样的大型公司&#xff0c;还是刚刚起步的初创公司&#xff0c;都会招python开发工程师。 python已成为越来越多开发者的开发语言选择&#xff0c; 而python开发工程师工资…

[附源码]计算机毕业设计Python架构的博客平台设计(程序+源码+LW文档)

该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程 项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等…

【Python计算几何】德劳内三角剖分算法 | scatter 绘制散点图 | Dealunay 函数

猛戳&#xff01;跟哥们一起玩蛇啊 &#x1f449; 《一起玩蛇》&#x1f40d; &#x1f4ad; 写在前面&#xff1a; 本章我们将介绍的是计算机和领域的 Delaunay 三角剖分算法&#xff08;即德劳内三角剖分&#xff09;&#xff0c;它是一种用于将点集划分成三角形网格的算法。…

如何同时启动Android平台GB28181设备接入模块和轻量级RTSP服务模块?

技术背景 在介绍GB28181设备接入模块和轻量级RTSP服务之前&#xff0c;我们需要先搞清楚&#xff0c;二者的使用场景和技术设计的差别&#xff1a; 首先是GB28181设备接入模块&#xff1a; 为什么要设计GB28181设备接入模块&#xff1f;GB28181接入SDK&#xff0c;实现不具备…

软件:分享六款实用的软件,每一款值得收藏

❤️作者主页&#xff1a;IT技术分享社区 ❤️作者简介&#xff1a;大家好,我是IT技术分享社区的博主&#xff0c;从事C#、Java开发九年&#xff0c;对数据库、C#、Java、前端、运维、电脑技巧等经验丰富。 ❤️个人荣誉&#xff1a; 数据库领域优质创作者&#x1f3c6;&#x…

[XCTF]funny_video(难度2)

目录 一、题目重述 二、解题思路 1.分解音视频 2.处理音频 总结 前言 视频夹杂着一段音频&#xff0c;怎么提取&#xff1f;遇到一款新的工具&#xff01;MKVToolNix 特此记录&#xff01; 一、题目重述 一段视频&#xff0c;观看之后发现有一段还夹杂着音频。 XCTF-fu…

避坑指南!Python里面的这九个坑,坑的就是你

Python里面有一些坑&#xff0c;让你防不胜防&#xff0c;菜鸟经常会弄晕&#xff0c;而学习多年的Python老鸟也会时不时中招。小编整理了9个坑&#xff0c;都是会经常碰到的坑&#xff0c;让你大呼我曾经也碰到过! 虽然是小的问题&#xff0c;但是在实际的项目中&#xff0c;哪…

测出让人血压升高的页面崩溃,我是如何排查的

前情回顾 前几天在一次web应用测试过程中&#xff0c;前端发起了向后端接口的查询请求&#xff0c;由于后端响应较慢&#xff0c;前端一直处于等待响应返回状态。在几分钟后&#xff0c;突然页面出现让人惊悚的“噢噢&#xff0c;页面崩溃了”几个大字。 看到这几个字的一瞬间…

用于销售、报告等的 LearnDash Group Management LMS分组管理插件

目录 获取强大、直观的LearnDash LMS组管理和报告 使用 LearnDash Groups LMS分组管理插件进行 B2B 销售 节省设置分组的时间或让客户自己构建和购买&#xff01; 获取强大、直观的LearnDash LMS组管理和报告 LearnDash分组是将学生组织成逻辑单元以进行报告和课程访问的绝…

java回顾:Maven高级

目录 一、私服搭建 二、Maven高级 2.1、依赖范围 2.2、依赖传递 2.3、依赖可选 2.4、依赖排除 2.5、依赖冲突 三、ssm工程改造成分层构建 3.1、maven的继承 3.2、继承的一些应用 3.3、maven的聚合&#xff08;多模块开发&#xff09; 一、私服搭建 https://blog.…

rust语句,表达式以及函数

语句和表达式 在rust里&#xff0c;语句和表达式的区别是非常重要的。语句没有返回值&#xff0c;表达式有返回值。例如&#xff1a; fn main() {let y {let x 3; // 赋值语句x 1 // 表达式};println!("The value of y is: {}", y); }上面使用一…

SQL | 自联接 Self Join

有时你可能需要获取位于同一个表中的相关数据。为此&#xff0c;你可以使用一种特殊的联接&#xff0c;称为自联接&#xff08;Self Join&#xff09;。在今天的文章中&#xff0c;我们将学习如何使用 Navicat Premium 作为数据库客户端编写包含自联接的查询。如果你没未使用过…

报表工具软件-FineReport JS实现下拉框自动展开

1. 概述 1.1 预期效果 在使用下拉框做筛选查询时&#xff0c;需要点击下拉框下拉三角才会展开所有选项&#xff0c;有些使用场景下&#xff0c;用户希望自动展开选项列表&#xff0c;尤其是在多个控件联动场景下。如下图所示&#xff1a; 地区控件选择地区后&#xff0c;销售…