Сообщество программистов Autodesk в СНГ

ADN Club => AutoLisp / VisualLISP и DCL => Тема начата: Матвей от 18-07-2019, 16:09:45

Название: Удаление примитивов из чертежа при помощи набора ssget
Отправлено: Матвей от 18-07-2019, 16:09:45
Создаю таблицу автокада
(https://i.postimg.cc/7JC13Xcb/1.png) (https://postimg.cc/7JC13Xcb)

Далее ее расчленяю (не спрашивайте зачем). У самой первой строки таблицы отключена видимость линий границ ячеек сверху, слева и справа (они окрашены серым цветом; номер этого цвета - 8 ). Если вывестие на печать таблицу (до расчленения),  эти линии не видны, но после того, как таблица расчленена, эти линии становятся обычными отрезками, которые будут печататься, поэтому они становятся для меня "лишними".  Удаляю я их следующим способом:
Код - Auto/Visual Lisp [Выбрать]
  1. ; сохраняем длину таблицы
  2. (setq tableWidth (vla-Get-Width table))
  3.  
  4. ; сохраняем высоту таблицы
  5. (setq tableHeight (vla-Get-Height table))
  6.  
  7. ; взрываем таблицу
  8. (vl-cmdf "_.EXPLODE" (vlax-vla-object->ename table))
  9.  
  10. ; выключаем объектную привязку
  11. (setvar "OSMODE" 0)
  12.  
  13. ; выделяем отрезки для удаления
  14. (setq selSet nil)
  15. (setq
  16.   selSet
  17.    (ssget
  18.      "_C"
  19.      (list (car gPoint) (cadr gPoint))
  20.      (list (+ (car gPoint) tableWidth) (- (cadr gPoint) tableHeight))
  21.      '((0 . "LINE") (62 . 8)
  22.    )
  23. )
  24.  
  25. ; возвращаем значение объектной привязки
  26. (setvar "OSMODE" oldOsmode)
  27.  
  28. ; удаляем отрезки
  29. (setq i 0)
  30. (repeat (sslength selSet) (vla-delete (vlax-ename->vla-object (ssname selSet i))) (setq i (1+ i)))
где gPoint - точка вставки таблицы (левый верхний угол).
Теоретически должно работать и работает, но не всегда стабильно (примерно один раз из десяти могут удалится не все отрезки). Причину такого поведения я для себя не установил.
Вопросы: на сколько данный метод вообще рационален и оправдан для такой задачи? Какие более надежные методы следует использовать?
Название: Re: Удаление примитивов из чертежа при помощи набора ssget
Отправлено: Александр Ривилис от 18-07-2019, 16:57:19
Вопросы: на сколько данный метод вообще рационален и оправдан для такой задачи? Какие более надежные методы следует использовать?
1. Использование (ssget "_C" ....) требует чтобы указанные точки были в ПСК (UCS) и (!!!) были видны на экране.
2. Удаление примитива во время итерации набора примитивов может испортить набор примитивов.
Название: Re: Удаление примитивов из чертежа при помощи набора ssget
Отправлено: Матвей от 18-07-2019, 23:06:35
1. Использование (ssget "_C" ....) требует чтобы указанные точки были в ПСК (UCS) и (!!!) были видны на экране.
это я, наверное, не всегда могу контролировать, следовательно, предложенный мною код, уже можно назвать не стабильным
2. Удаление примитива во время итерации набора примитивов может испортить набор примитивов.
то есть следует, например, создать список из vla-объектов (отрезков), а затем их уже удалять, вызывая из списка?

Александр, вы можете подсказать, как правильно следует удалить эти отрезки, если абстрагироваться от способа, предложенного мной? Может после расчленения таблицы в этих примитивах хранится информация о своем "родительском" объекте (таблице), за которую можно зацепиться? Или что-то в этом роде.
Название: Re: Удаление примитивов из чертежа при помощи набора ssget
Отправлено: Александр Ривилис от 18-07-2019, 23:13:02
это я, наверное, не всегда могу контролировать, следовательно данный код не стабилен
Ну теоретически ты можешь менять вид, чтобы точки были видны.
Александр, вы можете подсказать, как правильно следует удалить эти отрезки, если абстрагироваться от способа, предложенного мной? Может после расчленения таблицы в этих примитивах хранится информация о своем "родительском" объекте (таблице), за которую можно зацепиться?
Нет. Но ты можешь зафиксировать последний примитив в чертеже (при помощи (entlast)) до _EXPLODE, а затем найти все новые примитивы (при помощи (entnext))
Название: Re: Удаление примитивов из чертежа при помощи набора ssget
Отправлено: Матвей от 18-07-2019, 23:28:22
Но ты можешь зафиксировать последний примитив в чертеже (при помощи (entlast)) до _EXPLODE, а затем найти все новые примитивы (при помощи (entnext))
Спасибо за идею. Это я попробую.
Название: Re: Удаление примитивов из чертежа при помощи набора ssget
Отправлено: Алексей Кулик от 19-07-2019, 08:38:34
Я бы попробовал написать свой аналог "explode" для таблицы. Что-нибудь типа такого:
Код - Auto/Visual Lisp [Выбрать]
  1. (vl-load-com)
  2. (defun explode-table (ent erase / adoc def ent_lst res_lst ins)
  3.   ;; (setq ent (car (entsel)))
  4.   (if (and (setq ent (cond ((= (type ent) 'ename) ent)
  5.                            ((= (type ent) 'vla-object) (vlax-vla-object->ename ent))
  6.                            ) ;_ end of cond
  7.                  ) ;_ end of setq
  8.            (setq def (vla-item (vla-get-blocks (setq adoc (vla-get-activedocument (vlax-get-acad-object))))
  9.                                (cdr (assoc 2 (entget ent)))
  10.                                ) ;_ end of vla-item
  11.                  ) ;_ end of setq
  12.            ) ;_ end of and
  13.     (progn (vlax-for ent def (setq ent_lst (cons ent ent_lst)))
  14.            (setq ins     (vla-get-insertionpoint (vlax-ename->vla-object ent))
  15.                  res_lst (vla-copyobjects adoc
  16.                                           (vlax-make-variant
  17.                                             (vlax-safearray-fill (vlax-make-safearray vlax-vbobject (cons 0 (1- (length ent_lst)))) ent_lst)
  18.                                             ) ;_ end of vlax-make-variant
  19.                                           (vla-get-modelspace adoc)
  20.                                           ) ;_ end of vla-copyobjects
  21.                  ) ;_ end of setq
  22.            (foreach ent (vlax-safearray->list (vlax-variant-value res_lst))
  23.              (vla-move ent (vlax-3d-point '(0. 0. 0.)) ins)
  24.              ) ;_ end of foreach
  25.            (if erase
  26.              (entdel ent)
  27.              ) ;_ end of if
  28.            ) ;_ end of progn
  29.     ) ;_ end of if
  30.   ) ;_ end of defun
Здесь ent - указатель на вхождение таблицы; erase - удалять исходник или нет. Конечно, представленный код не завершен (хотя бы потому, что надо "эксплодить" не в пространство модели, а в пространство владельца таблицы). Но, думаю, общий принцип понятен.
Название: Re: Удаление примитивов из чертежа при помощи набора ssget
Отправлено: Матвей от 21-07-2019, 23:47:09
если честно, я не понял, что дает ваша функция
Название: Re: Удаление примитивов из чертежа при помощи набора ssget
Отправлено: Александр Ривилис от 21-07-2019, 23:54:14
если честно, я не понял, что дает ваша функция
Ну то что Алексей написал:
аналог "explode" для таблицы.
Название: Re: Удаление примитивов из чертежа при помощи набора ssget
Отправлено: Матвей от 22-07-2019, 19:20:15
Я понял, что эта функция расчленяет таблицу. Просто я не понял, как это поможет отыскать искомые отрезки для их последующего удаления.
У себя в программе выбор необходимых отрезков я переделал, используя вашу идею из #3, а от использования набора ssget полностью отказался.
Название: Re: Удаление примитивов из чертежа при помощи набора ssget
Отправлено: Алексей Кулик от 22-07-2019, 19:44:41
После расчленения таблицы моей функцией "невидимые" отрезки помещаются на слой Defpoints и выводиться на печать не будут.
Название: Re: Удаление примитивов из чертежа при помощи набора ssget
Отправлено: Матвей от 22-07-2019, 20:37:02
теперь понял. спасибо за ваше решение