图形学【免费下载链接】ezdxfPython interface to DXF项目地址https://gitcode.com/gh_mirrors/ez/ezdxf点击查看免费下载导读 本文以 ezdxf 官方参考文档 xref.rst 为主体系统讲解ezdxf.xref模块自 ezdxf 1.1 起引入如何创建、检测、分离与嵌入外部引用XREF并深入其附带的数据导入能力——用load_modelspace、load_paperspace、write_block与低层Loader接口把外部 DXF 文件的实体与资源图层、线型、文字样式等搬进当前文档。读完本文你将掌握 XREF 的定义结构、三种冲突处理策略ConflictPolicy的取舍以及用几行代码完成合并多个 DXF 文件块定义外置为 XREFXREF 内嵌为普通块等高频实战任务。/导读XREF 的基本概念附着、嵌套与覆盖在 DXF 语境中附着式外部引用Attached XREF是指向某个绘图文件模型空间modelspace的链接对被引用文件所做的修改会在宿主文件下次打开或 XREF 重新加载时自动反映到当前图纸中。XREF 支持三种典型的组合用法嵌套一个 XREF 内部可以再附着另一个 XREF即 XREF 可以层层套叠多次引用同一个 XREF 可以被一个或多个 INSERT 实体反复引用每次引用都可以拥有不同的位置insert、缩放scale与旋转rotation覆盖Overlay与附着不同覆盖式 XREF 在该文件被其他图纸作为 XREF 附着/覆盖时不会被传递。也就是说overlay 只影响当前文档不会随文档的再次引用而递归带入适用于避免环形引用或控制引用传播链的场合。关于 DXF 文件作为附着 XREF 的兼容性提醒关联文档在开头就给出一个重要警告AutoCAD 只能把 DWG 文件显示为附着 XREF而 ezdxf 只能生成 DXF 文件。因此任何作为 XREF 附着到 DXF 文档的 DXF 文件都必须先转换为 DWG 才能在 AutoCAD 中正常显示。相比之下BricsCAD 等 CAD 应用则宽松得多BricsCAD 可以直接把 DXF 文件当作 XREF 显示尽管 BricsCAD 应用本身不允许用户在界面里直接附着 DXF 文件。源码注释也印证了这一点见 src/ezdxf/xref.py 第 157-171 行AutoCAD 甚至对 ezdxf 生成的 DXF R2000 文件也不予解析而 BricsCAD accepts any DXF/DWG file as XREF。示例 examples/xref/attach_dxf_dwg_xref.py 中的export_dwg_xref_document()正是演示了通过odafc.export_dwg()把 DXF 导出为 DWG 后再附着这是面向 AutoCAD 场景的推荐做法。XREF 的文档结构带标志的普通块定义从 DXF 结构看一个 XREF 本质上就是BLOCKS 段中的一个普通块定义block definition只是它带有特殊的标志位flags和一个指向外部文件的路径xref_path且块内没有内容——块的内容就是被引用文件的模型空间。它可以被一个或多个 INSERT 实体引用。对应的标志位定义在 src/ezdxf/lldxf/const.py常量值含义BLK_XREF4附着式外部引用BLK_XREF_OVERLAY8覆盖式外部引用BLK_EXTERNAL16外部引用外部文件标志ezdxf.xref内部的make_xref_flags()src/ezdxf/xref.py 第 242-246 行会按 overlay 与否组合出BLK_XREF | BLK_EXTERNAL或BLK_XREF_OVERLAY | BLK_EXTERNAL作为块定义标志。检测既有文档中的 XREF关联文档给出了两种查找模式。第一种是在 BLOCKS 段遍历块定义for block_layout in doc.blocks: block block_layout.block # 即 BLOCK 实体 if block.is_xref: handle_xref(block_layout) elif block.is_xref_overlay: handle_xref_overlay(block_layout)Block.is_xref与Block.is_xref_overlay属性实现在 src/ezdxf/entities/block.py 第 181-189 行二者分别检查块的BLK_XREF/BLK_XREF_OVERLAY标志位。第二种是在模型空间中查找引用 XREF 的 INSERT 实体for insert in msp.query(INSERT): if insert.is_xref: handle_xref_reference(insert) # ... 或者获取 XREF 的定义 block_layout insert.block() if block_layout is not None: handle_xref_definition(block_layout)Insert.is_xref()src/ezdxf/entities/insert.py 第 280-285 行内部通过self.block()取回关联的BlockLayout再委托给block_record.is_xref判断因此它同时覆盖 XREF 与 XREF_OVERLAY 两种情形。如果要在宿主文档中手动创建自己的 XREF 定义可以使用xref.define()它以指定名称在 BLOCKS 段新建一个带 XREF 标志与xref_path的块定义当同名块已存在时抛出XrefDefinitionError。而attach()会自动调用define()完成定义创建因此直接使用attach()时若块已存在同样会抛出该异常。高层函数实战ezdxf.xref模块对外提供以下高层函数全部实现在 src/ezdxf/xref.py函数用途attach把 DXF/DWG 文件作为 XREF 附着到宿主文档define创建 XREF 块定义不创建块引用detach把块定义分离为 XREF反向操作见embedembed把 XREF 内容内嵌为一个普通块定义dxf_info扫描 DXF 文件的基本设置与属性load_modelspace从另一份 DXF 文档加载模型空间内容load_paperspace从另一份 DXF 文档加载某个图纸空间布局write_block把实体写入一个新 DXF 文档的模型空间加载 DWG 文件内容需要一个能把 DWG 读成Drawing文档的加载函数官方推荐使用ezdxf.addons.odafc插件提供的odafc.readfile详见 odafc 插件。attach附着外部引用attach的完整签名src/ezdxf/xref.py 第 249-305 行def attach( doc: Drawing, *, block_name: str, filename: str, insert: UVec (0, 0, 0), scale: float 1.0, rotation: float 0.0, overlayFalse, ) - Insert:doc宿主 DXF 文档block_nameXREF 定义块的名称filename被引用文件路径insert默认块引用的插入点默认(0, 0, 0)scale统一缩放因子默认1.0非 1.0 时同时设置xscale/yscale/zscalerotation旋转角度默认0.0overlay为True时创建覆盖式 XREF否则为附着式。该函数在模型空间中自动创建默认块引用并返回该Insert实体。若要为同一个 XREF 追加更多引用直接复用块引用方法即可msp.add_blockref(block_name, insertanother_location)来自 docs/source/tutorials/xref_module.rst 的典型调用host_doc ezdxf.new(DXFVERSION, unitsunits.M) xref.attach(host_doc, block_namedxf_xref, insert(0, 0), filenameattached_xref.dxf) host_doc.set_modelspace_vport(height10, center(0, 0)) host_doc.saveas(attach_host_dxf.dxf)完整的可运行示例见 examples/xref/attach_dxf_dwg_xref.py它同时演示了新旧两种 APIv1.1 之前用doc.add_xref_def()msp.add_blockref()v1.1 之后统一由xref.attach()一站式完成。单位换算提醒重要如果 XREF 与宿主文档的绘图单位不同必须在块引用上以统一缩放因子补上两种单位之间的换算比例。attach()不会自动做这件事因为单位只能通过dxf_info()扫描被引用文件的 HEADER 段得知。官方建议同一项目内所有图纸尽量使用同一单位。dxf_info扫描 DXF 文件基本信息dxf_info(filename)只扫描 HEADER 段不加载整个文档返回一个DXFInfo对象包含 DXF 版本、文本编码、绘图单位与插入基点$INSBASE。二进制 DXF 与文本 DXF 分别由validator.binary_dxf_info()与validator.dxf_info()处理若文件不是 DXF抛出IOError。集成测试 integration_tests/test_dxf_info_scanning.py 中有现成的调用范例。detach把块定义分离为 XREFdetach(block, *, xref_filename, overlayFalse)src/ezdxf/xref.py 第 413-449 行执行的是与附着相反的操作把指定块定义的内容写入一个新 DXF 文档的模型空间然后把原块转换为外部引用。新文档需要由调用方自行saveas()写出如需 DWG 可以交给 odafc 转换xref_doc xref.detach(my_block, my_block.dwg) odafc.export_dwg(xref_doc, my_block.dwg)几点关键细节分离操作不会创建任何块引用——因为块与 XREF 的引用方式相同已存在的引用无需改动新文档的 DXF 版本、单位、$INSBASE基点为原块基点都会与源块保持一致分离后建议清理宿主文档的实体数据库doc.entitydb.purge()分离后宿主文档被修改务必保存宿主文档若要把结果喂给 AutoCAD应保证xref_filename与最终导出的 DWG 文件名一致。完整的 DXF/DWG 双路径示例见 examples/xref/detach_block_as_xref.py集成测试 integration_tests/test_xref_detach.py 验证了分离后新文档的 DXF 版本、单位、$INSBASE 以及全部块实体与资源图层、ATTRIB 模板等均正确保留。embed把 XREF 内嵌为普通块embed(xref, *, load_fnNone, search_paths(), conflict_policyConflictPolicy.XREF_PREFIX)src/ezdxf/xref.py 第 340-410 行把 XREF 引用的文件内容加载进该块定义是detach的逆操作默认用ezdxf.readfile加载 DXF加载 DWG 需传load_fnodafc.readfile对于有错误的 DXF 文件可用load_fnlambda f: recover.readfile(f)[0]当xref_path是相对路径时会依次在宿主文档所在目录及search_paths指定的目录中查找查找逻辑见find_xref()src/ezdxf/xref.py 第 308-337 行若被引用文件的 DXF 版本高于宿主文档抛出DXFVersionError可先用 odafc 降级 XREF或升级宿主文档加载成功后块定义会清除 XREF 标志BLK_XREF | BLK_EXTERNAL并把块的基点更新为源文档的$INSBASE使内嵌后的插入行为与原 XREF 一致。示例用法摘自 docs/source/tutorials/xref_module.rstimport ezdxf from ezdxf.addons import odafc doc ezdxf.readfile(attach_host_dwg.dxf) gear_xref doc.blocks.get(GEAR) try: xref.embed(gear_xref, load_fnodafc.readfile) except FileNotFoundError as e: print(str(e))完整示例见 examples/xref/embed_dxf_dwg_xref.py。write_block写出可作 XREF 的独立文档write_block(entities, *, origin(0, 0, 0))src/ezdxf/xref.py 第 466-498 行把一组实体写入一个新 DXF 文档的模型空间功能类似 CAD 中的WBLOCK命令新文档可以但不必须当作外部引用块使用。origin定义块基点——即模型空间中的哪个点会被对齐到块引用的插入点。注意虚拟实体virtual entity不被支持因为每个实体都需要真实的数据库与所有者句柄传入空列表时返回一个空的新文档。支持的实体范围当前实现只支持可复制、可变换的 DXF 实体即 LINE、CIRCLE 等全部基础实体类型以及块引用和与之关联的必需表项、OBJECTS 段对象。来自教程 docs/source/tutorials/xref_module.rst 的补充说明指出所有在布局与 XREF 之间搬运实体的操作本质上是复制因此以下不可复制实体无法传输DXF 参考手册未记载的实体ACAD_TABLEACAD_PROXY_ENTITYOLE2FRAME早期版本中的 ACIS 实体BODY、3DSOLID、REGION 等基于 AutoCAD 垂直产品Map 3D、Civil 3D、Architecture 等的自定义实体。关联文档还明确指出不支持被包装在DXFTagStorage中的保留未知实体如代理实体与对象不支持的实体一律忽略且不抛异常。大多数存放在 HEADER 与 OBJECTS 段的文档特性也不受支持例如 GROUPS、LAYER_FILTER、GEODATA、SUN。需要特别留意的是版本演进ezdxf 1.3.0 起已加入对 ACIS 实体的支持对应集成测试见 integration_tests/test_xref_load_acis.py示例见 examples/xref/load_and_transform_acis_entities.py。从外部文件导入数据与资源ezdxf.xref模块的另一个重要使命是替代旧的ezdxf.addons.importer.Importer插件。用户经常需要从其他 DXF 文件把数据导入当前文档而Importer插件能力有限、会丢弃大量资源ezdxf.xref则尽力保留尽可能多的信息。load_modelspace(sdoc, tdoc, filter_fnNone, conflict_policyKEEP)把源文档模型空间内容加载进目标文档模型空间filter_fn可对每个源实体返回True加载或False跳过load_paperspace(psp, tdoc, filter_fnNone, conflict_policyKEEP)把源文档的某个图纸空间布局作为新布局加载进目标文档同名布局会被自动改名为名称 (2)、名称 (3)……只加载图纸空间内容不加载模型空间内容因此加载进来的 VIEWPORT 显示的是目标文档的模型空间write_block见上文。合并多个 DXF 文件的经典场景docs/source/tutorials/src/xref/merge_dxf_files.pyimport ezdxf from ezdxf import transform, xref from ezdxf.math import Matrix44 merged_doc ezdxf.new() for index in range(3): sdoc ezdxf.readfile(gear.dxf) # 可以是不同的 DXF 文件 transform.inplace(sdoc.modelspace(), Matrix44.translate(index * 10, 0, 0)) xref.load_modelspace(sdoc, merged_doc) merged_doc.saveas(merged.dxf)教程提示如果目标只是往既有文档追加新实体更推荐直接ezdxf.readfile把源文档作为模板读取、追加内容后saveas另存load_modelspace更适合组合多个已有 DXF 文件这类场景。ConflictPolicy资源名冲突处理策略这里的资源指图层、线型、文字样式、标注样式、MLINE 样式、MLEADER 样式、材质与块等定义。当源文档与目标文档存在同名资源时即发生冲突。ConflictPolicy枚举src/ezdxf/xref.py 第 101-121 行提供三种策略策略行为适用场景ConflictPolicy.KEEP保留目标文档中的现有资源忽略源文档的同名资源加载的实体改用目标文档中的资源外观可能因资源不同而变化默认策略保守、稳定ConflictPolicy.XREF_PREFIX总是把加载的资源重命名为xref$0$namexref为源文档名$0$为生成唯一名的数字name为原名模拟 CAD 应用的导入行为即使无冲突也强制重命名ConflictPolicy.NUM_PREFIX仅当资源名在目标文档已存在时重命名为$0$name只在冲突时改名最大限度保留原名以下系统级资源名永远被 KEEP保留不参与重命名见 src/ezdxf/xref.py 第 147-155 行注释及_Transfer的实现资源STANDARD材质GLOBAL、BYLAYER、BYBLOCK打印样式NORMAL图层0、DEFPOINTS及 Autodesk 特殊图层以*开头线型CONTINUOUS、BYLAYER、BYBLOCK箭头等特殊块匿名块会被赋予符合匿名块命名规则的新名字如*D01→*D0815。冲突策略的逐项行为在测试 tests/test_05_tools/test_536_xref_conflict.py 中有系统验证集成测试 integration_tests/test_issue_1359_xref_keep.py 则验证了 KEEP 策略下合并文档不产生冗余资源。Loader低层加载接口Loader类是构建一切加载操作的基础积木src/ezdxf/xref.py 第 742-1002 行。它管理一组加载命令loading commands命令通过loader.execute()一次性执行loader xref.Loader(sdoc, tdoc) # 默认冲突策略为 KEEP loader.load_modelspace() # 或 load_paperspace_layout / load_block_layout ... loader.execute()为什么必须一次性执行因为资源名映射重命名必须全局一致如果分多次执行即使资源来自同一源文档每次加载也会生成不同的唯一名导致同名资源出现多个副本。execute(xref_prefix)中的xref_prefix正是XREF_PREFIX策略用于生成xref$0$name前缀的源文档名。Loader支持下列加载命令方法方法行为load_modelspace(target_layoutNone, filter_fnNone)把源模型空间内容加载进目标布局默认目标文档模型空间也可以是图纸空间或块布局load_paperspace_layout(psp, filter_fnNone)把源图纸空间布局作为新布局加载同名自动改名为名称 (2)等load_paperspace_layout_into(psp, target_layout, filter_fnNone)把源图纸空间内容合并进目标文档的某个既有布局load_block_layout(block_layout)把源块定义作为新块定义加载冲突时应用冲突策略load_block_layout_into(block_layout, target_layout)把源块定义内容合并进目标文档的某个既有布局load_layers(names)按名称列表加载图层表项load_linetypes(names)按名称列表加载线型表项load_text_styles(names)按名称列表加载文字样式表项load_dim_styles(names)按名称列表加载标注样式表项会连带加载其依赖的文字样式load_mline_styles(names)按名称列表加载 MLINE 样式load_mleader_styles(names)按名称列表加载 MLEADER 样式load_materials(names)按名称列表加载材质以 examples/xref/load_table_resources.py 为例加载表资源的完整流程loader xref.Loader(source_doc, target_doc) # 加载全部图层默认图层 0 和 DEFPOINTS 不会被加载它们总是存在于目标文档 loader.load_layers([layer.dxf.name for layer in source_doc.layers]) # 加载指定线型GAS 会因被图层 Layer0 引用而自动加载额外指定也无害 loader.load_linetypes([CENTER, DASHED, DASHDOT]) # 加载指定文字样式 loader.load_text_styles([OpenSans, LiberationMono]) # 加载全部标注样式会连带加载依赖的文字样式 loader.load_dim_styles([dimstyle.dxf.name for dimstyle in source_doc.dimstyles]) # 一次性执行全部加载命令 loader.execute()一个值得注意的语义加载图层并不会加载引用该图层的实体——图层只是 DXF 属性不是实体容器。底层执行流程Loader.execute()内部依次为注册命令资源 → 用CopyMachine复制块与对象 → 通过_Transfer注册表资源与对象资源 → 重定向句柄映射把复制实体的句柄重定向到目标文档既有资源→ 映射实体/对象的资源引用 → 复制文档设置 → 依次执行各命令 →finalize()。同时Loader构造时若目标文档 DXF 版本低于源文档会发出警告日志源与目标不能是同一文档断言。异常体系ezdxf.xref定义了以下异常src/ezdxf/xref.py 第 79-98 行异常触发条件XrefError模块基础异常XrefDefinitionError同名块定义已存在define/attach、参数不是 XREF 定义或未定义xref_pathembedEntityError传入虚拟实体write_block等实体级错误LayoutError目标/源布局类型非法、布局不属于对应文档如load_paperspace的源布局来自目标文档等此外还会向上抛出标准的FileNotFoundErrorXREF 文件找不到、DXFVersionErrorXREF 版本高于宿主文档与IOErrordxf_info遇到非 DXF 文件。错误处理测试集中在 tests/test_05_tools/test_535_xref_basic.py 与 tests/test_05_tools/test_536_xref_conflict.py。小结XREF 工作流的四类典型任务任务推荐 API把外部 DXF/DWG 附着为 XREFxref.attach(doc, block_name..., filename...)把块定义外置为独立 DXF/DWG 再引用xref.detach(block, xref_filename...)odafc.export_dwg()把 XREF 内容固化进当前文档xref.embed(block, load_fn...)跨文档搬运实体与资源xref.load_modelspace/load_paperspace/write_block或低层xref.Loader组合各load_*命令所有高层函数均基于Loader构建统一由execute()一次性执行以保证资源重命名的一致性冲突处理由ConflictPolicy统一收口。进一步深入学习可参阅官方教程 docs/source/tutorials/xref_module.rst、xref 参考文档、examples/xref 示例目录 以及源码 src/ezdxf/xref.py。赞分享图形学【免费下载链接】ezdxfPython interface to DXF项目地址https://gitcode.com/gh_mirrors/ez/ezdxf点击查看免费下载相关推荐ezdxf Importer 插件使用指南跨 DXF 文件实体导入与资源迁移实战ezdxf Importer 插件使用指南跨 DXF 文件实体导入与资源迁移实战 导读 本文聚焦 ezdxf 的 Importer 插件 ezdxf.add图形学gridstack.js React 封装设计决策双组件架构、静态回调与 Portal 渲染方案详解gridstack.js React 封装设计决策双组件架构、静态回调与 Portal 渲染方案详解 导读 本文档基于 react/DESIGN DECISI图形学Weave Net 动态挂载与卸载容器weave attach / detach 完整实战指南Weave Net 动态挂载与卸载容器weave attach / detach 完整实战指南 Weave Net 支持在容器已经运行之后动态地将其挂载a网络云原生上一篇3步找回QQ空间青春记忆GetQzonehistory终极指南下一篇mdBook 表格渲染全解析Markdown 表格语法、转义规则与 HTML 输出实现创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考