Как получить размеры динамического блока с помощью чистого NET? (без COM)

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

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

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Самый простой пример, который пришел в голову, чтобы показать, почему этот способ неточен. Нарисуйте окружность, сделайте из нее блок, поверните этот блок на 45 градусов и попробуйте определить границы.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Да. В этом случае работать будет не точно. А вот с рамками должно быть нормально при любом повороте и масштабировании, так как сама рамка совпадает с габаритным контейнером и поворачивается и масштабируется одновременно с ним.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • **
  • Сообщений: 58
  • Карма: 0
Надо попробовать! Отпишусь как сделаю.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Немного модифицировал код. Теперь если блок имеет одинаковые коэффициенты масштабирования по X, Y, Z, то используется один алгоритм (более точный), если разные - другой. Ну и добавлена рекурсия (т.е. обрабатывается вставка блока в другом блоке):
Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.Runtime;
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.DatabaseServices;
  5. using Autodesk.AutoCAD.Geometry;
  6. using Autodesk.AutoCAD.EditorInput;
  7.  
  8. #pragma warning disable 618
  9.  
  10. [assembly: CommandClass(typeof(Rivilis.BlockExtents))]
  11.  
  12. namespace Rivilis
  13. {
  14.   public class BlockExtents
  15.   {
  16.     [CommandMethod("BlockExt")]
  17.     public void BlockExt()
  18.     {
  19.       Document doc = Application.DocumentManager.MdiActiveDocument;
  20.       if (doc == null) return;
  21.       Editor ed = doc.Editor;
  22.       PromptEntityOptions enOpt = new PromptEntityOptions("\nВыберите примитив: ");
  23.       PromptEntityResult enRes = ed.GetEntity(enOpt);
  24.       if (enRes.Status == PromptStatus.OK)
  25.       {
  26.         Extents3d blockExt = new Extents3d(Point3d.Origin, Point3d.Origin);
  27.         Matrix3d mat = Matrix3d.Identity;
  28.         using (Entity en = enRes.ObjectId.Open(OpenMode.ForRead) as Entity)
  29.         {
  30.           GetBlockExtents(en, ref blockExt, ref mat);
  31.         }
  32.         string s =
  33.           "MinPoint: " + blockExt.MinPoint.ToString() + " " +
  34.           "MaxPoint: " + blockExt.MaxPoint.ToString();
  35.         ed.WriteMessage(s);
  36.         //------------------------------------------------------------
  37.         // Только для тестирования полученного габаритного контейнера
  38.         //------------------------------------------------------------
  39.         #region TestinExts
  40.         using (BlockTableRecord curSpace =
  41.           doc.Database.CurrentSpaceId.Open(OpenMode.ForWrite) as BlockTableRecord)
  42.         {
  43.           Point3dCollection pts = new Point3dCollection();
  44.           pts.Add(blockExt.MinPoint);
  45.           pts.Add(new Point3d(blockExt.MinPoint.X,blockExt.MaxPoint.Y, blockExt.MinPoint.Z));
  46.           pts.Add(blockExt.MaxPoint);
  47.           pts.Add(new Point3d(blockExt.MaxPoint.X,blockExt.MinPoint.Y, blockExt.MinPoint.Z));
  48.           using (Polyline3d poly = new Polyline3d(Poly3dType.SimplePoly,pts,true))
  49.           {
  50.             curSpace.AppendEntity(poly);
  51.           }
  52.         }
  53.         #endregion
  54.       }
  55.     }
  56.     /// <summary>
  57.     /// Рекурсивное получение габаритного контейнера для вставки блока.
  58.     /// </summary>
  59.     /// <param name="en">Имя примитива</param>
  60.     /// <param name="ext">Габаритный контейнер</param>
  61.     /// <param name="mat">Матрица преобразования из системы координат блока в МСК.</param>
  62.     void GetBlockExtents(Entity en, ref Extents3d ext, ref Matrix3d mat)
  63.     {
  64.       if (!IsLayerOn(en.LayerId))
  65.         return;
  66.       if (en is BlockReference)
  67.       {
  68.         BlockReference bref = en as BlockReference;
  69.         Matrix3d matIns = mat * bref.BlockTransform;
  70.         using (BlockTableRecord btr =
  71.           bref.BlockTableRecord.Open(OpenMode.ForRead) as BlockTableRecord)
  72.         {
  73.           foreach (ObjectId id in btr)
  74.           {
  75.             using (DBObject obj = id.Open(OpenMode.ForRead) as DBObject)
  76.             {
  77.               Entity enCur = obj as Entity;
  78.               if (enCur == null || enCur.Visible != true)
  79.                 continue;
  80.               GetBlockExtents(enCur, ref ext, ref matIns);
  81.             }
  82.           }
  83.         }
  84.       }
  85.       else
  86.       {
  87.         if (mat.IsUniscaledOrtho())
  88.         {
  89.           using (Entity enTr = en.GetTransformedCopy(mat))
  90.           {
  91.             if (IsEmptyExt(ref ext))
  92.               ext = enTr.GeometricExtents;
  93.             else
  94.               ext.AddExtents(enTr.GeometricExtents);
  95.             return;
  96.           }
  97.         }
  98.         else
  99.         {
  100.           try
  101.           {
  102.             Extents3d curExt = en.GeometricExtents;
  103.             curExt.TransformBy(mat);
  104.             if (IsEmptyExt(ref ext))
  105.               ext = curExt;
  106.             else
  107.               ext.AddExtents(curExt);
  108.           }
  109.           catch { }
  110.           return;
  111.         }
  112.       }
  113.  
  114.       return;
  115.  
  116.     }
  117.     /// <summary>
  118.     /// Определяет видны ли объекты на слое, указанном его ObjectId.
  119.     /// </summary>
  120.     /// <param name="layerId">ObjectId слоя.</param>
  121.     /// <returns></returns>
  122.     bool IsLayerOn(ObjectId layerId)
  123.     {
  124.       using (LayerTableRecord ltr = layerId.Open(OpenMode.ForRead) as LayerTableRecord)
  125.       {
  126.         if (ltr.IsFrozen) return false;
  127.         if (ltr.IsOff) return false;
  128.       }
  129.       return true;
  130.     }
  131.     /// <summary>
  132.     /// Определят не пустой ли габаритный контейнер.
  133.     /// </summary>
  134.     /// <param name="ext">Габаритный контейнер.</param>
  135.     /// <returns></returns>
  136.     bool IsEmptyExt(ref Extents3d ext)
  137.     {
  138.       if (ext.MinPoint.DistanceTo(ext.MaxPoint) < Tolerance.Global.EqualPoint)
  139.         return true;
  140.       else
  141.         return false;
  142.     }
  143.   }
  144. }

Перевод в VB.NET сделаешь самостоятельно.
« Последнее редактирование: 25-08-2015, 01:47:32 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN OPEN
  • **
  • Сообщений: 58
  • Карма: 0
Спасибо! Сделаю обязательно. Почему нельзя добавлять карму за каждый ответ? Ведь это же другой ответ!

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Так круто, что я даже не понимаю, как это работает :) Надо будет потестировать на досуге... А с атрибутами пробовали, проблем нет? Это одни из тех граблей, что я не смог побороть аналитическими методами.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
А с атрибутами пробовали, проблем нет? Это одни из тех граблей, что я не смог побороть аналитическими методами.
Не пробовал. Точнее у меня было несколько блоков с атрибутами и с ними всё нормально. Но в крайнем случае и их обработаем отдельно.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Дошли наконец руки до этого кода. С атрибутами, как я и предполагал, не дружит. На 94 строке выдает исключение.
Еще один момент заметил. Если на краю блока полилиния с толщиной, то в рамку попадает только половина толщины. Мелочь, но неприятно... Причем, это не недостаток Вашего кода, это в принципе методами не учитывается при определении границ полилинии. Надо будет мне подумать, насколько это критично и как это можно учитывать...
P.S. посмотрел, как я решал проблему с атрибутами. Гениально, на мой взгляд :D (строки 24-27, исходное комментирование сохранено):
Код - C# [Выбрать]
  1. /// <summary>
  2. /// Получение границ блока
  3. /// </summary>
  4. /// <param name="blkRef">Ссылка на вставку блока</param>
  5. /// <returns>Границы блока</returns>
  6. public static Extents3d GetBlockGeometricExtents(this BlockReference blkRef)
  7. {
  8.     if (blkRef.IsDynamicBlock)
  9.     {
  10.         Extents3d resExts = new Extents3d();
  11.  
  12.         DBObjectCollection explObjs = new DBObjectCollection();
  13.         blkRef.Explode(explObjs);
  14.         foreach (DBObject dbObj in explObjs)
  15.         {
  16.             using (dbObj)
  17.             {
  18.                 try
  19.                 {
  20.                     Entity dbEnt = dbObj as Entity;
  21.  
  22.                     Extents3d entExt;
  23.                     if (
  24.                         // С атрибутами все непросто
  25.                         !(dbEnt is AttributeDefinition)                                
  26.                         // С размерами тоже
  27.                         && !(dbEnt is Dimension))
  28.                     {
  29.                         if (dbEnt is BlockReference)
  30.                             entExt = GetBlockGeometricExtents(dbEnt as BlockReference);
  31.  
  32.                         else entExt = dbEnt.GeometricExtents;
  33.  
  34.                         resExts.AddExtents(entExt);
  35.                     }
  36.                     else
  37.                         Debug.WriteLine
  38.                             ("GetBlockGeometricExtents subentity ignored: {0}",
  39.                             dbEnt.Handle.Value);
  40.                 }
  41.                 catch
  42.                 {
  43.                     Debug.WriteLine
  44.                         ("GetBlockGeometricExtents error! Block: {0}, subentity: {1}",
  45.                         blkRef.Handle.Value,
  46.                         dbObj.Handle.Value);
  47.                 }
  48.             }
  49.         }                
  50.         return resExts;
  51.     }
  52.     else return blkRef.GeometricExtents;
  53. }
  54.  

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Обработку определений атрибутов и атрибуты я действительно пропустил. Исправляюсь. Определения атрибутов нужно пропускать все кроме видимых константных. Вставки атрибутов следует обрабатывать все, кроме невидимых. Поэтому как-то так:
Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.Runtime;
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.DatabaseServices;
  5. using Autodesk.AutoCAD.Geometry;
  6. using Autodesk.AutoCAD.EditorInput;
  7.  
  8. #pragma warning disable 618
  9.  
  10. [assembly: CommandClass(typeof(Rivilis.BlockExtents))]
  11.  
  12. namespace Rivilis
  13. {
  14.   public class BlockExtents
  15.   {
  16.     [CommandMethod("BlockExt")]
  17.     public void BlockExt()
  18.     {
  19.       Document doc = Application.DocumentManager.MdiActiveDocument;
  20.       if (doc == null) return;
  21.       Editor ed = doc.Editor;
  22.       PromptEntityOptions enOpt =
  23.         new PromptEntityOptions("\nВыберите примитив: ");
  24.       PromptEntityResult enRes = ed.GetEntity(enOpt);
  25.       if (enRes.Status == PromptStatus.OK) {
  26.         Extents3d blockExt =
  27.           new Extents3d(Point3d.Origin, Point3d.Origin);
  28.         Matrix3d mat = Matrix3d.Identity;
  29.         using (Entity en =
  30.           enRes.ObjectId.Open(OpenMode.ForRead) as Entity) {
  31.           GetBlockExtents(en, ref blockExt, ref mat);
  32.         }
  33.         string s =
  34.           "MinPoint: " + blockExt.MinPoint.ToString() + " " +
  35.           "MaxPoint: " + blockExt.MaxPoint.ToString();
  36.         ed.WriteMessage(s);
  37.         //------------------------------------------------------------
  38.         // Только для тестирования полученного габаритного контейнера
  39.         //------------------------------------------------------------
  40.         #region TestinExts
  41.         using (BlockTableRecord curSpace =
  42.           doc.Database.CurrentSpaceId.Open(OpenMode.ForWrite) as BlockTableRecord) {
  43.           Point3dCollection pts = new Point3dCollection();
  44.           pts.Add(blockExt.MinPoint);
  45.           pts.Add(new Point3d(blockExt.MinPoint.X,
  46.             blockExt.MaxPoint.Y, blockExt.MinPoint.Z));
  47.           pts.Add(blockExt.MaxPoint);
  48.           pts.Add(new Point3d(blockExt.MaxPoint.X,
  49.             blockExt.MinPoint.Y, blockExt.MinPoint.Z));
  50.           using (Polyline3d poly =
  51.             new Polyline3d(Poly3dType.SimplePoly, pts, true)) {
  52.             curSpace.AppendEntity(poly);
  53.           }
  54.         }
  55.         #endregion
  56.       }
  57.     }
  58.     /// <summary>
  59.     /// Рекурсивное получение габаритного контейнера для вставки блока.
  60.     /// </summary>
  61.     /// <param name="en">Имя примитива</param>
  62.     /// <param name="ext">Габаритный контейнер</param>
  63.     /// <param name="mat">Матрица преобразования из системы координат блока в МСК.</param>
  64.     void GetBlockExtents(Entity en, ref Extents3d ext, ref Matrix3d mat)
  65.     {
  66.       if (!IsLayerOn(en.LayerId))
  67.         return;
  68.       if (en is BlockReference) {
  69.         BlockReference bref = en as BlockReference;
  70.         Matrix3d matIns = mat * bref.BlockTransform;
  71.         using (BlockTableRecord btr =
  72.           bref.BlockTableRecord.Open(OpenMode.ForRead) as BlockTableRecord) {
  73.           foreach (ObjectId id in btr) {
  74.             using (DBObject obj = id.Open(OpenMode.ForRead) as DBObject) {
  75.               Entity enCur = obj as Entity;
  76.               if (enCur == null || enCur.Visible != true)
  77.                 continue;
  78.               // Пропускаем неконстантные и невидимые определения атрибутов
  79.               AttributeDefinition attDef = enCur as AttributeDefinition;
  80.               if (attDef != null && (!attDef.Constant || attDef.Invisible))
  81.                 continue;
  82.               GetBlockExtents(enCur, ref ext, ref matIns);
  83.             }
  84.           }
  85.         }
  86.         // Отдельно обрабатываем атрибуты блока
  87.         if (bref.AttributeCollection.Count > 0) {
  88.           foreach (ObjectId idAtt in bref.AttributeCollection) {
  89.             using (AttributeReference attRef =
  90.               idAtt.Open(OpenMode.ForRead) as AttributeReference) {
  91.                 if (!attRef.Invisible && attRef.Visible)
  92.                 GetBlockExtents(attRef, ref ext, ref mat);
  93.             }
  94.           }
  95.         }
  96.       }
  97.       else {
  98.         if (mat.IsUniscaledOrtho()) {
  99.           using (Entity enTr = en.GetTransformedCopy(mat)) {
  100.             if (IsEmptyExt(ref ext)) {
  101.               try { ext = enTr.GeometricExtents; } catch { };
  102.             }
  103.             else {
  104.               try { ext.AddExtents(enTr.GeometricExtents); } catch { };
  105.             }
  106.             return;
  107.           }
  108.         }
  109.         else {
  110.           try {
  111.             Extents3d curExt = en.GeometricExtents;
  112.             curExt.TransformBy(mat);
  113.             if (IsEmptyExt(ref ext))
  114.               ext = curExt;
  115.             else
  116.               ext.AddExtents(curExt);
  117.           }
  118.           catch { }
  119.           return;
  120.         }
  121.       }
  122.  
  123.       return;
  124.  
  125.     }
  126.     /// <summary>
  127.     /// Определяет видны ли объекты на слое, указанном его ObjectId.
  128.     /// </summary>
  129.     /// <param name="layerId">ObjectId слоя.</param>
  130.     /// <returns></returns>
  131.     bool IsLayerOn(ObjectId layerId)
  132.     {
  133.       using (LayerTableRecord ltr = layerId.Open(OpenMode.ForRead) as LayerTableRecord) {
  134.         if (ltr.IsFrozen) return false;
  135.         if (ltr.IsOff) return false;
  136.       }
  137.       return true;
  138.     }
  139.     /// <summary>
  140.     /// Определят не пустой ли габаритный контейнер.
  141.     /// </summary>
  142.     /// <param name="ext">Габаритный контейнер.</param>
  143.     /// <returns></returns>
  144.     bool IsEmptyExt(ref Extents3d ext)
  145.     {
  146.       if (ext.MinPoint.DistanceTo(ext.MaxPoint) < Tolerance.Global.EqualPoint)
  147.         return true;
  148.       else
  149.         return false;
  150.     }
  151.   }
  152. }
« Последнее редактирование: 02-10-2015, 19:37:13 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Интересно получается, если в блоке есть размер. Его границы не пересчитываются в координаты модели и вычисляются для объекта внутри блока.


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

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

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

  • ADN
  • *
  • Сообщений: 2531
  • Карма: 735
Я вроде откопал решение. Нужно для размеров после получения их трансформированной копии выполнять метод Dimension.RecomputeDimensionBlock(true). Если это добавить - границы вычисляются правильно. Сейчас тестирую, пока вроде все ок.
А зачем Вы матрицу с ref передаете в метод? Для увеличения скорости?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
А зачем Вы матрицу с ref передаете в метод? Для увеличения скорости?
Да. Хотя была ещё одна мысль, что в каких-то ситуациях эту матрицу придётся модифицировать. Но пока не понадобилось.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Отмечено как Решение Александр Ривилис 18-06-2016, 18:27:59

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Дмитрий Загорулькин
По твоей наводке исправил код. Заодно на всякий случай обработал не только Dimension, но и Table:
Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.Runtime;
  3. using Autodesk.AutoCAD.ApplicationServices;
  4. using Autodesk.AutoCAD.DatabaseServices;
  5. using Autodesk.AutoCAD.Geometry;
  6. using Autodesk.AutoCAD.EditorInput;
  7.  
  8. #pragma warning disable 618
  9.  
  10. [assembly: CommandClass(typeof(Rivilis.BlockExtents))]
  11.  
  12. namespace Rivilis
  13. {
  14.   public class BlockExtents
  15.   {
  16.     [CommandMethod("BlockExt")]
  17.     public void BlockExt()
  18.     {
  19.       Document doc = Application.DocumentManager.MdiActiveDocument;
  20.       if (doc == null) return;
  21.       Editor ed = doc.Editor;
  22.       PromptEntityOptions enOpt =
  23.         new PromptEntityOptions("\nВыберите примитив: ");
  24.       PromptEntityResult enRes = ed.GetEntity(enOpt);
  25.       if (enRes.Status == PromptStatus.OK) {
  26.         Extents3d blockExt =
  27.           new Extents3d(Point3d.Origin, Point3d.Origin);
  28.         Matrix3d mat = Matrix3d.Identity;
  29.         using (Entity en =
  30.           enRes.ObjectId.Open(OpenMode.ForRead) as Entity) {
  31.           GetBlockExtents(en, ref blockExt, ref mat);
  32.         }
  33.         string s =
  34.           "MinPoint: " + blockExt.MinPoint.ToString() + " " +
  35.           "MaxPoint: " + blockExt.MaxPoint.ToString();
  36.         ed.WriteMessage(s);
  37.         //------------------------------------------------------------
  38.         // Только для тестирования полученного габаритного контейнера
  39.         //------------------------------------------------------------
  40.         #region TestinExts
  41.         using (BlockTableRecord curSpace =
  42.           doc.Database.CurrentSpaceId.Open(OpenMode.ForWrite) as BlockTableRecord) {
  43.           Point3dCollection pts = new Point3dCollection();
  44.           pts.Add(blockExt.MinPoint);
  45.           pts.Add(new Point3d(blockExt.MinPoint.X,
  46.             blockExt.MaxPoint.Y, blockExt.MinPoint.Z));
  47.           pts.Add(blockExt.MaxPoint);
  48.           pts.Add(new Point3d(blockExt.MaxPoint.X,
  49.             blockExt.MinPoint.Y, blockExt.MinPoint.Z));
  50.           using (Polyline3d poly =
  51.             new Polyline3d(Poly3dType.SimplePoly, pts, true)) {
  52.             curSpace.AppendEntity(poly);
  53.           }
  54.         }
  55.         #endregion
  56.       }
  57.     }
  58.     /// <summary>
  59.     /// Рекурсивное получение габаритного контейнера для выбранного примитива.
  60.     /// </summary>
  61.     /// <param name="en">Имя примитива</param>
  62.     /// <param name="ext">Габаритный контейнер</param>
  63.     /// <param name="mat">Матрица преобразования из системы координат блока в МСК.</param>
  64.     void GetBlockExtents(Entity en, ref Extents3d ext, ref Matrix3d mat)
  65.     {
  66.       if (!IsLayerOn(en.LayerId))
  67.         return;
  68.       if (en is BlockReference) {
  69.         BlockReference bref = en as BlockReference;
  70.         Matrix3d matIns = mat * bref.BlockTransform;
  71.         using (BlockTableRecord btr =
  72.           bref.BlockTableRecord.Open(OpenMode.ForRead) as BlockTableRecord) {
  73.           foreach (ObjectId id in btr) {
  74.             using (DBObject obj = id.Open(OpenMode.ForRead) as DBObject) {
  75.               Entity enCur = obj as Entity;
  76.               if (enCur == null || enCur.Visible != true)
  77.                 continue;
  78.               // Пропускаем неконстантные и невидимые определения атрибутов
  79.               AttributeDefinition attDef = enCur as AttributeDefinition;
  80.               if (attDef != null && (!attDef.Constant || attDef.Invisible))
  81.                 continue;
  82.               GetBlockExtents(enCur, ref ext, ref matIns);
  83.             }
  84.           }
  85.         }
  86.         // Отдельно обрабатываем атрибуты блока
  87.         if (bref.AttributeCollection.Count > 0) {
  88.           foreach (ObjectId idAtt in bref.AttributeCollection) {
  89.             using (AttributeReference attRef =
  90.               idAtt.Open(OpenMode.ForRead) as AttributeReference) {
  91.                 if (!attRef.Invisible && attRef.Visible)
  92.                 GetBlockExtents(attRef, ref ext, ref mat);
  93.             }
  94.           }
  95.         }
  96.       }
  97.       else {
  98.         if (mat.IsUniscaledOrtho()) {
  99.           using (Entity enTr = en.GetTransformedCopy(mat)) {
  100.             if (enTr is Dimension)
  101.               (enTr as Dimension).RecomputeDimensionBlock(true);
  102.             if (enTr is Table)
  103.               (enTr as Table).RecomputeTableBlock(true);
  104.             if (IsEmptyExt(ref ext)) {
  105.               try { ext = enTr.GeometricExtents; } catch { };
  106.             }
  107.             else {
  108.               try { ext.AddExtents(enTr.GeometricExtents); } catch { };
  109.             }
  110.             return;
  111.           }
  112.         }
  113.         else {
  114.           try {
  115.             Extents3d curExt = en.GeometricExtents;
  116.             curExt.TransformBy(mat);
  117.             if (IsEmptyExt(ref ext))
  118.               ext = curExt;
  119.             else
  120.               ext.AddExtents(curExt);
  121.           }
  122.           catch { }
  123.           return;
  124.         }
  125.       }
  126.  
  127.       return;
  128.  
  129.     }
  130.     /// <summary>
  131.     /// Определяет видны ли объекты на слое, указанном его ObjectId.
  132.     /// </summary>
  133.     /// <param name="layerId">ObjectId слоя.</param>
  134.     /// <returns></returns>
  135.     bool IsLayerOn(ObjectId layerId)
  136.     {
  137.       using (LayerTableRecord ltr = layerId.Open(OpenMode.ForRead) as LayerTableRecord) {
  138.         if (ltr.IsFrozen) return false;
  139.         if (ltr.IsOff) return false;
  140.       }
  141.       return true;
  142.     }
  143.     /// <summary>
  144.     /// Определят не пустой ли габаритный контейнер.
  145.     /// </summary>
  146.     /// <param name="ext">Габаритный контейнер.</param>
  147.     /// <returns></returns>
  148.     bool IsEmptyExt(ref Extents3d ext)
  149.     {
  150.       if (ext.MinPoint.DistanceTo(ext.MaxPoint) < Tolerance.Global.EqualPoint)
  151.         return true;
  152.       else
  153.         return false;
  154.     }
  155.   }
  156. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн JohnLennin

  • .Net Teapot
  • ADN OPEN
  • Сообщений: 49
  • Карма: 1
Коллеги, посмотрел я Ваше прекрасное обсуждение, вещь очень полезная, как раз то, что я ищу, однако есть один вопрос или нюанс - рамка и габаритный контейнер очень хороши, когда блоки ортогонально ориентированы, однако если есть поворот то контейнер выходит за пределы блока.
Мне необходимо решить простую задачу - стоят ли BReferences в одном ряду (вплотную друг к другу) или нет. Точка вставки у них расположена одинаково, осталось только вычислить длину блока. Данный код помогает все разобрать, но только при ортогональном расположении, а если BReferences стоят в ряд, но этот ряд повернут под углом, то этот  принцип не совсем работает.
Собственно в чем вопрос - можно ли этот контейнер ориентировать под тем же углом, под которым повернута BReference?