多段线扩展数据的应用场景

在C# CAD二次开发中,多段线(Polyline)的扩展数据(XData)主要用于为实体附加自定义的、非图形化的信息,以实现数据关联、流程控制或信息追溯等高级功能。

其核心用途可归纳为下表:

用途类别 具体说明 典型应用场景
存储自定义属性 将业务相关的属性(如构件ID、材料、状态、成本等)直接绑定到图形实体上。 在BIM或工程管理系统中,为多段线代表的管线、边界等存储其工程属性。
实现对象关联 通过存储其他实体的句柄(Handle)或唯一标识,建立图形对象之间的逻辑关系。 一条多段线(如道路中心线)通过扩展数据关联到多个标注或地块实体。
记录过程信息 保存实体创建、修改过程中的元数据,如创建者、时间、版本号或审批状态。 在协同设计流程中,追踪多段线的设计变更历史。
控制程序行为 存储特定标记或参数,供二次开发程序在运行时读取,以决定对实体的处理方式。 标记一条多段线是否需要被后续的批量处理程序忽略或进行特殊计算。

###核心操作代码示例

扩展数据的操作围绕 SetXData 和 GetXData 方法,并使用 ResultBuffer 来组织数据。数据以"类型-值"对(TypedValue)的形式存储。

  1. 为多段线写入扩展数据

以下代码演示如何为一条选中的多段线附加一个字符串类型的构件编号和一个整型的状态码。

csharp 复制代码
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using System;

public class XDataDemo
{
    [CommandMethod("WritePolylineXData")]
    public void WritePolylineXData()
    {
        Document doc = Application.DocumentManager.MdiActiveDocument;
        Database db = doc.Database;
        Editor ed = doc.Editor;

        // 1. 选择一条多段线
        PromptEntityOptions opt = new PromptEntityOptions("
请选择一条多段线:");
        opt.SetRejectMessage("
请选择多段线!");
        opt.AddAllowedClass(typeof(Polyline), false);
        PromptEntityResult res = ed.GetEntity(opt);
        if (res.Status != PromptStatus.OK) return;

        using (Transaction tr = db.TransactionManager.StartTransaction())
        {
            // 2. 以写模式打开多段线对象 Polyline pl = tr.GetObject(res.ObjectId, OpenMode.ForWrite) as Polyline;
            if (pl == null) return;

            // 3. 创建扩展数据缓冲区 (ResultBuffer)
            // 约定:注册应用名称为"MY_APP"
            string regAppName = "MY_APP";
            // 确保应用程序名称已注册到数据库
            RegAppTable rat = tr.GetObject(db.RegAppTableId, OpenMode.ForRead) as RegAppTable;
            if (!rat.Has(regAppName))
            {
                rat.UpgradeOpen();
                RegAppTableRecord ratr = new RegAppTableRecord();
                ratr.Name = regAppName;
                rat.Add(ratr);
                tr.AddNewlyCreatedDBObject(ratr, true);
            }

            // 4. 构建扩展数据内容 // 第一个TypedValue必须是注册应用程序名称 (1001, "MY_APP")
            // 后续可跟多个自定义数据对 ResultBuffer rb = new ResultBuffer();
            rb.Add(new TypedValue((int)DxfCode.ExtendedDataRegAppName, regAppName)); // 应用名 rb.Add(new TypedValue((int)DxfCode.ExtendedDataAsciiString, "BEAM-2024-001")); // 构件编号 (1000)
            rb.Add(new TypedValue((int)DxfCode.ExtendedDataInteger16, 1)); // 状态码 (1070)

            // 5. 将扩展数据赋给多段线 pl.XData = rb;
            rb.Dispose(); // 释放ResultBuffer资源

            tr.Commit();
            ed.WriteMessage("
成功为多段线写入扩展数据。");
        }
    }
}
  1. 从多段线读取扩展数据

以下代码演示如何读取并解析已附加的扩展数据。

csharp 复制代码
[CommandMethod("ReadPolylineXData")]
public void ReadPolylineXData()
{
    Document doc = Application.DocumentManager.MdiActiveDocument;
    Database db = doc.Database;
    Editor ed = doc.Editor;

    PromptEntityOptions opt = new PromptEntityOptions("
请选择一条带扩展数据的多段线:");
    opt.SetRejectMessage("
请选择多段线!");
    opt.AddAllowedClass(typeof(Polyline), false);
    PromptEntityResult res = ed.GetEntity(opt);
    if (res.Status != PromptStatus.OK) return;

    using (Transaction tr = db.TransactionManager.StartTransaction())
    {
        Polyline pl = tr.GetObject(res.ObjectId, OpenMode.ForRead) as Polyline;
        if (pl == null) return;

        // 获取扩展数据
        ResultBuffer rb = pl.GetXDataForApplication("MY_APP");
        if (rb == null)
        {
            ed.WriteMessage("
该多段线未找到'MY_APP'相关的扩展数据。");
            return;
        }

        // 遍历并解析ResultBuffer中的TypedValue
        ed.WriteMessage("
--- 扩展数据内容 ---");
        foreach (TypedValue tv in rb)
        {
            // 根据DxfCode判断数据类型并输出
            switch (tv.TypeCode)
            {
                case (int)DxfCode.ExtendedDataRegAppName:
                    ed.WriteMessage($"
应用名称: {tv.Value}");
                    break;
                case (int)DxfCode.ExtendedDataAsciiString: // 1000
                    ed.WriteMessage($"
字符串数据: {tv.Value}");
                    break;
                case (int)DxfCode.ExtendedDataInteger16: // 1070
                    ed.WriteMessage($"
短整型数据: {tv.Value}");
                    break;
                // 可继续添加其他类型的处理,如1071(长整型)、1040(双精度浮点)等 default:
                    ed.WriteMessage($"
未知类型码[{tv.TypeCode}]: {tv.Value}");
                    break;
            }
        }
        rb.Dispose();
        tr.Commit();
    }
}

关键注意事项1. 注册应用程序名称 :在写入扩展数据前,必须确保其关联的应用程序名称(如 "MY_APP")已存在于当前图形的注册应用程序表(RegAppTable)中,否则数据可能无法正确关联或读取。

  1. 数据类型与DxfCode :扩展数据支持多种数据类型,每种类型对应一个特定的 DxfCode(如1000代表字符串,1070代表16位整数)。必须使用正确的代码,否则在读取时会产生错误或乱码。
  2. 性能与存储:扩展数据存储在DWG文件内部,大量或过大的扩展数据会增加文件体积。对于海量复杂属性,应考虑使用外部数据库关联实体句柄(Handle)的方案。
  3. 事务管理:所有涉及数据库对象(包括扩展数据操作)的代码都必须置于事务(Transaction)中,以确保数据的一致性和完整性。

参考来源

相关推荐
步步为营DotNet26 分钟前
Async 状态机要搬进运行时了:.NET 10 Runtime Async 实测,快的地方快 1.5 倍,贵的地方贵 5 倍
性能优化·c#·.net·async·runtime
hixiong1231 小时前
C# 使用 ZXingCpp.Angle 进行条码、二维码识别
开发语言·c#·扫码
步步为营DotNet1 小时前
System.Text.Json 源生成:三个“看起来已经生效“的静默失效
c#·.net·native aot·源生成
用户7884773163416 小时前
用 C# 把每周 6 小时的 PDF 录入干到 20 分钟:一份可复制的桌面 OCR 方案
c#
csdn_aspnet18 小时前
C# .NetCore Swagger ISchemaFilter 处理枚举、特殊类型
c#·.netcore·swagger
滴滴答答哒18 小时前
C# 技巧:优雅实现对象的“局部更新”与“字段合并”
开发语言·c#
code_long1 天前
.net core 连接打印机 使用zpl指令打印机,并且位图本地渲染zpl指令
c#·.netcore·位图·打印机·模板编辑·模板预览
csdn_aspnet1 天前
C# .NetCore Swagger ISchemaFilter Long 转 String 防精度丢失
c#·.netcore·swagger
下页、再停留2 天前
【C#桌面客户端系列学习-11】将SQLite数据库打包到exe里
数据库·c#·visual studio
下页、再停留2 天前
【C#桌面客户端系列学习-12】封装SQLite数据库基础操作工具类(CURD)
数据库·c#·visual studio