本帖最后由 highflybir 于 2012-11-17 22:56 编辑
收集了一些与椭圆相关的程序和链接:
一 椭圆的几个基本参数:
DXF 组码中的几个数值
10 中心点
11 长轴矢量
40 长短比率
41 起点角度
42 终点角度
210 法线矢量
这些参数可以由entget得到,也可以由activeX方法得到。
注意 起点角度和终点角度的计算,如果是不是椭圆弧,是全椭圆,则这个数值为:0和2*Pi
如果是椭圆弧,则如图;
vlax-curve-getParamAtPoint 其中的参数指的就是这点的角度值(用弧度表示)。
椭圆的离心率由椭圆的长短比率得出。- (sqrt (- 1 (* ratio ratio)))
离心率越大圆就越扁,越小则越接近于圆.
二 椭圆上某点的切线:
可以由vlax-curve-getFirstDeriv 算出 也可以由某个点的参数通过数学方法算出。
三 空间椭圆的变换矩阵
由椭圆的长轴矢量,和短轴矢量以及法线矢量可以构成椭圆的自身的变换坐标系。- ;;;下面程序用以获得椭圆的变换矩阵。
- (defun Mat:GetEllipseTransMatrix (e / dxf Nrm Cen Maj Mnr ptb DX DY DZ mat)
- (defun AppendToMatrix (mat org)
- (append
- (mapcar 'append mat (mapcar 'list org))
- '((0. 0. 0. 1.))
- )
- )
- (setq dxf (entget e))
- (setq Nrm (cdr (assoc 210 dxf)))
- (setq Cen (cdr (assoc 10 dxf)))
- (setq Maj (cdr (assoc 11 dxf)))
- (setq PtB (vlax-curve-getPointAtParam e (/ pi 2)))
- (setq Mnr (mapcar '- ptb cen))
- (setq DX (Mat:unit Maj))
- (setq DY (Mat:unit Mnr))
- (setq DZ (Mat:unit Nrm))
- (setq mat (list DX DY DZ))
- (list
- (AppendToMatrix mat (mapcar '- (Mat:mxv mat cen))) ;WCS->OCS 由世界坐标系变换到物体坐标系
- (AppendToMatrix (Mat:trp mat) cen) ;OCS->WCS 由物体坐标系变换到世界坐标系
- )
- )
- ;;;以下为测试程序
- (defun c:test1 (/ sel ent mat obj doc)
- (if (setq sel (ssget ":S" '((0 . "ELLIPSE"))))
- (progn
- (setq doc (vla-get-ActiveDocument (vlax-get-acad-object)))
- (vla-StartUndoMark doc)
- (setq ent (ssname sel 0))
- (setq mat (Mat:GetEllipseTransMatrix ent))
- (setq obj (vlax-ename->vla-object ent))
- (vla-transformby obj (vlax-tmatrix (car mat)))
- (command "Select" ent pause)
- (vla-transformby obj (vlax-tmatrix (cadr mat)))
- (vla-EndUndoMark doc)
- (princ)
- )
- )
- )
- ;;;相关矩阵函数;;;----------------------------------------------------;
- ;;; 向量的模(长度) ;
- ;;; Vector Norm - Lee Mac ;
- ;;; Args: v - vector in R^n ;
- ;;;----------------------------------------------------;
- (defun MAT:norm ( v )
- (sqrt (apply '+ (mapcar '* v v)))
- )
- ;;;----------------------------------------------------;
- ;;; 向量乘标量(系数) ;
- ;;; Vector x Scalar - Lee Mac ;
- ;;; Args: v - vector in R^n, s - real scalar ;
- ;;;----------------------------------------------------;
- (defun MAT:vxs ( v s )
- (mapcar '(lambda ( n ) (* n s)) v)
- )
- ;;;----------------------------------------------------;
- ;;; 单位向量 ;
- ;;; Unit Vector - Lee Mac ;
- ;;; Args: v - vector in R^n ;
- ;;;----------------------------------------------------;
- (defun MAT:unit ( v )
- ( (lambda ( n )
- (if (equal 0.0 n 1e-14)
- nil
- (MAT:vxs v (/ 1.0 n))
- )
- )
- (MAT:norm v)
- )
- )
- ;;;----------------------------------------------------;
- ;;; 向量的点积 ;
- ;;; MAT:vxv Returns the dot product of 2 vectors ;
- ;;;----------------------------------------------------;
- (defun MAT:vxv (v1 v2)
- (apply '+ (mapcar '* v1 v2))
- )
- ;;;----------------------------------------------------;
- ;;; 两向量的叉积 ;
- ;;; Vector Cross Product - Lee Mac ;
- ;;; Args: u,v - vectors in R^3 ;
- ;;;----------------------------------------------------;
- (defun MAT:v^v ( u v )
- (list
- (- (* (cadr u) (caddr v)) (* (cadr v) (caddr u)))
- (- (* (car v) (caddr u)) (* (car u) (caddr v)))
- (- (* (car u) (cadr v)) (* (car v) (cadr u)))
- )
- )
- ;;;----------------------------------------------------;
- ;;; 矩阵转置 ;
- ;;; MAT:trp Transpose a matrix -Doug Wilson- ;
- ;;;----------------------------------------------------;
- (defun MAT:trp (m)
- (apply 'mapcar (cons 'list m))
- )
- ;;;----------------------------------------------------;
- ;;; 向量的矩阵变换(向量乘矩阵) ;
- ;;; Matrix x Vector - Vladimir Nesterovsky ;
- ;;; Args: m - nxn matrix, v - vector in R^n ;
- ;;;----------------------------------------------------;
- (defun MAT:mxv (m v)
- (mapcar (function (lambda (r) (apply '+ (mapcar '* r v)))) m)
- )
- ;;;----------------------------------------------------;
- ;;; 点到矩阵的变换 ;
- ;;;----------------------------------------------------;
- (defun MAT:mxp (m p)
- (reverse (cdr (reverse (MAT:mxv m (append p '(1.0))))))
- )
- ;;;----------------------------------------------------;
- ;;; 矩阵相乘 ;
- ;;; MAT:mxm Multiply two matrices -Vladimir Nesterovsky;
- ;;;----------------------------------------------------;
- (defun MAT:mxm (m q)
- (mapcar (function (lambda (r) (MAT:mxv (MAT:trp q) r))) m)
- )
如果椭圆位于图块内或者嵌套块内,关于其变换矩阵可以参考这个帖子的讨论:http://bbs.mjtd.com/thread-93828-1-1.html|;
这个地方的讨论已经很深入了。
四 椭圆的几种创建:
0. 由基本要素的创建。
- ;;;=====================================================
- ;;;功能: 画一个椭圆或者椭圆弧
- ;;;参数: 中心,长轴,短轴和旋转角度,起始角度,终点角度
- ;;;返回: 一个椭圆实体
- ;;;=====================================================
- (defun Make-Ellipse (cen a b ang an1 an2 / m n an)
- (if (> b a)
- (setq m b n a an (+ ang (/ pi 2)))
- (setq m a n b an ang)
- )
- (entmakeX
- (list
- '(0 . "ELLIPSE")
- '(100 . "AcDbEntity")
- '(100 . "AcDbEllipse")
- (cons 10 cen)
- (cons 11 (polar '(0. 0. 0.) an m))
- (cons 40 (/ n m 1.0))
- (cons 41 an1)
- (cons 42 an2)
- )
- )
- )
1. 四点画水平椭圆。
参见:http://bbs.mjtd.com/thread-91856-1-1.html
2. 已知椭圆的圆心和椭圆上的三点创建一个椭圆。
参见:http://bbs.mjtd.com/thread-91856-1-1.html
3. 已知椭圆的四条切线创建一个水平椭圆。
参见:http://bbs.mjtd.com/forum.php?mod=viewthread&tid=55068
4. 过五点画椭圆,有几何解法,
参见:http://bbs.mjtd.com/forum.php?mo ... 45&page=1#pid410208- (defun ELL:5PEllipse (p1 p2 p3 p4 p5 / p12 p23 p34 p45 t2 t3 t4 t23 t34 t45 cen)
- (setq p12 (inters p5 p1 p2 p3 nil))
- (setq p23 (inters p1 p2 p3 p4 nil))
- (setq p34 (inters p2 p3 p4 p5 nil))
- (setq p45 (inters p3 p4 p5 p1 nil))
- (setq t2 (inters p12 p23 p4 p5 nil))
- (setq t3 (inters p23 p34 p5 p1 nil))
- (setq t4 (inters p34 p45 p1 p2 nil))
- (setq t23 (inters t2 p2 t3 p3 nil))
- (setq t34 (inters t3 p3 t4 p4 nil))
- (setq m23 (midpt p2 p3))
- (setq m34 (midpt p3 p4))
- (setq cen (inters t23 m23 t34 m34 nil))
- (Mat:C3P-Ellipse cen p2 p3 p4)
- )
- (defun midpt (p1 p2)
- (mapcar (function (lambda (x) (* x 0.5))) (mapcar '+ p1 p2))
- )
- (defun c:test5 (/ p1 p2 p3 p4 p5 ret)
- (initget 1)
- (setq p1 (getpoint "\n输入第一点:"))
- (initget 1)
- (setq p2 (getpoint "\n输入第二点:"))
- (initget 1)
- (setq p3 (getpoint "\n输入第三点:"))
- (initget 1)
- (setq p4 (getpoint "\n输入第四点:"))
- (initget 1)
- (setq p5 (getpoint "\n输入第五点:"))
- (setq ret (ELL:5PEllipse p1 p2 p3 p4 p5))
- (apply 'Ell:Make-Ellipse ret)
- (princ)
- )
五 椭圆的曲率问题
如果要在CAD中几何作图,可以参考此贴:
http://bbs.mjtd.com/thread-62980-1-1.html
下面程序为获取椭圆的曲率和转弯半径。
- ;;;=====================================================
- ;;;功能: 获取椭圆上一点处的曲率和转弯半径
- ;;;参数: 椭圆实体和椭圆上的一点
- ;;;返回: 此处离心圆圆心、转弯半径及其曲率(离心率)
- ;;;=====================================================
- (defun ELL:GetCurvature (en pt / dxf maj rat a b p par x y k v1 v2 rad cen)
- (setq dxf (entget en))
- (setq maj (cdr (assoc 11 dxf)))
- (setq rat (cdr (assoc 40 dxf)))
- (setq a (distance '(0 0) maj))
- (setq b (* a rat))
- (setq p (vlax-curve-getclosestpointto en pt))
- (setq par (vlax-curve-getParamAtPoint en p))
- (setq v1 (vlax-curve-getFirstDeriv en par))
- (setq v2 (list (- (cadr v1)) (car v1) (caddr v1)))
- (setq x (* a (cos par)))
- (setq y (* b (sin par)))
- (setq k (expt rat 4))
- (setq rad (/ (expt (+ (* y y) (* k x x)) 1.5) rat rat b b))
- (setq cen (polar p (angle '(0 0 0) v2) rad))
- (list cen rad (/ 1 rad))
- )
- ;;;测试程序:
- (defun c:test2 (/ sel ent dxf pnt ret)
- (setq sel (nentselp "\n选取椭圆:"))
- (if (and (setq ent (car sel))
- (setq dxf (entget ent))
- (= "ELLIPSE" (cdr (assoc 0 dxf)))
- )
- (progn
- (setq pnt (cadr sel))
- (setq ret (ELL:GetCurvature ent (trans pnt 1 0)))
- (princ ret)
- (entmakeX
- (list
- '(0 . "CIRCLE")
- (cons 10 (car ret))
- (cons 40 (cadr ret))
- )
- )
- )
- )
- (princ)
- )
六 Steiner椭圆问题。
参见:
http://bbs.mjtd.com/thread-96417-1-1.html
下面为程序:
七 椭圆的包围盒和最小包围盒
- (defun c:test3 (/ i sel ent lst obj pta ptb p1 p2 p3 p4 t0)
- (setq i 0)
- (if (setq sel (ssget '((0 . "ELLIPSE"))))
- (progn
- (repeat (sslength sel)
- (setq ent (ssname sel i))
- (setq obj (vlax-ename->vla-object ent))
- (setq lst (vla-getboundingbox obj 'pta 'ptb))
- (setq pta (vlax-safearray->list pta))
- (setq ptb (vlax-safearray->list ptb))
- (setq p1 (list (car pta) (cadr pta)))
- (setq p2 (list (car ptb) (cadr pta)))
- (setq p3 (list (car ptb) (cadr ptb)))
- (setq p4 (list (car pta) (cadr ptb)))
- (entmake
- (list
- '(0 . "LWPOLYLINE")
- '(100 . "AcDbEntity")
- '(100 . "AcDbPolyline")
- '(90 . 4)
- '(70 . 1)
- (cons 10 p1)
- (cons 10 p2)
- (cons 10 p3)
- (cons 10 p4)
- )
- )
- (setq i (1+ i))
- )
- )
- )
- (princ)
- )
最小包围盒:
- ;;;获取椭圆的最小包围盒
- (defun ELL:GetMinBox (ent / CEN DXF EN MAJ P1 P2 P3 P4 PTB PTD)
- (setq dxf (entget ent))
- (setq cen (cdr (assoc 10 dxf)))
- (setq maj (cdr (assoc 11 dxf)))
- (setq ptb (vlax-curve-getPointAtParam en (* pi 0.5)))
- (setq ptd (vlax-curve-getPointAtParam en (* pi 1.5)))
- (setq p1 (mapcar '- ptd maj))
- (setq p2 (mapcar '+ ptd maj))
- (setq p3 (mapcar '+ ptb maj))
- (setq p4 (mapcar '- ptb maj))
- (list p1 p2 p3 p4)
- )
- ;;;测试程序
- (defun c:test4 (/ sel ent ret e)
- (if (setq sel (ssget ":S" '((0 . "ELLIPSE"))))
- (progn
- (setq ent (ssname sel 0))
- (setq ret (ELL:getMinBox ent))
- (setq e (Entmake (list '(0 . "POLYLINE")'(70 . 9))))
- (foreach p (reverse ret)
- (entmake (list '(0 . "VERTEX")'(70 . 32)(cons 10 p)))
- )
- (entmake '((0 . "SEQEND")))
- )
- )
- (princ)
- )
八 椭圆拟合问题:
http://bbs.mjtd.com/thread-56692-1-1.html
下面的帖子是用圆弧拟合椭圆的讨论:
http://bbs.mjtd.com/thread-86496-3-1.html
九 椭圆的公切线问题
http://bbs.mjtd.com/forum.php?mod=viewthread&tid=82900
十 椭圆的与直线的相交问题
http://bbs.mjtd.com/thread-62003-2-1.html
十一 最似圆椭圆问题
http://bbs.mjtd.com/thread-62903-1-1.html
以下是程序:
十二 椭圆JIG教程
http://bbs.mjtd.com/forum.php?mod=viewthread&tid=66579
十三 椭圆的UCS投影
http://www.theswamp.org/index.php?topic=43031.0
http://bbs.mjtd.com/forum.php?mod=viewthread&tid=84527
下面为相关程序:
十四 椭圆和多段线转化
如果以前系统变量pellipse设置为1时候画的椭圆,现在想转化为CAD的椭圆实体,则可以用如下程序。
- ;;;把以前用多段线画的椭圆改成真实的椭圆。
- (defun ELL:GetEllipseFromPoly (poly / pts pt0 pt1 pt2 pt3 cen a b rat maj)
- (defun Get-3dpoly-Coordinates (poly / v e l)
- (setq v (entnext poly))
- (while (/= (cdr (assoc 0 (setq e (entget v)))) "SEQEND")
- (setq l (cons (cdr (assoc 10 e)) l)
- v (entnext v)
- )
- )
- (reverse l)
- )
- (setq pts (Get-3dpoly-Coordinates poly))
- (setq pt0 (car pts))
- (setq pt1 (nth 4 pts))
- (setq pt2 (nth 8 pts))
- (setq pt3 (nth 12 pts))
- (setq cen (mapcar '* (mapcar '+ pt0 pt2) '(0.5 0.5 0.5)))
- (setq a (distance cen pt0))
- (setq b (distance cen pt1))
- (setq rat (/ b a))
- (setq maj (mapcar '- pt0 cen))
- (list cen maj rat)
- )
- ;;;测试程序
- (defun c:test5(/ pl ret)
- (setq pl (car (entsel)))
- (setq ret (ELL:GetEllipseFromPoly pl))
- (entmakeX
- (list
- '(0 . "ELLIPSE")
- '(100 . "AcDbEntity")
- '(100 . "AcDbEllipse")
- (cons 10 (car ret))
- (cons 11 (cadr ret))
- (cons 40 (caddr ret))
- )
- )
- (princ)
- )
相反转化则较为简单,设置pellipse系统变量为1,在CAD命令下重新构建那个椭圆则可。
十五 椭圆周长和面积问题
关于周长问题,可以参考如下帖子。
http://bbs.mjtd.com/forum.php?mod=viewthread&tid=82654&page=1#pid434059
面积问题则较为简单,可以用Pi*a*b计算出来。或者用vla-get-area得出结果。
|