Bentley OpenBuildings
GenerativeComponents CONNECT Ed.
GC脚本介绍
课程概述
GenerativeComponents(以下简称GC)为我们提供了很多创建几何图形的节点工具,通过现有的节点工具,我们可以实现很多的技术。但有时我们可能需要与GC对话或者互动,以满足一些特定的需求,而现有的节点可能并不满足这些需求。例如,我们想放置由数学公式驱动的点,或者按照要求的顺序创建对象,甚至自动的实现需要重复的任务。
GC脚本教程 - 图1
为了达到这样的需求,我们使用了GC脚本编程。我们可以将GC脚本看作是一种可以与GC交互从而实现我们需求的语言。在本文文档中,我们将学习如何使用GC脚本来实现特定的需求。
本文档通过一些练习向学生介绍GC脚本。这些练习会逐步的向我们展示GC脚本的功能,完成这些练习之后,我们将对GC脚本有一个很好的理解,并将其功能应用到自己的项目中去。
学习目标:

  • 了解GC脚本的基本概念;
  • 使用FunctionCall节点创建一个GC脚本函数;
  • 使用ByFunction方法写GC脚本在一个几何节点上创建几何图形;
  • 使用GC脚本中的列表(lists)、嵌套列表(nested list)方法;
  • 编写一个查询表达式;

    1 GC脚本

    GC脚本是一种C风格的编程语言,像C、C++、Java和C#等都可以在GC中很好的使用。
    GC脚本是一种现代的、健壮的编程语言,它提供了类型安全、条件语句、重复语句、块语句、函数和子函数、对象和方法、通过引用传递的参数、一组丰富的表达式操作符,以及其他很多丰富的功能。
    此外,GC脚本也有自己独特的方面,包括自动复制—在任何需要单个数值的地方使用列表或者嵌套列表的能力。
    GC脚本连接了GC模型中的所有特性(Feature)。GC脚本包括以下几个不同的形式:

  • 节点属性—每当你填写一个属性的值,该值就是一个GC脚本的表达式,它可以按照需求写的很简单或者很复杂;

  • FunctionCall节点和节点的ByFunction方法 — 我们所创建的所有GC脚本函数都是写在其中的;
  • 脚本事务(Script Transactions)—在一个事务文件中,一个脚本事务允许我们输入任意数目的GC脚本语句,当该事务执行时,这些语句会被依次执行;
  • 脚本文件 — 脚本文件是一个文本文件,其中包含了一个完整的GC脚本程序。我们可以在任何时候手动的运行这个程序,或者在任何其他GC脚本代码中自动的运行它;

在本部分中,我们将学习GC脚本的重要基本概念。 在基本的概念完成之后,我们将利用GC脚本创建所需的几何图形。

练习01:脚本控制台和变量

  1. 当我们开始学习GC脚本的时候,我们将使用脚本控制台作为一个“沙箱”来验证代码或者检查代码的正确性。
  1. 打开GC软件,创建一个新的工作集,新建一个名为GC脚本的文件;
  2. 如图所示,点击Model工具栏下的Console按钮打开控制台界面;

GC脚本教程 - 图2
接下来的内容我们会学习如何使用控制台。
变量
变量很像一个容器,里边存放了一些值。我们可以进一步指定变量可以保存的值类型,比如整数(如6、7)或者字符(如a、B、C)。 让我们在控制台创建第一个变量。

  1. 将光标放在控制台底部的输入框里,输入

Int A = 3;
A 是变量的名字;
GC脚本教程 - 图3Int 是变量A的类型;它表示变量A只能存储3、4、5这样的整型数值。而不能保存3.5这样的浮点型数值。
; 表示一行或者语句的结束。它的功能很像英语中的full stop(.);在GC脚本中,每一句写完之后都必须加上分号(;)。

  1. 写完每个语句之后按Enter结束;

GC脚本教程 - 图4恭喜!!!你已经成功的写下了第一行GC脚本。
让我们添加更多的变量…

  1. 在控制台对话框中键入:

Int B =3 ;
Int C;
语句int C;表示声明了一个暂时不应包括任何值的空变量;
GC脚本教程 - 图5一旦我们声明了变量,我们就可以对它做进一个不同的操作。让我们和来看几个例子。

  1. 在控制台对话框中键入:

C = A + B;
责怪语句中 C = A + B;意思是把B的值和A的值相加,然后将得到的值赋给C。

  1. GC脚本教程 - 图6我们可以通过在控制台键入Print(C)来查看C的值。

请注意控制台返回的值是6.
在第四行表达式使用变量C之前,变量C就已经在第三行中声明了。如果之前没有声明变量,我们就不能使用它们。

  1. GC脚本教程 - 图7在控制台对话框中键入:

D = A + B;
我们得到一条错误信息因为变量D之前没有声明。但是,我们可以在需要的时候动态的声明一个变量。

  1. 在控制台对话框中键入:

GC脚本教程 - 图8Int D = A + B;
Print(D);
请注意这次控制台返回的值是6.在这里变量D的声明和初始化在表达式的同一行完成了。
如果你希望清空控制柜台中的内容,请点击对话框右下角的红色叉号。

  1. 清空控制柜台。

GC脚本教程 - 图9到目前为止,我们必须明确的是为变量赋值是一个特定的方式,即A = 3;或者A = C+ D;而不是3 = A 或者 C + D = A。这是因为等号“=”的作用是将右边的值赋给左边的变量。
如果我们写了 3 = A,GC脚本会把这条语句解释为A的值赋给3,这是没有任何意义的。同样的,GC脚本也会误解C + D = A这样的语句。
我们还应该明确,等号操作符右边的类型必须和左边的类型保持一致。
另一个常用的语句是A = A + 1;

  1. GC脚本教程 - 图10在控制台对话框中键入:

Int A = 3;
A = A + 1;
Print(A);
我们如果按照上边的从右往左的读取逻辑,这意味着将1加到之前赋的值A(3)上,然后将结果赋给A,所以A的值变成了4。变量的值可以根据需要重写很多次,每次新值都会取代之前的值。
另一种写A = A +1的形式是A++,代表A的值会每次加1.

  1. GC脚本教程 - 图11在控制台对话框中键入:

A++;
Print(A);

  1. 点击右下角的红叉清空控制台。

到目前为止,我们只看过整形的变量,当然我们也有其他类型的变量。一些常用的变量如下所示:
Double — 这种类型可以保存浮点(实数)值。通常保存带小数点的数字。
Number –- 这种类型可以同时保存int 和double类型的值。
String —- 这种类型可以保存零个或者多个文本字符的序列。字符串必须保存在单引号或者双引号中。
Bool —- 这种类型保存布尔类型的值true或者false。
Var —- 这种类型可以保存任何类型的值。

  1. GC脚本教程 - 图12在控制台对话框中键入:

Int A = 3;
Double B = 4.5;
Number C = A + B;
String D = ‘GC is cool’;
Print(C);
类型var有助于变量的快速声明。例如,如果我们需要一个int类型变量、一个double类型变量和一个string类型变量;我们可以直接在一行中声明所有变量,而不用为每个变量单独写一行。

  1. GC脚本教程 - 图13在控制台对话框中键入:

Var E = 4, F = 3.7 G = ‘GC’;

  1. 清空控制台;

每种类型的变量对他们可以存储的信息的类型和数量都有严格的限制。例如int整形变量可以保存-2和2之间的整数。然而,浮点值表示一个浮点数(实数),大约有14位精度。整形和浮点型的区别在于是否有小数点。选择正确的变量类型将确保变量的输入和接受正确的值。例如,如果一个变量表示一个计数,那么正确的类型应该是一个整形int确保计数总是一个整数。
变量的命名规则
变量和其他符号值的命名规则和大多数编程语言的标准一致:一个字母或者下划线字符,后边跟着任意数量的字母、数字和下划线等,但注意不能有空格。

  • 名称区分大小写,名称lineLength和LineLength被认为时不同的名称;
  • 名称不能以数字开头;
  • 不能使用特殊字符如@!$^&,允许使用下划线“_”;
  • 在GC脚本中有特殊含义的单词不能使用;

    练习2:操作符

    操作符允许我们对变量和值进行操作。一个简单的例子就是加号“+”操作符可以将变量和值相加,如C = A + 3;
    数字运算符
    “+”是数字运算符的一种类型。让我们看看其他的数字运算符。
    A -3 ‘-’ 减号运算符
    A B ‘’ 乘号运算符
    A / B ‘/’ 除号运算符
    A \ B ‘\’ 分层除法(向负无穷四舍五入到最接近的整数)
    A % B ‘%’ 取余运算符
    在表达式中使用多个操作符是很常见的。
  1. GC脚本教程 - 图14在控制台对话框中键入:

Int A = 4,B = 10,C,D = 3;
C = A B + 9 / D – 1;
Print(C);
每个运算符都有优先级,就像数学中一样,括号,乘除运算,加减运算。操作符‘
’、 ‘/’、 ‘\’、 ‘%’ 具有相同的优先级,但他们的优先级高于‘+’和‘-’。
如果两个操作符具有相同的优先级,则从左往右计算他们。

  1. GC脚本教程 - 图15在控制台对话框中再次键入表达式,使用圆括号来改变计算的顺序:

C = A * (B + 9) / (D - 1);
Print(C);

  1. 清空控制台;

关系操作符
这种类型的操作符用于比较两个变量以理解它们的关系,例如,如果一个变量大于另一个变量或等于另一个变量等等。操作总是根据执行的测试返回一个布尔值(true或false)。
A==B; 验证A的值是否等于B;
A!=B; 验证A的值是否不等于B;
A>B; 验证A的值是否大于B;
AA>=B; 验证A的值是否大于等于B;
A<=B; 验证A的值是否小于等于B;

  1. GC脚本教程 - 图16尝试在控制台中使用关系型操作符,如下图所示:

布尔类型的操作符
布尔运算符或逻辑运算符用于检查条件的组合。和(&&)、或(||)是最常用的两个布尔运算符。
A && B; 如果A、B均为真则结果为真;
A || B; 如果A、B中有一个为真则结果为真;

  1. 尝试在控制台中使用布尔类型的操作符,如下图所示:

GC脚本教程 - 图17

  1. 清空控制台。

练习3:列表

GC脚本可以像处理单个值那样轻松的处理列表。列表是值的集合,其中的每个值都可以单独的管理。要指定一个列表,我们必须在花括号中放入一系列由逗号分隔的值。
  1. 在控制台对话框中键入:

int A = {1, 3, 5, 6};
我们可以通过下边的形式A[index]访问列表的每个成员。索引Index是成员在列表中的位置。列表的第一个成员的索引是0,第二个成员的索引是1,以此类推。
GC脚本教程 - 图18
Print(A[0]);
返回的结果是1.

  1. 我们可以进一步修改列表中任何成员的任何值。在控制台对话框中输入:

A[3]=7;
Print (A);
则新的列表变成了 {1,3,5,7}
GC脚本教程 - 图19

  1. 清空控制台。

列表也可以完全为空。一个空的列表用于存储一组用于其他目的的新值。我们可以通过两种方式向列表添加值,第一种,通过索引,第二种,通过Add( )函数。

  1. GC脚本教程 - 图20在控制台对话框中键入:

int A = {};
A[0] = 1;
A[1] = 2;
A[5] = 6;
Print(A);

列表现在是{1,2,null, null, null, 6}。使用索引,值会根据索引添加到相应的位置。
我们可以在GC脚本中使用值的属性和方法。例如,我们可以使用count属性进一步计算列表中的成员数量。属性是用点操作符‘.’来调用的,点操作都后跟属性名称,如list.Count。

  1. 使用Count属性查看列表中成员的数目。

Print(A.Count);
返回的结果是6,表示列表中有6个成员(包括空成员)。
Add方法是将成员添加到列表末尾的一种方法,示例如下。

  1. GC脚本教程 - 图21在控制台对话框中键入:

A.Add(7);
A.Add(8);
Print(A);
列表现在是 {1, 2, null, null, null, 6, 7, 8}. 使用Add( )函数,值是按顺序添加的。

练习4: 函数

一般来说,函数是对于给定的输入执行一些操作并产生一些输出,然后我们根据需要进一步使用输出的结果。函数的优点是,一旦定义了函数,就可以在一组新的输入上根据需要多次重复使用它。<br />    咖啡机就是一个功能的真实例子。咖啡机根据具体提到的输入类型(如咖啡、水和牛奶)生产咖啡。每次我们需要咖啡的时候,我们不需要制造机器。我们可以每次都使用同样的机器,但我们必须提供输入;咖啡、水和牛奶(可选输入)。如果我们使用了不同于指定的输入,那么它可能无法按预期执行,或者根本无法执行。<br />我们可以在FunctionCall节点或几何节点的ByFunction技术中创建函数。除了这些之外,我们还可以在事务脚本中创建函数,这里不做讨论。<br />在FunctionCall节点中创建一个函数<br />![](https://cdn.nlark.com/yuque/0/2021/png/21640782/1630293679763-dfaee1f1-cbf5-4d94-b549-cb73842704ef.png#)<br />FunctionCall节点中的一般函数体是这样的:<br />Function (argument1, argument2) <br />{<br />statement A<br />statement B <br />return output;<br />} <br />GC逐个读取语句。它将执行语句1,然后执行语句2。通过return语句,我们获得了所需的输出,然后就可以用于其他目的
  1. 将FunctionCall节点拖放到图表窗口中创建一个FunctionCall节点,将该节点重命名为functionSum;
  2. 选择“Create / edit this node ‘ s custom Script function”图标打开脚本编辑器,编辑器将打开一个新的void函数的语法。

GC脚本教程 - 图22

  1. 编辑文本,创建一个函数来返回两个数字之和。

function (int number1, int number2) //arguments
{
int sum = number1+number2; //statement A
return sum; //return output
}

  1. GC脚本教程 - 图23选择应用按钮。参数被添加到节点作为输入参数,并允许我们输入这两个数字。

我们可以直接将值填入输入框中,也可以将输入链接到另一个节点。它的行为方式与任何其他节点的输入相同。

  1. number1输入2,number2输入3。请注意该函数的输出是5。
  2. 录制事务(Record Transaction)。

    练习5:控制语句

    控制语句是根据逻辑条件确定执行流的语句。换句话说,这样的语句允许我们根据条件集指定一个语句是要跳过还是要重复。一些常见的类型有if、if-else、for和while。
    这些语句是复合类型的语句。复合类型语句由花括号内的一系列语句组成。GC脚本控制台只支持简单语句(单行语句)。因此,将在FunctionCall节点中尝试控制语句的示例。
    if语句
    该语句允许我们控制语句是否被执行。
    一般形式:
    if(表达式)
    {
    语句A
    }
    表达式的结果必须是bool值,如果该值为true,则执行语句A。

  3. 将FunctionCall节点拖放到图表窗口中创建一个FunctionCall节点,将该节点重命名为ifStatement。

  4. 选择“Create / edit this node ‘ s custom Script function”图标打开脚本编辑器。

我们将创建一个函数如果一个数能被6整除的话就给它加一。

  1. 编辑函数和参数。

Function(int Number) //arguments – input

  1. 我们可以通过从语句生成器图标中选择 if 来插入所需的代码片段。

  2. 如图所示编辑语句块、键入返回语句。

{
if(Number % 6 ==0) //test
{ return Number+1;} //return – output
}

  1. 在Number输入框中输入42,函数节点的输出值将会是43.

  2. 录制事务。

if-else 语句
if-else语句和if语句很类似,不同的地方是,当判断的结果是false的时候执行else中的语句B。一般形式为:
if (expression)
{ statement A }
else
{ statement B }

  1. 创建一个fucntionCall节点。在这个例子中我们将检查输入的数字数奇数还是偶数。将该节点重命名为if-else语句。
  2. 打开脚本编辑器并输入以下的代码:

function (int Number) //arguments
{
if (Number%2==0) //test, if the number is divided by 2 and the remainder is equal to 0
{
return ‘Number is even’; //return the text string if test is true
}
else
{
return ‘Number is odd’; //return the test string if test is false
}
}

  1. 点击应用(Apply)按钮,在输入框输入42.该函数节点将会返回“Number is even”。
  2. 录制事务。

For 循环
这个控制语句允许我们重复运行一组语句,且运行的次数是已知的。
一般形式:
for (variable initialization; condition check; update value of variable)
{
statement A
statement B
}
让我们通过一个例子来看看for循环时如何工作的:

  • 步骤1:初始化一个变量,赋初值为i = 0。此步骤只执行一次。
  • 步骤2:检查设置的条件,如果为真,则进入函数体。
  • 步骤3:执行函数体中的语句。
  • 步骤4:更新初始化变量的值。这里i的值增加了1。
  • 步骤5:检查变量(i = 1)的新值,如果为真则返回步骤3,如果为假则停止循环。
  1. 创建一个functionCall节点。在这个例子中,我们将创建一个累加到给定数字的函数(如果给定的数字是n,那么sum = 1+2+3+…+n)。将该节点重命名为forLoop.
  2. 打开脚本编辑器并输入如下代码:

function (int Number) //arguments – inputs
{
Int sum = 0; //declare the variable sum = 0
for (int i = 1; i <=Number; ++i) //for expression, i = 1, initializes the loop with 1, the first number in our summation
{
sum=sum+i; //statement – increases the current value of sum by the value of i.
}
return sum;
}

  1. 点击应用按钮。
  2. 在输入框输入4,则该函数的输出结果是10.

让我们来看看这个函数是怎么工作的:
循环1) sum = 0, i = 1, so sum = 0 + 1 = 1
循环1) sum = 1, i = 2, so sum = 1 + 2 = 3
循环2) sum = 3, i = 3, so sum = 3 + 3 = 6
循环3) sum = 6, i = 4, so sum = 6 + 4 = 10
循环4) sum = 10, i = 5, 5大于输入的数字4,所以循环终止执行下一条语句。
sum = 10

  1. 创建一个functionCall节点。在本例中,我们将筛选出100以内的最后一位数字是2且能被4整除的所有整数,如12,32等。将该节点重命为forLoopIfStatement 。
  2. 打开节点编辑器,并输入如下代码:

function (int Number) //arguments – inputs
{
int numberlist= {}; //declare the variables, numberlist is an empty list
for (int i = 1; i <=Number; ++i) //for expression, i=1, initializes the list at 1,
{
if (i%4==0 && i%10==2) //if expression, conditions that must be met for i beforecontinuing
{
numberlist.Add(i); //adds the value of Number to the list if it passed conditions set above
}
GC脚本教程 - 图24}
return numberlist;
}

  1. 点击应用按钮。
  2. 在输入框输入100,则该节点的输出结果是 {12,32,52,72,92}。
  3. 录制事务。

Foreach 循环
这个控制语句允许我们遍历或迭代给定列表的每个成员,从开始索引到最后一个。一般形式如下:
foreach (variable in sourcelist )
{
Statement
}
Variable是用来表示列表的后续成员或项的变量的名称。这个变量是foreach语句的局部限量。花括号中的语句会对列表的每个成员重复的执行。

  1. 创建一个functionCall节点。在本例中我们将求出给定列表中所有成员的和。将该节点重命名为foreachLoop。
  2. 打开脚本编辑器并输入如下代码:

function (int[ ] Numberlist) //arguments - int[ ] is used to indicate the input will be a list of integers
{
int sum = 0; //declare the variable
foreach (int item in Numberlist) //foreach variable ‘item’ in sourcelist ‘Numberlist’
{
sum = sum + item; //statement that adds each new item in the list to the previous item
}
return sum; //return - output
}

  1. 点击应用按钮。
  2. 在节点的输入框输入{1,3,5,7},则该节点会输出列表成员的和。
  3. 录制事务。

While 循环
While循环允许我们在判断给定条件为真后执行一组语句。一般形式为:
while(expression)
{
statement
}
在while循环中,首先会检查测试表达式返回值是否为真。如果表达式返回值为真,则执行花括号中的语句,且只要判断条件的结果为真,该循环就会重复执行花括号中的语句。但是,一旦出现了第一个判断条件为假的情况,就会跳出循环执行下一个语句。

  1. 创建一个functionCall节点。我们将创建一个以给定值递增的数字列表,直到达到限值。
  2. 打开脚本编辑器并输入以下代码:

function (int IncrementalValue, LimitValue) //Arguments - inputs
{
int chainagelist ={}, Number=0; //declare the variables, chainagelist is an empty list, Number will be the list members.
while (Number < LimitValue) //while expression
{
chainagelist.Add(Number); //statement – add the current value of Number to the list
Number = Number + IncrementalValue; //increment the Number variable by the IncrementalValue
}
return chainagelist;
}

  1. 点击应用按钮。
  2. 在节点的输入框里为IncrementValue 输入25,LimiValue输入500,则该节点的输出是一个开始于0,并以25递增,直到500但不包括500的数列。
  3. 录制事务。

练习6:长度规律变化的线

在这个练习中,我们将使用之前练习所学到的创建几何图形。我们将生成一个点列表,其中每个点与下一个点之间的距离是前一个点距离的两倍。<br />![](https://cdn.nlark.com/yuque/0/2021/png/21640782/1630293682718-a9cf42de-1aed-4b63-97ae-e717ffab0834.png#)<br />    这个问题的关键步骤是在于生成连续点的X坐标值,X坐标值应该是一个等比数列。我们可以创建一个函数,该函数根据给定的比值返回等比数列。并且,这个列表可以作为该点的X坐标值输入。
  1. 创建一个functionCall节点,将它重命名为GeometricSequence。打开脚本编辑器并输入如下的代码:

function (int CommonRatio, int XValue, int Count) //arguments - inputs
{
int GS = { }; //declare the variables, GS is an empty list
GS.Add(XValue); //statement – add the value of XValue to the list
for (int i = 0; i < Count; ++i) //for expression - initialize the loop at 0, increase by 1 until i is no longer less than Count
{
XValue = XValue * CommonRatio; //statement – multiply the current XValue by the CommonRatio
GS.Add(XValue); //statement – add the value of XValue to the list
}
return GS; //return - output
}

  1. 点击应用按钮。
  2. 在该节点的输入框中输入以下参数:

CommonRatio:2
XValue:1[1000]
Count:10
输出的结果是一个{1,2,4,8,……,}的列表,该列表总共有10个成员。

  1. 在图表中添加一个方法为ByCartesianCoordinates的点节点,节点的输入为:

CoordinateSystem:baseCS
XTranlsation:GeometricSequence

  1. 在图表中放置一个方法为ByChaining的线节点,输入为 Vertices:point1
  2. 录制事务。

    2 对象和类

    在这一部分中,我们将学习GenerativeComponents中对象的概念,以及如何使用GC脚本创建新的对象。在本部分的最后,我们可以够通过在几何节点上使用ByFunction技术,使用GC脚本创建新的几何图形。
    类和对象
    一般来说,对象可以是任何具有某些属性和功能的可识别实体。为了理解这一点,我们将把它与一个真实世界的人类例子进行比较。人类有身高、体重、性别等属性,还有走路、说话、跑步等功能。约翰,大卫,彼得都是人类实例化的例子。因此,它们都是人类的对象,他们将拥有人类所有的属性和功能。在GC中,line节点可以是对象的一个例子。在这里,line1是属于line类的对象。
    其他的一些例子如下:
    GC脚本教程 - 图25

我们可以通过点运算符访问对象的属性。
这些符号GC脚本教程 - 图26 GC脚本教程 - 图27分别表示方法和属性,方法类似于仅特定于该类的函数。

对象的属性也可以是不同类的对象。我们可以进一步访问该属性的属性。例如,让我们考虑对象line1的属性StartPoint。StartPoint是一种Point类型的对象。我们可以通过点操作符进一步访问StartPoint对象的属性。属性将与点类型相同。

在某些情况下,属性也可以是list类型的。在这种情况下,我们可以使用索引访问属性列表中所需的成员。

表示line1.Poles是一个一维列表。我们可以通过索引来访问列表中的单个元素。

练习7:使用ByFunction方法

在本节中,我们将学习如何使用GC脚本使用几何节点的ByFunction方法创建几何图形。这类似于在FunctionCall节点中创建一个函数。
在这个练习中,我们将创建一个点,它从一个坐标系原点对角偏移相同的X和Y距离。这个简单的练习将帮助我们理解如何对所有节点使用ByFunction技术。

  1. 新建一个文件,命名为PointByFunction.dgn
  2. 在Home工具栏下Place Geometry工具组中点击Create baseCS按钮,选择design model后点击OK。
  3. 在图表中新建一个方法为ByFunction的点节点,在函数输入框中选择“Open the full script editor”打开函数编辑器。

GC脚本教程 - 图28

  1. 在函数编辑器中,使用语句生成器向脚本添加一个函数。我们可以在需要的时候添加函数的输入参数。

  2. 创建一个名为pt的新变量,其类型与父节点(Point)的类型相同。

Point pt;

  1. 定义完了变量之后,我们需要提供一些的属性与方法,使该变量成为Point对象。因此,我们需要调用构造函数。

Point pt;
pt = new Point(this);

在这Point()使构造函数。通常默认的构造函数时对象类型名字后跟圆括号。我们也可以将上述语句写在一行中。
Point pt = new Point(this);
在这里,this的作用是让GC知道函数中新创建的Point对象与顶级父节点point1相关。在前边的步骤中,我们已经创建了pt,但它仍然是不完整的,因为我们没有选择任何创建点所需的方法。在下一步中,我们需要使用点操作符选择创建点所需的方法来初始化对象。

  1. 在下一行输入pt后输入点操作符‘.’,并从下拉列表中选择方法ByCartesianCoordinate。

注意:这些方法可以作为对象的方法使用。因此我们需要在选择方法之后加上括号。当我们键入第一个括号时,将会有所要求输入的提示。

通常,提示参数输入的顺序和我们在节点中是一致的,我们需要以相同的方式输入。在这个例子中,需要输入的参数是(CoordinateSystem, XTranslation, YTranslation, ZTranslation)。
function ()
{
Point pt = new Point(this);
pt.ByCartesianCoordinates(baseCS, 100, 100, 0);
}
在这里,baseCS是所使用的坐标系统的名称。100、100、0分别是XTraslation、YTranslation、Ztranslation的输入值。因为X轴和Y轴的平移是相等的,这个点将从原点对角偏移。
在这里,坐标系对象节点的名称baseCS对象在函数内部被直接调用。我们还可以为这个输入创建一个参数。我们强烈的建议使用参数而不是直接通过名称调用对象,因为如果对象或节点名被更改,那么函数将无法找到对象。

  1. 为坐标系添加一个参数,然后将baseCS替换为参数CS。
  2. 添加第二个参数作为点X、Y坐标的距离,将函数中的X、Y值替换为距离参数。

function (CoordinateSystem CS, double Distance)
{
Point pt;
pt = new Point(this);
pt.ByCartesianCoordinates(CS, Distance, Distance, 0);
}

  1. 点击应用按钮更新point1节点的函数,将baseCS输入到CS输入框,在Distance输入框填入点的坐标值,则一个新的点就会在指定坐标被创建出来。
  2. 录制事务。

练习8:使用线的ByFunction方法创建不同长度的线

本次练习与第一部分练习6中的练习基本相同,只是这次我们将根据计算的X坐标值直接添加点。
  1. 创建一个名为PointSequence的新的dgn文件。
  2. 在Home工具栏下Place Geometry工具组中点击Create baseCS按钮,选择design model后点击OK创建baseCS节点。

  3. 在图表中放置一个方法为ByFunction的点节点,点击函数的输入框打开脚本编辑器,如下图:

  4. 将下边的代码添加到脚本编辑器中:

function (int CommonRatio, int XValue, int Count, CoordinateSystem CS)
{
Point pt = new Point(this);
pt.ByCartesianCoordinates(CS, XValue, 0, 0); //Starting point of the series
for (int i = 0; i < Count; ++i)
{
XValue = XValue*CommonRatio; //Value for X-Coordinate
//Now the above calculated value will be used in creating new Point.
pt = new Point(this);
pt.ByCartesianCoordinates(CS, XValue, 0, 0); //adding new points
}
}

  1. 点击应用按钮。
  2. 在point1的输入框中输入如下的参数:

CommonRatio:2
XValue:1[1000]
Count:10
该节点的输出是一个X值从1开始,并以2倍的速度递增的,有10个成员的点列表。

3 嵌套列表

在本部分中我们将学习嵌套列表和如何使用嵌套列表类型的对象,我们还将学习如何使用一些列表函数。
有时候一个列表可以包含另一个列表作为它的成员,这种类型的列表被称为嵌套列表,如下例子所示:
int A = {2, {4,7,9}, 5, 6};
A[0] 的值是 2
A[1] 的值是 {4,7,9}
A[1][0] 的值是 4
GC脚本教程 - 图29
我们可以向主列表中添加任何空列表:
Int A = {2};
A.Add({ }); // 向列表的末尾添加一个空列表
Print(A);
使用之前的Add()方法也可以向空的嵌套列表中添加成员,如下所示:
Int A = {1,2,{ },{ },5};
A[2].Add(3); //将3添加到索引为2的位置
A[2][1].Add(3);//将3添加到列表中索引为[2][1]的位置
Print(A);
最终打印输出的列表的结果是{1,2,{3,3},{},5}
但是,如果列表中不存在嵌套列表,我们就不能用索引的方式向列表添加成员。
Int A = {};
A[2][2] = 4;
Print(A);
请注意,这个列表中A[2]索引处不是列表,所以不能在A[2][2]处添加成员。
我们可以先在A[2]处添加一个嵌套列表,然后再向其添加成员,如下所示:
Int A = {};
A[2] = {};
A[2][2] = 4;
Print(A);
打印出的结果是:{null, null, {null, null, 4}}.
我们可以使用函数FillList2d()来定义所需的嵌套列表数量和每个嵌套列表的成员数量,而不是每次都添加一个空的嵌套列表。这个函数有两个参数,第一个是嵌套列表的数量,第二个是每个嵌套列表的成员数量。让我们看一个例子。
Int B = FillList2d(3,2,9);
Print(B);
打印出的结果是:{{9, 9}, {9, 9}, {9, 9}}.
列表的计数(Count)和维度(Rank)
列表的计数是列表中成员的数量。如果主列表中有一个嵌套列表,那么它将把这个嵌套列表视为单个成员。
列表的维度是对列表嵌套深度的一种度量。列表中的每个成员都有一个维度,列表的维度是1加上它所有成员中的最小维度。我们来确定一个列表{3,{2,3}}的维度。在确定列表的级别之前,我们将确定列表中每个成员的级别。
GC脚本教程 - 图30
任何非列表成员的级别为0,而简单嵌套的列表成员的级别为1。这里成员3的最小维度是0。所以,这个列表的维度是0+1即1。让我们看一些更多的例子。
GC脚本教程 - 图31
如果有一个深度嵌套的列表成员,我们可以计算嵌套列表成员的维度,就像计算矩阵的秩一样。

确定最低所需维度
在声明列 表变量时,可以指定所需的最小维度。下面是我们如何确定最小维度的例子。
int [ ] x; [ ]定义变量x始终接受最小维度为1的列表。它不接受单个整数,因为单个整数的维度是0。
int[ ][ ] x; [ ][ ]定义变量x始终接受最小维度为2的列表。
定义列表的一般形式是类型名后跟所需的一对空方括号。使用的方括号对数表示列表的最小维度。
type[ ][ ][ ]x; type可以是从int、double到Point或Line的任意类型。使用的三对空方括号表示x将接受最小维度为3的列表。

练习9:使用ByFunction方法创建一个2D的点列表

在这个练习中,我们将通过创建一个二维列表的点数组。与使用Series函数创建具有增量间距的简单数组不同,我们将在每个方向创建不同的图案间隔。我们在点节点上使用ByFunction方法并添加参数,以便可以控制行和列的图案间隔。我们使用while循环创建X和Y坐标的两个值列表,然后使用for循环语句将每个点生成为2D列表。
  1. 创建一个新的名为Point2Darry.dgn的文件;
  2. 点击Home选项卡下的Place Geometry工具组中的Create baseCS按钮,如图所示,选择Design Model并点击OK按钮接受;
  3. 在图表窗口中放置一个方法为ByFunction的点节点,点击Function输入框打开脚本编辑器窗口,在窗口中输入如下的代码:

GC脚本教程 - 图32

  1. 点击应用更新新函数下点节点和输入窗口;
  2. 分别为Row,Column和Spacing参数输入如下的值:

Row:3;
Column:7;
RowA: 300, RowB: 500, ColB: 300, ColB: 750
CS: baseCS
如果我们将鼠标悬停在这些点上,我们会看到每个成员点的索引。
我们可以根据需要进一步索引point1对象。

  1. 在图表窗口中创建一个新的Line节点。
  2. 选择其方法为ByChaining,输入框Vertices:point1[1],将会创建一条直线将第二行的所有点连接起来。

    练习10:使用Function Call节点创建一个坐标列表

    在这个练习中,我们将为一系列点创建x、y、z值的坐标列表。x、y、z坐标的列表将使用FunctionCall节点创建,并由一个数学公式驱动。
    我们将创建一个正弦环,这是一个绕在圆柱上的正弦曲线。笛卡尔坐标参数形式是X=aCos(t), Y=aSin(t), Z=bCos(nt),变量“a”表示圆柱体的半径,“b”表示圆柱体的高度,n表示波的振荡次数,t表示沿圆周的角度。这些变量的值可以取大于0的常量。有了这个参数方程,我们将得到XYZ坐标值,基于它我们可以创建一系列的点。最后,用闭合的b样条曲线将这些点连接起来,得到正弦环。
    我们可以创建一个维度为2的列表来保存XYZ值,即{{X0,Y0,Z0}, {X1,Y1,Z1}, {X2,Y2,Z2},………..}。列表中的每个成员都将创建一个新点。

  3. 创建一个名为SinusoidalRing-Points.dgn.的新文件。

  4. 点击Home选项卡下的Place Geometry工具组中的Create baseCS按钮,如图所示,选择Design Model并点击OK按钮接受;
  5. 在图表界面创建一个新的FunctionCall节点;
  6. 打开脚本编辑器窗口,将如下的代码复制到编辑器中:

GC脚本教程 - 图33

  1. 点击应用按钮更新节点;
  2. 在节点的输入框填入如下参数:

Number: 5
Radius: 2000
Height: 3000

  1. 在图表界面新建一个点节点,将其方法设为ByCoodinateList。CoordinateSystem输入框输入baseCS,将functionCall节点的结果输入到XYZTranslation中;
  2. 创建一个新的B样条曲线(bsplineCurve)按钮,将其方法设为ByPoles,将上一步骤中的点输入到该节点中,结果如下图所示:

    练习11:将多个节点合并到一个函数中

    在之前的练习中,使用了3个节点来创建所需的曲线。但是,在本次练习中我们可以将这三个节点合并到一个函数节点中直接创建B样条曲线。

  3. 新建一个名为SinusoidalRing-Bspline .dgn的文件;

  4. 点击Home选项卡下的Place Geometry工具组中的Create baseCS按钮,如图所示,选择Design Model并点击OK按钮接受;

由于该函数将直接创建B样条曲线,所以我们需要使用B样条曲线节点下的ByFunction方法。

  1. 在图表界面创建一个方法为ByFunction的B样条曲线节点,打开脚本编辑器对话框;

现在我们开始用返回点坐标列表的functioncall节点中的几行代码编写函数。这些行应该与前面的练习中相同。唯一的区别是,这里我们将使用它来创建bsplinecurve函数内的点,而不是返回点坐标列表。

  1. 在脚本编辑器中键入如下的代码:

GC脚本教程 - 图34
GC脚本教程 - 图35
我们将在这个函数中基于坐标创建点,创建的点将用于构造B样条曲线。因此,点节点是一个作为临时节点。除非在函数结束之前返回,临时节点不会添加到图形中。可以通过在构造函数中不传递参数来创建临时节点。

  1. 为了创建作为临时节点的点,插入以下代码:

GC脚本教程 - 图36

  1. 这个临时点节点将使用与前面单独节点相同的技术和输入参数。要通过这种技术创建点,我们需要一个坐标系以及X、Y、Z值的列表。因此,还需要为坐标系添加一个参数。

GC脚本教程 - 图37
GC脚本教程 - 图38
使用这种临时节点具有特殊的优势,因为它们往往是轻量级的。这些临时节点通常用作创建其他相关几何图形的中间步骤。
GC脚本教程 - 图39现在我们可以使用这些临时节点来创建最终的B样条曲线。

  1. 为了创建B样条曲线,需要将上图所示的代码插入到编辑器中;
  2. 点击应用按钮更新B样条曲线节点和输入框;
  3. 在新的B样条曲线节点输入框中输入如下参数:

Number: 5
Radius: 2000
Height: 3000
注意:那些临时点在模型和图表中都不见了,我们使用函数直接创建了B样条曲线。

4 使用库函数

在这一部分,我们将介绍如何使用库函数和方法。
使用库函数
在GC中,有一个丰富的预定义函数库,可以在任何脚本上下文中使用它们。

  1. 重新打开之前创建的文件:Point2DArray.dgn
  2. 点击Model功能区的Functions按钮就可以打开Functions对话框;

  3. 点击任何函数(Functions),我们都可以看到函数的签名(Signature)和目的(Purpose)。Purpose的功能是对函数进行简单的描述,而Signature则让我们了解函数的一般形式和所需参数。

  4. 在可用函数列表中选择Abs,函数的签名number Abs(replicatable number n)

在函数前边的number表示它将返回一个数字类型的值。函数内部的replicatable number表示输入的参数是number类型的值,也可以是一个number类型的列表。
注意:当在控制台中使用(Abs({-23, 34, -56.33})时,控制台会返回一个列表{23, 34, 56.33},列表中每个成员的值都是开始列表的绝对值。

  1. 选择函数GetPropertyValue。该函数的签名是:object GetPropertyValue(object obj, string propertyName)

第一个参数是对象类型,这意味着它可以接收任何类型的对象,点、线、弧、节点等;第二个参数是字符串类型的,这意味着我们可以在括号内输入值;最后,这个函数的返回值类型也是基于入参的对象类型。

  1. 如图所示,选择Apply to functionCall1 > 会直接在图表中创建一个输入框是object类型的obj和string类型的Property Name 的function call节点;将line1节点连接到obj输入框;在propertyName输入框中键入“Vertices”,如下图所示:

注意:当填入如上的输入值时,该节点返回的结果是点类型。

练习12:列表方法

在这个练习中,我们将学习各种可用的列表方法。这些方法对于快速修改列表和检索成员是很有用的。下边将使用控制台和几何节点演示一些示例。这些方法的名称是直观的且自解释的。<br />**列表编辑方法 - List.Add( )**<br />    我们在整个文档中一直使用的列表方法的一个简单示例就是list.Add()方法,Add方法是一个修改列表的方法,这意味着它可以通过在列表的末尾添加新的成员来修改现有的列表。<br />    int A = {1, 2, 3, 4};     //creates a new list named ‘A’ with four members, 1,2,3, and 4<br />A.Add(5);             //Adds 5 to the end of list A
  1. 将第一行键入控制台中,如图所示;开始将第二行键入控制台中,使用点操作符访问列表的方法,在其中选择Add方法;键入Print(A);

注意:经过上边的操作,5已经被添加到A列表的末尾,A列表现在是
{1, 2, 3, 4, 5}.

其他的列表编辑函数图下图所示:
GC脚本教程 - 图40
上图中的每个方法返回的都是列表本身,这些方法可以连在一起调用,例如下边的代码就可以被写成一个语句:
// Assume ‘A’ is a pre-existing list of Points {1, 2, 3, 4, 5}
A.Insert(1, 1); // Insert ‘1’ at the index position of 1
A.RemoveAt(4); // remove the member at index position 4
Print(A);
Print(A.Insert(1, 1).RemoveAt(4));

列表检索方法
列表检索方法是在不修改列表的情况下返回数据或者列表的状态信息。
list.Append()** list.Prepend()**方法
list.Append(item)方法会返回一个包含源列表所有成员且在源列表末尾添加了新成员的新的列表;
list.Prepend(item)方法会返回一个包含源列表所有成员且在源列表开头添加新成员的新的列表;

  1. 在控制台键入如下代码:

int B = A.Append(8);
Print(B);
注意:如果我们想编辑最初的列表,您我们可以使用如下的代码:A = A.Append(8);
list.AppendFrom()list.PrependFrom()方法
list.AppendFrom(otherList)方法返回一个包含源列表所有成员且在源列表末尾添加了otherList成员的新的列表;
list.PrependFrom(otherList)方法返回一个包含源列表所有成员且在源列表开头添加了otherList成员的新的列表;

  1. 在控制台键入如下代码:int C = A.AppendFrom(B);

Print(C);

list.First() list. Last()方法
顾名思义,list. first()和list. last()将返回源列表的第一个和最后一个成员。

  1. 在控制台中键入如下的代码:B.First(); B.Last();

注意:这两个方法不接收任何参数,它们只返回列表的第一个或最后一个成员。
接下来,我们将使用这些方法从point1检索点。

  1. 打开line1节点,将Vertices输入框的值变为:

Vertices: Point1.First()
注意:point1是一个2D数组,所以point1的第一个成员是所有第一个下标为0的点。

  1. 将line1节点的Vertices输入框的值变为:

Vertices: Point1.Last()
list.Take()list.Skip() 方法
list. take (count)方法返回一个新的列表,其中只包含列表中第“count”个成员。参数’count’是可选的;如果省略,它将被视为1。
list. skip (count)方法返回一个新的列表,包含源列表中除了第“count”个成员之外的所有成员。参数’count’是可选的;如果省略,它将被视为1。

  1. 将line1节点的Vertices输入框的值变为:

Vertices: Point1.Take(3)

  1. 将line1节点的Vertices输入框的值变为:

Vertices: Point1.Skip(2)

注意:如果没有提供实参,则使用默认值1,返回一个包含一个成员的列表。

list.TakeLast()list.SkipLast() 方法
List.TakeLast(count)方法返回一个包含源列表最后“Count”个成员的新列表;形参count是可选的,如果不输入,则会使用默认值1.
List.SkipLast(count)方法返回一个去除了源列表最后“Count”个成员的新列表;形参count是可选的,如果不输入,则会使用默认值1.

  1. 将line1节点的Vertices输入框的值变为:

Vertices: Point1.TakeLast(3)

  1. 将line1节点的Vertices输入框的值变为:

Vertices: Point1.SkipLast(3)

其他的一些列表检索的方法如下图所示:
GC脚本教程 - 图41
GC脚本教程 - 图42
列表复制方法
列表复制方法返回整个列表的副本,虽然会重排列列表,但不会改变现有的列表。
Flatten()方法
Flatten()方法返回一个将任何嵌套列表转为简单一维列表的新的列表。
让我们来看看下边的例子:
int A = {2, {4,7,9}, 5, 6};
GC脚本教程 - 图43
当我们对这个列表应用了A.Flatten()方法之后,它就变成了这样 {2, 4, 7, 9, 5, 6}
GC脚本教程 - 图44

  1. 在控制台中键入:

int A = {2, {4,7,9}, 5, 6};
Print(A.Flatten());
我们也可以将它应用到几何上:

  1. 将Line1节点的Vertices输入框改为:

Vertices: point1.Flatten()
2D的point1点列表被扁平化为一维点列表,并通过所有的点依次绘制直线。
我们还可以将此方法与其他列表方法组合使用,首先将列表扁平化,然后从扁平化的列表中检索成员。

  1. 将Line1节点的Vertices输入框改为:

Vertices: point1.Flatten().Take(25) 或者 Vertices: point1.Flatten().TakeLast(25),

转置方法()Transpose()
转置方法会将所有嵌套列表转换为一个前两个索引位置(维度)互换的新的列表。
在讨论这个方法之前,我们先来看看转置在excel中的一个简单例子:

换位后,上面的行和列也会交换。
对于索引位置为[i][j]的成员,在执行转置方法后变成[j] [i]。让我们来看一个例子。

  1. 在控制台中键入:

Int A = {{11, 12, 13}, {21, 22, 23}, {31, 32, 33}};
Print(A.Transpose());
返回的列表已经被转置,因此第一个嵌套列表是每个原始嵌套列表的第一个成员,第二个嵌套列表是每个原始嵌套列表的第二个成员,以此类推。
我们可以将转置方法应用给二维的点列表或者其他的几何节点。

  1. 将line1节点的Vertices输入框的值修改为:

Vertices: point1.Transpose()
注意:在应用完转置方法之后,这些线从水平线变成了竖直线。

  1. 将line1节点的Vertices输入框重新改回point1.

其他的一些列表复制的方法如下所示:
GC脚本教程 - 图45
到目前为止,我们已经在控制台和几何节点的输入框中使用了列表方法来修改一个点列表。我们还可以在函数中使用列表方法来修改它调用的列表。让我们在创建point1的脚本中使用它来删除列表中的倒数第二个成员。

  1. 打开之前创建的point1的函数脚本编辑器窗口,将下边的代码键入其中:

GC脚本教程 - 图46

添加这条语句的作用是删除点列表中最后两行的点。

练习13: 选择函数

让我们来看看另一个脚本函数Select(),Select函数返回一个包含给定列表中满足给定条件的成员新的列表。<br />函数签名为:<br />Select(object[] list, bool function(object member,…)selector,…)<br />Select是GC脚本中一个非常通用的函数,允许用户根据自己定义的标准从给定的输入列表中进行选择。一般情况下,我们将在第二个参数中创建一个放置选择条件的匿名函数。一般形式如下所示:<br />object[] Select(object[] list, bool function(object member) { return criteria_expression;})<br />选择函数的工作方式是遍历输入数组的每个成员,并测试它们是否满足选择标准。用户通过编写自定义的函数作为选择条件并指定函数的输入,确定选择函数如何进行选择,以及返回什么。<br />在下面的练习中,我们将使用Select()函数从2D点数组中选择Y值大于或等于1000的点。点列表与第三部分中创建2D点数组时使用的列表相同。
  1. 放置一个Value节点;
  2. 打开Value节点的脚本编辑器,在其中添加选择函数去选择点列表中Y值大于等于1000的点;

Select(point1, function(Point pt){return pt.Y>=1000;})
在这里,Point1是点列表;在匿名函数中,必须定义与第一个形参类型相同的形参,这也是为什么在这里使用了Point pt,pt是临时点的名称。根据选择条件表达式,匿名函数的返回类型是布尔类型的值。

  1. 将新建的Value1节点连接到line1节点的输入框中,则line1节点就只会画出点的Y值大于1000的线,如下图所示:

    我们可以向匿名函数添加额外的参数。例如,我们可以使用参数来代替直接值1000,并使用滑块来控制该参数。

  2. 添加一个滑块节点,将范围设置为0-1000.

  3. 打开Value节点的脚本编辑器对话框,将函数编辑为如下形式:

Select(point1, function(Point X, int Ymax){return X.Y>Ymax;}, slider1)
现在滑块1(slider1)的值就是参数Y的最大值。我们可以通过动态调节滑块的值来选择输入line1的点。

练习14:创建一个用户自定义的全局函数

在本次练习中,我们将在GC的函数库中创建一个可以在会话期间的任何时间被调用的全局函数。添加全局函数类似于在FunctionCall节点中添加函数,唯一的区别是我们要为分别为函数添加返回值类型和函数名。
  1. 将之前point1的函数复制出来。
  2. 打开GC的函数库。
  3. 在Functions对话框中,点击Create New Script Function按钮,程序会打开一个供我们添加新函数的脚本编辑器,如下图所示:

我们首先根据函数返回的内容定义返回值类型。在这里,我们将添加与第三部分中相同的函数来创建2D点列表,因此,函数的返回类型为Point。

  1. 在创建了函数的返回类型之后,我们将添加函数的名称。函数名称的命名应遵循和变量命名相同的原则。我们将这个函数命名为Point2DArray。
  2. 函数的形参和函数体部分与之前在FunctionCall节点中相同。

Point Point2DArray(int Row, int Column, double RowA, RowB, ColA, ColB, CoordinateSystem CS)
{
}
函数的其余部分都是相同的,可以直接从剪切板粘贴过来。

  1. 选择应用按钮保存函数并将它添加到函数库中。现在我们可以在函数库中找到我们新添加的函数。

在这个文件的整个会话中,我们可以在相应几何节点中使用ByFunction方法直接调用这个函数。我们的函数有返回类型Point,所以我们可以在Point节点内调用它。
我们也可以在其他的函数中直接调用全局函数。

全局函数可以被保存到GC环境中,这样我们就可以当前工作集下的其他文件中使用该函数。全局函数也可以被保存在程序包中,如下图所示:

5 查询表达式(Query Expresssions)

在本部分中,我们将学习如何使用查询表达式,以及如何使用这个简单的表达式来快速实现的我们的需求。
查询表达式(Query Expressions)
查询表达式提供了一种优雅而强大的用来检索由特定条件过滤、按特定方向排序或由特定计算处理的列表成员。
查询表达式的结果是一个新列表,它本身可以在任何可以使用列表的地方使用。
查询表达式的一般形式如下。方括号不是语法的一部分,表示可选的部分
GC脚本教程 - 图47
变量Variable – 是迭代变量的名称,它表示源列表的每个成员。我们可以任意命名该变量;该变量是自发创建的,并且是查询表达式的局部变量。
源列表sourceList – 所要查询的源列表。查询表达式不会更改其源列表的内容。
和GC中的其他内容一样,查询表达式可以写在一行上,也可以写在多行。多行通常比较好,因为它们更容易阅读。但是,这两种形式本质上没有区别。
GC脚本教程 - 图48
表达式的第一部分from语句表示访问源列表的每个成员。这里,源列表是line1, ln是用来表示源列表中每个成员的变量名,这个变量仅对给定的查询表达式是局部的。
第二部分,即select语句,表示查询表达式的条件部分。我们根据它获得新的成员列表。通过这一语句,我们想要line1中所有长度小于500的元素。where,是为查询表达式保留的一个特殊关键字。对于具有不同函数的查询表达式,还有其他保留关键字。在下面的语句中,我们将更多地了解它们。
Where关键字后跟一个表达式,我们可以得到表达式为真的那些成员组成的列表。
from ln in line1 where ln.Length < 500
orderby关键字后跟表达式,我们会得到一个由表达式中的参数排序后的新的排序列表。
from ln in line1 orderby ln.Length
上面的查询表达式根据线的长度生成一个新的升序列表。我们还可以在最后添加关键字descending(降序)对列表进行降序排序。
from ln in line1 orderby ln.Length descending
在select关键字后跟一个表达式,我们根据表达式中的对象类型获得一个新的列表。
from ln in line1 select ln.StartPoint
这个语句产生一个由给定列表中每条线的起点组成新的列表。这个结果与line1.StartPoint得到的结果相同。当我们将select与上面的关键字结合起来时,它是很有用的。
from ln in line1 where ln.Length < 500 select ln.StartPoint
这个语句的结果是在线的起始点中筛选出长度小于500的线的列表。
使用distinct关键字,我们可以从结果列表中删除重复的成员。
使用reverse关键字,可以逆转结果列表的顺序。
Skip关键字后跟一个整形数字n,得到的结果是跳过选择表达式结果前n个成员的新列表。
from pt in Point1 skip 2
以上语句返回的结果是跳过了前两个成员的新的point1的点列表。
Take关键字后跟一个整形数字n,得到的结果是仅有选择表达式结果前n个成员的新列表。
from pt in Point1 take 2
以上语句返回的结果是仅有前两个成员的新的point1的点列表。
以上七个小语句可以在不同的组合中一起使用。
from pt in Point1 orderby pt.X take 5 select pt.Y
关键字的执行顺序是从左往右。以上语句的功能是将point1中的每个点按照X值先从小到大排列,然后将新列表中前五个点的Y值组成的列表作为语句执行的结果返回。

练习15: 查询表达式

在本次练习中,我们将创建一个新的点列表并使用查询表达式与该列表互动。
  1. 创建一个新的dgn文件命名为Query Expressions.dgn。
  2. 点击Home功能区中Place Geometry工具栏下的Create baseCS按钮,选择Design Model并单击OK按钮接受。
  3. 在图表中创建一个方法为ByCartesianCoordinates的point节点,将baseCS节点连接到CoordinateSystem输入框中,在XTranslation输入框中填入Series(0,10000,1000)。

查询表达式可以用与任何节点的输入框。首先,我们将使用point1点列表中出了第一个和最后一个点之外的其他点创建长度相等的垂直与XY面的线。

  1. 创建一个方法为ByStartPointDirectionLength的线节点,Vertiecs输入框填入from pt in point1 take point1.Count-1 skip 1,Direction输入框填入 baseCS.Zdirection,Length输入框填入5000

  2. 录制事务。

接下来,我们将使用point1点列表中所有索引为奇数的点创建长度等其X坐标的垂直于XY平面的直线。
GC脚本教程 - 图49

可以在函数库中新建一个全局函数使用查询表达式来生成一个仅包含原始点列表中索引为偶数的点列表,作为后续操作的输入列表

  1. 在Functions对话框中点击Create New Script Function按钮,打开一个脚本编辑器创建我们的新全局函数:

GC脚本教程 - 图50

  1. 点击应用将函数保存到函数库中。
  2. 创建一个新的点节点point2。
  3. 方法设置为ByFunction
  4. 将节点的Function输入框设置为EvenPoints
  5. 将point1节点输出的点列表连接到point2节点的PointList输入框中。如下图所示,备选的索引为偶数的点被筛选出来。

在下一节中,我们会练习一些其他的查询表达式的示例。
在接下来的例子中,我们将做如下的假设:

  • Line1的之前定义的Line节点的名称
  • maxLength是之前定义的对象名称,表示线的最大长度。它可以是一个expression节点、一个滑块节点、一个函数的参数或者一个变量。

GC脚本教程 - 图51
GC脚本教程 - 图52