Использование нодов напрямую в Python-скрипте
11 июня 2025, 15:45
От автора @Анжелика Жилина
В NVP появилась возможность использовать функции из нодов в Python-скрипте. Рассмотрим создание скрипта двумя способами: через ноды и с помощью их использования в Python. Создадим скрипт, размещающий на 3D-сцене массив кубиков с возможностью редактировать ряды, столбцы, поворот вокруг своей оси и масштаб.
Создание скрипта с помощью нодов
Создаем базовый квадрат с заданной стороной.

Добавляем возможность поворота в центре квадрата.

Добавляем возможность масштабирования элемента.

Создаем ряды.

Создаем столбцы.

Добавим новый параметр «Пропорциональность масштабу» и применим его к смещениям по X и Y. Этот параметр регулирует расстояние между рядами и столбцами в соответствии с масштабом.

Применяем выдавливание для всех элементов.

Входные данные.

Весь скрипт.

Результаты работы скрипта.


Создание скрипта через Python-нод
Перенесем всю логику скрипта в Python-нод.
Для использования нода в Python-скрипте необходимо получить его функцию с помощью конструкции Nodes.Get("Наименование нода"). В скобках указывается точное название нужного нода. После этого полученную переменную, например func = Nodes.Get("Наименование нода"), можно использовать как обычную функцию, передавая ей необходимые аргументы в нужном порядке и нужного типа, аналогично работе с функциями в Python: func(a, b, c).
Такой подход позволяет интегрировать ноды в скрипты. Таким образом можно получать не только функции из базовых нодов, но и из библиотеки нодов под Revit и Nanocad, а также кастомных нодов, созданных пользователем (с помощью C# или из скрипта NVP). Не все базовые ноды можно использовать в Python-скрипте, нельзя использовать такие ноды как List, Console, RunBranch, Python и т.д. В них нет необходимости.
Добавляем входные данные и нод для написания Python-скрипта в рабочую область. Так будет выглядеть весь скрипт.

Переходим к написанию кода в Python-ноде. Импортируем List и получаем входные данные из инпутов. List нам потребуется в дальнейшем для передачи данных в ноды и манипуляций с результатами работы нодов.
#ввод данных
from System.Collections.Generic import List
length = Inputs[0]
row_count = Inputs[1]
row_step = Inputs[2]
column_count = Inputs[3]
column_step = Inputs[4]
rotation_angle = Inputs[5]
scale_value = Inputs[6] / 100
is_proportionally = Inputs[7]
Получаем функции из нодов с помощью конструкции Nodes.Get(). В дальнейшем будем использовать их в коде.
#необходимые функции
CreatePoint = Nodes.Get("Точка")Rotate = Nodes.Get("Повернуть элемент")
ArrayOffset = Nodes.Get("Смещение массивом")
Extrusion = Nodes.Get("Выдавливание")
Scale = Nodes.Get("Масштабировать элемент")
Создаем точки квадрата и векторы, используя полученную из нода функцию CreatePoint, в скобках передаем ей входные данные, в результате получим точку.
p1 = CreatePoint(0, 0, 0)
p2 = CreatePoint(0, length, 0)
p3 = CreatePoint(length, length, 0)
p4 = CreatePoint(length, 0, 0)
x = CreatePoint(1, 0, 0)
y = CreatePoint(0, 1, 0)
z = CreatePoint(0, 0, 1)
Создаем список, правильно инициализируем его как List[object]() для возможности добавления в него точек. Список необходим для последующей передачи в нод «Полигон по точкам».
points = List[object]([p1, p2, p3, p4])
Создаем полигон по точкам и получаем его центр, передавая в функцию параметры как в нод. Вызывать функцию можно еще и так:
base_polygon = Nodes.Get("Полигон по точкам")(points, False)
center = Nodes.Get("Центр фигуры")(base_polygon)
Добавляем возможность поворота и масштабирования, вызывая функции полученные выше.
#поворот масштабирование
if rotation_angle > 0:
base_polygon = Rotate(base_polygon, z, center, rotation_angle, False)
base_polygon = Scale(base_polygon, scale_value)
Создаем список для результатов смещения, правильно инициализируем его.
#смещение
polygons = List[object]()
Задаем шаг для смещения с учетом параметра «Пропорциональность масштабу».
yOffset = row_step + length
xOffset = column_step + length
if is_proportionally:
yOffset = yOffset * scale_value
xOffset = xOffset * scale_value
Смещаем базовый полигон по оси Y, используя функцию, полученную из нода «Смещение массивом». Добавляем результаты в список всех полигонов.
polygons_yOffset = ArrayOffset(base_polygon, y, yOffset, row_count)
polygons_yOffset.Add(base_polygon)
polygons.AddRange(polygons_yOffset)
Смещаем каждый из полигонов, расположенных по оси Y, вдоль оси X.
for polygon_yOffset in polygons_yOffset:
polygons_xOffset = ArrayOffset(polygon_yOffset, x, xOffset, column_count)
polygons.AddRange(polygons_xOffset)
Выполняем выдавливание и выводим результат в виде списка.
cubes = []
for polygon in polygons:
cubes.append(Extrusion(polygon, z, length * scale_value))
#вывод результата
Result.Set(cubes)
В результате получился такой же скрипт, но более компактный.
Файл скрипта тут