Итак, о последствиях.
Некоторое время спустя проектировщики стали жаловаться, что у них часто вылетает AutoCAD, очень сильно тормозит при работе с небольшими чертежами и т.д. Начали смотреть, да, действительно все плохо. Основные симптомы выявленные мной:
Как боролись раньше:
Вариант 1: В самом ProSteel есть чудесная команда PS_CLEAN_PROXY, которая избавляет от этих объектов.
Плюсы: гарантированное избавление.
Минусы: Требуется наличие установленного приложения Bentley ProSteel, длительное время выполнения (на чертеже весом в 20 МБ время выполнения 1-2 минуты)
Вариант 2: ARX-утилита от небезызвестного Александра Ривилиса ExplodeProxy, которая добавляет в AutoCAD команду RemoveAllProxy. Отличная штука, когда этих proxy-объектов немного, но в нашей ситуации оказалась практически бесполезной.
Плюсы: Избавляет от proxy-объектов практически полностью (за редким исключением).
Минусы: Длительное время выполнения (на чертежах весом 20 МБ время выполнения 10-15 минут на 64-х битной машинке. На 32-х битной AutoCAD начинает кричать о нехватке памяти уже на 10-15 МБайтных чертежах.)
Вариант 3: Стандартная команда AutoCAD _WBLOCK (ПБЛОК). Тоже хорошее решение, но т.к. у нас используется система электронного архива, а на выходе команды получается новый файл, необходимо каждый раз экспортировать чертежи из архива, прогонять через _WBLOCK, подменять старый чертеж в файловой системе и импортировать обратно в архив.
Плюсы: Время выполнения - несколько секунд. Гарантированное избавление от объектов.
Минусы: Очень большое количество операций с чертежом. Необходимость операций экспорта/импорта из системы электронного архива.
Ни один из вышеперечисленных вариантов не устраивал полностью, поэтому я взял несколько чертежей для анализа. Более глубокий анализ показал наличие в базе чертежа словарей (Dictionaries), в которых и хранятся эти объекты. Перечислю эти словари ниже:
Первая проверяет наличие в базе чертежа объектов ProSteel.
Полный код можно посмотреть на github.
Вот, пожалуй, и все. Ах да, плюсы и минусы...
Плюсы: Время выполнения 2-3 секунды, на очень больших чертежах 5-6 секунд. Выполняется в текущем чертеже, не требует дополнительных операций с файлом.
Минусы: Пока не обнаружил :)
Update: Обнаружил один существенный минус. На одном и том же чертеже функция может выдать следующую ошибку: "Ошибка Automation. На объект ссылаются другие объекты". А может и корректно отработать. К сожалению, выяснить причину подобного поведения пока не удалось, если есть мысли, подскажите в комментариях. Но поигравшись с чистым AutoLISPом обнаружил, что dictremove удаляет словарь даже если vla-delete спотыкается. Отсюда родилась следующая функция.
Вот теперь все.
- Во-первых, объем небольшого по графике чертежа становится неприемлемым, чертежи вырастают до 10-15-20-30... МБайт. Самый ужасный чертеж, который я встречал весил 258 МБ.
- Во-вторых, при копировании стандартных примитивов AutoCAD из чертежа в чертеж, AutoCAD вылетает или жутко тормозит.
Как боролись раньше:
Вариант 1: В самом ProSteel есть чудесная команда PS_CLEAN_PROXY, которая избавляет от этих объектов.
Плюсы: гарантированное избавление.
Минусы: Требуется наличие установленного приложения Bentley ProSteel, длительное время выполнения (на чертеже весом в 20 МБ время выполнения 1-2 минуты)
Вариант 2: ARX-утилита от небезызвестного Александра Ривилиса ExplodeProxy, которая добавляет в AutoCAD команду RemoveAllProxy. Отличная штука, когда этих proxy-объектов немного, но в нашей ситуации оказалась практически бесполезной.
Плюсы: Избавляет от proxy-объектов практически полностью (за редким исключением).
Минусы: Длительное время выполнения (на чертежах весом 20 МБ время выполнения 10-15 минут на 64-х битной машинке. На 32-х битной AutoCAD начинает кричать о нехватке памяти уже на 10-15 МБайтных чертежах.)
Вариант 3: Стандартная команда AutoCAD _WBLOCK (ПБЛОК). Тоже хорошее решение, но т.к. у нас используется система электронного архива, а на выходе команды получается новый файл, необходимо каждый раз экспортировать чертежи из архива, прогонять через _WBLOCK, подменять старый чертеж в файловой системе и импортировать обратно в архив.
Плюсы: Время выполнения - несколько секунд. Гарантированное избавление от объектов.
Минусы: Очень большое количество операций с чертежом. Необходимость операций экспорта/импорта из системы электронного архива.
Ни один из вышеперечисленных вариантов не устраивал полностью, поэтому я взял несколько чертежей для анализа. Более глубокий анализ показал наличие в базе чертежа словарей (Dictionaries), в которых и хранятся эти объекты. Перечислю эти словари ниже:
- Ks_ShapeRefDictionary
- Ks_DetailStyleDictionary
- Ks_XRecordDictionary
- Ks_GroupDataDictionary
Первая проверяет наличие в базе чертежа объектов ProSteel.
;;; <LISPDOC> ;;; <SUBR>(prosteel-check)</SUBR> ;;; <DESC>Check is there any prosteel dictionaries in drawing database</DESC> ;;; <RET>T or nil</RET> ;;; </LISPDOC> (defun prosteel-check (/ result) (vlax-for dict (vla-get-dictionaries (vla-get-activedocument (vlax-get-acad-object))) (if (vlax-property-available-p dict 'Name) (if (member (vlax-get dict 'Name) '("Ks_ShapeRefDictionary" "Ks_DetailStyleDictionary" "Ks_XRecordDictionary" "Ks_GroupDataDictionary")) (setq result T)))) result)Вторая удаляет словари ProSteel из базы данных чертежа.
;;; <LISPDOC> ;;; <SUBR>(prosteel-remove-dicts-vl)</SUBR> ;;; <DESC>Remove all prosteel dictionaries (proxy-objects)</DESC> ;;; <RET>nil</RET> ;;; </LISPDOC> (defun prosteel-remove-dicts-vl (/ result) (vlax-for dict (vla-get-dictionaries (vla-get-activedocument (vlax-get-acad-object))) (if (vlax-property-available-p dict 'Name) (if (member (vlax-get dict 'Name) '("Ks_ShapeRefDictionary" "Ks_DetailStyleDictionary" "Ks_XRecordDictionary" "Ks_GroupDataDictionary")) (vla-delete dict)))))Я намеренно внедрил все определенные за пределами функции для простоты восприятия.
Полный код можно посмотреть на github.
Вот, пожалуй, и все. Ах да, плюсы и минусы...
Плюсы: Время выполнения 2-3 секунды, на очень больших чертежах 5-6 секунд. Выполняется в текущем чертеже, не требует дополнительных операций с файлом.
Минусы: Пока не обнаружил :)
Update: Обнаружил один существенный минус. На одном и том же чертеже функция может выдать следующую ошибку: "Ошибка Automation. На объект ссылаются другие объекты". А может и корректно отработать. К сожалению, выяснить причину подобного поведения пока не удалось, если есть мысли, подскажите в комментариях. Но поигравшись с чистым AutoLISPом обнаружил, что dictremove удаляет словарь даже если vla-delete спотыкается. Отсюда родилась следующая функция.
;;; <LISPDOC> ;;; <SUBR>(prosteel-remove-dicts-ent)</SUBR> ;;; <DESC>Remove all prosteel dictionaries using dictremove (proxy-objects)</DESC> ;;; <RET>nil</RET> ;;; </LISPDOC> (defun prosteel-remove-dicts-ent ( / dict) (foreach dict '("Ks_ShapeRefDictionary" "Ks_DetailStyleDictionary" "Ks_XRecordDictionary" "Ks_GroupDataDictionary")) (dictremove (namedobjdict) dict)) nil)Здесь пока проблем не нашел, код на github обновил.
Вот теперь все.
Комментариев нет:
Отправить комментарий