哈哈哈哈再见才怪!!!小编我怎么可能这么水一篇??
一年过去了,小编不可能还只有SQLite数据库操作这点冷饭的嘛。作为老牌的结构设计软件应该不会是只有SQLite接口吧?经过一番研究,小编即将带初探PKPM二次开发的终极大杀器——“PDB-IO”。
目前PKPM的最新版本为PKPM V5.2,不过PDB-IO其实从V3.2版本就开放了,近几年来也更新了不少东西。另外,PKPM在近年来做产品重构时,研发部门内部也是使用这一套PDB-IO做数据接口的,这可谓是把内部资料放出来了啊,其开放的数据甚至可以从中提取有限元计算刚度矩阵组装前的所有数据,包括每个有限单元的各类属性,这可比一个简单的SQLite数据表要强大多了。
下面的配图来自PDB-IO官方开发范例:
但这一看熟悉的#include就明白了,这PDB-IO是一个C++的接口啊!我们要怎么才能把它在Rhino+Grasshopper里用起来呢?Grasshopper可是没有C++电池的,这怎么才能帮助我们快速二次开发/数据可视化?
这就需要在Python/C#环境中调用C++了。小编在这里只简单地介绍一下如何在Rhino+Grasshopper环境中使用C#调用PDB-IO,关于Python如何调用C++,网上也有很多资料,使用原生的ctypes包就可以调用c++的动态链接库是比较方便的方法,有兴趣的读者也可以自己去尝试,但总体思路是一样的。
首先需要说明的一点是,PDB-IO是一个实现对PKPM建模计算的中间数据库文件(也就是.PDB文件)进行读写操作的一套API,其主要的组成部分是一套C++的动态链接库(.dll文件),虽然也是DLL文件,但这套dll文件并非遵循.NET框架,故无法直接像我们之前用SQLite数据库那样直接可以通过在Grasshopper电池上右键点击“Manage Assembly”来进行导入,这里需要用到的是“dllimport”来对每一个函数进行重定义。
实现这个操作需要的参数有下面几个
导入的C++动态链接库文件位置(DLL文件位置)
导入的C++函数名称
确定由C++输入/输出变量到C#中所对应的类型
下面我们由如何实现“打开PDB文件”函数代码来依次讲解如何做到:
[DllImport(@"D:PDB-IORuntimeDLLsx64pdb_Common_Interface_X64.dll",
EntryPoint = "COMMON_OPEN_FILE_CODE",
CharSet = CharSet.Ansi)]
static extern void OpenFile(string code,
string fileName,
int type,
ref int iFileHandler,
ref int iSuccess);
dllimport后面接的路径为PDB-IO的C++动态链接库文件路径,后面的EntryPoint表明需要调用的dll里的方法名称,下面有extern修饰的函数定义行即确定C++/C#对应的变量类型。
这里我们可以发现,与直接Manage Assembly嵌入之后使用using直接引用的原生C#支持的DLL文件不同,这里我们的每个子函数都需要声明dllimport并且标明该函数对应的在C++动态链接库中的函数名称。
也就是说,using可以直接一次导入大批量的类和函数,但dllimport只能一个一个导入,每一个导入的函数都得声明其在C++库中原来的名字。这个”原来的名字”就可以直接打开PDB-IO中的“pdb_Common_Interface.h”中查找其定义,比如刚刚上面的一个“打开PDB文件”函数在“pdb_Common_Interface.h”中的原名是由下面代码定义的:
DLL_PDB void __stdcall COMMON_OPEN_FILE_CODE(
char * code,
char * pdbfilename,
int opentype,
int & iPDBFile,
int & iok);
EntryPoint后的参数就为这个C++的函数名,也就是COMMON_OPEN_FILE_CODE。
在确定dllimport之后,我们就需要将这个C++函数装载为C#函数。
这里直接放出这两个函数的对比图,可以看到char*直接替换成string,int仍然是int,但C++中的int &为引用类型,在C#中需要使用ref int来装载。
至此,在Grasshopper的C#电池中插入这段代码之后就可以成功打开PDB文件了!需要注意的是,dllimport这段代码需要放在C#电池的最下方,且dllimport需要在顶部加入引用“using System.Runtime.InteropServices;”才可以使用。
序列号SN_CODE可以向PKPM官方客服申请,在PDB-IO的说明文档中也有咨询电话。
可以看到C#电池的颜色为白色的,证明该电池成功运行了代码,没有报错。但是这似乎没有输出?因为现在只是打开了一个pdb文件,并没有对其中的数据有任何读取,于是,让我们找找看PDB-IO中哪个函数可以用来读取数据库中的信息,作为一个例子c#sqlite,为了保持与之前的模型一致,这里就使用节点坐标来举例把。
我们首先需要从“pdb_Common_Interface.h”中找到节点坐标数组的操作API,发现其数据出入口为“COMMON_COORDINATES_IO”,其定义为
DLL_PDB void __stdcall COMMON_COORDINATES_IO(
int kkk1,
double * xi1,
double * yi1,
double * zi1,
int numnp,
int & iok);
通过代码注释说明可以知道:
在这里,有一点C++知识的读者会知道double*是一个指针,可以用来表示一个double类型的数组。所以在C#中,我们的载入函数就应写为
[DllImport(@"D:PDB-IORuntimeDLLsx64pdb_Common_Interfaced_X64.dll",
EntryPoint = "COMMON_COORDINATES_IO",
CharSet = CharSet.Ansi)]
public static extern void PointCoordinates(
int kkk1,
double[] x,
double[] y,
double[] z,
int totalNumberOfPoints,
ref int iSuccess);
将这段完整代码再放到Grasshopper中
可以看到,已经可以成功输出各个节点坐标值了,而且我们也发现pdb文件内部是以米作为坐标单位的。
然后就是我们熟悉的操作了,接上生成点的GH电池试试看:
找到获取构件的接口,试着把所有结构梁都用单线做出来:
这样,我们就实现了在Grasshopper中读取模型信息了!
此刻,某同事高呼——就这??SQLite它不香吗?又是C++又是dllimport的,直接原生System.Data.SQLite加上数据库操作也能获取这些信息,简单又方便!
但,SQLite数据库只是模型定义数据,对于计算结果那可是爱莫能助,而PDB-IO则能够读取计算结果数据。比如说梁的挠度信息在PDB-IO就有相应的数据接口可以直接获取(COMMON_BEAM_DFL_IO)c#sqlite,直接将梁挠度显示在Rhino中那也是轻而易举:
这密密麻麻的数字是在明示我们挑选一层出来看俯视图:
再加上一些色彩特效,我们甚至可以看到梁中挠度的分布云图(把挠度数字显示先关掉)
这以后做PPT结构也不能输给建筑了!换一层,再来点实体特效,或者换个颜色梯度,想要什么效果来什么效果。这个我可是太拿手了,Grasshopper特效玩一年。
有些地方的梁的缺失是因为只提取了梁的结果,剪力墙的结果并没有提取和显示,所以模型中空缺的地方就是剪力墙部分了。
在文章的最后,再来个全楼模型的梁挠度与原模型在PKPM里的对比做本文结尾,完美诠释什么叫做花里胡哨,相信读者肯定有更好的审美能把这个模型做得更好看:
今天的PKPM二次开发就介绍到这里,欢迎大家加群讨论更多的可能性。这次是真的再见啦!
请添加我们“大菲儿”微信,
加入讨论交流群。
往期精彩回顾
限时特惠:本站每日持续更新海量展厅资源,一年会员只需29.9元,全站资源免费下载
站长微信:zhanting688