Как узнать текущие размеры прокси-объекта?

Автор Тема: Как узнать текущие размеры прокси-объекта?  (Прочитано 6884 раз)

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

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

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
Есть файл, рамка которого выполнена в виде спдс-прокси объекта. GeometricExtents возвращает какие-то мифические размеры. Возможно ли в данном случае как-либо узнать координаты оконтовки объекта?
Попробовал через взрыв. Ответ всё-равно не сходится с тем, который даёт инструмент "Расстояние" (ИЗМЕРИТЬГЕОМ)
Команда: ИЗМЕРИТЬГЕОМ
Расстояние = 51430.3929,  Угол в плоскости XY = 35,  Угол от плоскости XY = 0
Дельта X = 41992.6966,  Дельта Y = 29693.4125,   Дельта Z = 0.0000
Команда: PROXYEXPLODETEST
Размеры прокси-объекта определились как 18500x12700
Неточность дельты Х и дельты Y связана с отсутствием привязки к точкам прокси-объекта.

Размеры через код определяю только по "не текстовым" объектам. Если взорвать "вручную", то вместо прокси-объекта появятся линии (полилинии) и тексты. Линии на месте, тогда как текстовые поля съезжают. Но в коде по линиям выходят не те размеры. С чем это может быть связано?
Полный код примера:
Код - C# [Выбрать]
  1. using System;
  2. using Autodesk.AutoCAD.ApplicationServices;
  3. using Autodesk.AutoCAD.DatabaseServices;
  4. using Autodesk.AutoCAD.Geometry;
  5. using Autodesk.AutoCAD.Runtime;
  6.  
  7. namespace AutocadTestProject {
  8.     public class AutocadTestProxy : IExtensionApplication {
  9.  
  10.         [CommandMethod("ProxyExplodeTest")]
  11.         public void ProxyExplode() {
  12.             var doc = Application.DocumentManager.MdiActiveDocument;
  13.             using (doc.LockDocument()) {
  14.                 ProxyEntity proxy = null;
  15.                 using (var tr = doc.TransactionManager.StartTransaction()) {
  16.                     var db = doc.Database;
  17.                     using (var bt = tr.GetObject(db.BlockTableId, OpenMode.ForRead) as BlockTable) {
  18.                         using (var space = tr.GetObject(bt[BlockTableRecord.ModelSpace], OpenMode.ForWrite) as BlockTableRecord) {
  19.                             var proxy_id = ObjectId.Null;
  20.                             foreach (var object_id in space) {
  21.                                 using (var obj = tr.GetObject(object_id, OpenMode.ForRead) as ProxyEntity) {
  22.                                     if (obj == null) continue;
  23.                                     proxy_id = object_id;
  24.                                 }
  25.                                 break;
  26.                             }
  27.                             if (proxy_id == ObjectId.Null) {
  28.                                 doc.Editor.WriteMessage("Не найдено ни одного прокси-объекта");
  29.                                 return;
  30.                             }
  31.                             proxy = tr.GetObject(proxy_id, OpenMode.ForWrite) as ProxyEntity;
  32.                         }
  33.                     }
  34.                     if (proxy == null) {
  35.                         doc.Editor.WriteMessage("Не удалось определить прокси-объект по id");
  36.                         return;
  37.                     }
  38.                     var extents = GetProxyGeometricExtents(proxy, tr);
  39.                     doc.Editor.WriteMessage(String.Format("Размеры прокси-объекта определились как {0}x{1}", extents.MaxPoint.X - extents.MinPoint.X, extents.MaxPoint.Y - extents.MinPoint.Y));
  40.                 }
  41.             }
  42.         }
  43.  
  44.         public Extents3d GetProxyGeometricExtents(ProxyEntity proxy, Transaction trn) {
  45.             var collection = new DBObjectCollection();
  46.             proxy.Explode(collection);
  47.             Extents3d? extents = null;
  48.             foreach (var obj in collection) {
  49.                 var ent = obj as Entity;
  50.                 if (ent == null || ent is DBText || ent is MText) continue;
  51.                 try {
  52.                     if (extents == null) {
  53.                         extents = ent.GeometricExtents;
  54.                     } else {
  55.                         var mip1 = extents.Value.MinPoint;
  56.                         var mip2 = ent.GeometricExtents.MinPoint;
  57.                         var map1 = extents.Value.MaxPoint;
  58.                         var map2 = ent.GeometricExtents.MaxPoint;
  59.                         var pe1 = new Point3d(Math.Min(mip1.X, mip2.X), Math.Min(mip1.Y, mip2.Y), Math.Min(mip1.Z, mip2.Z));
  60.                         var pe2 = new Point3d(Math.Max(map1.X, map2.X), Math.Max(map1.Y, map2.Y), Math.Max(map1.Z, map2.Z));
  61.                         extents = new Extents3d(pe1, pe2); //extents.Value.AddExtents(ent.GeometricExtents);
  62.                     }
  63.                 } catch {}
  64.             }
  65.             return extents ?? new Extents3d();
  66.         }
  67.  
  68.         public void Initialize() {
  69.            
  70.         }
  71.  
  72.         public void Terminate() {
  73.            
  74.         }
  75.     }
  76. }

Но! Когда я удаляю таблицу, которая находится внутри прокси-объекта (но не относится к самому прокси-объекту), размеры начинают определяться правильно:
Команда: PROXYEXPLODETEST
Размеры прокси-объекта определились как 42000x29700
« Последнее редактирование: 22-12-2014, 11:51:52 от JohnJ »

Отмечено как Решение JohnJ 22-12-2014, 11:52:01

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

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
Всё, разобрался в чём дело. Оказывается таблица тоже была прокси-объектом и именно её размеры я определял в начале, пока не удалил... Тему можно закрывать :)
Отдельная благодарность Загорулькину Дмитрию за наводку к методу с Explode в соседней теме!

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

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
Кстати, если заменить
Код - C# [Выбрать]
  1.                         var mip1 = extents.Value.MinPoint;
  2.                         var mip2 = ent.GeometricExtents.MinPoint;
  3.                         var map1 = extents.Value.MaxPoint;
  4.                         var map2 = ent.GeometricExtents.MaxPoint;
  5.                         var pe1 = new Point3d(Math.Min(mip1.X, mip2.X), Math.Min(mip1.Y, mip2.Y), Math.Min(mip1.Z, mip2.Z));
  6.                         var pe2 = new Point3d(Math.Max(map1.X, map2.X), Math.Max(map1.Y, map2.Y), Math.Max(map1.Z, map2.Z));
  7.                         extents = new Extents3d(pe1, pe2); //extents.Value.AddExtents(ent.GeometricExtents);
  8.  
на
Код - C# [Выбрать]
  1. extents.Value.AddExtents(ent.GeometricExtents);
То ответ получается не верным: 42000х0

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

  • Administrator
  • *****
  • Сообщений: 13877
  • Карма: 1785
  • Рыцарь ObjectARX
  • Skype: rivilis
Кстати, если заменить
Код - C#: [Выделить]

                            var mip1 = extents.Value.MinPoint;
                            var mip2 = ent.GeometricExtents.MinPoint;
                            var map1 = extents.Value.MaxPoint;
                            var map2 = ent.GeometricExtents.MaxPoint;
                            var pe1 = new Point3d(Math.Min(mip1.X, mip2.X), Math.Min(mip1.Y, mip2.Y), Math.Min(mip1.Z, mip2.Z));
                            var pe2 = new Point3d(Math.Max(map1.X, map2.X), Math.Max(map1.Y, map2.Y), Math.Max(map1.Z, map2.Z));
                            extents = new Extents3d(pe1, pe2); //extents.Value.AddExtents(ent.GeometricExtents);
     

на
Код - C#: [Выделить]

    extents.Value.AddExtents(ent.GeometricExtents);

То ответ получается не верным: 42000х0
Подозреваю что у тебя в коде что-то нет. В противном случае это баг в методе AddExtents. Проверить не могу, т.к. ты удалил тестовый чертеж, а я его не успел скачать.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
Да, тот файл я и у себя удалил. Но для того что бы разобраться, попросил сделать пример из спдс-объекта в виде рамки А4. Прикладываю его, а так же класс, который считает двумя методами и выводит результат. В данном случае получается такой:
Команда: PROXYEXPLODETEST
Размеры прокси-объекта определились как 21000x29700 (метод 0)
Размеры прокси-объекта определились как 21000x0 (метод 1)
Размеры прокси-объекта определились как 21000x29700 (метод 0)
Размеры прокси-объекта определились как 21000x0 (метод 1)
Код - C# [Выбрать]
  1.                         if (CalcMethod == 1) {
  2.                             extents.Value.AddExtents(ent.GeometricExtents);
  3.                             continue;
  4.                         }
  5.                         var mip1 = extents.Value.MinPoint;
  6.                         var mip2 = ent.GeometricExtents.MinPoint;
  7.                         var map1 = extents.Value.MaxPoint;
  8.                         var map2 = ent.GeometricExtents.MaxPoint;
  9.                         var pe1 = new Point3d(Math.Min(mip1.X, mip2.X), Math.Min(mip1.Y, mip2.Y), Math.Min(mip1.Z, mip2.Z));
  10.                         var pe2 = new Point3d(Math.Max(map1.X, map2.X), Math.Max(map1.Y, map2.Y), Math.Max(map1.Z, map2.Z));
  11.                         extents = new Extents3d(pe1, pe2);

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

  • Administrator
  • *****
  • Сообщений: 13877
  • Карма: 1785
  • Рыцарь ObjectARX
  • Skype: rivilis
Сравни:
Код - C# [Выбрать]
  1. public Extents3d GetProxyGeometricExtents(ProxyEntity proxy, Transaction trn)
  2. {
  3.   var collection = new DBObjectCollection();
  4.   proxy.Explode(collection);
  5.   Extents3d ext1;
  6.   Extents3d extall = new Extents3d(Point3d.Origin,Point3d.Origin);
  7.   foreach (var obj in collection) {
  8.     var ent = obj as Entity;
  9.     if (ent == null || ent is DBText || ent is MText) continue;
  10.     try {
  11.       if (extall.MinPoint == extall.MaxPoint) {
  12.         extall = ent.GeometricExtents;
  13.       } else {
  14.         if (CalcMethod == 1) {
  15.           ext1 = ent.GeometricExtents;
  16.           extall.AddExtents(ext1);
  17.           continue;
  18.         }
  19.         var mip1 = extall.MinPoint;
  20.         var mip2 = ent.GeometricExtents.MinPoint;
  21.         var map1 = extall.MaxPoint;
  22.         var map2 = ent.GeometricExtents.MaxPoint;
  23.         var pe1 = new Point3d(Math.Min(mip1.X, mip2.X),
  24.                 Math.Min(mip1.Y, mip2.Y), Math.Min(mip1.Z, mip2.Z));
  25.         var pe2 = new Point3d(Math.Max(map1.X, map2.X),
  26.                 Math.Max(map1.Y, map2.Y), Math.Max(map1.Z, map2.Z));
  27.         extall = new Extents3d(pe1, pe2);
  28.       }
  29.     }
  30.     catch { }
  31.   }
  32.   return extall;
  33. }

Цитировать
Command: PROXYEXPLODETEST
Размеры прокси-объекта определились как 21000x29700 (метод 0)
Размеры прокси-объекта определились как 21000x29700 (метод 1)
Размеры прокси-объекта определились как 21000x29700 (метод 0)
Размеры прокси-объекта определились как 21000x29700 (метод 1)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
Огромное спасибо! Я понял в чём дело - с вопросительным знаком нужно аккуратнее работать...

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

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

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

  • ADN Club
  • **
  • Сообщений: 78
  • Карма: 1
  • c# autocad
  • Skype: johnj255work
Я сначала так и делал, но после прочтения этой статьи переучился (не нашёл сейчас ту статью, о которой хотел рассказать, но нашёл нечто подобное http://habrahabr.ru/post/39231/ ).  Благо мне было это не сложно после javascript. Решил, что лучше использовать var, что бы не повторять дважды название класса, например. Теперь уже привык. Для меня такой код выглядит более читаемый, чем с явным указанием типов.
Плюс ко всему, использую ReSharper: он мало того, что при наведении на var отображает какой тип там скрывается, так ещё и подчёркивает явно указанный тип, настойчиво предлагая заменить его на var. Разумеется за исключением тех случаев, где явное указание типа необходимо.
А иногда это даже удобно, когда в процессе разработки я меняю тип результата, возвращаемый функцией (либо даже саму функцию решаю использовать другую), мне не приходится менять у всех переменных его. Хотя такое не часто пригождается.