Тема: LISP. Построение перпендикуляров к любым линейным примитивам

Строит перпендикуляры к линиям, полилиниям, аркам, окружностям, эллипсам, сплайнам, лучам и х-линям в указанной точке. Перпендикуляр в точке пересечения первого перпендикуляра с дуговыми и криволинейными сегментами даёт возмодность построить касательную.

(defun c:per(/ oldEcho oldOsm uPnt sSet
        sCurve Dr Ang *error*)
  (vl-load-com)
  (defun *error* (msg)
    (setvar "CMDECHO" oldEcho)
    (setvar "OSMODE" oldOsm)
    (princ)
    ); end of *error*
  (setq oldEcho(getvar "CMDECHO")
   oldOsm(getvar "OSMODE")
   ); end setq
  (setvar "CMDECHO" 0)
  (setvar "OSMODE" 819)
  (if
    (and
    (setq uPnt(getpoint "\nSelect point at line or curve -> "))
    (setq sSet(ssget uPnt '((0 . "*LINE,ARC,ELLIPSE,CIRCLE,RAY,XLINE")
               (-4 . "<NOT")(0 . "MLINE")(-4 . "NOT>"))))
    (setq sCurve(vlax-ename->vla-object(ssname sSet 0)))
    (setq Dr(vlax-curve-getFirstDeriv sCurve
      (vlax-curve-getParamAtPoint sCurve uPnt)))
     ); end and
    (progn
      (setq Ang(angtos(- pi(atan(/(car dr)(cadr dr))))))
      (setvar "OSMODE" 0)
      (command "_.xline" "_a" Ang uPnt "")
      ); end progn
    ); end if
  (setvar "CMDECHO" oldEcho)
  (setvar "OSMODE" oldOsm)
  (princ)
  ); end of c:per

Re: LISP. Построение перпендикуляров к любым линейным примитивам

Кажется мне, что и такая программа:

(defun C:PPER (/ osm tper)
(setq osm (getvar "OSMODE"))
(setvar "OSMODE" 512)
(setq tper (getpoint "\n Укажите точку: "))
(vl-cmdf "_xline" "_per" tper tper "")
(setvar "OSMODE" osm)
(princ)
)

строит перпендикуляр к отрезкам, полилиниям, дугам, окружностям, эллипсам, эллиптическим дугам, кольцам, сплайнам, лучам и х-линиям в указанной точке. Перепендикуляр к мультилинии не строит, а к 3D-полилинии строит как попало.

Re: LISP. Построение перпендикуляров к любым линейным примитивам

Вот построить бы перпендикуляр определенной длины...

Re: LISP. Построение перпендикуляров к любым линейным примитивам

Да так действительно проще.

Вот построить бы перпендикуляр определенной длины...

Примерно так, хоть возможно немного коряво. Можно строить как перпендикуляры, так и касательные нужной длинны. Код особо не тестировал:

(defun c:per(/ oldEcho oldOsm uPnt sSet oldOrt
        sCurve Dr Ang1 Ang2 pt1 pt2 *error*)
  (vl-load-com)
  (defun *error* (msg)
    (setvar "ORTHOMODE" oldOrt)
    (command "_.ucs" "_p")
    (command "_.ucs" "_p")
    (setvar "CMDECHO" oldEcho)
    (setvar "OSMODE" oldOsm)
    (princ)
    ); end of *error*
  (setq oldEcho(getvar "CMDECHO")
        oldOsm(getvar "OSMODE")
        oldOrt(getvar "ORTHOMODE")
   ); end setq
  (setvar "CMDECHO" 0)
  (setvar "OSMODE" 819)
  (command "_.ucs" "_w")
  (if
    (and
    (setq uPnt(getpoint "\nSelect point at line or curve -> "))
    (setq sSet(ssget uPnt '((0 . "*LINE,ARC,ELLIPSE,CIRCLE,RAY,XLINE")
               (-4 . "<NOT")(0 . "MLINE")(-4 . "NOT>"))))
    (setq sCurve(vlax-ename->vla-object(ssname sSet 0)))
    (setq Dr(vlax-curve-getFirstDeriv sCurve
      (vlax-curve-getParamAtPoint sCurve uPnt)))
     ); end and
    (progn
      (if(=(cadr dr) 0.0)
    (setq Ang1 0.0)
    (setq Ang1(- pi(atan(/(car dr)(cadr dr)))))
    ); end if
      (setq Ang2(- Ang1(/ pi 2))
        pt1 (polar uPnt Ang1 1.0)
        pt2 (polar uPnt Ang2 1.0)
        ); end setq
      (setvar "OSMODE" 0)
      (command "_.ucs" "_3" uPnt pt1 pt2)
      (setvar "ORTHOMODE" 1)
      (princ "\nSpecify length: ")
      (command "_.line" (trans uPnt 0 1) pause "")
      (command "_.ucs" "_p")
      (command "_.ucs" "_p")
      (setvar "ORTHOMODE" oldOrt)
      ); end progn
    ); end if
  (setvar "CMDECHO" oldEcho)
  (setvar "OSMODE" oldOsm)
  (princ)
  ); end of c:per

Re: LISP. Построение перпендикуляров к любым линейным примитивам

> {Smirnoff}
Ваша программа работает.
А я вот угрюмо продвигаю свой вариант. Правда, он не обрабатывает ошибки. И курсор надо стараться вести
строго вдоль x-линии...

(defun C:PERP (/ echo osm tper xl)
(setq echo (getvar "CMDECHO"))
(setvar "CMDECHO" 0)
(setq osm (getvar "OSMODE"))
(setvar "OSMODE" 512)
(setq tper (getpoint "\n Укажите начальную точку перпендикуляра: "))
(vl-cmdf "_xline" "_per" tper tper "")
(setq xl (entlast))
(princ "\n Укажите конечную точку или задайте расстояние вдоль x-линии: ")
(vl-cmdf "_LINE" tper pause "")
(vl-cmdf "_ERASE" xl "")
(setvar "CMDECHO" echo)
(setvar "OSMODE" osm)
(princ)
)

Re: LISP. Построение перпендикуляров к любым линейным примитивам

Пока у тебя более комфортно, поскольку если перед отрисовкой линии перпендикуляра можно включить привязки Intrsection и Apparent Intersection (чего пока нет) доводить перпендикуляр до пересечения с нужным контуром.
Однако мой код имеет большие возможности для развития потому что позволяет выбирать что отрисовывать перпендикуляр или касательную. А если отрисовть 2 перпендикулярные х-линии, сделать их под цвет экрана или подсветить как направляющие, включить вышеуказанные привязки, то получится очень и очень прикольно. Только учитывая все проверки потребуется намного больше кода.

Re: LISP. Построение перпендикуляров к любым линейным примитивам

Конечно, ваша программа позволяет добавить разные дополнительные возможности, но я-то и не хотел делать сложную, универсальную программу, поэтому и не буду дальше думать на эту тему. И так все работает.

Re: LISP. Построение перпендикуляров к любым линейным примитивам

Маленькое замечание. Если в моих программах заменить привязку "_per" на "_tan", то будет строиться касательная, но только к окружности или дуге.

Re: LISP. Построение перпендикуляров к любым линейным примитивам

ИМХО, если неинтересно / нереализуемо, послать меня нафиг. Предложения по доработке: указать примитив(ы), к которому строить попиндикуляр; динамически отслеживать положение курсора и строить прямую от мыши к примитиву. В случае попадания курсора на пересечение примитивов строить 2 (3, 4, 5...) прямых перпендикуляров к каждому примитиву. Потом потребовать, в каком направлении и какой длины строить перпендикуляр. Если не указано ни направление, ни длина, строить прямую. Если указано только направление, строить луч. Если указана только длина, строить 2 отрезка в обе стороны от примитива. Если указано и направление, и длина, строить отрезок.

> Владимир Громов
Если в коде после (vl-cmdf "_.xline") сразу устанавливать системные переменные (в частности, "osmode"), чего получится? Для отслеживания ошибок и восстановления системных переменных могу предоставить обработчик (немного переделанный из ruCAD'a).
В проге не отслеживается, выбран какой-то объект на момент указания точки, или нет. Если текущий слой заблокирован, функция выдала ошибку.
> All: А почему нет полных меток начала и конца отмены? Или я просто логику не понял?

Re: LISP. Построение перпендикуляров к любым линейным примитивам

> kpblc
Да я тут и не претендую на абсолютно готовый вариант. К тому же я не очень-то приветствую сверхуниверсальные программы с множеством проверок на "вшивость"...:) С другой стороны, мне бы и в голову не пришло что-либо отрисовывать на блокированном слое.

Re: LISP. Построение перпендикуляров к любым линейным примитивам

А вот и вариант с косательной...

(defun test (/ a)
  (if (and (setq a (entsel))
       (not
         (vl-catch-all-error-p
           (vl-catch-all-apply
         (function vlax-curve-getClosestPointTo)
         (list (car a) (cadr a))
           ) ;_  vl-catch-all-apply
         ) ;_  vl-catch-all-error-p
       ) ;_  not
      ) ;_  and
    (entmakex
      (list '(0 . "XLINE")
        '(100 . "AcDbEntity")
        '(100 . "AcDbXline")
        (cons 10
          (vlax-curve-getClosestPointTo
            (car a)
            (cadr a)
          ) ;_  vlax-curve-getClosestPointTo
        ) ;_  cons
        (cons 11
          (vlax-curve-getFirstDeriv
            (car a)
            (vlax-curve-getParamAtPoint
              (car a)
              (vlax-curve-getClosestPointTo
            (car a)
            (cadr a)
              ) ;_  vlax-curve-getClosestPointTo
            ) ;_  vlax-curve-getParamAtPoint
          ) ;_  vlax-curve-getFirstDeriv
        ) ;_  cons
      ) ;_  list
    ) ;_  entmakex
  ) ;_  if
  (princ)
)

Re: LISP. Построение перпендикуляров к любым линейным примитивам

Вполне может иметь место ситуация, когда необходимо построить перпендикуляр/касательную от конкретного объекта из точки пересечения нескольких объектов. Ни один из приведенных примеров не даёт такой возможности, а хотелось бы...
С уважением.

Re: LISP. Построение перпендикуляров к любым линейным примитивам

> Kosarev
Например так:

(defun c:test(/ GR LW PT)
(while(and(setq gr(grread 5))(=(car gr) 5))
(if lw(redraw lw 4))
(if(and(setq pt(osnap(cadr gr) "_nea,_end"))
(setq lw(ssget pt '((0 . "LWPOLYLINE,LINE,ARC,CIRCLE,ELLIPSE,SPLINE"))))
(setq lw(ssname lw 0)))(redraw lw 3)))
(if lw(redraw lw 4))
(if(and pt lw)
(entmakex(list '(0 . "XLINE") '(100 . "AcDbEntity") '(100 . "AcDbXline")
(cons 10 pt)
(cons 11 (vlax-curve-getFirstDeriv lw
(vlax-curve-getParamAtPoint lw pt))))))
(princ)
)

Re: LISP. Построение перпендикуляров к любым линейным примитивам

Направление понятно, но код, похоже, не рабочий...

Re: LISP. Построение перпендикуляров к любым линейным примитивам

> Kosarev
Только, что скопировал с форума и проверил - все работает, правда не задает никаких вопросов - после запуска нужно ткнуть любую кривую...

Re: LISP. Построение перпендикуляров к любым линейным примитивам

Прошу прощения, запускл как (test), а не как (C:test) - тормоз конечно...
А вообще - оригинальная штука, с Вашего позволения применю способ выбора кое-где в своих програмках. Но я имел ввиду не это: допустим необходимо выполнить построение НЕПОСРЕДСТВЕННО  ИЗ  ТОЧКИ  ПЕРЕСЕЧЕНИЯ примитивов, т.е. ткнули в пересечение, а в наборе оказалось несколько объектов и тут как бы и вопрос: "От какого именно?", ну и т.д.

Re: LISP. Построение перпендикуляров к любым линейным примитивам

> Kosarev
Применяйте, конечно...
Если с сылкой на меня - то вообще распространяйте где угодно, хоть продавайте!

Re: LISP. Построение перпендикуляров к любым линейным примитивам

;;; !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
(defun c:perpen ( /
         cmd_key
         Obj_per
         Obj_per_VLAX
         TestColorObj_per
         test_point
         OldColor
         Angl
         orthomode_key
         point
         Derivate
         snap_key
         Param
           )
  (STORE)
  (command "_.UNDO" "_be")
  (setq OLDERROR *ERROR*)
  (setq *ERROR* *MY_ERROR*)
  (vlr-remove-all)
  (setq cmd_key (getvar 'CMDECHO))
  (setvar "CMDECHO" 0)
  (while (= Obj_per nil)
  (terpri)
  (setq Obj_per (entsel "Выделите линию для восстановления перпендикуляра:"))
  )
  (terpri)
  (if (/= Obj_per nil)
    (progn
      (setq Obj_per (car Obj_per))
      (setq Obj_per_VLAX (vlax-ename->vla-object Obj_per))
      (setq TestColorObj_per (vlax-property-available-p Obj_per_VLAX "Color" T))
      (if (= TestColorObj_per T)
    (progn
      (setq OldColor (vlax-get-property Obj_per_VLAX 'Color))
      (if (/= OldColor 1)
        (vlax-put Obj_per_VLAX "Color" 1)
        (vlax-put Obj_per_VLAX "Color" 5)
      )
    )
      )
      (while (= test_point nil)
    (terpri)
    (setq point (getpoint "Укажите точку на линии для восстановления перпендикуляра:"))
    (if (=  (ssget "_C" point point) nil)
      (setq test_point nil)
      (setq test_point (ssmemb Obj_per (ssget "_C" point point)))
    )
      )
      (if (/= test_point nil)
    (progn
      (setq point (vlax-curve-getclosestpointto Obj_per (trans point 1 0)))
      (setq Param (vlax-curve-getParamAtPoint Obj_per point))
      (if (not Param)
        (progn
          (if(equal point(vlax-curve-getStartPoint Obj_per)0.1)(setq Param(vlax-curve-getStartParam Obj_per)))
          (if(equal point(vlax-curve-getEndPoint Obj_per)0.1)(setq Param(vlax-curve-getEndParam Obj_per)))
        )
      )
      (setq Derivate (vlax-curve-getfirstderiv Obj_per Param))
      (setq Angl (- (atof (angtos (angle '(0 0 0) Derivate) 0 4)) 90))
      (setq point (polar '(0 0 0) (angtof (rtos (- (atof (angtos (angle '(0 0 0) (trans point 0 1)) 0 4)) Angl) 2 5)) (distance '(0 0 0) (trans point 0 1))))
      (command "_ucs" "_z" Angl)
      (setq orthomode_key (getvar 'ORTHOMODE))
      (setvar "ORTHOMODE" 1)
      (setq snap_key (getvar 'OSMODE))
      (setvar "OSMODE" 0)
      (command "_line" point pause "")
      (vlax-put Obj_per_VLAX "Color" OldColor)
      (setvar "ORTHOMODE" orthomode_key)
      (setvar "OSMODE" snap_key)
      (command "_ucs" "_p")
    )
      )
    )
  )
  (setvar "CMDECHO" cmd_key)
  (command "_.UNDO" "_e")
  (setq *ERROR* OLDERROR)
  (princ)
)
;<<<<<<<<>>>>>>>>>><<<<<<<<<<<<<>>>>>>>>>>>>>>><<<<<<<<<<<<<<<>>>>>>>>>>>>><<<<<<<<<<>>>>><><><><><><><><><><
писалось очень давно - но строит по моему к чему угодно, кроме блоков ест-но, из указанной точки

Re: LISP. Построение перпендикуляров к любым линейным примитивам

Только сегодня нашел немного времени дописать программу как хотел:

(defun c:per(/ oldEcho oldOsm uPnt sSet oldOrt
        sCurve Dr Ang1 Ang2 pt1 pt2 *error*
         actDoc actLay actSp oldSt xl1 xl2)
  (vl-load-com)
  (defun *error* (msg)
    (setvar "ORTHOMODE" oldOrt)
    (command "_.ucs" "_p")
    (command "_.ucs" "_p")
    (setvar "CMDECHO" oldEcho)
    (setvar "OSMODE" oldOsm)
    (if(and xl1 xl2)
      (progn
      (vla-put-Lock actLay :vlax-false)
      (vla-delete xl1)(vla-delete xl2)
      (vla-put-Lock actLay oldSt)
      ); end progn
      ); end if
    (vla-EndUndoMark actDoc)
    (princ)
    ); end of *error*
  (setq oldEcho(getvar "CMDECHO")
        oldOsm(getvar "OSMODE")
        oldOrt(getvar "ORTHOMODE")
   ); end setq
  (setvar "CMDECHO" 0)
  (setvar "OSMODE" 819)
  (command "_.ucs" "_w")
  (if
    (and
    (setq uPnt(getpoint "\nSelect point at line or curve -> "))
    (setq sSet(ssget uPnt '((0 . "*LINE,ARC,ELLIPSE,CIRCLE,RAY,XLINE")
               (-4 . "<NOT")(0 . "MLINE")(-4 . "NOT>"))))
    (setq sCurve(vlax-ename->vla-object(ssname sSet 0)))
    (setq Dr(vlax-curve-getFirstDeriv sCurve
      (vlax-curve-getParamAtPoint sCurve uPnt)))
     ); end and
    (progn
      (if(=(cadr dr) 0.0)
    (setq Ang1 0.0)
    (setq Ang1(- pi(atan(/(car dr)(cadr dr)))))
    ); end if
      (setq Ang2(- Ang1(/ pi 2))
        pt1 (polar uPnt Ang1 1.0)
        pt2 (polar uPnt Ang2 1.0)
        actDoc(vla-get-ActiveDocument
            (vlax-get-acad-object))
        actLay(vla-get-ActiveLayer actDoc)
        oldSt(vla-get-Lock actLay)
        ); end setq
      (vla-StartUndoMark actDoc)
      (if(= 1(vla-get-ActiveSpace actDoc))
    (setq actSp(vla-get-ModelSpace actDoc))
    (setq actSp(vla-get-PaperSpace actDoc))
    ); end if
      (vla-put-Lock actLay :vlax-false)
      (setq xl1(vla-AddXline actSp
         (vlax-3D-point uPnt)
         (vlax-3D-point pt1))
        xl2(vla-AddXline actSp
         (vlax-3D-point uPnt)
         (vlax-3D-point pt2))
        ); end setq
      (vla-put-color xl1 130)
      (vla-put-color xl2 51)
      (vla-Highlight xl1 :vlax-true)
      (vla-Highlight xl2 :vlax-true)
      (command "_.ucs" "_3" uPnt pt1 pt2)
      (setvar "ORTHOMODE" 1)
      (princ "\nSpecify length: ")
      (setvar "OSMODE" 2080)
      (command "_.line" (trans uPnt 0 1) pause "")
      (vla-delete xl1)(vla-delete xl2)
      (vla-put-Lock actLay oldSt)
      (command "_.ucs" "_p")
      (command "_.ucs" "_p")
      (setvar "ORTHOMODE" oldOrt)
      (vla-EndUndoMark actDoc)
      ); end progn
    ); end if
  (setvar "CMDECHO" oldEcho)
  (setvar "OSMODE" oldOsm)
  (princ)
  ); end of c:per

>pavel
Отсутствует функция STORE :(

Re: LISP. Построение перпендикуляров к любым линейным примитивам

Был небольшой "косячок", если функция отменялась ESC сразу после запкска. Исправил:

(defun c:per(/ oldEcho oldOsm uPnt sSet oldOrt
        sCurve Dr Ang1 Ang2 pt1 pt2 *error*
         actDoc actLay actSp oldSt xl1 xl2)
  (vl-load-com)
  (defun *error* (msg)
    (setvar "ORTHOMODE" oldOrt)
    (command "_.ucs" "_p")
    (command "_.ucs" "_p")
    (setvar "CMDECHO" oldEcho)
    (setvar "OSMODE" oldOsm)
    (if(and xl1 xl2)
      (progn
      (vla-put-Lock actLay :vlax-false)
      (vla-delete xl1)(vla-delete xl2)
      (vla-put-Lock actLay oldSt)
      ); end progn
      ); end if
    (vla-EndUndoMark actDoc)
    (princ)
    ); end of *error*
  (setq oldEcho(getvar "CMDECHO")
        oldOsm(getvar "OSMODE")
        oldOrt(getvar "ORTHOMODE")
   ); end setq
  (setvar "CMDECHO" 0)
  (setvar "OSMODE" 819)
  (command "_.ucs" "_w")
  (setq actDoc(vla-get-ActiveDocument
            (vlax-get-acad-object))
    actLay(vla-get-ActiveLayer actDoc)
    oldSt(vla-get-Lock actLay)
    ); end setq
(vla-StartUndoMark actDoc)
  (if
    (and
    (setq uPnt(getpoint "\nSelect point at line or curve -> "))
    (setq sSet(ssget uPnt '((0 . "*LINE,ARC,ELLIPSE,CIRCLE,RAY,XLINE")
               (-4 . "<NOT")(0 . "MLINE")(-4 . "NOT>"))))
    (setq sCurve(vlax-ename->vla-object(ssname sSet 0)))
    (setq Dr(vlax-curve-getFirstDeriv sCurve
      (vlax-curve-getParamAtPoint sCurve uPnt)))
     ); end and
    (progn
      (if(=(cadr dr) 0.0)
    (setq Ang1 0.0)
    (setq Ang1(- pi(atan(/(car dr)(cadr dr)))))
    ); end if
      (setq Ang2(- Ang1(/ pi 2))
        pt1 (polar uPnt Ang1 1.0)
        pt2 (polar uPnt Ang2 1.0)
        ); end setq
      (if(= 1(vla-get-ActiveSpace actDoc))
    (setq actSp(vla-get-ModelSpace actDoc))
    (setq actSp(vla-get-PaperSpace actDoc))
    ); end if
      (vla-put-Lock actLay :vlax-false)
      (setq xl1(vla-AddXline actSp
         (vlax-3D-point uPnt)
         (vlax-3D-point pt1))
        xl2(vla-AddXline actSp
         (vlax-3D-point uPnt)
         (vlax-3D-point pt2))
        ); end setq
      (vla-put-color xl1 130)
      (vla-put-color xl2 51)
      (vla-Highlight xl1 :vlax-true)
      (vla-Highlight xl2 :vlax-true)
      (command "_.ucs" "_3" uPnt pt1 pt2)
      (setvar "ORTHOMODE" 1)
      (princ "\nSpecify length: ")
      (setvar "OSMODE" 2080)
      (command "_.line" (trans uPnt 0 1) pause "")
      (vla-delete xl1)(vla-delete xl2)
      (vla-put-Lock actLay oldSt)
      (command "_.ucs" "_p")
      (command "_.ucs" "_p")
      (setvar "ORTHOMODE" oldOrt)
      ); end progn
    ); end if
  (setvar "CMDECHO" oldEcho)
  (setvar "OSMODE" oldOsm)
  (vla-EndUndoMark actDoc)
  (princ)
  ); end of c:per

Re: LISP. Построение перпендикуляров к любым линейным примитивам

Может кто-нибуть подсказать ламеру как пользоваться этой прогой?
Т.е. что делать с этим кодом чтобы в акаде появилось возможность строить перпендикуляр?

Re: LISP. Построение перпендикуляров к любым линейным примитивам

> Антимозг
http://dwg.ru/forum/viewtopic.php?t=11445

Re: LISP. Построение перпендикуляров к любым линейным примитивам

Последние две программы не корректно работают, стоится бесконечные ортогональные лучи, относительно наклонного отрезка, назад пользовательская система координат не меняется, после этого кад зависает.
Если возможно проверьте пожалуйста, запускал под 2006 локализованный кад.

Re: LISP. Построение перпендикуляров к любым линейным примитивам

> guest
Вот эту > {Smirnoff} (2005-12-17 12:54:58) тоже запускал под 2006 RUS с установленной пользовательской ПСК. Все работает. Я бы только добавил установку UCSFOLLOW - в 0.

Re: LISP. Построение перпендикуляров к любым линейным примитивам

LISP. Построение перпендикуляров к любым линейным примитивам