Author Topic: Lisp to get coordinates of tangent of a circle?  (Read 237 times)

0 Members and 1 Guest are viewing this topic.

Vikram

  • Newt
  • Posts: 37
Lisp to get coordinates of tangent of a circle?
« on: December 30, 2019, 07:30:19 AM »
I want a lisp which can give me coordinates of the tangent of the circle. It should display the coordinates of the tangent on command line or it should write the coordinates on a text file.
I have attached a image of sample drawing.

Grrr1337

  • Swamp Rat
  • Posts: 714
Re: Lisp to get coordinates of tangent of a circle?
« Reply #1 on: December 30, 2019, 11:43:53 AM »
Simply:
Code - Auto/Visual Lisp: [Select]
  1. (defun f ( circle pline / p )
  2.   (setq p (vlax-curve-getClosestPointTo pline (cdr (assoc 10 (entget circle)))))
  3.   (if (vlax-curve-getParamAtPoint circle p) p)
  4. )

or something like:
Code - Auto/Visual Lisp: [Select]
  1. (defun f ( circle pline / r )
  2.   (mapcar 'set '(circle pline) (mapcar 'vlax-ename->vla-object (list circle pline)))
  3.   (setq r
  4.     (
  5.       '((f L)(f L))
  6.       '((L)(if L (cons (list (car L) (cadr L) (caddr L)) (f (cdddr L)))))
  7.       (vlax-invoke circle 'IntersectWith pline acExtendNone)
  8.     )
  9.   )
  10.   (cond
  11.     ( (null r) (alert "\nObjects don't touch") )
  12.     ( (= 1 (length r)) (car r) )
  13.     ( (<= 2 (length r)) (alert "\nObjects intersect each other") )
  14.   )
  15. )

...
Code - Auto/Visual Lisp: [Select]
  1. (f
  2.   (car (entsel "\nPick Circle: "))
  3.   (car (entsel "\nPick Pline: "))
  4. )
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)

roy_043

  • Water Moccasin
  • Posts: 1747
  • BricsCAD 18
Re: Lisp to get coordinates of tangent of a circle?
« Reply #2 on: December 30, 2019, 12:46:46 PM »
The OP uses IntelliCAD which does not have any VL* functions.
See here:
https://www.theswamp.org/index.php?topic=55648.0

Grrr1337

  • Swamp Rat
  • Posts: 714
Re: Lisp to get coordinates of tangent of a circle?
« Reply #3 on: December 30, 2019, 06:03:29 PM »
The OP uses IntelliCAD which does not have any VL* functions.
See here:
https://www.theswamp.org/index.php?topic=55648.0

Duh, thats so.. annoying.
Still I think its solvable - with some math (which I'm bad at it) and Lee Mac's help -

Code - Auto/Visual Lisp: [Select]
  1. (defun C:test ( / pl SS Point i )
  2.   (and
  3.     (setq pl (car (entsel "\nPick pline: ")))
  4.     (setq SS (ssget "_:L-I" '((0 . "CIRCLE"))))
  5.     (defun Point (pt)(if pt (entmakex (list (cons 0 "POINT")(cons 10 pt)))))
  6.     (repeat (setq i (sslength SS))
  7.       (Point (_GetCirclePlineTangentPoint (ssname SS (setq i (1- i))) pl))
  8.     )
  9.   )
  10.   (princ)
  11. )
  12.  
  13.  
  14. (defun _GetCirclePlineTangentPoint ( circle pline / cr p L mid tmp dis lc bc seg r )
  15.   (and
  16.     circle pline
  17.     (setq cr (cdr (assoc 40 (entget circle)))) ; circle radius
  18.     (setq p (cdr (assoc 10 (entget circle))))
  19.     (setq L (_PlineInfo pline))
  20.     (setq mid (lambda (p1 p2) (mapcar '(lambda (a b) (* 0.5 (+ a b))) p1 p2)))
  21.    
  22.     (foreach itm (cdr L)
  23.       (setq lc (mid (cadr itm) (caddr itm))) ; line center
  24.       (setq dis (distance lc p))
  25.       (if (setq bc (nth 6 itm)) ; bulge center
  26.         (setq dis (min dis (distance bc p)))
  27.       )
  28.       (and (or (not tmp) (> tmp dis)) (setq tmp dis) (setq seg itm) )
  29.     ); foreach
  30.   ); and
  31.   (if (setq bc (nth 6 seg))
  32.     (setq r (polar bc (angle bc p) (nth 7 seg)))
  33.     (setq r (inters (cadr seg) (caddr seg) p (polar p (+ (* 0.5 PI) (angle (cadr seg) (caddr seg))) (distance (cadr seg) (caddr seg))) nil))
  34.   ); if
  35.   ; (Point r)
  36.   (if (not (equal (distance r p) cr 1e-6))
  37.     (prompt "\nThe circle is not tangent ot the pline.")
  38.     r
  39.   ); if
  40. ); defun _GetCirclePlineTangentPoint
  41.  
  42.  
  43. ;; Modified sub, taken from here:
  44. ;; http://www.lee-mac.com/lisp/html/PolyInfoV1-3.html
  45. (defun _PlineInfo ( pline /  LM:lwvertices LM:bulgeradius LM:bulgecentre )
  46.  
  47.   ;; LW Vertices  -  Lee Mac
  48.   ;; Returns a list of lists in which each sublist describes
  49.   ;; the position, starting width, ending width and bulge of the
  50.   ;; vertex of a supplied LWPolyline
  51.  
  52.   (defun LM:lwvertices ( e )
  53.     (if (setq e (member (assoc 10 e) e))
  54.       (cons (list (assoc 10 e) (assoc 40 e) (assoc 41 e) (assoc 42 e) ) (LM:lwvertices (cdr e)))
  55.     )
  56.   )
  57.  
  58.   ;; Bulge Radius  -  Lee Mac
  59.   ;; p1 - start vertex
  60.   ;; p2 - end vertex
  61.   ;; b  - bulge
  62.   ;; Returns the radius of the arc described by the given bulge and vertices
  63.  
  64.   (defun LM:bulgeradius ( p1 p2 b ) (/ (* (distance p1 p2) (1+ (* b b))) 4 (abs b)))
  65.  
  66.   ;; Bulge Centre  -  Lee Mac
  67.   ;; p1 - start vertex
  68.   ;; p2 - end vertex
  69.   ;; b  - bulge
  70.   ;; Returns the centre of the arc described by the given bulge and vertices
  71.  
  72.   (defun LM:bulgecentre ( p1 p2 b ) (polar p1 (+ (angle p1 p2) (- (/ pi 2) (* 2 (atan b)))) (/ (* (distance p1 p2) (1+ (* b b))) 4 b)))
  73.  
  74.  
  75.   ( ; Main
  76.     (lambda ( pline / _vl-some enx lst seg flg )
  77.      
  78.       (setq _vl-some ; (_vl-some '(lambda (x) (if (= (* x x) (* 2 x)) x)) '(9 8 7 2 4 6 7 3)) >> 2
  79.         (lambda (tf L)
  80.           (cond
  81.             ( (not L) L)
  82.             ( (apply tf (list (car L))) )
  83.             ( (_vl-some tf (cdr L)) )
  84.           ); cond
  85.         ); lambda
  86.       ); setq _vl-some
  87.      
  88.       (if
  89.         (and
  90.           (eq 'ENAME (type pline))
  91.           (setq enx (entget pline))
  92.           (member '(0 . "LWPOLYLINE") enx)
  93.           (setq lst (LM:lwvertices enx))
  94.           (setq seg 0)
  95.         )
  96.         (cons
  97.           (append '(SEG START END WIDTH1 WIDTH2 LENGTH)
  98.             (if (setq flg (_vl-some '(lambda ( x ) (not (zerop (cdr (assoc 42 x))))) lst))
  99.               '(CENTRE RADIUS)
  100.             )
  101.           )
  102.           (mapcar
  103.             (function
  104.               (lambda ( l1 l2 / b p q )
  105.                 (setq
  106.                   p (cdr (assoc 10 l1))
  107.                   q (cdr (assoc 10 l2))
  108.                   b (cdr (assoc 42 l1))
  109.                 )
  110.                 (append
  111.                   (list (setq seg (1+ seg))) ; seg #
  112.                   (list
  113.                     p ; start
  114.                     q ; end
  115.                   )
  116.                   (list
  117.                     (cdr (assoc 40 l1)) ; width 1
  118.                     (cdr (assoc 41 l1)) ; width 2
  119.                   )
  120.                   (if (zerop b)
  121.                     (cons  (distance p q) (if flg '(() ()))) ; length
  122.                     (append
  123.                       (list (abs (* (LM:bulgeradius p q b) (atan b) 4))) ; bulge-length
  124.                       (list (LM:bulgecentre p q b)) ; centre
  125.                       (list (LM:bulgeradius p q b)) ; radius
  126.                     )
  127.                   )
  128.                 )
  129.               )
  130.             )
  131.             lst
  132.             (if (= 1 (logand 1 (cdr (assoc 70 enx))))
  133.               (append (cdr lst) (list (car lst)))
  134.               (cdr lst)
  135.             )
  136.           )
  137.         )
  138.       ); if
  139.     ); lambda
  140.     pline
  141.   )
  142. ); defun _PlineInfo
(apply ''((a b c)(a b c))
  '(
    (( f L ) (apply 'strcat (f L)))
    (( L ) (if L (cons (chr (car L)) (f (cdr L)))))
    (72 101 108 108 111 32 87 111 114 108 100)
  )
)

Vikram

  • Newt
  • Posts: 37
Re: Lisp to get coordinates of tangent of a circle?
« Reply #4 on: December 31, 2019, 12:25:46 AM »
Thanks for your time @Grrr1337. Your lisp is throwing me the error: "bad SSGET mode string"
Yes Im using Intellicad even I am fed up with the lisp compatibility of this product. They have poor forum to resolve the issues so I have to be dependent on Autocad forum.
I tired both the lisp first one throwed invalid argument. So I used second one.
Code: [Select]
(defun C:test ( / pl SS Point i )
  (and
    (setq pl (car (entsel "\nPick pline: ")))
    (setq SS (ssget "_:L-I" '((0 . "CIRCLE"))))
    (defun Point (pt)(if pt (entmakex (list (cons 0 "POINT")(cons 10 pt)))))
    (repeat (setq i (sslength SS))
      (Point (_GetCirclePlineTangentPoint (ssname SS (setq i (1- i))) pl))
    )
  )
  (princ)
)
 
 
(defun _GetCirclePlineTangentPoint ( circle pline / cr p L mid tmp dis lc bc seg r )
  (and
    circle pline
    (setq cr (cdr (assoc 40 (entget circle)))) ; circle radius
    (setq p (cdr (assoc 10 (entget circle))))
    (setq L (_PlineInfo pline))
    (setq mid (lambda (p1 p2) (mapcar '(lambda (a b) (* 0.5 (+ a b))) p1 p2)))
   
    (foreach itm (cdr L)
      (setq lc (mid (cadr itm) (caddr itm))) ; line center
      (setq dis (distance lc p))
      (if (setq bc (nth 6 itm)) ; bulge center
        (setq dis (min dis (distance bc p)))
      )
      (and (or (not tmp) (> tmp dis)) (setq tmp dis) (setq seg itm) )
    ); foreach
  ); and
  (if (setq bc (nth 6 seg))
    (setq r (polar bc (angle bc p) (nth 7 seg)))
    (setq r (inters (cadr seg) (caddr seg) p (polar p (+ (* 0.5 PI) (angle (cadr seg) (caddr seg))) (distance (cadr seg) (caddr seg))) nil))
  ); if
  ; (Point r)
  (if (not (equal (distance r p) cr 1e-6))
    (prompt "\nThe circle is not tangent ot the pline.")
    r
  ); if
); defun _GetCirclePlineTangentPoint
 
 
;; Modified sub, taken from here:
;; http://www.lee-mac.com/lisp/html/PolyInfoV1-3.html
(defun _PlineInfo ( pline /  LM:lwvertices LM:bulgeradius LM:bulgecentre )
 
  ;; LW Vertices  -  Lee Mac
  ;; Returns a list of lists in which each sublist describes
  ;; the position, starting width, ending width and bulge of the
  ;; vertex of a supplied LWPolyline
 
  (defun LM:lwvertices ( e )
    (if (setq e (member (assoc 10 e) e))
      (cons (list (assoc 10 e) (assoc 40 e) (assoc 41 e) (assoc 42 e) ) (LM:lwvertices (cdr e)))
    )
  )
 
  ;; Bulge Radius  -  Lee Mac
  ;; p1 - start vertex
  ;; p2 - end vertex
  ;; b  - bulge
  ;; Returns the radius of the arc described by the given bulge and vertices
 
  (defun LM:bulgeradius ( p1 p2 b ) (/ (* (distance p1 p2) (1+ (* b b))) 4 (abs b)))
 
  ;; Bulge Centre  -  Lee Mac
  ;; p1 - start vertex
  ;; p2 - end vertex
  ;; b  - bulge
  ;; Returns the centre of the arc described by the given bulge and vertices
 
  (defun LM:bulgecentre ( p1 p2 b ) (polar p1 (+ (angle p1 p2) (- (/ pi 2) (* 2 (atan b)))) (/ (* (distance p1 p2) (1+ (* b b))) 4 b)))
 
 
  ( ; Main
    (lambda ( pline / _vl-some enx lst seg flg )
     
      (setq _vl-some ; (_vl-some '(lambda (x) (if (= (* x x) (* 2 x)) x)) '(9 8 7 2 4 6 7 3)) >> 2
        (lambda (tf L)
          (cond
            ( (not L) L)
            ( (apply tf (list (car L))) )
            ( (_vl-some tf (cdr L)) )
          ); cond
        ); lambda
      ); setq _vl-some
     
      (if
        (and
          (eq 'ENAME (type pline))
          (setq enx (entget pline))
          (member '(0 . "LWPOLYLINE") enx)
          (setq lst (LM:lwvertices enx))
          (setq seg 0)
        )
        (cons
          (append '(SEG START END WIDTH1 WIDTH2 LENGTH)
            (if (setq flg (_vl-some '(lambda ( x ) (not (zerop (cdr (assoc 42 x))))) lst))
              '(CENTRE RADIUS)
            )
          )
          (mapcar
            (function
              (lambda ( l1 l2 / b p q )
                (setq
                  p (cdr (assoc 10 l1))
                  q (cdr (assoc 10 l2))
                  b (cdr (assoc 42 l1))
                )
                (append
                  (list (setq seg (1+ seg))) ; seg #
                  (list
                    p ; start
                    q ; end
                  )
                  (list
                    (cdr (assoc 40 l1)) ; width 1
                    (cdr (assoc 41 l1)) ; width 2
                  )
                  (if (zerop b)
                    (cons  (distance p q) (if flg '(() ()))) ; length
                    (append
                      (list (abs (* (LM:bulgeradius p q b) (atan b) 4))) ; bulge-length
                      (list (LM:bulgecentre p q b)) ; centre
                      (list (LM:bulgeradius p q b)) ; radius
                    )
                  )
                )
              )
            )
            lst
            (if (= 1 (logand 1 (cdr (assoc 70 enx))))
              (append (cdr lst) (list (car lst)))
              (cdr lst)
            )
          )
        )
      ); if
    ); lambda
    pline
  )
); defun _PlineInfo

I have attached the dxf file to the thread for reference.