REMOVEALLPROXY

Автор Тема: REMOVEALLPROXY  (Прочитано 94014 раз)

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

Оффлайн Дима_

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Re: REMOVEALLPROXY
« Ответ #30 : 15-11-2014, 18:51:52 »
На которые код стал "лучше".

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #31 : 15-11-2014, 21:02:40 »
На которые код стал "лучше".
А! Я думаю что ты прав и мы не будем обсуждать стили программирования, а будем обсуждать существо программы. Например, я уже много лет собираюсь, но так и не реализовал такую интересную штуку, которая касается ExplodeAllProxy. Метод Explode далеко не всегда возвращает то, что соотвествует тому, что видно на экране. Достаточно часто изображение сдвинуто, повернуто и т.д. Чтобы получить реальное изображение proxy-примитива нужно:
1) создать свой класс унаследованный от AcGiWorldDraw и создать экземпляр этого класса (назовем его ProxyWorldDraw *wd)
2) вызвать метод worldDraw() нашего proxy-примитива, передав ему в качестве параметра wd
3) на основе того, что будет передано в wd создаём примитивы и помещаем их в базу данных.
Это очень упрощенная схема, но частично она реализована в ARXDBG в команде ArxDbgTestWorldDraw. Боюсь, что аналог в AutoCAD .NET API невозможен.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • Сообщений: 23
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #32 : 16-11-2014, 08:37:37 »
На мой взгляд, стоит забыть уже про высказывания о качестве кода, стили разные, да и обращать внимание на попытку сконцентрировать внимание на if-е, человеком который уже несколько раз просрочил завтра тоже не стоит (Андрей, если ты ратуешь за качество и производительность то должен знать, что switch намного быстрее if-а при перечислениях т.к позволит компилятору сделать хэш-меп и сразу выбрать значение). Нужно развивать идею с AcGiWorldDraw  или закрывать тему.

Оффлайн Алексей Кулик

  • Administrator
  • *****
  • Сообщений: 1096
  • Карма: 172
Re: REMOVEALLPROXY
« Ответ #33 : 16-11-2014, 16:29:51 »
На мой взгляд, стоит забыть уже про высказывания о качестве кода, стили разные, да и обращать внимание на попытку сконцентрировать внимание на if-е, человеком который уже несколько раз просрочил завтра тоже не стоит (Андрей, если ты ратуешь за качество и производительность то должен знать, что switch намного быстрее if-а при перечислениях т.к позволит компилятору сделать хэш-меп и сразу выбрать значение). Нужно развивать идею с AcGiWorldDraw  или закрывать тему.
Чего? Я несколько раз перечитал текст, но так ничего внятного и не понял.
Все, что сказано - личное мнение.

Правила форума существуют не просто так!

Приводя в сообщении код, не забывайте про его форматирование!

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #34 : 16-11-2014, 16:39:31 »
Чего? Я несколько раз перечитал текст, но так ничего внятного и не понял.
Я подозреваю, что это реакция на это:
Код T72 мне не понравился, поэтому написал свою альтернативу.
Надеюсь, что до виртуального рукоприкладства дело не дойдет. Иначе придётся принимать меры, а делать это мне очень не хочется.

Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • Сообщений: 23
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #35 : 16-11-2014, 18:16:11 »
Цитата: Алексей Кулик от 16-11-2014, 16:29:51

    Чего? Я несколько раз перечитал текст, но так ничего внятного и не понял.

Я подозреваю, что это реакция на это:
Цитата: Андрей Бушман от 12-11-2014, 20:01:39

    Код T72 мне не понравился, поэтому написал свою альтернативу.

Надеюсь, что до виртуального рукоприкладства дело не дойдет. Иначе придётся принимать меры, а делать это мне очень не хочется.
Да ну бросьте, если бы мне хотелось с кем то спорить и что-то доказывать то я отреагировал бы сразу после того поста. А так просто уже от темы в сторону стали уходить, поэтому я и написал, что стоит дальше развивать идею с "правильным" расчленением объектов или закрывать ее.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #36 : 16-11-2014, 21:13:03 »
Надеюсь, что до виртуального рукоприкладства дело не дойдет. Иначе придётся принимать меры, а делать это мне очень не хочется.
Я игнорирую, так что не дойдёт. :)

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #37 : 16-11-2014, 21:52:22 »
T72, я хотел бы уточнить (так как не тестировал твой код). Твой код после всех исправлений на форуме сейчас работает нормально, т.е. можно считать, что это полностью работоспособный вариант или нужно его править?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #38 : 19-11-2014, 13:34:33 »
В ниже предоставленном коде я отделяю "мух от котлет": предоставляю API для работы с proxy (и не только), на основе которого можно создавать различные команды в CAD системе (пример одной такой команды так же приведён ниже). Итак, мой вариант выглядит следующим образом:

Код - C# [Выбрать]
  1. // © Andrey Bushman, 2014
  2. // LayerLockingSwitcher.cs
  3.  
  4. using System;
  5.  
  6. #if AUTOCAD
  7. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  8. using Ap = Autodesk.AutoCAD.ApplicationServices;
  9. using Db = Autodesk.AutoCAD.DatabaseServices;
  10. using Ed = Autodesk.AutoCAD.EditorInput;
  11. using Rt = Autodesk.AutoCAD.Runtime;
  12. using Gm = Autodesk.AutoCAD.Geometry;
  13. #endif
  14.  
  15. namespace Bushman.CAD {
  16.     public sealed class LayerLockingSwitcher : IDisposable {
  17.  
  18.         static readonly Rt.RXClass layerRXType = Rt.RXClass.GetClass(typeof(
  19.                 Db.LayerTableRecord));
  20.         Db.ObjectId layerId = Db.ObjectId.Null;
  21.         Boolean oldValue = false;
  22.  
  23.         public LayerLockingSwitcher(Db.ObjectId id) {
  24.             // Check argument
  25.             if (null == id)
  26.                 throw new ArgumentNullException("null == id");
  27.             if (id.IsNull)
  28.                 throw new ArgumentException("id.IsNull == true");
  29.             if (id.IsErased)
  30.                 throw new ArgumentException("id.IsErased == true");
  31.             if (null == id.Database)
  32.                 throw new ArgumentException("null == id.Database");
  33.             if (id.Database.IsDisposed)
  34.                 throw new ArgumentException("id.Database.IsDisposed == true");
  35.  
  36.             if (!id.ObjectClass.IsDerivedFrom(layerRXType))
  37.                 throw new ArgumentException(
  38.                     "id.ObjectClass.IsDerivedFrom(layerRXType) != true");
  39.  
  40.             // -----------------            
  41.             layerId = id;
  42.             Db.Database db = layerId.Database;
  43.  
  44.             using (Db.Transaction tr = db.TransactionManager
  45.                 .StartOpenCloseTransaction()) {
  46.                 Db.LayerTableRecord layer = tr.GetObject(layerId,
  47.                     Db.OpenMode.ForRead) as Db.LayerTableRecord;
  48.                 oldValue = layer.IsLocked;
  49.                 if (oldValue) {
  50.                     layer.UpgradeOpen();
  51.                     layer.IsLocked = false;
  52.                 }
  53.                 tr.Commit();
  54.             }
  55.         }
  56.         public void Dispose() {
  57.             if (layerId.IsErased || !oldValue) {
  58.                 return;
  59.             }
  60.             Db.Database db = layerId.Database;
  61.             using (Db.Transaction tr = db.TransactionManager
  62.                 .StartOpenCloseTransaction()) {
  63.                 Db.LayerTableRecord layer = tr.GetObject(layerId,
  64.                     Db.OpenMode.ForWrite) as Db.LayerTableRecord;
  65.                 layer.IsLocked = true;
  66.                 tr.Commit();
  67.             }
  68.         }
  69.     }
  70. }

Код - C# [Выбрать]
  1. // © Andrey Bushman, 2014
  2. // ExtensionMethods.cs
  3. // This code partially based on Alexander Rivilis's code (ARX version):
  4. // http://adn-cis.org/forum/index.php?topic=1060.msg4983#msg4983
  5.  
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9.  
  10. #if AUTOCAD
  11. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  12. using Ap = Autodesk.AutoCAD.ApplicationServices;
  13. using Db = Autodesk.AutoCAD.DatabaseServices;
  14. using Ed = Autodesk.AutoCAD.EditorInput;
  15. using Rt = Autodesk.AutoCAD.Runtime;
  16. using Gm = Autodesk.AutoCAD.Geometry;
  17. #endif
  18.  
  19. namespace Bushman.CAD {
  20.     public static class ExtensionMethods {
  21.  
  22.         static Rt.RXClass proxyObjectRXType = Rt.RXClass.GetClass(typeof(
  23.             Db.ProxyObject));
  24.  
  25.         static Rt.RXClass proxyEntityRXType = Rt.RXClass.GetClass(typeof(
  26.             Db.ProxyEntity));
  27.  
  28.         public static Db.ObjectId[] GetDBObjectIds(this Db.Database db) {
  29.             Db.ObjectId[] ids = GetDBObjectIds(db, (n => true));
  30.             return ids;
  31.         }
  32.  
  33.         public static Db.ObjectId[] GetDBObjectIds(this Db.Database db,
  34.             Func<Db.ObjectId, Boolean> filter) {
  35.  
  36.             // Check arguments
  37.             if (null == db)
  38.                 throw new ArgumentNullException("null == db");
  39.             if (null == filter)
  40.                 throw new ArgumentNullException("null == filter");
  41.             if (db.IsDisposed)
  42.                 throw new ArgumentException("true == db.IsDisposed");
  43.  
  44.             // -------------------
  45.             Int32 approxNum = db.ApproxNumObjects;
  46.             List<Db.ObjectId> ids = new List<Db.ObjectId>();
  47.  
  48.             for (Int64 i = db.BlockTableId.Handle.Value; i < db.Handseed.Value
  49.                 && approxNum > 0; ++i) {
  50.  
  51.                 Db.Handle h = new Db.Handle(i);
  52.                 Db.ObjectId id = Db.ObjectId.Null;
  53.  
  54.                 Boolean parseResult = db.TryGetObjectId(h, out id);
  55.  
  56.                 if (parseResult) {
  57.                     --approxNum;
  58.                     if (filter(id)) {
  59.                         ids.Add(id);
  60.                     }
  61.                 }
  62.             }
  63.             return ids.ToArray();
  64.         }
  65.  
  66.         public static Db.ObjectId[] GetEntityIds(this Db.Database db) {
  67.             Db.ObjectId[] ids = GetEntityIds(db, (n => true));
  68.             return ids;
  69.         }
  70.  
  71.         public static Db.ObjectId[] GetEntityIds(this Db.Database db,
  72.             Func<Db.ObjectId, Boolean> filter) {
  73.  
  74.             // Check arguments
  75.             if (null == db)
  76.                 throw new ArgumentNullException("null == db");
  77.             if (null == filter)
  78.                 throw new ArgumentNullException("null == filter");
  79.             if (db.IsDisposed)
  80.                 throw new ArgumentException("true == db.IsDisposed");
  81.  
  82.             // -------------------
  83.             List<Db.ObjectId> ids = new List<Db.ObjectId>();
  84.             // Entity items can be located in the BlockTableRecord instances
  85.             // only.
  86.             using (Db.Transaction tr = db.TransactionManager.StartTransaction()
  87.                 ) {
  88.                 Db.BlockTable bt = tr.GetObject(db.BlockTableId,
  89.                     Db.OpenMode.ForRead) as Db.BlockTable;
  90.  
  91.                 // Skip erased BlockTableRecord instances.
  92.                 IEnumerable<Db.ObjectId> btrIds = bt.Cast<Db.ObjectId>()
  93.                     .Where(n => !n.IsErased);
  94.  
  95.                 foreach (Db.ObjectId btrId in btrIds) {
  96.                     Db.BlockTableRecord btr = tr.GetObject(btrId,
  97.                         Db.OpenMode.ForRead) as Db.BlockTableRecord;
  98.                     foreach (Db.ObjectId id in btr) {
  99.                         if (filter(id)) {
  100.                             ids.Add(id);
  101.                         }
  102.                     }
  103.                 }
  104.                 tr.Commit();
  105.             }
  106.             return ids.ToArray();
  107.         }
  108.  
  109.         public static Db.ObjectId[] ExplodeProxyEntity(
  110.             Db.ObjectId proxyEntityId) {
  111.  
  112.             // Check arguments
  113.             if (null == proxyEntityId)
  114.                 throw new ArgumentException("null == proxyEntityId");
  115.             if (proxyEntityId.IsErased)
  116.                 throw new ArgumentException("true == proxyEntityId.IsErased");
  117.             if (null == proxyEntityId.Database)
  118.                 throw new ArgumentException("null == proxyEntityId.Database");
  119.             if (proxyEntityId.Database.IsDisposed)
  120.                 throw new ArgumentException(
  121.                     "true == proxyEntityId.Database.IsDisposed");
  122.             if (!proxyEntityId.ObjectClass.IsDerivedFrom(proxyEntityRXType))
  123.                 throw new ArgumentException("false == proxyEntityId." +
  124.                     "ObjectClass.IsDerivedFrom(proxyEntityRXType)");
  125.  
  126.             // -------------------
  127.             using (Db.DBObjectCollection newDBObjects =
  128.                 new Db.DBObjectCollection()) {
  129.                 Db.Database db = proxyEntityId.Database;
  130.  
  131.                 using (Db.Transaction tr = db.TransactionManager
  132.                     .StartOpenCloseTransaction()) {
  133.                     Db.ProxyEntity proxyEntity = tr.GetObject(
  134.                         proxyEntityId, Db.OpenMode.ForRead)
  135.                         as Db.ProxyEntity;
  136.  
  137.                     using (new LayerLockingSwitcher(proxyEntity.LayerId)) {
  138.  
  139.                         proxyEntity.UpgradeOpen();
  140.  
  141.                         if (proxyEntity.GraphicsMetafileType ==
  142.                             Db.GraphicsMetafileType.FullGraphics) {
  143.  
  144.                             proxyEntity.Explode(newDBObjects);
  145.                         }
  146.                         else if (proxyEntity.GraphicsMetafileType ==
  147.                             Db.GraphicsMetafileType.BoundingBox) {
  148.  
  149.                             Db.Extents3d ext = proxyEntity.GeometricExtents;
  150.                             Gm.Point3dCollection arr =
  151.                                 new Gm.Point3dCollection();
  152.  
  153.                             arr.Add(ext.MinPoint);
  154.                             arr.Add(new Gm.Point3d(ext.MinPoint.X,
  155.                                 ext.MaxPoint.Y, ext.MinPoint.Z));
  156.                             arr.Add(new Gm.Point3d(ext.MaxPoint.X,
  157.                                 ext.MaxPoint.Y, ext.MinPoint.Z));
  158.                             arr.Add(new Gm.Point3d(ext.MaxPoint.X,
  159.                                 ext.MinPoint.Y, ext.MinPoint.Z));
  160.  
  161.                             Db.Polyline3d pline = new Db.Polyline3d(
  162.                                 Db.Poly3dType.SimplePoly, arr, true);
  163.  
  164.                             pline.LayerId = proxyEntity.LayerId;
  165.                             pline.LinetypeId = proxyEntity.LinetypeId;
  166.                             pline.Color = proxyEntity.Color;
  167.  
  168.                             newDBObjects.Add(pline);
  169.                         }
  170.  
  171.                         try {
  172.                             proxyEntity.Erase();
  173.                         }
  174.                         catch {
  175.                             if (!proxyEntity.IsErased) {
  176.                                 using (Db.Line rep = new Db.Line()) {
  177.                                     proxyEntity.HandOverTo(rep, false, false);
  178.                                     rep.Erase();
  179.                                     rep.Close();
  180.                                     proxyEntity.Dispose();
  181.                                 }
  182.                             }
  183.                         }
  184.  
  185.                         Db.BlockTableRecord btr = tr.GetObject(
  186.                             proxyEntity.BlockId, Db.OpenMode.ForWrite, false)
  187.                             as Db.BlockTableRecord;
  188.  
  189.                         if (newDBObjects.Count > 0) {
  190.                             foreach (Db.DBObject item in newDBObjects) {
  191.                                 if (item is Db.Entity) {
  192.                                     Db.Entity _ent = item as Db.Entity;
  193.                                     btr.AppendEntity(_ent);
  194.                                     tr.AddNewlyCreatedDBObject(item, true);
  195.                                 }
  196.                             }
  197.                         }
  198.                         Db.ObjectIdCollection idsRef =
  199.                             btr.GetBlockReferenceIds(true, true);
  200.                         foreach (Db.ObjectId id in idsRef) {
  201.                             Db.BlockReference br = tr.GetObject(id,
  202.                                 Db.OpenMode.ForWrite, false)
  203.                                 as Db.BlockReference;
  204.                             br.RecordGraphicsModified(true);
  205.                         }
  206.                         tr.Commit();
  207.                     }
  208.                 }
  209.                 return newDBObjects.Cast<Db.DBObject>().Select(n => n.ObjectId)
  210.                     .ToArray();
  211.             }
  212.         }
  213.  
  214.         public static void RemoveDBObject(Db.ObjectId id) {
  215.  
  216.             // Check arguments
  217.             if (null == id)
  218.                 throw new ArgumentException("null == id");
  219.             if (id.IsErased)
  220.                 throw new ArgumentException("true == id.IsErased");
  221.             if (null == id.Database)
  222.                 throw new ArgumentException("null == id.Database");
  223.             if (id.Database.IsDisposed)
  224.                 throw new ArgumentException("true == id.Database.IsDisposed");
  225.  
  226.             // -------------------
  227.             Db.Database db = id.Database;
  228.  
  229.             using (Db.Transaction tr = db.TransactionManager
  230.                 .StartOpenCloseTransaction()) {
  231.                 Db.DBObject obj = tr.GetObject(id, Db.OpenMode.ForRead);
  232.                 if (obj is Db.Entity) {
  233.                     Db.Entity ent = obj as Db.Entity;                    
  234.                     using (new LayerLockingSwitcher(ent.LayerId)) {
  235.                         ent.UpgradeOpen();
  236.                         EraseDBObject(obj);
  237.                     }
  238.                 }
  239.                 else {
  240.                     obj.UpgradeOpen();
  241.                     EraseDBObject(obj);
  242.                 }
  243.                 tr.Commit();
  244.             }
  245.         }
  246.  
  247.         private static void EraseDBObject(Db.DBObject obj) {
  248.  
  249.             // Check argument
  250.             if (null == obj)
  251.                 throw new ArgumentNullException("null == obj");
  252.             if (obj.IsErased)
  253.                 throw new ArgumentException("true == obj.IsErased");
  254.             if (obj.IsDisposed)
  255.                 throw new ArgumentException("true == obj.IsDisposed");
  256.             if (null == obj.Database)
  257.                 throw new ArgumentException("null == obj.Database");
  258.             if (obj.Database.IsDisposed)
  259.                 throw new ArgumentException("true == obj.Database.IsDisposed");
  260.  
  261.             // ----------------
  262.             try {
  263.                 obj.Erase(true);
  264.             }
  265.             catch {
  266.                 if (!obj.IsErased) {
  267.                     using (Db.DBObject rep = obj is Db.Entity ?
  268.                         (Db.DBObject)new Db.Line() :
  269.                         new Db.DBDictionary()) {
  270.                         obj.HandOverTo(rep, false, false);
  271.                         rep.Erase(true);
  272.                         rep.Close();
  273.                         obj.Dispose();
  274.                     }
  275.                 }
  276.             }
  277.         }
  278.  
  279.         public static Db.ObjectId[] GetFreeAnnotativeScaleIds(
  280.             this Db.Database db) {
  281.  
  282.             // Check argument
  283.             if (null == db)
  284.                 throw new ArgumentNullException("null == db");
  285.             if (db.IsDisposed)
  286.                 throw new ArgumentException("true == db.IsDisposed");
  287.  
  288.             // ----------------
  289.             using (Db.ObjectIdCollection ids = new Db.ObjectIdCollection()) {
  290.                 Db.ObjectContextManager ocMng = db.ObjectContextManager;
  291.                 if (null != ocMng) {
  292.                     Db.ObjectContextCollection ocItems =
  293.                         ocMng.GetContextCollection("ACDB_ANNOTATIONSCALES");
  294.                     if (null != ocItems) {
  295.                         foreach (Db.ObjectContext item in ocItems) {
  296.                             if (item is Db.AnnotationScale)
  297.                                 ids.Add(new Db.ObjectId(item.UniqueIdentifier));
  298.                         }
  299.                         db.Purge(ids);
  300.                     }
  301.                 }
  302.                 return ids.Cast<Db.ObjectId>().ToArray();
  303.             }
  304.         }
  305.  
  306.         public static void RemoveFreeAnnotativeScales(this Db.Database db) {
  307.  
  308.             // Check argument
  309.             if (null == db)
  310.                 throw new ArgumentNullException("null == db");
  311.             if (db.IsDisposed)
  312.                 throw new ArgumentException("true == db.IsDisposed");
  313.  
  314.             // -----------------
  315.             Db.ObjectId[] ids = db.GetFreeAnnotativeScaleIds();
  316.  
  317.             using (Db.Transaction tr = db.TransactionManager.StartTransaction()
  318.                 ) {
  319.                 foreach (Db.ObjectId id in ids) {
  320.                     try {
  321.                         Db.DBObject obj = tr.GetObject(id, Db.OpenMode
  322.                             .ForWrite, false);
  323.                         obj.Erase();
  324.                     }
  325.                     catch { }
  326.                 }
  327.                 tr.Commit();
  328.             }
  329.         }
  330.     }
  331. }

Ну и теперь, собственно, пример использования:
Код - C# [Выбрать]
  1. // © Andrey Bushman, 2014
  2. // Commands.cs
  3.  
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7.  
  8. #if AUTOCAD
  9. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  10. using Ap = Autodesk.AutoCAD.ApplicationServices;
  11. using Db = Autodesk.AutoCAD.DatabaseServices;
  12. using Ed = Autodesk.AutoCAD.EditorInput;
  13. using Rt = Autodesk.AutoCAD.Runtime;
  14. using Gm = Autodesk.AutoCAD.Geometry;
  15. #endif
  16.  
  17. [assembly: Rt.ExtensionApplication(typeof(Bushman.CAD.ExtensionApplication))]
  18. [assembly: Rt.CommandClass(typeof(Bushman.CAD.Commands))]
  19.  
  20. namespace Bushman.CAD {
  21.     public sealed class Commands {
  22.  
  23.         [Rt.CommandMethod("Test", Rt.CommandFlags.Modal)]
  24.         public void Command_Test() {
  25.  
  26.             Ap.Document doc = cad.DocumentManager.MdiActiveDocument;
  27.             Ed.Editor ed = doc.Editor;
  28.             Db.Database db = doc.Database;
  29.  
  30.             // Get ids for unerased objects only
  31.             Db.ObjectId[] ids = db.GetDBObjectIds(n => !n.IsErased);
  32.             ed.WriteMessage("DBObjects count before: {0}.\n", ids.Length
  33.                 .ToString());
  34.  
  35.             Rt.RXClass proxyObjectRXType = Rt.RXClass.GetClass(typeof(
  36.                 Db.ProxyObject));
  37.             Rt.RXClass proxyEntityRXType = Rt.RXClass.GetClass(typeof(
  38.                 Db.ProxyEntity));
  39.  
  40.             Func<Db.ObjectId, Boolean> proxyEntityFilter = n => !n.IsErased &&
  41.                 n.ObjectClass.IsDerivedFrom(proxyEntityRXType);
  42.  
  43.             Func<Db.ObjectId, Boolean> proxyObjectFilter = n => !n.IsErased &&
  44.                 n.ObjectClass.IsDerivedFrom(proxyObjectRXType);
  45.  
  46.             Db.ObjectId[] proxyEntityIds = db.GetEntityIds(proxyEntityFilter);
  47.             ed.WriteMessage("including ProxyEntity items count: {0};\n",
  48.                 proxyEntityIds.Length.ToString());
  49.  
  50.             Db.ObjectId[] proxyObjectIds = db.GetDBObjectIds(proxyObjectFilter);
  51.             ed.WriteMessage("including ProxyObject items count: {0};\n\n",
  52.                 proxyObjectIds.Length.ToString());
  53.  
  54.             Int64 newEntityCount = 0;
  55.  
  56.             foreach (Db.ObjectId id in proxyEntityIds) {
  57.                 Db.ObjectId[] newEntityIds = ExtensionMethods
  58.                     .ExplodeProxyEntity(id);
  59.                 newEntityCount += newEntityIds.Length;
  60.             }
  61.  
  62.             foreach (Db.ObjectId id in proxyObjectIds) {
  63.                 ExtensionMethods.RemoveDBObject(id);
  64.             }
  65.  
  66.             ed.WriteMessage("All ProxyEntity items exploded.\nNew DBObjects " +
  67.                 "count: {0}.\n", newEntityCount.ToString());
  68.             ed.WriteMessage("All ProxyObject items removed.\n\n");
  69.  
  70.             Db.ObjectId[] freeAnnotScaleIds = db.GetFreeAnnotativeScaleIds();
  71.  
  72.             ed.WriteMessage("Unused annotation scales count: {0}.\n",
  73.                 freeAnnotScaleIds.Length.ToString());
  74.  
  75.             db.RemoveFreeAnnotativeScales();
  76.             ed.WriteMessage("Unused annotation scales removed.\n\n");
  77.  
  78.             ids = db.GetDBObjectIds(n => !n.IsErased);
  79.             ed.WriteMessage("DBObjects count after: {0}.\n\n" +
  80.                 "Run the _AUDIT command with the _Y option, please.\n",
  81.                 ids.Length.ToString());
  82.         }
  83.     }
  84. }

В результате работы команы в консоль CAD системы выводится отчёт о проделанной работе. Для сравнения (дабы можно было сравнить количество обработанных объектов), ниже для того же DWG файла приведён лог, выводимый в консоль командами ExplodeAllProxy и RemoveAllProxy, написанными Р.А.Н.:

Цитата: CAD console output (R.A.N.)
Command: explodeallproxy
Удалено Proxy: 230 Новых объектов: 3834

Command: removeallproxy
Первая метка объекта: <1>, последняя метка объекта: <34A9>
Всего найдено proxy-объектов: 4609. Из них proxy-примитивов: 0.
Всего удалено proxy-объектов: 4609. Из них proxy-примитивов: 0.
Для проверки ошибок выполните команду _AUDIT

Цитата: CAD console output (Bushman)
Command: test
DBObjects count before: 5565.
including ProxyEntity items count: 230;
including ProxyObject items count: 4609;

All ProxyEntity items exploded.
New DBObjects count: 3834.
All ProxyObject items removed.

Unused annotation scales count: 24.
Unused annotation scales removed.

DBObjects count after: 4869.

Run the _AUDIT command with the _Y option, please.

Конструктивная критика и замечания приветствуются.

P.S. Код тестировался в AutoCAD 2009 Enu SP3 x64.
« Последнее редактирование: 19-11-2014, 15:29:17 от Андрей Бушман »

Оффлайн German

  • ADN Club
  • **
  • Сообщений: 84
  • Карма: 13
Re: REMOVEALLPROXY
« Ответ #39 : 19-11-2014, 14:11:19 »
замечания приветствуются
Заметил по отчету, что DBObjects count меняется не "арифметически":
(5565 - 230 + 3834 - 4609 - 24) != 4869
Оставшиеся ведь и не удаленные, и валидные. Это нормально?

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #40 : 19-11-2014, 14:59:16 »
Это нормально?
Нужно будет поразбираться, почему не бьётся сумма.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #41 : 20-11-2014, 12:42:19 »
За счёт добавления проверки ProxyFlags удалось избавиться от блоков try\catch, что в свою очередь позволило существенно увеличить скорость работы. В виду этого появился смысл переписать класс LayoutLockingSwitcher и внести изменения в ряд методов класса ExtensionMethods, что и было сделано. В статический класс ExtensionMethods добавлен метод GetLockedLayerIds. Изменены сигнатуры методов ExplodeProxyEntity, EraseDBObject и RemoveDBObject - добавлена возможность вести подсчёт количества вызовов HandOverTo. Подумав, добавил в фильтрах, обозначенных в коде команды, проверку на не уничтоженность владельцев в иерархии владения объектами (свойство IsEffectivelyErased).

В виду переработки LayoutLockingSwitcher, внесены соответствующие изменения в код тестовой команды. Дополнительно в коде команды добавлена некоторая информация, отправляемая в консоль.
Код - C# [Выбрать]
  1. // © Andrey Bushman, 2014
  2. // LayerLockingSwitcher.cs
  3.  
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7.  
  8. #if AUTOCAD
  9. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  10. using Ap = Autodesk.AutoCAD.ApplicationServices;
  11. using Db = Autodesk.AutoCAD.DatabaseServices;
  12. using Ed = Autodesk.AutoCAD.EditorInput;
  13. using Rt = Autodesk.AutoCAD.Runtime;
  14. using Gm = Autodesk.AutoCAD.Geometry;
  15. #endif
  16.  
  17. namespace Bushman.CAD {
  18.     public sealed class LayerLockingSwitcher : IDisposable {
  19.  
  20.         static readonly Rt.RXClass layerRXType = Rt.RXClass.GetClass(typeof(
  21.                 Db.LayerTableRecord));
  22.         List<Db.ObjectId> layerIds = null;
  23.  
  24.         public LayerLockingSwitcher(Db.ObjectId[] layer_ids) {
  25.  
  26.             // Check argument
  27.             if (null == layer_ids)
  28.                 throw new ArgumentNullException("null == ids");
  29.             if (0 == layer_ids.Length)
  30.                 return;
  31.             if (layer_ids.Select(n => n.Database).Distinct().Count() > 1)
  32.                 throw new ArgumentException("All items must to have the " +
  33.                     "same 'Database' property value.");
  34.  
  35.             // -----------------            
  36.             layerIds = new List<Db.ObjectId>();
  37.             Db.Database db = layer_ids[0].Database;
  38.  
  39.             using (Db.Transaction tr = db.TransactionManager
  40.                 .StartOpenCloseTransaction()) {
  41.                 foreach (Db.ObjectId id in layer_ids) {
  42.                     if (!id.IsNull &&
  43.                         !id.IsErased &&
  44.                         !id.IsEffectivelyErased &&
  45.                         null != id.Database &&
  46.                         !id.Database.IsDisposed &&
  47.                         id.ObjectClass.IsDerivedFrom(layerRXType)) {
  48.  
  49.                         Db.LayerTableRecord layer = tr.GetObject(id,
  50.                     Db.OpenMode.ForRead) as Db.LayerTableRecord;
  51.                         if (layer.IsLocked) {
  52.                             layer.UpgradeOpen();
  53.                             layer.IsLocked = false;
  54.                             layerIds.Add(id);
  55.                         }
  56.                     }
  57.                 }
  58.                 tr.Commit();
  59.             }
  60.         }
  61.         public void Dispose() {
  62.             if (layerIds.Count == 0)
  63.                 return;
  64.  
  65.             Db.Database db = layerIds[0].Database;
  66.             using (Db.Transaction tr = db.TransactionManager
  67.                 .StartOpenCloseTransaction()) {
  68.                 foreach (Db.ObjectId id in layerIds) {
  69.                     Db.LayerTableRecord layer = tr.GetObject(id,
  70.                         Db.OpenMode.ForWrite) as Db.LayerTableRecord;
  71.                     layer.IsLocked = true;
  72.                 }
  73.                 tr.Commit();
  74.             }
  75.         }
  76.     }
  77. }

Код - C# [Выбрать]
  1. // © Andrey Bushman, 2014
  2. // ExtensionMethods.cs
  3. // This code partially based on Alexander Rivilis's code (ARX version):
  4. // http://adn-cis.org/forum/index.php?topic=1060.msg4983#msg4983
  5.  
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9.  
  10. #if AUTOCAD
  11. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  12. using Ap = Autodesk.AutoCAD.ApplicationServices;
  13. using Db = Autodesk.AutoCAD.DatabaseServices;
  14. using Ed = Autodesk.AutoCAD.EditorInput;
  15. using Rt = Autodesk.AutoCAD.Runtime;
  16. using Gm = Autodesk.AutoCAD.Geometry;
  17. #endif
  18.  
  19. namespace Bushman.CAD {
  20.     public static class ExtensionMethods {
  21.  
  22.         static Rt.RXClass proxyObjectRXType = Rt.RXClass.GetClass(typeof(
  23.             Db.ProxyObject));
  24.  
  25.         static Rt.RXClass proxyEntityRXType = Rt.RXClass.GetClass(typeof(
  26.             Db.ProxyEntity));
  27.  
  28.         public static Db.ObjectId[] GetDBObjectIds(this Db.Database db) {
  29.             Db.ObjectId[] ids = GetDBObjectIds(db, (n => true));
  30.             return ids;
  31.         }
  32.  
  33.         public static Db.ObjectId[] GetDBObjectIds(this Db.Database db,
  34.             Func<Db.ObjectId, Boolean> filter) {
  35.  
  36.             // Check arguments
  37.             if (null == db)
  38.                 throw new ArgumentNullException("null == db");
  39.             if (null == filter)
  40.                 throw new ArgumentNullException("null == filter");
  41.             if (db.IsDisposed)
  42.                 throw new ArgumentException("true == db.IsDisposed");
  43.  
  44.             // -------------------
  45.             Int32 approxNum = db.ApproxNumObjects;
  46.             List<Db.ObjectId> ids = new List<Db.ObjectId>();
  47.  
  48.             for (Int64 i = db.BlockTableId.Handle.Value; i < db.Handseed.Value
  49.                 && approxNum > 0; ++i) {
  50.  
  51.                 Db.Handle h = new Db.Handle(i);
  52.                 Db.ObjectId id = Db.ObjectId.Null;
  53.  
  54.                 Boolean parseResult = db.TryGetObjectId(h, out id);
  55.  
  56.                 if (parseResult) {
  57.                     --approxNum;
  58.                     if (filter(id)) {
  59.                         ids.Add(id);
  60.                     }
  61.                 }
  62.             }
  63.             return ids.ToArray();
  64.         }
  65.  
  66.         public static Db.ObjectId[] GetEntityIds(this Db.Database db) {
  67.             Db.ObjectId[] ids = GetEntityIds(db, (n => true));
  68.             return ids;
  69.         }
  70.  
  71.         public static Db.ObjectId[] GetEntityIds(this Db.Database db,
  72.             Func<Db.ObjectId, Boolean> filter) {
  73.  
  74.             // Check arguments
  75.             if (null == db)
  76.                 throw new ArgumentNullException("null == db");
  77.             if (null == filter)
  78.                 throw new ArgumentNullException("null == filter");
  79.             if (db.IsDisposed)
  80.                 throw new ArgumentException("true == db.IsDisposed");
  81.  
  82.             // -------------------
  83.             List<Db.ObjectId> ids = new List<Db.ObjectId>();
  84.             // Entity items can be located in the BlockTableRecord instances
  85.             // only.
  86.             using (Db.Transaction tr = db.TransactionManager.StartTransaction()
  87.                 ) {
  88.                 Db.BlockTable bt = tr.GetObject(db.BlockTableId,
  89.                     Db.OpenMode.ForRead) as Db.BlockTable;
  90.  
  91.                 // Skip erased BlockTableRecord instances.
  92.                 IEnumerable<Db.ObjectId> btrIds = bt.Cast<Db.ObjectId>()
  93.                     .Where(n => !n.IsErased);
  94.  
  95.                 foreach (Db.ObjectId btrId in btrIds) {
  96.                     Db.BlockTableRecord btr = tr.GetObject(btrId,
  97.                         Db.OpenMode.ForRead) as Db.BlockTableRecord;
  98.                     foreach (Db.ObjectId id in btr) {
  99.                         if (filter(id)) {
  100.                             ids.Add(id);
  101.                         }
  102.                     }
  103.                 }
  104.                 tr.Commit();
  105.             }
  106.             return ids.ToArray();
  107.         }
  108.  
  109.         public static Db.ObjectId[] ExplodeProxyEntity(
  110.             Db.ObjectId proxyEntityId, out Boolean handOverTo_called) {
  111.  
  112.             // Check arguments
  113.             if (null == proxyEntityId)
  114.                 throw new ArgumentException("null == proxyEntityId");
  115.             if (proxyEntityId.IsErased)
  116.                 throw new ArgumentException("true == proxyEntityId.IsErased");
  117.             if (null == proxyEntityId.Database)
  118.                 throw new ArgumentException("null == proxyEntityId.Database");
  119.             if (proxyEntityId.Database.IsDisposed)
  120.                 throw new ArgumentException(
  121.                     "true == proxyEntityId.Database.IsDisposed");
  122.             if (!proxyEntityId.ObjectClass.IsDerivedFrom(proxyEntityRXType))
  123.                 throw new ArgumentException("false == proxyEntityId." +
  124.                     "ObjectClass.IsDerivedFrom(proxyEntityRXType)");
  125.  
  126.             // -------------------
  127.             using (Db.DBObjectCollection newDBObjects =
  128.                 new Db.DBObjectCollection()) {
  129.                 Db.Database db = proxyEntityId.Database;
  130.  
  131.                 using (Db.Transaction tr = db.TransactionManager
  132.                     .StartOpenCloseTransaction()) {
  133.                     Db.ProxyEntity proxyEntity = tr.GetObject(
  134.                         proxyEntityId, Db.OpenMode.ForWrite)
  135.                         as Db.ProxyEntity;
  136.  
  137.                     if (proxyEntity.GraphicsMetafileType ==
  138.                         Db.GraphicsMetafileType.FullGraphics) {
  139.  
  140.                         proxyEntity.Explode(newDBObjects);
  141.                     }
  142.                     else if (proxyEntity.GraphicsMetafileType ==
  143.                         Db.GraphicsMetafileType.BoundingBox) {
  144.  
  145.                         Db.Extents3d ext = proxyEntity.GeometricExtents;
  146.                         Gm.Point3dCollection arr =
  147.                             new Gm.Point3dCollection();
  148.  
  149.                         arr.Add(ext.MinPoint);
  150.                         arr.Add(new Gm.Point3d(ext.MinPoint.X,
  151.                             ext.MaxPoint.Y, ext.MinPoint.Z));
  152.                         arr.Add(new Gm.Point3d(ext.MaxPoint.X,
  153.                             ext.MaxPoint.Y, ext.MinPoint.Z));
  154.                         arr.Add(new Gm.Point3d(ext.MaxPoint.X,
  155.                             ext.MinPoint.Y, ext.MinPoint.Z));
  156.  
  157.                         Db.Polyline3d pline = new Db.Polyline3d(
  158.                             Db.Poly3dType.SimplePoly, arr, true);
  159.  
  160.                         pline.LayerId = proxyEntity.LayerId;
  161.                         pline.LinetypeId = proxyEntity.LinetypeId;
  162.                         pline.Color = proxyEntity.Color;
  163.  
  164.                         newDBObjects.Add(pline);
  165.                     }
  166.  
  167.                     // ----------------
  168.                     Boolean canBeErased = (proxyEntity.ProxyFlags & 0x1) != 0;
  169.  
  170.                     if (canBeErased) {
  171.                         proxyEntity.Erase();
  172.                         handOverTo_called = false;
  173.                     }
  174.                     else {
  175.                         using (Db.Line tmp = new Db.Line()) {
  176.                             proxyEntity.HandOverTo(tmp, false, false);
  177.                             tmp.Erase();
  178.                             proxyEntity.Dispose();
  179.                             handOverTo_called = true;
  180.                         }
  181.                     }
  182.  
  183.                     Db.BlockTableRecord btr = tr.GetObject(
  184.                         proxyEntity.BlockId, Db.OpenMode.ForWrite, false)
  185.                         as Db.BlockTableRecord;
  186.  
  187.                     if (newDBObjects.Count > 0) {
  188.                         foreach (Db.DBObject item in newDBObjects) {
  189.                             if (item is Db.Entity) {
  190.                                 Db.Entity _ent = item as Db.Entity;
  191.                                 btr.AppendEntity(_ent);
  192.                                 tr.AddNewlyCreatedDBObject(item, true);
  193.                             }
  194.                         }
  195.                     }
  196.                     Db.ObjectIdCollection idsRef =
  197.                         btr.GetBlockReferenceIds(true, true);
  198.                     foreach (Db.ObjectId id in idsRef) {
  199.                         Db.BlockReference br = tr.GetObject(id,
  200.                             Db.OpenMode.ForWrite, false)
  201.                             as Db.BlockReference;
  202.                         br.RecordGraphicsModified(true);
  203.                     }
  204.                     tr.Commit();
  205.                 }
  206.                 return newDBObjects.Cast<Db.DBObject>().Select(n => n.ObjectId)
  207.                     .ToArray();
  208.             }
  209.         }
  210.  
  211.         public static void RemoveDBObject(Db.ObjectId id,
  212.             out Boolean handOverTo_called) {
  213.  
  214.             // Check arguments
  215.             if (null == id)
  216.                 throw new ArgumentException("null == id");
  217.             if (id.IsErased)
  218.                 throw new ArgumentException("true == id.IsErased");
  219.             if (null == id.Database)
  220.                 throw new ArgumentException("null == id.Database");
  221.             if (id.Database.IsDisposed)
  222.                 throw new ArgumentException("true == id.Database.IsDisposed");
  223.  
  224.             // -------------------
  225.             Db.Database db = id.Database;
  226.  
  227.             using (Db.Transaction tr = db.TransactionManager
  228.                 .StartOpenCloseTransaction()) {
  229.                 Db.DBObject obj = tr.GetObject(id, Db.OpenMode.ForWrite);
  230.                 EraseDBObject(obj, out handOverTo_called);
  231.                 tr.Commit();
  232.             }
  233.         }
  234.  
  235.         private static void EraseDBObject(Db.DBObject obj,
  236.             out Boolean handOverTo_called) {
  237.  
  238.             // Check argument
  239.             if (null == obj)
  240.                 throw new ArgumentNullException("null == obj");
  241.             if (obj.IsErased)
  242.                 throw new ArgumentException("true == obj.IsErased");
  243.             if (obj.IsDisposed)
  244.                 throw new ArgumentException("true == obj.IsDisposed");
  245.             if (null == obj.Database)
  246.                 throw new ArgumentException("null == obj.Database");
  247.             if (obj.Database.IsDisposed)
  248.                 throw new ArgumentException("true == obj.Database.IsDisposed");
  249.  
  250.             // ----------------
  251.             Boolean canBeErased = true;
  252.  
  253.             // AcDbProxyEntity::kEraseAllowed = 0x1
  254.             if (obj is Db.ProxyObject) {
  255.                 Db.ProxyObject proxy = obj as Db.ProxyObject;
  256.                 canBeErased = (proxy.ProxyFlags & 0x1) != 0;
  257.             }
  258.             else if (obj is Db.ProxyEntity) {
  259.                 Db.ProxyEntity proxy = obj as Db.ProxyEntity;
  260.                 canBeErased = (proxy.ProxyFlags & 0x1) != 0;
  261.             }
  262.  
  263.             if (canBeErased) {
  264.                 obj.Erase(true);
  265.                 handOverTo_called = false;
  266.             }
  267.             else {
  268.                 using (Db.DBObject tmp = obj is Db.Entity ?
  269.                     (Db.DBObject)new Db.Line() : new Db.DBDictionary()) {
  270.                     obj.HandOverTo(tmp, false, false);
  271.                     tmp.Erase(true);
  272.                     obj.Dispose();
  273.                     handOverTo_called = true;
  274.                 }
  275.             }
  276.         }
  277.  
  278.         public static Db.ObjectId[] GetFreeAnnotativeScaleIds(
  279.             this Db.Database db) {
  280.  
  281.             // Check argument
  282.             if (null == db)
  283.                 throw new ArgumentNullException("null == db");
  284.             if (db.IsDisposed)
  285.                 throw new ArgumentException("true == db.IsDisposed");
  286.  
  287.             // ----------------
  288.             using (Db.ObjectIdCollection ids = new Db.ObjectIdCollection()) {
  289.                 Db.ObjectContextManager ocMng = db.ObjectContextManager;
  290.                 if (null != ocMng) {
  291.                     Db.ObjectContextCollection ocItems =
  292.                         ocMng.GetContextCollection("ACDB_ANNOTATIONSCALES");
  293.                     if (null != ocItems) {
  294.                         foreach (Db.ObjectContext item in ocItems) {
  295.                             if (item is Db.AnnotationScale)
  296.                                 ids.Add(new Db.ObjectId(item.UniqueIdentifier)
  297.                                     );
  298.                         }
  299.                         db.Purge(ids);
  300.                     }
  301.                 }
  302.                 return ids.Cast<Db.ObjectId>().ToArray();
  303.             }
  304.         }
  305.  
  306.         public static void RemoveFreeAnnotativeScales(this Db.Database db) {
  307.  
  308.             // Check argument
  309.             if (null == db)
  310.                 throw new ArgumentNullException("null == db");
  311.             if (db.IsDisposed)
  312.                 throw new ArgumentException("true == db.IsDisposed");
  313.  
  314.             // -----------------
  315.             Db.ObjectId[] ids = db.GetFreeAnnotativeScaleIds();
  316.  
  317.             using (Db.Transaction tr = db.TransactionManager.StartTransaction()
  318.                 ) {
  319.                 foreach (Db.ObjectId id in ids) {
  320.                     try {
  321.                         Db.DBObject obj = tr.GetObject(id, Db.OpenMode
  322.                             .ForWrite, false);
  323.                         obj.Erase();
  324.                     }
  325.                     catch { }
  326.                 }
  327.                 tr.Commit();
  328.             }
  329.         }
  330.  
  331.         public static Db.ObjectId[] GetLockedLayerIds(Db.ObjectId[] entityIds
  332.             ) {
  333.  
  334.             if (null == entityIds)
  335.                 throw new ArgumentNullException("null == entityIds");
  336.  
  337.             if (0 == entityIds.Length)
  338.                 return new Db.ObjectId[] { };
  339.  
  340.             if (entityIds.Select(n => n.Database).Distinct().Count() > 1)
  341.                 throw new ArgumentException(
  342.                     "All items of 'entityIds' must to have the same " +
  343.                     "'Database' property value.");
  344.  
  345.             Rt.RXClass entityRXType = Rt.RXClass.GetClass(typeof(Db.Entity));
  346.             if (entityIds.Any(n => !n.ObjectClass.IsDerivedFrom(entityRXType)))
  347.                 throw new ArgumentException("All items of 'entityIds' must " +
  348.                     "to be derived from Entity type.");
  349.  
  350.             if (null == entityIds[0].Database || entityIds[0].Database
  351.                 .IsDisposed)
  352.                 throw new ArgumentNullException(
  353.                     "entityIds[0].Database || entityIds[0].Database.IsDisposed"
  354.                     );
  355.  
  356.             HashSet<Db.ObjectId> hashSet = new HashSet<Db.ObjectId>();
  357.  
  358.             using (Db.Transaction tr = entityIds[0].Database.TransactionManager
  359.                 .StartTransaction()) {
  360.                 foreach (Db.ObjectId id in entityIds) {
  361.  
  362.                     Db.Entity entity = tr.GetObject(id, Db.OpenMode
  363.                         .ForRead, true) as Db.Entity;
  364.  
  365.                     Db.LayerTableRecord layer = tr.GetObject(entity.LayerId,
  366.                         Db.OpenMode.ForRead, false) as Db.LayerTableRecord;
  367.  
  368.                     if (layer.IsLocked) {
  369.                         hashSet.Add(entity.LayerId);
  370.                     }
  371.                 }
  372.                 tr.Commit();
  373.             }
  374.             return hashSet.ToArray();
  375.         }
  376.     }
  377. }

Код - C# [Выбрать]
  1. // © Andrey Bushman, 2014
  2. // Commands.cs
  3.  
  4. using System;
  5. using System.Collections.Generic;
  6. using System.Linq;
  7. using System.Diagnostics;
  8.  
  9. #if AUTOCAD
  10. using cad = Autodesk.AutoCAD.ApplicationServices.Application;
  11. using Ap = Autodesk.AutoCAD.ApplicationServices;
  12. using Db = Autodesk.AutoCAD.DatabaseServices;
  13. using Ed = Autodesk.AutoCAD.EditorInput;
  14. using Rt = Autodesk.AutoCAD.Runtime;
  15. using Gm = Autodesk.AutoCAD.Geometry;
  16. #endif
  17.  
  18. [assembly: Rt.CommandClass(typeof(Bushman.CAD.Commands))]
  19.  
  20. namespace Bushman.CAD {
  21.     public sealed class Commands {
  22.  
  23.         [Rt.CommandMethod("Test", Rt.CommandFlags.Modal)]
  24.         public void Command_Test() {
  25.  
  26.             Ap.Document doc = cad.DocumentManager.MdiActiveDocument;
  27.             Ed.Editor ed = doc.Editor;
  28.             Db.Database db = doc.Database;
  29.  
  30.             Stopwatch sw = Stopwatch.StartNew();
  31.             sw.Start();
  32.  
  33.             // Get ids of unerased objects only
  34.             Db.ObjectId[] ids = db.GetDBObjectIds(n => !n.IsErased &&
  35.                 !n.IsEffectivelyErased);
  36.             ed.WriteMessage("\nDBObjects count before: {0}.\n", ids.Length
  37.                 .ToString());
  38.  
  39.             Rt.RXClass proxyObjectRXType = Rt.RXClass.GetClass(typeof(
  40.                 Db.ProxyObject));
  41.             Rt.RXClass proxyEntityRXType = Rt.RXClass.GetClass(typeof(
  42.                 Db.ProxyEntity));
  43.  
  44.             Func<Db.ObjectId, Boolean> proxyEntityFilter = n => !n.IsErased &&
  45.                  !n.IsEffectivelyErased && n.ObjectClass.IsDerivedFrom(
  46.                  proxyEntityRXType);
  47.  
  48.             Func<Db.ObjectId, Boolean> proxyObjectFilter = n => !n.IsErased &&
  49.                 !n.IsEffectivelyErased && n.ObjectClass.IsDerivedFrom(
  50.                 proxyObjectRXType);
  51.  
  52.             Db.ObjectId[] proxyEntityIds = db.GetEntityIds(proxyEntityFilter);
  53.             ed.WriteMessage("including ProxyEntity items count: {0};\n",
  54.                 proxyEntityIds.Length.ToString());
  55.  
  56.             Db.ObjectId[] proxyObjectIds = db.GetDBObjectIds(proxyObjectFilter);
  57.             ed.WriteMessage("including ProxyObject items count: {0};\n\n",
  58.                 proxyObjectIds.Length.ToString());
  59.  
  60.             Int64 newEntityCount = 0;
  61.             Int64 handOverTo_entity_count = 0;
  62.             Int64 handOverTo_object_count = 0;
  63.  
  64.             Db.ObjectId[] lockedLayerIds = ExtensionMethods.GetLockedLayerIds(
  65.                 proxyEntityIds);
  66.  
  67.             using (new LayerLockingSwitcher(lockedLayerIds)) {
  68.                 foreach (Db.ObjectId id in proxyEntityIds) {
  69.                     Boolean handOverTo_called = false;
  70.                     Db.ObjectId[] newEntityIds = ExtensionMethods
  71.                         .ExplodeProxyEntity(id, out handOverTo_called);
  72.                     newEntityCount += newEntityIds.Length;
  73.                     if (handOverTo_called)
  74.                         ++handOverTo_entity_count;
  75.                 }
  76.             }
  77.  
  78.             foreach (Db.ObjectId id in proxyObjectIds) {
  79.                 Boolean handOverTo_called = false;
  80.                 ExtensionMethods.RemoveDBObject(id, out handOverTo_called);
  81.                 if (handOverTo_called)
  82.                     ++handOverTo_object_count;
  83.             }
  84.  
  85.             ed.WriteMessage("All ProxyEntity items exploded.\nNew DBObjects " +
  86.                 "count: {0}.\n", newEntityCount.ToString());
  87.             ed.WriteMessage("All ProxyObject items removed.\n\n");
  88.  
  89.             ed.WriteMessage("Count of 'HandOverTo' operations for the " +
  90.                 "ProxyEntity items: {0}.\n", handOverTo_entity_count.ToString()
  91.                 );
  92.             ed.WriteMessage("Count of 'HandOverTo' operations for the " +
  93.                 "ProxyObject items: {0}.\n\n", handOverTo_object_count.ToString()
  94.                 );
  95.  
  96.             Db.ObjectId[] freeAnnotScaleIds = db.GetFreeAnnotativeScaleIds();
  97.  
  98.             ed.WriteMessage("Unused annotation scales count: {0}.\n",
  99.                 freeAnnotScaleIds.Length.ToString());
  100.  
  101.             db.RemoveFreeAnnotativeScales();
  102.             ed.WriteMessage("Unused annotation scales removed.\n\n");
  103.  
  104.             ids = db.GetDBObjectIds(n => !n.IsErased &&
  105.                 !n.IsEffectivelyErased);
  106.             ed.WriteMessage("DBObjects count after: {0}.\n\n", ids.Length
  107.                 .ToString());
  108.  
  109.             sw.Stop();
  110.             ed.WriteMessage("Ellapsed time [Hours:Minutes:Seconds:Milli" +
  111.                 "seconds]: {0}:{1}:{2}:{3}\n\n", sw.Elapsed.Hours.ToString(),
  112.                 sw.Elapsed.Minutes.ToString(), sw.Elapsed.Seconds.ToString(),
  113.                 sw.Elapsed.Milliseconds.ToString());
  114.  
  115.             ed.WriteMessage("Run the _AUDIT command with the _Y option, " +
  116.                 "please.\n\n", ids.Length.ToString());
  117.         }
  118.     }
  119. }

Консольный вывод тестовой команды выглядит следующим образом:
Цитировать
Command: test

DBObjects count before: 5547.
including ProxyEntity items count: 230;
including ProxyObject items count: 4591;

All ProxyEntity items exploded.
New DBObjects count: 3834.
All ProxyObject items removed.

Count of 'HandOverTo' operations for the ProxyEntity items: 0.
Count of 'HandOverTo' operations for the ProxyObject items: 131.

Unused annotation scales count: 24.
Unused annotation scales removed.

DBObjects count after: 4860.

Ellapsed time [Hours:Minutes:Seconds:Milliseconds]: 0:0:0:627

Run the _AUDIT command with the _Y option, please.

Теперь, пожалуй, можно начинать разбираться с тем, почему не бьётся сумма.
« Последнее редактирование: 20-11-2014, 14:40:20 от Андрей Бушман »

Оффлайн bender

  • ADN Club
  • **
  • Сообщений: 62
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #42 : 20-11-2014, 13:39:07 »
А почему при удалении прокси-объекта сразу не делать его подмену "пустышкой", без попыток удаления?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #43 : 20-11-2014, 13:46:41 »
А почему при удалении прокси-объекта сразу не делать его подмену "пустышкой", без попыток удаления?
Она не совсем пустышка и если делать много подмен (десятки/сотни тысяч), то база чертежа будет расти в памяти до того момента, пока чертеж не будет сохранён и открыт повторно. Я бы это делать не рекомендовал.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Оффлайн bender

  • ADN Club
  • **
  • Сообщений: 62
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #44 : 20-11-2014, 13:49:31 »
Понятно, спасибо.