找回密码
 立即注册

QQ登录

只需一步,快速开始

扫一扫,访问微社区

查看: 389|回复: 4

[求助] 高程点外围复合线并注记面积

[复制链接]
发表于 2025-2-15 17:00:37 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

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

×
高程点外围复合线并注记面积
  1. (defun c:DB011 (/ pts hull ent)
  2.     ;; 提示用户选择高程点
  3.     (setq pts (ssget '((0 . "POINT"))))
  4.     (if pts
  5.         (progn
  6.             ;; 从选择集中提取所有点的坐标
  7.             (setq pts (get-points-from-ss pts))
  8.             ;; 计算凸包得到最外围点
  9.             (setq hull (convex-hull pts))
  10.             ;; 创建闭合的多段线
  11.             (setq ent (make-closed-polyline hull))
  12.         )
  13.     )
  14.     (princ)
  15. )

  16. ;; 从选择集提取点的坐标
  17. (defun get-points-from-ss (ss / i len entlist pt pts)
  18.     (setq i 0
  19.           len (sslength ss)
  20.           pts nil
  21.     )
  22.     (repeat len
  23.         (setq ent (ssname ss i)
  24.               entlist (entget ent)
  25.               pt (cdr (assoc 10 entlist))
  26.         )
  27.         (if pt
  28.             (setq pts (cons pt pts))
  29.         )
  30.         (setq i (1+ i))
  31.     )
  32.     pts
  33. )

  34. ;; 计算凸包(Graham 扫描算法)
  35. (defun convex-hull (points / p0 sorted-points stack)
  36.     (if (< (length points) 3)
  37.         points
  38.         (progn
  39.             ;; 找到 y 坐标最小的点
  40.             (setq p0 (car (vl-sort points '(lambda (a b) (if (< (cadr a) (cadr b)) T (< (car a) (car b))))))
  41.             ;; 根据极角排序
  42.             (setq sorted-points (sort-by-angle p0 (remove p0 points)))
  43.             ;; 初始化栈
  44.             (setq stack (list p0 (car sorted-points)))
  45.             ;; 遍历排序后的点
  46.             (foreach p (cdr sorted-points)
  47.                 (while (and (>= (length stack) 2)
  48.                             (<= (orientation (nth (- (length stack) 2) stack) (car (last stack)) p) 0)
  49.                      )
  50.                     (setq stack (reverse (cdr (reverse stack))))
  51.                 )
  52.                 (setq stack (cons p stack))
  53.             )
  54.             stack
  55.         )
  56.     )
  57. )

  58. ;; 根据极角排序
  59. (defun sort-by-angle (p0 points)
  60.     (vl-sort points '(lambda (a b) (< (angle-between p0 a) (angle-between p0 b)))))

  61. ;; 计算两点间的极角
  62. (defun angle-between (p1 p2)
  63.     (angle p1 p2)
  64. )

  65. ;; 判断三点的方向
  66. (defun orientation (p q r)
  67.     (- (* (- (cadr r) (cadr p)) (- (car q) (car p)))
  68.        (* (- (cadr q) (cadr p)) (- (car r) (car p)))
  69.     )
  70. )

  71. ;; 创建闭合的多段线
  72. (defun make-closed-polyline (points / pline-data)
  73.     (setq pline-data
  74.           (append
  75.               '((0 . "POLYLINE") (100 . "AcDbEntity") (100 . "AcDb2dPolyline") (70 . 1))
  76.               (mapcar '(lambda (p) (list 10 p)) points)
  77.               '((0 . "SEQEND"))
  78.           )
  79.     )
  80.     (entmake pline-data)
  81. )

  82. (defun CONVEX-HULL (points / p0 sorted-points stack)
  83.     ;; 如果点的数量少于 3 个,直接返回原点集
  84.     (if (< (length points) 3)
  85.         points
  86.         (progn
  87.             ;; 找到 y 坐标最小的点,若 y 相同则取 x 最小的点作为基准点 p0
  88.             (setq p0 (car (vl-sort points '(lambda (a b) (if (< (cadr a) (cadr b)) T (< (car a) (car b))))))
  89.             ;; 根据点相对于 p0 的极角对除 p0 外的点进行排序
  90.             (setq sorted-points (sort-by-angle p0 (remove p0 points)))
  91.             ;; 初始化栈,将 p0 和排序后第一个点压入栈
  92.             (setq stack (list p0 (car sorted-points)))
  93.             ;; 遍历排序后的点集
  94.             (foreach p (cdr sorted-points)
  95.                 ;; 当栈中元素不少于 2 个且当前点与栈顶两个点不构成左转关系时,弹出栈顶元素
  96.                 (while (and (>= (length stack) 2)
  97.                             (<= (orientation (nth (- (length stack) 2) stack) (car (last stack)) p) 0)
  98.                      )
  99.                     (setq stack (reverse (cdr (reverse stack))))
  100.                 )
  101.                 ;; 将当前点压入栈
  102.                 (setq stack (cons p stack))
  103.             )
  104.             ;; 返回栈中的点,即凸包上的点
  105.             stack
  106.         )
  107.     )
  108. )

  109. ;; 根据极角对除基准点外的点进行排序
  110. (defun sort-by-angle (p0 points)
  111.     (vl-sort points '(lambda (a b) (< (angle-between p0 a) (angle-between p0 b)))))

  112. ;; 计算两点相对于基准点的极角
  113. (defun angle-between (p1 p2)
  114.     (angle p1 p2)
  115. )

  116. ;; 判断三点的方向,返回值大于 0 表示左转,小于 0 表示右转,等于 0 表示共线
  117. (defun orientation (p q r)
  118.     (- (* (- (cadr r) (cadr p)) (- (car q) (car p)))
  119.        (* (- (cadr q) (cadr p)) (- (car r) (car p)))
  120.     )
  121. )





论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!

已领礼包: 48个

财富等级: 招财进宝

发表于 2025-2-16 10:56:01 | 显示全部楼层
楼主:你这个程序运行不了。
以下是Lee Mac和gile版的凸包生成程序
  1. ;; Clockwise-p  -  Lee Mac
  2. ;; Returns T if p1,p2,p3 are clockwise oriented or collinear

  3. (defun LM:Clockwise-p ( p1 p2 p3 )
  4.     (<  (-  (* (- (car  p2) (car  p1)) (- (cadr p3) (cadr p1)))
  5.             (* (- (cadr p2) (cadr p1)) (- (car  p3) (car  p1)))
  6.         )
  7.         1e-8
  8.     )
  9. )

  10. (defun c:chull ( / i l s )
  11.     (if (setq s (ssget '((0 . "POINT,INSERT"))))
  12.         (progn
  13.             (repeat (setq i (sslength s))
  14.                 (setq l (cons (cdr (assoc 10 (entget (ssname s (setq i (1- i)))))) l))
  15.             )
  16.             (setq l (LM:ConvexHull l))
  17.             (entmakex
  18.                 (append
  19.                     (list
  20.                        '(000 . "LWPOLYLINE")
  21.                        '(100 . "AcDbEntity")
  22.                        '(100 . "AcDbPolyline")
  23.                         (cons 90 (length l))
  24.                        '(070 . 1)
  25.                        '(62 . 1)
  26.                     )
  27.                     (mapcar '(lambda ( x ) (cons 10 x)) l)
  28.                 )
  29.             )
  30.         )
  31.     )
  32.     (princ)
  33. )

  34. ;; convhull  -  gile
  35. ;; Retourne la liste des points formant l'enveloppe convexe de pts
  36. (defun convhull (pts / clockwise p0 acc)

  37.   ;; Evalue si les points p1 p2 p3 tournent en sens horaire ou sont alignés
  38.   (defun clockwise (p1 p2 p3)
  39.     (< (sin (- (angle p1 p3) (angle p1 p2))) -1e-9)
  40.   )

  41.   ;; recherche du pivot
  42.   (setq p0 (car pts))
  43.   (foreach p (cdr pts)
  44.     (if (or (< (cadr p) (cadr p0))
  45.             (and (= (cadr p) (cadr p0)) (< (car p) (car p0)))
  46.         )
  47.       (setq p0 p)
  48.     )
  49.   )

  50.   ;; tri de la liste
  51.   (setq pts (vl-sort pts
  52.                      '(lambda (p1 p2 / d1 d2 c1 c2)
  53.                         (setq d1 (distance p0 p1)
  54.                               d2 (distance p0 p2)
  55.                         )
  56.                         (if (or (= 0 d1)
  57.                                 (= 0 d2)
  58.                                 (equal (setq c1 (/ (- (car p0) (car p1)) d1))
  59.                                        (setq c2 (/ (- (car p0) (car p2)) d2))
  60.                                        1e-9
  61.                                 )
  62.                             )
  63.                           (< d1 d2)
  64.                           (< c1 c2)
  65.                         )
  66.                       )
  67.             )
  68.         acc (list (cadr pts) (car pts))
  69.         pts (cddr pts)
  70.   )

  71.   ;; supression des points ne faisant pas partie de l'enveloppe
  72.   (foreach p pts
  73.     (while (and (cdr acc) (clockwise (cadr acc) (car acc) p))
  74.       (setq acc (cdr acc))
  75.     )
  76.     (setq acc (cons p acc))
  77.   )

  78.   ;; résultat retourné
  79.   (reverse acc)
  80. )

  81. ;; Commande de test
  82. (defun c:ch (/ ss n lst)
  83.   (if (setq ss (ssget '((0 . "POINT,INSERT"))))
  84.     (progn
  85.       (repeat (setq n (sslength ss))
  86.         (setq lst (cons (cdr (assoc 10 (entget (ssname ss (setq n (1- n)))))) lst))
  87.       )
  88.       (vla-StartUndoMark (vla-get-ActiveDocument (vlax-get-acad-object)))
  89.       (entmake
  90.         (vl-list*
  91.           '(0 . "LWPOLYLINE")
  92.           '(100 . "AcDbEntity")
  93.           '(100 . "AcDbPolyline")
  94.           (cons 90 (length lst))
  95.           '(70 . 1)
  96.           '(62 . 5)
  97.           (mapcar '(lambda (p) (list 10 (car p) (cadr p))) (convhull lst))
  98.         )
  99.       )
  100.       (vla-EndUndoMark (vla-get-ActiveDocument (vlax-get-acad-object)))
  101.     )
  102.   )
  103.   (princ)
  104. )
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 48个

财富等级: 招财进宝

发表于 2025-2-16 10:58:34 | 显示全部楼层
  1. ;; Convex Hull  -  Lee Mac
  2. ;; Implements the Graham Scan Algorithm to return the Convex Hull of a list of points.

  3. (defun LM:ConvexHull ( lst / ch p0 )
  4.     ;(setq lst pts)
  5.     (cond
  6.         (   (< (length lst) 4) lst)
  7.         (   (setq p0 (car lst))
  8.             (foreach p1 (cdr lst)
  9.                 (if (or (< (cadr p1) (cadr p0))
  10.                         (and (= (cadr p1) (cadr p0)) (< (car p1) (car p0)))
  11.                     )
  12.                     (setq p0 p1)
  13.                 )
  14.             )
  15.             (setq lst (vl-remove p0 lst))
  16.             (setq lst (append (list p0) lst))
  17.             (setq lst
  18.                 (vl-sort lst
  19.                     (function
  20.                         (lambda ( a b / c d )
  21.                               (if (or (equal (setq c (angle p0 a)) (setq d (angle p0 b)) 1e-8) (and (or (equal c 0.0 1e-8) (equal c (* 2 pi) 1e-8)) (or (equal d 0.0 1e-8) (equal d (* 2 pi) 1e-8))))
  22.                                   (< (distance (list (car p0) (cadr p0)) a) (distance (list (car p0) (cadr p0)) b))
  23.                                   (< c d)
  24.                               )
  25.                         )
  26.                     )
  27.                 )
  28.             )
  29.             (setq ch (list (cadr lst) (car lst)))
  30.             (foreach pt (cddr lst)
  31.                 (setq ch (cons pt ch))
  32.                 (while (and (caddr ch) (LM:Clockwise-p (caddr ch) (cadr ch) pt))
  33.                     (setq ch (cons pt (cddr ch)))
  34.                 )
  35.             )
  36.             (reverse ch)
  37.         )
  38.     )
  39. )

  40. ;; Clockwise-p  -  Lee Mac
  41. ;; Returns T if p1,p2,p3 are clockwise oriented or collinear

  42. (defun LM:Clockwise-p ( p1 p2 p3 )
  43.     (<  (-  (* (- (car  p2) (car  p1)) (- (cadr p3) (cadr p1)))
  44.             (* (- (cadr p2) (cadr p1)) (- (car  p3) (car  p1)))
  45.         )
  46.         1e-8
  47.     )
  48. )

  49. (defun c:chull ( / i l s )
  50.     (if (setq s (ssget '((0 . "POINT,INSERT"))))
  51.         (progn
  52.             (repeat (setq i (sslength s))
  53.                 (setq l (cons (cdr (assoc 10 (entget (ssname s (setq i (1- i)))))) l))
  54.             )
  55.             (setq l (LM:ConvexHull l))
  56.             (entmakex
  57.                 (append
  58.                     (list
  59.                        '(000 . "LWPOLYLINE")
  60.                        '(100 . "AcDbEntity")
  61.                        '(100 . "AcDbPolyline")
  62.                         (cons 90 (length l))
  63.                        '(070 . 1)
  64.                        '(62 . 1)
  65.                     )
  66.                     (mapcar '(lambda ( x ) (cons 10 x)) l)
  67.                 )
  68.             )
  69.         )
  70.     )
  71.     (princ)
  72. )

  73. ;; convhull  -  gile
  74. ;; Retourne la liste des points formant l'enveloppe convexe de pts
  75. (defun convhull (pts / clockwise p0 acc)

  76.   ;; Evalue si les points p1 p2 p3 tournent en sens horaire ou sont alignés
  77.   (defun clockwise (p1 p2 p3)
  78.     (< (sin (- (angle p1 p3) (angle p1 p2))) -1e-9)
  79.   )

  80.   ;; recherche du pivot
  81.   (setq p0 (car pts))
  82.   (foreach p (cdr pts)
  83.     (if (or (< (cadr p) (cadr p0))
  84.             (and (= (cadr p) (cadr p0)) (< (car p) (car p0)))
  85.         )
  86.       (setq p0 p)
  87.     )
  88.   )

  89.   ;; tri de la liste
  90.   (setq pts (vl-sort pts
  91.                      '(lambda (p1 p2 / d1 d2 c1 c2)
  92.                         (setq d1 (distance p0 p1)
  93.                               d2 (distance p0 p2)
  94.                         )
  95.                         (if (or (= 0 d1)
  96.                                 (= 0 d2)
  97.                                 (equal (setq c1 (/ (- (car p0) (car p1)) d1))
  98.                                        (setq c2 (/ (- (car p0) (car p2)) d2))
  99.                                        1e-9
  100.                                 )
  101.                             )
  102.                           (< d1 d2)
  103.                           (< c1 c2)
  104.                         )
  105.                       )
  106.             )
  107.         acc (list (cadr pts) (car pts))
  108.         pts (cddr pts)
  109.   )

  110.   ;; supression des points ne faisant pas partie de l'enveloppe
  111.   (foreach p pts
  112.     (while (and (cdr acc) (clockwise (cadr acc) (car acc) p))
  113.       (setq acc (cdr acc))
  114.     )
  115.     (setq acc (cons p acc))
  116.   )

  117.   ;; résultat retourné
  118.   (reverse acc)
  119. )

  120. ;; Commande de test
  121. (defun c:ch (/ ss n lst)
  122.   (if (setq ss (ssget '((0 . "POINT,INSERT"))))
  123.     (progn
  124.       (repeat (setq n (sslength ss))
  125.         (setq lst (cons (cdr (assoc 10 (entget (ssname ss (setq n (1- n)))))) lst))
  126.       )
  127.       (vla-StartUndoMark (vla-get-ActiveDocument (vlax-get-acad-object)))
  128.       (entmake
  129.         (vl-list*
  130.           '(0 . "LWPOLYLINE")
  131.           '(100 . "AcDbEntity")
  132.           '(100 . "AcDbPolyline")
  133.           (cons 90 (length lst))
  134.           '(70 . 1)
  135.           '(62 . 5)
  136.           (mapcar '(lambda (p) (list 10 (car p) (cadr p))) (convhull lst))
  137.         )
  138.       )
  139.       (vla-EndUndoMark (vla-get-ActiveDocument (vlax-get-acad-object)))
  140.     )
  141.   )
  142.   (princ)
  143. )
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 48个

财富等级: 招财进宝

发表于 2025-2-17 14:58:50 | 显示全部楼层
本帖最后由 dnbc 于 2025-2-18 09:02 编辑

加上面积标汪
  1. <blockquote>;; Convex Hull  -  Lee Mac
复制代码

高程点生成外围复合线并注记面积.lsp

6.96 KB, 下载次数: 3, 下载积分: D豆 -1 , 活跃度 1

论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

已领礼包: 275个

财富等级: 日进斗金

发表于 2025-8-3 00:49:59 | 显示全部楼层
我也顺便来学习一下。感谢大家。
论坛插件加载方法
发帖求助前要善用【论坛搜索】功能,那里可能会有你要找的答案;
如果你在论坛求助问题,并且已经从坛友或者管理的回复中解决了问题,请把帖子标题加上【已解决】;
如何回报帮助你解决问题的坛友,一个好办法就是给对方加【D豆】,加分不会扣除自己的积分,做一个热心并受欢迎的人!
回复 支持 反对

使用道具 举报

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

本版积分规则

QQ|申请友链|Archiver|手机版|小黑屋|辽公网安备|晓东CAD家园 ( 辽ICP备15016793号 )

GMT+8, 2025-9-25 18:19 , Processed in 0.178325 second(s), 41 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

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