Отсоединение балки от плоскости
Вопрос: В пользовательском интерфейсе с помощью контекстного меню балки есть команда «Отсоединить от плоскости». А как можно сделать то же самое, только программно?
После того, как я нажал правую кнопку на балке и выбрал «Отсоединить от плоскости», Revit удаляет параметр Рабочая плоскость, т.е. встроенный параметр BuiltInParameter.SKETCH_PLANE_PARAM, и делает активным параметр Базовый уровень, который до этого был только для чтения. Хотелось бы проделать эти действия с помощью Revit API.
Я попробовал удалить параметр Рабочая плоскость, но это не помогло. Свойство FamilyInstance.Host также является только для чтения, поэтому с помощью него не получится отсоединить балку от рабочей плоскости.
Есть ли способ отсоединить балку от плоскости программно?
Ответ: Изменение положения балки по высоте с помощью параметров Смещение начального и конечного уровня приведет к тому что балка не будет находиться на плоскости. Это действие приведет к тому что балка отсоединится от рабочей поверхности.
Ответ: Но мне нужно чтобы физически балка оставалась на том же самом месте. То есть мне нужно проделать что-то типа этого:
- Первая транзакция: Переместить балку на некоторое расстояние в направлении нормали плоскости
- Вторая транзакция: Вернуть балку назад, сместив ее в противоположном направлении на то же самое расстояние.
Верно?
Ответ: Я думаю вполне можно обойтись и одной транзакцией.
Если все же не получится, то можно использовать TransactionGroup, для объединения двух транзакций в одну.
Ответ: Спасибо огромное. Действительно, все работает и в одной транзакции.
Вот пример кода, который у меня получился:
- [Transaction(TransactionMode.Manual)]
- public class Command : IExternalCommand
- {
- public Result Execute(
- ExternalCommandData commandData,
- ref string message,
- ElementSet elements)
- {
- UIApplication uiapp = commandData.Application;
- UIDocument uidoc = uiapp.ActiveUIDocument;
- Document doc = uidoc.Document;
- // Выберем балку
- SelectionFilterBeam selFilterBeam
- = new SelectionFilterBeam();
- Reference r = uidoc.Selection.PickObject(
- ObjectType.Element, selFilterBeam,
- "Выберите балку для отсоединения от плоскости");
- FamilyInstance beam = doc.GetElement(r)
- as FamilyInstance;
- // Проверим, что балку можно отсоединить от плоскости.
- //
- // Кто то может подумать, что можно просто проверить
- // свойство .Host как в закомментированном коде ниже, НО
- // возможна странная ситуация, когда свойство Host
- // равно null а Revit все еще отображает параметр Рабочая плоскость
- // Со значением <не задано>
- //
- //if (null == beam.Host)
- //{
- // MessageBox.Show("Выбранный экземпляр семейства 'Каркас несущий' не имеет рабочей плоскости!");
- // return Result.Cancelled;
- //}
- //
- // Поэтому, мы должны проверить, что параметр Рабочая плоскость существует
- if (null == beam.get_Parameter(
- BuiltInParameter.SKETCH_PLANE_PARAM))
- {
- MessageBox.Show("Выбранный экземпляр семейства 'Каркас несущий' не имеет рабочей плоскости!");
- return Result.Cancelled;
- }
- // Теоретически плоскость может не быть горизонтальной
- // но в 99% случаев она будет именно горизонтальной
- // и в 99,99% балка не будет лежать в вертикальной плосоксти.
- // В этом случае приведенный ниже код не будет работать.
- // Так как свойство .Host только для чтения
- // то единственный способ - это сдвинуть
- // смещение начального и конечного уровней
- // сместив балку с поверхности.
- // Внутренне, Revit тем самым отсоединит балку от плоскости.
- // Затем мы вернем балку назад в прежнее пложение.
- // Заметьте, что простое смещение элемента не будет работать
- // так как балка привязна к плоскости.
- double elevOldSta = beam.get_Parameter(
- BuiltInParameter.STRUCTURAL_BEAM_END0_ELEVATION)
- .AsDouble();
- double elevOldEnd = beam.get_Parameter(
- BuiltInParameter.STRUCTURAL_BEAM_END1_ELEVATION)
- .AsDouble();
- double elevTmpSta = elevOldSta + 1.0;
- double elevTmpEnd = elevOldEnd + 1.0;
- using (var t = new Transaction(doc, "Отсоединение балки от плоскости"))
- {
- t.Start();
- // Это приведет к отсоединению балки от плоскости.
- beam.get_Parameter(
- BuiltInParameter.STRUCTURAL_BEAM_END0_ELEVATION)
- .Set(elevTmpSta);
- beam.get_Parameter(
- BuiltInParameter.STRUCTURAL_BEAM_END1_ELEVATION)
- .Set(elevTmpEnd);
- // вернем балку назад
- // на прежнее положение
- beam.get_Parameter(
- BuiltInParameter.STRUCTURAL_BEAM_END0_ELEVATION)
- .Set(elevOldSta);
- beam.get_Parameter(
- BuiltInParameter.STRUCTURAL_BEAM_END1_ELEVATION)
- .Set(elevOldEnd);
- t.Commit();
- }
- MessageBox.Show("Балка отсоединена");
- return Result.Succeeded;
- }
- }
- class SelectionFilterBeam : ISelectionFilter
- {
- public bool AllowElement(Element e)
- {
- if (!(e is FamilyInstance))
- {
- return false;
- }
- if (e.Category.Id.IntegerValue != (int)
- BuiltInCategory.OST_StructuralFraming)
- {
- return false;
- }
- // не стоит надеяться только на категорию
- // так как это не обязательно может быть балка
- return true;
- }
- public bool AllowReference(Reference r, XYZ p)
- {
- return true;
- }
- }
Обратите внимание на множество комментариев в коде.
Также заметьте, что можно немного увеличить производительность, изменяя только смещение одного уровня, вместо двух.
Источник: http://thebuildingcoder.typepad.com/blog/2014/03/detach-beam-from-plane.html
Обсуждение: http://adn-cis.org/forum/index.php?topic=614
Опубликовано 15.03.2014