关于类型转换的问题

我在编写插件的过程中,发现了一个问题

我只是在代码中,将x值赋值给了a,但是在犀牛中却进行了类型的转换


在Python编译好的代码中,我重新定义了输出端的类型
但是他还是没有输出Referenced Brep这种类型结构
如果输入端和输出端同为ID的话,则可以通过Brep电池转换成功
但是我想在编译好的源码上修改某些数据来达到这个效果,各位有什么好的办法吗


这个是Guid的转换

@NARUTO @Jorin
月神和Jorin老师,这位在mcneel的帖子如下

我总结一下,C#的话直接注册brep为输入,brep为输出,做出来的gha电池可以输入reference 输出也reference
他试图用python电池原地编译ghpy实现,也尝试注册输入输出,但是发现出来的电池,输入reference,无法输出reference

该问题涉及到我的知识盲区 :face_with_peeking_eye:故建议他在中文区论坛发帖。

@Deer @Niko
这个我也没注意过,如果想和GH电池输入输出一样,我还是建议用C#写gha,会省心不少。

再说把ghpython电池编译成ghpy格式。你可以看看Giulio的教程: Tutorial: creating a Grasshopper component with the Python GHPY compiler。我记得他帖子中有个和写gha一样的格式,可以设置输入输出类型。

也许可以实现和C#写gha一样的效果,我没深入研究过。

@Deer 他这个问题和类型转换无关,这个需求也是个伪需求。原因如下:

Referenced Brep 的意思是,这个 Brep 是 Rhino 当前所操作的文档(Rhino.RhinoDoc.ActiveDoc)中的 Brep,Referenced XXX 只有一个作用——把 Rhino 里画好的几何体拿到 GH 里来处理。如果物件是从 Rhino 里抓的,并且没有进行 Internalise data 的操作,就一定是 Referenced,用 GH 里任何一个电池处理完以后,新生成的几何体 一定就存放在 ghdoc 里面了,已经不存在于 RhinoDoc 里面了,就不可能再是 Referenced 了。

如下图所示,这个 Referenced Brep 的 ID 和它在 Rhino 文档中的 ID 是完全一样的,因为它只存在于当前 Rhino 文档中。把它接到 python script 以后,即便没做任何操作,它已经复制到 ghdoc 里面了,已经有新的 ID 了,就不可能再是 Referenced 了:

如果通过某种“奇技淫巧”,任然让它是 Referenced Brep,那这个电池的功能也和左侧第一个电池 BREP 的功能完全一样,没有任何意义。

这样就可以让它仍然是 Referenced Brep ,但是就像前面说的,没有任何的意义,就图一乐呵。

2 个赞

我把mcneel回复他的整理一下在这里
这个问题我当时看到帖子时研究了一下
自带的电池和C#+VS其实都是用AddPointParameter这样的函数,如下图是我自己的某个vs文件
image
而这样的函数会直接调用GH_Point类
下面的链接是GH_Point类
https://developer.rhino3d.com/api/grasshopper/html/T_Grasshopper_Kernel_Types_GH_Point.htm


这些类我看了一下,其实类本身都包含了对Guid的兼容处理
也就是说给Reference它内部就会保留这个信息,并且输出的也是Reference
最后达成的效果就是
GH所有自带的电池,例如楼主mcneel发帖的sort point,给了4个reference point,排序完毕的还是reference point
其实是他自己的GH_Point class内部就有记录Guid(如果他是来自Rhino)
同时VS+C#开发的gha只要遵循David提供的模板,使用AddPointParameter之类的方式注册变量,就能成功给将输入的点注调用GH_Point类,做到和GH自带电池一样的效果。

楼主的需求就是让自己的python编译的ghpy也可以做到这一点。
月月给的那个Giulio的参考链接其实楼主之前也照做了,我看了一下楼主写的没问题
就很奇怪最后楼主还是没有实现这个功能。

其实楼主本来的代码也是按照Giulio的模板的

image
我自己试了一下,确认了注册输入和输出都是Param_Point()
直接原地输出a=x
完事了还是不行

GH 里的 Python Script 和 C# Script 电池,只要以几何的方式接到 x ,就已经在 ghdoc 里复制了一份了,print 一下 x 的 id 就知道了,和 rhino 里面的 id 都不一样。要通过这两个 Script 电池拿到 referenced data,可以把 input 类型设置为 Rhino 的 guid,然后就可以拿到了。

接进去就已经不是一个东西了。

如果真的有这个需求,就用我上面提供的方法,用原始的 guid 去拿最简单了。

这个确实是楼主现在的解决方案,就是直接Guid搞起
经过几次实验我发现了问题所在。先不考虑python的问题的话


这是测试结果


这是两个Mesh的代码
可以看到注册输入的函数都是AddMeshParameter
但是接受这个函数的类,一个是普通的Mesh,另一个是GH_Mesh (隶属于Kernal.Types而并不是Kernal.Parameters)
前者Mesh只接受几何信息,后者就如我之前提到的是包含Guid兼容的处理的。
所以刚才第一个截图的上输入端无法输出Reference,因为Guid在经过Mesh这个类的时候就丢掉了
而下一个输入端可以输出Reference,因为他是被GH_Mesh类接受的,这个类是会记录下来物体的Guid(如果来自Rhino)

楼主测试的SortPoint电池,用的接收器就是GH_Point而不是Point,他会在该保留reference的时候保留。
如果是Deconstruct Point之类的,他就不会用GH_Point接受,而是普通的Point。因为他操作的事情就是将点分解,而不是将点排序。这两者的不同应该是David设计的时候考虑进去的。
所有涉及到list和tree的操作,应该都是使用带GH_前缀的类型传输数据,内部可以保留reference信息

1 个赞

是的呀,所以要去实例化一个 Grasshopper.Kernel.Types.GH_XXXX 的对象。

是的,然而python这个样例的架构和C#不同

C#的AddMeshParameter是用Parameters.Param_Mesh类
而下面获取输入的时候实例化一个Types.GH_Mesh然后直接接受就行,他会在内部做好Cast


整个过程干净利索

python就怎么都搞不定
image
首先是接受变量一定要Param类型,而不能是GH_类型,因为只有Param类才能有Access和name等等
然后按照C#的逻辑,直接强制给他搞成GH_就行了
我试了如下2个办法,没报错但是也没成功
1:
obj = self,marshal.GetInput(DA, 0)
p0 = Grasshopper.Kernal.Types.GH_Mesh()
p0.CastFrom(obj) # 也不知道这个CastFrom是不是这么用
self.marshal.SetOutpul(p0, DA, 0, True)

2:
obj = self,marshal.GetInput(DA, 0)
p0 = Grasshopper.Kernal.Types.GH_Mesh(obj ) # 直接构造
self.marshal.SetOutpul(p0, DA, 0, True)


我输入端试着用ID,结果已经是可以的了
主要的问题就是输入端是ID

输入类型是ID当然可以了
我们后面讨论的问题就是如何不输入ID也能继承

不引入 Guid 做不到,虽然这个东西可以 RegisterInputParams,但它已经被封装成 ExecutingComponent 了,和我们在 VisualStudio 中开发插件时继承的 GH_Component 类有很大的区别,GH_Component 可以直接把前一个电池传过来的 GH_Point 那进来用,而这里不行,根源在于 ghPython 编译的 ExecutingComponent 获取参数使用了下面这个操作:

obj = self.marshal.GetInput(DA,0)

GetInput 方法会根据 Param_XXX 的不同去自动确定 Type hint,就和我们从这里选是一模一样的:

拿进来类型就已经是 Point3d 了,已经不包含 Rhino 中点实例的 Guid 信息了。

所以如果一定要输出 Referenced Data 的话,还是推荐直接用 Guid 去重新实例化一个 GH_Point,没有任何影响。

个人观点: 都已经用输入端接数据进来了,还要原样输出为 Referenced 毫无必要,毫无意义,纯属娱乐

2 个赞

原来python架构差异那么大
现在全搞清楚了
楼主可以放弃了。。。。老老实实用Guid吧

其实楼主的想法也很正常,就好比GH自带电池,list item这种,都是会继承Reference的
之所以GH那么设计应该也是考虑用户会需要将来的Refence ID

就以楼主当时mcneel发帖的那个例子为例,sort point的话,排序完毕的点还继承reference。可能后续他还需要和rhino互动
另外看他那帖子的意思,是除了sort point还要做其他操作,一连串代码以后再去拿着这个Guid干啥啥的。

楼主只是想着C#和原生电池能做到的继承Reference, GHpy也想要做到。。。现在看来是没戏了

楼主不妨还是将你这个需求明确一下,为啥非要保留Reference。到底是强迫症呢,还是真的有具体需求。
我说的后续给Rhino用也只是猜测,真实情况就是你到底要Reference干啥呢?不说清楚的话,不免会让人感觉到无厘头 :crazy_face:

这个要求我也觉得没必要,但是这个需求不是我提出的,解决办法我之前也已经说明了,但是客户(相当于)这边比较倔强非得要引用的物件才和他之前习惯的相匹配;秉承着客户至上的原则,所以我还是想用一些折中的办法去完成这个需求,但是目前Python确实和C#有很多区别

你的客户应该也没有强求你用python吧
用C#就没这个问题了