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

10/11/2013

Как определить месторасположение элемента из связанного файла в системе координат основного файла

Вопрос: Я все воюю со связанными файлами в Revit 2014.

Я прочитал статью Как вывести список элементов из связанного файла (на англ.) и она мне действительно очень помогла.

Проблема в том, что в той статье описывается как получить координаты элемента в системе координат связанного файла.

Скажем, есть у меня связанный файл, в котором находится только одна стена. В этом файле стена располагается в точке 100;100;0.

В основном файле, я поместил эту стену в точку 300;100;0.

Мне нужно определить расположение стены из связанного файла внутри основного файла. То есть я хочу получить координаты 300;100;0.

Как можно это сделать?

Как я уже сказал, код из вышеупомянутой статьи определяет месторасположение стены в координатах связанного файла (100;100;0), а это совсем не те координаты, которые мне нужны.

Код - C#: [Выделить]
  1.  Document d = rvtlink.GetLinkDocument();
  2.   Element e = d.GetElement( id );
  3.   LocationCurve curve = e.Location as LocationCurve;
  4.   XYZ p = curve.Curve.GetEndPoint( 0 );
  5.   XYZ q = curve.Curve.GetEndPoint( 1 );

Чтобы полностью описать и воспроизвести мою проблему, я создал два тестовых проекта, А и В, и две стены – синюю и красную.

Проект А выглядит вот так:

 

Красная стена располагается в нулевой точке (0;0;0) этого проекта. Синяя в точке -12000;0;0

 

Проект В выглядит так:

 

Розовая линия обозначает границу связанного файла проекта А в проекте В.

Проект А располагается в проекте В таким образом, что нулевая точка проекта А находится в точке 5000;5000;0 проекта В.

Как говорил, моя цель – получить координаты расположения красной стены (стены из связанного файла), но в системе координат проекта В.

Таким образом, мне нужен некий алгоритм, с помощью которого я могу определить, что красная стена находится в точке 5000;5000;0, а синяя – в точке -7000;5000;0.

Так как можно это сделать?

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

Код - C#: [Выделить]
  1.   UIApplication uiapp = commandData.Application;
  2.   UIDocument uidoc = uiapp.ActiveUIDocument;
  3.   Document doc = uidoc.Document;
  4.   Selection sel = uidoc.Selection;
  5.  
  6.   Reference r = sel.PickObject(
  7.     ObjectType.Element,
  8.     new LinkSelectionFilter(),
  9.     "Выбериете связанный файл" );
  10.  
  11.   RevitLinkInstance rvtlink = doc.GetElement( r )
  12.     as RevitLinkInstance;
  13.  
  14.   if( rvtlink == null )
  15.   {
  16.     return Result.Failed;
  17.   }
  18.  
  19.   // В примере рассмотрим только
  20.   // синюю и красную стены
  21.  
  22.   var walls = new FilteredElementCollector(
  23.       rvtlink.GetLinkDocument() )
  24.     .OfClass( typeof( Wall ) )
  25.     .Where( c => c.Id.IntegerValue == 179910
  26.       || c.Id.IntegerValue == 179980 );
  27.  
  28.   foreach( Wall wall in walls )
  29.   {
  30.     // Определим координаты; Но эти координаты
  31.     // относятся к связанному файла, т.е. к проекту А.
  32.  
  33.     LocationCurve curve = wall.Location
  34.       as LocationCurve;
  35.  
  36.     XYZ p = curve.Curve.GetEndPoint( 0 );
  37.     XYZ q = curve.Curve.GetEndPoint( 1 );
  38.  
  39.     if( wall.Id.IntegerValue == 179910 )
  40.     {
  41.       TaskDialog.Show( "Красная стена",
  42.         "Красная стена располагается в точке "
  43.         + PointString( p ) );
  44.     }
  45.     else
  46.     {
  47.       TaskDialog.Show( "Синяя стена",
  48.         "Синяя стена располагается в точке: "
  49.         + PointString( p ) );
  50.     }
  51.  
  52.     // Так как определить координаты
  53.     // синей и красной стен в системе координат
  54.     // проекта В?
  55.   }
  56.   return Result.Succeeded;

Как мне реализовать последний шаг?

Ответ: На самом деле, очень легко.

Перед тем как углубиться в детали, я хотел бы заметить, что я недавно обсуждал как получить доступ к отдельным элементам из связанного файла (на англ.) и там я указывал достаточно большое количеств ссылок на подобные темы.

Класс RevitLinkInstance наследуется от класса Instance. Класс содержит метод GetTransform, с помощью которого можно получить данные о преобразовании элемента, а также метод GetTotalTransform, который возвращает текущее преобразование элемента с направлением на север.

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

Этого легко достичь, используя свойство Location класса RevitLinkInstance, чтобы определить смещение координаты связанного файла относительно основного, а затем применить это смещение к координатам, которые вы уже смогли получить.

Кстати, я хотел бы заметить, что вы значительно усложняете отладку кода, работая с миллиметрами в пользовательском интерфейсе, так как все значения внутри базы данных файла Revit хранятся в футах.

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

Код - C#: [Выделить]
  1.   const double _inch_to_mm = 25.4;
  2.   const double _foot_to_mm = 12 * _inch_to_mm;
  3.  
  4.   /// <summary>
  5.   /// Возвращает строку для числа с плавающей точкой
  6.   /// отформатированную до двух знаков после запятой
  7.   /// </summary>
  8.   public static string RealString( double a )
  9.   {
  10.     return a.ToString( "0.##" );
  11.   }
  12.  
  13.   /// <summary>
  14.   /// Возвращает строку для трехмерной точки XYZ
  15.   /// или вектора с координатами этой точки
  16.   /// преобразованную из футов в миллиметры
  17.   /// и отформатированную до двух знаков после запятой
  18.   /// </summary>
  19.   public static string PointStringMm( XYZ p )
  20.   {
  21.     return string.Format( "({0},{1},{2})",
  22.       RealString( p.X * _foot_to_mm ),
  23.       RealString( p.Y * _foot_to_mm ),
  24.       RealString( p.Z * _foot_to_mm ) );
  25.   }

Запустив команду на тестовом проекте, мы увидим два сообщения, по одному для каждой стены. Вот такое сообщение для красной стены:

 

И точно такое же для синей:

 

Примечание: в исходной статье не были представлены файлы проектов А и В. Я создал подобные файлы, но координаты там немного различаются. Файлы проектов, используемых в статье, можно скачать по ссылке ниже.

Надеюсь я полностью ответил на ваш вопрос.

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

Источник: http://thebuildingcoder.typepad.com/blog/2013/11/determining-host-document-location-of-a-linked-element.html

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

Опубликовано 10.11.2013
Отредактировано 10.11.2013 в 11:08:17