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

27/10/2014

Видимость элемента на заданном виде

Видимость элемента на заданном виде

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

Здесь я хочу рассказать о неплохом решение в виде метода IsElementHiddenInView, который можно добавить в любую надстройку, и который поможет дать ответ на поставленный выше вопрос. Метод предоставил Frode Tørresdal из компании Norconsult Informasjonssystemer AS.

Для любого элемента e и вида v, метод возвращает true, если элемент e виден на виде v.

Проверка происходит по следующему алгоритму:

  • Задана ли область подрезки на виде? Располагается ли элемент e полностью вне границ области подрезки? Если нет, лежит ли менее 25% элемента в границах области подрезки?

  • Спрятан ли элемент на этом виде?

  • Спрятана ли категория или одна из родительских категорий элемента на виде?

Вот код метода:

Код - C#: [Выделить]
  1. /// <summary>
  2.   /// Возвращает true если элемент спрятан на виде
  3.   /// Это может быть в случаях если:
  4.   /// - Элемент располагается за пределами области подрезки
  5.   /// - Элемент скрыт на виде
  6.   /// - Категория элемента или родительская категория скрыта на виде.
  7.   /// </summary>
  8.   bool IsElementHiddenInView(
  9.     Element e,
  10.     View v )
  11.   {
  12.     if( v.CropBoxActive )
  13.     {
  14.       BoundingBoxXYZ viewBox = v.CropBox;
  15.       BoundingBoxXYZ elBox = e.get_BoundingBox( v );
  16.  
  17.       Transform transInv = v.CropBox.Transform.Inverse;
  18.  
  19.       elBox.Max = transInv.OfPoint( elBox.Max );
  20.       elBox.Min = transInv.OfPoint( elBox.Min );
  21.  
  22.       if( elBox.Min.X > elBox.Max.X )
  23.       {
  24.         XYZ tmpP = elBox.Min;
  25.         elBox.Min = new XYZ( elBox.Max.X, elBox.Min.Y, 0 );
  26.         elBox.Max = new XYZ( tmpP.X, elBox.Max.Y, 0 );
  27.       }
  28.  
  29.       if( elBox.Min.Y > elBox.Max.Y )
  30.       {
  31.         XYZ tmpP = elBox.Min;
  32.         elBox.Min = new XYZ( elBox.Min.X, elBox.Max.Y, 0 );
  33.         elBox.Max = new XYZ( tmpP.X, elBox.Min.Y, 0 );
  34.       }
  35.  
  36.       if( elBox.Min.X > viewBox.Max.X
  37.         || elBox.Max.X < viewBox.Min.X
  38.         || elBox.Min.Y > viewBox.Max.Y
  39.         || elBox.Max.Y < viewBox.Min.Y )
  40.       {
  41.         return true;
  42.       }
  43.       else
  44.       {
  45.         BoundingBoxXYZ inside = new BoundingBoxXYZ();
  46.         double x, y;
  47.         x = elBox.Max.X;
  48.  
  49.         if( elBox.Max.X > viewBox.Max.X )
  50.           x = viewBox.Max.X;
  51.  
  52.         y = elBox.Max.Y;
  53.  
  54.         if( elBox.Max.Y > viewBox.Max.Y )
  55.           y = viewBox.Max.Y;
  56.  
  57.         inside.Max = new XYZ( x, y, 0 );
  58.  
  59.         x = elBox.Min.X;
  60.  
  61.         if( elBox.Min.X < viewBox.Min.X )
  62.           x = viewBox.Min.X;
  63.  
  64.         y = elBox.Min.Y;
  65.  
  66.         if( elBox.Min.Y < viewBox.Min.Y )
  67.           y = viewBox.Min.Y;
  68.  
  69.         inside.Min = new XYZ( x, y, 0 );
  70.  
  71.         double eBBArea = ( elBox.Max.X - elBox.Min.X )
  72.           * ( elBox.Max.Y - elBox.Min.Y );
  73.  
  74.         double einsideArea =
  75.           ( inside.Max.X - inside.Min.X )
  76.           * ( inside.Max.Y - inside.Min.Y );
  77.  
  78.         double factor = einsideArea / eBBArea;
  79.  
  80.         if( factor < 0.25 )
  81.           return true;
  82.       }
  83.     }
  84.     bool hidden = e.IsHidden( v );
  85.     if( !hidden )
  86.     {
  87.       Category cat = e.Category;
  88.       while( null != cat && !hidden )
  89.       {
  90.         hidden = !cat.get_Visible( v );
  91.         cat = cat.Parent;
  92.       }
  93.     }
  94.     return hidden;
  95.   }

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

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

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

Большое спасибо Frode за решине.

Этот метод добавлен в примеры The Building Coder.

Источник: http://thebuildingcoder.typepad.com/blog/2014/10/is-a-given-element-hidden-in-a-view.html

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

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