Многомерные списки
Добавим еще больше уровней в иерархию и углубимся в нашу кроличью нору. Структура данных может быть гораздо более объемной, чем простой двумерный список списков. Поскольку списки являются самостоятельными элементами в Dynamo, мы можем создать данные с практически неограниченным количеством измерений.
Это похоже на матрешку. Каждый список можно рассматривать как один контейнер, который содержит несколько элементов. Каждый список обладает собственными свойствами и рассматривается как отдельный объект.
Набор матрешек (фотография предоставлена Zeta) является аналогией многомерных списков. Каждый слой представляет список, и каждый список содержит элементы. В Dynamo каждый контейнер может содержать несколько контейнеров (представляющих элементы каждого списка).
Многомерные списки сложно объяснить визуально, но в данном разделе есть несколько упражнений, которые помогут вам разобраться в работе со списками, число измерений которых превышает два.
Сопоставление и комбинации
Сопоставление — возможно, самый сложный аспект управления данными в Dynamo, особенно когда речь идет о сложных иерархических структурах, состоящих из списков. В рамках приведенных ниже упражнений мы рассмотрим случаи, в которых следует использовать сопоставление и комбинации при работе с многомерными данными.
Основные сведения по работе с узлами List.Map и List.Combine можно найти в предыдущем разделе. Эти узлы будут использованы для работы со сложной структурой данных в последнем из приведенных ниже упражнений.
Упражнение. Двумерные списки. Основы
Скачайте файлы примера для этого упражнения (щелкните правой кнопкой мыши и выберите «Сохранить ссылку как...»). Полный список файлов примеров можно найти в приложении. 1.n-Dimensional-Lists.dyn 2.n-Dimensional-Lists.sat
Это первое из трех упражнений, направленных на работу с импортированной геометрией. От упражнения к упражнению структура данных будет усложняться.
- Начнем с файла SAT, расположенного в папке с файлами для упражнения. Добавим его в приложение с помощью узла File Path.
- Узел Geometry.ImportFromSAT импортирует геометрию в Dynamo и отображает ее в виде двух поверхностей.
Для простоты в этом упражнении вы будете работать только с одной поверхностью.
- Чтобы выбрать верхнюю поверхность, задайте индекс 1. Для этого добавьте узел List.GetItemAtIndex.
Теперь нужно преобразовать поверхность в сетку из точек.
- С помощью узла Code Block вставьте две следующие строки кода:
0..1..#10; 0..1..#5;
- Используя узел Surface.PointAtParameter, соедините два значения Code Block с портами ввода u и v. Задайте для параметра Переплетение этого узла значение декартово произведение.
- Полученная структура данных отображается в области предварительного просмотра Dynamo.
- Чтобы отобразить структуру данных, соедините узел NurbsCurve.ByPoints с портом вывода узла Surface.PointAtParameter.
- В области предварительного просмотра отображаются десять кривых, идущих вертикально вдоль поверхности.
- Базовый узел List.Transpose позволяет поменять местами столбцы и строки в списке списков.
- При соединении порта вывода узла List.Transpose с узлом NurbsCurve.ByPoints вы получите пять кривых, идущих горизонтально вдоль поверхности.
Упражнение. 2D-списки. Для опытных пользователей
Усложним задачу. Предположим, что нам нужно выполнить определенное действие с кривыми, которые мы получили в предыдущем упражнении. Например, нужно связать эти кривые с другой поверхностью и выполнить лофтинг между ними По сути, логика остается прежней, но задача требует более внимательной работы со структурой данных.
- Начнем с операции, уже знакомой вам по предыдущему упражнению. Изолируйте верхнюю поверхность импортированной геометрии с помощью узла List.GetItemAtIndex.
- Используя узел Surface.Offset, задайте значение 10, чтобы сместить поверхность.
- Как и в предыдущем упражнении, добавьте узел Code Block с двумя строками кода:
0..1..#10; 0..1..#5;
- Соедините порты вывода этого узла с двумя узлами Surface.PointAtParameter и задайте для параметра Переплетение каждого из них значение декартово произведение. Один из этих узлов соединен с исходной поверхностью, а второй — с поверхностью смещения.
- Как и в предыдущем упражнении, соедините порты вывода с двумя узлами NurbsCurve.ByPoints.
- В области предварительного просмотра Dynamo отображаются две кривые, соответствующие двум поверхностям.
- С помощью узла List.Create можно объединить два набора кривых в один список списков.
- В результате создаются два списка с десятью элементами, каждый из которых представляет собой связанный набор NURBS-кривых.
- С помощью узла Surface.ByLoft можно создать визуальное представление этой структуры данных. Узел выполняет лофтинг для всех кривых в каждом списке.
- Как вы помните, узел List.Transpose позволяет поменять местами столбцы и строки в списке списков. В результате использования этого узла два списка из десяти кривых каждый преобразуются в десять списков из двух кривых каждый. Теперь каждая NURBS-кривая связана с соседней кривой на другой поверхности.
- С помощью узла Surface.ByLoft мы получили реберную конструкцию.
- Вместо узла List.Transpose можно использовать узел List.Combine. Он выполняет роль «обьединителя» для каждого вложенного списка.
- В данном случае мы используем List.Create в качестве «обьединителя» для создания списка по каждому элементу во вложенных списках.
- Добавив узел Surface.ByLoft, мы получаем те же поверхности, что и в предыдущем шаге. В данном случае узел Transpose является более простым вариантом, но при работе с еще более сложной структурой данных надежнее будет использовать узел List.Combine.
- Вернемся на несколько шагов назад. Если вы хотите изменить ориентацию кривых в реберной конструкции, узел List.Transpose следует применить до соединения с узлом NurbsCurve.ByPoints. В результате столбцы и строки поменяются местами, и мы получим пять горизонтальных ребер.
Упражнение. Трехмерные списки
Продолжаем усложнять задачи. В этом упражнении мы используем обе импортированные поверхности, чтобы создать сложную иерархическую структуру данных. По сути, вам предстоит выполнить то же самое действие, пользуясь той же самой логикой, что и ранее.
- Вернемся к файлу, импортированному в предыдущем упражнении.
- Как и в предыдущем упражнении, используйте узел Surface.Offset, чтобы задать значение смещения, равное 10.
- Обратите внимание, что добавление узла смещения привело к созданию двух поверхностей.
- Как и в предыдущем упражнении, добавьте узел Code Block с двумя строками кода:
0..1..#20; 0..1..#10;
- Соедините порты вывода этого узла с двумя узлами 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.
- Добавим вспомогательную поверхность для этих двух конструкций. Используйте узел List.GetItemAtIndex, чтобы выбрать заднюю поверхность из поверхностей лофтинга, созданных в предыдущих шагах.
- Теперь увеличьте толщину выбранных поверхностей.
В результате мы получили нечто, похожее на слегка неустойчивое кресло-качалку. Зато сколько данных ушло на его создание!
Наконец, изменим направление бороздок. Для этого выполните процедуру, аналогичную преобразованию, которое вы уже использовали ранее.
- Так как здесь присутствует еще один уровень иерархии, то используйте узел List.Map с функцией List.Tranpose, чтобы изменить направление NURBS-кривых.
- Если требуется увеличить количество канавок, то данные узла Code Block можно изменить на следующие:
0..1..#20; 0..1..#10;
Если первая версия кресла-качалки была обтекаемой, то вторая получилась более похожей на колесо внедорожника.