Тема: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

Предлагается дополнительная панель с кнопками для опций и новых
команд при работе с полилинией. При использовании AutoCAD 2004, 2005
строки меню можно скопировать в файлы acad.mns или (и) acad.mnu.
При использовании AutoCAD 2006 придется вручную создать панель и
кнопки в acad.cui.
Фрагмент меню.

**TB_PL_OPTION
[_Toolbar("Опции полилинии", _Floating, _Show, 497, 92, 1)]
[_Button("Полилиния", RCDATA_16_PLINE, RCDATA_16_PLINE)]^C^C_pline
[_Button("Ширина", "width.bmp", "width.bmp")]_W
[_Button("Дуговой сегмент", "arc.bmp", "arc.bmp")]_Arc
[_Button("2-я точка дуги", "second.bmp", "second.bmp")]_S
[_Button("Линейный сегмент", "line.bmp", "line.bmp")]_L
[_Button("Замкнуть", "close.bmp", "close.bmp")]_CL
[_Button("Отменить последний сегмент", "undo.bmp", "undo.bmp")]_U
[--]
[_Button("Редактировать полилинию", RCDATA_16_PEDIT, RCDATA_16_PEDIT)]^C^C_pedit
[--]
[_Button("Полилиния из независимых сегментов", "lw_one.bmp", "lw_one.bmp")]^C^C^P(if (not C:PL_ONE) (load "pl_one")) PL_ONE
[_Button("Добавить вершину в полилинию", "lw_vert.bmp", "lw_vert.bmp")]^C^C^P(if (not C:PLINE_STR) (load "pline_str")) PLINE_STR
[_Button("Заменить линейный сегмент дуговым", "lw_arc.bmp", "lw_arc.bmp")]^C^C^P(if (not C:LW_ARC) (load "lw_arc")) LW_ARC
[_Button("Заменить дуговой сегмент линейным", "lwarc_line.bmp", "lwarc_line.bmp")]^C^C^P(if (not C:LWARC_LINE) (load "lwarc_LINE")) LWARC_LINE

Коды программ.
Полилиния из независимых сегментов. Сохранить в файле pl_one.lsp

;************ pl_one.lsp *************************************************************
;          Отрисовка непрерывной полилинии с независимыми сегментами.
;          Автор Владимир Громов.
;
(defun C:PL_ONE ( / wdt1 wdt tn flag tk)
      (setvar "cmdecho" 0)
      (setq wdt1 (getvar "PLINEWID"))
      (princ "\n Ширина сегментов полилинии <") (princ wdt1) (princ ">: ")
      (setq wdt (getreal))
      (if (= wdt nil) (setq wdt wdt1))
      (setvar "PLINEWID" wdt)
      (setq tn (getpoint "\n Укажите начальную точку сегмента полилинии (ENTER-отказ): "))
(if tn
    (progn
    (setq flag T)
    (while flag
          (if flag
              (progn
              (setq tk (getpoint tn "\n Укажите следующую точку (ENTER-Конец): "))
              (if tk
              (progn
              (command "_PLINE" tn tk "")
              (setq tn tk)
              ); progn
              (setq flag nil)
              ); progn
              ); if
           ); if
    );while
    ) ;progn
    (princ "\n Отказ.")
); if
    (princ)
)

Добавить вершину в полилинию. Сохранить в файле pline_str.lsp

;********************* pline_str.lsp ***************************************************
;      Автор участник конференции под ником kpblc
;
(defun kpblc-stretch-pline (/ break_point _osmode_ selset_oper break_ent break_ent_type)
 ;; Определения локальных функций
  ;; Собственно разрыв и дополнительный одновременный _.stretch.
  ;; Параметры:
  ;; ent_pline  - ссылка на разрываемый объект, аналог (entsel)
  ;; ent_type  - тип объекта: nil -> lwpolyline; t -> line
  ;; объект обратно в LINE не разбивается
  (defun _kpblc-break-pline (ent-pline ent-type break-point)
    (command "_.break" ent-pline break-point break-point)
    (command "_.pedit" "_M" "_C" break-point break-point "")
    ;; Здесь определяем по ent_type - чего делать дальше
    (if  ent-type
      (command "_yes")
      ) ;_ end of if
    (command "_join" 0 "")
    (command "_.stretch" "_C" break-point break-point "" break-point (getpoint break_point "Укажите новую точку : "))
    ) ;_ end of defun
  ;; Конец определения локальных функций
  (vl-load-com)
  (if (not *kpblc-activedoc*)
    (setq *kpblc-activedoc* (vla-get-activedocument (vlax-get-acad-object)))
    ) ;_ end of if
  (vla-endundomark *kpblc-activedoc*)
  (vla-startundomark *kpblc-activedoc*)
  (setq  _osmode_ (getvar "osmode")
  ) ;_ end of setq
  (setvar "osmode" 512)
  ;; Обработка пустого выбора
  (while (not (setq break_point  (getpoint "\nУкажите точку разрыва : ")
        selset_oper  (ssget break_point)
        ) ;_ end of setq
        ) ;_ end of not
   ) ;_ end of while
  ;; Теперь проверка на вшивость - в смысле, на правильность выбора
  ;; Вынесено специально в отдельный setq, а также введена дополнительная
  ;; локальная переменная определения типа разрываемого объекта
  (setq  break_ent      (ssname selset_oper 0)
  break_ent_type (cdr (assoc 0 (entget break_ent)))
  ) ;_ end of setq
  (cond
    ((or (= break_ent_type "LWPOLYLINE") (= break_ent_type "POLYLINE"))
     (progn
       (_kpblc-break-pline break_ent nil break_point)
       ) ;_ end of progn
     )
    ((= break_ent_type "LINE")
     (_kpblc-break-pline break_ent t break_point)
     )
    (t (alert "Добавить вершину к выбранному примитиву невозможно!"))
    ) ;_ end of cond
  (setvar "osmode" _osmode_)
  (vla-endundomark *kpblc-activedoc*)
  (princ)
  ) ;_ end of defun
(defun c:pline_str ()
  (kpblc-stretch-pline)
  ) ;_ end of defun

Этот вариант программы программы я использую в своей работе. Обсуждение и другие варианты
можно посмотреть здесь:
https://www.caduser.ru/forum/topic20243.html
Заменить линейный сегмент дуговым. Сохранить в файле lw_arc.lsp

;**************** lW_arc.lsp *************************************
;                Замена линейного сегмента в полилинии
;                дуговым сегментом.
;                Автор  Евгений Елпанов.
(defun C:LW_ARC(/ A1 ENT GR I LST LW PAR PT)
(vl-load-com)
(vl-cmdf "_.undo" "_be")
(setq lw(entsel "\n Выберите нужный сегмент в полилинии. "))
(if(and lw(=(cdr(assoc 0(entget(car lw)))) "LWPOLYLINE"))
(progn(setq par  (vlax-curve-getParamAtPoint(car lw)
(vlax-curve-getClosestPointTo(car lw)(cadr lw)))
a1(angle(vlax-curve-getPointAtParam(car lw)(fix par))
(vlax-curve-getPointAtParam(car lw)(1+(fix par)))))
(princ "\n Задайте визуально кривизну сегмента. ")
(while(and(setq gr(grread 5))(=(car gr) 5))
(setq i 0 lst nil ent(entget(car lw)))
(while(or(/=(caar ent) 42)
(if(< i(fix par))(setq i(1+ i))))
(setq  lst(cons(car ent) lst)ent(cdr ent)))
(redraw)
(grdraw(setq pt(vlax-curve-getPointAtParam
(car lw)(fix par)))(cadr gr) 6 1)
(entmod(append(reverse(cons(cons 42
(/(sin(/(- a1(angle pt(cadr gr)))2.))
(cos(/(- a1(angle pt(cadr gr)))2.))))lst))
(cdr ent)))(entupd(car lw))))
(princ "\n Ничего не выбрано или объект не полилиния. "))
(vl-cmdf "_.undo" "_e")
(redraw)
(princ)
)

Заменить дуговой сегмент линейным. Сохранить в файле lwarc_line.lsp

;**************** lwarc_line.lsp *************************************
;                Замена дугового сегмента в полилинии
;                линейным сегментом.
;                Автор  Евгений Елпанов.
(defun C:LWARC_LINE (/ lw)
(setq lw(entsel"\n Выберите нужный дуговой сегмент в полилинии:"))
(if(and lw(=(cdr(assoc 0(entget(car lw))))"LWPOLYLINE"))
(progn(vla-StartUndoMark(vla-get-activedocument(vlax-get-acad-object)))
(vl-load-com)(vla-SetBulge(vlax-ename->vla-object(car lw))
(fix(vlax-curve-getParamAtPoint(car lw)
(vlax-curve-getClosestPointTo(car lw)(cadr lw))))0.)
(vla-EndUndoMark(vla-get-activedocument(vlax-get-acad-object))))
(princ"\n Ничего не выбрано или объект не полилиния."))
(princ)
)

Пиктограммы

RCDATA_16_PLINE и RCDATA_16_PEDIT

являются стандартными.
Пиктограммы

width.bmp arc.bmp second.bmp line.bmp close.bmp undo.bmp
lw_one.bmp lw_vert.bmp lw_arc.bmp lwarc_line.bmp

необходимо сделать самостоятельно. У меня есть свои простенькие
пиктограммы. При желании я могу их выложить на webfile.ru.

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

> Владимир Громов
>" У меня есть свои простенькиепиктограммы."
Если есть желание - могу засунуть твои картинки в программу, которая будет создавать из лиспа *.bmp в указанной директории (недавно какраз занимался такими задачами)...

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

При желании я могу их выложить на webfile.ru

Можно закодировать (например в Base64 Тотал Коммандером) и выложить сюда как текст :))

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

> Евгений Елпанов
Ну, я-то предполагал, что эти 10 файлов *.bmp просто расположить в папке в пути доступа (там же, где и программы), - да и все.
А как это засунуть картинки в программу?

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

> VK
Это я не умею...

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

> Владимир Громов
Вот лисп создающий список из прочитанного файла 2.bmp:

(setq f (open "d:\\2.bmp" "r"))
(setq x (vl-string->list (read-line f)))
(close f)

т.е. этот список можно без потерь сохранить в текстовом виде. Далее, как ты наверное догадался, этот список можно превратить в файл - например моя старенькоя иконка с очень известным макросом
"^C^C_Lengthen;\;_Dimangular;@;_Text;$m=$(Getvar,Perimeter);\"...

(setq f (open "d:\\2_new.bmp" "w")) (write-line (vl-list->string
'(66 77 54 3 0 0 0 0 0 0 54 0 0 0 40 0 0 0 16 0 0 0 16 0 0 0 1 0 24 0 0 0 0 0
  0 3 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 255 216 233 236 216 233 236 216
  233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233
  236 216 233 236 216 233 236 216 233 236 216 233 236 0 0 255 0 0 255 0 0 255
  0 0 255 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233
  236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 0 0 255 0 0
  255 0 0 255 0 0 255 0 0 255 216 233 236 216 233 236 216 233 236 216 233 236
  216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216
  233 236 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 216 233 236 216 233
  236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236
  216 233 236 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255
  216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216
  233 236 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0
  255 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236
  216 233 236 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255
  0 0 255 0 0 255 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236
  0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0
  255 0 0 255 0 0 255 216 233 236 216 233 236 216 233 236 216 233 236 0 0 255
  0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 255 0 0 0 216 233 236
  216 233 236 0 0 255 216 233 236 216 233 236 216 233 236 216 233 236 216 233
  236 216 233 236 0 0 0 0 0 255 0 0 255 0 0 255 0 0 255 216 233 236 0 0 0 216
  233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233
  236 216 233 236 216 233 236 0 0 0 216 233 236 216 233 236 0 0 255 216 233
  236 216 233 236 216 233 236 0 0 0 216 233 236 216 233 236 216 233 236 216
  233 236 216 233 236 216 233 236 216 233 236 0 0 0 216 233 236 216 233 236
  216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 0 0
  0 0 0 0 216 233 236 216 233 236 216 233 236 0 0 0 0 0 0 216 233 236 216 233
  236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236
  216 233 236 216 233 236 216 233 236 0 0 0 0 0 0 0 0 0 216 233 236 216 233
  236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236
  216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216
  233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233
  236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236
  216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216
  233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233
  236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236
  216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216 233 236 216
  233 236 216 233 236 216 233 236
 ))f)(close f)

Блин... Кажется это длинновато для передачи картинок в двоичном виде, хотя этот пример, наверняка будет кому-нибудь интересен!

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

> Евгений Елпанов
Смысл в общем понял. Но я на всякий случай загнал на webfile.ru файл BMP.bmp. Это самораспаковывающийся архив RAR (BMP.exe), переименованный в BMP.bmp. Для распаковки надо переименовать его назад в EXE.
http://webfile.ru/683647
Имя файла - BMP.bmp , размер 99 Кбайт. Файлу присвоен номер 683647, он будет доступен до 18.12.2005 19:28.

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

Кстати, хочу всем пояснить по поводу чтения двоичных данных:
Если функция чтения файла наткнется на (chr 26) - символ конца файла - дальше файл читаться не будет!
и еще:
символы 10 "\n" и 13 "\r" будут читаться как 0
Но это не мешает с помощью лиспа записывать в файл любые из перечисленных символов в любых количествах...

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

oops
>"символы 10 "\n" и 13 "\r" будут читаться как 0"
Будут читаться как новая строка, т.е. файл прочтется только до первого из этих символов, а дальше нужно читать с новой строки!

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

Еще одна новая опция.
Изменение ширины отдельного сегмента полилинии.

[_Button("Изменить ширину сегмента", "lw_width.bmp", "lw_width.bmp")]^C^C^P(if (not C:LW_WIDTH) (load "lw_width")) LW_WIDTH

Код программы. Сохранить в файле lw_width.lsp

  ;**************** lw_width.lsp *********************************
  ;  Изменение начальной и конечной ширины
  ;  произвольного сегмента полилинии.
  ;  Автор  Евгений Елпанов.
(defun C:LW_WIDTH(/ ENDWIDTH GR LW PAR STARTWIDTH)
(vl-load-com)
(vla-StartUndoMark(vla-get-activedocument(vlax-get-acad-object)))
(setq lw(entsel "\n Выберите нужный сегмент в полилинии. "))
(if(and lw(=(cdr(assoc 0(entget(car lw)))) "LWPOLYLINE"))
(progn(setq par(vlax-curve-getParamAtPoint(car lw)
(vlax-curve-getClosestPointTo(car lw)(cadr lw)))
 lw(vlax-ename->vla-object(car lw)))
(princ "\n Задайте ширину начала сегмента.\t")
(vla-GetWidth lw(fix par) 'StartWidth 'EndWidth)
(while(and(setq gr(grread 5))(=(car gr) 5))
(vla-SetWidth lw(fix par)
(setq StartWidth(*(distance(cadr gr)
(vlax-curve-getClosestPointTo lw(cadr gr))) 2.))EndWidth))
(if(=(car gr) 2)(vla-SetWidth lw(fix par)
(setq StartWidth(atof(strcat(princ(vl-list->string(cdr gr)))
(getstring)))) EndWidth))
(princ "\n Задайте ширину конца сегмента.\t")
(while(and(setq gr(grread 5))(=(car gr) 5))
(vla-SetWidth lw(fix par) StartWidth(*(distance(cadr gr)
(vlax-curve-getClosestPointTo lw(cadr gr))) 2.)))
(if(=(car gr) 2)(vla-SetWidth lw(fix par) StartWidth
(atof(strcat(princ(vl-list->string(cdr gr)))(getstring))))))
(princ "\n Ничего не выбрано или объект не полилиния.\t"))
(vla-EndUndoMark(vla-get-activedocument(vlax-get-acad-object)))
(princ)
)

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

(C:LW_WIDTH) корректно работает только в WCS...

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

Вообще-то, я предполагал изначально, что работа со всеми новыми опциями полилинии, как с плоским объектом, будет выполняться в Мировой системе координат. А есть примеры работы с полилинией не в МСК (WCS)?

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

> Kosarev
Для работы с LWPOLYLINE в других системах координат нужна дополнительная функция, которая будет временно менять на WCS, причем это нужно для любой работы с LWPOLYLINE и не относится к какой либо отдельной програме...
Хотя, критика правильная и заслуженная:)

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

;Вставка узла в полилинию, отрезок, дугу разрывом в точке и добавлением нового сегмента к полилинии.
;Удаление узла из полилинии
;Преобразование сегмента полилинии в дугу<->отрезок
(vmon)
;----------------------------------
(DEFUN INSERTP ( txt / TipE priv tv name)
  (setq priv(getvar "osmode"))
  (setvar "osmode"  562) ;-- Привязка Середина (2), 562->+Пересечение(32),+Квадрант(16),+Ближайшая(512)
  (setvar "CMDECHO" 0)   ;-- подавление ЭХА команд Автокада в Лиспе
  (command "_break"(setq Name(entsel txt))"\_f"(setq tv(getpoint))"\@");разрыв в точке
  (setq name(car name)
        TipE(CDR(ASSOC 0(ENTGET name))))
  (cond ;добавление к полилинии "нового" ПОСЛЕДНЕГО куска
    ((OR(= TipE "LINE")(= TipE "ARC"))(command "_pedit" name "_Y" "_J" (ssget "_L") "" ""))
    ((= TipE "LWPOLYLINE")            (command "_pedit" name      "_j" (ssget "_L") "" ""))
    (T(progn(Princ "\nСоздание ПОЛИЛИНИИ не возможно")(command "_Undo" "")))
  )
  (setvar "osmode" priv)
  (setq TvName(list tv name));для переноса переменных во внешний модуль
)
;----------------------------------
(defun ARC_LINE (/ tv name);Модуль преобразования сегмента полилинии в дугу-отрезок
   (setq TvName(INSERTP "\nУкажите полилинию для преобразования сегментов ДУГА-ЛИНИЯ:"));!!!!!!!!!!!!!Добавление вершины на указанный сегмент
   (setq tv(nth 0 TvName)Name(nth 1 TvName));восстановление переменных для переноса в другой модуль
   (DELV tv name "ДугОтр");!!!!!!!!!!!!!!!!Удаление вершины с преобразованием типа сегмента ДУГА-ОТРЕЗОК
)
;----------------------------------
;Удаление вершины
(defun DELV(tv name Var / nn nnspis spnn newspis newk kod kolv newkolv vardel)
(if(= tv nil)
  (progn
      (setq priv(getvar "osmode"));Сохранение текущего режима привязки
      (setvar "osmode"  1)       ;-- Привязка КОНточка
      (setvar "CMDECHO" 0)    ;-- подавление ЭХА команд Автокада в Лиспе
      (setq Name   (car(entsel "\nУкажите полилинию для удаления вершин"))
            PrSpis (entget Name);Список описания примитива
        tv     (getpoint "\nУкажите точку для удаления из ПОЛИЛИНИИ");
      );s
  );pr
);if
(setq tv(list 10(nth 0 tv)(nth 1 tv));perevod TV в формат координат списка
      PrSpis (entget name)  ;Список-описание полилинии
      NNSpis (length PrSpis);кол-во элементов в списке
      NN 0 NewSpis '();Счетчик прохода по списку
      VarDEL "НеУдалена" ;контроль - только удаление вершины или с преобразованием сегмента
      TipE   (CDR(ASSOC 0  PrSpis));тип вабранного примитива
      KolV   (cdr(assoc 90 PrSpis));Кол-во вершин в полилинии
)
(if(= var nil)(setq var "НеДугОтр"));Если не задали, то код=0 - только удалить вершины - иначе (1) - преобразовать сегмент
(if(and(/= var "ДугОтр")(or(/= TipE "LWPOLYLINE")(<= kolv 2)));Если нельзя удалить вершину - отмена поиска и преобразования в списке
   (setq NewSpis nil NN NNspis VarDEL(Princ "\nНевозможно - всего 1 сегмент или не полилиния"))
)
(while(< NN NNSpis);Перебор списка в поиске совпадения координат
   (if(equal tv(setq SpNN(nth NN PrSpis))0.01);поиск совпадающих координат
      (progn                          ;если вершины совпали
        (setq kod (cdr (car NewSpis)));текущий код предыдущего искомой вершине сегмента
    (if (= kod 0.0) (setq NewK (cons 42 -1)) (setq NewK (cons 42 0.0)));выбор - код дуги или отрезка
    (if (= Var "ДугОтр")(setq NewSpis (cons NewK(cdr NewSpis))));преобразование сегмента - если Var=ДугОтр
    (setq NN(+ NN 4)VarDEL "Удалена");перевод счетчика через описания найденой координаты
      );pr
      (setq NewSpis(cons SpNN NewSpis)NN(1+ NN));Иначе - Дальнейший перебор-формирование списка
   );if
);w
(if(= VarDEL "Удалена");Если вершина удалена - уменьшается код кол-во вершин в списке
  (setq KolV(assoc 90 prspis) newKolV(cons 90(1-(cdr KolV))) PrSpis(subst newKolV KolV prspis))
);if
(if(/= NewSpis nil);eсли не было отказа удалять вершину - обновить список
  (progn(setq PrSpis (reverse NewSpis))
        (entmod prspis)
        (entupd name)
  );pr
);if
(PrinC)
)
;------------------------------------
;Вставить верш "В" "в" "D" или "d" - Удалить "У" "у" "E" или "e" - Преобразовать "П" "п" "G" или "g"
(defun c:poli ( / key )
  (setq key "У")
  (while (/= key nil)
    (initget "В в D d У у E e П п G g")
    (setq key (getkword "\nРедактирование полилинии [Вставить вершину/Удалить вершину/Преобразовать сегмент в дугу-линию] <Выход>:"))
    (cond((or(= key "E")(= key "e")(= key "У")(= key "у"))(DELV nil nil nil))
         ((or(= key "G")(= key "g")(= key "П")(= key "п"))(ARC_LINE))
         ((or(= key "В")(= key "в")(= key "D")(= key "d"))(INSERTP "\nВыберите полилинию, отрезок или дугу для добавления вершин:"))
         (T(setq key nil))
    );c
  );w
  (princ)
)
;------------------------------------

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

Ну, и ну - (vmon)! Последний раз я ее применял лет 13 назад. Разве она сейчас актуальна?

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

Выкладываю новую версию одной из программ...

;******** lW_arc.lsp ***************
;    Замена линейного сегмента полилинии
;    дуговым сегментом.
;    Автор  Евгений Елпанов.
;    Последняя редакция 04.06.06
(defun C:LW_ARC (/  LW i P1 P2 P3)
 (vl-load-com)
 (or doc (setq doc (vla-get-ActiveDocument (vlax-get-acad-object))))
 (if (and (setq lw (entsel "\n Выберите нужный сегмент в полилинии. "))
          (= (cdr (assoc 0 (entget (car lw)))) "LWPOLYLINE")
     ) ;_  and
  (progn
   (setq i  (fix (vlax-curve-getParamAtPoint
                  (car
                   lw
                  ) ;_  car
                  (vlax-curve-getClosestPointTo (car lw) (cadr lw))
                 ) ;_  vlax-curve-getParamAtPoint
            ) ;_  fix
         p1 (vlax-curve-getPointAtParam (car lw) i)
         p3 (vlax-curve-getPointAtParam (car lw) (1+ i))
         lw (vlax-ename->vla-object (car lw))
   ) ;_  setq
   (princ "\n Задайте визуально кривизну сегмента. ")
   (vla-StartUndoMark doc)
   (while (and (setq p2 (grread 5)) (= (car p2) 5))
    (vla-SetBulge
     lw
     i
     ((lambda (a) (/ (sin a) (cos a)))
      (/ (- (angle p1 (cadr p2)) (angle (cadr p2) p3)) -2.)
     )
    ) ;_  vla-SetBulge
   ) ;_  while
   (vla-EndUndoMark doc)
  ) ;_  progn
  (princ "\n Ничего не выбрано или объект не полилиния. ")
 ) ;_  if
) ;_  defun

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

Еще одна новая опция.
Разбивает выбранный сегмент полилинии на указанное количество сегментов или через указанное расстояние
Вариант кнопки

[_Button("Добавить вершины", "pl_div.bmp", "pl_div.bmp")]^C^C^P(if (not C:PL-DIV) (load "pl_div")) PL-DIV

Код программы. Сохранить в файле pl_div.lsp

;|*********************** Команда PL-DIV *********************************
*                                                                        *
*   Разбивает выбранный сегмент полилинии на указанное количество        *
*  сегментов или через указанное расстояние. По аналогии с командами     *
*  подели (divide) и разметь (measure). Если разбиваем сегмент через     *
*  указанное расстояние, то новые вершины добавляются начиная с вершины, *
*  ближайшей к точке указания. Не обрабатываются 3d полилинии.           *
*  В ответ на запрос "[Длина (-) /Количество (+) ] сегментов : "         *
*  можно вводить                                                         *
*   - число >0 - воспримется как кол-во сегментов                        *
*   - число <0 - воспримется как расстояние для разметки                 *
*   - соответствующие опции команды (Д К + -)                            *
*                                                                        *
**************************************************************************
Идея и первая реализация здесь https://www.caduser.ru/forum/topic27961.html
Принцип добавления сегментов взят из программы kpblc'a kpblc-stretch-pline
Обсуждения и варианты здесь https://www.caduser.ru/forum/topic20243.html
   Автор  Владимир Азарко (VVA)
   Редакция 21.06.2006|;
(defun C:PL-DIV ( / ent-pline break-point-count osm adoc osm *error* next)
(vl-load-com)
;| Функция pline-addvertex-divide
Добавляет вершины к сегменту полилинии
Параметры:
   ent_pline          - ссылка на полилинию, аналог (entsel)
   break-point-count  - число >0 кол-во сегментов (divide)
                      - число <0 длина сегмента   (measure)|;
(defun pline-addvertex-divide (ent-pline break-point-count /
                   pln bpt coors segm fpt
                   spt len i break-point-list )
;;;***************** Вспомогательные функции ******************************
;;======================================================;;
;;  Return list of segms and radii valiues of polyline  ;;
;;  written by Fatty The Old Horse 10/13/05    ;;
;;      (framework)      ;;
;;======================================================;;
(defun group-by-num (lst num / ls ret)
 (if (= (rem (length lst) num ) 0)
   (progn
     (setq ls nil)
     (repeat (/ (length lst) num)
     (repeat num
       (setq ls (cons (car lst) ls)
            lst (cdr lst)))
     (setq ret (append ret (list (reverse ls)))
        ls nil))))
  ret)
;|=======================================================================================
* Ф-ция _pline-get-verts
* Возвращает координаты вершин полилинии
* Взята или на autocad.ru или на dwg.ru
* Arguments [Type]:
   pline_obj = Object [Vla-Object]
* Возвращает [Type]:
   список координат вида ((90.987 183.524) (93.2774 206.991) (123.052 208.708) (140.23 184.382) (111.6 170.073))
|;
(defun _pline-get-verts (pline_obj / verts)
  (setq verts (vlax-get pline_obj 'Coordinates)
      verts
      (cond
        ((wcmatch (vlax-get pline_obj 'Objectname )
           "AcDb2dPolyline,AcDb3dPolyline")
         (group-by-num verts 3))
        ((eq (vlax-get pline_obj 'Objectname )
           "AcDbPolyline")
         (group-by-num verts 2))
        (T nil))))
;;;*************** pline-addvertex-divide *********************
 (setq pln (vlax-ename->vla-object (car ent-pline))
       bpt (cadr ent-pline)
       bpt (trans bpt 1 0)
       bpt (vlax-curve-getclosestpointto pln bpt))
 (if (eq (vla-get-closed pln) :vlax-false)
   (setq coors (_pline-get-verts pln))
   (progn
     (setq coors (_pline-get-verts pln))
     (setq coors (append coors (list (car coors))))
     )
   )
   (setq segm (fix (vlax-curve-getparamatpoint pln bpt)) ;;;№ Сегмента
          fpt (nth segm coors)                ;_1-я Вершина сегмента
          spt (nth (1+ segm) coors)           ;_2-я Вершина сегмента
;|len - список из 3-х чисел
 (Длина сегмента
 Расстояние от начала сегмента до точки указания
 Расстояние от точки указания до конца сегмента)|;
          len (mapcar
               '(lambda (p1 p2)
              (abs(- (vlax-curve-getDistAtPoint pln p1)
              (vlax-curve-getDistAtPoint pln p2))))
           (list fpt fpt bpt)
           (list spt bpt spt))
break-point-list nil);_setq
 (if (minusp break-point-count)
  (progn ;_Длина
    (setq break-point-count (abs break-point-count)
        segm (fix (/ (car len) break-point-count))
       coors (if (> (nth 1 len)(nth 2 len))
               (- (car len)(* segm break-point-count)) ;_ближе к последнему сегменту
               0)
           i 1
         len break-point-count
         break-point-count segm)
   (if (zerop coors)
    (setq break-point-count (1+ break-point-count))
    (setq break-point-list
     (append break-point-list
       (list (vlax-curve-getPointAtDist pln
             (+ (vlax-curve-getDistAtPoint pln fpt) coors))))))
  )
  (progn ;_Кол-во
    (setq len (/ (car len) break-point-count)
            i 1
        coors 0))
  );_if
  (repeat (1- break-point-count)
    (setq break-point-list
            (append break-point-list
                 (list (vlax-curve-getPointAtDist pln
                       (+ (vlax-curve-getDistAtPoint pln fpt)
                          (+ (* i len) coors))))))
    (setq i (1+ i)))
    (foreach break-point break-point-list
       (setq break-point (trans break-point 0 1))
       (command "_.break" ent-pline "_F" break-point break-point)
       (command "_.pedit" "_M" "_C" break-point break-point "" "_join" 0 "")
       (setq ent-pline (list (entlast) break-point )))
  );_pline-addvertex-divide
(setq adoc (vla-get-activedocument (vlax-get-acad-object))
       osm (getvar "OSMODE")
      next t)
(defun *error* (message)
;;;Прерываем активную команду
(while (> (getvar "CMDACTIVE") 0)(command))
(if (car ent-pline)(redraw (car ent-pline) 4))
  (setvar "OSMODE" osm)
  (princ message)
  (vla-endundomark adoc)
  (princ)
  ) ;_ end of defun
  (vla-startundomark adoc)
(while next
  (setvar "ERRNO" 0)
  (if (and
        (setq ent-pline
               (entsel "\nВыберите сегмент полилинии для добавления вершин <выход>: "))
        (member (vla-get-ObjectName
                  (vlax-ename->vla-object (car ent-pline)))
                '("AcDb2dPolyline" "AcDbPolyline"))
      )
    (progn
      (redraw (car ent-pline) 3)
      (initget "Количество Длина + -" 3)
      (prompt "\nЧисло <0-длина сегмента >0-количество сегментов")
      (setq break-point-count
             (getint "\n[Длина (-) /Количество (+) ] сегментов : "))
      (cond ((and
               (= (type break-point-count) 'STR)
               (member (substr break-point-count 1 1) '("Д" "-"))
               )
             (initget 7)
             (setq break-point-count
                    (getdist "\nУкажите длину сегментов : ")
                   break-point-count (- 0 break-point-count))
              )
            ((and
                (= (type break-point-count) 'STR)
                (member (substr break-point-count 1 1) '("К" "+"))
              )
              (initget 7)
              (setq break-point-count
                     (getint "\nУкажите количество сегментов : "))
             )
             (t nil));_cond
      (redraw (car ent-pline) 4)
      (setvar "OSMODE" 0)
      (pline-addvertex-divide ent-pline break-point-count)
      (setvar "OSMODE" osm)
      )
   (progn
    (setq osm (getvar "ERRNO"))
    (cond ((= osm 7) (alert "Ничего не выбрано"));;;Пустой выбор
          ((and (car ent-pline)
                (member (vla-get-ObjectName
                           (vlax-ename->vla-object (car ent-pline)))
                        '("AcDb3dPolyline")))
           (alert "3d полилинии не обрабатываются"))
          ((= osm 52)(setq next nil))  ;;;Клавиша Ввод(выход)
          (t (alert "Необходимо выбрать полилинию")));_cond
    )));_while
  (vla-endundomark adoc)(princ)
  )
  (princ "\nНаберите PL-DIV")

Краткое описание
Команда PL-DIV разбивает выбранный сегмент полилинии на указанное количество сегментов или через указанное расстояние. Если разбиваем сегмент через указанное расстояние, то новые вершины добавляются начиная с вершины, ближайшей к точке указания. Не обрабатываются 3d полилинии.
В ответ на запрос "[Длина (-) /Количество (+) ] сегментов : " можно вводить
- число >0 - воспримется как кол-во сегментов
- число <0 - воспримется как расстояние для разметки
- соответствующие опции команды (Д К + -)

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

> VVA
Вот это не совсем понятно:

      (prompt "\nЧисло <0-длина сегмента >0-количество сегментов")

При вводе нуля выскакивает ошибка, программа выполняется далее, но в конце все равно выводится сообщение об ошибке.

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

> Владимир Громов
Еще раз скопировал код с форума - при вводе 0 у меня сообщает Значение должно быть ненулевым.
Я так и подозревал, что не по русски получилось.
Этой строкой я хотел подчеркнуть, что на запрос
[Длина (-) /Количество (+) ] сегментов :
можно вводить
— число >0 — воспримется как кол-во сегментов
— число <0 — воспримется как расстояние для разметки
— соответствующие опции команды (Длина Количество) по правой клавише мыши

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

> Atol
Очень благодарен Вам за программу!
Поставил себе и друзьям. Теперь горя не знаем.
А то, что вы когда-то давно применили vmon вызывает только уважение (старые компьютеры).
Здесь много уважаемые программисты рассуждали о редактировании полилинии, но ни один не сделал удаление узла (нормальное для юзера).

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

Новые команды для работы с полилинией
Вернее не новые, а дальнейшее развитие команд, упоминавшихся как на этом форуме, так и на dwg.ru
==============================================
PL-JOIN -Объединение полилиний чохом
PL-A2L -Замена линейного сегмента в полилинии дуговым сегментом.
PL-L2A -Замена дугового сегмента в полилинии линейным сегментом.
PL-DIV -Разбивает выбранный сегмент полилинии на указанное количество сегментов или через указанное расстояние
PL-VxAdd -Добавляет новую вершину к полилинии
ENTREVS -Реверс объекта. Поштучный выбор с указанием направления
ENTREV -Реверс объектов (множественный выбор)
PL-VxRdc -Удаление вершин полилиний, которые лежат на одной прямой (прополка)
PL-VxDel -Удаление выбранной вершины
PL-VxOpt -Удаление совпадающих вершин из полилинии
PL-NoArc -Аппроксимация дуговых сегментов полилинии
CVPOLY -Преобразование 3D полилиний в 2D полилинии от Tony Tanzillo
Особое внимание уделялось тому, чтобы полилиния не теряла ассоциативности и корректной работе в UCS
Берем отсюда http://dwg.ru/dwl/867

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

Следите за обновлениями программы.
Новая ссылка:
http://dwg.ru/dnl/607

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

Программа замечательная. Нарадоваться не могу. Позаменяла названия команд на более запоминающиеся. Теперь вообще цены нет.
Один только вопрос. А не реально сделать так чтобы   при добавлении новой вершины работала привязка к узлам?

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

> A-Tri
Только сейчас обнаружил, сорри. Если под узлами подразумевать привязку к точкам (_Node), то найди поиском PL-VxAdd, а там строчку

(kpblc-error-save-sysvar '(("ANGBASE" 0)("ANGDIR" 0)("UCSFOLLOW" 0)
                 ("UCSICON") ("CLAYER")("osmode" 512)("CMDECHO" 0)))

И вместо цифры 512 запиши нужную. Узнать какую можно, если выставить нужные привязки и набрать в командной строке OSMODE Попутно отмечу, что вышли новые обновления. Подробнее http://dwg.ru/dnl/607

Re: MNU, LISP. Предлагается панель с опциями и новыми командами для полилинии

Выражаю особую благодарность VVA за программу "Прополка полиинии". Очень пригодилась для значительного уменьшения количества вершин полилиний после выполнения таких преобразований: CDR->DWG->WMF->DWG.