You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 22:43:15