You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在AutoCAD或Python中获取绘图闭合区域的边界坐标?

提取闭合对象边界坐标的AutoCAD与Python实现方案

给定线条坐标列表(格式为coordinates_list = [[x, y, z, x1, y1, z1], ...]),需从对应绘图中提取全部15个闭合对象的边界坐标,针对你遇到的_-BOUNDARY命令无法直接读取坐标、DFS算法识别不全的问题,以下是两种可行方案:


一、AutoCAD 实现方案

步骤1:将坐标列表导入AutoCAD生成线条

_-BOUNDARY命令依赖AutoCAD中的图元对象,需先把坐标批量转换成直线图元,可通过以下两种方式实现:

  • AutoLISP 批量创建直线:
    (defun c:importlines (/ coords lst)
      ; 替换为你的坐标列表,格式为((x y z x1 y1 z1) (x2 y2 z2 x3 y3 z3) ...)
      (setq coords '((0 0 0 1 0 0) (1 0 0 1 1 0) ...))
      (foreach lst coords
        (command "LINE" (list (car lst) (cadr lst) (caddr lst)) 
                        (list (cadddr lst) (cadddr (cdr lst)) (cadddr (cddr lst))) "")
      )
    )
    
  • Python pyautocad 库批量创建直线:
    from pyautocad import Autocad, APoint
    
    acad = Autocad(create_if_not_exists=True)
    coordinates_list = [[0,0,0,1,0,0], [1,0,0,1,1,0], ...]  # 你的坐标数据
    
    for line in coordinates_list:
        start = APoint(line[0], line[1], line[2])
        end = APoint(line[3], line[4], line[5])
        acad.model.AddLine(start, end)
    

步骤2:生成闭合边界

线条导入完成后,执行_-BOUNDARY命令:

  1. 输入_-BOUNDARY回车,设置创建对象为多段线(_O选项选择_M);
  2. 依次拾取每个闭合区域的内部点,AutoCAD会自动生成对应闭合多段线;
  3. 若需批量处理,可提前准备15个闭合区域的内部点坐标,用AutoLISP循环执行命令:
    (defun c:batchboundary (/ pts)
      ; 替换为15个闭合区域的内部点坐标列表
      (setq pts '((0.5 0.5 0) (2.5 0.5 0) ...))
      (foreach pt pts
        (command "_-BOUNDARY" "_O" "_M" pt "")
      )
    )
    

步骤3:导出闭合边界坐标

选中生成的多段线,用以下方式提取坐标:

  • 执行LIST命令,直接查看多段线顶点坐标;
  • 用AutoLISP批量导出到文本文件:
    (defun c:exportboundcoords (/ ent coords f)
      (setq ent (car (entsel "\n选择闭合多段线:")))
      (setq coords (entget ent))
      (setq f (open "boundary_coords.txt" "w"))
      (foreach item coords
        (if (= (car item) 10) ; 提取顶点坐标
          (write-line (strcat (rtos (cadr item)) "," (rtos (caddr item)) "," (rtos (cadddr item))) f)
        )
      )
      (close f)
    )
    

二、Python 实现方案

你之前用DFS识别不全,大概率是未处理浮点精度误差、未做去重逻辑导致的,以下是优化后的实现:

核心逻辑

将线条的端点作为节点构建无向图,通过DFS查找所有环(闭合路径),同时处理浮点精度、排除重复环。

完整代码

import math
from collections import defaultdict

# 浮点精度阈值,解决坐标微小误差问题
EPS = 1e-6

def is_close(p1, p2):
    """判断两个点是否重合(考虑浮点精度)"""
    return math.hypot(p1[0]-p2[0], p1[1]-p2[1], p1[2]-p2[2]) < EPS

def get_closed_boundaries(coordinates_list):
    # 构建无向图:键为点元组,值为相连的点列表
    graph = defaultdict(list)
    # 存储已处理的线条,避免重复添加边
    processed_lines = set()

    for line in coordinates_list:
        p1 = (line[0], line[1], line[2])
        p2 = (line[3], line[4], line[5])
        # 用排序后的点对标识线条,避免重复存储
        line_key = tuple(sorted([p1, p2], key=lambda x: (x[0], x[1], x[2])))
        if line_key not in processed_lines:
            processed_lines.add(line_key)
            graph[p1].append(p2)
            graph[p2].append(p1)

    closed_boundaries = []
    visited_lines = set()

    def dfs(current_point, start_point, path, visited_points):
        # 回到起点且路径长度≥3,判定为有效闭合环
        if is_close(current_point, start_point) and len(path) >= 3:
            # 生成唯一标识去重(避免顺时针/逆时针的同一环被重复记录)
            boundary_key = tuple(sorted(path, key=lambda x: (x[0], x[1], x[2])))
            if boundary_key not in [tuple(sorted(b, key=lambda x: (x[0], x[1], x[2]))) for b in closed_boundaries]:
                closed_boundaries.append(path.copy())
            return
        
        for neighbor in graph[current_point]:
            line_key = tuple(sorted([current_point, neighbor], key=lambda x: (x[0], x[1], x[2])))
            # 避免重复走同一条线,且排除直接返回起点的无效路径(除了初始步骤)
            if line_key not in visited_lines and (not is_close(neighbor, start_point) or len(path) == 1):
                visited_lines.add(line_key)
                visited_points.add(neighbor)
                path.append(neighbor)
                dfs(neighbor, start_point, path, visited_points)
                # 回溯
                path.pop()
                visited_points.remove(neighbor)
                visited_lines.remove(line_key)

    # 遍历所有点作为起点查找闭合环
    for point in graph:
        dfs(point, point, [point], set([point]))
    
    # 最终去重:排除从不同起点识别的同一环
    unique_boundaries = []
    seen_keys = set()
    for boundary in closed_boundaries:
        key = tuple(sorted(boundary, key=lambda x: (x[0], x[1], x[2])))
        if key not in seen_keys:
            seen_keys.add(key)
            unique_boundaries.append(boundary)
    
    return unique_boundaries

# 示例调用
coordinates_list = [[0,0,0,1,0,0], [1,0,0,1,1,0], [1,1,0,0,1,0], [0,1,0,0,0,0], ...]
boundaries = get_closed_boundaries(coordinates_list)
print(f"识别到的闭合对象数量:{len(boundaries)}")
for idx, boundary in enumerate(boundaries):
    print(f"闭合对象 {idx+1} 的坐标:{boundary}")

关键优化说明

  1. 浮点精度处理:通过is_close函数判断点是否重合,解决坐标微小误差导致的节点匹配失败;
  2. 去重机制:对线条和闭合路径的点进行排序,排除同一闭合环的不同遍历方向或起点的重复记录;
  3. DFS终止条件:要求路径长度≥3,避免将两点往返误判为闭合环。

内容的提问来源于stack exchange,提问作者Bobby Lith

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 05:37:36