Тема: LISP. Прерисовка полилинии с возможностью ее продолжения

Указываете полилинию и програма ее перерисовывает с (вроде) всеми свойствами исходной полилинии, исходная полилиния удаляется. Возможны глюки: функция коректно работает в мировой ПСК и так сказать паралельной ей.

(defun c:con_pline (/ ARC ELEVATIONS ENTITY ENTITY_LST
            LAST_POINT OLD_ANGDIR OLD_CMDECHO
            OLD_OSMODE OLD_PLINEWID OLD_PROPERTIS)
  (setq old_osmode (getvar "osmode"))
  (setq old_plinewid (getvar "plinewid"))
  (setq old_cmdecho (getvar "cmdecho"))
  (setq old_angdir (getvar "angdir"))
  (cond
  ((vl-catch-all-error-p
     (setq entity
(vl-catch-all-apply 'entsel
  '("\nSelect pline for continue: "))))
   (princ))
  ((not entity) (princ))
  ((not (eq "LWPOLYLINE" (cdr (assoc 0
    (setq entity_lst (entget (car entity)))))))
   (princ "\nThis not pline.") (princ))
  ((not (equal '(210 0.0 0.0 1.0)
           (assoc 210 entity_lst)))
   (princ "\nThis pline is not in WCS.") (princ))
  (t
  (setq old_propertis (+runa_mopc (car entity)))
  (setvar "cmdecho" 0)
  (setvar "angdir" 0)
  (setq elevations (list (cdr (assoc 38 entity_lst))))
  (entdel (car entity))
  (setq entity_lst (vl-remove-if-not
             (function
               (lambda (x)
             (member (car x)
                 '(10 40 41 42))))
             entity_lst)
    last_point (nth (- (length entity_lst) 4)
            entity_lst)
    entity_lst (reverse (cddddr
                  (reverse entity_lst))))
   (setvar "osmode" 0)
  (vl-cmdf "_pline")
  (mapcar
    (function (lambda (x)
      (cond
    ((= (car x) 10)
    (vl-cmdf (trans (append (cdr x) elevations) 0 1)))
    ((= (car x) 40) (vl-cmdf "_w" (cdr x)))
    ((= (car x) 41) (vl-cmdf (cdr x)))
    ((= (car x) 42)
     (cond
      ((zerop (cdr x)) (if arc (progn (vl-cmdf "_l")
                     (setq arc nil))))
      (arc (vl-cmdf "_a" (/ (* 720 (atan (cdr x))) pi)))
     (t (vl-cmdf "_a" "_a" (/ (* 720 (atan (cdr x))) pi))
       (setq arc t))
        ))
     )))
      entity_lst)
  (setvar "angdir" old_angdir)
  (setvar "cmdecho" old_cmdecho)
  (vl-cmdf (trans (cdr last_point) 0 1))
  (setvar "osmode" old_osmode)
  (while (+runa_bit_in_flag 1 (getvar "CMDACTIVE"))
    (vl-cmdf pause))
  (setvar "cmdecho" 0)
  (+runa_mopc old_propertis)
  (setvar "plinewid" old_plinewid)
  (setvar "cmdecho" old_cmdecho)
    )
   )
  )
(defun +runa_bit_in_flag (bit flag / )
;|
(+runa_bit_in_flag 1 3)
|;
  (= (logand bit flag) bit))
(defun +runa_mopc (ent_name /
            C_COLOR C_LAYER C_LINE_TYPE
            C_LINE_TYPE_SCALE
            C_LINE_WEIGHT OLD_PROPERTIS I)
;|
(+runa_mopc (car (entsel)))
(+runa_mopc (+runa_mopc (car (entsel))))
Reval - old propertis (layer linetype scale etc.)
|;
  (setq old_propertis (list (cons 8 (getvar "clayer"))
                (cons 6 (getvar "celtype"))
                (cons 62 (getvar "cecolor"))
                (cons 370 (getvar "celweight"))
                (cons 48 (getvar "celtscale"))
                ))
  (if (not (listp ent_name)) (setq ent_name (entget ent_name)))
  (setq c_layer (cdr (assoc 8 ent_name)))
  (setq c_line_type (if (setq i (assoc 6 ent_name))
              (cdr i) "BYLAYER"))
  (setq c_color
  (if (setq i (assoc 62 ent_name))
  (if (eq (type (setq i (cdr i))) 'STR) i (itoa i))
    "BYLAYER"))
  (setq c_line_weight (if (setq i (assoc 370 ent_name))
            (cdr i) -1))
  (setq c_line_type_scale (if (setq i (assoc 48 ent_name))
                (cdr i) 1.0))
  (setvar "clayer" c_layer)
  (setvar "celtype" c_line_type)
  (setvar "cecolor" c_color)
  (setvar "celweight" c_line_weight)
  (setvar "celtscale" c_line_type_scale)
  old_propertis
  )

Две последние функции - так сказать библиотечные. Коментарии - крякозяблы пришлось вырезать.
Вызов функции _CON_PLINE
Макрос ^C^C_con_pline
и т.д.
Перед вызовом нужно загрузить все три функции.
ЗЫ. Похоже влезло как надо. Ваши выводы господа?

Re: LISP. Прерисовка полилинии с возможностью ее продолжения

Нарисовал замкнутую полилинию, загрузил Лисп-файл, ввел команду con_pline. Последний (замыкающий) сегмент исчез и пошло продолжение построения полилинии. Однако замкнуть пришлось с помощью "_pedit" ("полред"). Команда отмены отменила и нарисованную исходную полилинию, нехорошо. Если же последний сегмент был дуговой, то и продолжение рисуется дугой. А если нужен линейный сегмент?

Re: LISP. Прерисовка полилинии с возможностью ее продолжения

ИМХО, ИМХО...
Может, поменять немного алгоритм?
1. Проверить lwpolyline на замкнутость (не помню я сейчас dxf-кода). Если замкнута, запрос на разрыв в последней вершине.
2. Получить последнюю вершину lwpolyline, а также настройки последнего сегмента.
3. Дать команду "_.pline", с последней точки, с настройками последнего сегмента. Выполнять ее по циклу (vl-cmdf pause).
4. После выхода из цикла применить "_.pedit" "_m", в качестве выбора - последний примитив + предыдущая полилиния, "_join" "0" "".
---
еще раз - имхо.

Re: LISP. Прерисовка полилинии с возможностью ее продолжения

> Владимир Громов
Но зато ведь работает.)
Спасибо за отзыв.
Ну продолжить замкнутую полилинию нельзя - это уже логика. Замкнуть можна обычной опцией _C
Если нужно продолжить полилинию прямолинейным участком тогда опция _L, дугой - _A.
А вот насчет отмены я не подумал, надо будет что то придумать.
>kpblc
можно и так, но мне было интересно разобратся с построением полилинии с дуговыми сегментами. Кстати есть опция UNDO которая будет доступна при моей функции.
Я вот думаю как бы еще научить функцию задом наперед чертить, тогда и насчет отмены подумаю.

Re: LISP. Прерисовка полилинии с возможностью ее продолжения

> kpblc
Да насчет замкнусти тоже нужно будет подумать...

Re: LISP. Прерисовка полилинии с возможностью ее продолжения

Ну насчет отмены все достаточно просто - можешь посмотреть любой мой лиспик, там такое, как правило, есть (через ActiveX-функции). Единственное - для гарантии работы вначале имхо можно было бы воткнуть (vl-load-com) - пару раз требовалось на 2005-м - тот почему-то не подхватывал сразу vl*.
Насчет "задом наперед" - можно посмотреть на http://www.kurganobl.ru/cad/book.jsp?id … ;tn=main#b - там задачи ревера рассмотрены. Дополнительные лиспы там, по-моему, есть. Если нет - прошу в почту, пообщаемся ;)

Re: LISP. Прерисовка полилинии с возможностью ее продолжения

> kpblc
Спасибо за помощь. Похоже то что нужно. Только плохо понимаю я все эти RU_ хоть и книгу читал :)

Re: LISP. Прерисовка полилинии с возможностью ее продолжения

Давай по почте, ок? Пиши

Re: LISP. Прерисовка полилинии с возможностью ее продолжения

> Runa
Если нужны реверсы без "ру" могу дать...

Re: LISP. Прерисовка полилинии с возможностью ее продолжения

> Runa
Точно, опции полилинии работают, это хорошо. Надо бы в коментариях в начале кода об этом упомянуть или еще как-то.

Re: LISP. Прерисовка полилинии с возможностью ее продолжения

> Евгений Елпанов
спасибо не надо, уже дали пока с интернетом у меня были проблемы.

> Владимир Громов
надо было, но я не подумал. Кстати ведь стандартный запрос полилинии с опциями в коммандной строке должен быть если cmdecho = 1
Я вот думаю может не стоит вылизывать именно эту функцию, но немного я ее доделаю позднее. Есть у меня затея насчет редактора полилинии и эта функция будет одной из опций новой функции и там уже будет нужно подумать и насчет реверса.

Re: LISP. Прерисовка полилинии с возможностью ее продолжения

Не удержался и доделал сегодня, спасибо всем за помощь.

(defun c:con_pline (/ ARC ELEVATIONS ENTITY ENTITY_LST
            LAST_POINT OLD_ANGDIR OLD_CMDECHO
            OLD_OSMODE OLD_PLINEWID OLD_PROPERTIS
            closed)
  (if (not *kpblc-activedoc*)
    (setq *kpblc-activedoc*
      (vla-get-activedocument
        (vlax-get-acad-object)
        );_end of vla-get-activedocument
      );_end of vlax-get-acad-object
    );_end of if
  (vla-endundomark *kpblc-activedoc*)
  (vla-startundomark *kpblc-activedoc*)
  (setq old_osmode (getvar "osmode"))
  (setq old_plinewid (getvar "plinewid"))
  (setq old_cmdecho (getvar "cmdecho"))
  (setq old_angdir (getvar "angdir"))
  (cond
  ((/= 0 (last (getvar "ucsxdir")) (last (getvar "ucsydir")))
   (princ "\nCannot continue in this UCS.")
   (princ)
   )
  ((vl-catch-all-error-p
     (setq entity
(vl-catch-all-apply 'entsel
  '("\nSelect pline for continue: "))))
   (princ))
  ((not entity) (princ))
  ((not (eq "LWPOLYLINE" (cdr (assoc 0
    (setq entity_lst (entget (car entity)))))))
   (princ "\nThis not pline.") (princ))
  ((not (equal '(210 0.0 0.0 1.0)
           (assoc 210 entity_lst)))
   (princ "\nThis pline is not in WCS.") (princ))
  ((cond
     ((+runa_bit_in_flag 1 (cdr (assoc 70 entity_lst)))
      (if (progn
    (initget "Yes No")
    (vl-catch-all-error-p
    (setq closed
    (vl-catch-all-apply 'getkword
    '("\nPolyline is closed, continue [Yes/No] <Yes>:")))))
    t (cond
          ((not closed) nil)
          ((eq closed "Yes") nil)
          (t t)
          ))
      )
     (t nil)
     )
   (princ "\nEnd function.")(princ))
  (t
  (setq old_propertis (+runa_mopc (car entity)))
  (setvar "cmdecho" 0)
  (setvar "angdir" 0)
  (setq elevations (list (cdr (assoc 38 entity_lst))))
  (entdel (car entity))
  (setq entity_lst (vl-remove-if-not
             (function
               (lambda (x)
             (member (car x)
                 '(10 40 41 42))))
             entity_lst)
    last_point (nth (- (length entity_lst) 4)
            entity_lst)
    entity_lst (reverse (cddddr
                  (reverse entity_lst))))
   (setvar "osmode" 0)
  (vl-cmdf "_pline")
  (mapcar
    (function (lambda (x)
      (cond
    ((= (car x) 10)
    (vl-cmdf (trans (append (cdr x) elevations) 0 1)))
    ((= (car x) 40) (vl-cmdf "_w" (cdr x)))
    ((= (car x) 41) (vl-cmdf (cdr x)))
    ((= (car x) 42)
     (cond
      ((zerop (cdr x)) (if arc (progn (vl-cmdf "_l")
                     (setq arc nil))))
      (arc (vl-cmdf "_a" (/ (* 720 (atan (cdr x))) pi)))
     (t (vl-cmdf "_a" "_a" (/ (* 720 (atan (cdr x))) pi))
       (setq arc t))
        ))
     )))
      entity_lst)
  (setvar "angdir" old_angdir)
  (setvar "cmdecho" 1)
  (vl-cmdf (trans (cdr last_point) 0 1))
  (setvar "osmode" old_osmode)
  (while (+runa_bit_in_flag 1 (getvar "CMDACTIVE"))
    (vl-cmdf pause))
  (setvar "cmdecho" 0)
  (+runa_mopc old_propertis)
  (setvar "plinewid" old_plinewid)
  (setvar "cmdecho" old_cmdecho)
    )
   )
  (vla-endundomark *kpblc-activedoc*)
  (princ)
  )
+runa_mopc

и

+runa_bit_in_flag

см. выше.

> kpblc
коментарии пришлось вытереть - при копировании стали крякозяблами,  и отдельное спасибо за поддержку.
ЗЫ. Вроде работает нормально а вот реверс полилинии здесь не куда засунуть, на мой взгляд чем меньше запросов, тем лучше.

Re: LISP. Прерисовка полилинии с возможностью ее продолжения

Насчет реверса - может быть, может быть. Хотя на самом деле можно и подправить.
По поводу комментариев: лисп сохранить и открыть блокнотом, ctrl+с -> ctrl+v, все на месте. Сам матерился как не знаю кто. Ладно, бог с ним.
По поводу реверса: если рисование идет нестандартными типами линий (например, с буквами), то может и понадобиться (хотя тут не уверен), поскольку в таком случае вся полилиния будет отрисована этим типом в одном направлении. Уж анализ этого - извини, мозгов не хватат. Можно, конечно, попробовать использовать (tblnext "LTYPE"), но что там будет и как отображаться - я мимо.
Кстати, спасибо, конечно, за использование *kpblc-activedoc*, но вообще-то можно и свое имя взять ;) - например, *runa-activedoc* - главное, чтобы имя было достаточно уникальным, легко запоминающимся и отображающим суть содержимого в нем.

Re: LISP. Прерисовка полилинии с возможностью ее продолжения

Забыл в начале всунуть строчку (vl-load-com) и
я там еще ввел ограничение на ПСК чтобы полилиния не перерисовалось в другой системе координат но не для всех случаев это сработает :(
>kpblc насчет типа линии с буквами я даже и не думал, просто хотелось иметь возможность продолжать полилинию с первой точки, но зато теперь точно понятно что реверс полилинии должен быть отдельной функцией, можна будет даже при необходимости задействовать в con_pline но два раза для того чтобы вернуть назад порядок типа линии. А имя переменной потом для себя переименую, у меня где то была функция которая сохраняла несколько глобальных переменных, только нужно будет ее еще найти.

Re: LISP. Прерисовка полилинии с возможностью ее продолжения

Ну а какие должны быть глобальными переменные? указатель на текущий кад, на документ, замена обработки ошибки, указатель на пространство модели и листа (и то не факт), что еще? Возможно, список системных переменных (но по идее его надо держать только до момента возврата обрабочика ошибок на место - т.е. нечто наполовину глобальное)... все, вроде. В стартере прописать можно. И на всех функциях, вызываемых из меню, например, можно проверять на наличие гарантированно глобальной переменной, т.е. нечто типа:

(defun appstarter()
  (setq *kpblc-activedoc* (vla-get-activedocument (vlax-get-acad-object))
    *kpblc-model-space* (vla-get-modelspace *kpblc-activedoc*)
    *kpblc-layout-space* (vla-get-layout *kpblc-activedoc*)
    )
  ;; Загрузка дополнительных лиспов, fas etc
  )

И на макрос повесить:

^C^C(if (not *kpblc-activedoc*) (load "appstarter.lsp"));(Функция_с_параметрами);

---
ИМХО. В "САПР на базе..." подход принципиально другой.

Re: LISP. Прерисовка полилинии с возможностью ее продолжения

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

Re: LISP. Прерисовка полилинии с возможностью ее продолжения

Сейчас пересмотрел эту тему:
https://www.caduser.ru/forum/topic20243.html
Как раз у kpblc в его программе предлагается новую вершину растянуть в любое место. IMHO, это почти то, о чем я писал (добавление новых сегментов в разрыве полилинии).

Re: LISP. Прерисовка полилинии с возможностью ее продолжения

> kpblc
У меня было почти то же самое, когда начинал разбиратся с vla-* но потом я вернулся к так сказать чистому лиспу. А вот с обработчиком ошибок я ни как разобратся не могу, могу только стырять а правильно применить вряд ли смогу :(

> Владимир Громов
Правильно реверс именно для этого. Насчет добавления вершин еще подумаю но это будет отдельная функция, точно будет можно выбраный сегмент сделать дуговым или прямым. Но сделать красивое добавление вершины или дуги у меня не получится, и еше пока не могу добить выбор полилинии за один щелчек :( думал (osnap (last (getpoint)) "nea") но иногда точка привязывается к другому объекту а для (ssget ":E") нельзя задать точку (я бы почистил набор и тогда оснап срабатывал надежнее)
И впоследний раз, чтобы никто не ворчал что можно полилинии на блокированом слое выбирать :)

(defun c:con_pline (/ ARC ELEVATIONS ENTITY ENTITY_LST
            LAST_POINT OLD_ANGDIR OLD_CMDECHO
            OLD_OSMODE OLD_PLINEWID OLD_PROPERTIS
            closed)
;|
Перерисовка полилинии с возможностью продолжения команды pline
|;
  (if (not *kpblc-activedoc*)
    (setq *kpblc-activedoc*
      (vla-get-activedocument
        (vlax-get-acad-object)
        );_end of vla-get-activedocument
      );_end of vlax-get-acad-object
    );_end of if
  (vla-endundomark *kpblc-activedoc*)
  (vla-startundomark *kpblc-activedoc*)
  (setq old_osmode (getvar "osmode"))
  (setq old_plinewid (getvar "plinewid"))
  (setq old_cmdecho (getvar "cmdecho"))
  (setq old_angdir (getvar "angdir"))
  (cond
  ((/= 0 (last (getvar "ucsxdir")) (last (getvar "ucsydir")))
   (princ "\nCannot continue in this UCS.")
   (princ)
   )
  ((vl-catch-all-error-p
     (setq entity
(vl-catch-all-apply 'entsel
  '("\nSelect pline for continue: "))))
   (princ))
  ((not entity) (princ))
  ((not (eq "LWPOLYLINE" (cdr (assoc 0
    (setq entity_lst (entget (car entity)))))))
   (princ "\nThis not pline.") (princ))
  ((+runa_bit_in_flag 4
     (cdr (assoc 70
      (entget (tblobjname "layer"
    (cdr (assoc 8
    (setq entity_lst (entget (car entity))))))))))
   (princ "\nPline is on the locked layer.") (princ))
  ((not (equal '(210 0.0 0.0 1.0)
           (assoc 210 entity_lst)))
   (princ "\nThis pline is not in WCS.") (princ))
  ((cond
     ((+runa_bit_in_flag 1 (cdr (assoc 70 entity_lst)))
      (if (progn
    (initget "Yes No")
    (vl-catch-all-error-p
    (setq closed
    (vl-catch-all-apply 'getkword
    '("\nPolyline is closed, continue [Yes/No] <Yes>:")))))
    t (cond
          ((not closed) nil)
          ((eq closed "Yes") nil)
          (t t)
          ))
      )
     (t nil)
     )
   (princ "\nEnd function.")(princ))
  (t
  (setq old_propertis (+runa_mopc (car entity)))
  (setvar "cmdecho" 0)
  (setvar "angdir" 0)
  (setq elevations (list (cdr (assoc 38 entity_lst))))
  (entdel (car entity))
  (setq entity_lst (vl-remove-if-not
             (function
               (lambda (x)
             (member (car x)
                 '(10 40 41 42))))
             entity_lst)
    last_point (nth (- (length entity_lst) 4)
            entity_lst)
    entity_lst (reverse (cddddr
                  (reverse entity_lst))))
   (setvar "osmode" 0)
  (vl-cmdf "_pline")
  (mapcar
    (function (lambda (x)
      (cond
    ((= (car x) 10)
    (vl-cmdf (trans (append (cdr x) elevations) 0 1)))
    ((= (car x) 40) (vl-cmdf "_w" (cdr x)))
    ((= (car x) 41) (vl-cmdf (cdr x)))
    ((= (car x) 42)
     (cond
      ((zerop (cdr x)) (if arc (progn (vl-cmdf "_l")
                     (setq arc nil))))
      (arc (vl-cmdf "_a" (/ (* 720 (atan (cdr x))) pi)))
     (t (vl-cmdf "_a" "_a" (/ (* 720 (atan (cdr x))) pi))
       (setq arc t))
        ))
     )))
      entity_lst)
  (setvar "angdir" old_angdir)
  (setvar "cmdecho" 1)
  (vl-cmdf (trans (cdr last_point) 0 1))
  (setvar "osmode" old_osmode)
  (while (+runa_bit_in_flag 1 (getvar "CMDACTIVE"))
    (vl-cmdf pause))
  (setvar "cmdecho" 0)
  (+runa_mopc old_propertis)
  (setvar "plinewid" old_plinewid)
  (setvar "cmdecho" old_cmdecho)
    )
   )
  (vla-endundomark *kpblc-activedoc*)
  (princ)
  )

Re: LISP. Прерисовка полилинии с возможностью ее продолжения

Владимир Громов пишет:

Вот бы еще разорвать полилинию в любом месте, добавить сегменты и и все объединить.

См. INSPL в https://www.caduser.ru/forum/topic20243.html