Re: Контур по блоку

Выкладываю на тестирование вариант команды, строящий контур по любым выбранным объектам (в пределах возможности BOUNDARY). Выбор блока становится частнам случаем

;https://www.caduser.ru/forum/topic30797.html
;| ! *******************************************************************
;; !                  lib:IsPtInView
;; ! *******************************************************************
;; ! Проверяет находится ли точка в видовом экране
;; ! Auguments: 'pt'  — Точка для анализа в МСК!!!
;; ! Return   : T или nil если 'pt' в видовом экране или нет
;; ! *******************************************************************|;
(defun lib:IsPtInView (pt / VCTR Y_Len SSZ X_Pix Y_Pix X_Len Lc Uc)
(setq pt (trans pt 0 1))
(setq VCTR (getvar "VIEWCTR") Y_Len (getvar "VIEWSIZE")
   SSZ (getvar "SCREENSIZE")
   X_Pix (car SSZ) Y_Pix (cadr SSZ)
   X_Len (* (/ X_Pix Y_Pix) Y_Len)
   Lc (polar VCTR (dtr 180.0) (* 0.5 X_Len))
   Uc (polar Lc 0.0 X_Len)
   Lc (polar Lc (dtr 270.0) (* 0.5 Y_Len))
   Uc (polar Uc (dtr 90.0) (* 0.5 Y_Len)))
(if (and (> (car pt) (car Lc))(< (car pt) (car Uc))
   (> (cadr pt) (cadr Lc))(< (cadr pt) (cadr Uc)))
  T nil))
(defun DTR (a)(* pi (/ a 180.0)))
(defun RTD (a)(/ (* a 180.0) pi))
; ! ***********************************************************
;; !                             lib:Zoom2Lst
;; ! **********************************************************
;; ! Function : Zoom границ списка точек
;; ! Arguments: 'vlist' — Список точек в МСК!!!!
;; ! Зуммирует экран, чтобы все точки были видны
;; ! Returns  : t — было зуммирование nil — нет
;; ! **********************************************************
(defun lib:Zoom2Lst( vlist / bl tr Lst OS)
;(setq *MIP-ZOOM-PREV* nil)
(setq  Lst (lib:pt_extents vlist)
  bl (car Lst) tr (cadr Lst))
(if (not (and (lib:IsPtInView bl) (lib:IsPtInView tr)))
(progn  (setq OS (getvar "OSMODE"))(setvar "OSMODE" 0)
  (command "_.Zoom" "_Window" (trans bl 0 1)(trans tr 0 1)
    "_.Zoom" "0.95x")
 ;       (setq *MIP-ZOOM-PREV* 2)
  (setvar "OSMODE" OS)
  T) NIL))
;| ! ***************************************************************************
;; !           lib:pt_extents
;; ! ***************************************************************************
;; ! Function : Возвращает границы MIN, MAX X,Y,Z списка точек
;; ! Argument : 'vlist' — Список точек
;; ! Returns  : Список точек (ЛевНижн ПравВерхн)
;; ! ***************************************************************************|;
(defun  lib:pt_extents (vlist / tmp)
(setq tmp (mapcar '(lambda (x) (vl-remove-if 'null x))
 (mapcar '(lambda (what) (mapcar '(lambda (x) (nth what x)) vlist))
 '(0 1 2))));_setq
  (list (mapcar '(lambda(x)(apply 'min x)) tmp)(mapcar '(lambda(x)(apply 'max x)) tmp)));_defun
;https://www.caduser.ru/forum/topic30797.html
;Block Contour
(defun C:BC ( / *error* blk obj MinPt MaxPt hiden pt pl unnamed_block adoc tmp_blk adoc blks lays lay oname sel csp loc)
(defun *error* ( msg )(mapcar '(lambda(x)(vla-put-Visible x :vlax-true)) hiden)
  (vla-endundomark adoc)(if (and tmp_blk (vlax-write-enabled-p tmp_blk))(vla-Erase tmp_blk))
  (vla-clear sel)(vlax-release-object sel)(foreach x loc (vla-put-lock x :vlax-true)))
(vl-load-com)
(if (zerop (getvar "WORLDUCS"))(progn(vl-cmdf "_.UCS" "")(vl-cmdf "_.Plan" "")))
(setq adoc (vla-get-ActiveDocument (vlax-get-acad-object))
        blks (vla-get-blocks adoc)
        lays (vla-get-layers adoc)
        sel  (vla-get-activeselectionset adoc)
  )
(vla-startundomark adoc)(vla-clear sel)(princ "\nВыберите объекты для построения контура")
  (vla-selectonscreen sel)
 (if (not (zerop (vla-get-count sel)))
    (progn
    (setq csp (vla-objectidtoobject adoc (vla-get-ownerid (vla-item sel 0))))
    (setq unnamed_block (vla-add (vla-get-blocks adoc)(vlax-3d-point '(0. 0. 0.)) "*U"))
    (vlax-for x sel
        (setq oname (strcase (vla-get-objectname x))
              lay  (vla-item lays (vla-get-layer x))
        )
        (if (= (vla-get-lock lay) :vlax-true)
          (progn (vla-put-lock lay :vlax-false) (setq loc (cons lay loc)))
        )
      (cond ((member oname '("ACDBVIEWPORT" "ACDBATTRIBUTEDEFINITION")) nil)
        ((= oname "ACDBBLOCKREFERENCE")
         (vla-InsertBlock unnamed_block
           (vla-get-insertionpoint x)(vla-get-name x)
           (vla-get-xscalefactor x)(vla-get-yscalefactor x)
           (vla-get-zscalefactor x)(vla-get-rotation x))
         (setq blk (cons x blk))
         )
        (t (setq obj (cons x obj)))
        )
      );_vlax-for
        (setq lay  (vla-item lays (getvar "CLAYER")))
        (if (= (vla-get-lock lay) :vlax-true)
          (progn (vla-put-lock lay :vlax-false) (setq loc (cons lay loc)))
        )
     (if obj
       (progn
         (vla-copyobjects
              (vla-get-activedocument (vlax-get-acad-object))
              (vlax-make-variant
                (vlax-safearray-fill
                  (vlax-make-safearray vlax-vbobject (cons 0 (1- (length obj))))
                  obj
          )
              )
              unnamed_block
            )
     )
       )
    (setq obj (append obj blk))
    (if obj (progn
          (setq tmp_blk (vla-insertblock csp (vlax-3d-point '(0. 0. 0.))(vla-get-name unnamed_block) 1.0 1.0 1.0 0.0))
          (vla-GetBoundingBox tmp_blk 'MinPt 'MaxPt)  ;_Границы блока
               (setq MinPt (vlax-safearray->list MinPt)
                     MaxPt (vlax-safearray->list MaxPt)
                     MinPt (mapcar '- MinPt '(10 10))
                     MaxPt (mapcar '+ MaxPt '(10 10)))
           (lib:Zoom2Lst (list MinPt MaxPt))
           (setq sset (ssget "_C" MinPt MaxPt))
(if sset (progn
      (setq hiden (mapcar 'vlax-ename->vla-object(vl-remove-if 'listp (mapcar 'cadr (ssnamex sset))))
        hiden (vl-remove tmp_blk hiden))
      (mapcar '(lambda(x)(vla-put-Visible x :vlax-false)) hiden)
      (setq pt (mapcar '+ MinPt '(5 5)))
      (vl-cmdf "_.RECTANG" (trans MinPt 0 1)(trans MaxPt 0 1))
      (setq pl (vlax-ename->vla-object(entlast)))
      (if (VL-CATCH-ALL-ERROR-P (VL-CATCH-ALL-APPLY '(lambda ()
         (vl-cmdf "_-BOUNDARY" (trans pt 0 1) "")
              (while (> (getvar "CMDACTIVE") 0)(command "")))))
      (princ "\nНе удалось построить контур"))
      (vla-Erase pl)(vla-Erase tmp_blk)(vl-cmdf "_.ERASE" MinPt "")
      (setq pl (vlax-ename->vla-object(entlast)))
      (mapcar '(lambda(x)(vla-put-Visible x :vlax-true)) hiden)
      (initget  "Yes No")
      (if (= (getkword "\nУдалять объекты? [Yes/No] <No> : ") "Yes")
         (mapcar '(lambda (x) (if (vlax-write-enabled-p x) (vla-Erase x))) obj))
     )
       )
      )
     )
     (vla-clear sel)(vlax-release-object sel)
     )
   );_if not
  (foreach x loc (vla-put-lock x :vlax-true))
  (vla-endundomark adoc)(princ))
(princ "\nНаберите в командной строке BC")

Re: Контур по блоку

хорошо, начнём тестить.

Re: Контур по блоку

функция работает тока пару раз....потом ничего не строит....иногда доходит вот до этого

Команда: _BC ; ошибка: В функции *error* возникла ошибка:неверный тип
аргумента: VLA-OBJECT nil

иногда я строю окр. вокруг необходимых обектов и запускаю _BC и иногда помогает.
Такое ощущение, что иногда фукция невозвращает max(X,Y)

Re: Контур по блоку

> [b]Август[/b]
Прогнал чуть больше 20 раз ничего такого не замечено. Пробовал последнюю версию от 2006-11-16 14:46:45. Но только на блоках.
> VVA
И еще раз спасибо.

Re: Контур по блоку

> Юрий
мож тогда это глюк моём Каде?
Подождём ещё мнений!!!!

Re: Контур по блоку

> Август
Хотел тоже сказать про глюк, пока не случилось то же. Исследования показали, что в какой-то момент попытка получить указатель на активный набор через vla-методы приводит в аварийному завершению:

(setq adoc (vla-get-ActiveDocument (vlax-get-acad-object))
        sel  (vla-get-activeselectionset adoc))

Потом я вспомнил, что сам наступал на эти грабли
http://dwg.ru/forum/viewtopic.php?t=6482
http://dwg.ru/forum/viewtopic.php?t=6670
Переписал на ssget, вроде работает там где не работало. Плюс переписал алгоритм поиска контура, если он есть. Оставляется самый внешний контур, внутренние островки тоже удаляются. При запросе на удаление объектов, они удаляются с учетом блокировки слоя. Ну вот вроде и все изменения. Исправленный вариан на тестирование.

;https://www.caduser.ru/forum/topic30797.html
;| ! *******************************************************************
;; !                  lib:IsPtInView
;; ! *******************************************************************
;; ! Проверяет находится ли точка в видовом экране
;; ! Auguments: 'pt'  — Точка для анализа в МСК!!!
;; ! Return   : T или nil если 'pt' в видовом экране или нет
;; ! *******************************************************************|;
(defun lib:IsPtInView (pt / VCTR Y_Len SSZ X_Pix Y_Pix X_Len Lc Uc)
(setq pt (trans pt 0 1))
(setq VCTR (getvar "VIEWCTR") Y_Len (getvar "VIEWSIZE")
   SSZ (getvar "SCREENSIZE")
   X_Pix (car SSZ) Y_Pix (cadr SSZ)
   X_Len (* (/ X_Pix Y_Pix) Y_Len)
   Lc (polar VCTR (dtr 180.0) (* 0.5 X_Len))
   Uc (polar Lc 0.0 X_Len)
   Lc (polar Lc (dtr 270.0) (* 0.5 Y_Len))
   Uc (polar Uc (dtr 90.0) (* 0.5 Y_Len)))
(if (and (> (car pt) (car Lc))(< (car pt) (car Uc))
   (> (cadr pt) (cadr Lc))(< (cadr pt) (cadr Uc)))
  T nil))
(defun DTR (a)(* pi (/ a 180.0)))
(defun RTD (a)(/ (* a 180.0) pi))
; ! ***********************************************************
;; !                             lib:Zoom2Lst
;; ! **********************************************************
;; ! Function : Zoom границ списка точек
;; ! Arguments: 'vlist' — Список точек в МСК!!!!
;; ! Зуммирует экран, чтобы все точки были видны
;; ! Returns  : t — было зуммирование nil — нет
;; ! **********************************************************
(defun lib:Zoom2Lst( vlist / bl tr Lst OS)
;(setq *MIP-ZOOM-PREV* nil)
(setq  Lst (lib:pt_extents vlist)
  bl (car Lst) tr (cadr Lst))
(if (not (and (lib:IsPtInView bl) (lib:IsPtInView tr)))
(progn  (setq OS (getvar "OSMODE"))(setvar "OSMODE" 0)
  (command "_.Zoom" "_Window" (trans bl 0 1)(trans tr 0 1)
    "_.Zoom" "0.95x")
 ;       (setq *MIP-ZOOM-PREV* 2)
  (setvar "OSMODE" OS)
  T) NIL))
;| ! ***************************************************************************
;; !           lib:pt_extents
;; ! ***************************************************************************
;; ! Function : Возвращает границы MIN, MAX X,Y,Z списка точек
;; ! Argument : 'vlist' — Список точек
;; ! Returns  : Список точек (ЛевНижн ПравВерхн)
;; ! ***************************************************************************|;
(defun  lib:pt_extents (vlist / tmp)
(setq tmp (mapcar '(lambda (x) (vl-remove-if 'null x))
 (mapcar '(lambda (what) (mapcar '(lambda (x) (nth what x)) vlist))
 '(0 1 2))));_setq
  (list (mapcar '(lambda(x)(apply 'min x)) tmp)(mapcar '(lambda(x)(apply 'max x)) tmp)));_defun
;https://www.caduser.ru/forum/topic30797.html
;Block Contour
(defun C:BC ( / *error* blk obj MinPt MaxPt hiden pt pl unnamed_block adoc tmp_blk adoc blks lays lay oname sel csp loc sc ec ret)
(defun *error* ( msg )(mapcar '(lambda(x)(vla-put-Visible x :vlax-true)) hiden)
  (vla-endundomark adoc)(if (and tmp_blk (vlax-write-enabled-p tmp_blk)(not(vlax-erased-p tmp_blk)))(vla-Erase tmp_blk))
  (foreach x loc (vla-put-lock x :vlax-true)))
(vl-load-com)
(if (zerop (getvar "WORLDUCS"))(progn(vl-cmdf "_.UCS" "")(vl-cmdf "_.Plan" "")))
(setq adoc (vla-get-ActiveDocument (vlax-get-acad-object))
        blks (vla-get-blocks adoc)
        lays (vla-get-layers adoc))
  (vla-startundomark adoc)(princ "\nВыберите объекты для построения контура")
 (if (setq sel (ssget))
    (progn
    (setq sel (mapcar 'vlax-ename->vla-object(vl-remove-if 'listp (mapcar 'cadr (ssnamex sel)))))
    (setq csp (vla-objectidtoobject adoc (vla-get-ownerid (car sel))))
    (setq unnamed_block (vla-add (vla-get-blocks adoc)(vlax-3d-point '(0. 0. 0.)) "*U"))
    (foreach x sel
        (setq oname (strcase (vla-get-objectname x))
              lay  (vla-item lays (vla-get-layer x)))
        (if (= (vla-get-lock lay) :vlax-true)
          (progn (vla-put-lock lay :vlax-false) (setq loc (cons lay loc))))
      (cond ((member oname '("ACDBVIEWPORT" "ACDBATTRIBUTEDEFINITION")) nil)
        ((= oname "ACDBBLOCKREFERENCE")
         (vla-InsertBlock unnamed_block
           (vla-get-insertionpoint x)(vla-get-name x)
           (vla-get-xscalefactor x)(vla-get-yscalefactor x)
           (vla-get-zscalefactor x)(vla-get-rotation x))
         (setq blk (cons x blk)))
        (t (setq obj (cons x obj))))
      );_foreach
        (setq lay  (vla-item lays (getvar "CLAYER")))
        (if (= (vla-get-lock lay) :vlax-true)(progn (vla-put-lock lay :vlax-false) (setq loc (cons lay loc))))
     (if obj (progn
         (vla-copyobjects
              (vla-get-activedocument (vlax-get-acad-object))
              (vlax-make-variant
                (vlax-safearray-fill
                  (vlax-make-safearray vlax-vbobject (cons 0 (1- (length obj))))
                  obj
          )
              )
              unnamed_block
            )
     )
       )
    (setq obj (append obj blk))
    (if obj (progn
          (setq tmp_blk (vla-insertblock csp (vlax-3d-point '(0. 0. 0.))(vla-get-name unnamed_block) 1.0 1.0 1.0 0.0))
          (vla-GetBoundingBox tmp_blk 'MinPt 'MaxPt)  ;_Границы блока
               (setq MinPt (vlax-safearray->list MinPt)
                     MaxPt (vlax-safearray->list MaxPt)
                     MinPt (mapcar '- MinPt '(10 10))
                     MaxPt (mapcar '+ MaxPt '(10 10)))
           (lib:Zoom2Lst (list MinPt MaxPt))
           (setq sset (ssget "_C" MinPt MaxPt))
(if sset (progn
      (setq hiden (mapcar 'vlax-ename->vla-object(vl-remove-if 'listp (mapcar 'cadr (ssnamex sset))))
        hiden (vl-remove tmp_blk hiden))
      (mapcar '(lambda(x)(vla-put-Visible x :vlax-false)) hiden)
      (setq pt (mapcar '+ MinPt '(5 5)))
      (vl-cmdf "_.RECTANG" (trans MinPt 0 1)(trans MaxPt 0 1))
      (setq pl (vlax-ename->vla-object(entlast)))
      (setq sc (1-(vla-get-count csp)))
      (if (VL-CATCH-ALL-ERROR-P (VL-CATCH-ALL-APPLY '(lambda ()
         (vl-cmdf "_-BOUNDARY" (trans pt 0 1) "")
              (while (> (getvar "CMDACTIVE") 0)(command "")))))
      (princ "\nНе удалось построить контур"))
      (setq ec (vla-get-count csp))
        (while (< sc ec)
      (setq ret (append ret (list (vla-item csp sc)))
        sc(1+ sc)))
      (setq ret (vl-remove pl ret))
      (mapcar '(lambda (x)(vla-Erase x)(vlax-release-object x))
          (list pl tmp_blk))
      (setq ret (mapcar '(lambda ( x / mipt)
         (vla-GetBoundingBox x 'MiPt nil)  ;_Границы блока
                 (setq MiPt (vlax-safearray->list MiPt))
         (list MiPt x)) ret))
      (setq ret (vl-sort ret '(lambda (e1 e2)(< (distance MinPt (car e1))(distance MinPt (car e2))))))
      (setq pl (nth 1 ret) ret (vl-remove pl ret))(mapcar 'vla-erase (mapcar 'cadr ret))
      (mapcar '(lambda(x)(vla-put-Visible x :vlax-true)) hiden)
      (foreach x loc (vla-put-lock x :vlax-true))
      (if pl (progn
      (initget  "Yes No")
      (if (= (getkword "\nУдалять объекты? [Yes/No] <No> : ") "Yes")
         (mapcar '(lambda (x) (if (vlax-write-enabled-p x)(vla-Erase x))) obj)))
    (princ "\nНе удалось построить контур"))
     ))))
     (VL-CATCH-ALL-APPLY '(lambda ()(mapcar 'vlax-release-object
    (list unnamed_block tmp_blk csp blks lays))))
     )
   );_if not
  (foreach x loc (vla-put-lock x :vlax-true))
  (vla-endundomark adoc)(vlax-release-object adoc)(princ))
(princ "\nНаберите в командной строке BC")

PS

> Юрий

> Август
Результаты тестирования сообщите в любом случае.

Re: Контур по блоку

Здорово! Строит общий контур для группы перекрывающихся (соприкасающихся) блоков. Но уж если придираться, то до конца smile
Не учитывается толщина полилинии. Соответственно контур получается Уже на половину толщины полилинии.
Но, думаю, нельзя же объять необъятное.
Буду использовать с указанием Вашего авторства (обязательно). И разрешите откланяться. Работа-с. И еще раз спасибо.

Re: Контур по блоку

> Юрий
Это работа команды BOUNDARY. Использу вес, толщина уже анахронизм.

Re: Контур по блоку

Последний вариант здесь https://www.caduser.ru/forum/topic32529.html

Re: Контур по блоку

Чего-то с текстами ета "BC" не хочет работать.

Re: Контур по блоку

т.е. с текстовыми примитивами.

Re: Контур по блоку

Ответил здесь https://www.caduser.ru/forum/topic32529.html

Re: Контур по блоку

Уважаемый VVA
а не могли бы Вы Вашу программу усовершенствовать,
очень есть большая потребность.
А именно, чтобы создавались контуры для 3-х мерных
объектов.
С уважением.

Re: Контур по блоку

> nemoi
Моя команда, это лишь "надстройка" для команды _BOUNDARY. Если boundary не делает контуры (скорее всего так), то и ECO (BC) не будет. Из 3-х мерных нужно делать 2d. Это или flatten из Express Tools или _Flatshot (плоский снимок), начиная с 2007.

Re: Контур по блоку

to VVA
Ваша программа прекрасно работает,
мне нужны координаты вершин контуров всего 3-х мерного объекта, и для этого подошла бы именно Ваша доработанная программка.
Я загоняю дальше, но если 3-д объект сделан с помощью 3-d face, проблем нет, но в случае с Solids и регионами, или посоветуйте как мне считать контуры (координаты) регионов.