列表是我们组织数据的方式。在计算机的操作系统上,有文件和文件夹。在 Dynamo 中,我们可以分别将它们视为项目和列表。与操作系统一样,可通过多种方法创建、修改和查询数据。在本章中,我们将分析如何在 Dynamo 中管理列表。
列表是元素或项目的集合。以一串香蕉为例。每个香蕉都是列表(或串)中的一个项目。拾取一串香蕉比单独拾取每个香蕉要容易得多,同样适用于通过数据结构中的参数化关系对元素进行分组。
照片由 Augustus Binu 提供。
当我们购买生活用品时,我们会将所有购买物品放入一个袋子中。这个袋子也是一个列表。如果我们要制作香蕉面包,需要 3 束香蕉(我们要制作 许多 香蕉面包)。袋子表示一列香蕉串,每串表示一列香蕉。袋子是一列列表(二维),香蕉串是一个列表(一维)。
在 Dynamo 中,会对列表数据进行排序,并且每个列表中第一项的索引均为“0”。下面,我们将讨论如何在 Dynamo 中定义列表以及如何将多个列表相互关联。
乍看起来可能有些奇怪的是,列表的第一个索引始终为 0,而不是 1。因此,当我们谈论列表的第一项时,实际上是指对应于索引 0 的项。
例如,如果要计算我们右手的手指数,则很有可能您的计数是 1 到 5。但是,如果要将手指放入列表,Dynamo 会为其指定索引 0 到 4。尽管这对于编程初学者来说似乎有些奇怪,但是从零开始的索引是大多数计算系统中的标准做法。
请注意,列表中仍有 5 个项目;只是列表使用的是基于零的计数系统。而且,列表中存储的项目并不仅限于数字。它们可以是 Dynamo 支持的任何数据类型,例如点、曲线、曲面、族等。
a.索引
b.点
c.项目
通常,查看列表中存储的数据类型的最简单方法是将“Watch”节点连接到另一个节点的输出。默认情况下,观察节点自动将所有索引显示在列表的左侧,并在右侧显示数据项。
这些索引是使用列表时的关键元素。
与列表相关,输入和输出因使用的 Dynamo 节点而异。例如,我们使用一列 5 个点,并将该输出连接到两个不同的 Dynamo 节点:”PolyCurve.ByPoints”和“Circle.ByCenterPointRadius”:
“PolyCurve.ByPoints” 的 “points” 输入正在查找 “Point[]”。这表示一列点
“PolyCurve.ByPoints” 的输出是基于一列五个点所创建的一条复合线。
“Circle.ByCenterPointRadius” 的 “centerPoint” 输入要求提供 “Point”。
“Circle.ByCenterPointRadius” 的输出是一列五个圆,其中心与点的原始列表相对应。
“PolyCurve.ByPoints” 和 “Circle.ByCenterPointRadius” 的输入数据相同,但 “Polycurve.ByPoints” 节点会提供一条复合线,而 “Circle.ByCenterPointRadius” 节点会提供 5 个圆(中心位于每个点处)。直观地讲,这很有意义:将复合线绘制为连接 5 个点的曲线,而圆在每个点处创建不同的圆。数据发生了什么变化?
通过将光标悬停在 “Polycurve.ByPoints” 的 “points” 输入上,我们会看到该输入正在查找 “Point[]”。请注意末端的括号。这表示一列点,并且要创建复合线,输入需要每个复合线是一个列表。因此,该节点会将每个列表压缩为一个复合线。
另一方面,“Circle.ByCenterPointRadius” 的 “centerPoint” 输入要求提供 “Point”。此节点会查找一个点作为项目,以定义圆的圆心。这就是我们基于输入数据获得五个圆的原因。在 Dynamo 中识别输入的这些差异有助于在管理数据时更好地了解节点的运行方式。
在没有清晰解决方案的情况下,数据匹配会是一个问题。当节点有权访问不同大小的输入时,就会发生这种情况。更改数据匹配算法可能会导致结果差异极大。
假定在各点之间创建线段的节点(“Line.ByStartPointEndPoint”)。它将有两个输入参数,两个输入参数均提供点坐标:
最简单的方法是逐一连接输入,直到其中一个流运行干。这称为“最短列表”算法。这是 Dynamo 节点的默认行为:
“最长列表”算法会一直连接输入、重用元素,直到所有流都流干为止:
最后,“笛卡尔积”方法可以建立所有可能的连接:
如您所见,我们可以通过不同的方式在这些点集之间绘制直线。通过在某个节点的中心上单击鼠标右键并选择“连缀”菜单,即可找到连缀选项。
单击下面的链接下载示例文件。
可以在附录中找到示例文件的完整列表。
为了演示下面的连缀操作,我们将使用此基础文件定义最短列表、最长列表和笛卡尔积。
我们将更改 “Point.ByCoordinates” 上的连缀,但不会更改有关上图的其他任何内容。
通过选择 “最短列表” 作为连缀选项(也是默认选项),我们会得到一条由五个点组成的基本对角线。五个点是较小列表的长度,因此最短列表连缀在到达一个列表的末尾后即停止。
通过将连缀更改为 “最长列表”,我们得到一条垂直延伸的对角线。采用与概念图相同的方法,将重复该列表的 5 个项目中的最后一项,以达到较长列表的长度。
通过将连缀更改为 “笛卡尔积”,我们得到每个列表之间的每个组合,从而获得 5x10 点栅格。这是与上述概念图中所示的笛卡尔积等效的数据结构,但数据现在是一列列表。通过连接复合线,我们可以看到每个列表均由其 X 值定义,从而得到一行垂直线。
既然我们已经建立了列表,那么让我们来介绍如何对它执行操作。将一个列表想象为一副纸牌。一副纸牌即是列表,每张纸牌表示一个项目。
照片由 Christian Gidlöf 提供
我们可以在列表中进行哪些查询?这将访问现有特性。
一副纸牌中纸牌的张数?52.
玩家人数?4.
材料?纸。
长度?3.5" 或 89mm。
宽度?2.5" 或 64mm。
我们可以对列表执行哪些操作?这将基于给定操作更改列表。
我们可以洗牌。
我们可以按值对一副纸牌进行排序。
我们可以按玩家对一副纸牌进行排序。
我们可以拆分一副纸牌。
我们可以通过发牌来划分一副纸牌。
我们可以选择一副纸牌中某张特定纸牌。
上面列出的所有操作都有类似 Dynamo 节点来用于处理常规数据列表。下面的课程将演示可以对列表执行的一些基本操作。
单击下面的链接下载示例文件。
可以在附录中找到示例文件的完整列表。
下图是我们在两个圆之间绘制直线以表示基本列表操作的基础图形。我们将探讨如何管理列表中的数据,并通过下面的列表操作演示可视结果。
从 “代码块” 开始,其中值为
500;
连接到 “Point.ByCoordinates” 节点的 x 输入。
将上一步中的节点连接到 “Plane.ByOriginNormal” 节点的原点输入。
使用 “Circle.ByPlaneRadius” 节点,将上一步中的节点连接到平面输入。
使用 “代码块” ,为半径指定值
50;
。这是我们将创建的第一个圆。使用 “Geometry.Translate” 节点,将圆沿 Z 方向向上移动 100 个单位。
使用 “Code Block” 节点,通过以下一行代码定义一系列 10 个介于 0 和 1 之间的数字:
0..1..#10;
将上一步中的代码块连接到两个 “Curve.PointAtParameter” 节点的 “param” 输入。将 “Circle.ByPlaneRadius” 插入到顶部节点的曲线输入,并将 “Geometry.Translate” 连接到其下节点的曲线输入。
使用 “Line.ByStartPointEndPoint” ,连接两个 “Curve.PointAtParameter” 节点。
单击下面的链接下载示例文件。
可以在附录中找到示例文件的完整列表。
“List.Count” 节点简单明了:它计算列表中值的数量,并返回该数量。随着我们使用列表的列表,此节点会变得更加微妙,但我们会在接下来的各部分中进行演示。
“List.Count”**** 节点会返回 “Line.ByStartPointEndPoint” 节点中线的数量。在本例中,该值为 10,表示与从原始 “Code Block” 节点创建的点数一致。
单击下面的链接下载示例文件。
可以在附录中找到示例文件的完整列表。
“List.GetItemAtIndex” 是用于查询列表中项的基本方法。
首先,在 “Line.ByStartPointEndPoint” 节点上单击鼠标右键以关闭其预览。
使用 “List.GetItemAtIndex” 节点,我们选择索引 “0” 或线列表中的第一项。
将滑块值更改为介于 0 和 9 之间,以使用 “List.GetItemAtIndex” 选择其他项目。
单击下面的链接下载示例文件。
可以在附录中找到示例文件的完整列表。
“List.Reverse” 可反转列表中所有项的顺序。
要正确显示反转的线列表,请通过将 “代码块” 更改为
0..1..#50;
来创建更多线复制 “Line.ByStartPointEndPoint” 节点,在 “Curve.PointAtParameter” 和第二个 “Line.ByStartPointEndPoint” 之间插入“List.Reverse”节点
使用 “Watch3D” 节点预览两个不同的结果。第一个显示没有反向列表的结果。这些线垂直连接到相邻点。但是,反转列表会将所有点以相反顺序连接到其他列表。
单击下面的链接下载示例文件。
可以在附录中找到示例文件的完整列表。
“List.ShiftIndices” 是适用于创建扭曲或螺旋图案或者任何其他类似数据操作的工具。此节点会将列表中的项目移动给定数量的索引。
在与反转列表相同的过程中,将 “List.ShiftIndices” 插入到 “Curve.PointAtParameter” 和 “Line.ByStartPointEndPoint” 中。
使用 “代码块”,指定值为“1”以将列表移动一个索引。
请注意,更改很细微,但在连接到另一组点时,较低 “Watch3D” 节点中的所有线都已移动一个索引。
例如,通过将 “代码块” 更改为较大值(“30”),我们注意到对角线存在明显差异。在本例中,该移动类似于照相机的光圈,从而以原始圆柱形式创建扭曲。
单击下面的链接下载示例文件。
可以在附录中找到示例文件的完整列表。
“List.FilterByBooleanMask” 将基于布尔值列表移除某些项目,或通过读取“true”或“false”值来移除某些项目。
为了创建读取“true”或“false”的值列表,我们需要做更多的工作...
使用 “代码块”,通过以下语法定义一个表达式:
0..List.Count(list);
。将 “Curve.PointAtParameter” 节点连接到 “list” 输入。我们将在代码块章节中详细介绍此设置,但本例中的该行代码会为我们提供一个列表,该列表表示 ”Curve.PointAtParameter” 节点的每个索引。使用 “%” **(求模)**节点,将 代码块 的输出连接到 x 输入,将值 4 连接到 y 输入。当将索引列表除以 4 时,这将为我们提供余数。求模节点对于创建图案而言确实非常有用。所有值将读取为 4 的可能余数:0、1、2、3。
在 “%” (求模) 节点中,我们知道值为 0 意味着索引是 4 的倍数(0、4、8,依此类推)。通过使用 “==” 节点,我们可以针对值 “0” 对其进行测试,以测试其可除性。
“Watch” 节点仅显示以下情况:我们有一个“true/false”模式,其读取:true,false,false,false...。
使用此 true/false 模式,连接到两个 “List.FilterByBooleanMask” 节点的遮罩输入。
将 “Curve.PointAtParameter” 节点连接到 “List.FilterByBooleanMask” 的每个列表输入。
“Filter.ByBooleanMask” 的输出读取 “in” 和 “out”。“in” 表示遮罩值为 “true” 的值,而 “out” 表示值为 “false” 的值。通过将 “in” 输出连接到 “Line.ByStartPointEndPoint” 节点的 “startPoint” 和 “endPoint” 输入,我们创建了过滤后的线列表。
“Watch3D” 节点显示线数少于点数。通过仅过滤 true 值,我们仅选择了 25% 的节点!
让我们再为层次结构添加一个层级。如果我们从原始示例中获取数据卡组并创建包含多个数据卡组的框,则该框现在表示一列数据卡组,每个数据卡组表示一列数据卡。这是一列列表。在本节的类比中,下图包含一列硬币卷,每个卷包含一列便士。
照片由 Dori 拍摄。
我们可以在该列列表中进行哪些查询?这将访问现有特性。
硬币类型的数量?2.
硬币类型值?$0.01 和 $0.25。
两角五分的材料?75% 铜和 25% 镍。
便士材料?97.5% 锌和 2.5% 铜。
我们可以对该列列表执行哪些操作?这会根据给定的操作更改该列列表。
选择一叠特定的两角五分或便士。
选择一个特定的两角五分或便士。
重新排列各叠两角五分和便士。
将各叠堆叠在一起。
同样,Dynamo 为上述每项操作都提供了一个分析节点。由于我们处理的是抽象数据而不是物理对象,因此我们需要一组规则来控制如何上下移动数据层次结构。
在处理列表的列表时,数据是分层且复杂的,但这使得有机会执行一些很棒的参数化操作。让我们来分解基础知识,并在下面的课程中再讨论几项操作。
单击下面的链接下载示例文件。
可以在附录中找到示例文件的完整列表。
要从本部分中了解的基本概念:Dynamo 将列表视为自身内部和自身的对象。这种自上而下层次结构是在考虑面向对象编程的情况下开发的。Dynamo 会选择数据结构中主列表的索引,而不是使用诸如 “List.GetItemAtIndex” 之类的命令选择子元素。该项可以是另一个列表。让我们用示例图像进行分解:
使用 “代码块”,我们已定义两个范围:
0..2; 0..3;
这些范围连接到 “Point.ByCoordinates” 节点,其中连缀设置为 “叉积”。这将创建点栅格,并且还会返回一列列表作为输出。
请注意,“Watch” 节点提供 3 个列表,其中每个列表中有 4 个项目。
使用 “List.GetItemAtIndex” 时,在索引为 0 的情况下,Dynamo 会选择第一个列表及其所有内容。其他程序可能会选择数据结构中每个列表的第一个项目,但 Dynamo 在处理数据时采用自上而下层次结构。
单击下面的链接下载示例文件。
可以在附录中找到示例文件的完整列表。
“展平”会从数据结构中删除所有层级的数据。这在操作不需要数据层次结构时非常有用,但由于它会删除信息,因此可能存在风险。下面的示例显示了展平一列数据的结果。
在 “代码块” 中插入一行代码以定义一个范围:
-250..-150..#4;
通过将 “代码块” 插入到 “Point.ByCoordinates” 节点的 “x” 和 “y” 输入,我们会将连缀设置为 “叉积” 以获取点栅格。
“Watch” 节点显示我们有一列列表。
“PolyCurve.ByPoints” 节点将引用每个列表并创建相应的复合线。请注意,在 Dynamo 预览中,我们有四条复合线分别表示栅格中的每一行。
通过在复合线节点之前插入 “展平”,我们为所有点创建了一个列表。“PolyCurve.ByPoints” 节点引用列表来创建一条曲线,并且由于所有点都在一个列表中,因此我们得到了一条锯齿形复合线,该复合线贯穿整个点列表。
还有用于展平孤立层级数据的选项。使用 “List.Flatten” 节点,可以定义一定数量的数据层级,以从层次结构的顶部展平。如果要处理的复杂数据结构不一定与工作流相关,那么这是一个非常有用的工具。另一个选择是在 “List.Map” 中将展平节点用作函数。我们将在下面详细介绍 “List.Map”。
单击下面的链接下载示例文件。
可以在附录中找到示例文件的完整列表。
使用参数化建模时,有时您还希望将修改现有列表的数据结构。此外,还有许多节点可用于此操作,其中最基本的版本是“切除”。使用“切除”,我们可以将一个列表划分为具有一定数量项目的子列表。
“切除”命令会根据给定的列表长度来分割列表。在某些方面,切除与展平相反:它不是删除数据结构,而是向其中添加新的层级。这是一个有助于执行几何操作(如以下示例)的工具。
单击下面的链接下载示例文件。
可以在附录中找到示例文件的完整列表。
“List.Map/Combine” 会将设置的函数应用于输入列表,但在层次结构中向下一步。组合与贴图相同,但组合可以具有与给定函数的输入相对应的多个输入。
注意:此练习是使用 Dynamo 的先前版本创建的。通过添加“List@Level”功能,“List.Map”的大部分功能已经解决。有关详细信息,请参见 下面 的“List@Level”。
通过简单介绍一下,我们来回顾上一节中的 “List.Count” 节点。
“List.Count” 节点对列表中的所有项目进行计数。我们将使用此节点来演示 “List.Map” 如何工作。
将两行代码插入到 “代码块”:
-50..50..#Nx; -50..50..#Ny;
在键入此代码后,代码块将为 Nx 和 Ny 创建两个输入。
使用两个 整数滑块,通过将它们连接到 “代码块” 来定义 “Nx” 和 “Ny” 值。
将代码块的每行连接到 “Point.ByCoordinates” 节点的相应 “X” 和 “Y” 输入。在节点上单击鼠标右键,选择“连缀”,然后选择 “叉积”。这将创建点栅格。因为我们定义的范围是 -50 到 50,所以我们跨越了默认的 Dynamo 栅格。
“Watch” 节点显示所创建的点。请注意数据结构。我们已创建一列列表。每个列表都表示栅格的一行点。
将上一步中的 “List.Count” 节点附加到“Watch”节点的输出。
将 “Watch” 节点连接到 “List.Count” 输出。
请注意,“List.Count”节点提供的值为“5”。这等于代码块中所定义的“Nx”变量。这是为什么呢?
首先,“Point.ByCoordinates” 节点使用“x”输入作为用于创建列表的主输入。当 Nx 为 5 且 Ny 为 3 时,我们得到一列 5 个列表,每个列表都包含 3 个项目。
由于 Dynamo 将列表视为自身内部和自身的对象,因此 “List.Count” 节点会应用于层次结构中的主列表。结果为值 5 或主列表中列表的数量。
通过使用 “List.Map” 节点,我们在层次结构中向下一步,然后在此级别上执行 “函数”。
请注意,“List.Count” 节点没有输入。它将用作一个函数,因此 “List.Count” 节点将应用于层次结构中向下一步的每个单独列表。“List.Count” 的空白输入对应于 “List.Map” 的列表输入。
“List.Count” 的结果现在提供一列 5 个项目,每个项目的值为 3。这表示每个子列表的长度。
注意:此练习是使用 Dynamo 的先前版本创建的。通过添加“List@Level”功能,“List.Combine”的大部分功能已经解决。有关详细信息,请参见下面的“List@Level”。
在本练习中,我们将使用 “List.Combine” 演示如何使用它来在单独的对象列表中应用函数。
首先,设置两个点列表。
使用 “Sequence” 节点生成 10 个值,每个值都有 10 步增量。
将结果连接到 “Point.ByCoordinates” 节点的 x 输入。这将在 Dynamo 中创建点列表。
将第二个 “Point.ByCoordinates” 节点添加到工作空间、使用相同的 “Sequence” 输出作为其 x 输入,但使用 “Interger Slider” 作为其 y 输入并将其值设置为 31(它可以是任何值,只要它们不与第一组点重叠),这样 2 组点就不会相互重叠。
接下来,我们将使用 “List.Combine” 对 2 个单独列表中的对象应用函数。在本例中,它将是一个简单的绘制线函数。
将 “List.Combine” 添加到工作空间,并连接 2 组点作为其 list0 和 list1 输入。
使用 “Line.ByStartPointEndPoint” 作为 “List.Combine” 的输入函数。
完成后,通过 “Line.ByStartPointEndPoint” 函数将 2 组点压缩/成对组合在一起,并在 Dynamo 中返回 10 行。
请参见 n 维列表中的练习,以查看使用“List.Combine”的另一个示例。
单击下面的链接下载示例文件。
可以在附录中找到示例文件的完整列表。
相较于 “List.Map”,“List@Level” 功能允许直接选择要在节点的输入端口上使用的列表级别。此功能可应用于节点的任何传入输入,并让您可以更快、更容易地访问列表的各级别(相较于其他方法)。只需告诉节点要使用列表的哪个级别作为输入,然后让节点执行其余操作即可。
在本练习中,我们将使用 “List@Level” 功能隔离特定级别的数据。
我们将从一个简单的三维点栅格开始。
该栅格使用 X、Y 和 Z 范围构建,因此我们知道数据结构由 3 个层级组成:X 列表、Y 列表和 Z 列表。
这些层级存在于不同的级别上。级别显示在预览气泡的底部。“列表级别”列与上述列表数据相对应,以帮助确定要在哪个级别工作。
“列表级别”按相反顺序进行组织,以便最低级别数据始终位于“L1”。这将有助于确保图形按计划工作,即使上游发生任何更改也是如此。
要使用 “List@Level” 函数,请单击“>”。在此菜单中,您会看到两个复选框。
使用级别 - 这会启用 “List@Level” 功能。单击此选项后,将能够点进,然后选择希望节点使用的输入列表级别。使用此菜单,可以通过单击上下箭头来快速试用不同的级别选项。
保持列表结构 - 如果已启用,则可以选择保持该输入的级别结构。有时,您可能会有目的地将数据组织到子列表中。选中此选项,即可使列表组织保持完整,而不会丢失任何信息。
使用简单的三维栅格,我们可以通过切换“列表级别”来访问和可视化列表结构。每个列表级别和索引组合将从原始三维集中返回一组不同的点。
DesignScript 中的“@L2”允许我们仅选择级别 2 的列表。级别 2 列表(索引为 0)仅包含第一组 Y 点,从而仅返回 XZ 栅格。
如果将级别过滤器更改为“L1”,则我们将能够看到第一列表级别中的所有内容。级别 1 列表(索引 0)将所有三维点都包括在一个展平列表中。
如果我们尝试对“L3”执行相同操作,则我们仅会看到第三列表级别点。级别 3 列表(索引为 0)仅包含第一组 Z 点,从而仅返回 XY 栅格。
如果我们尝试对“L4”执行相同操作,则我们仅会看到第三列表级别点。级别 4 列表(索引为 0)仅包含第一组 X 点,从而仅返回 YZ 栅格。
尽管也可以使用 “List.Map” 创建此特定示例,但 “List@Level” 会极大地简化交互,从而可以轻松访问节点数据。请在下面查看 “List.Map” 和 “List@Level” 方法的比较:
尽管这两种方法都将允许我们访问相同的点,但 “List@Level” 方法允许我们轻松地在一个节点内的数据层之间切换。
要使用 “List.Map” 访问点栅格,我们需要使用 “List.GetItemAtIndex” 节点以及 “List.Map”。对于我们要向下步进的每个列表级别,我们需要使用额外的 “List.Map” 节点。根据列表的复杂程度,这可能需要将大量 “List.Map” 节点添加到图形中,才能访问正确级别的信息。
在此示例中,“List.GetItemAtIndex” 节点与 “List.Map” 节点结合使用会返回列表结构与 “List.GetItemAtIndex”(在选择“@L3”的情况下)相同的一组相同点。
单击下面的链接下载示例文件。
可以在附录中找到示例文件的完整列表。
“Transpose”是一个处理列表的列表时的基本函数。与在电子表格程序中一样,转置会翻转数据结构的列和行。我们将在下面的基本矩阵中对此进行演示,并且在以下部分中我们将演示如何使用转置来创建几何关系。
让我们从上一个练习中删除 “List.Count” 节点,然后转到一些几何图形以查看数据的结构。
从 “Point.ByCoordinates” 将 “PolyCurve.ByPoints” 连接到“Watch”节点的输出。
输出会显示 5 条复合线,我们可以在 Dynamo 预览中看到这些曲线。Dynamo 节点将查找一列点(或在本例中为一列点列表)并基于它们创建一条复合线。实际上,每个列表已转换为数据结构中的曲线。
“List.Transpose” 节点将切换一列列表中所有列表的所有项目。这听起来很复杂,但其逻辑与 Microsoft Excel 中的“转置”相同:在数据结构中切换列和行。
请注意抽象结果:“转置”将列表结构从 5 列(每列 3 个项目)更改为 3 列(每列 5 个项目)。
请注意几何结果:使用 “PolyCurve.ByPoints”,我们在与原始曲线的垂直方向上获得 3 条复合线。
代码块简写使用“[]”来定义列表。与 “List.Create” 节点相比,这种方法可更快、更流畅地创建列表。代码块会在 “代码块和 DesignScript” 中进行更详细的介绍。请参照下图,以注意如何使用代码块定义具有多个表达式的列表。
代码块简写使用“[]”作为要从复杂数据结构中选择所需特定项目的快速简便方法。代码块会在“代码块和 DesignScript”一章中进行更详细的介绍。请参照下图,以注意如何使用代码块查询具有多个数据类型的列表。
单击下面的链接下载示例文件。
可以在附录中找到示例文件的完整列表。
本练习使用在上一个练习中建立的某些逻辑来编辑曲面。我们在此处的目标一目了然,但将更多涉及数据结构导航。我们希望通过移动控制点来接合曲面。
从上述节点字符串开始。我们将创建一个跨越默认 Dynamo 栅格的基本曲面。
使用 “代码块”,插入以下两行代码并分别连接到 “Surface.PointAtParameter” 的 “u” 和 “v” 输入:
-50..50..#3;
-50..50..#5;
确保将 “Surface.PointAtParameter” 的“连缀”设置为 “叉积”。
“Watch” 节点显示我们有一列 3 个列表(每个列表都含有 5 个项目)。
在此步骤中,我们要在已创建的栅格中查询中心点。为此,我们将选择中间列表中的中间点。有道理,对吧?
要确认这一点是正确的,我们还可以单击“Watch”节点项目来确认我们面向的目标是正确的。
使用 “代码块”,我们将编写一行基本代码,用于查询一列列表:
points[1][2];
使用 “Geometry.Translate”,我们会将选定点在 Z 方向上上移 20 个单位。
我们还要使用 “List.GetItemAtIndex” 节点选择中间行的点。注意:与上一步类似,我们还可以使用 “代码块”,通过一行代码
points[1];
查询列表
到目前为止,我们已成功查询中心点并将其向上移动。现在,我们需要将此移动的点插回原始数据结构。
首先,我们要替换在上一步中隔离的列表项。
使用 “List.ReplaceItemAtIndex”,我们会将使用且索引为 “2” 的中间项替换为与移动的点( “Geometry.Translate” )相连的替换项。
输出显示我们已将移动的点输入到列表的中间项。
现在,我们已经修改了列表,我们需要将此列表插回原始数据结构:列表的列表。
遵循相同的逻辑,使用 “List.ReplaceItemAtIndex” 将中间列表替换为我们修改的列表。
请注意,为这两个节点定义索引的 “代码块” 为 1 和 2,这与 “代码块” (points[1][2]) 中的原始查询匹配。
通过选择 “索引 1” 处的列表,我们会看到数据结构在 Dynamo 预览中亮显。我们已成功将移动的点合并到原始数据结构中。
基于这组点生成曲面的方法有多种。在本例中,我们将通过一起放样曲线来创建曲面。
创建 “NurbsCurve.ByPoints” 节点并连接新的数据结构,来创建三条 NURBS 曲线。
将 “Surface.ByLoft” 连接到 “NurbsCurve.ByPoints” 的输出。现在,我们得到了一个修改的曲面。我们可以更改几何图形的原始 Z 值。平移并观察几何图形更新!
再往下钻,让我们为层次结构添加更多层。数据结构可以扩展到远超二维列表的列表。由于列表是 Dynamo 中的项目,而且它们本身也是项目,因此我们可以创建尽可能多维的数据。
我们将在此处使用的类比是俄罗斯套娃。每个列表可视为一个包含多个项的容器。每个列表都有自己的特性,也被视为自己的对象。
一组俄罗斯套娃(照片由 Zeta 提供)是 n 维列表的类比。每个层表示一个列表,每个列表在其中包含项目。在 Dynamo 的情况下,每个容器内可以有多个容器(表示每个列表的项目)。
n 维列表很难用直观的方式进行解释,但是我们在本章中设置了一些练习,这些练习着重于处理超出二维范围的列表。
映射无疑是 Dynamo 中数据管理最复杂的部分,并且在处理列表的复杂层次结构时尤其重要。在下面的一系列练习中,我们将演示在数据变为多维时何时使用映射和组合。
在上一节中,可以找到 “List.Map” 和 “List.Combine” 的初步介绍。在下面的最后一个练习中,我们将对复杂数据结构使用这些节点。
单击下面的链接下载示例文件。
可以在附录中找到示例文件的完整列表。
本练习是三个练习中的第一个,侧重于阐述输入的几何图形。本系列练习中的每个部分都将增加数据结构的复杂性。
让我们从练习文件文件夹中的“.sat”文件开始。我们可以使用 “File Path” 节点抓取此文件。
使用 “Geometry.ImportFromSAT”,该几何图形将作为两个曲面输入到 Dynamo 预览中。
在本练习中,我们希望保持简单并处理其中一个曲面。
让我们选择索引 1,以抓取上方曲面。我们使用 “List.GetItemAtIndex” 节点来执行此操作。
关闭 “Geometry.ImportFromSAT” 预览中的几何图形预览。
下一步是将曲面分割为点栅格。
1.使用 “代码块”,插入以下两行代码:
0..1..#10;
0..1..#5;
2.使用 “Surface.PointAtParameter”,将两个代码块值连接到 u 和 v。将此节点的 “连缀” 更改为 “叉积”。
3.输出显示数据结构,这在 Dynamo 预览中也可见。
接下来,使用上一步中的点以沿曲面生成十条曲线。
要了解数据结构的组织方式,我们将 “NurbsCurve.ByPoints” 连接到 “Surface.PointAtParameter” 的输出。
现在,可以关闭 “List.GetItemAtIndex” 节点的预览,以获得更清晰的结果。
基本 “List.Transpose” 将翻转一列列表的列和行。
通过将 “List.Transpose” 的输出连接到 “NurbsCurve.ByPoints”,我们现在得到五条曲线在整个曲面上水平延伸。
可以在上一步中关闭 “NurbsCurve.ByPoints” 节点的预览,以在图像中获得相同的结果。
让我们增加复杂性。假定我们要对上一个练习中创建的曲线执行操作。也许,我们希望将这些曲线与其他曲面相关联,并在它们之间进行放样。这需要更加注意数据结构,但基本逻辑是相同的。
从上一练习的步骤开始,使用 “List.GetItemAtIndex” 节点隔离已输入几何图形的上曲面。
使用 “Surface.Offset”,将曲面偏移值 “10”。
按照与上一练习相同的方式,使用以下两行代码定义 “代码块”:
0..1..#10;
0..1..#5;
将这些输出连接到两个 “Surface.PointAtParameter” 节点,每个节点的 “连缀” 设置为 “叉积”。其中一个节点连接到原始曲面,而另一个节点连接到偏移曲面。
关闭这些曲面的预览。
与上一练习中一样,将输出连接到两个 “NurbsCurve.ByPoints” 节点。结果显示与两个曲面对应的曲线。
通过使用 “List.Create”,我们可以将两组曲线合并为一列列表。
在输出中注意到,我们有两个列表,其中每个列表都包含十个项目,分别表示每个 NURBS 曲线的连接集。
通过执行 “Surface.ByLoft”,我们可以直观地了解此数据结构。该节点将放样每个子列表中的所有曲线。
在上一步中,关闭 “Surface.ByLoft” 节点的预览。
通过使用 “List.Transpose”,请记住,我们将翻转所有列和行。此节点会将两列(每个列表十条曲线)转换为十列(每个列表两条曲线)。现在,我们得到与另一个曲面上的相邻曲线相关的每条 NURBS 曲线。
使用 “Surface.ByLoft”,我们得到一个带肋的结构。
接下来,我们将演示实现此结果的替代流程
在开始之前,请在上一步中关闭 “Surface.ByLoft” 预览以避免混淆。
除 “List.Transpose” 之外,还可以使用 “List.Combine”。这将对每个子列表运算 “连结符”。
在本例中,我们使用 “List.Create” 作为 “连结符”,这将在子列表中创建每个项目的列表。
使用 “Surface.ByLoft” 节点,我们得到与上一步中相同的曲面。在这种情况下,转置更容易使用,但当数据结构变得更加复杂时,“List.Combine” 更加可靠。
如果要切换带肋结构中曲线的方向,请后退几步,我们需要先使用 “List.Transpose”,然后再连接到 “NurbsCurve.ByPoints”。这将翻转列和行,从而得到 5 个水平加强筋。
现在,我们将更进一步。在本练习中,我们将使用两个输入的曲面,从而创建复杂的数据层次结构。尽管如此,我们的目标是使用相同的基础逻辑来完成相同的操作。
从上一练习中输入的文件开始。
与上一练习中一样,使用 “Surface.Offset” 节点按值 “10” 进行偏移。
在输出中注意到,我们创建了两个具有偏移节点的曲面。
按照与上一练习相同的方式,使用以下两行代码定义 “代码块”:
0..1..#20;
0..1..#20;
将这些输出连接到两个 “Surface.PointAtParameter” 节点,每个节点的连缀设置为 “叉积”。其中一个节点连接到原始曲面,而另一个节点连接到偏移曲面。
与上一练习中一样,将输出连接到两个 “NurbsCurve.ByPoints” 节点。
查看 “NurbsCurve.ByPoints” 的输出,注意到这是一列两个列表,比上一练习更复杂。数据按基础曲面分类,因此我们为结构化数据添加了另一个层级。
请注意,“Surface.PointAtParameter” 节点中的对象变得更加复杂。在本例中,我们会看到一列列表。
在继续操作之前,请关闭现有曲面的预览。
使用 “List.Create” 节点,我们将 NURBS 曲线合并为一个数据结构,从而创建一列列表(其中每个元素也是一个列表)。
通过连接 “Surface.ByLoft” 节点,我们得到原始曲面的版本,因为它们各自保留在由原始数据结构创建的自己列表中。
在上一练习中,我们能够使用 “List.Transpose” 创建带肋结构。这在此处不起作用。对二维列表应使用转置,但由于我们有三维列表,因此“翻转列和行”操作不会像之一样轻松。请记住,列表是对象,因此 “List.Transpose” 将翻转包含子列表的列表,但不会将 NURBS 曲线在层次结构中进一步向下翻转一个列表。
“List.Combine” 在此处将更加适用。当访问更复杂的数据结构时,我们要使用 “List.Map” 和 “List.Combine” 节点。
使用 “List.Create” 作为 “连结符”,我们可以创建一个数据结构,使其更加适用。
数据结构仍需要在层次结构上向下转置一步。为此,我们将使用 “List.Map”。除了使用一个输入列表(而不是两个或更多)之外,这类似于使用 “List.Combine”。
我们将应用于 “List.Map” 的函数是 “List.Transpose”,这将翻转主列表中子列表的列和行。
最后,我们可以结合使用正确的数据层次结构放样 NURBS 曲线,从而提供带肋结构。
我们使用 “Surface.Thicken” 节点和输入设置为几何图形添加一些深度,如图所示。
最好添加一个曲面来支撑这两个结构,因此请添加另一个 “Surface.ByLoft” 节点,并使用上一步中 “NurbsCurve.ByPoints” 的第一个输出作为输入。
随着预览变得混乱,请通过在每个节点上单击鼠标右键并取消选中“预览”以关闭这些节点的预览,以便更好地查看结果。
加厚这些选定曲面,完成连接。
这不是有史以来最舒适的摇椅,但还会进行大量数据处理。
最后一步,我们反转带条纹成员的方向。如在上一练习中使用转置一样,我们将在此处执行类似操作。
由于我们的层次结构中还有一层级,因此我们需要将 “List.Map” 与 “List.Tranpose” 函数一起使用来更改 NURBS 曲线的方向。
我们可能希望增加踏板数,因此可以将 “代码块” 更改为
0..1..#20;
0..1..#30;
摇椅的第一个版本很流畅,因此我们的第二个模型提供了越野、运动多功能版本的靠背。