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

24/04/2014

Использование метода NewTakeOffFitting для создания врезки

Вопрос: В середине одного из воздуховодов моей MEP модели я хочу сделать врезку. В API для этого есть метод NewTakeOffFitting, который принимает 2 аргумента: коннектор и MEP-кривую (трубу, воздуховод, кабельные лотки) и возвращает созданный экземпляр семейства. Вопрос состоит в том, что я не пойму, как создать эту кривую и коннектор. Можете привести пример кода по созданию врезки с использованием этого метода? Спасибо

Ответ: Для начала я бы посоветовал просмотреть примеры AutoRoute и AvoidObstruction из примеров Revit SDK, в которых показано, как программно создавать трубы, воздуховоды и фитинги к ним.

Я так же просмотрел пример создания и позиционирования фитингов кабельных лотков.

Однако ни в одном из этих примеров нет явного использования метода NewTakeOffFitting.

Метод NewTakeOffFitting используется для вставки нового экземпляра семейства, представляющего фитинг врезки, с помощью одного коннектора и одной MEP-кривой.

 

MEP-кривая представляет собой трубу или воздуховод. Коннектор принадлежит другому элементу, который мы хотим присоединить.

Я создал небольшой пример CreateTakeoff для демонстрации использования этого метода. На самом деле, при создании я столкнулся с некоторыми проблемами. Основные из них это какой элемент воздуховода использовать и как их позиционировать.

Ниже представлен полный код команды для создания врезки:

Код - C#: [Выделить]
  1.         public Result Execute(ExternalCommandData commandData,
  2.               ref string message,
  3.               ElementSet elements)
  4.         {
  5.             Result result = Result.Failed;
  6.  
  7.             UIApplication uiapp = commandData.Application;
  8.             Document doc = uiapp.ActiveUIDocument.Document;
  9.  
  10.             Transaction t = null;
  11.  
  12.             Autodesk.Revit.Creation.Document creDoc
  13.               = doc.Create;
  14.  
  15.             try
  16.             {
  17.                 // determine duct type to use:
  18.  
  19.                 FilteredElementCollector collector
  20.                   = new FilteredElementCollector(doc);
  21.  
  22.                 collector.OfCategory(
  23.                   BuiltInCategory.OST_DuctCurves);
  24.  
  25.                 collector.OfClass(typeof(
  26.                   ElementType));
  27.  
  28.                 DuctType ductType
  29.                   = collector.FirstElement() as DuctType;
  30.  
  31.                 if (null == ductType)
  32.                 {
  33.                     message = ("Не найден тип воздуховода");
  34.                     return Result.Failed;
  35.                 }
  36.                 else
  37.                 {
  38.                     t = new Transaction(doc, "Создание врезки");
  39.  
  40.                     t.Start();
  41.  
  42.                     // Создадим воздуховод1 вдоль оси Х
  43.                     // c (0,0,0) до (6,0,0):
  44.  
  45.                     XYZ start = XYZ.Zero;
  46.                     XYZ end = start + 6 * XYZ.BasisX;
  47.                     XYZ mid = 0.5 * (start + end);
  48.  
  49.                     Duct duct1 = creDoc.NewDuct(
  50.                       start, end, ductType);
  51.  
  52.                     // создадим воздуховод2 параллельно оси Y
  53.                     // с (1,2,0) по (1,4,0):
  54.  
  55.                     start = mid + 2 * XYZ.BasisY;
  56.                     end = start - 2 * XYZ.BasisY;
  57.  
  58.                     Duct duct2 = creDoc.NewDuct(
  59.                       start, end, ductType);
  60.  
  61.                     // выберем ближайщий к первому воздуховоду коннектор
  62.                     // на втором воздуховоде.
  63.  
  64.                     Connector duct2_start = null;
  65.  
  66.                     // Просто взять первый попавшийся не получится
  67.                     // так как порядок может измениться.
  68.                     // нужно всегда учитывать месторасположение коннектора
  69.  
  70.                     double dist = double.MaxValue;
  71.  
  72.                     foreach (Connector c in
  73.                       duct2.ConnectorManager.Connectors)
  74.                     {
  75.                         XYZ p = c.Origin;
  76.                         double d = p.DistanceTo(mid);
  77.  
  78.                         if (d < dist)
  79.                         {
  80.                             dist = d;
  81.                             duct2_start = c;
  82.                         }
  83.                         break;
  84.                     }
  85.  
  86.                     // создадим врезку
  87.  
  88.                     FamilyInstance takeoff
  89.                       = creDoc.NewTakeoffFitting(
  90.                         duct2_start, duct1);
  91.  
  92.                     t.Commit();
  93.  
  94.                     result = Result.Succeeded;
  95.                 }
  96.             }
  97.             catch (Exception ex)
  98.             {
  99.                 if (null != t)
  100.                 {
  101.                     t.RollBack();
  102.                 }
  103.                 message = ex.Message;
  104.             }
  105.             return result;
  106.         }
  107.     }

Важно запомнить, что вы не можете полагаться на порядок коннекторов, который возвращает вам ConnectorManager, так как этот порядок может меняться. Поэтому мы не можем просто взять скажем первый попавшийся коннектор. Нужно учитывать другие критерии при поиски коннектора, например, месторасположение. В своем коде я определяю расстояние коннекторов второго воздуховода до центра первого и беру ближайший.

С другой стороны, можно попробовать расположить воздуховод таким образом, что его коннектор будет располагаться практически на середине и в этом случае можно использовать метод XYZ.IsAlmostEqualTo.

Вот результат выполнения команды:

 

Ради интереса попробовал запустить команду в Revit Architecture. Но сразу же получил ошибку что эта возможность доступна только в Revit MEP.

Скачать готовый проект с примером можно по ссылке.

Источник: http://thebuildingcoder.typepad.com/blog/2011/02/use-of-newtakeofffitting-on-a-duct.html

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

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