Re: Как добавить вершину в полилинию нажатием одной кнопки?

> Евгений Елпанов
Я так считал, что выпрямить два смежных сегмента без удаления вершины легче, чем добавить вершину в сегмент. Стандартная команда редактирования полилини позволяет удалить сразу несколько вершин и плучить 1 линейный сегмент.
Вопрос об удалении вершины поднят здесь:
https://www.caduser.ru/forum/topic22839.html
Наверное, можно сделать программу удаления произвольной вершины полилинии, но мне кажется более интересной задачей сохранить вершины, но сегменты выпрямить на указанных участках или между указанными вершинами, возможно, с запросом об удалении вершин.

Re: Как добавить вершину в полилинию нажатием одной кнопки?

> Владимир Громов
Если я правильно понял, то фактически предлагается на 1 линейном сегменте иметь не 2, а 3 вершины. Если это так, то после применения overkill останутся только 2 вершины.

Re: Как добавить вершину в полилинию нажатием одной кнопки?

> kpblc
Да, нет, я имел в виду вот что: имеются 3 (для примера) вершины полилинии не на одной прямой. Надо выпрямть участок из 2 сегментов, но чтобы и осталось 2 сегмента, расположенных на одной прямой, т.е. средняя вершина осталась на этой прямой. Вершин можно задействовать и больше, а  сегменты могут быть и дуговые. Частный случай - вершины удаляются. В этом случае задача попроще, примерно как при вставке новой вершины по программе. Полилиния разрывается в двух точках, все сегменты между этими точками удаляются, между этими точками рисуется полилиния, потом все объединяется. А вот первый случай посложней. Зачем он? Да просто, чтобы сохранить вершины для дальнейшего (при необходимости) редактирования полилинии. Но этот случай можно отложить, потому что теперь есть (или скоро будет) программа вставки вершины в полилинию. Но если человек озаботился такой проблемой здесь:
https://www.caduser.ru/forum/topic22839.html
то, может и перейти в ту тему?

Re: Как добавить вершину в полилинию нажатием одной кнопки?

Еще один вариант команды pline-str kpblc'а, использующий не связку BREAK-STRETCH, а только PEDIT с "гулянием" по вершинам.
Плюсы этого варианта - ассоциативность полилинии не теряется (при штриховке или если подрезан видовой экран), минусы- если добавляем в дуговой сегмент, одна часть остается дугой, а вторая - линейным сегментом.
Чтобы не повторяться эти ф-ции ,брать https://www.caduser.ru/forum/topic20243.html kpblc (2005-10-25 16:47:45)
lib:ent-to-ename
lib:layer-is-changeable
lib:layer-by-object
kpblc-error-save-sysvar
_kpblc-ent-modify-autoregen
(kpblc-error-restore-sysvar)

Сам текст

(defun pl_AddVxbyPedit (/       break_point
          selset_oper break_ent     break_ent_type
          *error* layer_status
          )
  (vl-load-com)
;;; ============ Библиотечные ф-ции BEGIN =============================
(defun D2R (a)(* pi (/ a 180.0)))
(defun R2D (a)(/ (* a 180.0) pi))
(defun lib:dxf (n lst)(cdr (assoc n lst)))
(defun lib:massoc (key alist / x nlist)
  (foreach x alist
    (if (eq key (car x))
      (setq nlist (cons (cdr x) nlist))))
  (reverse nlist))
;| ! *******************************************************************
;; !                  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
   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 (d2r 180.0) (* 0.5 X_Len))
   Uc (polar Lc 0.0 X_Len)
   Lc (polar Lc (d2r 270.0) (* 0.5 Y_Len))
   Uc (polar Uc (d2r 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))
;| ! ***************************************************************************
;; !           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
; ! ****************************************************************************
;; !                             lib:Zoom2Lst
;; ! ****************************************************************************
;; ! Function : Zoom границ списка точек
;; ! Arguments: 'vlist' - Список точек
;; ! Зуммирует экран, чтобы всеточки были видны
;; ! ****************************************************************************
(defun lib:Zoom2Lst( vlist / bl tr Lst OS )
(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" bl tr
        "._Zoom" "0.95x")
    (setvar "OSMODE" OS))))
;;; pln - ENAME or Vla-Object polyline
;;; bpt Point in WCS
;;; Retunt Number Vertex Since 0 (начиная с 0)
(defun lib:pl_getVxNumber ( pln bpt /  segm )
   (if (eq (type pln) 'ENAME)
     (setq pln (vlax-ename->vla-object pln)))
     (setq bpt (vlax-curve-getclosestpointto pln bpt))
     (fix (vlax-curve-getparamatpoint pln bpt))) ;;;№ Сегмента
;; ! ****************************************************************************
;; !               lib:pl_AddPointbyPedit
;; ! ****************************************************************************
;; ! Function : Add a new point on the polyline just before the specified vertex
;; !            number 'VxNum'
;; ! Arguments: 'ename'  - The name of the POLYLINE entity (Vla or Ename)
;; !            'VxNum'  - Vertex Number (actual count, not array) После какой вершины добавить, начиная с 1
;; !            'Pt'     - New value of the point to be added.
;; ! Action   : Adds a vertex at the specified point along the polyline
;; ! Returns  : Point of vertex if a vertex was added else returns nil
;; !Идея взята с    : www.4d-technologies.com
;; ! ****************************************************************************
(defun lib:pl_AddPointbyPedit ( ename VxNum Pt / pt1 elist ptlist Added OS )
 (if (eq (type ename) 'VLA-OBJECT)
     (setq ename (vlax-vla-object->ename ename)))
(setq    OS (getvar "OSMODE")
    Added nil
    ptlist (lib:massoc 10 (entget ename)))
(setvar "OSMODE" 0)
(lib:Zoom2Lst ptlist)
(command "._Pedit" ename "_Edit")
(if (> VxNum 0)(repeat (1- VxNum)(command "_Next")))
(command "_Insert" Pt)
(setq Added Pt)
(if (> VxNum 0)(command "_X" "_X")
(progn
    (setq elist (entget ename))
    (if (= (lib:dxf 0 elist) "LWPOLYLINE")
    (progn
      (command "_Previous")
      (setq pt1 (append (lib:dxf 10 elist) (list (lib:dxf 38 elist)))))
    (setq pt1 (lib:dxf 10 (entget (entnext ename)))))
    (command "_Move" Pt "_Next" "_Move" pt1 "_X" "_X")))
(setvar "OSMODE" OS)
Added)
;;; ============ Библиотечные ф-ции END ===============================
  (setq *error* kpblc-error)
  (if (not *kpblc-activedoc*)
    (setq *kpblc-activedoc*
     (vla-get-activedocument
       (vlax-get-acad-object)
       ) ;_ end of vla-get-activedocument
    ) ;_ end of setq
    ) ;_ end of if
  (vla-endundomark *kpblc-activedoc*)
  (vla-startundomark *kpblc-activedoc*)
  (kpblc-error-save-sysvar '(("osmode" 512)))
  ;; Обработка пустого выбора
  (while (setq break_point
    (getpoint "\nУкажите точку разрыва <выход> : "))
    (setq selset_oper   (ssget break_point)
            break_ent   (if selset_oper (ssname selset_oper 0) nil)
         break_ent_type (if break_ent (cdr (assoc 0 (entget break_ent))) nil)
      selset_oper nil
    ) ;_ end of setq
    (if (and break_ent
          (not (lib:layer-is-changeable (lib:layer-by-object break_ent))))
      (progn
         (setq layer_status (cdr (assoc  70
             (entget (lib:layer-by-object break_ent)))))
         (_kpblc-ent-modify-autoregen
            (lib:layer-by-object break_ent) 70 0 t)
      ))
    (cond
      ((member break_ent_type '("LWPOLYLINE"  "POLYLINE"))
        (lib:pl_AddPointbyPedit
      break_ent
      (1+ (lib:pl_getVxNumber break_ent
        (trans break_point 1 0)))
      (trans (getpoint break_point "Укажите новую точку : ") 1 0)
      )
       )
      ((member break_ent_type '("LINE" "ARC"))
       (if (getvar "PEDITACCEPT")(setvar "PEDITACCEPT" 0))
       (command "_.PEDIT" break_ent "_Yes" "") ;_Делаем полилинию
       (setq break_ent (entlast))
        (lib:pl_AddPointbyPedit
      break_ent
      (1+ (lib:pl_getVxNumber break_ent
        (trans break_point 1 0)))
      (trans (getpoint break_point "Укажите новую точку : ") 1 0)
      )
       )
      ((null break_ent_type)(alert "Ничего не выбрано!"))
      (t (alert "Добавить вершину к выбранному примитиву невозможно!")))
      (if  layer_status (progn
         (_kpblc-ent-modify-autoregen
          (lib:layer-by-object break_ent)
           70 layer_status t)
        (setq layer_status nil))) ;_ end of if
    ) ;_ end of while
  (kpblc-error-restore-sysvar)
  (vla-endundomark *kpblc-activedoc*)
  (princ)) ;_ end of defun
(defun c:pline-strPE ()
  (pl_AddVxbyPedit)
  ) ;_ end of defun
(princ "\nНаберите pline-strPE")

Re: Как добавить вершину в полилинию нажатием одной кнопки?

Наткнулся на этот пост, может кому интересно будет узнать, что Autodesk реализовали эту возможность в Civil 3D. Очень удобно реализовали, прямо как я и заказывал. Совпадение, наверное :)

Re: Как добавить вершину в полилинию нажатием одной кнопки?

Эта и другие подобные темы - уже прошлое. Теперь у нас есть отличный набор инструментов для работы с полилинией:
http://dwg.ru/dnl/607

Re: Как добавить вершину в полилинию нажатием одной кнопки?

Могу предложить макрос
^C^C(setq s (getvar "Osmode"));(setvar "Osmode" 1536);_break \_f \@;_pedit;_Last;_J;(entnext); ;Stretch;_Last;;
(setvar "Osmode" s)

Re: Как добавить вершину в полилинию нажатием одной кнопки?

Ошибся. Дал какой-то промежуточный вариант.
Вот этот должен работать. Но тоже как-то странно. В 2005 работает.
В 2004 не хочет. Другая реализация break может быть.
^C^C_break \_f \@;_pedit;_Last;_J;(entnext);;;

Re: Как добавить вершину в полилинию нажатием одной кнопки?

Опять ошибся. Работает только в новом файле. Блин.
(defun c:poi(/p h e)
(setq h (entsel "Pick pline"))
(setq e (car h))
(setq p (cadr h))
(command "_break" e p p)
(command "_pedit" e "_J" (entnext e) "" "")
)
Пытаюсь эту сделать как макрос. Но не получается. Работает только как лисп.

Re: Как добавить вершину в полилинию нажатием одной кнопки?

> Евгений
Елпанов
просьба вопрос
не могли бы Вы слегка переделать вашу замечательную программу по добавлению вершин в полилинию. Меня интересует добавления
вершин только в дуги,т.е. то что и делает Ваша программа, но без диалога. Оформить как функцию
с аргументами, где 1-й аргумент сама полилиния
2-й вершина дуги, беру из другой функции.
спасибо заранее.

Re: Как добавить вершину в полилинию нажатием одной кнопки?

Элегантная прога!)