乐于分享
好东西不私藏

【lisp】源码:散点排序并生成样条曲线

【lisp】源码:散点排序并生成样条曲线

ALISP 代码解读:散点排序并生成样条曲线(命令 LL

功能概述

选择 CAD 中的多个 「POINT」 对象,按“相对距离”贪心排序后,用一条 「SPLINE」 样条曲线依次穿过所有点。

源码:https://tool.zml84.xyz/lisp/view/?uuid=cca49dc7-2ff5-40df-9f28-b3f6be895fdf


主函数 c:LL

1. 选择点对象

(setq ss (ssget '((0 . "POINT"))))
  • 仅允许选择类型为 POINT 的实体,其他图元被过滤。

2. 提取所有点的坐标

(setq ptList '())(repeat (sslength ss)  (setq en (ssname ss i))  (setq pt (cdr (assoc10 (entget en))))  (setq ptList (cons pt ptList))  (setq i (1+ i)))
  • 遍历选择集,通过 assoc 10 获取每个点的坐标(DXF 组码 10)。
  • 将坐标依次存入列表 ptList

3. 去重(精度 1e-8)

(setq ptList (unique ptList))
  • 调用自定义 unique 函数,删除坐标完全重复的点。

4. 点数检查

(if (< (length ptList) 2)  (princ"\n至少需要2个不同的点!")  ...)
  • 如果去重后点数不足 2 个,提示并退出。

5. 贪心最近邻排序

  • 「起点选择」
  (setq curPt (getStartPoint ptList))

调用 getStartPoint,取 X+Y 最小的点(即左下角)作为路径起点。

  • 「初始化未访问列表」
  (setq unvisited (vl-remove curPt ptList))  (setq sortedList (list curPt))
  • 「循环找最近点」
  (while unvisited    (foreach p unvisited      (setq d (distance curPt p))      (if (or (null minDist) (< d minDist))        (setq minDist d  minPt p)      )    )    (setq sortedList (append sortedList (list minPt)))    (setq unvisited (vl-remove minPt unvisited))    (setq curPt minPt)  )
  • 每次从剩余点中找出距离当前点最近的点 minPt
  • 将其加入排序列表,从未访问列表中移除,并更新当前点。
  • 重复直到所有点被访问。

6. 绘制样条曲线

(drawSpline sortedList)
  • 调用 drawSpline 函数,执行 _.SPLINE 命令,依次输入各点坐标。

辅助函数详解

unique – 列表去重

(defun unique (lst / res)  (foreach p lst    (if (not (vl-some '(lambda (x) (equal x p 1e-8)) res))      (setq res (cons p res))    )  )  (reverse res))
  • 遍历原始点列表,利用 vl-some 检查当前点是否已存在于结果集 res 中(容差 1e-8)。
  • 若不存在,则加入。最后反转列表恢复顺序。

getStartPoint – 获取左下角起点

(defun getStartPoint (pts)  (car (vl-sort pts                '(lambda (a b)                   (< (+ (car a) (cadr a))                      (+ (car b) (cadr b)))                  ))))
  • 按 X+Y 的值升序排序,取第一个点。该点大致位于点集的左下方。

drawSpline – 执行 SPLINE 命令

(defun drawSpline (pts / cmd)  (if (<= (length pts) 2)    (princ"\n点数不足,无法绘制 SPLINE。")    (progn      (command"_.SPLINE")      (foreach p pts (command p))      (command"""""")   ; 两个回车结束点输入,第三个确认    )  ))
  • 启动 SPLINE 命令,依次输入每个点的坐标。
  • 最后三个空字符串:第一个表示结束点输入,第二个结束切线定义,第三个确认(多一个无影响)。

使用方法

  1. 「加载代码」:保存为 .lsp 文件,用 APPLOAD 命令加载,或直接拖入 CAD 绘图区。
  2. 「运行命令」:在命令行输入 LL 并回车。
  3. 「选择点」:框选或点选图面上的 POINT 对象(至少两个不同的点)。
  4. 「自动生成」:程序完成排序并绘制一条通过所有点的样条曲线。

注意事项

  • 「排序策略」:贪心最近邻,非全局最优(简单旅行商近似),但适用于大多数散点连线场景。
  • 「点类型限制」:仅对 POINT 实体有效。如需支持圆心、插入点等,可修改 ssget 过滤条件。
  • 「性能」:点数量很大(如 >500)时,双层循环效率较低,但对常规设计足够。
  • 「曲线属性」:生成的 SPLINE 使用当前图层和线型,可自行修改 drawSpline 添加参数。

总结

这是一个实用的 CAD 辅助工具,能够自动将散乱的点按“邻近优先”的顺序连接成一条光滑曲线,常用于道路边线测点连线、轮廓生成等场景。

源码:https://tool.zml84.xyz/lisp/view/?uuid=cca49dc7-2ff5-40df-9f28-b3f6be895fdf