REMOVEALLPROXY

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

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

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

  • ADN Club
  • Сообщений: 23
  • Карма: 4
REMOVEALLPROXY
« : 31-10-2014, 10:02:07 »
Добрый день. Скорее всего вопрос к Александру.
Хочу вызвать данную команду через acedCmdLookup но она требует параметр (Очистить список масштабов? [Да/Нет] <Да>: Д)
Как можно это обойти или только пересобирать библиотеку?
Спасибо.

Код - C# [Выбрать]
  1.         public delegate void AcRxFunctionPtr();
  2.  
  3.         [StructLayoutAttribute(LayoutKind.Sequential)]
  4.         public struct AcEdCommandStruc
  5.         {
  6.             public AcRxFunctionPtr fcnAddr;
  7.             public int flags;
  8.             public System.IntPtr app;
  9.             public System.IntPtr hResHandle;
  10.             public System.IntPtr cmd;
  11.         }
  12.  
  13.         [StructLayoutAttribute(LayoutKind.Sequential)]
  14.         public struct HINSTANCE__
  15.         {
  16.             public int unused;
  17.         }
  18.  
  19.         [DllImportAttribute("acad.exe", EntryPoint = "acedCmdLookup")]
  20.         public static extern int acedCmdLookup([InAttribute()][MarshalAsAttribute(UnmanagedType.LPWStr)] string cmdStr,
  21.             int globalLookup,
  22.             ref AcEdCommandStruc retStruc,
  23.             int skipUndef);
  24.  
  25.         public  static bool LookupCommand(string command)
  26.         {
  27.             AcEdCommandStruc cs = new AcEdCommandStruc();
  28.             int res = acedCmdLookup(command, 1, ref cs, 1);
  29.  
  30.             if (res != 0)
  31.                 cs.fcnAddr.Invoke();
  32.             else
  33.                 return false;
  34.  
  35.             return true;
  36.         }
  37.  
« Последнее редактирование: 31-10-2014, 14:48:27 от Александр Ривилис »

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #1 : 31-10-2014, 15:02:42 »
Приветствую на форуме!
Хочу вызвать данную команду через acedCmdLookup
Зачем? Есть куча других способов для этого. Кстати, команда _REMOVEALLPROXY - модальная, работающая только с текущим/активным чертежом, по этой причине не блокирует его и соответственно прямым вызовом может вызываться только из определенных контекстов.
Почему не вызвать её через Editor.RunCommand (или P/Invoke acedCmd) в версиях до 2014 и Editor.Command в версиях начиная с 2015?
Самый же радикальный способ переписать её с чистого ObjectARX на AutoCAD .NET API, что вполне возможно. Если хочешь, я выложу исходник на C++ и дам комментарии как его переделать на C#. Там со всеми обработками ошибок около сотни строк. Ну и если ты обязуешься выложить соответствующий исходник на C#. :) 
« Последнее редактирование: 31-10-2014, 16:05:39 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • Сообщений: 23
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #2 : 31-10-2014, 15:59:02 »
Цитировать
Есть куча других способов для этого?
Возможно :)

Ее конкретно возможно и можно но есть другие команды которые я не могу использовать через RunCommand так как он не ждет окончания, acedCmd не работает с CommandFlags.Session
Если переводить на .Net тогда и EXPLODEALLPROXY нужно.
А перевести можно и исходники выложить. Буду ждать. Спасибо.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #3 : 31-10-2014, 18:33:40 »
но есть другие команды которые я не могу использовать через RunCommand так как он не ждет окончания
Ждет. Ты путаешь RunCommand с SendCommand. RunCommand - это непубличный метод класса Editor, который нужно вызвать хитрым способом.
Код - C# [Выбрать]
  1. // (c) 2013  Tony Tanzillo
  2. public static class EditorInputExtensionMethods
  3. {
  4.    public static PromptStatus Command( this Editor editor, params object[] args )
  5.    {
  6.       if( editor == null )
  7.          throw new ArgumentNullException( "editor" );
  8.       return runCommand( editor, args );
  9.    }
  10.  
  11.    static Func<Editor, object[], PromptStatus> runCommand = GenerateRunCommand();
  12.  
  13.    static Func<Editor, object[], PromptStatus> GenerateRunCommand()
  14.    {
  15.       MethodInfo method = typeof( Editor ).GetMethod( "RunCommand",
  16.          BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public );
  17.       var instance = Expression.Parameter( typeof( Editor ), "instance" );
  18.       var args = Expression.Parameter( typeof( object[] ), "args" );
  19.       return Expression.Lambda<Func<Editor, object[], PromptStatus>>(
  20.          Expression.Call( instance, method, args ), instance, args )
  21.             .Compile();
  22.    }
  23. }
  24. // Пример использования:
  25. //  var doc = Application.DocumentManager.MdiActiveDocument;
  26. //  var ed = doc.Editor;
  27. //  ed.Command("_REMOVEALLPROXY","_Y");

acedCmd не работает с CommandFlags.Session
Мне не очень понятно зачем тебе запускать команду из контекста приложения. Но если даже это и нужно, то делается это просто: делаешь фиктивную команду с флагом Modal, которую запускаешь из контекста приложения через AcadDocument.SendCommand или Document.SendStringToExecute. А все остальные действия выполняешь именно в этой команде.


« Последнее редактирование: 05-11-2014, 12:55:04 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #4 : 31-10-2014, 18:41:49 »
А перевести можно и исходники выложить. Буду ждать. Спасибо.
Код - C++ [Выбрать]
  1. typedef void __cdecl ACEDRESETSCALELIST(bool,bool,class AcDbDatabase *);
  2. static void RemoveAllProxy(void)
  3. {
  4.   Acad::ErrorStatus es;
  5.   AcDbDatabase *pDb = acdbCurDwg(); // Текущая база
  6.   AcDbHandle firstHandle = pDb->blockTableId().handle(); // Первая метка объекта - метка таблицы блоков
  7.   AcDbHandle lastHandle = pDb->handseed(); // Следующая после последней метки
  8.   int nObjects = pDb->approxNumObjects(); // Приблизительное количество объектов в базе
  9.   ACHAR buf[256],buf1[256]; lastHandle.getIntoAsciiBuffer(buf);
  10.   __int64 iLast = 0; swscanf(buf,_T("%I64x"),&iLast);
  11.   firstHandle.getIntoAsciiBuffer(buf1);
  12.   __int64 iFirst = 0; swscanf(buf1,_T("%I64x"),&iFirst);
  13.   __int64 nProxyTotal = 0, nProxyEntityTotal = 0;
  14.   acutPrintf(_T("\nПервая метка объекта: <%s>, последняя метка объекта: <%s>"),buf1,buf);
  15.   AcDbObjectIdArray ids;
  16.   // Массив меток заблокированных слоёв - их придётся временно разблокировать
  17.   AcDbObjectIdArray idsLockedLayers;
  18.  
  19.  for (__int64 i = iFirst; i < iLast && nObjects > 0; i++) {
  20.     AcDbHandle h(i);
  21.     AcDbObjectId id = AcDbObjectId::kNull;
  22.     if ((es = pDb->getAcDbObjectId(id,false,h)) == Acad::eOk) { // Получаем ObjectId по Handle
  23.       AcDbObjectPointer<AcDbObject> pObj(id,AcDb::kForRead);
  24.       if (pObj.openStatus() == Acad::eOk && pObj->isAProxy()) {
  25.         nProxyTotal++;
  26.         ids.append(id);
  27.         AcDbEntity *pEnt = AcDbEntity::cast(pObj.object());
  28.         if (pEnt) {
  29.           nProxyEntityTotal++;
  30.           AcDbObjectId idLayer = pEnt->layerId();
  31.           if (!idsLockedLayers.contains(idLayer)) {
  32.             AcDbLayerTableRecordPointer pLayer(idLayer,AcDb::kForWrite);
  33.             if (pLayer.openStatus() == Acad::eOk) {
  34.               if (pLayer->isLocked()) {
  35.                 pLayer->setIsLocked(false);
  36.                 idsLockedLayers.append(idLayer);
  37.               }
  38.             }
  39.           }
  40.         }
  41.       }
  42.       nObjects--;
  43.     }
  44.   }
  45.  
  46.  wsprintf(buf,_T("\nВсего найдено proxy-объектов: %I64d. Из них proxy-примитивов: %I64d."),nProxyTotal,nProxyEntityTotal); acutPrintf(_T("%s"),buf);
  47.  
  48.  ACEDRESETSCALELIST *acedResetScaleList = NULL;
  49.  HMODULE hAcad = LoadLibraryA("accore.dll");
  50.  if (!hAcad) hAcad = LoadLibraryA("acad.exe");
  51.  
  52.  if (hAcad != NULL) {
  53.  #ifdef _WIN64
  54.    acedResetScaleList = (ACEDRESETSCALELIST *)GetProcAddress(hAcad,"?acedResetScaleList@@YAX_N0PEAVAcDbDatabase@@@Z");
  55.  #else // _WIN64
  56.    acedResetScaleList = (ACEDRESETSCALELIST *)GetProcAddress(hAcad,"?acedResetScaleList@@YAX_N0PAVAcDbDatabase@@@Z");
  57.  #endif
  58.    if (acedResetScaleList) {
  59.      ACHAR res[256];
  60.      acedInitGet(0,_T("Да Нет Yes No _ Yes No Yes No"));
  61.      int rc = acedGetKword(_T("\nОчистить список масштабов? [Да/Нет] <Да>: "),res);
  62.      if (rc == RTNONE || (rc == RTNORM && !wcsicmp(res,_T("Yes")))) {
  63.        acedResetScaleList(true,false,acdbCurDwg());
  64.      }
  65.    }
  66.    FreeLibrary(hAcad);
  67.  }
  68.  
  69.   int nProxyDeleted = 0;
  70.   int nProxyEntityDeleted = 0;
  71.   for (int j=0; j < ids.length(); j++) {
  72.     AcDbObjectPointer<AcDbObject> pObj(ids[j],AcDb::kForWrite);
  73.     if (pObj.openStatus() == Acad::eOk) {
  74.       if (pObj->erase(true) == Acad::eOk) {
  75.         nProxyDeleted++;
  76.         if (AcDbEntity::cast(pObj.object())) {
  77.           nProxyEntityDeleted++;
  78.         }
  79.       } else {
  80.         AcDbObject *ppObj; pObj.release(ppObj);
  81.         if (AcDbEntity::cast(ppObj)) {
  82.           AcDbLine *pRep = new AcDbLine();
  83.           if (ppObj->handOverTo(pRep,false,false) == Acad::eObjectToBeDeleted) {
  84.             pRep->erase(); pRep->close();
  85.             delete ppObj;
  86.             nProxyDeleted++;
  87.             nProxyEntityDeleted++;
  88.           } else {
  89.             delete pRep;
  90.           }
  91.         } else {
  92.           AcDbDictionary *pRep = new AcDbDictionary();
  93.           if (ppObj->handOverTo(pRep,false,false) == Acad::eObjectToBeDeleted) {
  94.             pRep->erase(); pRep->close();
  95.             delete ppObj;
  96.             nProxyDeleted++;
  97.           } else {
  98.             delete pRep;
  99.           }
  100.         }
  101.       }
  102.     }
  103.   }
  104.  
  105.   for (int i = 0; i < idsLockedLayers.length(); i++)  {
  106.     AcDbLayerTableRecordPointer pLayer(idsLockedLayers[i],AcDb::kForWrite);
  107.     if (pLayer.openStatus() == Acad::eOk) {
  108.       pLayer->setIsLocked(true);
  109.     }
  110.   }
  111.   acutPrintf(_T("\nВсего удалено proxy-объектов: %d. Из них proxy-примитивов: %d."),nProxyDeleted,nProxyEntityDeleted);
  112.   acutPrintf(_T("\nДля проверки ошибок выполните команду _AUDIT"));
  113. }
« Последнее редактирование: 06-11-2014, 01:23:11 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #5 : 31-10-2014, 18:55:52 »
Код - C++ [Выбрать]
  1. enum ExplodeStatus {
  2.   success   =  0,
  3.   parmerr   = -1,
  4.   openerr   = -2,
  5.   explerr   = -3,
  6.   appenderr = -4,
  7.   eraseerr  = -5
  8. };
  9. static int ExplodeProxyInBTR(AcDbObjectId blkId, long &proxy, long &exploded);
  10. static void ExplodeAllProxy(void)
  11. {
  12.   AcDbObjectIdArray idsLockedLayers;
  13.   {
  14.     AcDbLayerTablePointer pTblBlk(acdbCurDwg()->layerTableId(),AcDb::kForRead);
  15.     AcDbLayerTableIterator *pIter = NULL;
  16.     if (pTblBlk->newIterator(pIter) == Acad::eOk && pIter) {
  17.       for (pIter->start(); !pIter->done(); pIter->step()) {
  18.         AcDbObjectId layId;
  19.         if (pIter->getRecordId(layId) == Acad::eOk) {
  20.           AcDbLayerTableRecordPointer pLayer(layId,AcDb::kForWrite);
  21.           if (pLayer.openStatus() == Acad::eOk) {
  22.             if (pLayer->isLocked()) {
  23.               pLayer->setIsLocked(false);
  24.               idsLockedLayers.append(layId);
  25.             }
  26.           }
  27.         }
  28.       }
  29.       delete pIter;
  30.     }
  31.   }
  32.  
  33.   AcDbBlockTablePointer pTblBlk(acdbCurDwg()->blockTableId(),AcDb::kForRead);
  34.   if (pTblBlk.openStatus() == Acad::eOk) {
  35.     AcDbBlockTableIterator *pIter = NULL;
  36.     if (pTblBlk->newIterator(pIter) == Acad::eOk && pIter) {
  37.       AcDbObjectIdArray blkIds;
  38.       for (pIter->start(); !pIter->done(); pIter->step()) {
  39.         AcDbObjectId blkId;
  40.         if (pIter->getRecordId(blkId) == Acad::eOk) {
  41.           blkIds.append(blkId);
  42.         }
  43.       }
  44.       delete pIter;
  45.       pTblBlk->close();
  46.       long exploded = 0, proxy = 0;
  47.       for (int i=0; i < blkIds.length(); i++) {
  48.         if (ExplodeProxyInBTR(blkIds[i],proxy,exploded) != success) {
  49.           acutPrintf(_T("\nОшибка расчленения ACAD_PROXY_ENTITY!"));
  50.         }
  51.       }
  52.       acutPrintf(_T("\nУдалено Proxy: %d Новых объектов: %d"), proxy, exploded);
  53.     } else {
  54.       acutPrintf(_T("\nНе могу создать итератор для таблицы блоков!"));
  55.     }
  56.   } else {
  57.     acutPrintf(_T("\nНе могу открыть таблицу блоков!"));
  58.   }
  59.   {
  60.     for (int i = 0; i < idsLockedLayers.length(); i++) {
  61.       AcDbLayerTableRecordPointer pLayer(idsLockedLayers[i],AcDb::kForWrite);
  62.       if (pLayer.openStatus() == Acad::eOk) {
  63.         pLayer->setIsLocked(true);
  64.       }
  65.     }
  66.   }
  67. }
  68. static int ExplodeProxyInBTR(AcDbObjectId blkId, long &proxy, long &exploded)
  69. {
  70.   Acad::ErrorStatus es = Acad::eOk;
  71.   AcDbBlockTableRecordIterator *pBlkIter = NULL;
  72.  
  73.   // Массив в который добавляются расчлененные proxy
  74.   AcDbVoidPtrArray aExplProxy;
  75.  
  76.   if (!blkId.isNull()) {
  77.     AcDbBlockTableRecordPointer pBtr(blkId,AcDb::kForRead);
  78.     if (pBtr.openStatus() != Acad::eOk) {
  79.       return openerr;
  80.     }
  81.     if (pBtr->newIterator(pBlkIter) != Acad::eOk || !pBlkIter) {
  82.       return openerr;
  83.     }
  84.  
  85.     for (pBlkIter->start(); !pBlkIter->done(); pBlkIter->step()) {
  86.       AcDbEntity *pEnt = NULL;
  87.       if (pBlkIter->getEntity(pEnt,AcDb::kForWrite) == Acad::eOk && pEnt) {
  88.         AcDbProxyEntity *pProxy = AcDbProxyEntity::cast(pEnt);
  89.         if (pProxy && (pProxy->graphicsMetafileType() == AcDbProxyEntity::kFullGraphics ||
  90.                        pProxy->graphicsMetafileType() == AcDbProxyEntity::kBoundingBox)) {
  91.           if (pProxy->graphicsMetafileType() == AcDbProxyEntity::kFullGraphics) {
  92.             pProxy->explode(aExplProxy);
  93.             proxy++;
  94.             if (pProxy->erase() != Acad::eOk) {
  95.               AcDbLine *pLine = new AcDbLine();
  96.               if (pProxy->handOverTo(pLine,false,false) == Acad::eObjectToBeDeleted) {
  97.                 pLine->erase(); pLine->close();
  98.                 delete pProxy;
  99.                 continue;
  100.               }
  101.             }
  102.           } else {
  103.             AcDbExtents ext;
  104.             if (pProxy->getGeomExtents(ext) == Acad::eOk) {
  105.               AcGePoint3dArray arr;
  106.               arr.append(ext.minPoint());
  107.               arr.append(AcGePoint3d(ext.minPoint().x,ext.maxPoint().y,ext.minPoint().z));
  108.               arr.append(AcGePoint3d(ext.maxPoint().x,ext.maxPoint().y,ext.minPoint().z));
  109.               arr.append(AcGePoint3d(ext.maxPoint().x,ext.minPoint().y,ext.minPoint().z));
  110.               AcDb3dPolyline *pPline = new AcDb3dPolyline(AcDb::k3dSimplePoly,arr,Adesk::kTrue);
  111.               aExplProxy.append(pPline);
  112.               pPline->setLayer(pProxy->layerId());
  113.               pPline->setLinetype(pProxy->linetypeId());
  114.               pPline->setColor(pProxy->color());
  115.             }
  116.             proxy++;
  117.             if (pProxy->erase() != Acad::eOk) {
  118.               AcDbLine *pLine = new AcDbLine();
  119.               if (pProxy->handOverTo(pLine,false,false) == Acad::eObjectToBeDeleted) {
  120.                 pLine->erase(); pLine->close();
  121.                 delete pProxy;
  122.                 continue;
  123.               }
  124.             }
  125.           }
  126.         }
  127.         pEnt->close();
  128.       }
  129.     }
  130.     exploded += aExplProxy.length();
  131.     delete pBlkIter;
  132.     AcDbObjectIdArray idsRef;
  133.     pBtr->getBlockReferenceIds(idsRef);
  134.  
  135.     if (aExplProxy.length() > 0) {
  136.       es = pBtr->upgradeOpen();
  137.       if (es == Acad::eOk || es == Acad::eWasOpenForWrite) {
  138.         for (int i=0; i < aExplProxy.length(); i++) {
  139.           AcDbEntity *pEnt = static_cast<AcDbEntity *>(aExplProxy[i]);
  140.           if (pEnt) {
  141.             Acad::ErrorStatus es_curr;
  142.             es_curr = pBtr->appendAcDbEntity(pEnt);
  143.             if (es_curr != Acad::eOk) {
  144.               delete (AcDbEntity *)aExplProxy[i];
  145.             } else {
  146.               pEnt->close();
  147.             }
  148.           }
  149.         }
  150.       }
  151.  
  152.       pBtr->close();
  153.  
  154.       for (int i=0; i < idsRef.length(); i++) {
  155.         AcDbObjectPointer<AcDbBlockReference> pRef(idsRef[i],AcDb::kForWrite);
  156.         if (pRef.openStatus() == Acad::eOk) {
  157.           pRef->recordGraphicsModified();
  158.         }
  159.       }
  160.     }
  161.     return success;
  162.   } else {
  163.     return openerr;
  164.   }
  165. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • Сообщений: 23
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #6 : 05-11-2014, 14:45:08 »
Код - C# [Выбрать]
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5.  
  6. #if CORE
  7. using AcAp = Autodesk.AutoCAD.ApplicationServices.Core;
  8. #else
  9. using AcAp = Autodesk.AutoCAD.ApplicationServices;
  10. #endif
  11. using AcDb = Autodesk.AutoCAD.DatabaseServices;
  12. using AcEd = Autodesk.AutoCAD.EditorInput;
  13. using AcGe = Autodesk.AutoCAD.Geometry;
  14. using Autodesk.AutoCAD.DatabaseServices;
  15. using Autodesk.AutoCAD.Geometry;
  16.  
  17. namespace ImplementLink
  18. {
  19.     public static class Acad
  20.     {
  21.         #region Static Properties
  22.  
  23.         public static Autodesk.AutoCAD.ApplicationServices.Document Document
  24.         {
  25.             get { return AcAp.Application.DocumentManager.MdiActiveDocument; }
  26.         }
  27.  
  28.         public static AcDb.Database Database
  29.         {
  30.             get { return AcAp.Application.DocumentManager.MdiActiveDocument.Database; }
  31.         }
  32.  
  33.         public static AcEd.Editor Editor
  34.         {
  35.             get { return AcAp.Application.DocumentManager.MdiActiveDocument.Editor; }
  36.         }
  37.  
  38.         public static AcDb.TransactionManager TransactionManager
  39.         {
  40.             get { return AcAp.Application.DocumentManager.MdiActiveDocument.TransactionManager; }
  41.         }
  42.  
  43.         #endregion
  44.  
  45.         #region Transactional Methods
  46.  
  47.         public static T Read<T>(this AcDb.ObjectId objectId, bool openErased = false, bool forceOpenOnLockedLayer = true)
  48.             where T : AcDb.DBObject
  49.         {
  50.             return objectId.GetObject(AcDb.OpenMode.ForRead, openErased, forceOpenOnLockedLayer) as T;
  51.         }
  52.  
  53.         public static T Write<T>(this AcDb.ObjectId objectId, bool openErased = false, bool forceOpenOnLockedLayer = true)
  54.             where T : AcDb.DBObject
  55.         {
  56.             return objectId.GetObject(AcDb.OpenMode.ForWrite, openErased, forceOpenOnLockedLayer) as T;
  57.         }
  58.  
  59.         #endregion
  60.     }
  61. }
  62.  

Код - C# [Выбрать]
  1. #if CORE
  2.         public const string ACAD = "accore.dll";
  3.         public const string ACDB = "acdb19.dll";
  4. #else
  5.         public const string ACAD = "acad.exe";
  6.         public const string ACDB = "acdb18.dll";
  7. #endif
  8.  
  9. #if WIN32
  10.         [DllImport(ACAD, CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acedResetScaleList@@YAX_N0PAVAcDbDatabase@@@Z")]
  11.         public static extern void acedResetScaleList(bool b1, bool b2, IntPtr db);
  12. #else
  13.         [DllImport(ACAD, CallingConvention = CallingConvention.Cdecl, EntryPoint = "?acedResetScaleList@@YAX_N0PEAVAcDbDatabase@@@Z")]
  14.         public static extern void acedResetScaleList(bool b1, bool b2, IntPtr db);
  15. #endif
  16.  
  17.         private static int PurgeDatabase(Database db)
  18.         {
  19.             int idCount = 0;
  20.             using (Autodesk.AutoCAD.ApplicationServices.Application.DocumentManager.MdiActiveDocument.LockDocument())
  21.             using (var tr = Acad.Database.TransactionManager.StartTransaction())
  22.             {
  23.                 ObjectIdCollection idsToPurge = new ObjectIdCollection();
  24.                 RegAppTable rat = (RegAppTable)tr.GetObject(db.RegAppTableId, OpenMode.ForRead);
  25.  
  26.                 foreach (ObjectId raId in rat)
  27.                 {
  28.                     if (raId.IsValid)
  29.                     {
  30.                         idsToPurge.Add(raId);
  31.                     }
  32.                 }
  33.  
  34.                 db.Purge(idsToPurge);
  35.  
  36.                 foreach (ObjectId id in idsToPurge)
  37.                 {
  38.                     DBObject obj = tr.GetObject(id, OpenMode.ForWrite);
  39.                     obj.Erase();
  40.                 }
  41.  
  42.                 idCount = idsToPurge.Count;
  43.                 tr.Commit();
  44.             }
  45.             return idCount;
  46.         }
  47.  

Код - C# [Выбрать]
  1.         [CommandMethod("REMOVEALLPROXY", CommandFlags.Modal)]
  2.         public static void RemoveAllProxy()
  3.         {
  4.             Database db = Acad.Database;                  // Текущая база
  5.             Handle firstHandle = db.BlockTableId.Handle;  // Первая метка объекта - метка таблицы блоков
  6.             Handle lastHandle = db.Handseed;              // Следующая после последней метки
  7.             int nObjects = db.ApproxNumObjects;           // Приблизительное количество объектов в базе
  8.  
  9.             string bufferLast = lastHandle.ToString();
  10.             string bufferFirst = firstHandle.ToString();
  11.             Int64 iLast = Int64.Parse(bufferLast, System.Globalization.NumberStyles.HexNumber);
  12.             Int64 iFirst = Int64.Parse(bufferFirst, System.Globalization.NumberStyles.HexNumber); ;
  13.  
  14.             Acad.Editor.WriteMessage(
  15.                 string.Format("\nПервая метка объекта: <{0}>, последняя метка объекта: <{1}>",
  16.                 bufferFirst,
  17.                 bufferLast));
  18.  
  19.             Int64 nProxyTotal = 0;
  20.             Int64 nProxyEntityTotal = 0;
  21.             ObjectIdCollection ids = new ObjectIdCollection();
  22.             // Массив меток заблокированных слоёв - их придётся временно разблокировать
  23.             ObjectIdCollection idsLockedLayers = new ObjectIdCollection();
  24.  
  25.             using (AcAp.Application.DocumentManager.MdiActiveDocument.LockDocument())
  26.             using (var tr = Acad.TransactionManager.StartTransaction())
  27.             {
  28.                 LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
  29.  
  30.                 for (Int64 i = iFirst; i < iLast && nObjects > 0; i++)
  31.                 {
  32.                     Handle h = new Handle(i);
  33.                     ObjectId id = ObjectId.Null;
  34.                     if (db.TryGetObjectId(h, out id))
  35.                     {
  36.                         try
  37.                         {
  38.                             DBObject dbObj = tr.GetObject(id, OpenMode.ForRead, true, true);
  39.                             if (dbObj != null && !dbObj.IsErased && dbObj.IsAProxy)
  40.                             {
  41.                                 nProxyTotal++;
  42.                                 ids.Add(id);
  43.                                 Entity entity = dbObj as Entity;
  44.                                 if (entity != null && entity.IsAProxy)
  45.                                 {
  46.                                     nProxyEntityTotal++;
  47.                                     ObjectId idLayer = entity.LayerId;
  48.                                     if (!idsLockedLayers.Contains(idLayer))
  49.                                     {
  50.                                         LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(idLayer, OpenMode.ForRead);
  51.                                         if (ltr.IsLocked)
  52.                                         {
  53.                                             ltr.IsLocked = false;
  54.                                             idsLockedLayers.Add(idLayer);
  55.                                         }
  56.                                     }
  57.                                 }
  58.                             }
  59.                             nObjects--;
  60.                         }
  61.                         catch { }
  62.                     }
  63.                 }
  64.  
  65.                 tr.Commit();
  66.  
  67.             }
  68.  
  69.             Acad.Editor.WriteMessage(string.Format("\nВсего найдено proxy-объектов: {0}. Из них proxy-примитивов: {1}.",
  70.                 nProxyTotal,
  71.                 nProxyEntityTotal));
  72.  
  73.             PromptKeywordOptions pko = new PromptKeywordOptions("\nОчистить список масштабов? ");
  74.             pko.Keywords.Add("Yes", "Д", "Да", true, true);
  75.             pko.Keywords.Add("No", "Н", "Нет", true, true);
  76.             pko.Keywords.Default = "Yes";
  77.             PromptResult pr = Acad.Editor.GetKeywords(pko);
  78.             if (pr.Status == PromptStatus.OK && pr.StringResult == "Yes")
  79.             {
  80.                 acedResetScaleList(false, true, db.UnmanagedObject);
  81.             }
  82.  
  83.             int nProxyDeleted = 0;
  84.             int nProxyEntityDeleted = 0;
  85.  
  86.             using (AcAp.Application.DocumentManager.MdiActiveDocument.LockDocument())
  87.             {
  88.                 for (int j = 0; j < ids.Count; j++)
  89.                 {
  90.  
  91.                     using (DBObject dbObj = ids[j].Open(OpenMode.ForWrite, false))
  92.                     {
  93.                         try
  94.                         {
  95.                             dbObj.Erase(true);
  96.                             if (dbObj.IsErased)
  97.                             {
  98.                                 nProxyDeleted++;
  99.                                 Entity entity = dbObj as Entity;
  100.                                 if (entity != null)
  101.                                 {
  102.                                     nProxyEntityDeleted++;
  103.                                 }
  104.                             }
  105.                         }
  106.                         catch
  107.                         {
  108.                             Entity entity = dbObj as Entity;
  109.                             DBObject tmpObj = null;
  110.                             if (entity != null)
  111.                             {
  112.                                 tmpObj = new Line();
  113.                             }
  114.                             else
  115.                             {
  116.                                 tmpObj = new DBDictionary();
  117.                             }
  118.                             dbObj.HandOverTo(tmpObj, false, false);
  119.                             nProxyDeleted++;
  120.                             tmpObj.Erase(true);
  121.                             tmpObj.Close();
  122.                             tmpObj.Dispose();
  123.                         }
  124.                     }
  125.                 }
  126.  
  127.                 using (var tr = Acad.TransactionManager.StartTransaction())
  128.                 {
  129.                     LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
  130.                     for (int i = 0; i < idsLockedLayers.Count; i++)
  131.                     {
  132.                         LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(idsLockedLayers[i], OpenMode.ForWrite);
  133.                         ltr.IsLocked = true;
  134.                     }
  135.  
  136.                     tr.Commit();
  137.                 }
  138.  
  139.                 idsLockedLayers.Dispose();
  140.  
  141.                 Acad.Editor.WriteMessage(
  142.                     string.Format("\nВсего удалено proxy-объектов: {0}. Из них proxy-примитивов: {1}.",
  143.                     nProxyDeleted,
  144.                     nProxyEntityDeleted));
  145.             }
  146.  
  147.             Autodesk.AutoCAD.Interop.AcadApplication app = (Autodesk.AutoCAD.Interop.AcadApplication)AcAp.Application.AcadApplication;
  148.             app.ActiveDocument.AuditInfo(true);
  149.             PurgeDatabase(db);
  150.         }
  151.  

Код - C# [Выбрать]
  1.         [CommandMethod("EXPLODEALLPROXY", CommandFlags.Modal)]
  2.         public static void ExplodeAllProxy()
  3.         {
  4.             Database db = Acad.Database;
  5.             ObjectIdCollection idsLockedLayers = new ObjectIdCollection();
  6.  
  7.             using (AcAp.Application.DocumentManager.MdiActiveDocument.LockDocument())
  8.             {
  9.                 using (var tr = Acad.TransactionManager.StartTransaction())
  10.                 {
  11.                     LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
  12.  
  13.                     foreach (var layerId in lt)
  14.                     {
  15.                         LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(layerId, OpenMode.ForWrite);
  16.                         if (ltr.IsLocked)
  17.                         {
  18.                             ltr.IsLocked = false;
  19.                             idsLockedLayers.Add(layerId);
  20.                         }
  21.                     }
  22.  
  23.                     tr.Commit();
  24.                 }
  25.  
  26.                 long exploded = 0;
  27.                 long proxy = 0;
  28.                 ObjectIdCollection ids = new ObjectIdCollection();
  29.                 using (var tr = Acad.TransactionManager.StartTransaction())
  30.                 {
  31.                     BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);
  32.                     ids = new ObjectIdCollection(bt.OfType<ObjectId>().ToArray());
  33.  
  34.                     bt.Close();
  35.                 }
  36.  
  37.                 foreach (ObjectId currentId in ids)
  38.                 {
  39.                     if (!ExplodeProxyInBTR(currentId, ref proxy, ref exploded))
  40.                     {
  41.                         Acad.Editor.WriteMessage(
  42.                             string.Format("\nОшибка расчленения ACAD_PROXY_ENTITY!",
  43.                             currentId));
  44.                     }
  45.                 }
  46.  
  47.                 Acad.Editor.WriteMessage(string.Format("\nУдалено Proxy: {0} Новых объектов: {1}", proxy, exploded));
  48.  
  49.  
  50.                 using (var tr = Acad.TransactionManager.StartTransaction())
  51.                 {
  52.                     LayerTable lt = (LayerTable)tr.GetObject(db.LayerTableId, OpenMode.ForRead);
  53.                     for (int i = 0; i < idsLockedLayers.Count; i++)
  54.                     {
  55.                         LayerTableRecord ltr = (LayerTableRecord)tr.GetObject(idsLockedLayers[i], OpenMode.ForWrite);
  56.                         ltr.IsLocked = true;
  57.                     }
  58.  
  59.                     tr.Commit();
  60.                 }
  61.             }
  62.         }
  63.  
  64.         public static bool ExplodeProxyInBTR(ObjectId blkId, ref long proxy, ref long exploded)
  65.         {
  66.             if (blkId == ObjectId.Null)
  67.             {
  68.                 return false;
  69.             }
  70.  
  71.             DBObjectCollection aExplProxy = new DBObjectCollection();
  72.             ObjectIdCollection proxyEntities = new ObjectIdCollection();
  73.  
  74.             using (var tr = Acad.TransactionManager.StartTransaction())
  75.             {
  76.                 using (BlockTableRecord btr = (BlockTableRecord)tr.GetObject(blkId, OpenMode.ForRead))
  77.                 {
  78.                     foreach (var item in btr)
  79.                     {
  80.                         ProxyEntity proxyEntity = tr.GetObject(item, OpenMode.ForWrite) as ProxyEntity;
  81.                         if (proxyEntity != null)
  82.                         {
  83.                             proxyEntities.Add(item);
  84.                             proxyEntity.Close();
  85.                             System.Diagnostics.Debug.WriteLine(item.ObjectClass.Name);
  86.                         }
  87.                     }
  88.                 }
  89.             }
  90.  
  91.             for (int i = 0; i < proxyEntities.Count; i++)
  92.             {
  93.                 ProxyEntity proxyEntity = proxyEntities[i].Open(OpenMode.ForWrite, false, false) as ProxyEntity;
  94.                 switch (proxyEntity.GraphicsMetafileType)
  95.                 {
  96.                     case GraphicsMetafileType.BoundingBox:
  97.                         {
  98.                             Extents3d ext = proxyEntity.GeometricExtents;
  99.                             if (ext != null)
  100.                             {
  101.                                 Point3dCollection arr = new Point3dCollection();
  102.                                 arr.Add(ext.MinPoint);
  103.                                 arr.Add(new Point3d(ext.MinPoint.X, ext.MaxPoint.Y, ext.MinPoint.Z));
  104.                                 arr.Add(new Point3d(ext.MaxPoint.X, ext.MaxPoint.Y, ext.MinPoint.Z));
  105.                                 arr.Add(new Point3d(ext.MaxPoint.X, ext.MinPoint.Y, ext.MinPoint.Z));
  106.  
  107.                                 Polyline3d pLine = new Polyline3d(Poly3dType.SimplePoly, arr, true);
  108.                                 pLine.LayerId = proxyEntity.LayerId;
  109.                                 pLine.LinetypeId = proxyEntity.LinetypeId;
  110.                                 pLine.Color = proxyEntity.Color;
  111.  
  112.                                 aExplProxy.Add(pLine);
  113.                             }
  114.  
  115.                             proxy++;
  116.                             proxyEntity.Erase(true);
  117.  
  118.                             Line line = new Line();
  119.                             proxyEntity.HandOverTo(line, false, false);
  120.                             line.Dispose();
  121.                         }
  122.                         break;
  123.                     case GraphicsMetafileType.FullGraphics:
  124.                         {
  125.                             proxyEntity.Explode(aExplProxy);
  126.                             if (aExplProxy.Count > 0)
  127.                             {
  128.                                 try
  129.                                 {
  130.                                     proxy++;
  131.                                     proxyEntity.Erase(true);
  132.  
  133.                                     Line line = new Line();
  134.                                     proxyEntity.HandOverTo(line, false, false);
  135.                                     line.Dispose();
  136.                                 }
  137.                                 catch{}
  138.                             }
  139.                             else
  140.                             {
  141.                                 //System.Diagnostics.Debug.WriteLine(proxyEntity.ObjectId.ToString());
  142.                             }
  143.                         }
  144.                         break;
  145.                     case GraphicsMetafileType.NoMetafile:
  146.                         break;
  147.                     default:
  148.                         break;
  149.                 }
  150.  
  151.                 proxyEntity.Dispose();
  152.             }
  153.             proxyEntities.Dispose();
  154.  
  155.             using (var tr = Acad.TransactionManager.StartTransaction())
  156.             {
  157.                 using (BlockTableRecord btr = (BlockTableRecord)tr.GetObject(blkId, OpenMode.ForRead))
  158.                 {
  159.                     exploded += aExplProxy.Count;
  160.                     ObjectIdCollection idsRef = btr.GetBlockReferenceIds(true, true);
  161.  
  162.                     if (aExplProxy.Count > 0)
  163.                     {
  164.                         for (int i = 0; i < aExplProxy.Count; i++)
  165.                         {
  166.                             btr.UpgradeOpen();
  167.                             Entity entity = aExplProxy[i] as Entity;
  168.                             btr.AppendEntity(entity);
  169.                             tr.AddNewlyCreatedDBObject(entity, true);
  170.                             entity.Close();
  171.                         }
  172.                     }
  173.  
  174.                     for (int i = 0; i < idsRef.Count; i++)
  175.                     {
  176.                         BlockReference br = (BlockReference)tr.GetObject(idsRef[i], OpenMode.ForWrite);
  177.                         br.RecordGraphicsModified(true);
  178.                         br.Close();
  179.                     }
  180.  
  181.                     idsRef.Dispose();
  182.                     btr.Close();
  183.                 }
  184.             }
  185.  
  186.             aExplProxy.Dispose();
  187.  
  188.             return true;
  189.         }
  190.  
« Последнее редактирование: 21-11-2014, 12:19:40 от T72 »

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #7 : 05-11-2014, 18:54:59 »
Несколько замечаний по коду. Строка 93 третьей части кода:
Код - C# [Выбрать]
  1. DBObject dbObj = ids[j].Open(OpenMode.ForWrite, false);
Ты открываешь это объект, но нигде не закрываешь его. Если dbObj.Erase(true) выполнилось успешно, то нужно вызвать dbObj.Close(). Если возникло исключение и мы пользуемся для удаления
Код - C# [Выбрать]
  1. dbObj.HandOverTo(tmpObj, false, false);
то нужно выполнить dbObj.Dispose() и tmpObj.Close()
Поэтому (я не тестировал код) лучше использовать конструкцию:
Код - C# [Выбрать]
  1. using (DBObject dbObj = ids[j].Open(OpenMode.ForWrite, false))
  2. {
  3. }
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #8 : 05-11-2014, 22:28:10 »
Еще одно замечание. Можно конечно использовать и условную компиляцию, т.е. в зависимости от версии и в зависимости от разрядности AutoCAD компилировать отдельные dll-файлы. А можно проверить и то и другое динамически и динамически вызвать нужную функцию. Тогда в отличие от arx-файла, который всегда нужно делать для каждой разрядности AutoCAD, можно сделать (в 95% случаев) dll-файл независящий от разрядности AutoCAD.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #9 : 06-11-2014, 01:21:18 »
T72, ну и спасибо тебе за то, что навёл меня на баг в моей версии. В версиях начиная с 2013 список масштабов в команде REMOVEALLPROXY не чистился. Причина банальная - перенос функции acedResetScaleList в accore.dll. Подправил свои исходники и выложил исправленные arx-файлы.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • Сообщений: 23
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #10 : 06-11-2014, 07:52:59 »
Несколько замечаний по коду. Строка 93 третьей части кода:
Код - C#: [Выделить]

    DBObject dbObj = ids[j].Open(OpenMode.ForWrite, false);

Ты открываешь это объект, но нигде не закрываешь его. Если dbObj.Erase(true) выполнилось успешно, то нужно вызвать dbObj.Close(). Если возникло исключение и мы пользуемся для удаления
Спасибо. Close там был но потом я его при рефакторинге случайно удалил, а вот то, что Dispose нужен не знал, учту.
По поводу 95% в данном случае действительно можно сделать так.


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

  • ADN Club
  • Сообщений: 23
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #11 : 06-11-2014, 14:16:00 »
Добавил EXPLODEALLPROXY.
Пришлось немного поменять из-за несовместимости транзакций и HandOverTo.
Еще хочу обратить внимание на момент с расчленением прокси. Если explode возвращает 0 примитивов то выполнять proxy++ не стоит (по моему мнению), т.к. данный ACAD_PROXY_ENTITY исчезает из быстрого выбора, но в чертеже содержится и при следующем открытии будет снова доступен.
Спасибо.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #12 : 06-11-2014, 21:21:49 »
Если explode возвращает 0 примитивов то выполнять proxy++ не стоит (по моему мнению), т.к. данный ACAD_PROXY_ENTITY исчезает из быстрого выбора, но в чертеже содержится и при следующем открытии будет снова доступен.
Эту мысль я что-то не понял.  В моём коде вне зависимости от того что возвращает explode сам примитив потом удаляется и поэтому proxy++ справедливо.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #13 : 06-11-2014, 22:30:34 »
Эта конструкция в корне неправильна:
Код - C# [Выбрать]
  1. proxyEntity.Explode(aExplProxy);
  2. if (aExplProxy.Count > 0)
  3. {
  4.     proxy++;
  5.     proxyEntity.Erase(true);
  6.  
  7.     Line line = new Line();
  8.     proxyEntity.HandOverTo(line, false, false);
  9.     line.Close();
  10.     line.Dispose();
  11. }
1. Ты сначала удаляешь  proxyEntity, и не проверив удачно ли это получилось выполняешь повторное удаление при помощи HandOverTo
2. После HandOverTo ты делаешь line.Close() - это правильно, т.к. теперь line - это примитив в базе. А где же line.Erase() ?
3. Нужно делать не line.Dispose(), а proxyEntity.Dispose()
Мы тут уже на форуме это обсуждали, что если объект/примитив AutoCAD содержится в базе (т.е. его ObjectId отличен от 0), то метод Dispose() для него эквивалентен методу Close(), а если примитив не содержится в базе (т.е. его ObjectId равен 0), то метод Dispose эквивалентен освобождению памяти этого примитива.
Таким образом  line.Close(); и  line.Dispose();  -  эквивалентны, зато нет освобождения памяти proxyEntity
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • Сообщений: 23
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #14 : 06-11-2014, 22:36:17 »
Цитата: T72 от 06-11-2014, 14:16:00

    Если explode возвращает 0 примитивов то выполнять proxy++ не стоит (по моему мнению), т.к. данный ACAD_PROXY_ENTITY исчезает из быстрого выбора, но в чертеже содержится и при следующем открытии будет снова доступен.

Эту мысль я что-то не понял.  В моём коде вне зависимости от того что возвращает explode сам примитив потом удаляется и поэтому proxy++ справедливо.
Данная функция для разбиения прокси на примитивы - значит если не получилось разбить то не стоит удалять, для этого есть другая функция.

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

  • Administrator
  • *****
  • Сообщений: 1096
  • Карма: 172
Re: REMOVEALLPROXY
« Ответ #15 : 06-11-2014, 22:43:51 »
ну и спасибо тебе за то, что навёл меня на баг в моей версии. В версиях начиная с 2013 список масштабов в команде REMOVEALLPROXY не чистился. Причина банальная - перенос функции acedResetScaleList в accore.dll. Подправил свои исходники и выложил исправленные arx-файлы.
Александр, а можно сделать "финт ушами"? То есть сделать по 2 arx-модуля: с чисткой масштабов и без оной? Честно говоря, я был безумно рад, что запроса по чистке масштабов не стало...
Все, что сказано - личное мнение.

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

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

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #16 : 06-11-2014, 23:03:31 »
Данная функция для разбиения прокси на примитивы - значит если не получилось разбить то не стоит удалять, для этого есть другая функция.
Ага. С этой логикой я согласен.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #17 : 06-11-2014, 23:06:43 »
Александр, а можно сделать "финт ушами"?
Запросто. Тем более что теперь на форуме выложены даже два варианта кода: и ObjectARX, и .NET API. Так что можешь для себя сделать любую сборку. :)
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • Сообщений: 23
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #18 : 07-11-2014, 07:34:14 »
Эта конструкция в корне неправильна:
Код - C#: [Выделить]

    proxyEntity.Explode(aExplProxy);
    if (aExplProxy.Count > 0)
    {
        proxy++;
        proxyEntity.Erase(true);
     
        Line line = new Line();
        proxyEntity.HandOverTo(line, false, false);
        line.Close();
        line.Dispose();
    }

1. Ты сначала удаляешь  proxyEntity, и не проверив удачно ли это получилось выполняешь повторное удаление при помощи HandOverTo
2. После HandOverTo ты делаешь line.Close() - это правильно, т.к. теперь line - это примитив в базе. А где же line.Erase() ?
3. Нужно делать не line.Dispose(), а proxyEntity.Dispose()
Мы тут уже на форуме это обсуждали, что если объект/примитив AutoCAD содержится в базе (т.е. его ObjectId отличен от 0), то метод Dispose() для него эквивалентен методу Close(), а если примитив не содержится в базе (т.е. его ObjectId равен 0), то метод Dispose эквивалентен освобождению памяти этого примитива.
Таким образом  line.Close(); и  line.Dispose();  -  эквивалентны, зато нет освобождения памяти proxyEntity

Про эквивалентности и нюансы с памятью не знал, спасибо учту.
« Последнее редактирование: 07-11-2014, 09:36:32 от T72 »

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #19 : 12-11-2014, 20:01:39 »
Александр, а можно сделать "финт ушами"? То есть сделать по 2 arx-модуля: с чисткой масштабов и без оной? Честно говоря, я был безумно рад, что запроса по чистке масштабов не стало...
Два варианта не нужны. Просто на уровне API нужно отделять мух от котлет: отдельные команды по работе с proxy и отдельные по работе со списком аннотативных масштабов. Затем различные комбинации этих методов заворачиваются в виде команд CAD системы. Т.е. отдельные команды для взрыва и удаления proxy и отдельная для очистки списка аннотативных масштабов.  Я себе это оформил в виде методов со следующими сигнатурами:

Код - C# [Выбрать]
  1. public static Db.ObjectIdCollection GetFreeAnnotativeScaleIds(Db.Database db);
  2.  
  3. public static void ClearAnnotativeScalesList(Db.Database db);
  4.  
  5. public static void GetProxyIds(Db.Database db, out Db.ObjectIdCollection proxyObjectIds, out Db.ObjectIdCollection proxyEntityIds, out Db.ObjectIdCollection proxyLockedLayerIds, Boolean unlockLayers);
  6.  
  7. public static void ExplodeAllProxy(Db.Database db, out StringBuilder sb);
  8.  
  9. public static ExplodeStatus ExplodeProxyInBTR(Db.ObjectId btrId, out Int64 proxy, out Int64 exploded);
  10.  
  11. public static void RemoveAllProxy(Db.Database db, out Int64 proxyNotEntityErased, out Int64 proxyEntityErased);
  12.  

P.S.
По коду Александра Наумовича завтра выложу замечания\вопросы. Код T72 мне не понравился, поэтому написал свою альтернативу. Выложу его после тестирования.

P.S.2
Кстати, список аннотативных масштабов я чищу "родными" средствами .NET API, не прибегая к вызову неуправляемых функций. Делаю это за счёт обработки контекста коллекции "ACDB_ANNOTATIONSCALES".

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #20 : 12-11-2014, 21:53:44 »
Зачем вы выполняете двойную проверку?

Код - C++ [Выбрать]
  1. for (__int64 i = iFirst; i < iLast && nObjects > 0; i++) {

разве не достаточно проверять i < iLast?

вы полагаете, что может оказаться существенная разница между разностью (iLast - iFirst) и значением nObjects и тем самым решили добавить дополнительную проверку, дабы максимально сократить цикл?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #21 : 12-11-2014, 22:46:17 »
вы полагаете, что может оказаться существенная разница между разностью (iLast - iFirst) и значением nObjects и тем самым решили добавить дополнительную проверку, дабы максимально сократить цикл?
Да. Я сталкивался с такой ситуацией несколько раз. Если мне не изменяет память я тебе рассказывал, что в изначальном коде iFirst был равен 0, но оказалось, что бывают чертежи у которых первая "живая" метка имеет очень большой номер и программа может очень длительное время перебирать метки (минутами, если не часами). Аналогично и с iLast. Достаточно просто сохранить чертеж в DXF-формате, изменить значение системной переменной $HANDSEED на какое-то очень большое и потом снова пересохранить в dwg-формат. Аналогичная ситуация возможна при получении чертежа из программ, которые генерируют DXF-файлы, если они не корректно вычисляют $HANDSEED.
« Последнее редактирование: 13-11-2014, 09:38:16 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #22 : 13-11-2014, 09:30:56 »
Код T72 мне не понравился
Что так? В основном T72 переводил мой код с C++ на C# (по мере возможности) без изменений. Мой код тоже не блещет изяществом. Первая версия его писалась > 15 лет назад и с годами просто адаптировалась к новым версиям без существенной переработки.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #23 : 13-11-2014, 11:05:27 »
Что так? В основном T72 переводил мой код с C++ на C# (по мере возможности) без изменений.
Именно поэтому, ведь C# это всё же не C++.
Код - C++ [Выбрать]
  1. Мой код тоже не блещет изяществом.
Идеал вряд ли достижим. Тем не менее, к нему всегда стоит стремиться (имхо) :) Собственный вариант "переписи на C#" мне ближе в виду того, что он более похож на C#, чем на C++.
Цитата: Александр Ривилис
Если мне не изменяет память я тебе рассказывал...
Я такого не помню.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #24 : 13-11-2014, 12:24:43 »
На мой взгляд, конструкцию

Код - C++ [Выбрать]
  1. if (pProxy && (pProxy->graphicsMetafileType() == AcDbProxyEntity::kFullGraphics ||
  2.                            pProxy->graphicsMetafileType() == AcDbProxyEntity::kFullGraphics)) {
  3.                            
  4.   if (pProxy->graphicsMetafileType() == AcDbProxyEntity::kFullGraphics) {
  5.         ...
  6.   } else {
  7.         ...
  8.   }
  9. }

можно было бы заменить более компактным вариантом:

Код - C++ [Выбрать]
  1. if (pProxy && (pProxy->graphicsMetafileType() == AcDbProxyEntity::kFullGraphics) {                         
  2.         ...
  3. }
  4. else if (pProxy && (pProxy->graphicsMetafileType() == AcDbProxyEntity::kBoundingBox) {                     
  5.         ...
  6. }
« Последнее редактирование: 13-11-2014, 12:51:18 от Андрей Бушман »

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #25 : 13-11-2014, 12:38:08 »
Я такого не помню.
Склероз у тебя. :-) Это было тогда, когда я поделился с тобой алгоритмом прохода по всем Handle в чертеже. Если помнишь, ты еще проверял какой из алгоритмов быстрее позволяет получить ObjectId по Handle. Были варианты: 1) Database.GetObjectId 2) P/Invoke для AcDbDatabase::getAcDbObjectId и 3) Database.TryGetObjectId - самый быстрый.
можно было бы заменить более компактным вариантом:
Он несколько компактнее по форме записи, но требует дополнительной проверки на неравенство нулю proxy в каждом операторе if. Так что тут дело вкуса. Тем более я не могу предугадать как этот код оптимизирует компилятор C++.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #26 : 13-11-2014, 12:48:00 »
требует дополнительной проверки на неравенство нулю proxy в каждом операторе if.
Но ведь вас не смутила двойная проверка на равенство AcDbProxyEntity::kFullGraphics. :)
Код - C++ [Выбрать]
  1. if(pProxy){
  2.         if (pProxy->graphicsMetafileType() == AcDbProxyEntity::kFullGraphics) {                        
  3.                         ...
  4.         }
  5.         else if (pProxy->graphicsMetafileType() == AcDbProxyEntity::kBoundingBox) {                    
  6.                         ...
  7.         }
  8. }
Цитировать
Это было тогда, когда я поделился с тобой алгоритмом прохода по всем Handle в чертеже. Если помнишь, ты еще проверял какой из алгоритмов быстрее позволяет получить ObjectId по Handle.
Я помню, что вы поделились, равно как и помню эти сравнения. Однако про дополнительную проверку за счёт уменьшения значения approxNumObjects() информации всё же не помню (возможно прослушал). Мой код, который вы упомянули, не использовал эту проверку (здесь, в коде строка 87).

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #27 : 13-11-2014, 13:01:28 »
Однако про дополнительную проверку за счёт уменьшения значения approxNumObjects() информации всё же не помню (возможно прослушал).
Ты невнимательно прочитал. Я напоминал тебе про старый разговор о стартовом номере, т.е. что Handle нужно начинать не с 0, а с db.BlockTableId.Handle. Про конечный номер мы не тогда не говорили, но с ним аналогично - дополнительная проверка не помешает.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Re: REMOVEALLPROXY
« Ответ #28 : 15-11-2014, 14:31:55 »
Ух начилось....
Где мой попкорн...
А давайте еще я свой вариант напишу - шутка не буду.
Александр, Андрей - я уверен что считать строки и байты - это немножко не ваш уровень.

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

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

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

  • 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 »
Понятно, спасибо.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #45 : 20-11-2014, 13:58:49 »
Она не совсем пустышка и если делать много подмен (десятки/сотни тысяч), то база чертежа будет расти в памяти до того момента, пока чертеж не будет сохранён и открыт повторно. Я бы это делать не рекомендовал.
Я так понял, что он спрашивает о том, почему бы не ограничиться только HandOverTo. Насчёт "будет расти в памяти" я не понял. Смотрим код:
Код - C# [Выбрать]
  1. using (Db.Line rep = new Db.Line()) {
  2.         proxyEntity.HandOverTo(rep, false, false);
  3.         rep.Erase();
  4.         rep.Close();
  5.         proxyEntity.Dispose();
  6.         handOverTo_called = true;
  7. }
Видим, что удаляется как оригинал, так и пустышка (для обоих вызывается Dispose). И за счёт чего же у нас, в этом случае, будет "расти память"?

Оффлайн bender

  • ADN Club
  • **
  • Сообщений: 62
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #46 : 20-11-2014, 14:27:34 »
Раз пошла такая пьянка, то зачем в Using Close?

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #47 : 20-11-2014, 14:29:47 »
аз пошла такая пьянка, то зачем в Using Close?
Чтобы применить это:
Код - C# [Выбрать]
  1. rep.Erase();

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #48 : 20-11-2014, 14:30:47 »
То что удаляется через Erase - удаляется не сразу, а только при сохранении чертежа. Соотвественно ты как-бы добавил примитив к базе, потом сделал ему Erase. Можешь поэкспериментировать и понаблюдать за памятью в AutoCAD. Не исключено, что я не прав.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #49 : 20-11-2014, 14:33:11 »
Чтобы применить это:
А bender прав. После HandOverTo у line появляется ненулевой ObjectId и соотвественно line.Dispose() приводит к line.Close(). Так что вызов line.Close() лишний.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #50 : 20-11-2014, 14:34:41 »
Спасибо, исправляю.
UPD Обновил код для ExtensionMethods.cs в последней версии, опубликованной мною выше (убрал лишние вызовы Close()).

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #51 : 20-11-2014, 14:52:07 »
То что удаляется через Erase - удаляется не сразу, а только при сохранении чертежа.
Тогда тем более:
Код - C# [Выбрать]
  1. if (canBeErased) {
  2.         proxyEntity.Erase();
  3.         handOverTo_called = false;
  4. }
  5. else {
  6.         using (Db.Line tmp = new Db.Line()) {
  7.                 proxyEntity.HandOverTo(tmp, false, false);
  8.                 tmp.Erase();
  9.                 proxyEntity.Dispose();
  10.                 handOverTo_called = true;
  11.         }
  12. }
Как в первом, так и во втором случаях - мы в итоге вызываем Erase.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #52 : 20-11-2014, 14:56:50 »
Как в первом, так и во втором случаях - мы в итоге вызываем Erase.
Но в первом случае ты вызываешь Erase для примитива, который уже находится в базе. Соотвественно объем памяти не изменяется. Во втором случае ты вызываешь Erase для примитива, который только что добавлен в базу. Вот за счет этого и возможно увеличение памяти.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #53 : 20-11-2014, 14:58:40 »
Кстати, если мы вызываем dbObj.HandOverTo, то у других объектов, ссылающихся на  dbObj, свойство ObjectId.IsEffectivelyErased начнёт показывать true (свойство DBObject.OwnerId), в то время как свойство ObjectId.IsErased будет по прежнему false. Именно по этой причине в фильтр я и добавил проверку ObjectId.IsEffectivelyErased.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #54 : 20-11-2014, 15:06:01 »
Именно по этой причине в фильтр я и добавил проверку ObjectId.IsEffectivelyErased.
Но в этом случае у тебя скорее всего не будет сходится статистика.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #55 : 20-11-2014, 15:07:55 »
Но в этом случае у тебя скорее всего не будет сходится статистика.
Да она и до этого не сходилась.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #56 : 20-11-2014, 16:33:13 »
Все дружно шлём апельсины (не путать с помидорами) в адрес Дмитрия Загорулькина, напомнившего о существовании перегруженной версии метода
Код - C# [Выбрать]
  1. Transaction.GetObject Method (ObjectId, Autodesk.AutoCAD.DatabaseServices.OpenMode, [MarshalAs(UnmanagedType.U1)] bool, [MarshalAs(UnmanagedType.U1)] bool)
Последний параметр позволяет открывать и править объекты на заблокированных слоях. Т.о. отваливается необходимость и в методе GetLockedLayerIds, а так же в файле LayoutLockingSwitcher.cs.

Выкладываю очередную (вторую по счёту) модификацию кода (теперь только два файла):

Код - 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, false, true)
  135.                         as Db.ProxyEntity;
  136.  
  137.                     if (proxyEntity.GraphicsMetafileType ==
  138.                         Db.GraphicsMetafileType.FullGraphics) {
  139.                         try {
  140.                             proxyEntity.Explode(newDBObjects);
  141.                         }
  142.                         catch {
  143.                         }
  144.                     }
  145.                     else if (proxyEntity.GraphicsMetafileType ==
  146.                         Db.GraphicsMetafileType.BoundingBox) {
  147.  
  148.                         Db.Extents3d ext = proxyEntity.GeometricExtents;
  149.                         Gm.Point3dCollection arr =
  150.                             new Gm.Point3dCollection();
  151.  
  152.                         arr.Add(ext.MinPoint);
  153.                         arr.Add(new Gm.Point3d(ext.MinPoint.X,
  154.                             ext.MaxPoint.Y, ext.MinPoint.Z));
  155.                         arr.Add(new Gm.Point3d(ext.MaxPoint.X,
  156.                             ext.MaxPoint.Y, ext.MinPoint.Z));
  157.                         arr.Add(new Gm.Point3d(ext.MaxPoint.X,
  158.                             ext.MinPoint.Y, ext.MinPoint.Z));
  159.  
  160.                         Db.Polyline3d pline = new Db.Polyline3d(
  161.                             Db.Poly3dType.SimplePoly, arr, true);
  162.  
  163.                         pline.LayerId = proxyEntity.LayerId;
  164.                         pline.LinetypeId = proxyEntity.LinetypeId;
  165.                         pline.Color = proxyEntity.Color;
  166.  
  167.                         newDBObjects.Add(pline);
  168.                     }
  169.  
  170.                     Db.BlockTableRecord btr = tr.GetObject(
  171.                         proxyEntity.BlockId, Db.OpenMode.ForWrite, false)
  172.                         as Db.BlockTableRecord;
  173.  
  174.                     // ----------------
  175.                     Boolean canBeErased = (proxyEntity.ProxyFlags & 0x1) != 0;
  176.  
  177.                     if (canBeErased) {
  178.                         proxyEntity.Erase();
  179.                         handOverTo_called = false;
  180.                     }
  181.                     else {
  182.                         using (Db.Line tmp = new Db.Line()) {
  183.                             proxyEntity.HandOverTo(tmp, false, false);
  184.                             tmp.Erase();
  185.                             proxyEntity.Dispose();
  186.                             handOverTo_called = true;
  187.                         }
  188.                     }
  189.  
  190.                     if (newDBObjects.Count > 0) {
  191.                         foreach (Db.DBObject item in newDBObjects) {
  192.                             if (item is Db.Entity) {
  193.                                 Db.Entity _ent = item as Db.Entity;
  194.                                 btr.AppendEntity(_ent);
  195.                                 tr.AddNewlyCreatedDBObject(item, true);
  196.                             }
  197.                         }
  198.                     }
  199.                     Db.ObjectIdCollection idsRef =
  200.                         btr.GetBlockReferenceIds(true, true);
  201.                     foreach (Db.ObjectId id in idsRef) {
  202.                         Db.BlockReference br = tr.GetObject(id,
  203.                             Db.OpenMode.ForWrite, false)
  204.                             as Db.BlockReference;
  205.                         br.RecordGraphicsModified(true);
  206.                     }
  207.                     tr.Commit();
  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.             out Boolean handOverTo_called) {
  216.  
  217.             // Check arguments
  218.             if (null == id)
  219.                 throw new ArgumentException("null == id");
  220.             if (id.IsErased)
  221.                 throw new ArgumentException("true == id.IsErased");
  222.             if (null == id.Database)
  223.                 throw new ArgumentException("null == id.Database");
  224.             if (id.Database.IsDisposed)
  225.                 throw new ArgumentException("true == id.Database.IsDisposed");
  226.  
  227.             // -------------------
  228.             Db.Database db = id.Database;
  229.  
  230.             using (Db.Transaction tr = db.TransactionManager
  231.                 .StartOpenCloseTransaction()) {
  232.                 Db.DBObject obj = tr.GetObject(id, Db.OpenMode.ForWrite, false,
  233.                     true);
  234.                 EraseDBObject(obj, out handOverTo_called);
  235.                 tr.Commit();
  236.             }
  237.         }
  238.  
  239.         private static void EraseDBObject(Db.DBObject obj,
  240.             out Boolean handOverTo_called) {
  241.  
  242.             // Check argument
  243.             if (null == obj)
  244.                 throw new ArgumentNullException("null == obj");
  245.             if (obj.IsErased)
  246.                 throw new ArgumentException("true == obj.IsErased");
  247.             if (obj.IsDisposed)
  248.                 throw new ArgumentException("true == obj.IsDisposed");
  249.             if (null == obj.Database)
  250.                 throw new ArgumentException("null == obj.Database");
  251.             if (obj.Database.IsDisposed)
  252.                 throw new ArgumentException("true == obj.Database.IsDisposed");
  253.  
  254.             // ----------------
  255.             Boolean canBeErased = true;
  256.  
  257.             // AcDbProxyEntity::kEraseAllowed = 0x1
  258.             if (obj is Db.ProxyObject) {
  259.                 Db.ProxyObject proxy = obj as Db.ProxyObject;
  260.                 canBeErased = (proxy.ProxyFlags & 0x1) != 0;
  261.             }
  262.             else if (obj is Db.ProxyEntity) {
  263.                 Db.ProxyEntity proxy = obj as Db.ProxyEntity;
  264.                 canBeErased = (proxy.ProxyFlags & 0x1) != 0;
  265.             }
  266.  
  267.             if (canBeErased) {
  268.                 obj.Erase(true);
  269.                 handOverTo_called = false;
  270.             }
  271.             else {
  272.                 using (Db.DBObject tmp = obj is Db.Entity ?
  273.                     (Db.DBObject)new Db.Line() : new Db.DBDictionary()) {
  274.                     obj.HandOverTo(tmp, false, false);
  275.                     tmp.Erase(true);
  276.                     obj.Dispose();
  277.                     handOverTo_called = true;
  278.                 }
  279.             }
  280.         }
  281.  
  282.         public static Db.ObjectId[] GetFreeAnnotativeScaleIds(
  283.             this Db.Database db) {
  284.  
  285.             // Check argument
  286.             if (null == db)
  287.                 throw new ArgumentNullException("null == db");
  288.             if (db.IsDisposed)
  289.                 throw new ArgumentException("true == db.IsDisposed");
  290.  
  291.             // ----------------
  292.             using (Db.ObjectIdCollection ids = new Db.ObjectIdCollection()) {
  293.                 Db.ObjectContextManager ocMng = db.ObjectContextManager;
  294.                 if (null != ocMng) {
  295.                     Db.ObjectContextCollection ocItems =
  296.                         ocMng.GetContextCollection("ACDB_ANNOTATIONSCALES");
  297.                     if (null != ocItems) {
  298.                         foreach (Db.ObjectContext item in ocItems) {
  299.                             if (item is Db.AnnotationScale)
  300.                                 ids.Add(new Db.ObjectId(item.UniqueIdentifier)
  301.                                     );
  302.                         }
  303.                         db.Purge(ids);
  304.                     }
  305.                 }
  306.                 return ids.Cast<Db.ObjectId>().Where(n => !n.IsErased
  307.                     && !n.IsEffectivelyErased).ToArray();
  308.             }
  309.         }
  310.  
  311.         public static void RemoveFreeAnnotativeScales(this Db.Database db) {
  312.  
  313.             // Check argument
  314.             if (null == db)
  315.                 throw new ArgumentNullException("null == db");
  316.             if (db.IsDisposed)
  317.                 throw new ArgumentException("true == db.IsDisposed");
  318.  
  319.             // -----------------
  320.             Db.ObjectId[] ids = db.GetFreeAnnotativeScaleIds();
  321.  
  322.             using (Db.Transaction tr = db.TransactionManager.StartTransaction()
  323.                 ) {
  324.                 foreach (Db.ObjectId id in ids) {
  325.                     try {
  326.                         Db.DBObject obj = tr.GetObject(id, Db.OpenMode
  327.                             .ForWrite, false);
  328.                         obj.Erase();
  329.                     }
  330.                     catch { }
  331.                 }
  332.                 tr.Commit();
  333.             }
  334.         }
  335.     }
  336. }

Код - 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.         static Db.ObjectId circleId = Db.ObjectId.Null;
  24.  
  25.         [Rt.CommandMethod("Proxy", Rt.CommandFlags.Modal)]
  26.         public void Command_PrintProxyInfo() {
  27.  
  28.             Ap.Document doc = cad.DocumentManager.MdiActiveDocument;
  29.             Ed.Editor ed = doc.Editor;
  30.             Db.Database db = doc.Database;
  31.  
  32.             // Proxy types
  33.             Rt.RXClass proxyObjectRXType = Rt.RXClass.GetClass(typeof(
  34.                 Db.ProxyObject));
  35.             Rt.RXClass proxyEntityRXType = Rt.RXClass.GetClass(typeof(
  36.                 Db.ProxyEntity));
  37.  
  38.             // Filters
  39.             Func<Db.ObjectId, Boolean> proxyEntityFilter = n => !n.IsErased &&
  40.                  !n.IsEffectivelyErased && n.ObjectClass.IsDerivedFrom(
  41.                  proxyEntityRXType);
  42.  
  43.             Func<Db.ObjectId, Boolean> proxyObjectFilter = n => !n.IsErased &&
  44.                 !n.IsEffectivelyErased && n.ObjectClass.IsDerivedFrom(
  45.                 proxyObjectRXType);
  46.  
  47.             // Filtered ids
  48.             Db.ObjectId[] proxyEntityIds = db.GetEntityIds(proxyEntityFilter);
  49.             Db.ObjectId[] proxyObjectIds = db.GetDBObjectIds(proxyObjectFilter
  50.                );
  51.             ed.WriteMessage(
  52.                 "{0} ProxyEntity and {1} ProxyObject items found.\n",
  53.                 proxyEntityIds.Length.ToString(), proxyObjectIds.Length
  54.                 .ToString());
  55.         }
  56.  
  57.         [Rt.CommandMethod("ClrScales", Rt.CommandFlags.Modal)]
  58.         public void Command_ClearUnusedAnnotativeScales() {
  59.  
  60.             Ap.Document doc = cad.DocumentManager.MdiActiveDocument;
  61.             Ed.Editor ed = doc.Editor;
  62.             Db.Database db = doc.Database;
  63.  
  64.             Db.ObjectId[] freeAnnotScaleIds = db.GetFreeAnnotativeScaleIds();
  65.             db.RemoveFreeAnnotativeScales();
  66.  
  67.             try {
  68.                 /* Remove erased objects from memory.
  69.                  * An exception occurs if erasedIds contain ids which was
  70.                  * removed from memory already. There is no method to check it
  71.                  * in advance. */
  72.                 Db.ObjectId[] erasedIds = db.GetDBObjectIds(n => n.IsErased);
  73.  
  74.                 /* This checking is neccessary, bacause if erasedIds.Length ==
  75.                  * 0 we get an exception in the ObjectIdCollection
  76.                  * initialization. */
  77.                 if (erasedIds.Length > 0) {
  78.                     using (Db.ObjectIdCollection ids =
  79.                         new Db.ObjectIdCollection(erasedIds)) {
  80.                         db.ReclaimMemoryFromErasedObjects(ids);
  81.                     }
  82.                 }
  83.             }
  84.             catch {/* nothing here */ }
  85.  
  86.             ed.WriteMessage("{0} unused annotation scales found and removed.\n",
  87.                 freeAnnotScaleIds.Length.ToString());
  88.         }
  89.  
  90.         [Rt.CommandMethod("rmProxy", Rt.CommandFlags.Modal)]
  91.         public void Command_RemoveAllProxyObjests() {
  92.  
  93.             Ap.Document doc = cad.DocumentManager.MdiActiveDocument;
  94.             Ed.Editor ed = doc.Editor;
  95.             Db.Database db = doc.Database;
  96.  
  97.             Rt.RXClass proxyObjectRXType = Rt.RXClass.GetClass(typeof(
  98.                 Db.ProxyObject));
  99.             Rt.RXClass proxyEntityRXType = Rt.RXClass.GetClass(typeof(
  100.                 Db.ProxyEntity));
  101.  
  102.             Func<Db.ObjectId, Boolean> proxyObjectFilter = n => !n.IsErased &&
  103.                 !n.IsEffectivelyErased && n.ObjectClass.IsDerivedFrom(
  104.                 proxyObjectRXType);
  105.             Func<Db.ObjectId, Boolean> proxyEntityFilter = n => !n.IsErased &&
  106.                  !n.IsEffectivelyErased && n.ObjectClass.IsDerivedFrom(
  107.                  proxyEntityRXType);
  108.  
  109.             Db.ObjectId[] proxyObjectIds = db.GetDBObjectIds(proxyObjectFilter
  110.                 );
  111.             Db.ObjectId[] proxyEntityIds = db.GetEntityIds(proxyEntityFilter);
  112.  
  113.             Int64 handOverTo_object_count = 0;
  114.             Int64 handOverTo_entity_count = 0;
  115.  
  116.             foreach (Db.ObjectId id in proxyObjectIds) {
  117.                 Boolean handOverTo_called = false;
  118.                 ExtensionMethods.RemoveDBObject(id, out handOverTo_called);
  119.                 if (handOverTo_called)
  120.                     ++handOverTo_object_count;
  121.             }
  122.             ed.WriteMessage("{0} ProxyObject items found and removed.\n",
  123.                 proxyObjectIds.Length.ToString());
  124.             ed.WriteMessage("Count of 'HandOverTo' operations: {0}.\n\n",
  125.                 handOverTo_object_count.ToString());
  126.  
  127.             foreach (Db.ObjectId id in proxyEntityIds) {
  128.                 Boolean handOverTo_called = false;
  129.                 ExtensionMethods.RemoveDBObject(id, out handOverTo_called);
  130.                 if (handOverTo_called)
  131.                     ++handOverTo_entity_count;
  132.             }
  133.  
  134.             try {
  135.                 /* Remove erased objects from memory.
  136.                  * An exception occurs if erasedIds contain ids which was
  137.                  * removed from memory already. There is no method to check it
  138.                  * in advance. */
  139.                 Db.ObjectId[] erasedIds = db.GetDBObjectIds(n => n.IsErased);
  140.  
  141.                 /* This checking is neccessary, bacause if erasedIds.Length ==
  142.                  * 0 we get an exception in the ObjectIdCollection
  143.                  * initialization. */
  144.                 if (erasedIds.Length > 0) {
  145.                     using (Db.ObjectIdCollection ids =
  146.                         new Db.ObjectIdCollection(erasedIds)) {
  147.                         db.ReclaimMemoryFromErasedObjects(ids);
  148.                     }
  149.                 }
  150.             }
  151.             catch {/* nothing here */ }
  152.  
  153.             ed.WriteMessage("{0} ProxyEntity items found and removed.\n",
  154.                 proxyEntityIds.Length.ToString());
  155.             ed.WriteMessage("Count of 'HandOverTo' operations: {0}.\n\n",
  156.                 handOverTo_entity_count.ToString());
  157.  
  158.             ed.WriteMessage("Run the _AUDIT command with the _Y option, " +
  159.                 "please.\n");
  160.         }
  161.  
  162.         [Rt.CommandMethod("xProxy", Rt.CommandFlags.Modal)]
  163.         public void Command_ExplodeAllProxyEntities() {
  164.  
  165.             Ap.Document doc = cad.DocumentManager.MdiActiveDocument;
  166.             Ed.Editor ed = doc.Editor;
  167.             Db.Database db = doc.Database;
  168.  
  169.             Rt.RXClass proxyEntityRXType = Rt.RXClass.GetClass(typeof(
  170.                 Db.ProxyEntity));
  171.  
  172.             Func<Db.ObjectId, Boolean> proxyEntityFilter = n => !n.IsErased &&
  173.                  !n.IsEffectivelyErased && n.ObjectClass.IsDerivedFrom(
  174.                  proxyEntityRXType);
  175.  
  176.             Db.ObjectId[] proxyEntityIds = db.GetEntityIds(proxyEntityFilter);
  177.  
  178.             Int64 newEntityCount = 0;
  179.             Int64 handOverTo_entity_count = 0;
  180.  
  181.             foreach (Db.ObjectId id in proxyEntityIds) {
  182.                 Boolean handOverTo_called = false;
  183.                 Db.ObjectId[] newEntityIds = ExtensionMethods
  184.                     .ExplodeProxyEntity(id, out handOverTo_called);
  185.                 newEntityCount += newEntityIds.Length;
  186.                 if (handOverTo_called)
  187.                     ++handOverTo_entity_count;
  188.             }
  189.  
  190.             try {
  191.                 /* Remove erased objects from memory.
  192.                  * An exception occurs if erasedIds contain ids which was
  193.                  * removed from memory already. There is no method to check it
  194.                  * in advance. */
  195.                 Db.ObjectId[] erasedIds = db.GetDBObjectIds(n => n.IsErased);
  196.  
  197.                 /* This checking is neccessary, bacause if erasedIds.Length ==
  198.                  * 0 we get an exception in the ObjectIdCollection
  199.                  * initialization. */
  200.                 if (erasedIds.Length > 0) {
  201.                     using (Db.ObjectIdCollection ids =
  202.                         new Db.ObjectIdCollection(erasedIds)) {
  203.                         db.ReclaimMemoryFromErasedObjects(ids);
  204.                     }
  205.                 }
  206.             }
  207.             catch {/* nothing here */ }
  208.  
  209.             ed.WriteMessage("{0} ProxyEntity items found and exloded.\n",
  210.                 proxyEntityIds.Length.ToString());
  211.             ed.WriteMessage("{0} new DBObjects created.\n", newEntityCount
  212.                 .ToString());
  213.             ed.WriteMessage("Count of 'HandOverTo' operations: {0}.\n",
  214.                 handOverTo_entity_count.ToString());
  215.  
  216.             ed.WriteMessage("Run the _AUDIT command with the _Y option, " +
  217.                 "please.\n");
  218.         }
  219.     }
  220. }
« Последнее редактирование: 21-11-2014, 12:46:51 от Андрей Бушман »

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #57 : 20-11-2014, 17:28:20 »
Все дружно шлём апельсины (не путать с помидорами) в адрес Дмитрия Загорулькина, напомнившего о существовании перегруженной версии метода
Код - C#: [Выделить]

    Transaction.GetObject Method (ObjectId, Autodesk.AutoCAD.DatabaseServices.OpenMode, [MarshalAs(UnmanagedType.U1)] bool, [MarshalAs(UnmanagedType.U1)] bool)

Последний параметр позволяет открывать и править объекты на заблокированных слоях. Т.о. отваливается необходимость и в методе GetLockedLayerIds, а так же в файле LayoutLockingSwitcher.cs.
1) Про этот метод я помнил, но он появился только в AutoCAD 2009, так что для тебя он актуален, но в случае необходимости писать универсальный код - не подходит (это касается и чистого ObjectARX)
2) По поводу твоей функции RemoveFreeAnnotativeScales. Её действия отличаются от стандартной команды _SCALELISTEDIT _Reset. В стандарте не удаляются неиспользуемые, но стандартные масштабы.

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

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #58 : 20-11-2014, 17:31:38 »
но стандартные масштабы.
у иностранцев свой список стандартных масштабов, а в России свой. Так что удаление их стандартных записей нам [проектировщикам компании, в которой я работаю] только на руку - не будут попусту глаза мозолить.

Цитировать
но в случае необходимости писать универсальный код - не подходит
"Универсальность" - понятие относительное... Например для меня это слово означает переносимость на уровне кода для AutoCAD 2009 и выше (более старые версии мне не интересны), а так же между различными CAD платформами (AutoCAD, nanoCAD, BricsCAD и т.п.).

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #59 : 20-11-2014, 17:41:58 »
Например для меня это слово означает переносимость на уровне кода для AutoCAD 2009 и выше (более старые версии мне не интересны)
Считай, что это было не для тебя, а для тех, кто еще пишет под версии AutoCAD до 2009.
Что касается списка масштабов, то восстановление в русской версии AutoCAD должно быть в стандартный список масштабов русской версии, что команда _SCALELISTEDIT _Reset и делает. Если вашим пользователям так удобнее, то и хорошо. Но это не всегда так. Допустим использовали только масштаб 1:2, ты все остальные масштабы удалил. Теперь пользователю самому придется создать масштаб 1:1.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #60 : 20-11-2014, 17:48:41 »
Допустим использовали только масштаб 1:2, ты все остальные масштабы удалил. Теперь пользователю самому придется создать масштаб 1:1.
Подразумевается, что полная очистка, в т.ч. и масштабов, происходит в самом конце работы, когда документ оформлен и его нужно очистить от лишнего. Кроме того, у меня есть отдельная команда, которая создаёт список аннотативных масштабов по госту, считывая все возможные варианты из внешнего XML файла, так что восстановить гостовские масштабы (при необходимости) не проблема. Да и не только их, т.к. XML можно подредактировать как угодно.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #61 : 20-11-2014, 19:26:13 »
В #56 Обновил исходный код:
1. В файле ExtensionMethods.cs добавил дополнительную проверку в строке 303 (оказалась нужной).
2. Переписал файл Commands.cs, убрав из него тестовую команду Test и добавив несколько новых, которыми пользователи могут пользоваться.

Реализованы следующие команды:
  • Proxy - вывести в консоль CAD информацию о количестве имеющихся в чертеже объектов ProxyObject и ProxyEntity.
  • ClrScales - сокращение от "clear scales". Команда удаляет в чертеже все неиспользованные аннотативные масштабы.
  • rmProxy - сокращение от "remove proxy". Удалить из чертежа все имеющиеся объекты ProxyObject и ProxyEntity.
  • xproxy - сокращение от "explode proxy". Расчленить в чертеже все имеющиеся объекты ProxyEntity.
Всё, финиш.

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

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Re: REMOVEALLPROXY
« Ответ #62 : 20-11-2014, 22:32:17 »
Подразумевается, что полная очистка, в т.ч. и масштабов, происходит в самом конце работы, когда документ оформлен и его нужно очистить от лишнего.
Я, например, чаще чищу чертежи, полученные от кого-то, до работы с ними (иначе их нередко ни чем не "повернуть").

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #63 : 20-11-2014, 22:33:39 »
Я, например, чаще чищу чертежи до работы с ними (иначе их нередко ни чем не "повернуть").
Цитировать
Кроме того, у меня есть отдельная команда, которая создаёт список аннотативных масштабов по госту, считывая все возможные варианты из внешнего XML файла, так что восстановить гостовские масштабы (при необходимости) не проблема. Да и не только их, т.к. XML можно подредактировать как угодно.

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

  • ADN Club
  • ****
  • Сообщений: 473
  • Карма: 66
Re: REMOVEALLPROXY
« Ответ #64 : 20-11-2014, 22:48:12 »
Я не про масштабы, а про чистку в общем.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #65 : 21-11-2014, 03:07:26 »
Вспомнил я еще про такой метод: Database.ReclaimMemoryFromErasedObjects, который позволяет освободить оперативную память, занятую удаленными (методом Erase) объектами. Может быть актуально если с чертежом продолжают работу в том же сеансе без сохранения.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • Сообщений: 23
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #66 : 21-11-2014, 07:44:29 »
Цитировать
T72, я хотел бы уточнить (так как не тестировал твой код). Твой код после всех исправлений на форуме сейчас работает нормально, т.е. можно считать, что это полностью работоспособный вариант или нужно его править?
Добрый день. Извиняюсь за столь долгий ответ, тестировал функции. Пока все работает хорошо, добавил еще один try/catch т.к. в одном из цивиловских фалов возникла ситуация при которой точка COGO не хотела удаляться, код в сообщении подправил.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #67 : 21-11-2014, 10:40:23 »
в одном из цивиловских фалов возникла ситуация при которой точка COGO не хотела удаляться
Можешь выложить этот DWG файл для тестирования?

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #68 : 21-11-2014, 10:41:04 »
Вспомнил я еще про такой метод: Database.ReclaimMemoryFromErasedObjects, который позволяет освободить оперативную память, занятую удаленными (методом Erase) объектами.
Спасибо, полезная информация. Добавлю в код.


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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #69 : 21-11-2014, 11:03:35 »
По поводу метода Database.ReclaimMemoryFromErasedObjects: в конец кода команды ClrScales (исходники см. выше в файле Commands.cs) я попробовал добавить такой код:

Код - C# [Выбрать]
  1. // Remove erased objects from memory
  2. Db.ObjectId[] erasedIds = db.GetDBObjectIds(n => n.IsErased);
  3. using (Db.ObjectIdCollection ids = new Db.ObjectIdCollection(
  4.         erasedIds)) {
  5.         db.ReclaimMemoryFromErasedObjects(ids);
  6. }

Однако если вызвать команду ClrScales два раза подряд, то в строке 5 получаем следующее исключение:

Цитировать
Autodesk.AutoCAD.Runtime.Exception was unhandled by user code
  Message=ePermanentlyErased
  Source=acdbmgd
  StackTrace:
       at Autodesk.AutoCAD.DatabaseServices.Database.ReclaimMemoryFromErasedObjects(ObjectIdCollection ids)
       at Bushman.CAD.Commands.Command_ClearUnusedAnnotativeScales() in c:\Users\developer\Documents\Visual Studio 2013\Projects\DwgResave_solution\Acad2009_Proxy\Commands.cs:line 82
       at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorker(MethodInfo mi, Object commandObject, Boolean bLispFunction)
       at Autodesk.AutoCAD.Runtime.CommandClass.InvokeWorkerWithExceptionFilter(MethodInfo mi, Object commandObject, Boolean bLispFunction)
       at Autodesk.AutoCAD.Runtime.PerDocumentCommandClass.Invoke(MethodInfo mi, Boolean bLispFunction)
       at Autodesk.AutoCAD.Runtime.CommandClass.CommandThunk.Invoke()
  InnerException:

Обратите внимание на подсвеченное красным цветом. В чистку я пытаюсь отправить идентификаторы всех объектов базы данных, которые IsErased == true.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #70 : 21-11-2014, 11:32:42 »
Всё правильно. Так и должно быть. Документация говорит о том, что код ePermanentlyErased возникает при повторном освобождении памяти. Специального признака того, что объект освобожден нет. Чтобы проверить это нужно его попытаться открыть и если получаем исключение ePermanentlyErased, то его память освобождена. Несмотря на то, что у тебя при вызове Database.ReclaimMemoryFromErasedObjects возникает исключение, тем не менее (согласно документации) все объекты обрабатываются, а исключение генерируется если хотя бы один из объектов уже освобожден (см. описание метода AcDbDatabase::reclaimMemoryFromErasedObjects).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #71 : 21-11-2014, 11:41:56 »
Добрый день. Извиняюсь за столь долгий ответ, тестировал функции. Пока все работает хорошо, добавил еще один try/catch т.к. в одном из цивиловских фалов возникла ситуация при которой точка COGO не хотела удаляться, код в сообщении подправил.
Я не зря задал этот вопрос. Судя по коду у тебя не должны удаляться "неудаляемые" прокси-объекты/прокси-примитивы. В твоем коде если не срабатывает метод Erase(), то вызывается:
Код - C# [Выбрать]
  1. Entity entity = dbObj as Entity;
  2. DBObject tmpObj = null;
  3. if (entity != null)
  4. {
  5.     tmpObj = new Line();
  6. }
  7. else
  8. {
  9.     tmpObj = new DBDictionary();
  10. }
  11. dbObj.HandOverTo(tmpObj, false, false);
  12. nProxyDeleted++;
  13. tmpObj.Close();
  14. tmpObj.Dispose();
Но нигде нет tmpObj.Erase(); :(
Так что или код у тебя работает не всегда, или на форуме не окончательный код. Проверь пожалуйста.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #72 : 21-11-2014, 11:57:25 »
Специального признака того, что объект освобожден нет.
Жаль. Этот функционал не помешал бы.
Несмотря на то, что у тебя при вызове Database.ReclaimMemoryFromErasedObjects возникает исключение, тем не менее (согласно документации) все объекты обрабатываются, а исключение генерируется если хотя бы один из объектов уже освобожден (см. описание метода AcDbDatabase::reclaimMemoryFromErasedObjects).
Т.е. вы хотите сказать, что исключение вываливается не на первом же уже удалённом объекте, но "в уме" запоминается, что такой объект присутствует и пробежав по всем элементам, обработав нужные, исключение вываливается после полной обработки? В этом случае просто нет смысла в исключении, поскольку AutoCAD мог просто в итерации пропускать "инвалидов" и обрабатывать только "валидов". Если так, то будет достаточно этот код засунуть в try\catch с пустым catch.

UPD Странно, что после вызова Database.ReclaimMemoryFromErasedObjects повторная итерация по Database снова находит эти ObjectId. Логичней, на мой взгляд, было бы для их Handle в Database.TryGetObjectId возвращать false, чтобы не сбивать с толку.

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

  • ADN Club
  • Сообщений: 23
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #73 : 21-11-2014, 12:09:06 »
    в одном из цивиловских фалов возникла ситуация при которой точка COGO не хотела удаляться

Можешь выложить этот DWG файл для тестирования?
Огрызок от файла http://file.sngp.ru/fileshare/d0f03cf0-5f57-42bf-a464-310102aba44d в нем эти точки, при эрейзе в эксплоде ругается eNotAllowedForThisProxy, но при повторном вызове их уже нет.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #74 : 21-11-2014, 12:19:21 »
Огрызок от файла
Я не нашёл в этом файле ни одного proxy.
UPD а блин... у меня по умолчанию открылся пустой (я не заметил этого), т.к. AutoCAD 2009 не смог открыть этот файл. Сейчас пересохраню в более старую версию и попытаюсь снова.

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

  • ADN Club
  • Сообщений: 23
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #75 : 21-11-2014, 12:21:18 »
Цитата: T72 от 21-11-2014, 12:09:06

    Огрызок от файла

Я не нашёл в этом файле ни одного proxy.
8 прокси там, нужно открыть в обычном автокаде и отключить энейблеры, если таковые имеются.

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

  • ADN Club
  • Сообщений: 23
  • Карма: 4
Re: REMOVEALLPROXY
« Ответ #76 : 21-11-2014, 12:23:38 »
Но нигде нет tmpObj.Erase(); :(
Так что или код у тебя работает не всегда, или на форуме не окончательный код. Проверь пожалуйста.
Да вы правы, имеет место досадная невнимательность, добавил, но и без нее работало. Ошибка с COGO точкой возникает при EXPLODEALLPROXY, а не REMOVEALLPROXY.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #77 : 21-11-2014, 12:24:35 »
8 прокси там, нужно открыть в обычном автокаде и отключить энейблеры, если таковые имеются.
я добавил UPD в предыдущем сообщении.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #78 : 21-11-2014, 12:31:56 »
8 прокси там
у меня показывает следующие цифры:
Цитировать
Command: proxy
21 ProxyEntity and 2583 ProxyObject items found.
Голый AutoCAD 2009.

Попытка выполнить команду xproxy (взорвать все ProxyEntity) привела к Fatal Error:
Цитировать
Unhandled Access Violation Reading 0x0008 Exception at 8d0076h

Спасибо за файл, буду дальше тестить.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #79 : 21-11-2014, 12:36:39 »
Fatal Error происходит в коде метода ExplodeProxyEntity в строке кода
Код - C# [Выбрать]
  1. Db.BlockTableRecord btr = tr.GetObject(
  2.         proxyEntity.BlockId, Db.OpenMode.ForWrite, false)
  3.         as Db.BlockTableRecord;
Текст:
Цитировать
System.AccessViolationException occurred
  Message=Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
  Source=acdbmgd
  StackTrace:
       at AcDbEntity.blockId(AcDbEntity* , AcDbObjectId* )
       at Autodesk.AutoCAD.DatabaseServices.Entity.get_BlockId()
       at Bushman.CAD.ExtensionMethods.ExplodeProxyEntity(ObjectId proxyEntityId, Boolean& handOverTo_called) in c:\Users\developer\Documents\Visual Studio 2013\Projects\DwgResave_solution\DwgRecovery_x64\ExtensionMethods.cs:line 202
  InnerException:
Причину ошибки нашёл, исправил. Чуть позже обновлю исходники.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #80 : 21-11-2014, 12:50:45 »
Обновил исходники в #56
Взрывы и расчленения прокси на обозначенном T72 файле (да и вообще в любом DWG) проходят без всяких блоков try\catch, тем самым существенно сокращая время обработки.

P.S. T72, благодарю за DWG файл, с его помощью я нашёл и исправил ошибку в своём коде.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #81 : 21-11-2014, 13:19:22 »
Маленькое пояснение: в моём коде присутствует такой try\catch:
Код - C# [Выбрать]
  1. try {
  2.     proxyEntity.Explode(newDBObjects);
  3. }
  4. catch {
  5. }
его присутствие обусловлено тем, что мои оригинальные исходники несколько отличаются от тех, которые я опубликовываю на данном форуме. В оригинале компиляция попутно идёт и под др. CAD системы. Наличие данного блока try\catch обусловлено тем, что BricsCAD генерирует исключение при попытке взорвать некоторые ProxyEntity. Поскольку исходники одни и те же на все интересующие меня CAD системы, то я и добавил этот блок try\catch. Если компилировать только под AutoCAD, то операцию расчленения прокси элемента можно вытащить из try\catch (при желании), т.к. в AutoCAD всё взрывается успешно, без генерации Exceptions.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #82 : 22-12-2014, 20:15:13 »
Обновлённая, полная версия исходников показана здесь. Исправлены найденные ошибки, добавлены более развёрнутые комментарии в код.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #83 : 28-08-2015, 21:03:43 »
Отделил оффтопик: http://adn-cis.org/forum/index.php?topic=2956.0
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #84 : 03-09-2015, 13:06:54 »
Внёс необходимые правки в исходный код, опубликованный ранее в блоге (была выявлена проблема с использованием "точки входа" в accoreconsole.exe) и перекомпилировал приложение. Проверил работу кода в AutoCAD 2009-2016 (acad.exe) и AutoCAD 2013-2016 (accoreconsole.exe). Перезалил архив по обозначенной в блоге ссылке, содержащей откомпилированную версию приложения.

Изменения:
1. Для accoreconsole.exe добавил отдельную точку входа (см. readme.txt).
2. Обновил содержимое файла readme.txt.
3. Убрал из исходного кода использование псевдонимов для пространств имён.
4. Отредактировал и опубликовал код "точки входа".

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #85 : 03-09-2015, 14:21:26 »
В соответствии с изменениями, указанными здесь, внёс исправления в исходный код, перекомпилировал его и перезалил архив.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #86 : 22-09-2015, 16:14:37 »
Закинул исходники на GitHub.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #87 : 23-09-2015, 20:18:46 »
По совету Алексея Кулика посмотрел в сторону BitBucket. Ознакомившись решил, что условия его использования и предоставляемые возможности для меня более приемлемы чем то, что предоставляет GitHub. Один из ключевых плюсов (для меня), при схожем наборе предоставляемых возможностей - это возможность бесплатно создавать private репозитории. В виду этого я перенёс репозиторий cadproxy на BitBucket, после чего удалил свой GitHub-аккаунт.

Оффлайн Владимир Азарко

  • ADN Club
  • Сообщений: 3
  • Карма: 3
  • Skype: azarko67
Re: REMOVEALLPROXY
« Ответ #88 : 03-10-2015, 18:52:46 »
В виду этого я перенёс репозиторий cadproxy на BitBucket, после чего удалил свой GitHub-аккаунт.
Андрей, в файле readme ссылка FEEDBACK осталась на github

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #89 : 03-10-2015, 20:45:48 »
Андрей, в файле readme ссылка FEEDBACK осталась на github
Исправил. Кстати, удалить профиль на GitHub, в свете перехода на BitBucket, было опрометчивым решением, т.к. он может пригодиться при работе с чужими проектами, размещёнными на нём. В виду этого профиль был на всякий случай восстановлен.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #90 : 05-05-2016, 16:53:05 »
Сегодня обнаружил, что написанный мною управляемый вариант где-то содержит серьёзную ошибку в коде. Вылезло на одном чертеже. Если на этом файле после команды XPROXY запускаю AUDIT Y, то с листа всё исчезает, после чего появляется сообщение, обозначенное на скрине и аудит находит множество ошибок (до расчленения прокси их не находил). Реализация от А.Н. Ривилиса отрабатывает без ошибок.

Пока не разбирался в причинах. Как появится свободное время - займусь поиском ошибок в коде.

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

  • Administrator
  • *****
  • Сообщений: 1096
  • Карма: 172
Re: REMOVEALLPROXY
« Ответ #91 : 05-05-2016, 20:54:33 »
Я тут обнаружил еще один момент (подчеркиваю - я не понимаю как работает код; единственное что я сделал - это его скомпилировал под мои привычные условия использования): создаю новый документ. Запускаю ExplodeAllProxy - ни одного прокси-объекта (что, в принципе, ожидаемо). Твои команды, вызванные после ExplodeAllProxy выдает наличие нескольких объектов, которые не разбиваются и не удаляются. Если надо - могу завтра на работе еще раз смоделировать ситуацию и выдать любую нужную информацию.
Или тут проще не заморачиваться и плюнуть? ;)
Все, что сказано - личное мнение.

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

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

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #92 : 05-05-2016, 20:58:15 »
Или тут проще не заморачиваться и плюнуть? ;)
Вполне возможно, что это наведёт Андрея на ошибку, т.к. если прокси в файле нет, то и его программа ничего находить не должна.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #93 : 05-05-2016, 20:59:22 »
Если надо - могу завтра на работе еще раз смоделировать ситуацию и выдать любую нужную информацию.
Буду признателен. Выкладывание обозначенных DWG файлов так же приветствуется, дабы можно было под отладчиком посмотреть что к чему.
Или тут проще не заморачиваться и плюнуть? ;)
Я всегда за исправление багов.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #94 : 05-05-2016, 21:00:16 »
Вполне возможно, что это наведёт Андрея на ошибку, т.к. если прокси в файле нет, то и его программа ничего находить не должна.
Или обнаружится ещё один баг в моём коде :)

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

  • Administrator
  • *****
  • Сообщений: 1096
  • Карма: 172
Re: REMOVEALLPROXY
« Ответ #95 : 05-05-2016, 21:00:50 »
Ок, тогда завтра займусь. Вполне может оказаться, что я по незнанию что-то намудрил с кодом при пересборке.
Все, что сказано - личное мнение.

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

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

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #96 : 05-05-2016, 21:02:34 »
Ок, тогда завтра займусь. Вполне может оказаться, что я по незнанию что-то намудрил с кодом при пересборке.
Или у тебя файл шаблона по-умолчанию содержит прокси объекты, которые ExplodeAllProxy почему-то пропускает.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #97 : 05-05-2016, 21:04:07 »
подчеркиваю - я не понимаю как работает код; единственное что я сделал - это его скомпилировал под мои привычные условия использования
А мне почему-то запомнилось, что ты там что-то химичил от себя :) :
Цитата: Алексей Кулик
Ниже показан исправленный мною код. Я поменял код так, чтобы хоть что-то в нем понять (Андрей, прости!)
Я не сравнивал с оригиналом, поэтому не знаю характер и объём произведённых тобой изменений (форка на битбукете не было).

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

  • Administrator
  • *****
  • Сообщений: 1096
  • Карма: 172
Re: REMOVEALLPROXY
« Ответ #98 : 05-05-2016, 21:08:21 »
Насколько я помню: Основной механизм не трогался. Структура тоже не менялась. Основной код был вынесен в отдельные функции с единственным параметром - выводить сообщения в ком.строку или нет. На ее основе были сделаны команды и лисп-функции. Код собран для ACAD2009, 2013-2016 и запущен в работу.
Завтра приведу лог выполнения на ACAD2009, 2013, 2016 (все - 64-битные, английские) на пустом файле. dwg тоже выложу. C#-переделку выкладывать?
Все, что сказано - личное мнение.

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

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

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #99 : 05-05-2016, 21:08:55 »
Или у тебя файл шаблона по-умолчанию содержит прокси объекты, которые ExplodeAllProxy почему-то пропускает.
А что, разве такое возможно? В каких случаях?

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

  • Administrator
  • *****
  • Сообщений: 1096
  • Карма: 172
Re: REMOVEALLPROXY
« Ответ #100 : 05-05-2016, 21:12:42 »
Теоретически возможно, если они прошли через "шаловливые ручки" вертикальных приложений.
Все, что сказано - личное мнение.

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

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

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #101 : 05-05-2016, 21:14:38 »
C#-переделку выкладывать?
Неа. Я в оригинале для начала найти должен. Если что - тебе не составит труда скопипастить свои изменения в обновлённую версию, если мне удастся найти причины кривизны моего кода (надеюсь, что удастся). К сожалению, завтра меня не будет на работе... :( Постараюсь завтра и на выходных из дома посмотреть.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #102 : 05-05-2016, 21:16:35 »
Теоретически возможно, если они прошли через "шаловливые ручки" вертикальных приложений.
Т.е. шаблоны ты создавал на вертикалке? Мне всё равно не понятно, в каких случаях код А.Н. Ривилиса для таких шаблонов может не находить прокси будучи запущенным в голом акаде...

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #103 : 05-05-2016, 21:17:40 »
Или у тебя файл шаблона по-умолчанию содержит прокси объекты, которые ExplodeAllProxy почему-то пропускает.
А что, разве такое возможно? В каких случаях?
Возможно что? Создать файл шаблона, содержащий прокси-примитивы? Или ExplodeAllProxy может пропустить прокси объект?
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #104 : 05-05-2016, 21:18:39 »
Возможно что? Создать файл шаблона, содержащий прокси-примитивы? Или ExplodeAllProxy может пропустить прокси объект?
Конечно же второй вариант...

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

  • Administrator
  • *****
  • Сообщений: 1096
  • Карма: 172
Re: REMOVEALLPROXY
« Ответ #105 : 05-05-2016, 21:38:21 »
Ситуацию "словил" на чистом dwt.
Объекты "вертикалок" не будут распознаваться как прокси, если demandload=3 и подгружен / науден соответствующий ObjectEnabler - это очевидно. Но, может, у Александра такой объект действительно не распознается как прокси при таких условиях, а у тебя - распознается? Это все в качестве предположения...
Все, что сказано - личное мнение.

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

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

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #106 : 05-05-2016, 21:44:52 »
Конечно же второй вариант...
Может. В отличие от RemoveAllProxy, который сканирует всю базу, ExplodeAllProxy работает только с теми контейнерами, которые могут содержать примитивы, а именно с (AcDb)BlockTableRecord'ами содержащимися в (AcDb)BlockTable. Т.е. если гипотетически предположить, что владельцем прокси-примитива будет не блок (том числе *ModelSpace, *PaperSpace, *PaperSpaceX), то ExplodeAllProxy его пропустит и обрабатывать не будет. Теоретически владельцами (AcDb)Entity могут быть только (AcDb)BlockTableRecord, но чем черт не шутит...
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #107 : 05-05-2016, 21:47:02 »
Но, может, у Александра такой объект действительно не распознается как прокси при таких условиях, а у тебя - распознается? Это все в качестве предположения...
Насколько я помню, то фильтрацию проксей я делал по аналогии с кодом А.Н. так что ожидались и одинаковые результаты. Нужно будет глянуть и сравнить...

Онлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
Re: REMOVEALLPROXY
« Ответ #108 : 05-05-2016, 22:02:56 »
Еще в качестве предположения проанализируй приведение к другому типу и удаление
Код - C# [Выбрать]
  1. using (Db.Line tmp = new Db.Line())
  2. {
  3.    proxyEntity.HandOverTo(tmp, false, false);
  4.    tmp.Erase();
  5.    proxyEntity.Dispose();
  6.    handOverTo_called = true;
  7. }

На одном чертеже словил, что создаются примитивы от разбивки, но сами  прокси не удаляются.
Т.к. почистить чертеж нужно было срочно, разбил оригинальной программой Александра Ривилиса, проанализировать причину не успел.
В других чертежах все работало норм.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #109 : 05-05-2016, 22:20:21 »
На одном чертеже словил, что создаются примитивы от разбивки, но сами  прокси не удаляются.
Как ты открывал свой proxyEntity (через транзакцию или без)?
Цитата: Андрей Бушман
Внимание! Если в коде не используется OpenCloseTransaction (ниже в коде я покажу оба варианта), то после того, как замещяемый объект (Circle в примере выше) открыт с опцией OpenMode.ForWrite - для него позднее должен быть обязательно вызван метод Dispose(), а для замещающего - метод Close() для того, чтобы зафиксировать изменение и закрыть запись в файле "UNDO.ac$". Обратите внимание на то, что удалять старый объект (Circle в примере выше), вызывая экземплярный метод Erase(), в данном случае не нужно, так как эта операция удаления выполняется в коде метода DBObject.HandOverTo(). Однако очистка памяти от замещаемого объекта (Circle в примере выше) путём вызова его метода Dispose() нужна, т. к. в коде метода HandOverTo() эта очистка не выполняется.

Онлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
Re: REMOVEALLPROXY
« Ответ #110 : 05-05-2016, 22:24:55 »
Теоретически владельцами (AcDb)Entity могут быть только (AcDb)BlockTableRecord, но чем черт не шутит...
Подтверждаю. На практике попадалась пара чертежей, в которых примитивы лежали не там, где надо, т.е. не в BlockTable. Предполагаю, что это результат  вылетов во время сохранения, или неудачного копирования и последующего сохранения.

Онлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
Re: REMOVEALLPROXY
« Ответ #111 : 05-05-2016, 22:26:29 »
Как ты открывал свой proxyEntity (через транзакцию или без)?
Без. насколько помню HandOverTo не работает с объектами транзакций вызывая исключение.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #112 : 05-05-2016, 22:29:08 »
насколько помню HandOverTo не работает с объектами транзакций вызывая исключение.
угу
Цитировать
Метод DBObject.HandOverTo()не разрешён к использованию на объектах, которые являются резидентными объектами транзакции.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #113 : 05-05-2016, 22:46:59 »
В #109 исправил текст цитаты, предварительно внеся соответствующие изменения в оригинал.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #114 : 05-05-2016, 23:32:16 »
Предполагаю, что это результат  вылетов во время сохранения, или неудачного копирования и последующего сохранения.
Только не это. Теоретически владельцем (AcDb)Entity может оказаться (AcDb)DBDictionary, но он для этого не предназначен.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Онлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
Re: REMOVEALLPROXY
« Ответ #115 : 06-05-2016, 06:59:15 »
Только не это. Теоретически владельцем (AcDb)Entity может оказаться (AcDb)DBDictionary, но он для этого не предназначен.
В теории да, но на практике попадаются объекты, в том числе примитивы с OwnerId которого не существует в БД. Т.е. вне иерархии, либо объекты/примитивы у которых ownerId==ObjectId.Null;

Чтоб не быть голословным:
https://yadi.sk/i/qvB-W41XrWy3s
https://yadi.sk/i/TUUbhOyDrWy54

Справедливости ради, отмечу - такое очень, очень редко встречается)))))))
Audit удаляет такие объекты.
« Последнее редактирование: 06-05-2016, 07:52:55 от Привалов Дмитрий »

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #116 : 07-05-2016, 01:31:50 »
Audit удаляет такие объекты.
Скажем так. Я считаю, что перед расчленением/удалением прокси следует выполнить как минимум _AUDIT, а еще лучше _RECOVER. В этом случае все не имеющие владельцев объекты будут удалены. А после этого с чертежом уже можно работать.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #117 : 10-05-2016, 14:44:38 »
Если надо - могу завтра на работе еще раз смоделировать ситуацию и выдать любую нужную информацию.
Напоминаю.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #118 : 10-05-2016, 15:01:35 »
Андрей Бушман
Подозреваю, что у тебя "шалит" Database.ReclaimMemoryFromErasedObjects. В моём коде он не используется.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #119 : 10-05-2016, 15:08:07 »
Подозреваю, что у тебя "шалит" Database.ReclaimMemoryFromErasedObjects. В моём коде он не используется.
"Будем посмотреть".

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

  • Administrator
  • *****
  • Сообщений: 1096
  • Карма: 172
Re: REMOVEALLPROXY
« Ответ #120 : 10-05-2016, 17:44:00 »
Сегодня прогнал на 2009х64. Похоже, я где-то что-то намудрил: команды выдают 0 объектов, а лисп-функции сообщают, что в файле 2 прокси объекта (если я все верно понимаю).
Все, что сказано - личное мнение.

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

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

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #121 : 10-05-2016, 17:53:47 »
Сегодня прогнал на 2009х64. Похоже, я где-то что-то намудрил: команды выдают 0 объектов, а лисп-функции сообщают, что в файле 2 прокси объекта (если я все верно понимаю).
Ясно.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #122 : 11-05-2016, 15:48:03 »
Подозреваю, что у тебя "шалит" Database.ReclaimMemoryFromErasedObjects. В моём коде он не используется.
Да, если закомментировать все её вызовы в коде, то проблемный файл обрабатывается нормально. Хотите сказать, что это не баг API, но либо я вызывал функцию не к месту, либо некорректный набор идентификаторов передаю в параметре?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #123 : 11-05-2016, 15:55:21 »
Хотите сказать, что это не баг API, но я вызывал функцию не к месту?
Интуитивно я предполагаю, что после вызова этого метода с чертежом лучше ничего больше не делать, а сразу его сохранить и закрыть.
Вообще этот метод добавили скорее всего для пакетной обработки файлов, чтобы противодействовать утечкам памяти. Но память освобождается, а ссылки на неё сохраняются пока база не закрыта. Это и приводит к непредсказуемым результатам.
Интересно, а в какой версии ты его проверял? Если мне не изменяет память, то этот метод появился в AutoCAD 2009.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #124 : 11-05-2016, 16:05:01 »
Но память освобождается, а ссылки на неё сохраняются пока база не закрыта. Это и приводит к непредсказуемым результатам.
Если это так, то это конкретный баг...
Интересно, а в какой версии ты его проверял? Если мне не изменяет память, то этот метод появился в AutoCAD 2009.
В нём и обнаружилась проблема. Соответственно в нём и тестировал.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #125 : 11-05-2016, 16:14:59 »
Цитата: ObjectARX SDK 2009
This member function deletes the objects underneath the input object ids and performs some related cleanup.

The object ids in the input array must already be erased, and they should reside in the invoked database. Objects owned by the objects listed in the input array will be erased unless they already are, and their memory also reclaimed.

All deleted objects and memory will be restored upon undo, and re-deleted upon redo, by use of their DWG filing members.
Заменил везде это
Код - C# [Выбрать]
  1. ObjectId[] erasedIds = db.GetDBObjectIds(n => n.IsErased);
на такой вариант
Код - C# [Выбрать]
  1. ObjectId[] erasedIds = db.GetDBObjectIds(n => n.IsErased && n.IsResident);
и снова раскомментировал вызовы
Код - C# [Выбрать]
  1. db.ReclaimMemoryFromErasedObjects(ids);

Результат: дополнительная проверка не помогла и проблема снова наблюдается.

Вывод: похоже, что в AutoCAD реализация ReclaimMemoryFromErasedObjects является кривой и пользоваться этим методом не стоит. Добавлю директиву препроцессора и закомментирую для AutoCAD код, относящийся к использованию этого метода и добавлю соответствующие комментарии о том, почему это было сделано.

P.S.
Затем проверю, как вызов ReclaimMemoryFromErasedObjects на проблемном файле отработает в nanoCAD и BricsCAD (ZWCAD пока не настроил - сделаю это позже).

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #126 : 11-05-2016, 16:54:32 »
Дополнительная информация:

Использование ReclaimMemoryFromErasedObjects в AutoCAD 2016 не приводит к изчезновению примитивов и возникновению обозначенного выше окна с ошибкой (как это было в AutoCAD 2009). Однако последующий аудит находит кучу ошибок:
Цитировать
Total errors found 358 fixed 358

Т.о. метод ReclaimMemoryFromErasedObjects криво работает не только в AutoCAD 2009 , но и в AutoCAD 2016 (сильно подозреваю, что все промежуточные версии  AutoCAD - не исключение из этого правила).

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #127 : 11-05-2016, 17:09:48 »
В нём и обнаружилась проблема. Соответственно в нём и тестировал.
А в более свежих?
Если это так, то это конкретный баг...
Вопрос только чей.
Objects owned by the objects listed in the input array will be erased unless they already are, and their memory also reclaimed.
Вот это бы я выделил красным. При этом ссылки от других объектов на эти объекты становятся нарушенными (впрочем и без ReclaimMemoryFromErasedObjects тоже). Именно поэтому, когда я создавал REMOVEALLPROXY два десятка лет назад я понимал, что как минимум требуется _AUDIT таких чертежей. А возможно они будут невосстановимо убиты.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #128 : 11-05-2016, 17:43:02 »
Вот это бы я выделил красным.
Ну так это логично, что если зависимые от него объекты удалены, то и они будут подчищены.

Вопрос только чей.
Намекаете на то, что мой? Я помню, что вы выше "интуитивно предполагали", однако в документации я не вижу информации о том, в каких контекстах этот метод следует вызывать, а в каких нельзя. Я вижу описание метода. Контекст, в котором я использую ReclaimMemoryFromErasedObjects выглядит вполне уместно, особенно если учитывать, что:
Цитировать
All deleted objects and memory will be restored upon undo, and re-deleted upon redo, by use of their DWG filing members.
т.е. если я верно понял этот текст - операция, выполненная при помощи ReclaimMemoryFromErasedObjects может быть спокойно отменена или возобновлена командами undo и redo.

Цитата: Александр Ривилис
Именно поэтому, когда я создавал REMOVEALLPROXY два десятка лет назад я понимал, что как минимум требуется _AUDIT таких чертежей. А возможно они будут невосстановимо убиты.
Это всё здорово, только какое отношение это имеет к текущему поведению ReclaimMemoryFromErasedObjects? Я вызвал метод в соответствии с тем, как его использование документировано в SDK, передавая ему идентификаторы объектов, удовлетворяющих условию использования этого метода. На выходе получил поломанный документ. Поясните своё "Вопрос только чей." в данном контексте.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #129 : 11-05-2016, 17:59:49 »
Я вызвал метод в соответствии с тем, как его использование документировано в SDK, передавая ему идентификаторы объектов, удовлетворяющих условию использования этого метода. На выходе получил поломанный документ. Поясните своё "Вопрос только чей." в данном контексте.
1. Audit ты запускал в том же сеансе работы с dwg-файлом или сохранил, открыл его и выполнил Audit?
Если в одном сеансе, то понятно что ты не исправил все ссылки на удаляемые объекты. Это не то, что должен делать указанный тобой метод.
2. Этот метод просто освобождает память, занимаемую переданными объектами и теми объектами, которыми владеют переданные объекты. Но этот метод не анализирует базу в контексте того, какие еще могут быть ссылки на эти объекты. Если ты прочитаешь описание не только .NET-метода, а исходного ObjectARX метода, то увидишь, что там есть куча оговорок по поводу использования этого метода. В частности:
Цитировать
Some specialized object classes may require cleanup beyond the scope of this function. Such requirements cannot be anticipated in this function, so the developer who utilizes this function is advised to beware, and to thoroughly test the stability of the set of custom classes they anticipate to input to this function. They may have to wrap calls to this function in a function that performs additional cleanup for specific classes.
В данном случае тебе бы пришлось найти в базе все ссылки в других объектах на эти объекты (и все объекты, которыми они владеют и так далее по иерархии) и удалить эти ссылки или заменить их на что-то такое, что не приводит к ошибкам в структуре dwg-файла. Это очень и очень сложно. Так что остается уповать на корректность работы _AUDIT.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Онлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
Re: REMOVEALLPROXY
« Ответ #130 : 11-05-2016, 18:09:42 »
Использование ReclaimMemoryFromErasedObjects в AutoCAD 2016 не приводит к изчезновению примитивов и возникновению обозначенного выше окна с ошибкой (как это было в AutoCAD 2009). Однако последующий аудит находит кучу ошибок:
Если не использовать ReclaimMemoryFromErasedObjects в 2016, аудит выдает 0 ошибок?

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #131 : 11-05-2016, 18:32:39 »
В данном случае тебе бы пришлось найти в базе все ссылки в других объектах на эти объекты (и все объекты, которыми они владеют и так далее по иерархии) и удалить эти ссылки или заменить их на что-то такое, что не приводит к ошибкам в структуре dwg-файла. Это очень и очень сложно. Так что остается уповать на корректность работы _AUDIT.
Т.е. в сухом остатке - лучше не использовать вызовы ReclaimMemoryFromErasedObjects в коде расширений.

Цитировать
Если не использовать ReclaimMemoryFromErasedObjects в 2016, аудит выдает 0 ошибок?
Я уже писал выше, что в этом случае аудит выдаёт 0 ошибок. В т.ч. и в 2016-м:
Цитировать
Command: NETLOAD
acad.proxy.R19.0.dll
© Andrey Bushman, 2016
 Commands:
proxy - get count of ProxyEntity and ProxyObject in the current Database.
xProxy - explode all proxy in the current Database.
rmProxy - remove all ProxyEntities and ProxyObjects in the current Database.
rmScales - remove all unused annotation scales in the current Database.

Command: AUDIT
Fix any errors detected? [Yes/No] <N>:
Auditing Header
Auditing Tables
Auditing Entities Pass 1
Pass 1 22300   objects audited
Auditing Entities Pass 2
Pass 2 22300   objects audited
Auditing Blocks
 466     Blocks audited
Auditing AcDsRecords
Total errors found 0 fixed 0
Erased 0 objects

Command: XPROXY
327 ProxyEntity items found.
327 ProxyEntity items exloded.
2700 new DBObjects created.
Count of 'HandOverTo' operations: 0.
Run the _AUDIT command with the _Y option, please.

Command: AUDIT
Fix any errors detected? [Yes/No] <N>:
Auditing Header
Auditing Tables
Auditing Entities Pass 1
Pass 1 24700   objects audited
Auditing Entities Pass 2
Pass 2 24700   objects audited
Auditing Blocks
 466     Blocks audited
Auditing AcDsRecords
Total errors found 0 fixed 0
Erased 0 objects

Command: RMPROXY
134 ProxyObject items found and removed.
Count of 'HandOverTo' operations: 0.
0 ProxyEntity items found and removed.
Count of 'HandOverTo' operations: 0.
Run the _AUDIT command with the _Y option, please.

Command: AUDIT
Fix any errors detected? [Yes/No] <N>:
Auditing Header
Auditing Tables
Auditing Entities Pass 1
Pass 1 24600   objects audited
Auditing Entities Pass 2
Pass 2 24600   objects audited
Auditing Blocks
 466     Blocks audited
Auditing AcDsRecords
Total errors found 0 fixed 0
Erased 0 objects

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #132 : 11-05-2016, 19:25:05 »
Т.е. в сухом остатке - лучше не использовать вызовы ReclaimMemoryFromErasedObjects в коде расширений.
Во всяком случае не в этом расширении. Если бы ты освобождал память из объектов, которые сам и создал и знаешь все их взаимосвязи, то этим методом можно было бы пользоваться.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #133 : 11-05-2016, 19:55:16 »
Во всяком случае не в этом расширении. Если бы ты освобождал память из объектов, которые сам и создал и знаешь все их взаимосвязи, то этим методом можно было бы пользоваться.
Ясно, спасибо.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #134 : 12-05-2016, 18:30:03 »
На битбукете обновил версию исходников. Обозначенная выше ошибка исправлена, проект переделан так, чтобы при компиляции на выходе получался Bundle-пакет. Помимо аглицкого описания расширения присутствует и на русском. Откомпилированная версия так же обновлена (https://bitbucket.org/Andrey-Bushman/cadproxy/downloads ).

Онлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
Re: REMOVEALLPROXY
« Ответ #135 : 13-05-2016, 08:33:14 »
На битбукете обновил версию исходников. Обозначенная выше ошибка исправлена, проект переделан так, чтобы при компиляции на выходе получался Bundle-пакет. Помимо аглицкого описания расширения присутствует и на русском. Откомпилированная версия так же обновлена (https://bitbucket.org/Andrey-Bushman/cadproxy/downloads ).

Есть незначительное замечание по коду.
А именно использование Polyline3d вместо Polyline, как в оригинале у Александра, для  отрисовки габаритов прокси,( если конечно кому-то нужен именно такой режим отображения)

Все дело в том, что Polyline для 4х вершин создает один объект в базе данных, внутри которого размещены все вершины.
а Polyline3d или Polyline2d создадут по 6 объектов DbObject
https://yadi.sk/i/6krjM-vtrg24c


Что скорее всего нежелательно для больших чертежей.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #136 : 13-05-2016, 10:14:38 »
Спасибо, гляну.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #137 : 13-05-2016, 10:30:08 »
А именно использование Polyline3d вместо Polyline, как в оригинале у Александра, для  отрисовки габаритов прокси,( если конечно кому-то нужен именно такой режим отображения)
Стоп... В строке 110 кода функции ExplodeProxyInBTR я вижу использование AcDb3dPolyline. Мой C#-вариант идентичен. Поторопился я тебе плюсик ставить... :)

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #138 : 13-05-2016, 10:37:54 »
Александр Наумович, а почему вы в упомянутом выше фрагменте кода, создающем 3D-полилинию не захотели для неё вызывать метод SetDatabaseDefaults()? Ведь вы в коде инициализировали не все свойства, которые настраивает SetDatabaseDefaults()... Т.е. не подправленными остались значения для Linetype scale, Visibility, Plot style name и Line weight.

Онлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
Re: REMOVEALLPROXY
« Ответ #139 : 13-05-2016, 10:48:43 »
Мой C#-вариант идентичен.
хм. а я смотрел не исходник, а прогнал ExplodeProxy2007.arx в 2008 автокаде. Более новые версии не смотрел.
так вот там рамки polyline создались.

В любом случае polyline на 4 вершины примерно в 6 раз меньше памяти займет чем Polyline3d.
 т.к. все объекты входящие в Polyline3d(3dPolylineVertex, SequenceEnd) это Entity, которые хранят информацию о стилях и т.д. ну ты понял - лишнюю инфу))))

https://yadi.sk/i/NBdjWBeArgBZ9

Кружком обведены координаты, а все остальные свойства в комплекте))))))
Еще обрати внимание на ползунок, свойств для вершин и SequenceEnd примерно в 2 раза больше. и все храниться в чертеже.

Онлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
Re: REMOVEALLPROXY
« Ответ #140 : 13-05-2016, 11:01:05 »
Еще обрати внимание на ползунок, свойств для вершин и SequenceEnd примерно в 2 раза больше. и все храниться в чертеже.

и сравни это с вершинами Polyline
AddVertexAt(int index, Point2d pt, double bulge, double startWidth, double endWidth);

явно Polyline3d проигрывает Polyline по компактности ;-)

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #141 : 13-05-2016, 11:02:02 »
В любом случае polyline на 4 вершины примерно в 6 раз меньше памяти займет чем Polyline3d.
Однако Polyline использует 2D-точки в то время как прокси может быть смещённым и повёрнутым относительно всех трёх осей.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #142 : 13-05-2016, 11:03:29 »
А именно использование Polyline3d вместо Polyline, как в оригинале у Александра, для  отрисовки габаритов прокси,( если конечно кому-то нужен именно такой режим отображения)
У меня AcDb3dPolyline. И сделано это умышленно, так как габариты могут в пространстве располагаться как угодно. AcDbPolyline пришлось бы крутить в пространстве. Да и вообще это как раз тот случай, когда полезной информации минимум, т.к. это информация о габаритном контейнере, а не о виде прокси-примитива. Заниматься дополнительной оптимизаций я счел лишним, но это не мешает тебе поступить иначе.
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #143 : 13-05-2016, 11:04:18 »
И сделано это умышленно, так как габариты могут в пространстве располагаться как угодно.
То, о чём я и писал в предыдущем сообщении.

Онлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
Re: REMOVEALLPROXY
« Ответ #144 : 13-05-2016, 11:07:40 »
Polyline использует 2D-точки в то время как прокси может быть смещённым и повёрнутым относительно всех трёх осей.

И? В коде построения габаритной рамки это не учитывается(не используется), а создается габаритный прямоугольник лежащий на одном уровне ;-)

У любой Entity есть свойство:
Matrix3d Ecs
в том числе у Polyline и даже SequenceEnd
смещай, поворачивай и масштабируй)

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #145 : 13-05-2016, 11:10:29 »
Привалов Дмитрий
Ну по-хорошему нужно было бы строить ящик (AcDb3dSolid), чтобы он соответствовал габаритному контейнеру. Но кому это нужно? 
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #146 : 13-05-2016, 11:14:55 »
У любой Entity есть свойство:
Matrix3d Ecs
в том числе у Polyline и даже SequenceEnd
смещай, поворачивай и масштабируй)
Ну по-хорошему нужно было бы строить ящик (AcDb3dSolid), чтобы он соответствовал габаритному контейнеру. Но кому это нужно? 
Оба варианта содержат разумное зерно, однако пока меня вполне устраивает и текущий вариант. Исходники в открытом доступе, так что любой желающий может их скопировать и подправить как ему нравится.

Онлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
Re: REMOVEALLPROXY
« Ответ #147 : 13-05-2016, 11:17:48 »
Ну по-хорошему нужно было бы строить ящик (AcDb3dSolid), чтобы он соответствовал габаритному контейнеру. Но кому это нужно? 
скорее всего не нужно, на крайний случай можно и Polyline выдавить с помощью свойства Thickness

насколько я понял GeometricExtents выдаст габарит без учета Ecs т.е. это 2 габаритные точки мин и макс, без всякого поворота. Или я не прав?

Онлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
Re: REMOVEALLPROXY
« Ответ #148 : 13-05-2016, 11:31:08 »
насколько я понял GeometricExtents выдаст габарит без учета Ecs т.е. это 2 габаритные точки мин и макс, без всякого поворота. Или я не прав?

Т.е. я подозреваю ,что габаритный куб не повернут также, как и сам примитив в пространстве. И скорее всего он всегда без поворота и учитывает габариты проекций примитивов по плоскостям координатной системы.

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #149 : 13-05-2016, 11:43:14 »
Грани габаритного контейнера всегда параллельны осям МСК (кроме случая когда примитив внутри блока, вставленного с поворотом).
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

Онлайн Привалов Дмитрий

  • ADN Club
  • *****
  • Сообщений: 533
  • Карма: 117
Re: REMOVEALLPROXY
« Ответ #150 : 13-05-2016, 11:49:52 »
И сделано это умышленно, так как габариты могут в пространстве располагаться как угодно. AcDbPolyline пришлось бы крутить в пространстве

Грани габаритного контейнера всегда параллельны осям МСК (кроме случая когда примитив внутри блока, вставленного с поворотом).

т.е. крутить и учитывать в данном случае ничего не нужно. я правильно понял?

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

  • Administrator
  • *****
  • Сообщений: 13829
  • Карма: 1784
  • Рыцарь ObjectARX
  • Skype: rivilis
Re: REMOVEALLPROXY
« Ответ #151 : 13-05-2016, 11:53:17 »
т.е. крутить и учитывать в данном случае ничего не нужно. я правильно понял?
Если 3D то вообще ничего не нужно. А если 2D, то нужно разбираться с Z.
Разговор о матрицах преобразования отделил: http://adn-cis.org/forum/index.php?topic=7083.0
« Последнее редактирование: 13-05-2016, 14:23:01 от Александр Ривилис »
Не забывайте про правильное Форматирование кода на форуме
Создание и добавление Autodesk Screencast видео в сообщение на форуме
Если Вы задали вопрос и на форуме появился правильный ответ, то не забудьте про кнопку Решение

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #152 : 18-05-2016, 22:41:08 »
Добавил в решение проект создания MSI-инсталляторов. Подправил настройки манагера конфигов. Удалил мусор.  Откомпилированные версии MSI выложил в общий доступ. Установщик распаковывает BUNDLE-пакет в каталог %ProgramFiles%\Autodesk\ApplicationPlugins\.

Важно!
Перед установкой следует удалить предыдущие версии расширения (cadproxy), в т.ч. выгрузить его менюшки и удалить их копии, созданные акадом в каталоге C:\Users\<UserName>\AppData\Roaming\Autodesk\AutoCAD <Year>\R<Major>.<Minor>\enu\Support\.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #153 : 04-06-2016, 00:25:51 »
Закрываю проект по этой теме на bitbucket.org. Кто интересовался исходниками, тот скачал себе предыдущую версию. Обновлённая версия решения будет позднее распространяться под лицензией Freeware - т.е. для свободного использования будут доступны бинарники, но уже без обновлённого исходного кода.

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

  • ADN Club
  • *****
  • Сообщений: 2000
  • Карма: 163
  • Пишу программки...
    • Блог
  • Skype: Compositum78
Re: REMOVEALLPROXY
« Ответ #154 : 27-06-2016, 14:11:09 »