
简介将 MATLAB 图形数据转换为 AutoCAD 标准交换格式 DXF是跨软件共享绘图成果时经常遇到的需求。这篇方法研究资料面向科研人员、测绘与地理信息相关工作者以及需要跨软件制图的工程师。内容来自一篇已发表论文围绕 MATLAB 句柄图形结构逐一讨论了文字、线、块、面、像五类图形对象的数据获取与转换要点文字需处理位置、内容、字体、旋转角以及 RGB 与 ACI 颜色系统差异线对象要注意线型映射和相对宽度转换块对象需解析顶点坐标、高程属性与索引配色面对象依赖网格化与三角化图像对象则要拆分为线条或块表示。同时梳理了从解析 FIG 文件句柄到写出 DXF 文件的完整流程给出各个关键属性的 get 函数调用方式对编写自动化转换脚本有直接参考价值。包体为 1 个 PDF约 431KB方便系统阅读。已有 267 人浏览学习反映出 MATLAB 与 CAD 数据互通的需求较为普遍。通过阅读可掌握各图形元素的数据提取与映射思路从而提升工程制图与数据复用的效率。1. Matlab 图形出图的下半场从 FIG 到 DXF 的转换路径Matlab 绘图能力强但画完图之后的路一直不好走。默认的 FIG 格式只在 Matlab 生态内流通导出 PNG 又丢失矢量信息放到 CAD、GIS 工具链里基本没法用。DXF 作为 AutoCAD 的外部数据交换格式被几乎所有 GIS 软件当作默认互通协议这才是 Matlab 图形真正需要抵达的地方。问题在于 Matlab 里一张图对应一棵句柄树字、线、块、面、像五类实体对象挂在不同的节点上属性存取方式各不相同颜色体系也和 AutoCAD 的 ACI 索引颜色对不上直接写 DXF 是写不出来的。这篇文章从数据提取、颜色映射、DXF 组码写入到典型图形的转换验证完整走一遍这个流程适合需要把 Matlab 科学计算图形送进 CAD/GIS 工作流的工程师。2. 句柄图形结构拆解五类实体对象的数据获取2.1 句柄树与实体对象的父子关系每次在 Matlab 里执行 figure、plot、text 这类命令时底层都会创建一个对应的句柄对象所有句柄构成一棵树。根节点是 figure下一层是 axes再往下是 line、text、patch、surface、image 这些实体对象。uicontrol 和 uimenu 属于界面控制类不参与图形数据的实际表达转换时可以直接忽略。理解这棵树的目的是为了定位对象。实际工作中最常见的问题是一张图里既有曲线又有注记还有色块想只取某一类靠肉眼去找句柄是不现实的需要用 findobj 按类型过滤。下面这段代码可以列出当前图窗下所有实体对象及其类型% 获取当前图窗所有 child 对象的 type 属性 fig gcf; all_children findobj(fig); types get(all_children, type); % 当对象多于一个时get 返回 cell需要逐个处理 if iscell(types) unique_types unique(types); for i 1:length(unique_types) n sum(strcmp(types, unique_types{i})); fprintf(%s: %d\n, unique_types{i}, n); end else disp(types); end这段代码先用 findobj 拿到当前图窗下全部对象句柄再批量读取 type 属性。type 属性返回字符数组对象多于一个时 get 返回 cell需要判断一下再统计。实际转换时不需要统计数量直接把 findobj 的结果按类型过滤后循环处理即可。2.2 文字对象位置、内容、旋转角度的提取文字对象转换中最关键的是位置、内容、字体大小、颜色和旋转角度五个属性。假设 th 是某个 text 对象的句柄用 get 逐项取pos get(th, position); % 位置[x y z]z 通常为 0 str get(th, string); % 文字内容 fnz get(th, fontsize); % 字号相对屏幕 ang get(th, rotation); % 旋转角度度 col get(th, color); % RGB 颜色0~1 浮点值这里有两个坑。第一个是颜色Matlab 的 color 属性返回 RGB 三分量浮点数而 DXF 的 TEXT 实体通过组码 62 写入 ACI 整数索引色需要一套查找表做映射具体做法在第 3 章展开。第二个是字号Matlab 的 fontsize 是相对屏幕的显示值AutoCAD 里 TEXT 实体的组码 40 是图纸上的绝对单位直接写进去没有实际尺寸意义转完要么手动批量改要么在生成实体前根据图框比例换算一个初始值。论文原文也明确提到这一点文字大小转换后需要手动批量修改。get(th)不加参数可以拿到全部属性但大批量转换时不要用这种方式去逐条翻属性直接按 DXF 需要的字段取值效率最高。2.3 线类对象坐标、线型、线宽的提取plot、line 生成的线对象数据提取相对简单。坐标在 xdata、ydata三维时还有 zdata线型在 linestyle线宽在 linewidth颜色同样在 color。点是线的一个特例当 linestyle 为 none 且 marker 不为 none 时这个对象实际表达的是散点DXF 里需要用 POINT 实体逐个输出。lh findobj(gcf, type, line); xdata get(lh, xdata); ydata get(lh, ydata); ls get(lh, linestyle); lw get(lh, linewidth); if strcmp(ls, none) % 这是散点按 POINT 实体逐个输出 else % 这是折线按 LINE 或 POLYLINE 输出 end线型是第二个需要映射的字段。Matlab 的线型样式只有-、--、:、-.几种AutoCAD 的全部线型定义在 acadiso.lin 文件中样式名是 CONTINUOUS、DASHED、CENTER 这类命名。转换前需要建立映射关系Matlab 线型AutoCAD 线型名备注-CONTINUOUS实线--DASHED虚线:DOTTED需在 lin 文件中确认存在-.CENTER点画线近似替代实际项目中我一般只映射实线和虚线两种。冒号和点画线在 DXF 标准线型库里没有严格对应的样式如果下游对线型有硬性要求更可靠的做法是转换后到 AutoCAD 里用 LINETYPE 命令统一替换而不是指望在 DXF 中一次写对。线宽同理Matlab 的 linewidth 以 pt 为单位是相对屏幕的显示值DXF 的 LINE 实体没有线宽字段线宽由图层或打印样式控制所以约定为不写入 DXF。2.4 块与面对象顶点、颜色与高程数据的提取2.4.1 patch 对象的 vertices 与 userdatapatch 是五类对象里信息量最大、也最容易出错的一类。Matlab 中的 patch 是一个或多个多边形区域contour 生成的等高线图在底层就是以 patch 形式存储的。描述 patch 对象的三个关键属性是 vertices转折点坐标、userdata用户数据等高线里通常是高程值和 cdata颜色数据。ph findobj(gcf, type, patch); % 如果有多条等高线ph 是句柄数组 for i 1:length(ph) xy get(ph(i), vertices); % N×2 或 N×3 顶点矩阵 z get(ph(i), userdata); % 当前多边形的高程值 cd get(ph(i), cdata); % 颜色数据矩阵 fv get(ph(i), facevertexcdata); % 每个面的颜色索引 end这里需要特别注意vertices 返回的顶点矩阵是所有多边形共用的要还原出每条等高线的闭合路径还需要配合 faces 或 facevertexcdata 属性来确定哪些顶点属于同一闭合多边形。等高线的 userdata 一般是一个标量代表当前多边形的高程值等高线分层设色时靠的就是这个值。2.4.2 面对象的 cdata 与配色方式surf、mesh 生成的面对象读取方式与 patch 类似差别在颜色产生方式。面对象的 cdata 是与网格顶点一一对应的矩阵每个网格单元的颜色由顶点颜色插值或填充得到。mesh 类函数生成的曲面只在网格线着色颜色随高度变化这部分颜色可以转成多段线的颜色保存下来surf 类函数对整个曲面做面填充AutoCAD 中没有对应的面填充方式转换后颜色信息会整体丢失。块对象的颜色确定有整块赋色、每多边形赋色、每顶点赋色三种方式contour 系列函数按第二种方式配色。颜色值的获取有两条路径cdata 直接给 RGB 值或者 facevertexcdata 按索引方式从 colormap 中取色。索引方式的转换公式放在第 3 章专门讲因为这里牵涉到 colormap 的线性映射直接决定 DXF 里每个多边形写什么颜色号。2.5 图像对象数据交换的边界image 对象的处理方式完全不同。AutoCAD 的 DXF 格式里光栅图像Raster Image只记录外部图片文件的路径和显示参数像素数据本身不进入 DXF 文件因此无需转换 Matlab 中的图像数据。如果原图里包含 image 对象常见做法是先把图像数据用 imwrite 导出为独立文件再在 DXF 中按路径引用。R12 版本的 DXF 对 IMAGE 实体支持有限实践中更稳妥的方案是跳过图像对象、单独交付图片文件让下游在 CAD 里手工插入。注意patch 对象的 userdata 不总是高程值。有一些绘图函数会把别的元数据塞进 userdata转换前先 disp 看一下内容确认是数值标量再做索引颜色映射。3. RGB 到 ACI 颜色桥接从颜色矩阵到索引映射3.1 两个颜色体系的差异Matlab 的 color 属性采用 RGB 三元组每个分量是 0 到 1 的浮点数例如红色是 [1 0 0]。DXF 实体通过组码 62 写入的是一到二百五十五之间的整数即 AutoCAD 的 ACI 颜色号。默认调色板里 1 到 7 是红、黄、绿、青、蓝、品红、白/黑七种标准色8 到 9 是灰度10 到 249 是各种渐变色7 号颜色比较特殊浅色背景下显示为黑色深色背景下显示为白色。这个差异带来的直接问题是不能把 Matlab 的 RGB 值原样写进 DXF必须做一次从浮点三元组到整数索引的映射。映射精度取决于色差计算方式最简单的是最近邻查找即计算目标 RGB 与 ACI 标准色表中每一行的欧氏距离取距离最小的 ACI 号。3.2 索引颜色计算Zindex 公式patch 对象按索引方式取色时处理的是 colormap。colormap 是 k×3 的矩阵k 默认 64每行是一个 RGB 三元组。patch 对象的 userdata 存储的高程值 zi经过线性变换映射到 1 到 k 之间的索引值论文给出的公式是Zindex fix((zi - zmin) / (zmax - zmin) * k) 1其中 zi 是当前多边形的高程值zmax 和 zmin 是全部多边形的最大最小高程fix 向零方向取整。得到的 Zindex 就是 colormap 矩阵中的行号这一行的 RGB 值就是该多边形在 Matlab 里显示的颜色。把这个 RGB 值再按 3.3 节的方法转成 ACI 颜色号就能在 DXF 中对等高线多边形着色。3.3 颜色映射实现% ACI 前 7 号标准色每行是 [R G B]取值 0~1 aci_table [ 1 0 0; % 1 Red 1 1 0; % 2 Yellow 0 1 0; % 3 Green 0 1 1; % 4 Cyan 0 0 1; % 5 Blue 1 0 1; % 6 Magenta 1 1 1; % 7 White ]; function aci rgb2aci(rgb, aci_table) % rgb: 1×3 浮点数组取值 0~1 diff aci_table - rgb; dist sum(diff.^2, 2); [~, idx] min(dist); aci idx; end % 从 colormap 索引取色并转 ACI cmap colormap(gcf); k size(cmap, 1); zmin min(all_z); zmax max(all_z); % 防止 zmax zmin 时除零 if zmax - zmin eps zidx 1; else zidx fix((zi - zmin) / (zmax - zmin) * k) 1; zidx min(max(zidx, 1), k); % 边界夹紧 end rgb cmap(zidx, :); aci rgb2aci(rgb, aci_table);这段代码的关键在于先算 colormap 行号再查 RGB最后取最近的 ACI 颜色。zmax 等于 zmin 的情况实际中会出现比如所有等高线都是同一高度此时直接用 eps 做保护跳过颜色映射给默认颜色即可。边界问题要特别留意。fix 在负数区域是向零取整如果 zi 恰好等于 zmin公式计算结果是 1不会出界但浮点误差可能导致结果小于 1 或大于 k必须用 min/max 夹紧否则第 4 章写 DXF 时可能因为越界索引取到空值。3.4 常用颜色对照表颜色Matlab RGBACI红[1 0 0]1黄[1 1 0]2绿[0 1 0]3青[0 1 1]4蓝[0 0 1]5品红[1 0 1]6白/黑[1 1 1] 或 [0 0 0]7如果图形用了默认的 parula 或 jet colormap里面大部分颜色和 ACI 标准色都有差距最近邻映射后色差肉眼可见。对颜色精度要求高的场景建议导出为 DXF 后在 CAD 里手动指定 ACI 颜色不要依赖自动映射。4. 组装 DXF R12 文件ENTITIES 节写入与非法符号处理4.1 为什么选 R12 版本DXF 版本很多R12 是结构最简单、兼容性最好的一版。R12 的 DXF 文件不需要写完整的 HEADER 变量和 TABLES 节AutoCAD 允许缺省这些部分最简单的文件甚至可以仅由 ENTITIES 节和 EOF 标志组构成。几乎所有 GIS 软件和新版 AutoCAD 都保留了 R12 的读取能力数据量小、便于程序写入这是做格式转换时选 R12 的理由。4.2 DXF 文件的最小结构与组码一个可被 AutoCAD 打开的 DXF 文件最小结构是 ENTITIES 节加 EOF 标记。DXF 的基本单位是组码group code和值value组码占一行值占下一行成对出现。常用组码的含义如下组码含义适用实体0实体或节开始全部2节名称ENTITIES 等SECTION8图层名全部10/20/30主点坐标 X/Y/ZLINE、TEXT、VERTEX11/21/31第二点坐标 X/Y/ZLINE40文字高度TEXT1文本内容TEXT50旋转角度度TEXT62ACI 颜色号全部66是否跟随 VERTEX 子实体1是POLYLINE70多段线状态1闭合0开放POLYLINE4.3 实体写入函数LINE 实体需要两组坐标组码 10/20 是起点组码 11/21 是终点。TEXT 实体需要插入点10/20、高度40、内容1和可选的旋转角50。function write_dxf_line(fid, x1, y1, x2, y2, layer, aci) fprintf(fid, 0\nLINE\n); % 实体类型标记 fprintf(fid, 8\n%s\n, layer); % 图层名 fprintf(fid, 62\n%d\n, aci); % ACI 颜色号 fprintf(fid, 10\n%.6f\n20\n%.6f\n, x1, y1); fprintf(fid, 11\n%.6f\n21\n%.6f\n, x2, y2); end function write_dxf_text(fid, x, y, height, rotation, content, layer, aci) fprintf(fid, 0\nTEXT\n); fprintf(fid, 8\n%s\n, layer); fprintf(fid, 62\n%d\n, aci); fprintf(fid, 10\n%.6f\n20\n%.6f\n, x, y); fprintf(fid, 40\n%.6f\n, height); fprintf(fid, 1\n%s\n, content); if rotation ~ 0 fprintf(fid, 50\n%.6f\n, rotation); end end说明关键参数fid 是 fopen 打开的文件句柄写入模式用 wlayer 指定实体所在图层转换时按原始对象的类型分层方便 CAD 里批量控制aci 由第 3 章的颜色映射得到如果不写 62 组码实体继承图层颜色这有时反而更灵活。折线类型的对象建议写成 POLYLINE。等值线这类闭合路径适合用 POLYLINE 加 VERTEX 子实体表达function write_dxf_polyline(fid, xy, layer, aci, closed) fprintf(fid, 0\nPOLYLINE\n); fprintf(fid, 8\n%s\n, layer); fprintf(fid, 66\n1\n); % 后跟 VERTEX 子实体 fprintf(fid, 70\n%d\n, closed); % 1闭合0开放 for i 1:size(xy, 1) fprintf(fid, 0\nVERTEX\n); fprintf(fid, 8\n%s\n, layer); fprintf(fid, 10\n%.6f\n20\n%.6f\n, xy(i,1), xy(i,2)); end fprintf(fid, 0\nSEQEND\n); end多段线的 70 组码决定闭合性。等高线本身是闭合的用 1从 plot 出来的普通曲线且首尾不相连用 0。写完后记得补 SEQEND 结束子实体序列漏掉它 AutoCAD 打开时多段线显示不完整。4.4 Inf、NaN 与特殊字符过滤这个坑在实际转换中出现频率很高。Matlab 的坐标数组里 Inf 和 NaN 是合法值还能参与绘图NaN 会让连线断开但 DXF 的坐标组码只接受有限数值。写入之前必须统一过滤for i 1:numel(xdata) if ~isfinite(xdata(i)) || ~isfinite(ydata(i)) continue; % 跳过非法点断路处直接断开 end % 正常写入该点 end另外TEXT 实体里的字符串如果包含换行符或回车符也会导致 DXF 解析异常。写入前把 char(10) 和 char(13) 替换成空格或者按行拆分多个 TEXT 实体。这个问题在 AutoCAD 打开时通常不报错只是文字错位排查起来很费时间。4.5 图层组织策略一张图可能包含几百个实体对象全放在一个图层里下游打开后很难管理。常见做法是按对象类型分层text 对象落到 TEXT 层line 对象落到 LINE 层patch 对象落到 PATCH 层surface 对象落到 SURFACE 层。更细一点可以在图层名里追加原始 axes 编号或图例标签比如CONTOUR_3方便 CAD 里按图层冻结或改色。实现上只需要把 4.3 节函数里的 layer 参数从常量改成变量由上游解析逻辑传入。5. 转换试验复盘等高线、曲面与注记文字的实际效果5.1 contour 等高线的 patch 提取论文中的转换试验选了 contour(peaks) 作为块对象代表。逐个 patch 取出 vertices 和 userdata按第 3 章的索引公式计算每个闭合多边形的 ACI 颜色用第 4 章的 POLYLINE 写法落入 DXF。这样转出来的等高线形状、闭合性、分层颜色基本保持不变。需要单独检查每个 patch 对象的闭合环是否完整凡是出现 NaN 断点的多边形在 DXF 里会形成开口多段线这类位置要回到原始数据排查。5.2 meshz 曲面的颜色丢失meshz(peaks) 这类面对象转换后会丢颜色。surf 类面对象依赖网格单元的面填充色DXF 的 POLYLINE 只能给整条线一个颜色不能按网格渐变着色。如果项目里确实需要保留曲面颜色语义我一般用 mesh 代替 surf把曲面网格线转成多段线用 CData 按高度着色颜色能保住代价是图形从面填充变成线框。这个取舍取决于下游用途出版级插图建议直接导出矢量格式DXF 只承担数据交换职能。5.3 文字注记的位置与压线处理从论文的转换试验看文字注记的位置和角度转换正确但存在压线现象。DXF 的 TEXT 实体只记录插入点文字的实际包围盒由字体和高度在 CAD 端重新计算渲染结果不一定和 Matlab 完全一致。解决方法是生成 TEXT 实体前给每个注记加一个偏移量方向和距离根据注记与相邻实体的空间关系估算通常往右上方偏移若干图纸单位。这个偏移值在 Matlab 没有现成属性需要按实体包围盒的外扩量手工计算。5.4 坐标比例失真的修正Matlab 横纵轴默认按数据范围自适应缩放x 和 y 方向的比例通常不同直接转换到 CAD 后图形会被压扁或拉长。写入前读取 dataaspectratio 做等比修正dar get(gca, dataaspectratio); % 保持 x 方向原始尺度y 坐标按比例缩放 x_dxf xdata; y_dxf ydata / (dar(2) / dar(1));这样得到等比的坐标数据。具体按哪个方向缩放取决于你希望保留哪一维的原始尺度实际项目中我倾向保持 x 不变、调整 y。提示转换完成后在 AutoCAD 里用 DXFIN 命令或直接拖入文件验证。打开后先执行 LIST 命令抽查几个关键实体的坐标和颜色值再执行 REGEN 全图重生成确认没有解析警告。批量转换时用脚本循环处理 DXF 文件但手工抽检仍是最稳妥的兜底方式。本文还有配套的精品资源点击获取