ZenCad 3D脚本模拟系统

我想提请您注意的工作是尝试再次编写脚本化3D建模系统。 写我想见她的样子。


ZenCad系统的配方非常简单。 对OpenScad的3D建模进行脚本化的概念,OpenCascade的几何核心,将python3作为胶水,用于主动缓存计算的惰性计算库evalcache。 加入其他一些乐器的香料,加PyQt调味料调味,然后搅拌,但不要摇晃。


machine.png


脚本CAD系统


CAD或根据我们的CAD,是一种计算机辅助设计系统。 与交互式3D编辑器不同,脚本化CAD系统在其创建者通常理解软件的意义上解释“自动化”一词。 也就是说,它不是作为一组计算工具,而是作为一种透明的算法,仅在创建时才需要人工干预。


使用脚本化CAD,我们不会在屏幕上直接绘制模型,而是根据生成模型的方式构建程序。 对于仅熟悉交互式CAD的人们,此方法可以描述为绝对参数建模。 严格来说,脚本通常用于补充交互式环境,以编写其他工具,但是在使用范式清晰的脚本化CAD中工作,需要对工作流进行不同的组织,一种思维方式,并且设计用于稍有不同的任务范围。


目前最著名,最纯正的脚本设计CAD是OpenScad。


最初是OpenScad


有些人喜欢便捷的Compass,SolidWorks,FreeCad,平凡而朴实的OpenScad。 要回答他成功的秘诀是不容易的,但是您可以肯定地说它轻巧,使用灵活,设置最少。 上面写的部分模型易于重用。


但是,openscad有一些烦人的缺陷:


  • openscad仅适用于网状网络。
  • openscad具有相当低的可伸缩性限制,在大型模型上开始严重落后。
  • openscad很难与其他系统集成,其原因是使用自己的语言。

不幸的是,尽管脚本方法具有所有强大的功能,但要超出用功利性刷写OpenScad编写简单模型的范围仍然存在很多问题。


语言和所有所有


我想在这里解决的第一件事是采用通用语言作为战斗工具。 使用通用语言可以使您充分利用其语法功能以及先前编写的库的组合来解决3D建模问题。


ZenCad和OpenScad GUI的比较

ZenCad界面:
zencad.png


OpenScad界面:
openscad.png


与OpenScad相比,使用Python使模型代码更透明,从而简化了opencad代码。


示例:CSG
#!/usr/bin/env python #coding: utf-8 from zencad import * lazy.diag = True c1 = 100 c2 = 130 c3 = c2/2 + 20 base = box(c1,c1,c1,center=True) f1 = ngon(r = 35, n = 3) f2 = ngon(r = 35, n = 5) f3 = circle(35) s1 = linear_extrude(f1, c2, center=True) s2 = linear_extrude(f2, c2, center=True).rotateY(deg(90)) s3 = linear_extrude(f3, c2, center=True).rotateX(deg(90)) #          3 . m1 = base - s1 - s2 - s3 m2 = base ^ s1 ^ s2 ^ s3 m3 = s1 + s2 + s3 ystep = 240 xstep = 240 fontpath = os.path.join(zencad.moduledir, "examples/fonts/testfont.ttf") #    .      . t1 = textshape("difference", fontpath, 40) t1c = t1.center() t1=t1.translate(-t1c.x, -t1c.y, 0).rotateZ(deg(45)) t2 = textshape("intersect", fontpath, 40) t2c = t2.center() t2=t2.translate(-t2c.x, -t2c.y, 0).rotateZ(deg(45)) t3 = textshape("union", fontpath, 40) t3c = t3.center() t3=t3.translate(-t3c.x, -t3c.y, 0).rotateZ(deg(45)) #  ,  . disp(base.forw(ystep)) disp(s1) disp(s2.left(xstep)) disp(s3.right(xstep)) disp(m1.back(ystep)) disp(m2.left(xstep).back(ystep)) disp(m3.right(xstep).back(ystep)) disp(t1.back(ystep).up(c3), Color(1,1,0)) disp(t2.left(xstep).back(ystep).up(c3), Color(1,1,0)) disp(t3.right(xstep).back(ystep).up(c3), Color(1,1,0)) disp(s1.left(xstep).back(ystep), Color(0.5,0,0,0.95)) disp(s2.left(xstep).back(ystep), Color(0.5,0,0,0.95)) disp(s3.left(xstep).back(ystep), Color(0.5,0,0,0.95)) disp(s1.back(ystep), Color(0.5,0,0,0.95)) disp(s2.back(ystep), Color(0.5,0,0,0.95)) disp(s3.back(ystep), Color(0.5,0,0,0.95)) show() 

boolean.png


例如,使用生成器的语法过滤点云非常方便。


示例:过滤点数组。
 #!/usr/bin/env python3 from zencad import * #  . ng = ngon(r = 10, n = 6) #      . vertices = ng.vertices() filtered_vertices = [v for v in vertices if vx < 0] #      . m = ng.fillet(4, filtered_vertices) disp(m) show() 

恩贡


由于python在现代软件生态系统中非正式地占据了胶水之王的称号,因此zencad可以轻松地与其他库和软件系统集成。 我们可以在一个脚本中使用sympy来生成分析表面,使用numpy来处理在该表面上生成的点云,当然,还可以使用zencad进行构建,可视化和后处理。


示例:简单的逐点曲面构造
 from zencad import * import numpy xcoords = numpy.linspace(-10,10,50) ycoords = numpy.linspace(-10,15,50) lines = [ interpolate([point(x, y, 0.01*(x**2 + y**3)) for x in xcoords]) for y in ycoords ] wires = [] for l in lines: trans = translate(0,0,-30) sf = l.endpoints() w=sew([l, segment(sf[0], trans(sf[0])), trans(l), segment(sf[1], trans(sf[1]))]) wires.append(w) for l in lines: disp(l.left(30)) disp(loft(wires) - halfspace().down(10)) show() 

chair.png


OpenCascade的坚实基础


多边形网格的数学比边界表示的数学简单得多,但是边界表示的实用性更高。 尤其是,多边形网格具有组合爆炸问题,尤其是在需要渲染模型时,就会表现出来。 在OpenScad中,通常有必要开发一种分辨率远低于真实模型分辨率的产品,这违反了范式的纯度。


因此,第二点实现是使用成熟的几何核,该核使用边界表示而不是网格模型。 当然,ZenCad围绕OpenCascade的黑客几何核心构建,并不是要在python环境中提供其完整功能。 尝试完全传达OpenCascade将会导致编写第二个pythonOCC。 ZenCad占据榜首,试图在功能和人体工程学之间保持平衡。


示例:在ZenCad中播放的OpenCascade软件瓶
 #!/usr/bin/env python3 #coding: utf-8 from zencad import * import zencad.surface as surface import zencad.curve2 as curve2 lazy.diag=True height = 70 width = 50 thickness = 30 # BASE pnt1 = point(-width/2,0,0); pnt2 = point(-width/2,-thickness/4,0); pnt3 = point(0,-thickness/2,0); pnt4 = point(width/2,-thickness/4,0); pnt5 = point(width/2,0,0); edge1 = segment(pnt1, pnt2) edge2 = circle_arc(pnt2, pnt3, pnt4) edge3 = segment(pnt4, pnt5) wire = sew([edge1, edge2, edge3]) profile = sew([wire, wire.mirrorX()]) body = profile.fill().extrude(height) body = fillet(body, thickness/12) hl(body.forw(140)) # NECK neck_radius = thickness/4.; neck_height = height/10; neck = cylinder(r=neck_radius, h=neck_height).up(height) body = body + neck hl(body.forw(100)) # THICK body = thicksolid(body, -thickness / 50, [point(0,0,height+height/10)]) hl(body.forw(60)) # THREAD ( 2       .) cylsurf1 = surface.cylinder(neck_radius * 0.99) cylsurf2 = surface.cylinder(neck_radius * 1.05) major = 2 * math.pi; minor = neck_height / 10; angle = math.atan2(neck_height / 4, 2 * math.pi) ellipse1 = curve2.ellipse(major, minor).rotate(angle) arc1 = cylsurf1.map(curve2.trimmed_curve2(ellipse1, 0, math.pi)) segment1 = cylsurf1.map(curve2.segment(ellipse1.value(0), ellipse1.value(math.pi))) ellipse2 = curve2.ellipse(major, minor/4).rotate(angle) arc2 = cylsurf2.map(curve2.trimmed_curve2(ellipse2, 0, math.pi)) segment2 = cylsurf2.map(curve2.segment(ellipse2.value(0), ellipse2.value(math.pi))) m1 = sew([arc1, segment1]) m2 = sew([arc2, segment2]) thread = loft([m1, m2]).up(height + neck_height / 2) hl(m1.up(height + neck_height / 2).right(80)) hl(m2.up(height + neck_height / 2).right(60)) hl(thread.right(40)) # FINAL m = thread + body display(m) show() 

bottle.png


传统的连续性。 源于一切


zencad语法解决方案以他的哥哥和OpenScad老师为例,最大程度地减少了库中的实体数量。 与OpenScad一样,尽管OpenCascade允许这样做,但ZenCad从根本上无法在点(x,y,z)上创建基本体。 ZenCad首先在原点创建一个图元,然后使用转换设置它所需的位置。 ZenCad中的转换既作为单独的对象又作为实体的方法存在。


 #  . cube(40, center=True).rotateX(deg(45)).rotateZ(deg(45)).right(20) #  . (right(20) * rotateZ(deg(45)) * rotateX(deg(45)))(cube(40, center=True)) #  . trans = right(20) * rotateZ(deg(45)) * rotateX(deg(45)) cube(40, center=True).transform(trans) 

一组转换是标准的,包括平移,旋转,反射和缩放。


懒惰


为了最大程度地减少计算时间,ZenCad中的数学运算被简化,并且所有计算都被积极地缓存。 我之前在Habrahabr的页面上谈论过的del区块链evalcache库负责管理简化算法: 懒惰计算树的磁盘缓存 。 Zencad将计算结果保存在公共缓存中,可以通过可视化器界面监视其状态。 与显着冗余一起使用的sha512哈希算法消除了惰性对象的哈希键冲突的可能性(哈希空间是宇宙中原子数的10 ^ 74倍)。


创建此模型时,它会生成4兆字节的几何图形,并且在第一遍过程中可以计算很长时间:


bolt.png


使用螺纹表面在计算上是昂贵的:


logo.png


反射拓扑的问题。 近点法


OpenScad没有倒角或舍入操作。 OpenCascade提供了它们。 这些是非常重要的操作,如果不将其用于ZenCad,将是可耻的。 还有其他一些操作需要指定拓扑对象,例如,在OpenCascade瓶示例中获取薄壁模型的操作。 在图形CAD系统中,我们用鼠标指示一个拓扑对象(边缘,面,顶点)。 在编写脚本时,我们没有这样的机会。 本机OpenCascade通过反射解决了该问题,并将其用于图形CAD。 尽管ZenCad支持模型反射,但将其用作主要工具仍存在许多明显的缺点。 首先,使用这些工具所需的知识水平急剧增加,因为您至少必须了解内部拓扑概念。 其次,一旦出现在脚本中,惰性算法的和谐就会立即中断,并且模型代码也相当复杂。 在漫长的反思和实验过程中,我决定采用近点法。 简而言之,当执行依赖于拓扑的操作时,程序会绕过对象,并从进入人体的对象中找到最接近给定点的拓扑对象。 此项被视为已选中。 这样的解决方案在计算上更加昂贵,但是由于缓存,它的性能很好。 此方法用于依赖于拓扑元素的所有操作。


如上所述,如上例所示(示例:过滤点数组),也保留了常识反映模型的可能性。


标记Q和标记W


由于比例尺不清晰,因此很难从屏幕上读取模型的尺寸。 标记可以部分解决此问题。 具有直观的界面(无处更直观),标记发出信号并显示距离,从而简化了几何形状的分析以及对倒角/倒圆等操作的点的选择。


标记


跟踪源更新


像老大哥(OpenScad)一样,ZenCad能够在修改源文件时更新生成的模型。 与缓存系统结合使用,您可以非常方便地修改脚本,几乎实时地看到产品的变化状态。


动画制作


zencad的优点还不止于此。


ZenCad(由于采用了快速开放的核心级联)可以实时重绘场景,从而可以对3D模型进行动画处理。 动画是通过普通的python函数实现的,可让您自由自在地对待自己。 假设我们处于python环境中,那么zencad能够将来自外部源的数据可视化为模型移动(例如,使用多线程+ tcpsocket)。 因此,zencad可以用于例如机器人产品的半自然测试。 哦,凉亭! 嗨,罗斯! 也很高兴在观众见到你。 顺便说一下,正在开发一个运动学库,它将大大简化机器人操纵器的运动学链。


目前,动画仍处于半实验版本(尤其是在摄像机控制方面),因此我将不对其进行详细介绍。


出口-进口


当前,支持以brep格式导出和导入,这允许与freecad集成并以stl格式导出,从而可以生成用于3D打印的模型。 也支持屏幕截图生成。 包括自动。 特别是,在线手册中的屏幕截图是由ZenCad自动生成的。


现况


目前,ZenCad尚远未完成,但是在已准备就绪的部分中,它已经可以完全运行。


该库可在pypy中用于与python3.5,python3.6,python3.7版本兼容的Debian兼容轴


(由于PyQt5中的插件存在一些问题,您可能需要安装qt5-default)


 python3 -m pip install zencad apt install qt5-default 

从命令行运行gui:


 python3 -m zencad 

从python脚本运行gui:


 #!/usr/bin/env python3 import zencad m = zencad.cube(20) zencad.disp(m) zencad.show() 

不幸的是,系统的进度没有我们想要的那么快。 二维几何的大多数api和与曲面一起使用的api尚未实现,支持导出和导入标准格式,错误处理并不总是透明的,自动测试尚未制定出来,用于构造螺纹接头和齿轮产品的库已经被构想并尚未实现。 作为一个完全不正常的外部编辑,突然变得铁杆!!! Sublime Text ...我也真的很想完善系统,使其可以在Windows下运行(这需要大量的专家情报工作)。


但是,现在zencad允许您设计非常复杂的3D模型,创建3D打印模型,甚至可视化机械机构的运动学。


项目链接


github的: https : //github.com/mirmik/zencad,https : //github.com/mirmik/servoce


pypi: https ://pypi.org/project/zencad/,https://pypi.org/project/pyservoce/


手动


谢谢您的关注。


Source: https://habr.com/ru/post/zh-CN443140/


All Articles