硬核分享:一套云操作,让Dynamo成为变形金刚

你好,这里是BIMBOX。

我们的老朋友,建筑学和计算机双修的小神仙@VCTCN93又来BOX分享了。

当我问到他这次打算聊点啥,VCTCN93说,100%原创首发,聊一个很多人还不知道的事,可能有点超前,但他相信代表了未来的工作方式:给Dynamo搭一个服务器,让它成为真正的变形金刚

下面的文章,代码部分你可以照着实操一下,绝对可以验证;如果你从来没写过Python、甚至没用过Dynamo,也完全可以跳过代码部分,看这套方法背后的思想,还能给给涨点谈资。

Let’s rock it.

 
版本繁多的Pytnon  

 

很多人不知道,Python 有很多不同的版本,比如 CPython、 Jython、 RPython 与 IronPython 等等。
一般大家口中所说的 Python,默认代指的是标准版CPython,基于C语言实现,能够兼容诸多 CAPI。
CAPI是什么你不需要知道,只需要知道这些 CAPI 几乎无所不能,运行速度极快,于是大神们便通过它们,为 CPython 创造了一个又一个牛逼哄哄的武器:第三方库,这些武器能够把 Python 武装起来,最终让 Python 成了编程世界中一个无比强大的存在。
如果你去看大神们写的Python代码,会经常看到它们经常以这样的语句开头:

from pyecharts.charts import Bar

或者是这样的语句:

import plotly.express as px

这里的 import 某某,就是在召唤某个强大的第三方库进入python,你可以把它理解为一个别人写好的插件,不需要知道它的工作原理,只要载进来,就能帮你做到很多厉害的事。
比如,使用第三方库 pandas_profiling ,你只需要一行代码,就能做出一份完整的数据报表。

import pandas as pd

import pandas_profiling

#前两行是导入,命令就下面一行

df = pd.read_csv(‘churn.csv’)

可以说,没有第三方库的 Python,就像失去了武器的武者,要他干活,就像要他肉身搏坦克。
 
先天残疾的 IronPython  

 

前面我们说的是标准版 CPython,遗憾的是,Windows平台下的很多设计软件,比如我们熟知的 Grasshopper 与 Dynamo,它们内置的 Python 都是 IronPython
IronPython 虽然也有 Python 之名,但其底层是基于 .NET 平台实现的,与基于 C语言 的 原生Python 有天壤之别。它从一出生就注定了无法使用大神们创造的强大第三方武器。
从某种意义上来说,与 CPython 相比,IronPython 就是个只能用肉身搏坦克的先天残疾。
想要让手上的 Python 发出最大的威力,使用那些属于 Python 的利器,你就需要绕过 IronPython 的封锁,奔向 CPython 的自由世界。
 
MVP与云计算  

想在 Dynamo 中直接装 CPython?这是不现实的,不然就不会有 IronPython 这样折衷的存在了。
没关系,此路不通,换个思路。
我曾在教程「Dynamo 场地有限元分析」课程中提到过 MVP(Model-View-Present) 模式,简单来说就是,让计算与显示互不干涉、完全分离,把参数发给计算者,计算者返回你结果。
用大白话来解释就是:你不需要管我是怎么计算的,你给我数据,我给你结果就行了。
举个最简单的例子,你日常浏览网页就是一个这样的过程。
你在浏览器中输入了一串网页地址,按下回车,浏览器就把包含了参数的 URL 地址发给了网站的服务器,服务器再经过海量的计算,把计算的结果返回给你,这就形成了你日常看到的网页。
有些 URL 不仅是一个网站的地址,还包括一定的运算规则。
比如你在搜索引擎中搜索 「ArchiPython」,浏览器中的那一条 URL 中,就蕴含了大量需要完成本次搜索的参数,服务器计算了你提供的这些参数之后,才把所有本次运算的结果 ,也就是「含有ArchiPython的条目」返回给你。
想要摆脱 IronPython 的束缚,使用 CPython?我们大可以模仿这种方式。
没错,我就是要你在 Dynamo 中,像访问网页一样使用 Cpython。
我们的思路是,搭建一个使用 CPython 的本地服务器,接收 Dynamo 发来的含有参数的 URL,服务器计算出结果,再把计算的结果发回 Dynamo。
整个过程,其实是完全不用 Dynamo 中的电池做任何计算,而是让 Dynamo 成为一个纯显示端的存在。
云负责计算有所数据,本地负责显示所有结果,这也就是云计算的基本思想。
高能预警:下面开始出现代码,没有基础的小白同学可以跳着看看热闹。日后用到的时候,再回来看源代码做参考。

 

搭建服务器  

 

前面我们说到了CPython 强大的第三方库,接下来要干的活儿自然也少不了它的帮忙。
你只需要几行代码,就能使用 flask 库,在 CPython 中搭建本地服务器:
  1. from flask import Flask
  2.  
__author__ = ‘Vctcn93’
__publisher__ = ‘ArchiPython’

 

  1.  
  2.  
  3. app = Flast(__name__)
  4.  
  5.  
  6. if __name__ == '__main__':
  7. app.run()
诺,服务器就这么简单的搭好了,运行这个文件,你就开启了服务器。

图中Running on http://后边是一串服务器的地址
你可以在这个服务器中实现一些功能,比如测试是否成功链接:
  1. from flask import Flask
  2.  

__author__ = ‘Vctcn93’

__publisher__ = ‘ArchiPython’


 

  1.  
  2.  
  3. app = Flask(__name__)
  4.  
  5.  
  6. @app.route('/connect')
  7. def connect():
  8. return '连接成功!'
  9.  
  10.  
  11. if __name__ == '__main__':
  12. app.run()
通过设置的 connect 函数,如果连接成功,网页上就会显示出 连接成功 四个字。

值得注意的是,服务器只能返回字符串 (string),如果你想将计算结果用于 Dynamo 中,还需要对服务器返回的数据进行加工,以确保其类型的正确。
你也可以让服务器根据输入的参数,来计算出结果。
在脚本中添加一个 add 函数,让他求参数 a 参数 b 的和:
总结说来,一条满足服务器计算的 URL,需要满足如下公式:

与服务器只能返回字符串的特性一样,你通过请求(request)得到的参数也全是字符。
恭喜你,你现在已经成功突破了 Dynamo 的封锁!
基于以上代码,你就可以在这个 CPython 环境的服务器下,使用各种 Python 强大武器了,比如大名鼎鼎的 Numpy,pandas 等等。
在 Dynamo 中像在浏览器里一般发送接请求,就可以获得使用 CPython 计算的结果了。

 

在 Dynamo 中发请求  
 
由于 Dynamo 中的 Python 是 IronPython,所以它发送请求的方式是使用 .NET 的库,与 CPython 有非常大的不同,我们需要把发送和接受转化成 CPython 的方式,下面直接送上 DynamoPythonScript 中实现的代码:(代码中带有#的灰色行是代码说明
  1. # 启用 Python 支持和加载 DesignScript 库
  2. import clr
  3. clr.AddReference('ProtoGeometry')
  4. from Autodesk.DesignScript.Geometry import *
  5.  
  6. # 该节点的输入内容将存储为 IN 变量中的一个列表。
  7. dataEnteringNode = IN
  8.  
  9. # 将代码放在该行下面
  10. # IronPython 库的环境变量,一般在这个位置
  11. import sys
  12. sys.path.append('C:/Program Files (x86)/IronPython 2.7/Lib')
  13. from System.Net import WebRequest
  14. from System.IO import StreamReader
  15. from System.Text import Encoding
  16.  

__author__ = ‘Vctcn93’

__publisher__ = ‘ArchiPython’


 

  1.  
  2. # 服务器地址
  3. url = r'http://127.0.0.1:5000/'
  4.  
  5. # 可在在此处对 URL 进行编辑,使其支持参数
  6.  
  7. # 发送请求
  8. request = WebRequest.Create(url)
  9.  
  10. # 获取计算的结果
  11. response = request.GetResponse()
  12. result = StreamReader(response.GetResponseStream()).ReadToEnd()
  13.  
  14.  
  15. # 将输出内容指定给 OUT 变量。
  16. OUT = result
开启服务器后,你只需要对那个 URL 做一定的修改,Dynamo 就能发送请求,收到结果了。

 

实操案例  
 

下面我们来试试具体能做些什么,抛砖引玉,欢迎大家迸发新的灵感。

在 CPython 中有一个几何库,称为 shapely它功能强大,运算速度极快,是目前 Python 世界中非常流行的几何库之一

绕开了 IronPython 的封锁后,你就可以通过服务器,使用 shapely 做相关的几何运算。运算速度一般比 Dynamo 自带电池快 1000 倍以上。

我们来设计一个函数,通过一条多段线(polyline)与精度(density),返回一个均分的点矩阵(matrix),写成代码如下:
  1. def create_grid(polyline: List[list], deisty: float): -> List(list)
  2. pass
根据这个要求,你就可以开始搭建自己的服务器了,功能代码如下:
  1. import numpy as np
  2. from flask import Flask, request
  3. from shapely.geometry import Polygon, Point

 

__author__ = ‘Vctcn93’

__publisher__ = ‘ArchiPython’

 

  1. app = Flask(__name__)
  2.  
  3.  
  4. @app.route('/connect')
  5. def connect():
  6. return '连接成功!'
  7.  
  8.  
  9. @app.route('/add')
  10. def add():
  11. # 拿到 URL 中的参数
  12. a = request.args.get('a')
  13. b = request.args.get('b')
  14.  
  15. # 将他们还原成数字
  16. a, b = eval(a), eval(b)
  17.  
  18. # 计算
  19. result = a + b
  20.  
  21. # 只能返回字符串
  22. return str(result)
  23.  
  24.  
  25. @app.route('/create_grid')
  26. def create_grid():
  27. # 获得polyline参数
  28. polyline = request.args.get('polyline')
  29. print(polyline)
  30.  
  31. # 获得density
  32. density = request.args.get('density')
  33.  
  34. # 还原他们的类型
  35. polyline, density = eval(polyline), eval(density)
  36.  
  37. # 获得图形信息
  38. polygon = Polygon(polyline)
  39. bbox = polygon.bounds
  40. start_coords = bbox[:-2]
  41. width = bbox[2] - bbox[0]
  42. height = bbox[3] - bbox[1]
  43. round_x = round(width / density)
  44. round_y = round(height / density)
  45.  
  46. # 定义基本矢量
  47. vector_right = np.array([density, 0])
  48. vector_up = np.array([0, density])
  49. vector_point_start = np.array(start_coords)
  50.  
  51. # 获得原始点矩阵
  52. matrix = list()
  53.  
  54. for x in range(round_x):
  55. for y in range(round_y):
  56. vector_point = vector_point_start + vector_right * x + vector_up * y
  57. point = Point(vector_point)
  58.  
  59. # 同时做判断,如果点在范围内
  60. if polygon.contains(point):
  61. matrix.append(point)
  62.  
  63. # 将结果输出为字符
  64. result = [
  65. list(p.coords)[0] for p in matrix
  66. ]
  67.  
  68. return str(result)
  69.  
  70.  
  71. if __name__ == '__main__':
  72. app.run()
Console 中运行这个脚本,你就可以在浏览器中输入参数来测试结果:

输入一个 polyline,其几何为 [[0,0],[100,0],[100,100],[0,100]], density 为 10,求出其结果。

接下来,使用 Dynamo 发送这次请求,并获得服务器返回的结果:
  1. # 启用 Python 支持和加载 DesignScript 库

  1. import clr
  2. clr.AddReference('ProtoGeometry')
  3. from Autodesk.DesignScript.Geometry import *
  4.  
  5. # 该节点的输入内容将存储为 IN 变量中的一个列表。
  6. dataEnteringNode = IN
  7.  
  8. # 将代码放在该行下面
  9. # IronPython 库的环境变量,一般在这个位置
  10. import sys
  11. sys.path.append('C:/Program Files (x86)/IronPython 2.7/Lib')
  12. from System.Net import WebRequest
  13. from System.IO import StreamReader
  14. from System.Text import Encoding

__author__ = ‘Vctcn93’

__publisher__ = ‘ArchiPython’


 

  1.  
  2. # 服务器地址
  3. url = http://127.0.0.1:5000/
  4. url += 'creaet_grid?'
  5. url += 'polyline=[[0,0],[100,0],[100,100],[0,100]]&'
  6. url += 'density=10'
  7.  
  8. # 发送请求
  9. request = WebRequest.Create(url)
  10.  
  11. # 获取计算的结果
  12. response = request.GetResponse()
  13. result = StreamReader(response.GetResponseStream()).ReadToEnd()
  14.  
  15. # 将结果处理为一个个的点:
  16. points = [Point.ByCoordinates(*coords) for coords in eval(result)]
  17.  
  18. # 将输出内容指定给 OUT 变量。
  19. OUT = points

到这一步,我们就真正实现了 0 节点运算,仅靠服务器本身完成复杂的功能,Dynamo 在整个链条中,仅仅起到了显示的作用。

 
再复杂一点  

 

你也可以使用 Dynamo 中PolylineNumberSlider 来完成这项计算:
在 Revit 中绘制一条红线。
将红线导入 Dynamo 中,设置 number slider,让 Density 参数可调。
➤ 修改部分代码,让链接地址随参数变化而变化。
➤ 此时,你便会得到一个响应速度极快的、使用 CPython 实时计算的点矩阵。

 

意义  

 

最后给你总结一下这套思路的核心意义。
从表面上来看,这只是一个通过搭建服务器,跳出 Dynamo 自带的 IronPython,实现使用原生 Python 牛哄哄功能的方法。这对于纯建筑人员来说或许有些许难度,而对于程序员而言,或许并不是很厉害的功能。
但是,这篇分享的意义,远不止搭建个服务器这么简单。
VCTCN93 认为,「本地客户端只负责显示,运算交给云端」,这极有可能是未来几年越来越普及的工作方式。
在这个案例之中,在传统工作流中起到计算作用的 Dynamo,完全成为了显示结果的存在,所有的计算,都在服务器上完成了。
这次的分享仅仅只是引入了少量矢量库,未来有可能会引入计算机神经引擎,而正如我们前面所说的,Dynamo 也好,Revit 也好,目前都是不支持这些尖儿货的。
如果我们能在任意软件使用自己开发的功能,又何须要被软件本身的功能和API锁死自己的生产力呢?
软件如果能做,那就用软件做;软件如果不能做,那么我就只把它当做显示工具,整个系统都可能会被时代抛弃掉。
往大点的方向说,5G时代将要来临了,人类数据传输的效率又将进入一个新的台阶,云计算一定会成为未来的主流。
建筑师只需要把设计参数发送给云端,云端就能返回给你算好的结果,企业对于软件功能和硬件性能的升级,也只对应着云端服务器,能大量节省本地的资源。
今天只是 Dynamo 成了我们的显示端,但其实我可以用任何东西作为我的显示端。
如果一个工程师说「这件事我做不了,因为软件没有这个功能」,他就是被软件功能锁死了。软件本身应该为工程师的自身业务服务,而不是由工程师去迁就软件功能划出的地牢。
和很多建筑圈的计算机大牛一样,VCTCN93 曾经不止一次的在多个场合呼吁,不要局限在软件层面,更不要被任何软件锁死的原因。
因为把别人造好的轮子玩得滚瓜烂熟,远不如自己掌握核心科技。
至少,不要被科技吓到。
很多人会说,工程师是做设计、做施工的,凭啥去学 Dynamo、学Python?每个人当然有权不学,我们希望的是,至少人们知道自己脚下的边界在哪里,边界之外,还有多广阔的天地。
今天你至少收获了一个谈资:下次别人再告诉你学 Dynamo 要把 Python 玩儿溜,你可以反问一句:你说的是 CPython 还是 IronPython ? IronPython 可不够用啊!
关于云计算是怎么回事,它的发展和未来,我们在《精读10本好书中的20项新科技》这门音频课程里专门有一节讲到了它,特地拿出来给你设置成免费收听,感兴趣的话可以听听看。
作为BIMBOX小伙伴里的建筑+计算机双修撑场专员,再次向你诚意推荐 VCTCN93 的《Dynamo可视化脚本思维课》,能帮你打开一片为所欲为的新天地。
另外,VCTCN93 和BOX合作的 Dynamo+Python 工程师自我提升课程,也在积极筹备中,各位小伙伴有哪方面的实际需求,也欢迎给我们留言,帮助我们打造一套有价值的好教程。
有态度,有深度,BIMBOX,咱们下次见!

 

暂无评论

相关推荐

微信扫一扫

微信扫一扫

微信扫一扫,分享到朋友圈

硬核分享:一套云操作,让Dynamo成为变形金刚