Чтобы углубиться в процесс разработки визуальных программ, нам потребуется более тонкое понимание того, что представляют собой компоновочные блоки программ. В этой главе описываются основные понятия, относящиеся к данным, проходящим по проводам программы Dynamo.
Логика (а точнее условная логика) позволяет задать действие или набор действий в зависимости от результата проверки. После прохождения проверки выдается логическое значение True
или False
, которое можно использовать для управления ходом программы.
Числовые переменные могут хранить целый диапазон различных чисел. В логических переменных хранятся только два значения: «Истина» или «Ложь», да или нет, 1 или 0. Из-за ограниченной применимости логические операции можно не так часто встретить в расчетах.
Выражение «If» является ключевым для программирования. Если некое условие истинно, то происходит что-то одно; в противном случае происходит что-то другое. Действие, выполняемое после проверки с помощью данного выражения, зависит от логического значения. Существует несколько способов определения выражения If в Dynamo.
If (If)
test, true, false
результат
Formula (IF(x,y,z))
x, y, z
результат
Code Block ((x?y:z);)
X, Y, Z
результат
Рассмотрим краткий пример с каждым из этих трех узлов в действии, используя условное выражение If.
На этом изображении в узле boolean задано значение true. Это означает, что на выходе появится строка this is the result if true (это результат при истинном значении). Три узла, образующие выражение If, работают одинаково.
Напомним, что узлы работают одинаково. Если для boolean изменить значение на false, результатом будет число пи, как определено в исходном операторе If.
Скачайте файл с примером, щелкнув ссылку ниже.
Полный список файлов с примерами можно найти в приложении.
Используем логику, чтобы разделить список чисел на список четных и список нечетных чисел.
a. Number Range. Добавление диапазона чисел в рабочую область.
b. Numbers. Добавление трех узлов Number в рабочую область. Каждый узел Number должен иметь следующие значения: 0.0 для start, 10.0 для end и 1.0 для step
c. Output. На выходе получается список из 11 чисел в диапазоне от 0 до 10.
d. Modulo (%). Диапазон номеров в качестве входных данных для x и значение 2.0 в качестве входных данных для y. При этом рассчитывается остаток каждого числа в списке при делении на 2. На выходе из этого списка будет представлен список чередующихся значений 0 и 1.
e. Equality Test (==). Добавление в рабочую область проверки равенства. Соедините выходные данные modulo с входным параметром x, а значение 0.0 с входным параметром y.
f. Watch. В качестве выходных данных проверки равенства будет представлен список значений «Истина» (true) и «Ложь» (false). С помощью этих значений элементы будут разделяться в списке. 0 (или true) соответствует четным числам, а 1 (или false) — нечетным.
g. List.FilterByBoolMask. Этот узел отфильтровывает значения по двум разным спискам в зависимости от вводимого логического выражения. Соедините исходный диапазон чисел с входным параметром list, а выходной параметр проверки равенства с входным параметром mask. В выходных данных in представлены истинные значения, а в out — ложные.
h. Watch. В результате мы получили списки четных и нечетных чисел. Итак, с помощью логических операторов мы разделили списки по определенному признаку.
Применим логику из первого упражнения к моделированию.
2. За основу возьмем предыдущее упражнение с теми же узлами. Помимо изменения формата, единственными исключениями будут следующие.
a. Используйте узел Sequence с этими входными значениями.
b. Отсоединен входной параметр list от узла List.FilterByBoolMask. Эти узлы пока не нужны, но они потребуются позже.
3. Начнем с создания отдельной группы Graph, как показано на изображении выше. Эта группа узлов представляет собой параметрическое уравнение для определения линейной кривой. Примечания.
a. Первый регулятор Number Slider представляет частоту волны в диапазоне от 1 до 4 с шагом 0,01.
b. Второй регулятор Number Slider представляет амплитуду волны в диапазоне от 0 до 1 с шагом 0,01.
c. PolyCurve.ByPoints. Если скопировать приведенную выше схему узлов, на видовом экране предварительного просмотра Dynamo будет создана синусоидальная кривая.
При вводе данных используйте числовые узлы для более статических свойств и регуляторы чисел для более гибких свойств. Необходимо сохранить исходный диапазон чисел, который определяется в начале этого шага. Однако синусоидальная кривая, которую мы пытаемся создать, должна обладать определенной гибкостью. Перемещая регуляторы, можно видеть частотные и амплитудные изменения кривой.
4. Забежим немного вперед и посмотрим на конечный результат, чтобы представить, каким он должен быть. Первые два шага выполняются отдельно, теперь их нужно соединить. С помощью базовой синусоидальной кривой будет определяться местоположение компонентов молнии, а с помощью логики «истина/ложь» — элементы меньшего или большего размера.
a. Math.RemapRange. С помощью последовательности чисел, созданной на шаге 02, сформируем новую последовательность чисел, перенастроив диапазон. Исходные числа из шага 01 имеют диапазон от 0 до 100. С помощью входных параметров newMin и newMax диапазон значений изменяется на 0–1 соответственно.
5. Создайте узел Curve.PointAtParameter, а затем соедините выходной параметр Math.RemapRange из шага 04 с входным параметром param.
На этом шаге создаются точки вдоль кривой. Диапазон чисел был перенастроен на 0–1, так как входной параметр param ищет значения в этом диапазоне. Значение 0 соответствует начальной точке, а значение 1 — конечным точкам. Все промежуточные числа относятся к диапазону [0,1].
6. Соедините выходной параметр узла Curve.PointAtParameter с узлом List.FilterByBoolMask, чтобы разделить список четных и нечетных индексов.
a. List.FilterByBoolMask. Соедините узел Curve.PointAtParameter из предыдущего шага с входным параметром list.
b. Watch. Узел Watch для in и узел Watch для out показывают, что имеется два списка — c четными и нечетными индексами. Тот же самый порядок точек используется в кривой, что демонстрируется на следующем шаге.
7. Далее используйте результат вывода из узла List.FilterByBoolMask на шаге 05 для создания геометрий с размерами в соответствии с индексами.
Cuboid.ByLength. Для создания молнии вдоль синусоидальной кривой воспроизведите связи, представленные на изображении выше. В данном случае кубоид — это просто рамка, размер которой определяется в зависимости от точки кривой в центре рамки. Теперь логика деления «четные/нечетные» в модели должна быть понятной.
a. Список кубоидов с четными индексами.
b. Список кубоидов с нечетными индексами.
Готово! Вы только что запрограммировали процесс определения геометрических размеров в соответствии с логической операцией, показанной в этом упражнении.
Числа являются самой простой формой данных, а самым простым способом связать эти числа между собой является математика. Начиная от элементарных операторов, таких как деление, и заканчивая тригонометрическими функциями и более сложными формулами, математика — отличный способ начать знакомство с отношениями и закономерностями в мире чисел.
Оператор — это набор компонентов, в которых используются алгебраические функции с двумя входными числовыми значениями, результатом которых является одно выходное значение (сложение, вычитание, умножение, деление и т. д.). Они находятся в разделе «Операторы» > «Действия».
Сложение (+)
var[]...[], var[]...[]
var[]...[]
Вычитание (–)
var[]...[], var[]...[]
var[]...[]
Умножение (*)
var[]...[], var[]...[]
var[]...[]
Деление (/)
var[]...[], var[]...[]
var[]...[]
Скачайте файл с примером, щелкнув ссылку ниже.
Полный список файлов с примерами можно найти в приложении.
Объединяйте операторы и переменные для формирования более сложной связи с помощью формул. Используйте регуляторы для создания формулы, которой можно управлять с помощью входных параметров.
1. Создайте числовую последовательность, которая представляет собой «t» в параметрическом уравнении. Теперь нужен достаточно большой список для определения спирали.
Number Sequence. Определим последовательность чисел на основе трех входных параметров: start, amount и step.
2. На предыдущем шаге был создан список чисел для определения области параметрических компонентов. Создайте группу узлов, представляющих уравнение золотой спирали.
Золотая спираль определяется по следующей формуле:
На изображении ниже представлена золотая спираль в форме визуального программирования. Рассматривая группу узлов, обратите внимание на соответствие между визуальной программой и уравнением в записи.
a. Number Slider. Добавьте два регулятора чисел в рабочую область. Эти регуляторы будут задавать переменные a и b параметрического уравнения. Они представляют собой гибкую константу или параметры, которые можно настроить для получения желаемого результата.
b. Multiplication (*). Узел умножения обозначен звездочкой. Он будет часто использоваться для соединения умножаемых переменных
c. Math.RadiansToDegrees. Значения «t» необходимо преобразовать в градусы для их оценки в тригонометрических функциях. Следует помнить, что для оценки этих функций в Dynamo по умолчанию используются градусы.
d. Math.Pow. В качестве функции «t» и числа «e» этот узел создает последовательность Фибоначчи.
e. Math.Cos и Math.Sin. С помощью этих двух тригонометрических функций будут различаться координаты X и Y (соответственно) для каждой параметрической точки.
f. Watch. В качестве выходных данных отображается два списка, которые будут выступать в качестве координат x и y точек, используемых для формирования спирали.
Хотя набор узлов из предыдущего этапа будет выполнять поставленные задачи, этот процесс довольно трудоемкий. Для повышения эффективности работы ознакомьтесь с разделом DesignScript, в котором показано, как в одном узле разместить строку выражений Dynamo. На последующих этапах рассмотрим использование параметрического уравнения для построения спирали Фибоначчи.
Point.ByCoordinates. Соедините верхний узел умножения с входным параметром «x», а нижний — с входным параметром «y». На экране отобразится параметрическая спираль, проходящая через точки.
Polycurve.ByPoints. Соедините узел Point.ByCoordinates из предыдущего шага с входным параметром points. Параметр connectLastToFirst можно оставить без входных данных, поскольку мы не будем создавать замкнутую кривую. Таким образом, получаем спираль, которая проходит через каждую точку, заданную на предыдущем шаге.
Спираль Фибоначчи создана. Продолжим работу и выполним еще два упражнения, которые назовем «Наутилус» и «Подсолнух». Продемонстрируем два варианта использования спирали Фибоначчи на примере этих представителей естественных систем.
Circle.ByCenterPointRadius. Узел окружности будет иметь те же входные данные, что и на предыдущем шаге. Значение радиуса по умолчанию равно 1.0, поэтому окружности создаются сразу. Четко видно, каким образом точки отклоняются от начала координат.
Number Sequence. Это исходный массив элементов «t». Если соединить его со значением радиуса узла Circle.ByCenterPointRadius, центры окружностей будут по-прежнему отклоняться дальше от начального положения, но радиус окружностей будет увеличиваться, создавая необычный график спирали Фибоначчи.
3D-изображение этого объекта будет выглядеть замечательно.
Массив. После создания раковины наутилуса перейдем к параметрическим сеткам. Используя основной угол вращения спирали Фибоначчи, создайте сетку Фибоначчи, а на ее основе — модель расположения семян цветка подсолнуха.
Начнем с того же шага, что и в предыдущем упражнении: создадим массив точек спирали с помощью узла Point.ByCoordinates.
![](../images/5-3/2/math-part IV-01.jpg)
Далее выполните следующие небольшие действия, чтобы создать последовательность спиралей с различным вращением.
a. Geometry.Rotate. Существует несколько вариантов узла Geometry.Rotate. Убедитесь, что выбран узел с входными параметрами geometry, basePlane и degrees. Соедините узел Point.ByCoordinates с входным параметром «geometry». Щелкните правой кнопкой мыши этот узел и убедитесь, что для переплетения задано значение «Векторное произведение».
b. Plane.XY. Соедините узел с входным параметром basePlane. Вращение будет выполняться вокруг начала координат, которое совпадает с основанием спирали.
c. Number Range. Для входного параметра значений градусов необходимо создать несколько вращений. Это можно быстро сделать с помощью компонента Number Range. Соедините его с входным параметром degrees.
d. Number. Чтобы задать диапазон чисел, добавьте три узла Number в рабочую область в вертикальном порядке. В нисходящей последовательности назначьте значения 0.0,360.0 и 120.0 соответственно. Они будут определять вращение спирали. Обратите внимание на результаты вывода из узла Number Range после соединения с ним трех узлов Number.
Полученное изображение начинает напоминать водоворот. Скорректируйте некоторые параметры Number Range и посмотрите, как изменятся результаты.
Измените размер шага в узле Number Range, задав вместо значения 120.0 значение 36.0. Обратите внимание, что при этом генерируется больше вращений, и, следовательно, создается более плотная сетка.
Измените размер шага в узле Number Range, задав вместо значения 36.0 значение 3.6. Получится более плотная сетка, а у спирали будет отсутствовать направление. Итак, мы создали подсолнух.
Данные — это содержимое программы. Они передаются по проводам, предоставляя входные значения узлам, в которых затем обрабатываются и преобразуются в выходные данные новой формы. Давайте рассмотрим определение данных и их структуру, а затем начнем работу с данными в Dynamo.
Данные — это набор значений количественных и качественных переменных. Самая простая форма данных — это числа, например 0
, 3.14
и 17
. Однако существуют и другие типы данных: переменные, представляющие меняющиеся числа (height
); символы (myName
); геометрические объекты (Circle
); список элементов данных (1,2,3,5,8,13,...
).
В Dynamo данные добавляются (или передаются) в порты ввода узлов. Данные могут существовать без действий, однако они необходимы для обработки действий, которые представлены в форме узлов. Если узел добавлен в рабочее пространство, но не имеет входных данных, результатом будет функция, а не результат самого действия.
Простые данные
Данные и действие (узел), которое успешно выполняется.
Действие (узел) без входных данных возвращает типовую функцию.
Остерегайтесь значений null. Тип 'null'
указывает на отсутствие данных. Это абстрактное понятие, с которым можно, тем не менее, столкнуться при визуальном программировании. Если результат действия недопустим, узел возвращает нулевой объект.
Проверка наличия нулевых объектов и их удаление из структуры данных крайне важны для создания надежных программ.
При визуальном программировании можно очень быстро генерировать большие объемы данных, поэтому необходимы средства для управления их иерархией. Эту роль выполняют структуры данных — организационные схемы, в которых хранятся данные. Особенности структур данных и их использования зависят от языка программирования.
В Dynamo для построения иерархии данных используются списки. Они будут подробнее рассмотрены в следующих главах, пока же приведем только общие сведения.
Список — это набор элементов, размещенных в одной структуре данных:
У меня пять пальцев (элементы) на руке (список).
На моей улице (список) десять домов (элементы).
Узел Number Sequence определяет список чисел на основе входных данных start, amount и step. С помощью этих узлов было создано два отдельных списка из десяти чисел, один из которых охватывает диапазон 100–109, а другой — 0–9.
Узел List.GetItemAtIndex позволяет выбрать элемент в списке по определенному индексу. При выборе значения 0 будет получен первый элемент в списке (в данном случае — 100).
Та же процедура применительно ко второму списку дает значение 0 — первый элемент в списке.
Объединим оба списка в один с помощью узла List.Create. Обратите внимание, что узел создает список списков. Это меняет структуру данных.
При повторном использовании узла List.GetItemAtIndex с индексом 0 получаем первый список в списке списков. Это означает, что список рассматривается как элемент, в чем и состоит отличие от других языков программирования. В последующих главах операции со списками и структуры данных будут рассмотрены подробнее.
Главное, что следует помнить об иерархии данных в Dynamo — в случае со структурой данных списки рассматриваются как элементы. Другими словами, в Dynamo структура данных рассматривается сверху вниз. Что это означает? Рассмотрим пример.
Скачайте файл примера, щелкнув указанную ниже ссылку.
Полный список файлов примеров можно найти в приложении.
В первом примере создадим цилиндр с оболочкой, пройдя по ступеням геометрической иерархии, описанной в этом разделе.
1. Добавьте узел Point.ByCoordinates. После его добавления в рабочую область в начале координат сетки предварительного просмотра Dynamo появляется точка. Значения по умолчанию для выходных параметров x,y и z равны 0,0. В этом месте и была создана точка.
2. Plane.ByOriginNormal. Следующий шаг в построении геометрической иерархии — плоскость. Существует несколько способов построения плоскости. В этом случае в качестве входных данных используется начало координат и нормаль. Начало координат — это узел-точка, созданный на предыдущем шаге.
Vector.ZAxis. Это унифицированный вектор в направлении Z. Обратите внимание, что здесь входные данные отсутствуют, а есть только вектор со значением [0,0,1]. Он будет использоваться в качестве входных данных нормали для узла Plane.ByOriginNormal. В результате получается прямоугольная плоскость в области предварительного просмотра Dynamo.
3. Circle.ByPlaneRadius. Продвигаясь вверх по иерархии, создадим кривую из плоскости, полученной на предыдущем шаге. После соединения с узлом получаем окружность в начале координат. По умолчанию радиус в узле имеет значение 1.
4. Curve.Extrude. Теперь выполним выдавливание фигуры, задав глубину и двигаясь в третьем измерении. Этот узел создает поверхность из кривой путем выдавливания. По умолчанию расстояние в узле равно 1, а на видовом экране должен отображаться цилиндр.
5. Surface.Thicken. Этот узел создает замкнутое тело путем смещения поверхности на заданное расстояние и замыкания формы. По умолчанию значение толщины равно 1, а на видовом экране в соответствии с этими значениями отображается цилиндр с оболочкой.
6. Number Slider. Вместо использования значений по умолчанию для входных данных добавим в модель параметрические элементы управления.
Редактирование области. После добавления регулятора чисел в рабочую область щелкните значок в левом верхнем углу окна, чтобы отобразить параметры области.
Min/Max/Step. Задайте для параметров min, max и step значения 0, 2 и 0.01 соответственно. Это необходимо для управления размером всей геометрии.
7. Регуляторы чисел. Вместо входных значений по умолчанию скопируйте и вставьте этот регулятор чисел (выберите его, нажмите CTRL + C, затем CTRL + V) несколько раз, пока во всех входных параметрах со значениями по умолчанию не будут заданы регуляторы. Чтобы алгоритм действовал, некоторые значения регуляторов должны быть больше нуля (например, для увеличения толщины поверхности требуется глубина выдавливания).
8. В итоге с помощью регуляторов создан параметрический цилиндр с оболочкой. Попробуйте изменить некоторые из параметров, наблюдая за динамическим обновлением геометрических объектов на видовом экране Dynamo.
Регуляторы чисел. На следующем этапе мы добавили в рабочую область множество регуляторов, и теперь необходимо очистить интерфейс только что созданного инструмента. Щелкните один регулятор правой кнопкой мыши и выберите «Переименовать...». Замените имя каждого регулятора именем соответствующего параметра (толщина, радиус, высота и т. п.).
9. На данный момент создан цилиндр с толстыми стенками. Пока это только один объект. Теперь рассмотрим, как создать массив цилиндров, которые динамически связаны друг с другом. Для этого вместо одного объекта создадим список цилиндров.
Добавление (+). Наша цель — добавить ряд цилиндров возле уже имеющегося цилиндра. При вставке еще одного цилиндра рядом с текущим необходимо учитывать радиус цилиндра и толщину его оболочки. Это число можно получить, сложив два значения регуляторов.
10. Это более сложный шаг, поэтому рассмотрим его подробнее. Конечная цель — создать список чисел, определяющих местоположение каждого цилиндра в последовательности.
a. Умножение. Сначала умножим значение из предыдущего шага на 2. Это было значение радиуса, а цилиндр необходимо переместить на полный диаметр.
b. Number Sequence. С помощью этого узла создадим массив чисел. Сначала вставим узел умножения из предыдущего шага в качестве значения step. В качестве значения start можно указать 0.0, используя узел number.
c. Integer Slider. Чтобы задать значение amount, присоединим регулятор целых чисел. Он будет определять количество создаваемых цилиндров.
d. Выходные данные. В этом списке показано расстояние смещения каждого цилиндра в массиве, которое управляется параметрически с помощью первоначальных регуляторов.
11. Этот шаг достаточно прост: соедините последовательность из предыдущего шага с входным параметром x исходного узла Point.ByCoordinates. При этом регулятор pointX будет заменен, и его можно удалить. Теперь на видовом экране отображается массив цилиндров (убедитесь, что регулятор целых чисел имеет значение больше 0).
12. Цепь цилиндров по-прежнему динамически связана со всеми регуляторами. Перемещайте регуляторы, и вы увидите, как изменится картина.
Object.IsNull
obj
bool
Цвет — это тип данных, который помогает создавать наглядные визуальные представления, а также отражать различия в результатах визуального программирования. При работе с абстрактными данными и численными переменными бывает трудно определить, что именно изменилось и в какой степени. Для решения этой проблемы можно использовать цвета.
Цвета в Dynamo создаются с использованием входных данных ARGB, что является сокращенным обозначением комбинации альфа-канала (Alpha) с красным (Red), зеленым (Green) и синим (Blue) каналами. Альфа-канал служит для задания прозрачности цвета, а остальные три канала используются как основные цвета для создания всего цветового спектра.
Цвет ARGB (Color.ByARGB)
A,R,G,B
color
Цвета в таблице ниже запрашивают свойства, использованные для настройки итогового цвета: альфа, красный цвет, зеленый цвет и синий цвет. Обратите внимание, что узел Color.Components включает все четыре свойства в качестве портов вывода, поэтому его удобнее всего использовать для запроса свойств цвета.
Альфа (Color.Alpha)
color
A
Красный (Color.Red)
color
R
Зеленый (Color.Green)
color
G
Синий (Color.Blue)
color
B
Компоненты (Color.Components)
color
A, R, G, B
Цвета в таблице ниже соответствуют цветовому пространству HSB. Разделение цвета на такие составляющие, как оттенок, насыщенность и яркость, является более понятным и привычным с точки зрения интерпретации цвета. Какого оттенка должен быть цвет? Насколько ярким он должен быть? Насколько светлым или темным? Отвечая на эти вопросы, мы тем самым разбиваем цвет на составляющие, то есть на оттенок, насыщенность и яркость соответственно.
Оттенок (Color.Hue)
color
Hue
Насыщенность (Color.Saturation)
color
Saturation
Яркость (Color.Brightness)
color
Brightness
Цветовой диапазон аналогичен узлу Remap Range из упражнения #part-ii-from-logic-to-geometry: он повторно сопоставляет список чисел с другой областью. Однако вместо сопоставления с областью чисел цветовой диапазон выполняет сопоставление с цветовым градиентом в соответствии со входными значениями в диапазоне от 0 до 1.
Текущий узел хорошо выполняет свои функции, но с ним может быть трудно добиться нужных результатов с первого раза. Чтобы уверенно работать с цветовым градиентом, стоит несколько раз опробовать его на практике в интерактивном режиме. Выполните небольшое упражнение, чтобы узнать, как настроить градиент, так чтобы цвета на выходе соответствовали заданным числам.
Определите три цвета. С помощью узла Code Block определите красный, зеленый и синий цвета, назначив каждому из них соответствующие сочетания значений 0 и 255.
Создайте список. Объедините три цвета в один список.
Определите индексы. Создайте список для определения положения ручек каждого цвета (в диапазоне от 0 до 1). Обратите внимание, что для зеленого цвета задано значение 0,75. Это смещает зеленый цвет на 3/4 вдоль горизонтального градиента в регуляторе цветового диапазона.
Code Block. Введите значения (от 0 до 1), которые будут преобразованы в цвета.