Highflybird 发表于 2021-9-9 00:51:01

用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)
    )
)
)
其它具体实现细节请参见附件。

注明:此代码开源,不得做商业用途。转载需注明出处。



ynhh 发表于 2021-9-9 10:53:12

请教高飞大师
您这GIF动画是用什么程序录制的?
能不能上传分享一下。
谢谢

Highflybird 发表于 2021-9-9 11:44:52

本帖最后由 Highflybird 于 2021-9-9 11:47 编辑

ynhh 发表于 2021-9-9 10:53
请教高飞大师
您这GIF动画是用什么程序录制的?
能不能上传分享一下。

screenToGIF,网上一搜就出来了。
screentoGIF官网

ynhh 发表于 2021-9-9 12:40:09

Highflybird 发表于 2021-9-9 11:44
screenToGIF,网上一搜就出来了。
screentoGIF官网

谢谢您的热心帮助和指导
{:1_23:}

tzfcn 发表于 2021-9-9 16:40:12

很好的代码,值得学习、推广。

Michael527 发表于 2021-9-9 20:35:14

谢谢分享,值得收藏的代码

tigcat 发表于 2021-9-9 21:11:09

感谢高飞大神分享知识.

yangjian001 发表于 2021-9-12 09:54:59

做一个热心并受欢迎的人

60ck 发表于 2021-10-9 01:24:29

很棒的代碼,值的收藏
謝謝您的分享

1028882406@qq.c 发表于 2021-10-9 08:08:04

谢谢高版主   不错学习了

Backkom 发表于 2022-3-22 14:23:06

是回复可见吗

蟹岛蟹岛 发表于 2026-2-7 18:25:06

学习~~~~~~~~~~~~~~~~~~~~~~
页: [1]
查看完整版本: 用LISP绘制精确的抛物线和双曲线