Re: Отмерить по линии расстояние и поставить точку

Спасибо! Все работает, но получилось немного не то, что ожидалось, но тоже полезная программа.
Кстати команда на запуск не <D2P>, а <dist2p>.

Мне нужно, чтобы программа возвращала расстояния только от первой точки (от точки указанной при запуске программы): например расстояния между 1 и 2, 1 и 7, 1 и 542, 1 и 10 и т. д.

Чтобы в командной строке было не:
  >>>  ВЫБРАТЬ КРИВУЮ >>>
Первая точка на кривой :
Вторая точка на кривой (или Enter для завершения):
Вторая точка на кривой (или Enter для завершения):

а было:
  >>>  ВЫБРАТЬ КРИВУЮ >>>
Первая точка на кривой :
Вторая  или любая точка на кривой (или Enter для завершения):
Любая точка на кривой (или Enter для завершения):
Любая точка на кривой (или Enter для завершения):

Спасибо!

(изменено: fixo, 20 марта 2012г. 09:07:52)

Re: Отмерить по линии расстояние и поставить точку

Тогда удали ближе к концу:

(setq p1 p2)

Посмотри как оно в деле:

;;---------------------------------   D2p.lsp   ------------------------------------;; 

;; fixo () 2011 * all rights released
;; last edited: 3/20/12
(defun c:D2P ( / *error* a b dimbl dimz dist1 dist2 elist lname mp1 mp2 msg p1 p2 p3 par1 par2 plent pline sp txt)
  (defun *error* (msg)
    (cond ((not msg))
      ((vl-position
         msg
         '("Function cancelled" "quit / exit abort" "console break")
       )
      )
      ((princ (strcat "\nDist2P Command Error: " msg)))
    )
    (if    dimbl
      (setvar "dimldrblk" dimbl)
    )
    (if    dimz
      (setvar "dimzin" dimz)
    )
    (setvar "nomutt" 0)
    (command "_undo" "_end")
    (princ)
  )


  (command "_undo" "_begin")
  (setq dimbl (getvar "dimldrblk"))
  (setvar "dimldrblk" ".")
  (setq dimz (getvar "dimzin"))
  (setvar "dimzin" 0)

    (setq lname "Temp-Text");<---
  (if (not (snvalid lname))(progn
    (alert "Некорректное название слоя\n      Отмена программы...")(exit)(princ)))
  (if (not (tblsearch "layer" lname))
    (entmake
      (list
    '(0 . "LAYER")
    '(100 . "AcDbSymbolTableRecord")
    '(100 . "AcDbLayerTableRecord")
    (cons 2 lname)
    '(70 . 0)
    '(62 . 22);<---
    '(6 . "CONTINUOUS")
    )
      ))
  (setvar "nomutt" 0)
  (prompt "\n    >>>  ВЫБРАТЬ КРИВУЮ >>>\n")
  (setvar "nomutt" 1)

  (while (not (or (and (setq sp (ssget "_+.:S:E" '((0 . "*line")))))))
    (princ "\n\t--->   ВЫБРАТЬ ТОЛЬКО КРИВУЮ!"))
  (setvar "nomutt" 0)
  (setq    plent (ssname sp 0)
    pline (vlax-ename->vla-object plent)
  )
  (setq p1 (getpoint "\nПервая точка на кривой : "))

  (setq msg "\nВторая точка на кривой : ")
    (while (setq p2 (getpoint p1 msg))
         
    
      (progn
(princ "\nТочка вставки текста : ")
   (while (member (car (setq p3 (grread t 15 0))) '(5 2))
     (redraw)
     (if (listp (setq p3 (cadr p3)))
       (progn
     (grdraw p1 p3  1 1)
     (grdraw p2 p3  1 1)

       )
     )
   )
   (setq p3 (cadr p3))

   (setq p1 (vlax-curve-getclosestpointto pline p1))
   (setq par1 (vlax-curve-getparamatpoint pline p1))
   (setq dist1 (vlax-curve-getdistatparam pline par1))
   (setq mp1 (mapcar '(lambda (a b) (/ (+ a b) 2.0)) p1 p3))
   (setq p2 (vlax-curve-getclosestpointto pline p2))
   (setq par2 (vlax-curve-getparamatpoint pline p2))
   (setq dist2 (vlax-curve-getdistatparam pline par2))
   (setq mp2 (mapcar '(lambda (a b) (/ (+ a b) 2.0)) p2 p3))
   (setq txt (rtos (abs (- dist1 dist2)) 2 3));<-- точность 3 знака, изменить по условию


    (setq elist
           (list
         '(0 . "TEXT")
         '(100 . "AcDbEntity")
         '(67 . 0)
         '(410 . "Model")
         (cons 8 lname)
         '(100 . "AcDbText")
         (cons 10 p3)
         (cons 11 (list (car p3) (+ (cadr p3) (/ (* (getvar "textsize")(getvar "dimscale")) 2)) 0.0))
         (cons 40 (* (getvar "textsize")(getvar "dimscale")))
         (cons 1 txt)
         '(50 . 0.0)
         '(41 . 1.0)
         '(51 . 0.0)
         (cons 7 (getvar "textstyle"))
         '(71 . 0)
         '(72 . 0)
         (cons 210 (list 0.0 0.0 1.0))
         '(73 . 2)
           )
    )

(entmake elist)
   (setq msg "\nСледующая точка на кривой (или Enter для завершения): ")
;;;   (setq p1 p2)
    )
      (redraw)
      )
    
  (*error* nil)
  (princ)
)
(prompt "\n   ---   Команда на выполнение \"D2P\" или \"d2p\"  ---") 
(prin1) 
(or (vl-load-com) 
(princ) 
    ) 
;;---------------------------------   D2p.lsp   ------------------------------------;;

[FONT=Arial]~'J'~[/FONT]

Re: Отмерить по линии расстояние и поставить точку

Это ТО ЧТО НАДО!
Большее спасибо! Я уверен, что такая программа пригодиться многим и многим пользователям!

Re: Отмерить по линии расстояние и поставить точку

Пожалуйста :)

[FONT=Arial]~'J'~[/FONT]

(изменено: Вадим Иванов, 9 июня 2012г. 10:04:51)

Re: Отмерить по линии расстояние и поставить точку

Крайний код работает хорошо.Только у меня немного другие условия.Кривая уже поделена на сегменты(отрезки).Вы не могли бы подредактировать код , чтобы не искать начало и конец кривой.Просто щелкнул на кривой и поставил рядом значение.И хотелось , чтобы измеряла также сплайны и дуги.

Re: Отмерить по линии расстояние и поставить точку

Вадим Иванов пишет:

Крайний код работает хорошо.Только у меня немного другие условия.Кривая уже поделена на сегменты(отрезки).Вы не могли бы подредактировать код , чтобы не искать начало и конец кривой.Просто щелкнул на кривой и поставил рядом значение.И хотелось , чтобы измеряла также сплайны и дуги.

Короче тебе нужно проставлять длину отрезков на
середине сегмента?

[FONT=Arial]~'J'~[/FONT]

Re: Отмерить по линии расстояние и поставить точку

Можно и на середине.Но лучше указывать точку вставки . Не знаю как разместить здесь чертеж, а так бы скинул , чтобы было понятно.

Re: Отмерить по линии расстояние и поставить точку

Так будет по середине:

(defun C:PLL ( / ang dir pline pnt sset)
(vl-load-com)
  (while (setq sset (ssget "_:S:E" (list (cons 0 "LINE,*POLYLINE,*CONTOUR,ARC,SPLINE"))))
  (progn
    (setq pline (ssname sset 0))
  (if (eq "ARC" (cdr (assoc 0 (entget pline))))
    (progn
      (setq pline (vlax-ename->vla-object pline))
    (setq pnt (vl-catch-all-apply (function (lambda ()
     (vlax-curve-getclosestpointto pline (vlax-curve-getpointatdist pline (/ (vla-get-arclength pline) 2.)))))))
      )
      (setq pnt (vl-catch-all-apply (function (lambda ()
     (vlax-curve-getclosestpointto pline
       (vlax-curve-getpointatparam pline     
       (/ (- (vlax-curve-getendparam  pline)(vlax-curve-getstartparam  pline))2. ))))))))
    (setq dir(vlax-curve-getFirstDeriv pline
              (vlax-curve-getParamAtPoint pline pnt))
             ang(- pi
                (atan
                  (/(car dir)
                (if(= 0.0(cadr dir))(* 2 pi)(cadr dir)))
                  )
               )
          )

    
     (entmake
       (list (cons 0 "TEXT")
         (cons 10 pnt)
         (cons 7 (getvar "TEXTSTYLE"))
         (cons 40 (getvar "DIMTXT"))      ; <-- change text height to your needs
         (cons 50
               (if (and (> ang 0) (<= ang pi))
             (- ang (/ pi 2))
             (+ ang (/ pi 2))))
         (cons 1
               (rtos (vlax-curve-getdistatparam
                   pline
                   (vlax-curve-getendparam pline))
                 2
                 2))      ; <-- change number of decimals here
         (cons 11 (list (car pnt)(- (cadr pnt)(getvar "DIMTXT"))(cadr pnt)))
         (cons 71 0)
         (cons 72 1)
         (cons 73 1))
       )

  
       )
           )

(princ)
  )
(princ "\nType PLL to execute")
(princ)

[FONT=Arial]~'J'~[/FONT]

Re: Отмерить по линии расстояние и поставить точку

Все работает отлично!Спасибо! А можно сделать чтобы стиль текста был текущий,а то на маленьких деталях он все перекрывает ,а на больших его не видно?

Re: Отмерить по линии расстояние и поставить точку

Замени эту строку:
(cons 40 (getvar "DIMTXT"))
на
(cons 40 <твой размер текста здесь>)

Re: Отмерить по линии расстояние и поставить точку

Спасибо!

Re: Отмерить по линии расстояние и поставить точку

Пожалуйста  :)

[FONT=Arial]~'J'~[/FONT]

Re: Отмерить по линии расстояние и поставить точку

Здравствуйте fixo!
Вашей программой для определения расстояния успешно пользуюсь.
Мне нужно только изменить формат числа: нужно чтобы перед цифрой ставился символ <п> или какой либо другой. Где в коде это место? Например чтобы выводились такие значения: не 547.687 а п547.687 или пк547.687, или даже так п 5+47.69 или пк 5+47.69 или ПК 5+47.69
Спасибо.

Re: Отмерить по линии расстояние и поставить точку

Тебе нужно проставить пикеты?
Тогда нужно еще добавить расстояние между
пикетами (шаг)
Если просто добавить префикс, тогда измени эту строку
(setq txt (rtos (abs (- dist1 dist2)) 2 3));<-- точность 3 знака, изменить по условию

на

(setq txt (strcat "П-" (rtos (abs (- dist1 dist2)) 2 3)));<-- точность 3 знака, изменить по условию

в общем надо будет переписать всю программу, чтобы добавить
возможность выбора префикса и тд
Вернусь попозже,

[FONT=Arial]~'J'~[/FONT]

Re: Отмерить по линии расстояние и поставить точку

Спасибо!
Мне не нужно менять префикс часто. Так что из-за этого не нужно переписывать программу. А ПК по сплайну я проставляю командой measure блоком с определенным шагом (обычно 25 или 50 метров), затем запускаю свою программку на VBA и общелкиваю эти блоки мышкой. Получаю следующие надписи (однострочный текст):
п0+25 п0+50 п0+75... п6+25 п6+50 ... п12+00 п12+25 или с шагом 50м п0+00 п0+50 п1+00 п1+50...
Наверное многим проектировщикам нужна такая программа на Lisp: нужно только добавить при использовании команды <measure> возможность подписывать пикеты автоматически, т.е. нумеровать блоки: пк 0+00 пк 0+25 или п0+00 п0+25 и.т.д.

(изменено: fixo, 10 июня 2012г. 19:50:48)

Re: Отмерить по линии расстояние и поставить точку

А почему на VBA?
запускай через appload

как я понял, нумеруем только пикеты?
промежуточные точки не надо?
конечную точку тоже нумеровать?
как называется блок и как называется атрибут для пикета?

[FONT=Arial]~'J'~[/FONT]

Re: Отмерить по линии расстояние и поставить точку

Я работаю с VBA, потому-что остальные все мои программы на VBA.
А теперь эту операцию я бы хотел перевести на Lisp
Нумеровать (однострочным текстом, не атрибутами) нужно только пикеты и это должна быть отдельная программа. А все промежуточные и конечную точку кривой получаем Вашей программой <D2P>.

Re: Отмерить по линии расстояние и поставить точку

Vladimir Mich пишет:

Я работаю с VBA, потому-что остальные все мои программы на VBA.
А теперь эту операцию я бы хотел перевести на Lisp
Нумеровать (однострочным текстом, не атрибутами) нужно только пикеты и это должна быть отдельная программа. А все промежуточные и конечную точку кривой получаем Вашей программой <D2P>.

Имя блока и имя атрибута?

Re: Отмерить по линии расстояние и поставить точку

Доброго времени суток всем! У меня на локализованной версии почему-то программа не работает. Civil 3D 2012 rus.
На запрос о выборе примитива программа не реагирует. В чем проблема?

Re: Отмерить по линии расстояние и поставить точку

sertor пишет:

Доброго времени суток всем! У меня на локализованной версии почему-то программа не работает. Civil 3D 2012 rus.
На запрос о выборе примитива программа не реагирует. В чем проблема?

Никогда не работал в Civil 3D ,
попробуй набрать в командной строке:

(entget (car (entsel "\nВыбери объект: ))) и посмотри,

какое имя примитива в списке ( 0 . "тут имя примитива")

его и подставь в фильтр выбора

Re: Отмерить по линии расстояние и поставить точку

Вы писали: Имя блока и имя атрибута?
     Имя блока "шп500", атрибута НИ КАКОГО НЕ НАДО, а нужен только ОДНОСТРОЧНЫЙ текст около блока: у первого п0+25, у второго п0+50, у третьего п0+75, у четвертого п1+00, у пятого п1+25, если блок выносится на расстоянии например 2125 метров, то надпись должна быть п21+25. Шаг нужен 25, 50 и 100 метров, перед запуском программы следует это указать пользователю.

Re: Отмерить по линии расстояние и поставить точку

Vladimir Mich пишет:

Вы писали: Имя блока и имя атрибута?
Имя блока "шп500", атрибута НИ КАКОГО НЕ НАДО, а нужен только ОДНОСТРОЧНЫЙ текст около блока: у первого п0+25, у второго п0+50, у третьего п0+75, у четвертого п1+00, у пятого п1+25, если блок выносится на расстоянии например 2125 метров, то надпись должна быть п21+25. Шаг нужен 25, 50 и 100 метров, перед запуском программы следует это указать пользователю.

Понятно, завтра придумаю

Re: Отмерить по линии расстояние и поставить точку

Vladimir, начни отсюда:

;; written by Fatty T.O.H. () 2004 * all rights removed 

;; edited 6/5/10
;; edited 6/10/11
;; edited 6/11/11
;; edited 6/10/12

;; Пикеты

;;load ActiveX library
(vl-load-com)

;;local defuns


;;//
(defun start (curve)
  (vl-catch-all-apply (function (lambda()
  (vlax-curve-getclosestpointto curve
  (vlax-curve-getstartpoint curve
    )
  )
)
    )
  )
  )
;;//
(defun end (curve)
  (vl-catch-all-apply (function (lambda()
  (vlax-curve-getclosestpointto curve
  (vlax-curve-getendpoint curve
    )
  )
)
    )
  )
  )
;;//
(defun pointoncurve (curve pt)
  (vl-catch-all-apply (function (lambda()
  (vlax-curve-getclosestpointto curve
  pt
    )
  )
)
    )
  )
;;//
(defun paramatpoint (curve pt)
  (vl-catch-all-apply (function (lambda()
  (vlax-curve-getparamatpoint curve
  pt
    )
  )
)
    )
  )
;;//
(defun distatpt (curve pt)
  (vl-catch-all-apply (function (lambda()
  (vlax-curve-getdistatpoint curve
    (vlax-curve-getclosestpointto curve pt)
    )
  )
                )
    )
  )
;;//
(defun pointatdist (curve dist)
  (vl-catch-all-apply (function (lambda()
  (vlax-curve-getclosestpointto curve
  (vlax-curve-getpointatdist curve dist)
    )
  )
)
    )
  )
;;//
(defun curvelength (curve)
  (vl-catch-all-apply (function (lambda()
  (vlax-curve-getdistatparam curve
  (- (vlax-curve-getendparam curve)
     (vlax-curve-getstartparam curve)
    )
  )
  )
)
    )
  )
;;//
(defun distatparam (curve param)
  (vl-catch-all-apply (function (lambda()
  (vlax-curve-getdistatparam curve
  param
  )
  )
                )
    )
  )
;;//
(defun statlabel  (num step div)
  ;; num - integer, zero based
  ;; step - double or integer, must be non zero
  
  (strcat
    (itoa (fix (/ num div)))
    "+"
    (if (zerop (rem num div))
      "00"
      (rtos (* (rem num div) step) 2 0))

    )
  )



;;// written by VovKa (Vladimir Kleshev)
(defun gettangent (curve pt)
  
     (setq param (paramatpoint curve pt)
           ang ((lambda (deriv)
           (if (zerop (cadr deriv))
             (/ pi 2)
             (atan (apply '/ deriv))
           )
         )
          (cdr (reverse
             (vlax-curve-getfirstderiv curve param)
               )
          )
        )
)
  ang
  )

;;---------------------- main program -----------------------------;;

(defun c:DPK (/ *error* acsp adoc block cnt div en ent label
           lastp lay leng lnum mul num pt rot sign start step txh txt)
  
  (defun *error* (msg)
         
     (vla-endundomark
       (vla-get-activedocument (vlax-get-acad-object))
       )
    (cond ((not msg))
      ((vl-position
         msg
         '("Function cancelled" "quit / exit abort" "console break")
       )
      )
      ((princ (strcat "\nDist2P Command Error: " msg)))
    )
    (if    clay
      (setvar "celayer" clay)
    )
    (if    dimz
      (setvar "dimzin" dimz)
    )
  
    (princ)
  )
  
  (setvar "dimzin" 2)
  (setq lay (getvar "clayer"))
  (setvar "clayer" "0")
  
  (setq adoc    (vla-get-activedocument (vlax-get-acad-object))
       acsp    (vla-get-block (vla-get-activelayout adoc))
     )
  

 (while    (not
      (and
        (or
          (initget 6)
          (setq step (getreal "\nВведите шаг <25>: "))
          (if (not step)
        (setq step 25.)))
        (zerop (rem 100 step))))
   (alert (strcat "\nОстаток от деления 100 на шаг / " (rtos step 2 2) " не равен нулю,
          \nВведен некорректный шаг"))
   )
   (initget  "Yes No ")
   (setq ans (getkword "\nВставить префикс? (Y/N) <Y>:"))
   (setq pref  (if (not ans )(lisped   "ПК") ""))
   (setq txh (cond
          ((getdist (strcat "\nВведите высоту текста  [ Enter для подтверждения ]: <" (rtos  (getvar "dimtxt") 2 1) ">: ")))
          (txh)
          ))
(if

  (setq
    ent    (entsel
      "\nУказать кривую ближе к её началу >>"
      )
    )

   (progn
     

     (setq en    (car ent)
       pt    (pointoncurve en (cadr ent))
       leng    (distatparam en (vlax-curve-getendparam en))
       )

     (setq num (fix (/ leng step))
       )

     (setq div (fix (/ 100. step)
            )
       )

     (setq mul (- leng
          (* (setq lnum (fix (/ leng (* step div)))) (* step div))))

     (if (not (zerop mul))
       (setq lastp T)
       (setq lastp nil)
       )

     (if (> (- (paramatpoint en pt)
           (paramatpoint en (vlax-curve-getstartpoint en))
           )
        (- (paramatpoint en (vlax-curve-getendpoint en))
           (paramatpoint en pt)
           )
        )
       (progn
     (setq start leng
           sign  -1
           )
     )
       (progn

     (setq start (distatparam en (vlax-curve-getstartparam en))
           sign  1
           )
     )
       )


     (vla-startundomark
       (vla-get-activedocument (vlax-get-acad-object))
       )
     (setq cnt 0)
     (repeat (1+ num)
       (setq pt     (pointatdist en start)
         rot (gettangent en pt)
         )
       (setq txt (vla-addtext  acsp (strcat pref (statlabel cnt step div)) (vlax-3d-point pt) txh))
       (vla-put-rotation txt (+ rot(/ pi 2)))

       (setq cnt   (1+ cnt)
         start (+ start (* sign step))
         )
       )


     (if lastp
       (progn

     (if (= sign -1)
       (progn
         (setq pt  (vlax-curve-getstartpoint en)
           rot (gettangent en pt)
           )
         )
       (progn
         (setq pt  (vlax-curve-getendpoint en)
           rot (gettangent en pt)
           )
         )
       )


     (setq label (strcat (itoa lnum) "+" (rtos mul 2 2))
           )
           (setq txt (vla-addtext  acsp  (strcat pref label) (vlax-3d-point pt) txh))
       (vla-put-rotation txt (+ rot(/ pi 2)))

     )
       )

     )
   (princ "\nНичего не выбрано")
   )
  (*error* nil)
  (princ)
)
(prompt "\n   ---   Команда на выполнение \"DPK\" или \"dpk\"  ---") 
(prin1) 
(or (vl-load-com) 
(princ) 
    )

[FONT=Arial]~'J'~[/FONT]

Re: Отмерить по линии расстояние и поставить точку

fixo,

Опять же хочу возвратиться к своей проблеме. При запросе на выбор кривой программа выдает ошибку: Dist2P Command Error: ActiveX Server возвратил ошибку: Параметр является обязательным. Тестировал на AutoCAD 2013.Визуально видно, что выбор не происходит. Может еще какие-нибудь варианты будут на этот счет. Спасибо.

Re: Отмерить по линии расстояние и поставить точку

Набери в командной строке:

(entget (car (entsel "\nВыбери объект: )))

и выбери объект, какое у него будет название,
скопируй результат из командного окна и выложи сюда,

[FONT=Arial]~'J'~[/FONT]