sunny_8848 发表于 2025-4-18 08:23:00

画相切圆弧

本帖最后由 sunny_8848 于 2025-4-18 14:52 编辑

要求见图。
情形①已知两个圆半径(125),两圆圆心间距是(127),两圆心连线偏移(133),画圆与两小圆及上述偏移出来的直线相切,修剪后得到4段圆弧。
情形②已知两个圆半径(125),两圆圆心间距是(127),与上述两个圆相切的第三个圆半径(370),画出第三个相切圆,上下两段圆弧顶点间距(266)修剪后得到4段圆弧。
情形③已知两个圆半径(125),两圆圆心间距是(127),画与上述两个圆相切的第三个圆,其切点与圆心连线与竖直轴向夹角为14,修剪后得到4段圆弧。
请帮忙写一个lsp文件,上述圆半径等参数在命令行输入。
其实就是几个条件组合,满足3个条件就行。小圆半径和两圆心间距肯定是已知的,有时知道夹角,有时知道大圆半径370,有时知道上下两段圆弧距离是266而已





夏生生 发表于 2025-4-18 08:23:01

本帖最后由 夏生生 于 2025-4-19 12:21 编辑

更新了一下,采用算点法,避免了原来的视口问题,最好用这个
(defun c:tt(/xty-tanxty-acos ang dis1 dis2 m pt pt1pt2 pt3pt4 pt5pt6 pt7pt8 ptar1 r2)
(defunxty-tan   (ang)
((lambda (x)
    (if(equal 0. x 1e-14)
   nil
   (/ (sin ang) x)))      (cos ang)))
(defunxty-acos(num)
(if (zerop num)
   (* pi 0.5)
   (atan (sqrt (- 1.0 (* num num))) num)))
(setq ***tt-r1***    (if ***tt-r1***
         ***tt-r1***
         125)
       ***tt-dis1***(if ***tt-dis1***
         ***tt-dis1***
         127)
       ***tt-r2***    (if ***tt-r2***
         ***tt-r2***
         370)
       ***tt-ang***   (if ***tt-ang***
         ***tt-ang***
         14)
       ***tt-dis2***(if ***tt-dis2***
         ***tt-dis2***
         133)
       pt      '(0 0 0)
       pta      (getpoint "\n插入点:")
       r1      (getreal
         (strcat "\n两圆半径<" (rtos ***tt-r1*** 2 3) ">:"))
       r1      (if r1
         (setq ***tt-r1*** r1)
         ***tt-r1***)
       dis1      (getreal
         (strcat "\n两圆心距:<" (rtos ***tt-dis1*** 2 3) ">:"))
       dis1      (if dis1
         (setq ***tt-dis1*** dis1)
         ***tt-dis1***)
       dis1      (* 0.5 dis1)
       ***tt-kword*** (if ***tt-kword***
         ***tt-kword***
         "Off"))
(initget "Off Ang Rad")
(setq m (getkword
    (strcat "\n已知条件[偏线距(Off)/夹角(Ang)/半径(Rad)]<"
      ***tt-kword***
      ">")))
(if (null m)
(setq m ***tt-kword***))
(setq ***tt-kword*** m)
(cond
((eq m "Ang")
   (setq ang(getreal
         (strcat "\n夹角(角度)<" (rtos ***tt-ang*** 2 3) ">:"))
   ang(if ang
         (setq ***tt-ang*** ang)
         ***tt-ang***)
   ang(* pi (/ ang 180.))
   dis2 (+ r1 (* (xty-tan (* 0.5 ang)) dis1))))
((eq m "Off")
   (setq dis2 (getreal
         (strcat "\n偏线距<" (rtos ***tt-dis2*** 2 3) ">:"))
   dis2 (if dis2
         (setq ***tt-dis2*** dis2)
         ***tt-dis2***)
   ang(* 2 (atan (- dis2 r1) dis1))))
((eq m "Rad")
   (setq r2   (getreal
         (strcat "\n外接圆半径<" (rtos ***tt-r2*** 2 3) ">:"))
   r2   (if r2
         (setq ***tt-r2*** r2)
         ***tt-r2***)
   ang(- (* 0.5 pi) (xty-acos (/ dis1 (- r2 r1))))
   dis2 (- r2 (* (cos ang) (- r2 r1)))))
)
(setq pt1 (polar pt pi dis1)
       pt1 (polar pt1 (+ (* 0.5 pi) ang) r1)
       pt1 (mapcar '+ pt1 pta))
(setq pt2 (polar pt pi (+ r1 dis1))
       pt2 (mapcar '+ pt2 pta))
(setq pt3 (polar pt pi dis1)
       pt3 (polar pt3 (- (* 1.5 pi) ang) r1)
       pt3 (mapcar '+ pt3 pta))
(setq pt4 (polar pt (* 1.5 pi) dis2)
       pt4 (mapcar '+ pt4 pta))
(setq pt5 (polar pt 0 dis1)
       pt5 (polar pt5 (+ (* 1.5 pi) ang) r1)
       pt5 (mapcar '+ pt5 pta))
(setq pt6 (polar pt 0 (+ r1 dis1))
       pt6 (mapcar '+ pt6 pta))
(setq pt7 (polar pt 0 dis1)
       pt7 (polar pt7 (- (* 0.5 pi) ang) r1)
       pt7 (mapcar '+ pt7 pta))
(setq pt8 (polar pt (* 0.5 pi) dis2)
       pt8 (mapcar '+ pt8 pta))
(vl-cmdf "arc" "none" pt1 "none" pt2 "none" pt3)
(vl-cmdf "arc" "none" pt3 "none" pt4 "none" pt5)
(vl-cmdf "arc" "none" pt5 "none" pt6 "none" pt7)
(vl-cmdf "arc" "none" pt7 "none" pt8 "none" pt1)
;;; (vl-cmdf "pline" "none" pt1 "a" "s" "none" pt2    "none" pt3 "s" "none" pt4 "none" pt5 "s" "none"    pt6 "none"pt7"cl");_如采用lwpline将pt8可以注释掉

(princ))
采用作图法,容易出现视口问题,也就是图元在视口外的时候捕捉不到点
(以下为正确示例)

(defun c:tt(/xty-tan xty-acos ang dis1 dis2 en1 en2 en3 en4 mpt pt1 pt2 pt3 pt4 pt5 pt6 pt7 pt8 pta r1 r2)
(defunxty-tan   (ang)
((lambda (x)
    (if(equal 0. x 1e-14)
   nil
   (/ (sin ang) x)))      (cos ang)))
(defunxty-acos(num)
(if (zerop num)
   (* pi 0.5)
   (atan (sqrt (- 1.0 (* num num))) num)))
(setq pt      '(0 0 0)
       pta      (getpoint "\n插入点:")
       r1      (getreal "\n两圆半径:")
       dis1      (* 0.5 (getreal "\n两圆心距:"))
       ***tt-kword*** (if ***tt-kword***
         ***tt-kword***
         "Off"))
(vl-cmdf "circle" "none" (polar pt pi dis1) r1)
(setq en1 (vlax-ename->vla-object (entlast)))
(vl-cmdf "circle" "none" (polar pt 0 dis1) r1)
(setq en2 (vlax-ename->vla-object (entlast)))
(vl-cmdf "zoom"
    "w"
    (list (* 3 (- 0 r1 dis1)) (* 3 (- 0 r1 dis1)))
    (list (* 3 (+ r1 dis1)) (* 3 (+ r1 dis1))))
(initget "Off Ang Rad")
(setq m (getkword
    (strcat "\n已知条件[偏线距(Off)/夹角(Ang)/半径(Rad)]<"
      ***tt-kword***
      ">")))
(if (null m)
(setq m ***tt-kword***))
(setq ***tt-kword*** m)
(cond ((eq m "Off")
(setq dis2 (getreal "\n偏线距:")))
       ((eq m "Ang")
(setq ang(getreal "\n夹角(角度):")
      ang(* pi (/ ang 180.))
      dis2 (+ (* r1 (cos ang))
          (* (+ (* r1 (sin ang)) dis1) (xty-tan (* 0.5 ang))))))
       ((eq m "Rad")
(setq r2   (getreal "\n外接圆半径:")
      ang(- (* 0.5 pi) (xty-acos (/ dis1 (- r2 r1))))
      dis2 (+ (* r1 (cos ang))
          (* (+ (* r1 (sin ang)) dis1) (xty-tan (* 0.5 ang)))))))
(vl-cmdf "line"
    "none"
    (mapcar '+ pt (list (- dis1) dis2 0))
    "none"
    (mapcar '+ pt (list dis1 dis2 0))
    "")
(setq en3 (vlax-ename->vla-object (entlast)))
(setq pt7 (list 0 dis2 0)
       pt4 (list 0 (- dis2) 0)
       pt2 (list (- 0 r1 dis1) 0 0)
       pt6 (list (+ r1 dis1) 0 0))
(vl-cmdf "circle" "3p" "tan" pt2 "tan" pt6 "tan" pt7)
(setq en4 (vlax-ename->vla-object (entlast)))
(setq pt1 (vlax-safearray->list
      (vlax-variant-value(vla-intersectwith en1 en4 acExtendBoth))))
(setq pt7 (vlax-safearray->list
      (vlax-variant-value(vla-intersectwith en2 en4 acExtendBoth))))
(setq pt8 (vlax-safearray->list
      (vlax-variant-value(vla-intersectwith en3 en4 acExtendBoth))))
(setq pt3 (list (car pt1) (- (cadr pt1)) (caddr pt1)))
(setq pt5 (list (car pt7) (- (cadr pt7)) (caddr pt7)))
(setq pt1 (mapcar '+ pt1 pta))
(setq pt2 (mapcar '+ pt2 pta))
(setq pt3 (mapcar '+ pt3 pta))
(setq pt4 (mapcar '+ pt4 pta))
(setq pt5 (mapcar '+ pt5 pta))
(setq pt6 (mapcar '+ pt6 pta))
(setq pt7 (mapcar '+ pt7 pta))
(setq pt8 (mapcar '+ pt8 pta))
(foreach n (list en1 en2 en3 en4) (vla-delete n))
(vl-cmdf "arc" "none" pt1 "none" pt2 "none" pt3)
(vl-cmdf "arc" "none" pt3 "none" pt4 "none" pt5)
(vl-cmdf "arc" "none" pt5 "none" pt6 "none" pt7)
(vl-cmdf "arc" "none" pt7 "none" pt8 "none" pt1)
(vl-cmdf "zoom" "p")
(princ))
用算点算的,公式推错了,这个代码就作为错误示例放在这里吧,警示后人:lol
(以下为错误示例)

(defun c:tt(/      xty-acos ang dis1 dis2 m pt pt1 pt2 pt3 pt4 pt5 pt6 pt7 pt8 pta r1 r2)
(defun      xty-acos(num)
(if (zerop num)
   (* pi 0.5)
   (atan (sqrt (- 1.0 (* num num))) num)))
(setq pt            '(0 0 0)
       pta            (getpoint "\n插入点:")
       r1            (getreal "\n两圆半径:")
       dis1            (* 0.5 (getreal "\n两圆心距:"))
       ***tt-kword*** (if ***tt-kword***
                     ***tt-kword***
                     "Off"))
(initget "Off Ang Rad")
(setq m (getkword
          (strcat "\n已知条件[偏线距(Off)/夹角(Ang)/半径(Rad)]<"
                  ***tt-kword***
                  ">")))
(if (null m)
(setq m ***tt-kword***))
(setq ***tt-kword*** m)
(cond ((eq m "Ang")
      (setq ang(getreal "\n夹角(角度):")
            ang(* pi (/ ang 180.))
            dis2 (+ r1 (* 0.5 dis1 (sin (* 0.5 ang))))))
       ((eq m "Off")
      (setq dis2 (getreal "\n偏线距:")
            ang(- (* 0.5 pi) (xty-acos (/ (* 2. (- dis2 r1)) dis1)))))
       ((eq m "Rad")
      (setq r2   (getreal "\n外接圆半径:")
            ang(- (* 0.5 pi) (xty-acos (/ dis1 (- r2 r1))))
            dis2 (+ r1 (* 0.5 dis1 (sin (* 0.5 ang)))))))
(setq pt1 (polar pt pi dis1)
       pt1 (polar pt1 (+ (* 0.5 pi) ang) r1)
       pt1(mapcar'+ pt1 pta))
(setq pt2 (polar pt pi (+ r1 dis1))pt2(mapcar'+ pt2 pta))
(setq pt3 (polar pt pi dis1)
       pt3 (polar pt3 (- (* 1.5 pi) ang) r1)pt3(mapcar'+ pt3 pta))
(setq pt4 (polar pt (* 1.5 pi) dis2)pt4(mapcar'+ pt4 pta))
(setq pt5 (polar pt 0 dis1)
       pt5 (polar pt5 (+ (* 1.5 pi) ang) r1)pt5(mapcar'+ pt5 pta))
(setq pt6 (polar pt 0 (+ r1 dis1))pt6(mapcar'+ pt6 pta))
(setq pt7 (polar pt 0 dis1)
       pt7 (polar pt7 (- (* 0.5 pi) ang) r1)pt7(mapcar'+ pt7 pta))
(setq pt8 (polar pt (* 0.5 pi) dis2)pt8(mapcar'+ pt8 pta))
(vl-cmdf"arc""none" pt1 "none"pt2 "none"pt3)
(vl-cmdf"arc""none" pt3 "none"pt4 "none"pt5)
(vl-cmdf"arc""none" pt5 "none"pt6 "none"pt7)
(vl-cmdf"arc""none" pt7 "none"pt8 "none"pt1)
(princ))

lijiao 发表于 2025-4-18 09:37:28

(setq pt1 (getpoint))
(setq pt2 (getpoint pt1))
(setq line1 (vla-addline (vla-get-ModelSpace (VLA-GET-ACTIVEDOCUMENT (VLAX-GET-ACAD-OBJECT)))
              (VLAX-3D-POINT pt1) (VLAX-3D-POINT pt2)))
(setq minr (getdist pt2))
(setq circle1 (vla-addcircle (vla-get-ModelSpace (VLA-GET-ACTIVEDOCUMENT (VLAX-GET-ACAD-OBJECT)))
                (VLAX-3D-POINT pt1) minr))
(setq circle2 (vla-addcircle (vla-get-ModelSpace (VLA-GET-ACTIVEDOCUMENT (VLAX-GET-ACAD-OBJECT)))
                (VLAX-3D-POINT pt2) minr))
(setq ang12 (angle pt1 pt2))
(setq dist12 (distance pt1 pt2))
(setq ptm (polar pt1 ang12 (* 0.5 dist12)))
(setq pianju (getdist ptm))
(setq maxr (/ (+ (* pianju pianju) (* -1 minr minr) (* 0.25 dist12 dist12)) (* 2 (- pianju minr))))
(setq ptc1 (polar ptm (+ ang12 (* 0.5 pi)) (- maxr pianju)))
(setq ptc2 (polar ptm (- ang12 (* 0.5 pi)) (- maxr pianju)))
(setq arc1 (vla-addarc (vla-get-ModelSpace (VLA-GET-ACTIVEDOCUMENT (VLAX-GET-ACAD-OBJECT)))
                (VLAX-3D-POINT ptc1) maxr (angle ptc1 pt1) (angle ptc1 pt2)))
(setq arc2 (vla-addarc (vla-get-ModelSpace (VLA-GET-ACTIVEDOCUMENT (VLAX-GET-ACAD-OBJECT)))
                (VLAX-3D-POINT ptc2) maxr (angle ptc2 pt2) (angle ptc2 pt1)))
(setq arc3 (vla-addarc (vla-get-ModelSpace (VLA-GET-ACTIVEDOCUMENT (VLAX-GET-ACAD-OBJECT)))
                (VLAX-3D-POINT pt1) minr (angle ptc2 pt1) (angle ptc1 pt1)))
(setq arc4 (vla-addarc (vla-get-ModelSpace (VLA-GET-ACTIVEDOCUMENT (VLAX-GET-ACAD-OBJECT)))
                (VLAX-3D-POINT pt2) minr (angle ptc1 pt2) (angle ptc2 pt2)))
(vla-delete line1)
(vla-delete circle1)
(vla-delete circle2)

sunny_8848 发表于 2025-4-18 10:25:50

lijiao 发表于 2025-4-18 09:37


谢谢帮忙,上述代码在已知两圆半径、两圆心间距及第3个圆顶点间距的这种效果挺好的。能麻烦您增加下已知两圆半径和两圆心间距,然后是第三个相切圆半径或切线与垂直轴夹角这两种情形吗

sunny_8848 发表于 2025-4-18 13:11:12

夏生生 发表于 2025-4-18 11:59
用算点算的,由于算了角度,所以有时候误差不小,最好是用画法

谢谢帮忙。画图思路就是我想要的,只是输入第三个圆的半径或切线角度时,得到的圆和第一种方法有点差别,能麻烦您完善下吗

夏生生 发表于 2025-4-18 13:56:21

sunny_8848 发表于 2025-4-18 13:11
谢谢帮忙。画图思路就是我想要的,只是输入第三个圆的半径或切线角度时,得到的圆和第一种方法有点差别, ...

有角度计算,必然误差大,无法避免的,你自己的三个已知数,相互反算就对不上,可以按计算器试试

sunny_8848 发表于 2025-4-18 14:46:47

我找到偏差大的原因了,您是按切点与小圆圆心连线算角度,实际应该是切点与大圆圆心连线的角度。

sunny_8848 发表于 2025-4-18 14:52:19

夏生生 发表于 2025-4-18 13:56
有角度计算,必然误差大,无法避免的,你自己的三个已知数,相互反算就对不上,可以按计算器试试

我的参数是用约束求出的,不知道是否约束错了。麻烦您再看看,我感觉是角度那里的计算,您是采用切点与小圆圆心连线,实际我是需要切点与大圆的连线与垂直轴的夹角

uualice2020 发表于 2025-4-18 15:37:12

sunny_8848 发表于 2025-4-18 14:52
我的参数是用约束求出的,不知道是否约束错了。麻烦您再看看,我感觉是角度那里的计算,您是采用切点与小 ...

(setq ang(* (getreal "\n夹角(角度):") 2)

夏生生 发表于 2025-4-18 17:12:18

sunny_8848 发表于 2025-4-18 14:52
我的参数是用约束求出的,不知道是否约束错了。麻烦您再看看,我感觉是角度那里的计算,您是采用切点与小 ...

在四楼改了,试一下,如果您自己能推出2和3的公式可以用错误示例去改
页: [1] 2
查看完整版本: 画相切圆弧