Сравнение блоков

Автор Тема: Сравнение блоков  (Прочитано 11497 раз)

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

Оффлайн ВильдарАвтор темы

  • ADN Club
  • ****
  • Сообщений: 409
  • Карма: 77
  • Skype: vildar82
Сравнение блоков
« : 11-11-2015, 16:48:40 »
Доброго времени суток всем,

Как можно сравнить два определения блока? Одинаковая ли у них геометрия.
Мне нужно сравнивать блоки в текущем чертеже и во внешнем файле.

Пока придумался такой вариант:
Сохранить в список границы всех объектов в блоке . Потом сравнить списки.
Тестовый пример:
Код - C# [Выбрать]
  1. // Тест сравнения блока в текущем чертеже и в файле
  2.       [CommandMethod("Test")]
  3.       public void Test()
  4.       {
  5.          Document doc = Application.DocumentManager.MdiActiveDocument;
  6.          Editor ed = doc.Editor;
  7.          Database db = doc.Database;
  8.  
  9.          bool result = false;        
  10.  
  11.          using (var t = db.TransactionManager.StartTransaction())
  12.          {            
  13.             // Тестовый блок в текущем чертеже
  14.             ObjectId idBtrTest = GetTestBtr(db);
  15.             List<Extents3d> entsInfo = getEntInfoBtr(idBtrTest);
  16.  
  17.             // Тестовый блок во внешнем файле
  18.             using (var dbLib = new Database(false, true))
  19.             {
  20.                dbLib.ReadDwgFile(@"c:\test\Lib.dwg", FileShare.ReadWrite, false, "");
  21.                using (var tLib = dbLib.TransactionManager.StartTransaction())
  22.                {
  23.                   ObjectId idBtrTestLib = GetTestBtr(dbLib);
  24.                   List<Extents3d> entsInfoLib = getEntInfoBtr(idBtrTestLib);
  25.                   // Сравнение блоков                  
  26.                   result = entsInfo.SequenceEqual(entsInfoLib);
  27.                   tLib.Commit();
  28.                }
  29.             }
  30.             t.Commit();
  31.          }
  32.          ed.WriteMessage("Результат сравнения блоков - {0}", result);
  33.       }
  34.  
  35.       private List<Extents3d> getEntInfoBtr(ObjectId idBtrTest)
  36.       {
  37.          List<Extents3d> entsInfo = new List<Extents3d>();
  38.          var btr = idBtrTest.GetObject(OpenMode.ForRead) as BlockTableRecord;
  39.          foreach (ObjectId idEnt in btr)
  40.          {
  41.             var ent = idEnt.GetObject(OpenMode.ForRead) as Entity;
  42.             entsInfo.Add(ent.GeometricExtents);
  43.          }
  44.          return entsInfo;
  45.       }
  46.  
  47. private ObjectId GetTestBtr(Database db)
  48.       {
  49.          var bt = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
  50.          if (bt.Has("Test"))
  51.          {
  52.             return bt["Test"];
  53.          }
  54.          return ObjectId.Null;        
  55.       }

Вроде работает. Но, в этом случае большое значение имеет порядок объектов в блоке. При его изменении, но сохранении геометрии и расположения, вернет false.

Плиз, подскажите плюсы/минусы моего способа, и как его улучшить.
Или если есть другие идеи.

Спасибо!

/ Внес уточнения /

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Сравнение блоков
« Ответ #1 : 11-11-2015, 16:55:31 »
Не совсем конкретно поставлена задача! Какие варианты различий могут случиться? Может, например, достаточно сравнивать только GeometricExtents вхождения блока и не более
Да к тому-же - я могу изменить масштаб у блока - по логике геометрия у него та-же, только масштаб другой

Оффлайн ВильдарАвтор темы

  • ADN Club
  • ****
  • Сообщений: 409
  • Карма: 77
  • Skype: vildar82
Re: Сравнение блоков
« Ответ #2 : 11-11-2015, 17:02:41 »
Сравнивать нужно определения блоков.
Различия - изменение геометрии в блоке, добавление, удаление объектов и т.п.

Оффлайн Александр Пекшев aka Modis

  • ADN Club
  • *****
  • Сообщений: 1658
  • Карма: 366
  • Отец modplus.org
    • ModPlus
Re: Сравнение блоков
« Ответ #3 : 11-11-2015, 17:27:56 »
Но, в этом случае большое значение имеет порядок объектов в блоке. При его изменении, но сохранении геометрии и расположения, вернет false
http://stackoverflow.com/questions/3669970/compare-two-listt-objects-for-equality-ignoring-order

Оффлайн ВильдарАвтор темы

  • ADN Club
  • ****
  • Сообщений: 409
  • Карма: 77
  • Skype: vildar82
Re: Сравнение блоков
« Ответ #4 : 11-11-2015, 18:58:02 »
Тогда только границ для сравнения недостаточно думаю. Нужно точнее определять объекты.
Может такой класс описания объекта добавлять в список и потом сравнивать:
Код - C# [Выбрать]
  1. class EntityInfo : IEquatable<EntityInfo>, IComparable<EntityInfo>
  2.    {
  3.       private Extents3d _extents;
  4.       private Guid _classId;
  5.       private Color _color;
  6.       private string _layer;
  7.       private string _linetype;
  8.       private LineWeight _lineweight;
  9.  
  10.       public EntityInfo(Entity ent)
  11.       {
  12.          _extents = ent.GeometricExtents;
  13.          _classId = ent.ClassID;
  14.          _color = ent.Color;
  15.          _layer = ent.Layer;
  16.          _linetype = ent.Linetype;
  17.          _lineweight = ent.LineWeight;        
  18.       }
  19.      
  20.  
  21.       public bool Equals(EntityInfo other)
  22.       {
  23.          if (Object.ReferenceEquals(other, null)) return false;
  24.          if (Object.ReferenceEquals(this, other)) return true;
  25.          return _extents.Equals(other._extents) &&
  26.             _classId.Equals(other._classId) &&
  27.             _color.Equals(other._color) &&
  28.             _layer.Equals(other._layer) &&
  29.             _linetype.Equals(other._linetype) &&
  30.             _lineweight.Equals(other._lineweight);
  31.       }
  32.  
  33.       public override int GetHashCode()
  34.       {
  35.          return _extents.GetHashCode() ^ _classId.GetHashCode() ^ _color?.GetHashCode() ?? 0 ^ _linetype?.GetHashCode() ?? 0 ^ _lineweight.GetHashCode();
  36.       }
  37.  
  38.       public int CompareTo(EntityInfo other)
  39.       {
  40.          int res = _extents.GetHashCode().CompareTo(other._extents.GetHashCode());
  41.          if (res == 0) res = _classId.CompareTo(other._classId);
  42.          if (res == 0) res = _color.CompareTo(other._color);
  43.          if (res == 0) res = _layer.CompareTo(other._layer);
  44.          if (res == 0) res = _linetype.CompareTo(other._linetype);
  45.          if (res == 0) res = _lineweight.CompareTo(other._lineweight);
  46.          return res;
  47.       }
  48.    }

Тестовый код:
Код - C# [Выбрать]
  1. // Тест сравнения блока в текущем чертеже и в файле
  2.       [CommandMethod("Test")]
  3.       public void Test()
  4.       {
  5.          Document doc = Application.DocumentManager.MdiActiveDocument;
  6.          Editor ed = doc.Editor;
  7.          Database db = doc.Database;
  8.  
  9.          bool result = false;        
  10.  
  11.          using (var t = db.TransactionManager.StartTransaction())
  12.          {            
  13.             // Тестовый блок в текущем чертеже
  14.             ObjectId idBtrTest = GetTestBtr(db);
  15.             List<EntityInfo> entsInfo = getEntInfoBtr(idBtrTest);
  16.  
  17.             // Тестовый блок во внешнем файле
  18.             using (var dbLib = new Database(false, true))
  19.             {
  20.                dbLib.ReadDwgFile(@"c:\test\Lib.dwg", FileShare.ReadWrite, false, "");
  21.                using (var tLib = dbLib.TransactionManager.StartTransaction())
  22.                {
  23.                   ObjectId idBtrTestLib = GetTestBtr(dbLib);
  24.                   List<EntityInfo> entsInfoLib = getEntInfoBtr(idBtrTestLib);
  25.                   // Сравнение блоков                    
  26.                   result = Enumerable.SequenceEqual(entsInfo.OrderBy(e => e), entsInfoLib.OrderBy(e => e)); //entsInfo.SequenceEqual(entsInfoLib);
  27.                   tLib.Commit();
  28.                }
  29.             }
  30.             t.Commit();
  31.          }
  32.          ed.WriteMessage("Результат сравнения блоков - {0}", result);
  33.       }
  34.  
  35.       private List<EntityInfo> getEntInfoBtr(ObjectId idBtrTest)
  36.       {
  37.          List<EntityInfo> entsInfo = new List<EntityInfo>();
  38.          var btr = idBtrTest.GetObject(OpenMode.ForRead) as BlockTableRecord;
  39.          foreach (ObjectId idEnt in btr)
  40.          {
  41.             var ent = idEnt.GetObject(OpenMode.ForRead) as Entity;
  42.             entsInfo.Add(new EntityInfo(ent));
  43.             if (ent is BlockReference)
  44.             {
  45.                entsInfo.AddRange(getEntInfoBtr(((BlockReference)ent).BlockTableRecord));
  46.             }
  47.          }
  48.          return entsInfo;
  49.       }
  50.  
  51.       private ObjectId GetTestBtr(Database db)
  52.       {
  53.          var bt = db.BlockTableId.GetObject(OpenMode.ForRead) as BlockTable;
  54.          if (bt.Has("Test"))
  55.          {
  56.             return bt["Test"];
  57.          }
  58.          return ObjectId.Null;        
  59.       }

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Сравнение блоков
« Ответ #5 : 11-11-2015, 19:46:55 »
пробовал сравнивать хеши определений блоков?

Оффлайн ВильдарАвтор темы

  • ADN Club
  • ****
  • Сообщений: 409
  • Карма: 77
  • Skype: vildar82
Re: Сравнение блоков
« Ответ #6 : 11-11-2015, 19:48:06 »
 ;D Нет  :-[
Сейчас попробую. спасибо.

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Сравнение блоков
« Ответ #7 : 11-11-2015, 19:51:55 »
Я не утверждаю, что это сработает, но предположил как вариант. Если автодеск переопределила виртуальный метод Object.GetHashCode(), то имеет смысл попробовать, а если не переопределила, то скорее всего не поможет, т.к. у каждого объекта свои значения ObjectId и Handle, что наверняка повлияет на вычисление хеша в реализации, присутствующей по умолчанию.

Оффлайн ВильдарАвтор темы

  • ADN Club
  • ****
  • Сообщений: 409
  • Карма: 77
  • Skype: vildar82
Re: Сравнение блоков
« Ответ #8 : 11-11-2015, 19:55:21 »
Попробовал сравнить хеши - GetHashCode() у BlockTableRecord. Они разные для одинаковых блоков в разных файлах.
Просто, самый очевидный способ сразу не проверил. (

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Сравнение блоков
« Ответ #10 : 11-11-2015, 20:19:34 »
Однако код по указанной мною ссылке я бы переписал... Метод, выполняющий сравнение, должен (имхо) принимать логический параметр, указывающий на то, как выполнять проверку свойств, содержащих в качестве значения ObjectId: нужно ли сравнивать только значения таких идентификаторов, или же необходимо получать объекты, на которые указывают идентификаторы и рекурсивно сравнивать их. При этом следует вести контроль того, какие идентификаторы уже проверялись, дабы избежать попадания в бесконечный цикл, т.к. объекты могут иметь взаимные ссылки др. на др.

Оффлайн ВильдарАвтор темы

  • ADN Club
  • ****
  • Сообщений: 409
  • Карма: 77
  • Skype: vildar82
Re: Сравнение блоков
« Ответ #11 : 11-11-2015, 20:27:05 »
Может сделаю сравнение производительности разных способов сравнения объектов.
Для своего случая можно не сравнивать все параметры объекта, а только нужных. Может это будет быстрее.
Спасибо.

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

  • Administrator
  • *****
  • Сообщений: 13877
  • Карма: 1785
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: Сравнение блоков
« Ответ #12 : 11-11-2015, 20:28:57 »
В этом коде как минимум придётся исключить проверки свойств ObjectId. И вообще подозреваю, что с таким кодом проверка будет длится вечность... Не говоря уже о том сколько исключений будет при вызове свойств...
Кстати, этот вопрос (сравнение чертежей) мы кажется уже когда-то обсуждали.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Сравнение блоков
« Ответ #13 : 11-11-2015, 20:30:31 »
В этом коде как минимум придётся исключить проверки свойств ObjectId.
я выше писал насчёт ObjectId.

Оффлайн Андрей Бушман

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: Сравнение блоков
« Ответ #14 : 11-11-2015, 20:34:54 »
Не говоря уже о том сколько исключений будет при вызове свойств...
Сколько? :)