Сообщество программистов Autodesk в СНГ

ADN Club => Revit API => Тема начата: asia от 17-09-2020, 13:56:00

Название: Установка перемычки над проемом
Отправлено: asia от 17-09-2020, 13:56:00
Добрый день!
Ситуация такова, что в стене находятся проемы (дверь или окно). Сверху посредине для каждого нужно установить перемычку (они присутствуют в проекте, я просто выбираю по имени необходимую):
Код - C# [Выбрать]
  1. Element bar = new FilteredElementCollector(document)
  2.     .WhereElementIsElementType().ToElements().Where(x => x.Name.Equals(nameOfBar)).First();
  3.  
Для каждого проема (окна, например) я получаю ширину, чтоб определить средину:
Код - C# [Выбрать]
  1. foreach (Element aperture in apertures)
  2. {
  3.     apertureWidth = aperture.get_Parameter(BuiltInParameter.WINDOW_WIDTH).AsDouble();
  4. }
  5.  
Как можно реализовать непосредственно установку перемычки?
Название: Re: Установка перемычки над проемом
Отправлено: Александр Игнатович от 17-09-2020, 18:10:02
Краткий ответ: нужно разместить семейство.

Подробный: смотри методы document.Create.NewFamilyInstance, там overload-ов этого метода штук 12, поскольку пользовательские семейства все очень разные, т.е. они могут быть "обычные", могут быть на основе линии, могут размещаться на грани и т.д. Как у тебя сделано семейство этой перемычки мы не знаем, поэтому сказать, какой именно метод тебе нужен я не могу.

Да и ещё, у FamilySymbol нужно проверить свойство IsActive и при необходимости вызвать метод Activate().

Ещё я бы уточнил способ получения типоразмера семейства, обрати внимание, в API порядка 40 классов для создания фильтров, т.е. я бы скомбинировал поиск по категории, по классу FamilySymbol и добавил бы поиск по параметру-имени семейства и типоразмера. Например как-то так:
Код - C# [Выбрать]
  1. private static ElementFilter CreateFamilySymbolFilter(string familyName, string symbolName)
  2. {
  3.         var rules = new[]
  4.                 {
  5.                         ParameterFilterRuleFactory.CreateEqualsRule(new ElementId(BuiltInParameter.ALL_MODEL_FAMILY_NAME), familyName, false),
  6.                         ParameterFilterRuleFactory.CreateEqualsRule(new ElementId(BuiltInParameter.SYMBOL_NAME_PARAM), symbolName, false)
  7.                 };
  8.                
  9.         return new LogicalAndFilter(new ElementFilter[]
  10.                 {
  11.                         new ElementClassFilter(typeof(FamilySymbol)),
  12.                         new ElementCategoryFilter(BuiltInCategory.OST_StructuralFoundationTags), // категория твоего семейтства
  13.                         new ElementParameterFilter(rules)
  14.                 });
  15. }
Название: Re: Установка перемычки над проемом
Отправлено: asia от 17-09-2020, 18:52:40
Спасибо! Буду разбираться.
Название: Re: Установка перемычки над проемом
Отправлено: asia от 17-09-2020, 19:21:08
С помощью FamilyPlacementType определил, что семейство OneLevelBased.
Название: Re: Установка перемычки над проемом
Отправлено: Александр Игнатович от 17-09-2020, 20:51:42
Тогда пробуй этим методом:
Код - C# [Выбрать]
  1. public FamilyInstance NewFamilyInstance(
  2.         XYZ location,
  3.         FamilySymbol symbol,
  4.         Level level,
  5.         StructuralType structuralType
  6. )

Вероятно, после вставки, придется повернуть методом:
Код - C# [Выбрать]
  1. ElementTransformUtils.RotateElement
Название: Re: Установка перемычки над проемом
Отправлено: asia от 17-09-2020, 21:31:38
Метод работает, перемычка добавляется, но как ее расположить посредине над проемом в стене? Для этого мне нужно как-то задействовать ширину проема? Или в XYZ указывать, используя начальную и конечную точки проема для поиска центра?
Название: Re: Установка перемычки над проемом
Отправлено: Александр Игнатович от 17-09-2020, 22:03:46
Из геометрии или bounding box-а проема получить, например. У тебя, похоже, что проемы - это окна, они имеют точку вставки, которую с вероятностью 99% можно просто поднять на Max.Z Bounding box-а проема. Может быть, толщину перемычки ещё учесть придется, тут опять же зависит от того, как всё замоделировано
Название: Re: Установка перемычки над проемом
Отправлено: asia от 18-09-2020, 14:38:36
А можно ли как-то совместить центры? Вот я получаю центр boundingBox стены, чтоб посредине установить перемычку, но в центр устанавливается грань.
Код - C# [Выбрать]
  1. BoundingBoxXYZ wallBb= wall.get_BoundingBox(document.ActiveView);
  2.                     double wallCenter = (wallBb.Max.Y + wallBb.Min.Y) * 0.5;
  3.  


(https://i.postimg.cc/R6cXXxYP/ex.png) (https://postimg.cc/R6cXXxYP)
Название: Re: Установка перемычки над проемом
Отправлено: Александр Игнатович от 18-09-2020, 15:03:46
Подвинуть на половину ширины палки?
Название: Re: Установка перемычки над проемом
Отправлено: asia от 18-09-2020, 16:20:43
А если палка у меня определяется как FamilySymbol, что мне нужно сделать чтоб получить boundingBox для нее?

Код - C# [Выбрать]
  1. FamilySymbol bar = new FilteredElementCollector(document)
  2.                 .WhereElementIsElementType().ToElements().Where(x => x.Name.Equals(barName)).First() as FamilySymbol;
  3.  
А создается так:
Код - C# [Выбрать]
  1. FamilyInstance barInstance = document.Create.NewFamilyInstance(point, bar, level, StructuralType.NonStructural);
  2.  
Название: Re: Установка перемычки над проемом
Отправлено: Александр Игнатович от 22-09-2020, 16:24:37
после создания barInstance вызвать document.Regenerate(), затем получить bounding box из barInstance-а
Название: Re: Установка перемычки над проемом
Отправлено: asia от 23-09-2020, 09:45:45
Александр Игнатович, спасибо! Разобрался, все работает.
Название: Re: Установка перемычки над проемом
Отправлено: RevitTormentor от 06-10-2020, 13:02:58

Вероятно, после вставки, придется повернуть методом:
Код - C# [Выбрать]
  1. ElementTransformUtils.RotateElement

А на 270 градусов не должно быть проблем с поворотом?
Название: Re: Установка перемычки над проемом
Отправлено: Александр Игнатович от 08-10-2020, 11:48:23
Нет. Можно на 270, можно на -90, как больше нравится
Название: Re: Установка перемычки над проемом
Отправлено: asia от 22-10-2020, 09:20:53
Добрый день,
продолжая работу над установкой перемычек, столкнулся с проблемой. Решение через получение boundingBoxов проемов работает некорректно, если, допустим, в проекте несколько стен с разным направлением, максимумы/минимумы проемов в этих стенах уже другие. Подскажите, пожалуйста, как можно решить эту проблему, можно ли как-то получать глобальные координаты середин проемов, чтоб потом совмещать с серединами перемычек?

upd
Решил попробовать следующее: выбирать проем и получать хост-стену, появился вопрос: можно ли определить направление стены (запад/восток) или как-то получить фасад из вида?
Для северного и южного фасадов все работает корректно.
(https://i.postimg.cc/R6wnySNh/1.png) (https://postimg.cc/R6wnySNh)

Возможно, лучшим вариантом было бы получать вектор направления стены, но как тогда его использовать в методе NewFamilyInstance?
Название: Re: Установка перемычки над проемом
Отправлено: Александр Игнатович от 22-10-2020, 22:59:51
У стены всегда есть ориентация, т.е. вектор, ей перпендикулярный, направленный в сторону внешней стороны. У стены есть собственно Location, который можно привести к LocationCurve, из которого получить линию (или, потенциально дугу, или эллипс в последних версиях) по которой построена стена, собственно, отсюда можно получить абсолютно всю необходимую информацию.

Я бы ориентировался на центр bounding box-а, он не будет меняться от поворота стен.

как тогда его использовать в методе NewFamilyInstance?

Какое у тебя семейство перемычки, мы не знаем, тут могут быть разные варианты, как применить полученные знания, возможно, просто повернуть после создания.
Название: Re: Установка перемычки над проемом
Отправлено: asia от 23-10-2020, 14:23:39
Семейство OneLevelBased, наверное и правда можно попробовать просто поворачивать, тогда нужно как-то получить угол поворота стены.
Название: Re: Установка перемычки над проемом
Отправлено: Александр Ривилис от 23-10-2020, 15:01:43
Семейство OneLevelBased, наверное и правда можно попробовать просто поворачивать, тогда нужно как-то получить угол поворота стены.
Угол поворота, как я понимаю, ты можешь вычислить исходя из свойства Wall.Orientation - вектор нормали к плоскости стены.
Название: Re: Установка перемычки над проемом
Отправлено: asia от 23-10-2020, 15:49:15
Получилось так:
Код - C# [Выбрать]
  1. LocationCurve lc = wall.Location as LocationCurve;
  2. XYZ start = lc.Curve.GetEndPoint(0);
  3. XYZ end = lc.Curve.GetEndPoint(1);
  4. Line axis = Line.CreateBound(start, end);
  5. XYZ direction = axis.Direction;
И тогда я просто использую это здесь:
Код - C# [Выбрать]
  1. NewFamilyInstance(XYZ, symbol, direction, level, StructuralType.Beam);
Но проблема в том, что boundingBoxы для стен и проемов я получаю в виде double значений по осям, чтоб разместить перемычку четко по центру стены (по y):
Код - C# [Выбрать]
  1. BoundingBoxXYZ wallBb = wall.get_BoundingBox(doc.ActiveView);
  2. double y = (wallBb.Max.Y + wallBb.Min.Y) * 0.5;
и по центру проема вверху (по оси z самая высокая точка проема):
Код - C# [Выбрать]
  1. BoundingBoxXYZ windowBb = window.get_BoundingBox(doc.ActiveView);
  2. double z = windowBb.Max.Z;
Высота в любом случае одинаковая будет, даже если стена под углом, но значения по x и y изменятся:


(https://i.postimg.cc/jnJkSPfx/1.png) (https://postimg.cc/jnJkSPfx)