Всем привет! Сегодня расскажу, как с помощью Revit API создавать разрезы, параллельные стене, а также смещать их от стены на определённую величину, и раздвигать их границы.
При подготовке статьи я использовал материал из блога Джереми Тэммика:
https://thebuildingcoder.typepad.com/blog/2012/06/create-section-view-parallel-to-wall.html
Создание разреза
Разрезы в Revit API представлены классом ViewSection. Чтобы создать разрез, можно воспользоваться его статическим методом CreateSection. Он принимает документ, тип вида и BoundingBox. Соответственно, задача построения разреза сводится к правильному определению его BoundingBox.
Но сначала выберем нужный тип разреза, это тоже не сразу очевидная вещь. Я сделал это так:
var viewTypeId = new FilteredElementCollector(doc)
.OfClass(typeof(ViewFamilyType))
.ToElements()
.Cast<ViewFamilyType>()
.Where(type => type.ViewFamily == ViewFamily.Section)
.FirstOrDefault().Id;
Я беру элементы класса ViewFamilyType — это типы видов, и беру среди них те, которые являются типами разрезов (Section). В данном случае я беру первый элемент, но у себя в приложении вы можете создать ComboBox с выбором нужного типа. Похожий пример я писал в предыдущей статье.
Теперь давайте подробнее рассмотрим класс BoundingBoxXYZ. Это не просто параллелепипед, представленный свой минимальной и максимальной точкой. У него ещё есть свойство Transform, которое управляет его положением в пространстве. Нам надо будет решить задачу по правильному созданию этого самого Transform для разреза.
В своём коде я задал 3 переменные:
var projectionDeprth = 500/304.8;
var offset = 250/304.8;
var sectionOffset = 50/304.8;
Они представляют собой глубину проецирования разреза, смещение линии разреза от оси стены, и смещение верхних точек разреза от краёв стены. У меня их пока можно поменять только в коде, но, как и с типом разреза, можете прикрутить это себе к пользовательскому интерфейсу.
И далее пройдёмся циклом foreach по всем стенам на активном виде. Тут уже сложно будет выделить отдельные части, поэтому сразу приведу весь фрагмент кода (ссылка на итоговый код будет в конце статьи):
Сначала разберёмся с линией разреза. Для этого на строках 591-593 я получаю её из Location стены, а затем получаю нужные мне параметры:
- length — половина длины стены. Это расстояние от стартовой точки Transform в обе стороны.
- lineDifference — вектор от стартовой точки к конечной.
- middlePoint — центральная точка линии.
Далее разбираемся с границами по высоте. Я решил сделать их соответствующими границе стены, со смещением вверх на sectionOffset, то есть 50 мм. Я получаю переменные maxHeight и minHeight на строках 601-603 с помощью BoundingBox стены.
Далее задаю минимальную и максимальную точки моего BoundingBox на строках 604-605. Если я их так и оставлю, то он создастся в начале координат, поэтому надо трансформировать будущий BoundingBox с помощью Transform.
Для этого нам нужны 3 векторные переменные, которые мы потом назначим на BasisX, BasisY и BasisZ:
- Нормализованный lineDifference (приведённый к единичной длине) станет BasisX.
- XYZ.BasisZ (единичный вектор вверх) станет BasisY.
- А их векторное произведение запишем в BasisZ.
Если честно, я не до конца понимаю, почему всё работает именно так. Поэтому, когда я разбирался с SectionBox фасадов, я определял эти Basis методом подбора. Но с разрезами приведённый код работает. Если разберётесь, в чем дело и как это можно объяснить, чтобы было понятно — пишите в комментарии.
В общем, теперь всё. Записываем все значения в Transform на строках 612-616 и в sectionBox на 618-621, а потом создаём разрез.
Запускаю макрос, и вижу вот такой результат:
Стены обрисовываются во всех направлениях и под любыми углами. Сами разрезы выглядят так:
Как видите, сверху и снизу есть небольшой зазор, потому что я его назначил через sectionOffset. Сдвига вправо-влево нет, если вам он нужен, то добавьте его, модифицировав startPoint и endPoint.
Итоговый код макроса на GitHub Gist
На этом всё. Не забывайте подписываться на мой телеграм-канал о Revit API и ставить лайки на статьи, которые читаете. До новых встреч!