27/10/2014
Видимость элемента на заданном виде
Видимость элемента на заданном виде
Последнее время уже несколько человек спрашивали меня о том, как определить видимость элемента относительно заданной области подрезки на конкретном виде.
Здесь я хочу рассказать о неплохом решение в виде метода IsElementHiddenInView, который можно добавить в любую надстройку, и который поможет дать ответ на поставленный выше вопрос. Метод предоставил Frode Tørresdal из компании Norconsult Informasjonssystemer AS.
Для любого элемента e и вида v, метод возвращает true, если элемент e виден на виде v.
Проверка происходит по следующему алгоритму:
-
Задана ли область подрезки на виде? Располагается ли элемент e полностью вне границ области подрезки? Если нет, лежит ли менее 25% элемента в границах области подрезки?
-
Спрятан ли элемент на этом виде?
-
Спрятана ли категория или одна из родительских категорий элемента на виде?
Вот код метода:
Код - C#: [Выделить]
/// <summary>
/// Возвращает true если элемент спрятан на виде
/// Это может быть в случаях если:
/// - Элемент располагается за пределами области подрезки
/// - Элемент скрыт на виде
/// - Категория элемента или родительская категория скрыта на виде.
/// </summary>
bool IsElementHiddenInView(
Element e,
View v )
{
if( v.CropBoxActive )
{
BoundingBoxXYZ viewBox = v.CropBox;
BoundingBoxXYZ elBox = e.get_BoundingBox( v );
Transform transInv = v.CropBox.Transform.Inverse;
elBox.Max = transInv.OfPoint( elBox.Max );
elBox.Min = transInv.OfPoint( elBox.Min );
if( elBox.Min.X > elBox.Max.X )
{
XYZ tmpP = elBox.Min;
elBox.Min = new XYZ( elBox.Max.X, elBox.Min.Y, 0 );
elBox.Max = new XYZ( tmpP.X, elBox.Max.Y, 0 );
}
if( elBox.Min.Y > elBox.Max.Y )
{
XYZ tmpP = elBox.Min;
elBox.Min = new XYZ( elBox.Min.X, elBox.Max.Y, 0 );
elBox.Max = new XYZ( tmpP.X, elBox.Min.Y, 0 );
}
if( elBox.Min.X > viewBox.Max.X
|| elBox.Max.X < viewBox.Min.X
|| elBox.Min.Y > viewBox.Max.Y
|| elBox.Max.Y < viewBox.Min.Y )
{
return true;
}
else
{
BoundingBoxXYZ inside = new BoundingBoxXYZ();
double x, y;
x = elBox.Max.X;
if( elBox.Max.X > viewBox.Max.X )
x = viewBox.Max.X;
y = elBox.Max.Y;
if( elBox.Max.Y > viewBox.Max.Y )
y = viewBox.Max.Y;
inside.Max = new XYZ( x, y, 0 );
x = elBox.Min.X;
if( elBox.Min.X < viewBox.Min.X )
x = viewBox.Min.X;
y = elBox.Min.Y;
if( elBox.Min.Y < viewBox.Min.Y )
y = viewBox.Min.Y;
inside.Min = new XYZ( x, y, 0 );
double eBBArea = ( elBox.Max.X - elBox.Min.X )
* ( elBox.Max.Y - elBox.Min.Y );
double einsideArea =
( inside.Max.X - inside.Min.X )
* ( inside.Max.Y - inside.Min.Y );
double factor = einsideArea / eBBArea;
if( factor < 0.25 )
return true;
}
}
bool hidden = e.IsHidden( v );
if( !hidden )
{
Category cat = e.Category;
while( null != cat && !hidden )
{
hidden = !cat.get_Visible( v );
cat = cat.Parent;
}
}
return hidden;
}
Единственной особенностью метода, которую следовало бы отметить, является сравнение границ элемента и границы области подрезки.
Для того чтобы сравнить границы элемента и области подрезки, необходимо применить трансформацию границы области подрезки.
Это может привести к замены относительного положения минимальных и максимальных значений. Поэтому мы должны проверить, что минимальное значение является действительно минимальным и найти действительно минимальные значения.
Большое спасибо Frode за решине.
Этот метод добавлен в примеры The Building Coder.
Источник: http://thebuildingcoder.typepad.com/blog/2014/10/is-a-given-element-hidden-in-a-view.html