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

27/10/2015

Преобразование координат листа в координаты модели

Вопрос: Вы отмечали, что в Revit API есть пробел, связанный с конвертацией между координатами модели и координатами листа. Это как раз то, с чем мы столкнулись.

Нам нужно получить границы геометрии элемента на листе.

В Revit 2016 этот пробел все еще существует? Есть ли какой-то способ обойти это ограничение?

Ответ: Да, все еще есть. Однако, возможно довольно легко преобразовать координаты из координат листа в координаты модели, например, поместить текстовые метки и другие геометрические элементы, основываясь на каком либо объекте, находящимся на листе, например, на связанной пометке DWF.

Paolo Serra, технический консультант по BIM из Миланского офиса Autodesk, предоставил отличный пример, демонстрирующий данную возможность:

Я делал что-то подобное для клиента в Италии. Предполагая, что мы работаем с тем же самым уровнем на виде, что и на видовом экране листа, я взял пометки DWF (дуги и полилинии), для создания текстовый пометок, например. Вот что у меня получилось. Надеюсь это поможет.

Jeremy:  Я реализовал новую команду CmdSheetToModel в примерах The Building Coder, версия 2016.0.121.0 и поместил туда код Paolo.

Пример преобразования координат

Я запустил команду в простом примере модели Revit со связанным DWFx файлом:

 

Вот как выглядит видовой экран, из которого мы возьмем координаты.

  

 В команде я читаю пометки DWF в координатах листа, конвертирую их в координаты модели и добавляю тектовые метки в центре каждой дуги из DWF файла.

 

Сгенерированные пометки выглядят вот так:

 

Код команды:

Код - C#: [Выделить]
  1.   [Transaction( TransactionMode.Manual )]
  2.   class CmdSheetToModel : IExternalCommand
  3.   {
  4.     public void QTO_2_PlaceHoldersFromDWFMarkups(
  5.       Document doc,
  6.       string activityId )
  7.     {
  8.       View activeView = doc.ActiveView;
  9.  
  10.       if( !( activeView is ViewSheet ) )
  11.       {
  12.         TaskDialog.Show( "QTO",
  13.           "Команда должна выполняться на листе с импортированными пометками DWF" );
  14.         return;
  15.       }
  16.  
  17.       ViewSheet vs = activeView as ViewSheet;
  18.  
  19.       Viewport vp = doc.GetElement(
  20.         vs.GetAllViewports().First() ) as Viewport;
  21.  
  22.       View plan = doc.GetElement( vp.ViewId ) as View;
  23.  
  24.       int scale = vp.Parameters.Cast<Parameter>()
  25.         .First( x => x.Id.IntegerValue.Equals(
  26.           (int) BuiltInParameter.VIEW_SCALE ) )
  27.         .AsInteger();
  28.  
  29.       IEnumerable<Element> dwfMarkups
  30.         = new FilteredElementCollector( doc )
  31.           .OfClass( typeof( ImportInstance ) )
  32.           .WhereElementIsNotElementType()
  33.           .Where( x => x.Name.StartsWith( "Markup" )
  34.             && x.OwnerViewId.IntegerValue.Equals(
  35.               activeView.Id.IntegerValue ) );
  36.  
  37.       using( TransactionGroup tg = new TransactionGroup( doc ) )
  38.       {
  39.         tg.Start( "DWF markups placeholders" );
  40.  
  41.         using( Transaction t = new Transaction( doc ) )
  42.         {
  43.           t.Start( "DWF Transfer" );
  44.  
  45.           plan.Parameters.Cast<Parameter>()
  46.             .First( x => x.Id.IntegerValue.Equals(
  47.               (int) BuiltInParameter.VIEWER_CROP_REGION ) )
  48.             .Set( 1 );
  49.  
  50.           XYZ VC = ( plan.CropBox.Min + plan.CropBox.Max ) / 2;
  51.  
  52.           XYZ BC = vp.GetBoxCenter();
  53.  
  54.           t.RollBack();
  55.  
  56.           foreach( Element e in dwfMarkups )
  57.           {
  58.             GeometryElement GeoElem = e.get_Geometry( new Options() );
  59.  
  60.             GeometryInstance gi = GeoElem.Cast<GeometryInstance>().First();
  61.  
  62.             GeometryElement gei = gi.GetSymbolGeometry();
  63.  
  64.             IList<GeometryObject> gos = new List<GeometryObject>();
  65.  
  66.             if( gei.Cast<GeometryObject>().Count( x => x is Arc ) > 0 )
  67.             {
  68.               continue;
  69.             }
  70.  
  71.             foreach( GeometryObject go in gei )
  72.             {
  73.               XYZ med = new XYZ();
  74.  
  75.               if( go is PolyLine )
  76.               {
  77.                 PolyLine pl = go as PolyLine;
  78.  
  79.                 XYZ min = new XYZ( pl.GetCoordinates().Min( p => p.X ),
  80.                                 pl.GetCoordinates().Min( p => p.Y ),
  81.                                 pl.GetCoordinates().Min( p => p.Z ) );
  82.  
  83.                 XYZ max = new XYZ( pl.GetCoordinates().Max( p => p.X ),
  84.                                 pl.GetCoordinates().Max( p => p.Y ),
  85.                                 pl.GetCoordinates().Max( p => p.Z ) );
  86.  
  87.                 med = ( min + max ) / 2;
  88.               }
  89.  
  90.               med = med - BC;
  91.  
  92.               // конвертируем координаты DWF из листовых в координаты модели
  93.  
  94.               XYZ a = VC + new XYZ( med.X * scale, med.Y * scale, 0 );
  95.             }
  96.           }
  97.  
  98.           t.Start( "DWF Transfer" );
  99.  
  100.           foreach( Element e in dwfMarkups )
  101.           {
  102.             GeometryElement GeoElem = e.get_Geometry( new Options() );
  103.  
  104.             GeometryInstance gi = GeoElem.Cast<GeometryInstance>().First();
  105.  
  106.             GeometryElement gei = gi.GetSymbolGeometry();
  107.  
  108.             IList<GeometryObject> gos = new List<GeometryObject>();
  109.  
  110.             if( gei.Cast<GeometryObject>().Count( x => x is Arc ) == 0 )
  111.             {
  112.               continue;
  113.             }
  114.  
  115.             foreach( GeometryObject go in gei )
  116.             {
  117.               if( go is Arc )
  118.               {
  119.                 Curve c = go as Curve;
  120.  
  121.                 XYZ med = c.Evaluate( 0.5, true );
  122.  
  123.                 med = med - BC;
  124.  
  125.                 XYZ a = VC + new XYZ( med.X * scale, med.Y * scale, 0 );
  126.  
  127.                 // Warning CS0618:
  128.                 // Autodesk.Revit.Creation.ItemFactoryBase.NewTextNote(
  129.                 //   View, XYZ, XYZ, XYZ, double, TextAlignFlags, string)
  130.                 // is obsolete:
  131.                 // This method is deprecated in Revit 2016.
  132.                 // Please use one of the TextNote.Create methods instead.
  133.  
  134.                 //doc.Create.NewTextNote( plan,
  135.                 //                       a,
  136.                 //                       XYZ.BasisX,
  137.                 //                       XYZ.BasisY,
  138.                 //                       MMtoFeet( 5 ),
  139.                 //                       TextAlignFlags.TEF_ALIGN_CENTER,
  140.                 //                       activityId );
  141.  
  142.                 ElementId textTypeId = new FilteredElementCollector( doc )
  143.                   .OfClass( typeof( TextNoteType ) )
  144.                   .FirstElementId();
  145.  
  146.                 TextNote.Create( doc, plan.Id, a, activityId, textTypeId );
  147.               }
  148.             }
  149.  
  150.             t.Commit();
  151.           }
  152.         }
  153.  
  154.         tg.Assimilate();
  155.       }
  156.     }
  157.  
  158.     public Result Execute(
  159.       ExternalCommandData commandData,
  160.       ref string message,
  161.       ElementSet elements )
  162.     {
  163.       UIApplication uiapp = commandData.Application;
  164.       Document doc = uiapp.ActiveUIDocument.Document;
  165.  
  166.       QTO_2_PlaceHoldersFromDWFMarkups(
  167.         doc, "DWF Markup" );
  168.  
  169.       return Result.Succeeded;
  170.     }

Источник: http://thebuildingcoder.typepad.com/blog/2015/10/sheet-to-model-coordinate-conversion.html

Автор перевода: Виктор Чекалин

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

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