А именно про InvalidElementId и то, как он (не) может помочь при написании плагинов для Revit
Всем привет! В этой статье я не буду рассказывать о новых сложных темах — просто расскажу интересное поведение некоторых классов API. Так что наливайте чай, устраивайтесь поудобнее, и поехали.
Работа с витражами
Работа с витражами устроена довольно просто. Берём стену, находим её свойство CurtainGrid. У обычных стен там будет null, а у витражей — собственно CurtainGrid. Это нарезка витража, оттуда мы можем получить линии нарезки, панели, ячейки, импосты. Всё это можно посмотреть в Revit Lookup:
По Id элементов можно получить элементы, и дальше делать то, что нам надо. Ну хорошо, давайте посмотрим, что можно делать с панелями (и включим заодно свойства и методы, которые не поддерживаются):
О, интересно. Мы можем получить RefGridLines для витража. Вот описание этого метода из API:
Вспоминаю про свою статью:
Пора видимо переименовывать в "6 вещей": имя метода начинается с Get, но метод ничего не возвращает, а получаем значения мы через модификатор ref. Вот тут подробнее можно почитать про него. Выглядит код с этим методом так:
ElementId uId = null;
ElementId vId = null;
panel.GetRefGridLines(ref uId, ref vId);
Что это? Зачем? Почему так, почему не сделать хотя бы модификатор out, чтобы можно было не объявлять переменные заранее, как сделано в TryParse у int или double?
Вообще, лучше бы конечно они разделили на 2 метода, для U и для V линии, но пока имеем, что имеем.
Ищем GridLines по панели
Давайте напишем небольшой код такого плана:
Запишем в комментарии каждой панели витража Id для U- и V- линий сетки , и посмотрим, что получится:
Получилось вот что:
У другой панели:
То есть суть такая: линия сетки знает, что у неё есть панель справа и сверху от неё. Если панель крайняя левая или крайняя нижняя, то у ней не будет связанной GridLine. Что ж, окей — метод интересный, но нам особо не поможет.
Ищем панель по GridLines
Зная панель, мы можем найти её GridLine. Но вообще, зная GridLine, мы можем найти и панель методом GetPanel:
Вообще, внимательный читатель тут скажет: "Подождите, а почему в заголовке что-то про Revit Lookup?". А вот почему:
Эти методы ещё совсем недавно не поддерживались, а мне было интересно, как они работают. Поэтому я написал код в Revit Lookup по поддержке этих методов, и он вошёл в релиз 2025.0.1.
Продолжаем искать панель по GridLines
Итак, логично, что для реализации метода GetPanel по 2 ElementId от GridLines мы должны взять список U-lines, список V-lines, и сделать двойной цикл:
Но результат не порадует: мы не получим те панели, у которых нет линий сетки слева и снизу от них:
Но если мы вспомним, что там у этих панелей в параметре "Комментарии", то увидим там число -1. Это ElementId.InvalidElementId, чьё значение равно -1.
А что если попробовать добавить в список линий по обеим осям InvalidElementId, и посмотреть результат? Нам как раз 2 оси не достаёт:
Результат:
Да, мы можем передать в качестве аргумента InvalidElementId и получить результат, если это метод GetPanel или GetCell класса CurtainGrid.
Заключение
Всё это, конечно, интересно, но по факту применить это будет сложно. Да, можно попробовать искать панели через CurtainGridLine, да, можно добавлять InvalidElementId, но что нам это даст? У одного и того же витража будут крайние панели с -1 и со значением Id стоящих слева от них GridLine — крайние так не найти, только крайние левые или крайние нижние. Можно попробовать что-то найти через зависимые элементы, но какие зависимые элементы у -1?
В общем, если придумаете, как можно применить это знание, обязательно пишите в комментарии, может быть, добавлю в статью, но пока от изучения этих методов у меня только реакция "ну как можно было так плохо сделать API для работы с витражами???".
Итоги
Теперь вы тоже сможете посмотреть результат отработки этих методов, воспользовавшись новым релизом RevitLookup 2025.0.1
На этом на сегодня всё! Не забывайте подписываться на мой телеграм-канал о Revit API и до новых встреч!