画相切圆弧
本帖最后由 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-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)) (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) lijiao 发表于 2025-4-18 09:37
谢谢帮忙,上述代码在已知两圆半径、两圆心间距及第3个圆顶点间距的这种效果挺好的。能麻烦您增加下已知两圆半径和两圆心间距,然后是第三个相切圆半径或切线与垂直轴夹角这两种情形吗 夏生生 发表于 2025-4-18 11:59
用算点算的,由于算了角度,所以有时候误差不小,最好是用画法
谢谢帮忙。画图思路就是我想要的,只是输入第三个圆的半径或切线角度时,得到的圆和第一种方法有点差别,能麻烦您完善下吗 sunny_8848 发表于 2025-4-18 13:11
谢谢帮忙。画图思路就是我想要的,只是输入第三个圆的半径或切线角度时,得到的圆和第一种方法有点差别, ...
有角度计算,必然误差大,无法避免的,你自己的三个已知数,相互反算就对不上,可以按计算器试试 我找到偏差大的原因了,您是按切点与小圆圆心连线算角度,实际应该是切点与大圆圆心连线的角度。
夏生生 发表于 2025-4-18 13:56
有角度计算,必然误差大,无法避免的,你自己的三个已知数,相互反算就对不上,可以按计算器试试
我的参数是用约束求出的,不知道是否约束错了。麻烦您再看看,我感觉是角度那里的计算,您是采用切点与小圆圆心连线,实际我是需要切点与大圆的连线与垂直轴的夹角 sunny_8848 发表于 2025-4-18 14:52
我的参数是用约束求出的,不知道是否约束错了。麻烦您再看看,我感觉是角度那里的计算,您是采用切点与小 ...
(setq ang(* (getreal "\n夹角(角度):") 2) sunny_8848 发表于 2025-4-18 14:52
我的参数是用约束求出的,不知道是否约束错了。麻烦您再看看,我感觉是角度那里的计算,您是采用切点与小 ...
在四楼改了,试一下,如果您自己能推出2和3的公式可以用错误示例去改
页:
[1]
2