用LISP绘制精确的抛物线和双曲线
首先说一下,圆锥曲线在CAD中是有精确画法的。可以不用拟合方式或者很多个顶点的多段线模拟绘制。这样绘制出来的抛物线是样条曲线,仅仅用三个控制点,就能满足高精度要求。
关于这个精确画法,请参考我的下面的帖子:圆锥曲线在AutoCAD的精确表达法
因此根据这个画法,在这篇帖子里,对抛物线,我提供了三种画法的LISP程序:
下面是其动画演示:
三点式的核心代码如下:
;;;=============================================================
;;; 功能: 根据抛物线上三点获取获取圆锥曲线参数
;;; 输入: 抛物线上三点p1,p2,p3 (点表,至少二维)
;;; 输出: CAD中的抛物线的三点
;;;=============================================================
(defun MATH:GetArgumentsBy3P (p1 p2 p3 / A B C DX1 DX2 DX3 DY1
DY2 DY3 Q1 Q2 Q3 X1 X2 X3 Y1 Y2 Y3)
(mapcar 'set '(p1 p2 p3) (ALG:Sort3PbyX p1 p2 p3))
(mapcar 'set '(x1 x2 x3) (mapcar 'car (list p1 p2 p3)))
(mapcar 'set '(y1 y2 y3) (mapcar 'cadr (list p1 p2 p3)))
(if (not (GEO:Colinearity p1 p2 p3))
(setq dx1 (- x1 x2)
dx2 (- x2 x3)
dx3 (- x3 x1)
dy1 (- y1 y2)
dy2 (- y2 y3)
dy3 (- y3 y1)
dx1 (float dx1)
A (/ (- (* dx1 dy2) (* dx2 dy1)) (* dx1 dx2 dx3))
B (- (/ dy1 dx1) (* A (+ x1 x2)))
C (- y1 (* A x1 x1) (* B x1))
q1(polar p1 (atan (+ (* 2 A x1) B)) 666)
q3(polar p3 (atan (+ (* 2 A x3) B)) 666)
q2(list p1 (inters p1 q1 p3 q3 nil) p3 1)
)
)
)
;;;=============================================================
;;; 功能: 根据抛物线系数获取圆锥曲线参数
;;; 输入: 抛物线系数a,b,c和上下界m,n以及相对点(插入点)
;;; 输出: 抛物线的两端点及其切线交点
;;;=============================================================
(defun MATH:GetArgumentsByEquation (a b c m n p / P1 P2 P3 Q1 Q3)
(setq p1 (list m (+ (* m m a) (* b m) c) 0.0))
(setq p3 (list n (+ (* n n a) (* b n) c) 0.0))
(setq q1 (polar p1 (atan (+ (* 2 a m) b)) 666))
(setq q3 (polar p3 (atan (+ (* 2 a n) b)) 666))
(if (setq p2 (inters p1 q1 p3 q3 nil))
(list (mapcar '+ p p1) (mapcar '+ p p2) (mapcar '+ p p3) 1)
)
)
下面我继续介绍如何画双曲线:
经过研究,形成双曲线spline的三点对于P1,P3是容易得到的。对于P2点按照如下方式计算:
其中p2的权重取值为x/a.
其实当x取一些特殊值的时候,容易得到更简易的画法,譬如当x=2a的时候,以a=5,b=3为例,画法如下:
下面是用程序画出双曲线的演示:
双曲线的核心代码如下:
;;;=============================================================
;;; 功能: 获取圆锥曲线参数的子函数
;;; 参数: 两个半轴长度la,lb和中心坐标cx,cy以及四点X值,是否Y对称
;;; 返回: 两条SPLINE的参数(三个点和权重)
;;;-------------------------------------------------------------
(defun Ent:GetSplineOfConic (la lb cx cy x1 x2 x3 x4 isY /
d1 d2 d3 d4 px py qx qy mx nx wt)
(setq d1 (abs (- x1 cx)))
(setq d2 (abs (- x2 cx)))
(setq d3 (abs (- x3 cx)))
(setq d4 (abs (- x4 cx)))
(setq px (max d1 d2 d3 d4)) ;起点X值
(setq wt (/ px la)) ;第二点权重
(setq py (* lb (sqrt (1- (* wt wt))))) ;起点Y值-->此处要检查能否开平方?
(setq mx (/ la wt)) ;控制点坐标
(setq Qy (- cy py))
(setq Py (+ cy py))
(setq Qx (- cx px))
(setq Px (+ cx px))
(setq Nx (- cx mx))
(setq Mx (+ cx mx))
(if isY
(list
(list (list py px) (list cy mx) (list qy px) wt)
(list (list py qx) (list cy nx) (list qy qx) wt)
)
(list
(list (list px py) (list mx cy) (list px qy) wt)
(list (list qx py) (list nx cy) (list qx qy) wt)
)
)
)
其它具体实现细节请参见附件。
注明:此代码开源,不得做商业用途。转载需注明出处。
请教高飞大师
您这GIF动画是用什么程序录制的?
能不能上传分享一下。
谢谢
本帖最后由 Highflybird 于 2021-9-9 11:47 编辑
ynhh 发表于 2021-9-9 10:53
请教高飞大师
您这GIF动画是用什么程序录制的?
能不能上传分享一下。
screenToGIF,网上一搜就出来了。
screentoGIF官网
Highflybird 发表于 2021-9-9 11:44
screenToGIF,网上一搜就出来了。
screentoGIF官网
谢谢您的热心帮助和指导
{:1_23:} 很好的代码,值得学习、推广。 谢谢分享,值得收藏的代码 感谢高飞大神分享知识. 做一个热心并受欢迎的人 很棒的代碼,值的收藏
謝謝您的分享 谢谢高版主 不错学习了 是回复可见吗 学习~~~~~~~~~~~~~~~~~~~~~~
页:
[1]