明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 30602|回复: 61

[【高飞鸟】] 【越飞越高讲堂11】一个高效率的凸包算法!

    [复制链接]
发表于 2006-11-14 19:30 | 显示全部楼层 |阅读模式

关于凸包的算法有很多种,我在这里提供一种算法,称之为:“礼品包扎法”。

下面是它的lisp程序和附件,加载程序,运行test ,选取点,直线或多义线即可。

;;;************************************************************************
;;;一个求点集合的凸包的lisp程序--------------------------------------------
;;;------采用的算法为礼品包扎法--------------------------------------------
;;;方法为最右端的点开始处理,将该点作为凸包边界的第一个点P1,从最初的垂直线
;;;方向绕P1顺时针旋转,直到碰到另一个P2这就是凸包边界的第二个点P2,依此类推
;;;p2求得p3......直到又重新回到p1,已经考虑了各种退化情况和浮点运算,其算法
;;;时间不超过O(n.h),其中h是凸包的复杂度,时间还是很快的。大家不妨验证。   
;;;参考文献<<计算几何-算法及其应用>>(第二版),以及参考了其他网站的一些源代码
;;;------------------------------------------------------------------------
;;;其中程序主段是核心算法,其他的附加程序为取得点集,画凸包边界线,测试大量
;;;点集函数处理所花费的时间。----------------------------------------------
;;;用法: 加载lisp运行test选取点,直线段,或多义线(全是直线段组成)即可。----
;;;************************************************************************
(defun C:test(/ olderr en errmsg oldmode oce sl ss t1 t2 ptlist usetime pp)
  ;;定义错误函数和预处理--------------------
  (setvar "errno" 0)
  (setq olderr *error*)
  (defun *error* (msg)
    (setq en (getvar "errno"))
    (setq errmsg (strcat "errno=" (itoa en) "\nError:" msg))
    (alert errmsg)
    (setq *error* olderr)
  )
  (graphscr)
  (setq oldmode (getvar "osmode"))
  (setq oce (getvar "cmdecho"))
  (setvar "cmdecho" 0)
  (command ".ucs" "W")
  ;;也可以用其他方式取得点集----------------
  ;;取点,画点,并对函数用时计算------------
  (setq sl ' ( (-4 . "<OR" )
       (0 . "POINT")
       (0 . "LINE")
       (0 . "POLYLINE")
       (0 . "LWPOLYLINE")
       (-4 . "OR>" )))
  (setq ss (ssget sl))
  (setq ptlist (ssgetpoint1 ss))
  (setq t1 (getvar "CDATE"))
  (setq pp (hull ptlist))
  (setq t2 (getvar "CDATE"))
  (setq usetime (* (- t2 t1) 1e6))
  (princ (strcat "\n用时=" (rtos usetime 2 6) "秒"))
  (if (= nil pp)
    (progn
      (alert "点的有效数目太小,请重新输入!")
      (command ".ucs" "p")
      (setvar "osmode" oldmode)
      (setvar "cmdecho" oce)
      (princ "\n")
      (princ)
    )
    (progn
      ;;画凸包边界线------------------------
      (setvar "osmode" 0)
      (entmake
        (append
          '((0 . "lwpolyline")(100 . "AcDbEntity")(100 . "AcDbPolyline"))
          (list (cons 90 (length pp)))
          (mapcar '(lambda (x) (cons 10 (list (car x) (cadr x)))) pp)
          (list (cons 70 1))(list (cons 62 1))
        )
      )
      (command ".ucs" "P")
      (setvar "osmode" oldmode)
      (setvar "cmdecho" oce)
      (princ "\n")
      pp
    )
  )
)
;;;*****************************************
;;;程序主段,可以单独成为函数---------------
(defun hull (ptlist / pfirst p0 p1 pmax1 pmax2 pp)
  (cond
    ((= (length ptlist) 0)
      nil
    )
    ((or nil (= (length ptlist) 1) (= (length ptlist) 2))
     (progn
      (alert "你输入的点为两点或一点!")
      ptlist
     )
    )
    (t
     (progn
      ;;定义矢量之叉积,即二阶行列式之值-----
      (defun det2 (p1 p2)
 (- (* (car p1) (cadr p2)) (* (car p2) (cadr p1)))
      )
      ;;定义三点的行列式,即三点之倍面积-----
      (defun det (p1 p2 p3)
 (+ (det2 p1 p2) (det2 p2 p3) (det2 p3 p1))
      )
      (defun sign (x)
 (cond ((> x 0) -1.0)
       ((< x 0) 1.0)
       (t 0)
 )
      )
      ;;定义顺时针方向的夹角为正值,反之为负
      (defun ang (p1 p2 p3 / x)
 (setq x (abs (- (angle p1 p3) (angle p1 p2))))
 (if (equal p3 p1 1e-8)
   (- pi)
   (if (< (abs (sin x)) 1e-8)
     (if (equal (- (distance p2 p3)(+ (distance p1 p2) (distance p1 p3))) 0 1e-8)
       pi
       0
     )
     (if (> x pi)
       (* (- (* 2 pi) x) (sign (det p2 p1 p3)))
       (* x (sign (det p2 p1 p3)))
     )
   )
 )
      )
      ;;************************************
      ;;程序主段****************************
      (defun maxium (pts)
 (car (vl-sort pts
        '(lambda (e1 e2)
    (if (equal (car e1) (car e2) 1e-8)
      (> (cadr e1) (cadr e2))
      (> (car e1) (car e2))
    )
         )
      )
 )
      )
      ;;计算--------------------------------
      (setq p0 (maxium ptlist))
      (setq p1 p0 pfirst p0 p0 (list (car p0) (+ 1.0 (cadr p0)) (caddr p0)))
      (setq pmax1 p1)
      (setq p1 (mapcar '(lambda (x) (list (ang p1 p0 x) (distance p1 x) x)) ptlist))
      (setq pmax2 (caddr (maxium p1)))
      (setq pp (cons pmax2 (list pmax1)))
      (while (not (equal pfirst pmax2 1e-8))
 (setq p1 (mapcar '(lambda (x)(list (ang pmax2 pmax1 x) (distance pmax2 x) x))(mapcar 'caddr p1)))
 (setq pmax1 pmax2)
 (setq pmax2 (caddr (maxium p1)))
 (setq pp (cons pmax2 pp))
      )
      (reverse (cdr pp))
      )
    ) 
  )
)
;;;*****************************************
;;画点--------------------------------------
;;(setq pdm (getvar "pdmode"))--------------
;;(setq pds (getvar "pdsize"))--------------
;;(setvar "pdmode" 32);;这段可加可不加用来定
;;(setvar "pdsize"  0);义点的样式-----------
(defun drawpoint (x)
   (mapcar
     '(lambda (pt)
 (entmake
   (append
     '((0 . "Point") (100 . "AcDbEntity") (100 . "AcDbPoint"))
     (list (cons 10 pt))
   )
 )
      )
    x
  )
)
;;以下代码来自晓东定义取点函数--------------
(defun ssgetpoint (ss / i listpp a b c)
  (setq i 0 listpp nil )
  (if ss
    (repeat (sslength ss)
      (setq a (ssname ss i))
      (setq b (entget a))
      (setq c (cdr (assoc 10 b)))
      (setq listpp (cons c listpp))
      (setq i (1+ i)) 
    )
  )
  listpp
)
;;我改写的取点函数--------------------------
(defun ssgetpoint1 (ss / i listpp a b c d)
  (setq i 0 listpp nil )
  (if ss
    (repeat (sslength ss)
      (setq a (ssname ss i))
      (setq b (entget a))
      (setq ename (cdr (assoc 0 b)))
      (cond
 ( (or nil (= ename  "POLYLINE") (= ename "LWPOLYLINE"))
   (progn
     (setq c (GetListOfPline a))
     (setq listpp (append c listpp))
   )
        )
 ( (= ename "LINE")
   (progn
            (setq c (cdr (assoc 10 b)))
            (setq d (cdr (assoc 11 b)))
            (setq listpp (cons c listpp))
            (setq listpp (cons d listpp))
   )
 )
 ( (= ename "POINT")
   (progn
     (setq c (cdr (assoc 10 b)))
     (setq listpp (cons c listpp))
   )
 )
      )
      (setq i (1+ i))
    )    
  ) 
  listpp
)
;;以下代码来自明经通道----------------------
;;Get all nodes of the LWPolyline, Polyline.
(defun GetListOfPline (EntityName / SSE_Pline N newEntityName)
  (setq SSE_Pline (entget EntityName))
  (setq LastList nil)
  (if (= (cdr (assoc 0 SSE_Pline)) "LWPOLYLINE")
    (progn
      (setq LastList (LIST (LIST 0 0 0)))
      (setq N 0)
      (while (/= (nth N SSE_Pline) nil)
 (if (= (car (nth N SSE_Pline)) 10)
   (setq LastList (append LastList
     (list (list (cadr (nth N SSE_Pline))
          (caddr (nth N SSE_Pline))
          0
           )
     )
    )
   )
 )
 (setq N (+ N 1))
      )
      (setq LastList (cdr LastList))
    )
  )
  (if (= (cdr (ASSOC 0 SSE_Pline)) "POLYLINE")
    (PROGN
      (setq LastList (list (list 0 0 0)))
      (setq newEntityName (entnext EntityName))
      (while (= (cdr (assoc 0 (entget newEntityName))) "VERTEX")
 (setq
   LastList (append
       LastList
       (list
         (list (cadr (assoc 10 (entget newEntityName)))
        (caddr (assoc 10 (entget newEntityName)))
        0
         )
       )
     )
 )
 (setq newEntityName (entnext newEntityName))
      )
      (setq LastList (cdr LastList))
    )
  )
  (setq LastList LastList)
)

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x

点评

楼主高人  发表于 2011-11-17 06:27

评分

参与人数 4威望 +1 明经币 +2 金钱 +30 贡献 +5 激情 +5 收起 理由
tigcat + 1 很给力!
自贡黄明儒 + 1 很给力!
skymudy + 20
mccad + 1 + 10 + 5 + 5 【精华】好程序

查看全部评分

"觉得好,就打赏"
还没有人打赏,支持一下

本帖被以下淘专辑推荐:

发表于 2016-10-19 18:40 | 显示全部楼层
我要google下什么叫凸包
发表于 2017-8-3 08:45 来自手机 | 显示全部楼层
很好的程序。特别受启发!
发表于 2017-7-28 14:31 | 显示全部楼层
看不懂,但是强力mark
发表于 2006-11-15 00:10 | 显示全部楼层
本帖最后由 作者 于 2006-11-15 15:52:00 编辑

很好,这才是真正的编程。就是用数学的方法解决工作的问题。谢谢楼主的无私。

坚决支持这样的精华帖子。

发表于 2006-11-15 16:02 | 显示全部楼层

这样难得一见好贴就是没人顶,再顶一次。

 楼主| 发表于 2006-11-16 14:19 | 显示全部楼层

 多谢tcs19621!另我补充说明:

此程序对于当点数大于一定数量出现内存溢出错误,这种解决办法是再加一段分治算法进去,即可(代码叫容易实现,但我没加加进去)就是:把一个可能包含十万个以上的点按照100或者1000分段然后分别对每段求凸包,最后选择所有的凸包,再求凸包。也就是凸包集的凸包是点集的并集的凸包。(有点拗口)
重新改进代码段,使之更简短,更有效,比以前的速度快了不少。
算法用时跟规模是成线性的,由此可见此算法是一个跟n成线性的算法,不是平方级以上的。对此算法而言,时间主要取决于凸包的复杂度,时间不超过O(n.h),也就是说:凸包的边界点所占点集比例越大,时间越多。很可能出现这样一种情况,一个点集虽然比另外一个点集中的点多,但如果这个点集的凸包边界更简单的话,时间反而会少。
以此综述,这种算法不适宜于大量点位于凸包边界上的点集,但对于凸包边界简单的大量点集有效。
对此算法基本可以告一段落了,欢迎大家多提建议。

;;;************************************************************************
;;;一个求点集合的凸包的lisp程序--------------------------------------------
;;;------采用的算法为礼品包扎法--------------------------------------------
;;;方法为最右端的点开始处理,将该点作为凸包边界的第一个点P1,从最初的垂直线
;;;方向绕P1顺时针旋转,直到碰到另一个P2这就是凸包边界的第二个点P2,依此类推
;;;p2求得p3......直到又重新回到p1,已经考虑了各种退化情况和浮点运算,其算法
;;;时间不超过O(n.h),其中h是凸包的复杂度,时间还是很快的。大家不妨验证。   
;;;参考文献<<计算几何-算法及其应用>>(第二版),以及参考了其他网站的一些源代码
;;;------------------------------------------------------------------------
;;;其中程序主段是核心算法,其他的附加程序为取得点集,画凸包边界线,测试大量
;;;点集函数处理所花费的时间。----------------------------------------------
;;;用法: 加载lisp运行test选取点,直线段,或多义线(全是直线段组成)即可。----
;;;************************************************************************
(defun C:test (/ olderr en errmsg oldmode oce sl ss t1 t2 ptlist pp)
  ;;定义错误函数和预处理--------------------
  (setvar "errno" 0)
  (setq olderr *error*)
  (defun *error* (msg)
    (setq en (getvar "errno"))
    (setq errmsg (strcat "errno=" (itoa en) "\nError:" msg))
    (alert errmsg)
    (setq *error* olderr)
  )
  (graphscr)
  (setq oldmode (getvar "osmode"))
  (setq oce (getvar "cmdecho"))
  (setvar "cmdecho" 0)
  (command ".ucs" "W")
  ;;也可以用其他方式取得点集----------------
  ;;取点,画线,并对函数用时计算------------
  (setq sl ' ((-4 . "<OR" )
       (0 . "POINT")
       (0 . "LINE")
       (0 . "POLYLINE")
       (0 . "LWPOLYLINE")
       (-4 . "OR>" )))
  (setq ss (ssget sl))
  (setq ptlist (getpt ss))
  (setq t1 (getvar "CDATE"));;计时开始------
  (setq pp (hull ptlist))
  (setq t2 (getvar "CDATE"));;计时结束------
  (princ "\n用时=")
  (princ (* (- t2 t1) 1e6))
  (princ "秒")
  (if (= nil pp)
    (progn
      (alert "点的有效数目太小,请重新输入!")
      (command ".ucs" "p")
      (setvar "osmode" oldmode)
      (setvar "cmdecho" oce)
      (princ)
    )
    (progn
      ;;画凸包边界线------------------------
      (setvar "osmode" 0)
      (entmake
        (append
          '((0 . "lwpolyline")(100 . "AcDbEntity")(100 . "AcDbPolyline"))
          (list (cons 90 (length pp)))
          (mapcar '(lambda (x) (cons 10 (list (car x) (cadr x)))) pp)
          (list (cons 70 1))(list (cons 62 1))
        )
      )
      (command ".ucs" "P")
      (setvar "osmode" oldmode)
      (setvar "cmdecho" oce)
      (princ)
    )
  )
)
;;;*****************************************
;;;程序主段,可以单独成为函数---------------
(defun hull (ptlist / pfirst p0 p1 p2 pp)
  (cond
    ((= (length ptlist) 0)
      nil
    )
    ((or nil (= (length ptlist) 1) (= (length ptlist) 2))
     (progn
      (alert "你输入的点为两点或一点!")
      ptlist
     )
    )
    (t
     (progn
      ;;定义顺时针方向的夹角为正值,反之为负
      (defun ang (p1 p0 p2 / j2 j3 x)
 (setq j2 (angle p1 p0))
 (setq j3 (angle p1 p2))
 (setq x (- j3 j2))
        (cond
   ((equal p1 p2 1e-8) 0)
   ((> (- x pi) 1e-8) (+ x (* -2 pi)))
   ((< (+ x pi) 1e-8) (+ x (* 2 pi)))
   (t x)
 )
      )
      (defun angmax  (ptlist p0 p1)
 (nth (car (vl-sort-i (mapcar '(lambda (x) (ang p1 p0 x)) ptlist) '>)) ptlist)
      )
      ;;排序函数----------------------------
      (defun maxium (pts)
 (car (vl-sort pts '(lambda (e1 e2)(if (equal (car e1) (car e2) 1e-8)(> (cadr e1) (cadr e2))(> (car e1) (car e2))))))
      )
      ;;计算--------------------------------
      (setq pfirst (maxium ptlist))
      (setq p1 pfirst p0 (list (car pfirst) (+ 1.0 (cadr pfirst)) (caddr pfirst)))
      (setq p2 (angmax ptlist p0 p1))
      (setq pp (cons p2 (list p1)))
      (while (not (equal pfirst p2 1e-8))
 (setq p0 p1)
 (setq p1 p2)
 (setq p2 (angmax ptlist p0 p1))
 (setq pp (cons p2 pp))
      )
      (reverse (cdr pp))
      )
    ) 
  )
)
;;;程序主段结束-----------------------------
;;;*****************************************

;;依据晓东网站的代码改写而成的取点函数------
(defun getpt (ss / i listpp a b c d)
  (setq i 0 listpp nil )
  (if ss
    (repeat (sslength ss)
      (setq a (ssname ss i))
      (setq b (entget a))
      (setq ename (cdr (assoc 0 b)))
      (cond
 ( (or nil (= ename  "POLYLINE") (= ename "LWPOLYLINE"))
   (progn
     (setq c (GetListOfPline a))
     (setq listpp (append c listpp))
   )
        )
 ( (= ename "LINE")
   (progn
            (setq c (cdr (assoc 10 b)))
            (setq d (cdr (assoc 11 b)))
            (setq listpp (cons c listpp))
            (setq listpp (cons d listpp))
   )
 )
 ( (= ename "POINT")
   (progn
     (setq c (cdr (assoc 10 b)))
     (setq listpp (cons c listpp))
   )
 )
      )
      (setq i (1+ i))
    )    
  ) 
  listpp
)
;;以下代码来自明经通道----------------------
;;Get all nodes of the LWPolyline, Polyline.
(defun GetListOfPline (EntityName / SSE_Pline N newEntityName)
  (setq SSE_Pline (entget EntityName))
  (setq LastList nil)
  (if (= (cdr (assoc 0 SSE_Pline)) "LWPOLYLINE")
    (progn
      (setq LastList (LIST (LIST 0 0 0)))
      (setq N 0)
      (while (/= (nth N SSE_Pline) nil)
 (if (= (car (nth N SSE_Pline)) 10)
   (setq LastList (append LastList
     (list (list (cadr (nth N SSE_Pline))
          (caddr (nth N SSE_Pline))
          0
           )
     )
    )
   )
 )
 (setq N (+ N 1))
      )
      (setq LastList (cdr LastList))
    )
  )
  (if (= (cdr (ASSOC 0 SSE_Pline)) "POLYLINE")
    (PROGN
      (setq LastList (list (list 0 0 0)))
      (setq newEntityName (entnext EntityName))
      (while (= (cdr (assoc 0 (entget newEntityName))) "VERTEX")
 (setq
   LastList (append
       LastList
       (list
         (list (cadr (assoc 10 (entget newEntityName)))
        (caddr (assoc 10 (entget newEntityName)))
        0
         )
       )
     )
 )
 (setq newEntityName (entnext newEntityName))
      )
      (setq LastList (cdr LastList))
    )
  )
  (setq LastList LastList)
)

 

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
发表于 2006-11-20 22:28 | 显示全部楼层

你的数学很好所以你的程序很好。期待你以后有更多的好程序出现。

发表于 2006-11-21 13:11 | 显示全部楼层
很想知道它的应用价值
 楼主| 发表于 2006-12-4 09:44 | 显示全部楼层
关于凸包的用途,在许多文献以及网上都可以查找得到,计算几何一般把它作为开篇,因为其中牵涉到的很多算法在其他场合中都可运用。凸包的算法一般有Graham的扫描法,Jarvis步进法,Krikpatrick和Seidel的剪枝搜索法等等,每个算法都有优缺点。在网上有人把几种典型的算法做了比较。不妨参考他的论文。
我在上面除了给出Jarvis的礼品包扎法外,下面我还将给出用递归方法得出的凸包,同样高效率。加载程序,运行test进行测试。大家不妨作下比较。
  1. ;;;************************************
  2. ;;;程序的主段--------------------------
  3. ;;;求凸包函数--------------------------
  4. (defun Hull1 (ptlist / l p1 p2 p3 ppp pp1 pp2)
  5.   (setq l (length ptlist))
  6.   (if (<= l 3)
  7.     ptlist
  8.     (progn
  9.       (setq p1 (car  ptlist));;左端点
  10.       (setq p2 (last ptlist));;右端点
  11.       (setq ppp (mapcar (function (lambda (x) (det x p1 p2))) ptlist))
  12.       (setq p3 (nth (vl-position (apply 'max ppp) ppp) ptlist));;最大面积点
  13.       (foreach n ptlist
  14.         (if (and (judge p1 p3 n) (judge p3 n p2))
  15.    (setq pp1 (cons n pp1))
  16.         )
  17.         (if (and (judge p1 n p3) (judge n p3 p2))
  18.    (setq pp2 (cons n pp2))
  19.         )
  20.       )
  21.       (setq pp1 (reverse pp1) pp1 (cons p1 pp1) pp1 (append pp1 (list p3)))
  22.       (setq pp2 (reverse pp2) pp2 (cons p3 pp2) pp2 (append pp2 (list p2)))
  23.       (setq pp1 (hull1 pp1) pp2 (hull1 pp2));;递归(recursion)
  24.       (append pp1 (vl-remove p3 pp2))
  25.     )
  26.   )
  27. )
  28. ;;;分包函数----------------------------
  29. (defun divide (ptlist / p1 p2 ptlist1 ptlist2)
  30.   (setq p1 (car ptlist))
  31.   (setq p2 (last ptlist))
  32.   (setq ptlist1
  33.     (vl-remove-if
  34.       (function (lambda (x)(< (- (angle p2 p1) (angle p2 x)) 0))) ptlist
  35.     )
  36.   )
  37.   (setq ptlist2
  38.     (vl-remove-if
  39.       (function (lambda (x)(> (- (angle p2 p1) (angle p2 x)) 0))) ptlist
  40.     )
  41.   )
  42.   (setq ptlist1 (append (cons p1 ptlist1) (list p2)))
  43.   (setq ptlist2 (append (cons p1 ptlist2) (list p2)))
  44.   (list ptlist1 (reverse ptlist2))
  45. )
  46. ;;;主段结束****************************
  47. ;;;************************************
  48. (defun C:test (/ olderr en errmsg oce sl ss t0 pp
  49.                  ptlist ptlst1 ptlst2 ppup ppdw)
  50.   ;;定义错误函数和预处理
  51.   (setvar "errno" 0)
  52.   (setq olderr *error*)
  53.   (defun *error* (msg)
  54.     (setq en (getvar "errno"))
  55.     (setq errmsg (strcat "errno=" (itoa en) "\nError:" msg))
  56.     (alert errmsg)
  57.     (setq *error* olderr)
  58.   )
  59.   (graphscr)
  60.   (setq oce (getvar "cmdecho"))
  61.   (setvar "cmdecho" 0)
  62.   (command ".ucs" "W")
  63.   ;;也可以用其他方式取得点集
  64.   (setq sl '((0 . "POINT")))
  65.   (setq ss (ssget sl))
  66.   (if (= nil ss)
  67.     (progn
  68.       (alert "你输入的点数目太小!")
  69.       (command ".ucs" "p")
  70.       (setvar "cmdecho" oce)
  71.       (princ)
  72.     )
  73.     (progn
  74.       (setq ptlist (getpt ss))
  75.       ;;计算凸包用时
  76.       (setq t0 (getvar "TDUSRTIMER"))
  77.       ;;排序
  78.       (setq ptlist (XYsort ptlist))
  79.       ;;分包
  80.       (setq ptlist (divide ptlist))
  81.       (setq ptlst1 (car ptlist) ptlst2 (cadr ptlist))
  82.       ;;分别求出上凸包和下凸包
  83.       (setq ppup (cdr (hull1 ptlst1)))
  84.       (setq ppdw (cdr (hull1 ptlst2)))
  85.       ;;合并凸包
  86.       (setq pp (append ppup ppdw))
  87.       (princ "\n构造凸包用时")
  88.       (princ (* (- (getvar "TDUSRTIMER") t0) 86400))
  89.       (princ "秒")
  90.       ;;画凸包
  91.       (entmake
  92. (append
  93.    '((0 . "lwpolyline")(100 . "AcDbEntity")(100 . "AcDbPolyline"))
  94.    (list (cons 90 (length pp)))
  95.    (mapcar (function (lambda (x) (cons 10 (list (car x) (cadr x))))) pp)
  96.    (list (cons 70 1))
  97.    (list (cons 62 1))
  98. )
  99.       )
  100.       (command ".ucs" "P")
  101.       (setvar "cmdecho" oce)
  102.       (gc)
  103.       (princ)
  104.     )
  105.   )
  106. )
  107. ;;取点函数
  108. (defun getpt (ss / i listpp a b c)
  109.   (setq i 0 listpp nil )
  110.   (if ss
  111.     (repeat (sslength ss)
  112.       (setq a (ssname ss i))
  113.       (setq b (entget a))
  114.       (setq c (cdr (assoc 10 b)))
  115.       (setq c (list (car c) (cadr c)))
  116.       (setq listpp (cons c listpp))
  117.       (setq i (1+ i))  
  118.     )
  119.   )
  120.   (reverse listpp)
  121. )
  122. ;;定义矢量之叉积,即二阶行列式之值
  123. (defun det2 (p1 p2)
  124.   (- (* (car p1) (cadr p2)) (* (car p2) (cadr p1)))
  125. )
  126. ;;定义三点的行列式,即三点之倍面积
  127. (defun det (p1 p2 p3)
  128.   (+ (det2 p1 p2) (det2 p2 p3) (det2 p3 p1))
  129. )
  130. ;;定义判别法则
  131. (defun judge (p1 p2 p3 / x)
  132.   (setq x (det p1 p2 p3))
  133.   (if (> x 0) t nil)
  134. )
  135. ;;定义排序函数
  136. (defun XYsort (ptlist)
  137.   (vl-sort ptlist
  138.     (function
  139.       (lambda (e1 e2)
  140. (if (equal (car e1) (car e2) 1e-8)
  141.    (< (cadr e1) (cadr e2))
  142.    (< (car  e1) (car  e2))
  143. )
  144.       )
  145.     )
  146.   )
  147. )

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
发表于 2006-12-5 08:51 | 显示全部楼层
不错
发表于 2007-1-12 11:14 | 显示全部楼层

能改成VC的吗?

LISP看不明白啊!

 楼主| 发表于 2007-1-12 12:30 | 显示全部楼层

可惜我不懂VC。

不过网上很多介绍这方面的。你可以用google搜索一下。

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-4-24 06:25 , Processed in 0.382635 second(s), 34 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表