尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

libdxfrw 快速入门:30 分钟打通 DXF/DWG 图纸文件的读取与生成

libdxfrw 快速入门:30 分钟打通 DXF/DWG 图纸文件的读取与生成 libdxfrw 快速入门30 分钟打通 DXF/DWG 图纸文件的读取与生成【免费下载链接】libdxfrwC library to read and write DXF/DWG files项目地址: https://gitcode.com/gh_mirrors/li/libdxfrw你有没有遇到过这种情况客户甩过来一张.dwg图纸你的程序却只认.dxf两边的数据对不上或者你想在自家软件里做个图纸预览、批量提取标注文字去问商业 SDK 的价格被报价单吓了回来。别急着放弃libdxfrw就是一个免费开源的 C 库能读写 DXFASCII 和二进制两种也能解析从 R14 到 V2015 的 DWG 文件正好把这块短板补上。这篇 libdxfrw 实战教程我们沿着一条主线走把一个 DWG 图纸变成你自己程序里能用的数据再反方向生成图纸文件。开工之前这个库到底值不值得用先花一分钟看清它的家底心里有数再动手能力说明DXF 读写ASCII 与二进制两种 DXF 都能读能写从 R12 到 2010 多个版本DWG 读取内置多个版本化阅读器覆盖 R14、2004、2007、2010、2013/2015字符编码内置多张代码页码表图纸里的日文、中文、韩文标注能转成 UTF-8集成方式CMake、Autotools、Visual Studio 都能构建Linux/macOS/Windows 通吃开源协议GPL v2免费商用需注意条款见仓库根目录的 COPYING它的设计思路很小而美核心库只有一层薄薄的文件解析与实体模型具体怎么用完全由你决定。官方还附带两个现成工具dwg2dxf和dwg2text可以直接当教程读也可以当命令行工具用。先把库装进工程最快安装方法推荐走 CMake四个命令搞定git clone https://gitcode.com/gh_mirrors/li/libdxfrw cd libdxfrw mkdir build cd build cmake .. -DCMAKE_BUILD_TYPERelease make -j$(nproc) sudo make install编译依赖只有一个 libiconv负责字符编码转换Linux 下一般系统自带或一条包管理命令就能装上。安装后头文件在/usr/local/include/静态库是/usr/local/lib/libdxfrw.a。编译你自己的程序时记得加上-ldxfrw -liconv两个链接参数少一个都会报链接错误。理解它的插座设计回调接口就是全部秘密动手写代码之前先搞懂这个库最核心的一个概念回调接口。libdxfrw读取文件时并不是读完了把整个对象树扔给你而是边解析边调用一个接口里的各个虚函数读到一条直线就调addLine()读到一个圆就调addCircle()。你要做的就是继承这个接口、把你关心的函数填上自己的逻辑。这个接口定义在src/drw_interface.h里是整份契约的源头先读它再读实现效率最高。这正是整个库最值钱的设计解析细节被完全隔离在库内部你只跟一二十个回调函数打交道。因为 DWG 和 DXF 用的是同一套回调你写一份代码两种格式通吃——后面我们会用到这一点。第一个实战把图纸里的线段和圆读出来直接上代码。假设你想统计一张图纸里有多少条直线、多少个圆半径分布如何#include libdxfrw.h class DumpReader : public DRW_Interface { public: int lineCount 0, circleCount 0; // 表/头信息相关回调全部留空 void addHeader(const DRW_Header*) override {} void addLType(const DRW_LType) override {} void addLayer(const DRW_Layer) override {} void addDimStyle(const DRW_Dimstyle) override {} void addVport(const DRW_Vport) override {} void addTextStyle(const DRW_Textstyle) override {} void addAppId(const DRW_AppId) override {} void addBlock(const DRW_Block) override {} void setBlock(const int) override {} void endBlock() override {} // 实体回调只关心直线和圆 void addLine(const DRW_Line d) override { lineCount; printf(LINE (%.2f, %.2f) - (%.2f, %.2f)\n, d.basePoint.x, d.basePoint.y, d.secPoint.x, d.secPoint.y); } void addCircle(const DRW_Circle d) override { circleCount; printf(CIRCLE center(%.2f, %.2f) r%.2f\n, d.basePoint.x, d.basePoint.y, d.radious); } // 其余几十个实体回调点、圆弧、多段线、文字……照这个格式写空实现 void addPoint(const DRW_Point) override {} void addArc(const DRW_Arc) override {} void addEllipse(const DRW_Ellipse) override {} // ... }; int main(int argc, char* argv[]) { DumpReader r; dxfRW dxf(argv[1]); // 传入文件路径 if (!dxf.read(r, false)) return 1; // false 不做 2D 投影 printf(lines%d circles%d\n, r.lineCount, r.circleCount); return 0; }解释两句为什么这么写read()的第二个参数传false表示保留原始 3D 坐标传true会把实体做 extrusion拉伸方向投影成 2D坐标会被改写。做 CAD 预览可以传true做数据提取建议传false。接口里有大量纯虚函数一个都不能漏漏一个就编译不过。别嫌麻烦把所有回调都写上空实现是必须的功课。反方向操作让程序自己生成一张 DXF读出来之后自然会想写回去。生成文件同样走这个接口只不过这次换成写方向你在writeEntities()里构造实体通过一个写入器指针发出去最后指定版本号#include libdxfrw.h class MiniWriter : public DRW_Interface { public: dxfRW* w nullptr; void writeHeader(DRW_Header) override {} void writeBlocks() override {} void writeBlockRecords() override {} void writeLTypes() override {} void writeLayers() override {} void writeTextstyles() override {} void writeVports() override {} void writeDimstyles() override {} void writeAppId() override {} void writeEntities() override { DRW_Line l; l.basePoint.x 0; l.basePoint.y 0; l.secPoint.x 100; l.secPoint.y 80; w-writeLine(l); // 通过 dxfRW 写入实体 } }; int main() { dxfRW dxf(out.dxf); MiniWriter mw; mw.w dxf; // 第三个参数 false ASCII 格式true 二进制 if (!dxf.write(mw, DRW::AC1015, false)) return 1; return 0; }注意版本号别用 R2000 这种叫法版本枚举定义在src/drw_base.h里是 AC 开头的编码AC1009对应 R12AC1015对应 2000依次到AC10242010、AC10272013。写出来的文件直接拖进 CAD 软件就能打开正反馈即时拉满。统一入口DXF 和 DWG 用同一套代码读取前面说这个库一套回调通吃两种格式现在兑现。dxfRW管 DXFdwgR管 DWG两者接口签名几乎一致可以封装一个格式无关的导入函数#include libdxfrw.h #include libdwgr.h bool importAny(const char* path, DRW_Interface* cb) { std::string p(path); std::string ext p.size() 4 ? p.substr(p.size() - 4) : ; std::transform(ext.begin(), ext.end(), ext.begin(), ::toupper); if (ext .DXF) return dxfRW(path).read(cb, false); if (ext .DWG) return dwgR(path).read(cb, false); return false; }上层业务只认DRW_Interface一种回调底层是 DXF 还是 DWG 完全不关心。如果你收到的是 DWGdwgR内部会先探测文件版本R14 到 V2015再交给对应的版本化阅读器解析。不想写代码仓库自带的两个现成工具如果你只是偶尔转一次图纸或者想找个参考实现仓库里的两个工具可以直接用源码分别在dwg2dxf/和dwg2text/目录。dwg2dxf —— 格式转换器。把 DWG 转成 DXF顺便还能做版本迁移老图纸转新格式或新图纸降级成 R12dwg2dxf input.dwg -v2000 out.dxf # 转成 2000 版 ASCII dwg2dxf input.dwg -b -v2007 out.dxf # -b 输出二进制 DXF dwg2dxf list.txt -B -v2000 outdir # -B 批量模式list.txt 里每行一个文件参数速查-R12 / -v2000 / -v2004 / -v2007 / -v2010选输出版本-b输出二进制-B批量转换到指定目录-y输出文件已存在时静默覆盖。为什么版本迁移这么顺手因为它读进来用的是DRW_Interface回调写出去又走同一套回调中间天然就是一次翻译。dwg2text —— 文字提取器。把图纸里的 TEXT、MTEXT、尺寸标注文字全部打印到终端配合管道就能导入数据库。它内部还处理了 MTEXT 的格式代码比如\P换行、\f字体声明输出的是干净文本这个清洗逻辑在dwg2text/dx_iface.cpp里值得抄走。中文乱码排查先看 code page再动源码提取文字最常见的坑是乱码很多人第一反应是改源码其实方向错了。图纸里的文字在存储时可能用的是 CP932日文 Shift-JIS、CP936简体中文 GB2312、CP949韩文、CP950繁体 Big5等编码。libdxfrw内置了对应的四张码表src/intern/drw_cptable932.h、drw_cptable936.h等配合src/intern/drw_textcodec.cpp做自动转换你拿到回调里的字符串通常已经是 UTF-8。如果乱码优先检查源图纸声明的 code page 与内容是否一致再检查你程序输出端的编码——这两步排查完九成的乱码问题都能解决别急着怀疑库。翻车高发区速查把新手最容易踩的坑集中列一下对照自查症状原因对策编译不过报纯虚函数未实现DRW_Interface的回调没写全所有虚函数都给空实现一个别漏链接报 undefined reference少了 iconv编译命令补-ldxfrw -liconv坐标对不上read()的 ext 参数误传true要原始 3D 坐标就传false想用库直接写 DWG库里没有 DWG 写入功能先写 DXF再用dwg2dxf转回 DWG读 DWG 报版本不支持文件版本太新或已损坏用dwgR::getError()区分是版本问题还是文件问题两个容易被忽略的小机关最后送你两个藏起来的实用功能用好了能省不少事。机关一椭圆离散化精度控制。如果下游程序不支持椭圆实体比如老版本的 R12 环境可以先把椭圆转成多段线再输出。调用dxf.setEllipseParts(64)设置分段数数值越大越接近真实椭圆代价是文件体积略增。默认分段数偏低大尺寸椭圆放大后会看到棱角调大即可。机关二调试开关与错误定位。遇到解析失败dxf.setDebug(DRW::DEBUG)会输出解析进度和关键状态相当于给库装上了一个心电图。配合dwgR::getError()错误码枚举在src/drw_base.h有BAD_OPEN、BAD_VERSION等和dwgR::getVersion()能快速判断是文件损坏、版本不支持还是路径写错。对了仓库tests/目录下还有一组单元测试覆盖实体、多段线、文字、版本兼容、错误处理等场景在 build 目录里跑一句ctest就能验证你的环境是否正常。收尾回到开头那个场景客户发来的 DWG 打不开你的程序只认识 DXF。现在你知道了一次git clone加 30 行回调代码图纸里的坐标、文字、图层就都变成了你程序里的数据结构反过来说你也能凭空生成一张 CAD 能打开的图纸。从图纸打不开到程序里跑出坐标中间只差一次动手。把上面的读取器粘进你的工程跑一遍手头那张图纸——十分钟后的成就感值得你立刻开始。【免费下载链接】libdxfrwC library to read and write DXF/DWG files项目地址: https://gitcode.com/gh_mirrors/li/libdxfrw创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表