Как узнать текущие размеры динамического блока?

Автор Тема: Как узнать текущие размеры динамического блока?  (Прочитано 15462 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн JohnJАвтор темы

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
Есть документ (в приложении), в котором размеры динамического блока, определяемые по следующим точкам,
Код - Text [Выбрать]
  1.     var p1 = br.GeometricExtents.MinPoint;
  2.     var p2 = br.GeometricExtents.MaxPoint;
  3.  
оказываются равны 297 по вертикали и около 3000 по горизонтали, хотя на чертеже этот блок шириной с лист A4 (210), но при некоторых значениях Видимости может расширяться до 3000.

Как определить действительные размеры отображения этого блока при текущем значении Видимости? Я ничего похожего не нашёл среди свойств объекта в отладчике, ничего не нашёл и в интернете по запросу "c# autocad size of dynamic block", кроме одной статьи Accessing visible entities in a dynamic block ...
Не знаю, подойдёт ли мне этот метод, возможно есть способ проще? В данной задаче мне не требуется перебирать объекты блока. Просто - узнать контурные размеры.
« Последнее редактирование: 18-12-2014, 09:07:52 от Александр Ривилис »

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13877
  • Карма: 1785
  • Рыцарь ObjectARX
  • Skype: rivilis
В данной задаче мне не требуется перебирать объекты блока. Просто - узнать контурные размеры.
Боюсь что без перебора ничего не получится. Если тебе нужны точные размеры, то придется перебирать все элементы блока и вычислять их размер. Только  не элементы основного динамического блока, а того, который получается в этой видимости (анонимного).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн JohnJАвтор темы

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
Понял, т.е. нужно перебирать элементы определения блока, полученного по br.AnonymousBlockTableRecord?

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13877
  • Карма: 1785
  • Рыцарь ObjectARX
  • Skype: rivilis
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн JohnJАвтор темы

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
Перебрал все элементы BlockTableRecord от AnonymousBlockTableRecord. Среди них находятся полилинии всех длин (смотрел по GeometricExtensts полилиний), вплоть до 3000 с хвостиком. Как определять, какие видны именно в данный момент?

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Я использовал метод Explode и определял границы получившихся примитивов. Конечно, есть варианты, когда способ метод может дать неправильный результат, но в моем случае меня устроило. А иначе, нужно: перебрать все примитивы внутри, проверить их видимость (есть какое-то свойство для этого), трансформировать координаты примитива в соответствии с настройками блока...

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13877
  • Карма: 1785
  • Рыцарь ObjectARX
  • Skype: rivilis
Перебрал все элементы BlockTableRecord от AnonymousBlockTableRecord. Среди них находятся полилинии всех длин (смотрел по GeometricExtensts полилиний), вплоть до 3000 с хвостиком. Как определять, какие видны именно в данный момент?
Обратил внимание, что у них свойство Visible в False:
 
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн JohnJАвтор темы

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
Хех, забавно! Я ещё было подумал: "жаль, что нет свойства какого-нибудь, вроде Visible". Не заметил его что-то...
Спасибо!
« Последнее редактирование: 19-12-2014, 10:39:18 от JohnJ »

Оффлайн Дмитрий Загорулькин

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 737
Тут даже не в матрицах дело... Чтобы было понятнее - прикладываю картинку.
Пока отвечал, вопрос на который отвечал уже удалили  :)

Оффлайн JohnJАвтор темы

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
ну то, что при повороте совсем другая оконтовка - это я понимаю. Поэтому я поворот и не учитываю, что бы не делать сейчас не нужных мне расчётов.
Про матрицы я спрашивал в том смысле, что мне не нравится мой подход: я пересоздаю Extents каждый раз по рассчитанным "вручную" точкам, хотя предчувствую, что должны быть встроенные методы изменения величин с помощью матриц трансформации. Но у меня не получилось их использовать.
Код свой я пока убрал - на пробном чертеже он срабатывал, а на реальном начал сбоить. Сейчас переделаю и выложу ещё раз.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13877
  • Карма: 1785
  • Рыцарь ObjectARX
  • Skype: rivilis
BlockReference.BlockTransform далжно дать тебе нужную матрицу, при помощи которой ты можешь преобразовать Extents3d методом Extents3d.TransformBy. Но это даст тебе параллельный осям параллелепипед. Тебе это нужно?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн JohnJАвтор темы

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
Так замотался, что забыл выложить получившийся код. А ведь хочется услышать советы по оптимизации.
Код - C# [Выбрать]
  1. public Extents3d GetBlockGeometricExtents(BlockReference block, Transaction trn = null) {
  2.             Extents3d? extents = null;
  3.             if (!block.IsDynamicBlock) return block.GeometricExtents;
  4.             MakeInTransaction(trn, tr => {
  5.                 var entities = FindAll(block.BlockTableRecord, TYPE_ANY, tr).Where(e => e.Visible);
  6.                 foreach (var ent in entities) {
  7.                     try {
  8.                         if (extents == null) {
  9.                             extents = ent.GeometricExtents;
  10.                         } else {
  11.                             var mip1 = extents.Value.MinPoint;
  12.                             var mip2 = ent.GeometricExtents.MinPoint;
  13.                             var map1 = extents.Value.MaxPoint;
  14.                             var map2 = ent.GeometricExtents.MaxPoint;
  15.                             var pe1 = new Point3d(Math.Min(mip1.X, mip2.X), Math.Min(mip1.Y, mip2.Y), Math.Min(mip1.Z, mip2.Z));
  16.                             var pe2 = new Point3d(Math.Max(map1.X, map2.X), Math.Max(map1.Y, map2.Y), Math.Max(map1.Z, map2.Z));
  17.                             extents = new Extents3d(pe1, pe2); //extents.Value.AddExtents(ent.GeometricExtents);
  18.                         }
  19.                     } catch { // ent выдаёт ошибку при обращении к GeometricExtents, если это не графический элемент (например, атрибут блока)
  20.                        
  21.                     }
  22.                 }
  23.                 if (extents == null) return;
  24.                 var vp = block.Position.GetAsVector();
  25.                 var p1 = ((Extents3d) extents).MinPoint + vp;
  26.                 var maxp = ((Extents3d) extents).MaxPoint;
  27.                 var scl = block.ScaleFactors;
  28.                 var p2 = new Point3d(maxp.X * scl.X, maxp.Y * scl.Y, maxp.Z * scl.Z) + vp;
  29.                 extents = new Extents3d(p1, p2);
  30.             });
  31.             return extents ?? block.GeometricExtents;
  32.         }

Оффлайн JohnJАвтор темы

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
преобразовать Extents3d методом Extents3d.TransformBy
Возможно это именно то, что мне нужно, надо будет опробовать.

Оффлайн Александр Ривилис

  • Administrator
  • *****
  • Сообщений: 13877
  • Карма: 1785
  • Рыцарь ObjectARX
  • Skype: rivilis
// ent выдаёт ошибку при обращении к GeometricExtents, если это не графический элемент (например, атрибут блока)
Атрибут (класс AttributeReference) блока это графический примитив, как и определение атрибута (класс AttributeDefinition). И у них есть GeometricExtents. Только вот нужны ли они тебе для работы - это вопрос. Если уж и нужны, то AttributeReference, которые у BlockReference и AttributeDefinition с AttributeDefinition.Constant == true у BlockTableRecord
Я бы активнее пользовался бы Extents3d.AddExtents и Extents3d.AddPoint вместо того чтобы каждый раз создавать новый Extents3d
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн JohnJАвтор темы

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
Если есть GeometricExtents, откуда тогда Exception в частности в случае с AttributeReference? Ошибка в чертеже?

Extents3d.AddExtents я использовал, но потом закомментировал, так как не получал нужного результата (или мне так показалось). Чуть позже я вернусь к этому, что бы разобраться.