NCF参数化建筑论坛

标题: 关于rhino编程的一些基础知识 [打印本页]

作者: zhouningyi1    时间: 2012-8-8 01:14
标题: 关于rhino编程的一些基础知识
本帖最后由 zhouningyi1 于 2012-8-8 03:16 编辑

在苏麒大哥的帖子下,最近也开始看下gh c#,不过基础知识欠缺,比如厚厚的Rhino.Common,貌似连构架的介绍也没有,导致经常用错,在grasshopper3d上翻到些帖子 还不错,在这里陆续添加些笔记,很零散,理解也可能不对 请大家纠正,也希望能抛砖引玉

http://www.grasshopper3d.com/forum/topics/baking-breps-w-color

This is correct. Rhino is the main Namespace in our SDK. There's other namespaces inside Rhino, for example Rhino.Geometry and Rhino.Collections. Every type in .NET is part of some namespace. Namespaces only have one raison d'être, which is to group types into logical chunks.

A Type is the definition of a class or a structure. Classes and structures are very similar entities (they can both contain any number of methods, properties and other types), but because they behave differently, you need to know which is which.

An Instance of a type is a single object that actually exists. For example, the class Human is the definition of what it means to be human. You are an instance of this class. I am a different instance of this class. Damien is yet another instance of this class. Every instance can assign unique values to all its properties and fields. If for example the type Human had a property for height, then in my case it would say 1.97m. In Damien's case it would be set to something much less, as Damien isn't anywhere near as handsome and tall as I am.

A Reference is a piece of information that tells you where a certain instance is. Think of a reference as an address. When you mail a letter (or e-mail), you must specify a valid and unambiguous address or the letter won't arrive. Similarly, every piece of data stored in the memory of your computer also has a unique address, but instead of "3670, Woodland Park Avenue, Seattle", it looks like this 0x12345678. Trying to access an instance through an invalid reference is like sending a letter without an address.

References are sometimes also called "variables", though sometimes the word variable is only used to indicate primitive types, such as Booleans, Integers and such. A reference is not the instance itself. Take the following code:

1. Dim crv As Rhino.Geometry.Curve
2. Dim dup As Rhino.Geometry.Curve
3. crv = GetACurveFromSomewhere()
4. dup = crv
5. If (dup IsNot Nothing) Then dup = dup.DuplicateCurve()

One lines (1) and (2) I declare two references, one is called "crv", the other "dup". Because Visual Basic is a strongly typed language, I can assign limitations to what sort of data crv and dup are allowed to reference. In this case they can only point to instances of the Rhino.Geometry.Curve class or any class which derives from Rhino.Geometry.Curve (such as Rhino.Geometry.NurbsCurve, or Rhino.Geometry.LineCurve).

On line (3) I assign an actual curve instance to the crv reference/variable. At least, assuming the GetACurveFromSomewhere() function actually returns a proper instance. If it doesn't, crv will remain a "null reference".

Line (4) is interesting, because both crv and dup will now point to the same curve instance. So even though there is only 1 curve in memory, both crv and dup provide access to it. This means that when we change the curve via crv, then dup will notice that change.

On line (5) two things happen. I want to duplicate my curve data so I can change the data via dup, without affecting the data available via crv. The best way to duplicate a curve (i.e. create a second curve in memory, that has the same shape as the first curve) is to use the DuplicateCurve() method on the Rhino.Geometry.Curve class. However I cannot call a method on an instance that doesn't exist, so before I do that, I need to check whether or not dup actually points to a real curve object, or whether it is a null reference.

Finally, it is also possible to have an instance of a class in memory, without any references to it. In this case nobody can reach that curve any more and it is essentially dead weight, taking up pointless memory. In C++ this is called a Memory Leak and it's considered a serious bug. In VB.NET and C# this memory will automatically be cleaned up by the .NET Garbage Collector. In my opinion the Garbage Collector is the single most important feature in .NET. It's what turns VB and C# from frustration central into a friendly and flexible coding platform.

作者: 肃画    时间: 2012-8-8 01:31
{:14:}~~~~~~~~~~~~~~~~~~~~~~~~~~~~·
作者: zhouningyi1    时间: 2012-8-8 02:48
关于curve

Rhino.Geometry.Curve is to be treated as an abstract class. There are lots of different kinds of curves but they are all derived from the Curve base class. NurbsCurve is only one of these.
The special thing about NurbsCurve is that it can represent every other type of curve to within maximum accuracy. Circles and Arcs can be converted to degree=2 nurbs curves with weighted control points. Lines and Polylines can be converted into degree=1 nurbs curves. Polycurves can be converted into arbitrary nurbs curves with multiple interior knots for kinks. This is why all curve types support conversion to Nurbs curves.
The benefit from the developer point of view is that when your algorithms work on nurbs curves, they can work on all curves. If you rely on control-points or spans, then you can always get those via the ToNurbsCurve() method.
作者: zhouningyi1    时间: 2012-8-8 02:50
关于Line并非Curve
Rhino.Geometry.Line is not a type of curve. As in; it doesn't derive from Rhino.Geometry.Curve. There is another type called LineCurve which does derive from Curve and which provides a wrapper around the Line structure.
Curve have a method called GetLength() which has several overloads. It allows you to both get the length of the whole curve, or a sub-curve
作者: zhouningyi1    时间: 2012-8-8 02:53
目前gh的sdk中并没有材质图层等种种属性

currently there are no colors, layers, linestyles or other attributes in the Grasshopper SDK
Reply by Giulio Piacentino on July 5, 2012 at 2:13am
作者: zhouningyi1    时间: 2012-8-8 02:58
目前的gh sdk并不全面
Reply by David Rutten on July 9, 2012 at 1:43am
It is possible to set all properties of the slider via the SDK. There are a lot of classes in Grasshopper that have not been included in the SDK Documentation. The entire Grasshopper.Kernel.Special namespace is missing.
作者: zhouningyi1    时间: 2012-8-8 03:02
目前犀牛尚不允许五边形以上的mesh

faces with more than four sides are usually called n-gons. If you were able to create a 5-sided mesh face in Rhino, there would be a good chance that you could do that in Python, too. But Rhino does not allow that at present. It might be added in the future due to user requests. Requests are welcome on the Rhino newsgroup: news://news.rhino3d.com/rhino
Right now, you can create Patches (trimmed surfaces, if there are only a few). Another workaround, maybe more suitable for many faces, could be to import all faces as polylines?
I hope this helps, at least a little.
作者: zhouningyi1    时间: 2012-8-8 03:09
可以将一些外部的类库导入犀牛(比如文中的CGAL),但前提是数据结构必须简单
It is possible to invoke methods in a C++ dll using C#. However this requires that all method calls only use very simple data types (booleans, integers, doubles, pointers or arrays of the above, not an exhaustive list). This is how RhinoCommon talks to the Rhino C++ SDK.
I haven't looked at CGAL code but it is quite likely that some sort of wrapper dll needs to be written in C++ that exposes the functionality via such simplified functions. This is both difficult and a lot of work.
Porting code over to C# may or may not be feasible depending on how CGAL was written. If it uses a lot of pointers, instances and references then it will be a cr*pload of work to port it correctly.
The problem with porting libraries like these is that functions -such as straight skeletons- often rely on many other parts of the library, so porting a small part of it is in fact impossible.
I don't fancy your chances in the short term. I think there's a lot of interest in providing a .NET version of CGAL but it doesn't seem like there's anything out there yet.
作者: zhouningyi1    时间: 2012-8-8 03:23
一个几何类型 例如line,在gh的datatree里,并不是line,而是以GH_Structure的形式存在的

The data inside the tree cannot be Line, because the type Line in RhinoCommon does not implement the IGH_Goo interface, which is a prerequisite of GH_Structure.
This is why there is a GH_Line class, which exposes the Line type while implementing the IGH_Goo interface. This is true for practically all data types in Grasshopper. Rhino.Geometry.Brep is wrapped up in GH_Brep. System.Double is wrapped up in GH_Number.
If you want to get at the actual data inside the wrapper classes, there's usually a Value property that provides getter/setter access to the real data stored inside the wrapper.
Dim edgeData As Data.GH_Structure(Of GH_Line) = Nothing
If (Not DA.GetDataTree(0, edgeData)) Then Return
Dim edge As Line = edgeData.Branches(0)(0).Value
Note that when you retrieve IGH_Goo type data from input parameters you get the original data. This data may be shared amongst many parameters and therefore you should not change this data. Unfortunately there is no constness in .NET so I cannot enforce this limitation without copying data and I want to copy data as little as possible due to overhead.
Incidentally, if you want to make sure that there are no exceptions thrown in the code, you should probably add more tests:
Dim edgeData As GH_Structure(Of GH_Line) = Nothing
If (Not DA.GetDataTree(0, edgeData)) Then Return
If (edgeData Is Nothing) Then Return
If (edgeData.PathCount = 0) Then Return
Dim edgeList As List(Of GH_Line) = edgeData.Branch(0)
If (edgeList Is Nothing) Then Return
If (edgeList.Count = 0) Then Return
Dim edgeWrap As GH_Line = edgeList(0)
If (edgeWrap Is Nothing) Then Return
Dim edge As Line = edgeWrap.Value
As you can see, working with GH_Structures will involve a lot of bookkeeping and validation.
作者: zhouningyi1    时间: 2012-8-8 03:30
初学者建议:
Well it was difficult for me in the beginning too! Still is to be honest... So here is my advice.

First I'd like to point that it's much easier to learn if you have a specific project. It's true for learning GH as well as scripting. In my case my first shot was a grandstand script, which requires a simple iteration. So try to pick something where you know what the result should be, and keep it simple! Grandstand is good ;)
.
You really need to have clear ideas. So if you want to start from the very beginning script something you already did in GH, then write a pseudo-code ie write the script in plain english (in french in my case!) draw diagrams and sketches...
.
Second, forget open nurbs and go here to the RhinoCommon SDK reference site. Its much more simple. That is if you want to stick with VB. I don't know Python at all but I was told it's even simpler.
Btw "functions" are called Methods.  They apply to Objects and they need Arguments - that's what's within brackets. Got it?   Object.method(arg1,arg2)
.
Third, don't bother with data trees, its difficult and not very useful in most cases. Usually you can manage with the access type in the inputs menu (item, list, tree) and basic GH post processing if you really need to. But remember, keep it simple in the beginning!
.
And fourth, there are plenty of examples on this forum, and lots of people willing to help, so use the search feild and post questions (with precise titles plz!!)
Good luck! you'll spend a few nights over it for sure :))
作者: wangjunxiong    时间: 2012-8-8 08:02
貌似您说的是VB,而不是c#,呵呵呵。
作者: paul丶wu    时间: 2012-8-8 10:01
感谢分享。。。。。
作者: panhao1    时间: 2012-8-8 11:11
rhino common没必要背吧  其它软件无法调用它
作者: zhouningyi1    时间: 2012-8-8 15:18
犀牛是用c++写得 而gh是vb.net和c#写得 c#和c++不一样 不能互相自动转译

C is an old language. It was developed in the early 1970's and it is quite primitive. Bjarne Stroustrup (among others) extended C with the notion of OOP and it became 'C with classes' or 'C plus plus'. C++ arose in the early 80's and it is the language in which Rhino itself is written. C# is the next major version in this language family and it is the one used in .NET development. C# first appeared somewhere around 2001 and has gone through 4 major upgrades since then.
Grasshopper is written in C# and VB.NET (which is the .NET flavour of the Visual Basic language family) and the script components also allow only C# and VB.NET, none of the other c-style or vb-style languages out there.
There is no way to flawlessly convert code from C++ to C#. The two languages have non-overlapping features. Simple mathematical algorithms though tend to be highly portable.

作者: zhouningyi1    时间: 2012-8-8 16:50
经常有个数据类型叫IEnumerable(Of T),搞的不是很清楚,求高手解释下 不过 在c#里 可以用list替代

IEnumerable(Of T) is an interface which indicates that whoever implements it represents a collection of objects that can be iterated over. List(Of T) already implements this interface, as do almost all collection based types in the .NET framework. I.e. when a function wants an IEnumerable(Of Point3d), you can feed it List(Of Point3d) or a Point3d array and it will all work.
作者: zhouningyi1    时间: 2012-8-8 17:43
gh中 tree的结构:

A Tree is stored as two synchronized lists. The first one is a sorted list of all the paths, the second is a matching list of List(Of T), where T is the type of the Tree. So when you retrieve tree1.Branch(0), all you get is a single list filled with items that are of type T, with no path information whatsoever. The {0;3;0} now comes from the internal data matching logic.
But each of these branches has a path of {0;3;0}
That doesn't seem right to me either... Is there something I'm missing?
These branches do no have a path of {0;3;0}. They don't have a path at all, they are just List(Of T) instances. The {0;3;0} is only assigned at the very last moment, when RunScript returns and Grasshopper figures out that you've assigning a list to A. Since the input is marked as Tree Access, it simply picks the first path it comes across.
If you want to have control over the data structure of your outputs, you must output DataTree(Of T) instances, and not just the branches of a DataTree.
作者: angel120317    时间: 2012-8-8 18:10
感谢分享。。。。。
作者: zhouningyi1    时间: 2012-8-8 18:12
gh几乎就没多少几何函数 都在rhino.common里

Don't look in Grasshopper for geometric functionality. That's all RhinoCommon as Aaron pointed out. Grasshopper is 75% graphic interface and 24% solution accounting.
作者: zhouningyi1    时间: 2012-8-8 18:17
class(类)和struct(结构)的一些区别
the Interval type in RhinoCommon is a struct (Value Type), not a class (Reference Type). What this means is that when you ask a Curve for it's domain, you get a copy of the actual interval. Changing this copy doesn't accomplish anything and therefore the compiler won't let you do it.
作者: zhouningyi1    时间: 2012-8-8 18:29
不能trim surface 但可以trim brep
Surfaces in Rhino do not support trims. You'll always need to use Breps, and in case of surfaces just use breps with a single face.
作者: zhouningyi1    时间: 2012-8-9 02:04
本帖最后由 zhouningyi1 于 2012-8-9 11:15 编辑

关于List Arraylist Array三者之间的差别

ArrayList是使用大小可按需动态增加的数组实现列表。

Array类提供创建、操作、搜索和排序数组的方法,因而在公共语言运行库中用作所有数组的基类。里面的方法都是static,引用的时候Array.方法名,这些方法提供了针对数组的一些列操作(不论数组的类型是int还是string还是其他)。它不能通过new Array()的方式实例化。

所以ArrayList转换为Array后就不能改变大小了,这和数组的性质是一致的。为什么性质都是数组,还要转来转呢?原因在于ArrayList和Array数组,存的数据类型都是object,所以提供的方法也是针对object,对于特定类型的特定操作,没有涉及。转换成string[]字符串数组中,就可以用到很多有用的方法了,比如翻转,大小写转换了。


作者: zhouningyi1    时间: 2012-8-9 14:15
找了一篇关于list arraylist区别的文章
http://blog.csdn.net/gobiy/article/details/2759013

List是一个接口,而ListArray是一个类;
ListArray继承并实现了List;
所以List不能被构造,但可以向上面那样为List创建一个引用,而ListArray就可以被构造。
List list;     //正确   list=null;
List list=new List();    //   是错误的用法

List list = new ArrayList();这句创建了一个ArrayList的对象后把上溯到了List。此时它是一个List对象了,有些ArrayList有但是List没有的属性和方法,它就不能再用了。
而ArrayList list=new ArrayList();创建一对象则保留了ArrayList的所有属性。
这是一个例子:
import java.util.*;

public class TestList{
public static void main(String[] args){
List list = new ArrayList();
ArrayList arrayList = new ArrayList();

list.trimToSize(); //错误,没有该方法。
arrayList.trimToSize();   //ArrayList里有该方法。
}
}

编译一下就知道结果了。

如果这个样子:
List a=new ArrayList();
则a拥有List与ArrayList的所有属性和方法,不会减少
如果List与ArrayList中有相同的属性(如int i),有相同的方法(如void f()),
则a.i是调用了List中的i
a.f()是调用了ArrayList中的f();
--------------------------------------------------------------- ---------------------------------------------------------------

问题的关键是:
为什么要用 List list = new ArrayList() ,而不用 ArrayList alist = new ArrayList()呢?
问题就在于List有多个实现类,现在你用的是ArrayList,也许哪一天你需要换成其它的实现类,如 LinkedList或者Vector等等,这时你只要改变这一行就行了:
List list = new LinkedList(); 其它使用了list地方的代码根本不需要改动。
假设你开始用 ArrayList alist = new ArrayList(), 这下你有的改了,特别是如果你使用了 ArrayList特有的方法和属性。


地区用 List arr = new ArrayList();定义;行业用 ArrayListarr = new ArrayList();定义;则说明,行业里用到了ArrayList的特殊的方法.

另外的例子就是,在类的方法中,如下声明:
private void doMyAction(List list){}
这样这个方法能处理所有实现了List接口的类,一定程度上实现了泛型函数.

如果开发的时候觉得ArrayList,HashMap的性能不能满足你的需要,可以通过实现List,Map(或者Collection)来定制你的自定义
作者: zhouningyi1    时间: 2012-8-10 12:08
Rhino.common中 几何体类型 有些是结构,有些是类,找了一篇文章中关于结构和类的区别:http://blog.csdn.net/aspnet2002web/article/details/6084149
简单的说成class可以被实例化,属于引用类型struct属于值类型,
1)、类型,空间分配。结构是值类型,是分配在内存的栈上的.类时引用类型,,是分配在内存的堆上的。结构实例化可以不用new,即使用new操作也不会在堆里分配内存。作参数是按值传递,类时引用传递,变量用完自动解除内存分配,类需要垃圾回收期
2)、基类。结构继承自System.ValueType类,因此不具多态性。但是注意,System.ValueType是个引用类型。类继承自System.Object类;
3)、职能。struct常用于存储数据;而class表现为行为
4)、结构没有类的特性,不支持继承。但可以实现接口。
5)、结构无法声明无参的构造函数,但可以声明有参的构造函数
6)、结构的实例成员不能直接赋初值,必须通过构造函数来赋值,但静态成员可以直接赋初值
7)、无抽象结构,但有抽象类(abstract)
8)、class 可以声明protected成员、virtual成员、sealed成员和override成员;而struct不可以,但是值得注意的是,struct 可以重载System.Object的3个虚方法,Equals()、ToString()和GetHashTable()。





欢迎光临 NCF参数化建筑论坛 (http://ncf-china.com/) Powered by Discuz! X3.2