如何使用LibreDWG库从DWG文件的图块中提取文本?
从DWG图块中提取文本的实现方案
你当前的代码仅能提取顶级TEXT实体,要获取图块内的文本,需要递归遍历DWG中的块定义(DWG_TYPE_BLOCK)和块参照(DWG_TYPE_INSERT),解析其中包含的嵌套实体。以下是基于现有libdwg框架修改后的完整实现:
核心修改点
- 新增递归函数处理块内实体,支持嵌套块解析
- 遍历所有实体时,同时处理
TEXT、BLOCK和INSERT三种类型 - 处理块参照时,关联对应的块定义提取内部文本
修改后的完整代码
#include <cstring> #include <cassert> #include <vector> #include <string> // 假设类成员变量: // std::wstring text; // std::wstring separator; // class Printer* printer; void DWGTextLoader::extractTextFromEntities(const std::vector<Dwg_Object*>& entities, Dwg_Data& dwg) { char* text_value{ nullptr }; int isnew{ 0 }; for (auto obj : entities) { if (obj->type == DWG_TYPE_TEXT) { Dwg_Entity_TEXT* text_ent = obj->tio.entity->tio.TEXT; dwg_dynapi_entity_utf8text(text_ent, "TEXT", "text_value", &text_value, &isnew, NULL); text.append(separator + utf8_decode(text_value)); if (isnew) { free(text_value); // 释放动态分配的内存,避免泄漏 text_value = nullptr; isnew = 0; } } else if (obj->type == DWG_TYPE_BLOCK) { // 解析块定义中的内部实体 Dwg_Entity_BLOCK* block_ent = obj->tio.entity->tio.BLOCK; std::vector<Dwg_Object*> block_entities; for (BITCODE_BL i = 0; i < block_ent->num_entities; ++i) { block_entities.push_back(&dwg.object[block_ent->entity_indexes[i]]); } extractTextFromEntities(block_entities, dwg); } else if (obj->type == DWG_TYPE_INSERT) { // 关联块参照对应的块定义 Dwg_Entity_INSERT* insert_ent = obj->tio.entity->tio.INSERT; if (insert_ent->block_index != -1) { Dwg_Object* block_obj = &dwg.object[insert_ent->block_index]; if (block_obj->type == DWG_TYPE_BLOCK) { Dwg_Entity_BLOCK* block_ent = block_obj->tio.entity->tio.BLOCK; std::vector<Dwg_Object*> block_entities; for (BITCODE_BL i = 0; i < block_ent->num_entities; ++i) { block_entities.push_back(&dwg.object[block_ent->entity_indexes[i]]); } extractTextFromEntities(block_entities, dwg); } } } } } int DWGTextLoader::loadFile(const std::string& filename) { text.clear(); this->filename = utf8_decode(filename); Dwg_Data dwg; memset(&dwg, 0, sizeof(Dwg_Data)); int success = dwg_read_file(filename.c_str(), &dwg); if (!(success < DWG_ERR_CRITICAL)) { printer->printError(L"文件错误!"); return success; } std::vector<Dwg_Object*> all_entities; for (BITCODE_BL i = 0; i < dwg.num_objects; ++i) { all_entities.push_back(&dwg.object[i]); } extractTextFromEntities(all_entities, dwg); if (text.empty()) { printer->printError(L"未找到任何文本!"); } dwg_free(&dwg); return success; } std::wstring utf8_decode(const std::string& text) { if (text.empty()) return std::wstring(); int size_needed = ::MultiByteToWideChar(CP_UTF8, 0, text.c_str(), static_cast<int>(text.size()), NULL, 0); assert(size_needed > 0); std::wstring wstrTo(static_cast<size_t>(size_needed), 0); MultiByteToWideChar(CP_UTF8, 0, text.c_str(), static_cast<int>(text.size()), &wstrTo[0], size_needed); return wstrTo; }
关键注意事项
- 内存管理:调用
dwg_dynapi_entity_utf8text后,若isnew为1,必须手动释放text_value,避免内存泄漏 - 嵌套块支持:递归函数会自动处理块中嵌套的其他块,确保所有层级的文本都被提取
- VS2022兼容性:libdwg官方Windows编译包可直接在VS2022中使用,若遇编译问题,确保项目设置为C++17或更高版本,并正确链接libdwg的静态/动态库
内容的提问来源于stack exchange,提问作者Dmitriy Zelenev
相关产品推荐
相关产品推荐

