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

15/03/2014

Отсоединение балки от плоскости

Вопрос: В пользовательском интерфейсе с помощью контекстного меню балки есть команда «Отсоединить от плоскости». А как можно сделать то же самое, только программно?

После того, как я нажал правую кнопку на балке и выбрал «Отсоединить от плоскости», Revit удаляет параметр Рабочая плоскость, т.е. встроенный параметр BuiltInParameter.SKETCH_PLANE_PARAM, и делает активным параметр Базовый уровень, который до этого был только для чтения. Хотелось бы проделать эти действия с помощью Revit API.

Я попробовал удалить параметр Рабочая плоскость, но это не помогло. Свойство FamilyInstance.Host также является только для чтения, поэтому с помощью него не получится отсоединить балку от рабочей плоскости.

Есть ли способ отсоединить балку от плоскости программно?

Ответ: Изменение положения балки по высоте с помощью параметров Смещение начального и конечного уровня приведет к тому что балка не будет находиться на плоскости. Это действие приведет к тому что балка отсоединится от рабочей поверхности.

Ответ: Но мне нужно чтобы физически балка оставалась на том же самом месте. То есть мне нужно проделать что-то типа этого:

  • Первая транзакция: Переместить балку на некоторое расстояние в направлении нормали плоскости
  • Вторая транзакция: Вернуть балку назад, сместив ее в противоположном направлении на то же самое расстояние.

Верно?

Ответ: Я думаю вполне можно обойтись и одной транзакцией.

Если все же не получится, то можно использовать TransactionGroup, для объединения двух транзакций в одну.

Ответ: Спасибо огромное. Действительно, все работает и в одной транзакции.

Вот пример кода, который у меня получился:

Код - C#: [Выделить]
  1.     [Transaction(TransactionMode.Manual)]
  2.     public class Command : IExternalCommand
  3.     {
  4.         public Result Execute(
  5.           ExternalCommandData commandData,
  6.           ref string message,
  7.           ElementSet elements)
  8.         {
  9.             UIApplication uiapp = commandData.Application;
  10.             UIDocument uidoc = uiapp.ActiveUIDocument;
  11.             Document doc = uidoc.Document;
  12.  
  13.             // Выберем балку
  14.  
  15.             SelectionFilterBeam selFilterBeam
  16.               = new SelectionFilterBeam();
  17.  
  18.             Reference r = uidoc.Selection.PickObject(
  19.               ObjectType.Element, selFilterBeam,
  20.               "Выберите балку для отсоединения от плоскости");
  21.  
  22.             FamilyInstance beam = doc.GetElement(r)
  23.               as FamilyInstance;
  24.  
  25.             // Проверим, что балку можно отсоединить от плоскости.
  26.             //
  27.             // Кто то может подумать, что можно просто проверить
  28.             // свойство .Host как в закомментированном коде ниже, НО
  29.             // возможна странная ситуация, когда свойство Host
  30.             // равно null а Revit все еще отображает параметр Рабочая плоскость
  31.             // Со значением <не задано>
  32.             //
  33.             //if (null == beam.Host)
  34.             //{
  35.             //  MessageBox.Show("Выбранный экземпляр семейства 'Каркас несущий' не имеет рабочей плоскости!");
  36.             //  return Result.Cancelled;
  37.             //}
  38.             //           
  39.             // Поэтому, мы должны проверить, что параметр Рабочая плоскость существует
  40.  
  41.             if (null == beam.get_Parameter(
  42.               BuiltInParameter.SKETCH_PLANE_PARAM))
  43.             {
  44.                 MessageBox.Show("Выбранный экземпляр семейства 'Каркас несущий' не имеет рабочей плоскости!");
  45.  
  46.                 return Result.Cancelled;
  47.             }
  48.  
  49.             // Теоретически плоскость может не быть горизонтальной
  50.             // но в 99% случаев она будет именно горизонтальной
  51.             // и в 99,99% балка не будет лежать в вертикальной плосоксти.
  52.             // В этом случае приведенный ниже код не будет работать.
  53.             // Так как свойство .Host только для чтения
  54.             // то единственный способ - это сдвинуть
  55.             // смещение начального и конечного уровней
  56.             // сместив балку с поверхности.
  57.             // Внутренне, Revit тем самым отсоединит балку от плоскости.
  58.             // Затем мы вернем балку назад в прежнее пложение.
  59.             // Заметьте, что простое смещение элемента не будет работать
  60.             // так как балка привязна к плоскости.
  61.            
  62.             double elevOldSta = beam.get_Parameter(
  63.               BuiltInParameter.STRUCTURAL_BEAM_END0_ELEVATION)
  64.                 .AsDouble();
  65.  
  66.             double elevOldEnd = beam.get_Parameter(
  67.               BuiltInParameter.STRUCTURAL_BEAM_END1_ELEVATION)
  68.                 .AsDouble();
  69.  
  70.             double elevTmpSta = elevOldSta + 1.0;
  71.             double elevTmpEnd = elevOldEnd + 1.0;
  72.  
  73.             using (var t = new Transaction(doc, "Отсоединение балки от плоскости"))
  74.             {
  75.                 t.Start();
  76.  
  77.                 // Это приведет к отсоединению балки от плоскости.
  78.  
  79.                 beam.get_Parameter(
  80.                     BuiltInParameter.STRUCTURAL_BEAM_END0_ELEVATION)
  81.                     .Set(elevTmpSta);
  82.  
  83.                 beam.get_Parameter(
  84.                     BuiltInParameter.STRUCTURAL_BEAM_END1_ELEVATION)
  85.                     .Set(elevTmpEnd);
  86.  
  87.                 // вернем балку назад
  88.                 // на прежнее положение
  89.  
  90.                 beam.get_Parameter(
  91.                     BuiltInParameter.STRUCTURAL_BEAM_END0_ELEVATION)
  92.                     .Set(elevOldSta);
  93.  
  94.                 beam.get_Parameter(
  95.                     BuiltInParameter.STRUCTURAL_BEAM_END1_ELEVATION)
  96.                     .Set(elevOldEnd);
  97.  
  98.                 t.Commit();
  99.             }
  100.             MessageBox.Show("Балка отсоединена");
  101.  
  102.             return Result.Succeeded;
  103.         }
  104.     }
  105.  
  106.     class SelectionFilterBeam : ISelectionFilter
  107.     {
  108.         public bool AllowElement(Element e)
  109.         {
  110.             if (!(e is FamilyInstance))
  111.             {
  112.                 return false;
  113.             }
  114.  
  115.             if (e.Category.Id.IntegerValue != (int)
  116.               BuiltInCategory.OST_StructuralFraming)
  117.             {
  118.                 return false;
  119.             }
  120.  
  121.             // не стоит надеяться только на категорию
  122.             // так как это не обязательно может быть балка           
  123.  
  124.             return true;
  125.         }
  126.  
  127.         public bool AllowReference(Reference r, XYZ p)
  128.         {
  129.             return true;
  130.         }
  131.     }

Обратите внимание на множество комментариев в коде.

Также заметьте, что можно немного увеличить производительность, изменяя только смещение одного уровня, вместо двух.

Источник: http://thebuildingcoder.typepad.com/blog/2014/03/detach-beam-from-plane.html

Обсуждение: http://adn-cis.org/forum/index.php?topic=614

Опубликовано 15.03.2014