CAD的对象选择:从交互拾取到程序化查找

简介: 本文详解MxCAD对象选择机制:分为UI交互(点选、框选、栅栏选、累加选)和无UI编程选择(全选、ID/句柄查找、特征筛选)两大类;统一通过McObjectId标识对象,以MxCADResbuf实现跨场景筛选(类型、图层、颜色等),最终在MxCADSelectionSet中统一管理与遍历。

前言

之前聊了 MxCAD 的内置命令和圆弧、多段线的绘制,图有了,接下来就是怎么选中它们。对象选择其实就两件事:一是光标底下到底是哪个对象,二是怎么把一批对象挑出来统一处理。

在 MxCAD 里,选择分两条路走:一条靠 UI 交互,点选、框选、累加都行;另一条纯代码驱动,比如全选、按 ID 或句柄直接找、按特征筛选。不管走哪条路,都能挂上同一套筛选条件,把范围锁定在特定类型或图层上。
微信图片_20261016162657_28_31.png

一、两个基础概念

1.1、McObjectId:选择结果与实体之间的中间层

无论用哪种方式选择对象,最终拿到的都是一个 McObjectId(对象 ID)。它本身不携带实体的几何数据,只描述"这是数据库里的哪一个对象"。要真正操作实体,需要通过 getMcDbEntity() 从 ID 取出实体实例:

import {
    MxCADUiPrEntity } from "mxcad";
const getEnt = new MxCADUiPrEntity();
getEnt.setMessage("请选择目标对象");
const entId = await getEnt.go();
if (!entId || !entId.id) return;
const ent = entId.getMcDbEntity();
if (ent) console.log("对象类型:", ent.objectName);

McObjectId 还提供了几个常用判断方法:

entId.isValid();          // ID 是否有效
entId.isNull();          // ID 是否为空
entId.isKindOf("McDbLine"); // 指向的对象是否为直线
entId.isErase();         // 指向的对象是否已被删除

后续所有选择方式,都可以理解为"得到一个或一组 McObjectId",再通过 getMcDbEntity() 拿到实体做下一步操作。

1.2、 MxCADResbuf:筛选条件

MxCADResbuf 用来描述"哪些对象有资格被选中"。它可以挂载实体类型、图层、颜色、块名等条件,同时适用于有 UI 交互的选择和没有 UI 交互的选择。

import {
    MxCADResbuf } from "mxcad";
const filter = new MxCADResbuf();
filter.AddMcDbEntityTypes("LINE,CIRCLE");   // 只允许选直线和圆

后文每种选择方式都会用到这个筛选条件,这里先建立概念,具体用法在第五节展开。

二、有 UI 交互的选择

有 UI 交互的选择都需要用户参与(或给定坐标),返回一个选择集或对象 ID,并且可以挂 MxCADResbuf 过滤。

2.1、点选

2.1.1 交互式点选:MxCADUiPrEntity

MxCADUiPrEntity 用于让用户在图纸上点选一个对象,返回对应的 McObjectId,适合"选中某个对象后继续操作"的场景,如编辑、附加属性、读取属性等。

import {
    MxCADUiPrEntity } from "mxcad";
const getEnt = new MxCADUiPrEntity();
getEnt.setMessage("请选择目标对象");
const entId = await getEnt.go();
if (!entId || !entId.id) return;
const ent = entId.getMcDbEntity();
if (ent) console.log("当前对象类型:", ent.objectName);

点选结束后,还可以拿到"点在哪里选的"这个坐标,以及区分用户是选中了对象、按了回车还是输入了关键字:

const pickPt = getEnt.pickPoint();        // 拾取时的图纸坐标
const status = getEnt.getStatus();        // 操作状态
if (getEnt.isKeyWordPicked("P")) {
   
    // 用户输入了关键字 P(如"上一个对象")
}

2.1.2 坐标点选:pointSelect

如果坐标已经确定,不需要用户交互,可以直接用坐标在该处点选对象:

import {
    MxCADSelectionSet, MxCADResbuf } from "mxcad";
const ss = new MxCADSelectionSet();
const filter = new MxCADResbuf();
filter.AddMcDbEntityTypes("TEXT,MTEXT");   // 只挑文字对象
const index = ss.pointSelect(point.x, point.y, filter);
const ent = ss.item(index).getMcDbEntity();

pointSelect 的第三个参数是筛选条件,第四个参数是拾取容差。

如果不走选择集,MxCADUtility.findEntAtPoint() 可以直接在某点取到命中的实体,返回一个 McObjectId,适合"点选即识别"的场景:

import {
    MxCADUtility, MxCADResbuf, DxfCode } from "mxcad";
// 在 (x, y, z) 处查找命中的对象,-1 表示用默认拾取范围
const objId = MxCADUtility.findEntAtPoint(x, y, z, -1, null);
if (objId.isValid()) {
   
    const ent = objId.getMcDbEntity();
    console.log("命中对象:", ent?.objectName);
}
// 也可以带筛选条件,只命中直线
const filter = new MxCADResbuf([DxfCode.kEntityType, "LINE"]);
const lineId = MxCADUtility.findEntAtPoint(x, y, z, -1, filter);

2. 2 、框选

2.2.1 交互式框选:userSelect

userSelect 让用户在图纸上拉框选择,最接近桌面 CAD 中直接框选的操作:

import {
    MxCADSelectionSet, MxCADResbuf } from "mxcad";
const ss = new MxCADSelectionSet();
const filter = new MxCADResbuf();
filter.AddMcDbEntityTypes("INSERT");       // 只选块参照
if (await ss.userSelect("选择要刷的目标块:", filter)) {
   
    const ids = ss.getIds();               // 拿到全部选中的对象 ID
}

userSelect 返回一个布尔值,表示用户是否确认了选择:true 表示选中并确认,false 表示用户取消(按 Esc)或直接回车退出。

const confirmed = await ss.userSelect("选择要刷的目标块:", filter);
if (confirmed) {
   
    // 用户确认选择:处理 ss 中已选中的对象
} else {
   
    // 用户取消或退出
}

如果需要更细地区分结束原因,可以参考 MxCADSelectionSetStatus 枚举:kSelected(构造成功)、kNone(直接回车)、kCanceled(按 Esc 取消)、kRejected(无效关键字)、kKeyword(输入了关键字)。

框选完成后,可以调用getSelectPoint() 取回框选的两个对角点 {pt1, pt2},也可以调用getSelectPoints() 取回整条选择框的点阵。

const {
   pt1, pt2} = ss.getSelectPoint();
const points = ss.getSelectPoints();

2.2.2 程序化交叉窗选:crossingSelect

如果两个对角点已经确定,可以用 crossingSelect 直接完成框选,不需要用户交互:

ss.crossingSelect(x1, y1, x2, y2, filter);

交叉窗选对应 AutoCAD 中的"交叉 C":框内对象和跨越框边界的对象都会被选中。这与"窗选 W"(只选完全在框内的对象)不同。

2.2.3 栅栏选:fenceSelect

栅栏选对应 AutoCAD 的 F:用户画一条折线栅栏,选中所有被栅栏穿过的对象:

if (await ss.fenceSelect("选择栅栏要穿过的对象:", filter)) {
   
    console.log("栅栏选中:", ss.count());
}

2.3、累加选择

MxCADSelectionSet 默认 isWhileSelect = true,即循环选择:用户可以多次点选或框选,每次选择都累加进同一个选择集,直到确认结束。

const ss = new MxCADSelectionSet();
ss.isWhileSelect = true;      // 循环选择:多次选择不断累加
ss.isSelectHighlight = true;  // 选中对象高亮显示
// 用户连续点选,每次都往 ss 里累加;结束后:
const ids = ss.getIds();
console.log("累计选中:", ss.count());

currentSelect(filter?) 用于读取当前已选中的对象(对应 AutoCAD 的 PICKFIRST 语义),返回当前已选对象的数量:

// 读取当前已选对象数量
const n = ss.currentSelect();
// 带条件:只统计直线
const lineCount = ss.currentSelect(new MxCADResbuf([DxfCode.kEntityType, "LINE"]));

isFilterLockLayer 是一个布尔开关,控制遍历时是否跳过锁定图层上的对象,默认不跳过:

ss.isFilterLockLayer = true;   // 遍历时跳过锁定图层上的对象

三、无 UI 交互的选择

无 UI 交互的选择不依赖用户操作,由代码直接驱动,适合脚本、批处理和自动化场景。

3.1、全选:allSelect

const ss = new MxCADSelectionSet();
ss.allSelect();   // 全选当前空间的所有对象

也可以带条件,只选特定类型、特定图层上的对象:

import {
    DxfCode } from "mxcad";
// 只选 0 层上的直线、圆弧、圆、多段线
ss.allSelect(new MxCADResbuf([
    DxfCode.kEntityType, "LINE,ARC,CIRCLE,LWPOLYLINE",
    DxfCode.kLayer, "0"
]));
console.log("对象数:", ss.count());

3.2、按已知 ID 查找:McObjectId

McObjectId 的构造函数接受一个对象 ID(number 类型),可以直接由已知的 ID 还原出实体:

import {
    McObjectId } from "mxcad";
const id = new McObjectId(knownId);
if (id.isValid() && !id.isNull()) {
   
    const ent = id.getMcDbEntity();
    console.log(ent?.objectName);
}

这是选择结果与后续操作之间的衔接方式:drawEntity、allSelect、getIds() 等返回的都是 McObjectId,链式调用 getMcDbEntity() 即可继续编辑。

3.3、 按已知句柄查找:handleToIdIndex

句柄(handle)是对象在数据库中的字符串标识。数据库提供"句柄 → ID"的反查方法:

import {
    MxCpp } from "mxcad";
const db = MxCpp.getCurrentMxCAD().getDatabase();
const id = db.handleToIdIndex("ABCD1234");   // 句柄 → McObjectId
if (id && id.isValid()) {
   
    const ent = id.getMcDbEntity();
    console.log("句柄对应实体:", ent?.objectName);
}

反向操作是实体侧的 getHandle(),用于从实体取出句柄。ID、句柄、实体三者可以互相转换。

3.4、按实体特征查找

按实体特征查找,就是按对象自身的属性把符合条件的对象挑出来。根据特征的类型,有三种由浅入深的方式。

3.4.1 条件筛选

allSelect 配合 MxCADResbuf,用 DxfCode 指定特征维度,可以直接筛选类型、图层、颜色、块名等:

// 找 0 层上、颜色为 1、类型为直线的对象
ss.allSelect(new MxCADResbuf([
    DxfCode.kEntityType, "LINE",
    DxfCode.kLayer, "0",
    DxfCode.kColor, 1
]));

3.4.2 遍历加属性判定

条件筛选只能覆盖类型、图层、颜色、块名这类表级特征。如果要按几何量(半径、长度、坐标)识别对象,需要全选后遍历,逐个读取实体属性做判断:

ss.allSelect(new MxCADResbuf([DxfCode.kEntityType, "CIRCLE"]));
ss.forEach((id) => {
   
    const circle = id.getMcDbEntity();
    if (circle && Math.abs(circle.radius - 50) < 1e-6) {
   
        console.log("找到半径约 50 的圆:", circle.objectName);
    }
});

3.4.3 空间边界筛选:McDbSpatialFilter

按空间边界(点集围成的区域)筛选对象,典型用途是块参照的边界裁剪:

const spatialFilter = blkRef.getSpatialFilterId().getMcDbObject();
spatialFilter.setBoundary(aryPoint);   // 设置剪切边界点集
spatialFilter.setEnable(true);

四、选择结果的读取与遍历

无论用哪种方式选择,选中的对象都存放在 MxCADSelectionSet 中,通过以下方法读取:

ss.count();              // 选中对象数量
ss.item(i);              // 按索引取第 i 个对象的 McObjectId
ss.getIds();             // 取全部选中对象的 McObjectId 数组
ss.forEach((id) => {
       // 遍历每个选中对象
    const ent = id.getMcDbEntity();
});
ss.clear();              // 清空选择集
ss.isNull();             // 判断选择集是否为空

五、筛选条件 MxCADResbuf 的完整用法

前面每种选择方式都能挂上 MxCADResbuf,这是筛选贯穿两种选择方式的关键。

5.1. 构造筛选条件

import {
    MxCADResbuf, DxfCode } from "mxcad";
// 方式一:链式 add
const f1 = new MxCADResbuf();
f1.AddMcDbEntityTypes("LINE,CIRCLE");
// 方式二:构造时直接给「组码, 值」对
const f2 = new MxCADResbuf([
    DxfCode.kEntityType, "LINE,ARC",
    DxfCode.kLayer, "0"
]);

5.2. 可用的特征维度

DxfCode 枚举定义了筛选时可用的特征维度:

组码 含义 组码 含义
kEntityType 实体类型 kLayer 图层
kColor 颜色 kBlockName 块名
kExDataName 扩展数据名 kAppName XData 类型

实体类型值域包括:LINE、ARC、CIRCLE、LWPOLYLINE、TEXT、MTEXT、INSERT、ELLIPSE、SPLINE、POINT、LinkLine。

5.3. 同一个 filter 同时用于交互与程序化

同一个 MxCADResbuf 实例,既可以挂到有 UI 交互的选择上,也可以挂到无 UI 交互的选择上:

const filter = new MxCADResbuf([DxfCode.kEntityType, "LINE"]);
// 交互侧
const getEnt = new MxCADUiPrEntity();
getEnt.setFilter(filter);                 // 点选时只允许选直线
const ss = new MxCADSelectionSet();
ss.userSelect("选择直线:", filter);        // 框选时只选直线
ss.allSelect(filter);                      // 程序化全选时也只选直线

5.4. 读取与遍历筛选条件

MxCADResbuf 也能反向读出其中的条件,便于调试或复用:

filter.GetCount();                 // 条件项数量
filter.AtString(0);                // 取第 0 项字符串
filter.AtDouble(1);                // 取第 1 项 double
filter.AtPoint(2);                 // 取第 2 项点坐标
filter.AtObjectId(3);              // 取第 3 项对象 ID

六、把选择接上后续操作

选择只是第一步,选中对象后要做的是编辑、改属性、删除等。下面是一个"选择 → 批量改属性"的完整小命令,展示选完之后的用法:

import {
    MxCADSelectionSet, MxCADResbuf, DxfCode } from "mxcad";
async function Mx_SelectAndSetLinetype() {
   
    const ss = new MxCADSelectionSet();
    const filter = new MxCADResbuf([DxfCode.kEntityType, "LINE"]);
    if (!await ss.userSelect("选择要改线型的直线:", filter)) return;
    ss.forEach((id) => {
   
        const ent = id.getMcDbEntity();
        if (ent) ent.linetype = "DASHED";   // 批量改线型
    });
}

七、总结

对象选择是"用户意图"与"对象数据库"之间的环节,也是所有编辑命令的前置步骤。MxCAD 中对象选择分两类:

  • 有 UI 交互:点选(MxCADUiPrEntity / pointSelect)、框选(userSelect / crossingSelect / fenceSelect)、累加选择(isWhileSelect)。
  • 无 UI 交互:全选(allSelect)、按已知 ID 查找(new McObjectId)、按已知句柄查找(handleToIdIndex)、按实体特征查找(条件筛选 / 属性遍历 / McDbSpatialFilter)。

两类选择共用同一套筛选条件 MxCADResbuf,通过 DxfCode 指定类型、图层、颜色、块名等特征维度。选中的对象统一存放在 MxCADSelectionSet 中,通过 count、item、getIds、forEach 读取,再对每个 McObjectId 调用 getMcDbEntity() 拿到实体实例做后续操作。

掌握对象选择后,就可以进入修改工具,把选中的对象真正移动、复制、旋转编辑起来。

相关文章
|
2天前
|
云安全 人工智能 运维
当攻击全面Agent化,你的安全防御能否跟上AI Speed?
多起客户侧AK泄露事件应急的真实观察
1199 1
|
25天前
|
人工智能 JSON API
全网刷屏的 Jev 模型正式开放!一手实战测评 + 保姆级教程
全网爆火的 Jev 模型是什么?有什么用?怎么使用?怎么接入 AI 编程工具?效果真的好么?傻子可懂的 Jev 保姆级实战教程 + 项目实战测评来啦
9587 32
|
11天前
|
存储 人工智能 并行计算
大模型本地部署终端选型方法论:以 Qwen3.8-27B 为例的四档分层完整流程
本文提出一套大模型本地部署终端选型方法论:定约束、定档位、定框架、定参数四步决策法,配合入门、主力、质量、无损四档分层模型。以 Qwen3.8-27B 实测数据为例,逐环节解读显存、带宽、存储、散热、系统、预算等要素,给出面向不同预算的优选方案、决策自查清单与市场观察框架。文末前瞻 AI 笔记本的 CPU+GPU 与统一内存两条路线,论证四步决策法在新品类上的延续性。
|
10天前
|
人工智能 JSON 自然语言处理
2026 年 Jev 决策模型深度拆解:原理解读、实战测评与保姆级落地教程
有一款特殊AI模型在开发者圈子刷屏,它摒弃传统大模型擅长的对话聊天能力,专注做高速结构化决策,它就是TypeSafe AI推出的Jev模型。该模型由ChatGPT共同发明人Diogo Almeida主导研发,定位为**System One Model(系统一模型)**,对标人类大脑快速直觉判断的思维模式,在响应延迟、调用成本、结构化输出稳定性上相比传统生成式大模型有着巨大差异。本文会完整拆解Jev底层原理、三大核心原语能力、适用业务场景,同时提供可直接运行的curl、Python代码示例,并且结合多组实测数据,客观分析模型优势与能力边界,帮助普通开发者和AI应用从业者快速上手落地。
787 1
|
6天前
|
人工智能 JSON 自然语言处理
2026 年 Jev 决策模型全解析:核心原理拆解,性能实战测评与落地部署教程
有一款特殊AI模型在开发者圈子刷屏,它摒弃传统大模型擅长的对话聊天能力,专注做高速结构化决策,它就是TypeSafe AI推出的Jev模型。该模型由ChatGPT共同发明人Diogo Almeida主导研发,定位为System One Model(系统一模型),对标人类大脑快速直觉判断的思维模式,在响应延迟、调用成本、结构化输出稳定性上相比传统生成式大模型有着巨大差异。本文会完整拆解Jev底层原理、三大核心原语能力、适用业务场景,同时提供可直接运行的curl、Python代码示例,并且结合多组实测数据,客观分析模型优势与能力边界,帮助普通开发者和AI应用从业者快速上手落地。
522 0
|
23天前
|
人工智能 测试技术 API
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
Jev是TypeSafe AI推出的“系统一模型”,不生成文本,专做毫秒级结构化决策:Choice(多选)、Score(打分)、Noul(是非概率)。响应快193倍、成本低444倍,适合工单路由、内容审核、测试定级等高频判断场景。
2605 4
最近全网爆火的 Jev 到底是什么?适合干什么、怎么用,一篇讲透!
|
7天前
|
存储 人工智能 自然语言处理
千问办公官网入口链接在哪?2026年最新QwenWork测评、千问办公怎么样?一文看懂
千问办公(QwenWork)是阿里云推出的AI智能办公平台,提供网页端和阿里云官网双入口。支持PPT/Word/Excel生成、多模态处理、网页全栈搭建、钉钉深度集成等6大核心能力。个人版免费可用,高级版198元/月;企业版198元/人/月。新用户注册即赠2000积分。阿里千问办公QwenWork官网:https://t.aliyun.com/U/0VCTGt 阿里AI工作平台,一句话完成数据分析、PPT 生成、视频剪辑、网页搭建等复杂任务
1013 0
|
17天前
|
Windows
【保姆级】.NET Framework 3.5离线安装教程(2026最新实测)
.NET Framework 3.5是微软经典运行库,专为兼容老软件、老游戏设计。Win7自带,Win10/11需手动启用(在线或离线安装)。它与4.x系列并存不冲突,缺它会导致“找不到组件”报错。本文详解两种安装方式及常见问题解决,小白也能轻松上手。(239字)
2205 0

热门文章

最新文章