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

14/12/2014

Полезный вспомогательный класс для выбора двух элементов

Вчера мы обсуждали как создать размер между центрами семейств. Код команды, переведённый в том примере, довольно небольшой.

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

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

Класс довольно гибок в использовании и поддерживает три различных варианта выбора элементов:

  • Если в модели содержится только два элемента заданного типа, они автоматически будут выбраны.
  • Если в модели отсутствует два элемента заданного типа, выполнение команды будет прервано.
  • Если в модели больше чем два элемента заданного типа, то предварительно происходит проверка, не выделены ли элементы этого типа перед запуском команды. Если элементы были выделены, то используются первые два.
  • В любом другом случае пользователю предлагается выбрать два элемента требуемого типа.

Реализация класса основана на коде из статьи явное создание отводов при создании наклонного сегмента трубопровода, в котором выбор код по выбору труб занимал значительную часть кода.

Выделив выбор объектов в отдельный класс, код команды стал гораздо компактнее.

Реализованный класс – типизированный. В примере с размерами для выбора элементов был задан тип FamiliyInstance.

Вот полная реализация класса:

Код - C#: [Выделить]
  1. /// <summary>
  2. /// Выбор двух элементов заданного типа.
  3. /// Если в модели только два объекта заданного типа, берем их.
  4. /// Если элементов меньше чем два, прерываем выполнение.
  5.  /// Если перед запуском команды элементы были уже выделены, используем их.
  6. /// В противном случае предлагаем выбрать элементы пользователю
  7. /// </summary>
  8. class JtPairPicker<T> where T : Element
  9. {
  10.   UIDocument _uidoc;
  11.   Document _doc;
  12.   List<T> _a;
  13.  
  14.   /// <summary>
  15.   /// Разрешаем только выбор элементов типа T2.
  16.   /// </summary>
  17.   class ElementsOfClassSelectionFilter<T2> : ISelectionFilter
  18.   {
  19.     public bool AllowElement( Element e )
  20.     {
  21.       return e is T2;
  22.     }
  23.  
  24.     public bool AllowReference( Reference r, XYZ p )
  25.     {
  26.       return true;
  27.     }
  28.   }
  29.  
  30.   public JtPairPicker( UIDocument uidoc )
  31.   {
  32.     _uidoc = uidoc;
  33.     _doc = _uidoc.Document;
  34.   }
  35.  
  36.   /// <summary>
  37.   /// Возвращает результат выделения
  38.   /// </summary>
  39.   public IList<T> Selected
  40.   {
  41.     get
  42.     {
  43.       return _a;
  44.     }
  45.   }
  46.  
  47.   /// <summary>
  48.   /// Запуск автоматического или интерактивного
  49.   /// процесса выделения.
  50.   /// </summary>
  51.   public Result Pick()
  52.   {
  53.     // Извлекаем из модели все элементы типа T
  54.  
  55.     _a = new List<T>(
  56.       new FilteredElementCollector( _doc )
  57.         .OfClass( typeof( T ) )
  58.         .ToElements()
  59.         .Cast<T>() );
  60.  
  61.     int n = _a.Count;
  62.  
  63.     // Если элементов в модели меньше чем два,
  64.     // то продолжать безссмысленно.
  65.  
  66.     if( 2 > n )
  67.     {
  68.       return Result.Failed;
  69.     }
  70.  
  71.     // Если элементов всего два – берем их.
  72.  
  73.     if( 2 == n )
  74.     {
  75.       return Result.Succeeded;
  76.     }
  77.  
  78.     // Если элементов больше чем два.
  79.     // Проверяем не выбраны ли они перед запуском команды.
  80.  
  81.     _a.Clear();
  82.  
  83.     Selection sel = _uidoc.Selection;
  84.  
  85.     ICollection<ElementId> ids
  86.       = sel.GetElementIds();
  87.  
  88.     n = ids.Count;
  89.  
  90.     Debug.Print( "{0} pre-selected elements.", n );
  91.  
  92.     // Если было выбрано два или более элементов типа T -
  93.     // берем первые два.
  94.  
  95.     if( 1 < n )
  96.     {
  97.       foreach( ElementId id in ids )
  98.       {
  99.         T e = _doc.GetElement( id ) as T;
  100.  
  101.         Debug.Assert( null != e,
  102.           "Могут быть выбраны элементы только типа T" );
  103.  
  104.         _a.Add( e );
  105.  
  106.         if( 2 == _a.Count )
  107.         {
  108.           Debug.Print( "Нашли два элемента заданного типа. Игнорируем все остальное");
  109.  
  110.           break;
  111.         }
  112.       }
  113.     }
  114.  
  115.     // Если ничего не выбрано или выбрано меньше чем два элемента
  116.     // предлагаем пользователю выбрать элементы
  117.     if( 2 != _a.Count )
  118.     {
  119.       _a.Clear();
  120.  
  121.       // Выбираем первый элемент.
  122.  
  123.       try
  124.       {
  125.         Reference r = sel.PickObject(
  126.           ObjectType.Element,
  127.           new ElementsOfClassSelectionFilter<T>(),
  128.           "Выберите первый элемент." );
  129.  
  130.         _a.Add( _doc.GetElement( r.ElementId )
  131.           as T );
  132.       }
  133.       catch( Autodesk.Revit.Exceptions
  134.         .OperationCanceledException )
  135.       {
  136.         return Result.Cancelled;
  137.       }
  138.  
  139.       // Выбираем второй элемент.
  140.  
  141.       try
  142.       {
  143.         Reference r = sel.PickObject(
  144.           ObjectType.Element,
  145.           new ElementsOfClassSelectionFilter<T>(),
  146.           " Выберите второй элемент." );
  147.  
  148.         _a.Add( _doc.GetElement( r.ElementId )
  149.           as T );
  150.       }
  151.       catch( Autodesk.Revit.Exceptions
  152.         .OperationCanceledException )
  153.       {
  154.         return Result.Cancelled;
  155.       }
  156.     }
  157.     return Result.Succeeded;
  158.   }
  159. }

Источник: http://thebuildingcoder.typepad.com/blog/2014/11/picking-pairs-and-dimensioning-family-instance-origin.html#4

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

Опубликовано 14.12.2014
Отредактировано 27.12.2014 в 15:18:43