- UID
- 118401
- 积分
- 2156
- 精华
- 贡献
-
- 威望
-
- 活跃度
-
- D豆
-
- 在线时间
- 小时
- 注册时间
- 2004-3-28
- 最后登录
- 1970-1-1
|
楼主 |
发表于 2013-5-28 01:44:21
|
显示全部楼层
本帖最后由 Highflybird 于 2013-5-28 01:49 编辑
五、椭圆的相切和相交
[pcode=lisp,true]
;;;*********************************************************************
;;; 五、椭圆的相切和相交
;;;*********************************************************************
;;;=====================================================================
;;; 功能: 数学法求椭圆上一点的切线矢量(相当于vlax-curve-GetFirstDeriv)
;;; 输入: 这点的参数Param,椭圆中心C,长轴方向M,椭圆比率R和椭圆的法线N
;;; 输出: 这点的切线矢量
;;;=====================================================================
(defun ELL:PointTangentOn (Param C M R N / a b v)
(setq a (distance '(0 0 0) M))
(setq b (* R a))
(setq v (list (* (- a) (sin Param)) (* b (cos Param)) 0))
(Mat:mxv (car (ELL:RotationMatrix M N)) v)
)
;;; 切线矢量函数测试
(defun C:PointTangentOn ( / CEN DXF ENT MAJ NRM PAR PNT RAT RET SEL)
(if (setq sel (ssget ":S" '((0 . "ELLIPSE"))))
(progn
(setq ent (ssname sel 0))
(setq dxf (entget ent))
(setq cen (cdr (assoc 10 dxf)))
(setq maj (cdr (assoc 11 dxf)))
(setq rat (cdr (assoc 40 dxf)))
(setq Nrm (cdr (assoc 210 DXF)))
(while (setq Pnt (getpoint "\n选取点: "))
(setq Pnt (trans Pnt 1 0))
(setq pnt (vlax-curve-getclosestpointto ent pnt))
(setq par (vlax-curve-getParamAtPoint ent pnt))
(setq ret (ELL:PointTangentOn par cen maj rat Nrm))
(ent:make_line Pnt (mapcar '+ Pnt ret))
)
(princ)
)
)
)
;;; 上面是也可以由某个点的参数通过数学方法算出。
;;; 一般来说可以由vlax-curve-getFirstDeriv 算出,面是测试如下:
(defun C:TestDeriv (/ e o p param f1 f2)
(if (setq e (car (entsel)))
(progn
(setq o (vlax-ename->vla-object e))
(while (setq p (getpoint "\n测试点:"))
(setq p (trans p 1 0))
(setq p (vlax-curve-getclosestpointto e p))
(setq param (vlax-curve-getParamAtPoint e p))
(setq f1 (vlax-curve-getFirstDeriv e param))
(setq f2 (vlax-curve-getSecondDeriv e param))
(Ent:make_line p (mapcar '+ p f1))
(Ent:make_line p (mapcar '+ p f2))
)
)
)
)
;;;=====================================================================
;;; 功能: 求椭圆(平面)外一点到椭圆的切线
;;; 输入: 椭圆外一点Point,椭圆中心C,椭圆半长轴a,半短轴b,和椭圆的旋转角
;;; 输出: 此点到与椭圆相切的切点(一个,两个或者nil)
;;;=====================================================================
(defun ELL:PointTangentTo (Point C a b ang / AA BB K1 K2 KK P X Y Z XX YY)
(setq Point (mapcar '- Point C))
(setq z (polar '(0 0 0) ang a))
(setq P (trans point 0 z T))
(setq x (caddr p))
(setq y (car p))
(if (equal y 0 1e-8)
(if (> (abs x) a)
(progn
(setq kk (/ a x))
(setq xx (* a kk))
(setq yy (* b (sqrt (- 1 (* kk kk)))))
(list
(mapcar '+ C (trans (list yy 0 xx) z 0 T))
(mapcar '+ C (trans (list (- yy) 0 xx) z 0 T))
)
)
)
(progn
(setq aa (* a a))
(setq bb (* b b))
(setq xx (* x x))
(setq yy (* y y))
(setq k1 (+ (* aa yy) (* bb xx)))
(setq k2 (- k1 (* aa bb)))
(if (> k2 0)
(progn
(defun GetTan (A B C bb K1 X Y Z KK / d1 k4 k5 s1 x1 y1 p1)
(setq d1 (+ (* bb x) kk))
(setq k4 (/ (* d1 x) k1))
(setq k5 (/ (* d1 a) k1))
(setq s1 (atan (/ (* b (- 1 k4)) y) k5))
(setq x1 (* a (cos s1)))
(setq y1 (* b (sin s1)))
(setq P1 (trans (list y1 0 x1) z 0 T))
(setq p1 (mapcar '+ P1 C))
)
(setq kk (* (sqrt k2) (abs y)))
(list (GetTan A B C bb K1 X Y Z kk)
(GetTan A B C bb K1 X Y Z (- kk))
)
)
)
)
)
)
;;; 椭圆的切线函数测试
(defun C:PointTangentTo (/ A ANG B C DXF ENT MAJ PNT RET SEL)
(if (setq sel (ssget ":S" '((0 . "ELLIPSE"))))
(progn
(setq ent (ssname sel 0))
(setq dxf (entget ent))
(setq maj (cdr (assoc 11 dxf)))
(setq a (distance '(0 0 0) maj))
(setq b (* a (cdr (assoc 40 dxf))))
(setq c (cdr (assoc 10 dxf)))
(setq ang (angle '(0 0 0) maj))
(while (setq Pnt (getpoint "\n选取点: "))
(setq Pnt (trans Pnt 1 0))
(setq ret (ELL:PointTangentTo Pnt C a b ang))
(foreach p ret
(Ent:Make_line p Pnt)
)
)
)
)
)
;;;=====================================================================
;;; 关于椭圆的共切线问题请参考:
;;; http://bbs.mjtd.com/forum.php?mod=viewthread&tid=82900
;;; 另外可参考我的附件: ellipse-tan-solve1.LSP
;;;=====================================================================
;;;=====================================================================
;;; 功能: 求椭圆与直线的交点(计算几何方式1)
;;; 输入: 椭圆的长轴a,短轴b,两点P1,P2.
;;; 输出: 直线P1P2与椭圆的交点。
;;; 参考: http://bbs.mjtd.com/thread-62003-2-1.html
;;; RootOf((M^2*a^2+N^2*b^2)*_Z^2-M^2*a^2+L^2+2*L*N*b*_Z)*b
;;;=====================================================================
(Defun ELL:Inters_Ellipse_Line (a b P1 P2 / D E K L M N P PA PB X1 X2 Y1 Y2)
(setq k (/ b (float a)))
(setq X1 (car P1))
(setq X2 (car P2))
(setq Y1 (/ (cadr P1) k))
(setq Y2 (/ (cadr P2) k))
(Setq M (- Y1 Y2)) ;直线方程系数M
(Setq N (- X2 X1)) ;直线方程系数N
(setq D (/ (- (* Y2 X1) (* Y1 X2)) (sqrt (+ (* M M) (* N N))))) ;垂距
(setq e (angle (list x1 y1) (list x2 y2))) ;直线的与X轴线的交角
(setq p (polar '(0 0) (- e (* pi 0.5)) d)) ;圆心到直线的垂足
(setq d (abs d))
(if (equal d a 1e-8) ;如果垂距等于半径
(list (list (car p) (* k (cadr p)))) ;相切
(if (< d a) ;如果垂距小于半径
(progn
(setq L (sqrt (* (+ a d)(- a d)))) ;半弦长
(setq Pa (polar p e (- L)))
(setq Pb (polar p e L))
(setq pa (list (car Pa) (* k (cadr Pa))))
(setq pb (list (car Pb) (* k (cadr Pb))))
(list pa pb) ;有两个交点
)
)
)
)
;;;=====================================================================
;;; 功能: 求椭圆与直线的交点(计算几何方式2,似乎比方式1慢)
;;; 输入: 椭圆的长轴a,短轴b,两点P1,P2.
;;; 输出: 直线P1P2与椭圆的交点。
;;;=====================================================================
(Defun ELL:Inters_Ellipse_Line_1 (a b P1 P2 / K1 K2 K3 M N L MA NB PS X X1 X2 Y Y1 Y2)
(Setq X1 (Car P1))
(Setq Y1 (Cadr P1))
(Setq X2 (Car P2))
(Setq Y2 (Cadr P2))
(Setq M (float (- Y1 Y2))) ;直线方程系数M
(Setq N (float (- X2 X1))) ;直线方程系数N
(Setq L (float (- (* Y2 X1) (* Y1 X2)))) ;直线方程系数L
(setq Nb (* N b))
(if (equal M 0 1e-8) ;水平直线
(cond
( (equal (setq K1 (* (+ Nb L) (- Nb L))) 0 1e-8)
(list (list 0 (- (/ L N))))
)
( (> K1 0)
(setq x (/ (* a (sqrt k1)) Nb))
(setq y (- (/ L N)))
(list (list x y) (list (- x) y))
)
)
(progn
(setq Ma (* M a))
(setq k1 (+ (* Ma Ma) (* Nb Nb)))
(setq k2 (* 2 L Nb))
(setq k3 (- (* L L) (* Ma Ma)))
(foreach e (Math:Quadratic_Equation_1 k1 k2 k3)
(setq x (/ (+ L (* N e b)) (- M)))
(setq y (* e b))
(setq ps (cons (list x y) ps))
)
)
)
)
;;;=====================================================================
;;; 功能: 求平面椭圆与直线的交点
;;; 输入: 椭圆的中心Center,长轴方向major,椭率ratio,两点P1,P2.
;;; 输出: 直线P1P2与椭圆的交点。
;;;=====================================================================
(Defun ELL:Inters_Ellipse_Line_2D (Center major Ratio P1 P2 / v1 v2 a b s)
(setq v1 (mapcar '- p1 center))
(setq v2 (mapcar '- p2 center))
(setq v1 (trans v1 0 major T))
(setq v2 (trans v2 0 major T))
(setq v1 (list (caddr v1) (car v1)))
(setq v2 (list (caddr v2) (car v2)))
(setq a (distance '(0 0 0) major))
(setq b (* ratio a))
(foreach p (ELL:Inters_Ellipse_Line_1 a b v1 v2)
(setq p (trans (list (cadr p) 0 (car p)) major 0 T))
(setq p (mapcar '+ center p))
(setq s (cons p s))
)
)
;;;=====================================================================
;;; 功能: 求空间椭圆与直线的交点(注意,这个交点为在椭圆平面上的交点)
;;; 输入: 椭圆的中心Center,长轴方向major,椭率ratio,法线Normal,两点P1,P2.
;;; 输出: 直线P1P2与椭圆的交点。
;;;=====================================================================
(Defun ELL:Inters_Ellipse_Line_3D (Center major Ratio Normal P1 P2 / A B M1 M2 S V1 V2)
(setq v1 (mapcar '- p1 center))
(setq v2 (mapcar '- p2 center))
(setq m1 (ELL:RotationMatrix major Normal))
(setq m2 (cadr m1))
(setq m1 (car m1))
(setq v1 (mat:mxv m2 v1))
(setq v2 (mat:mxv m2 v2))
(setq a (distance '(0 0 0) major))
(setq b (* ratio a))
(foreach p (ELL:Inters_Ellipse_Line_1 a b v1 v2)
(setq p (mat:mxv m1 (append p '(0))))
(setq p (mapcar '+ center p))
(setq s (cons p s))
)
)
;;; 椭圆的与直线相交函数的测试
(defun C:iel (/ p1 p2 sel ent dxf cen maj rat nrm a b ret)
(initget 1)
(setq P1 (getpoint "\n选取点1: "))
(initget 1)
(setq P2 (getpoint P1 "\n选取点2: "))
(setq p1 (trans p1 1 0))
(setq p2 (trans p2 1 0))
(Ent:Make_Line p1 p2)
(if (setq sel (ssget ":S" '((0 . "ELLIPSE"))))
(progn
(setq ent (ssname sel 0))
(setq dxf (entget ent))
(setq cen (cdr (assoc 10 dxf)))
(setq maj (cdr (assoc 11 dxf)))
(setq rat (cdr (assoc 40 dxf)))
(setq Nrm (cdr (assoc 210 DXF)))
(setq a (distance '(0 0 0) maj))
(setq b (* rat a))
(MISC:test 100
'((ELL:Inters_Ellipse_Line_2d cen maj rat P1 P2)
(ELL:Inters_Ellipse_Line_3d cen maj rat Nrm P1 P2)))
;(setq ret (ELL:Inters_Ellipse_Line_2d cen maj rat P1 P2))
(setq ret (ELL:Inters_Ellipse_Line_3d cen maj rat Nrm P1 P2))
(and ret (mapcar 'Ent:Make_Point ret))
)
)
)
[/pcode]
|
|