Pular para o conteúdo principal

Extraindo Informações de documentos AutoCAD baseado em proximidade


Essa semana comecei um trabalho novo de verificação. Basicamente trata-se de verificar uma lista de construção. Essa lista é uma planilha em Excel que resume uma série de informações que também estão disponíveis em documentos DWG.

Inicialmente pensei em fazer uma análise qualitativa por amostragem. Nesse caso pegaria aleatoriamente parte das informações e se estivessem válidas assumiria que tudo estava correto. Talvez isso não seria o bastante para evitar um erro de engenharia afinal são 111 documentos DWG mais de 4000 informações para compatibilizar.

Pensando melhor é possível fazer um programa para extrair as informações do AutoCAD de modo sistemático?
Bom é possível sim e depende muito de como você vai isolar a informação.
A primeira parte do trabalho foi identificar o que estava padronizado no meio da quantidade de objetos e textos espalhados pelo documento.


Então vendo o texto padrão consegui notar duas coisas:

Todas as informações do texto estão alinhadas;

Existem pedaços de texto chaves como “VPtmin=” e “VPvext=”.

A ideia é localizar um objeto texto que contenha “VPtmin=”, como é um objeto vetorial tem coordenada de inserção podemos localizar sua coordenada X,Y e para textos próximos podemos associar como pertencentes ao mesmo “bloco” de informação.
Organizacionalmente o código seria assim:
  1. Listar todos os objetos do desenho; 
  2. Localizar os que são texto; 
  3. Localizar os que contêm o texto “VPtmin=”; 
  4. Listar novamente todos os objetos do desenho; 
  5. Localizar os que são texto; 

Se o texto tem coordenadas X,Y próximas do texto localizado em 3 associa (coloca na lista) incluindo o “VPtmin=”;

Aqui segue o exemplo de código

/// <summary>
/// Lê as informações de torre de diversos arquivos DWG de Planta e Perfil
/// e apresneta o resultado como uma lista em texto
/// </summary>
[CommandMethod("Extract1", CommandFlags.Session)]
public void Extract1()
{
    Document doc = Application.DocumentManager.MdiActiveDocument;
    Editor edo = doc.Editor;

    //Cria um texto de saída de dados
    String txtOuput = "";
  

    //Seleciona todos os objetos do DWG
    Database db = doc.Database;
    PromptSelectionResult acSSPrompt = Application.DocumentManager.MdiActiveDocument.Editor.SelectAll();

    //Verifica se a seleção foi OK
    if (acSSPrompt.Status != PromptStatus.OK)
    {
edo.WriteMessage("\nErro na seleção de objetos do comando PromptStatus = " + acSSPrompt.Status.ToString());
return;
    }

    //Abre a transaction
    Transaction tr = db.TransactionManager.StartTransaction();
    using (tr)
    {

SelectionSet acSSet = acSSPrompt.Value;

//Localiza todos os objetos que tem o texto padrão
foreach (SelectedObject acSSObj in acSSet)
{
    if (acSSObj == null)
continue;

    Entity acEnt = tr.GetObject(acSSObj.ObjectId, OpenMode.ForRead) as Entity;

    if (acEnt == null)
continue;

    // verifica se o objeto é um DBText, se sim, modifica o tamanho e o pontos de aprisionamento do texto.
    if ((acEnt.GetType() == typeof(Autodesk.AutoCAD.DatabaseServices.DBText)))
    {
DBText myText = new DBText();
myText = (DBText)acEnt;

if (myText.TextString.Contains("VPtmin="))
{
    //Dentro da mesma seleção busca os objetos que estão na proximidade
    foreach (SelectedObject acSSObj2 in acSSet)
    {
// Check to make sure a valid SelectedObject object was returned
if (acSSObj2 == null)
    continue;

// Open the selected object for write
Entity acEnt2 = tr.GetObject(acSSObj2.ObjectId, OpenMode.ForRead) as Entity;

// Check to make sure a valid Entity object was returned
if (acEnt2 == null)
    continue;

if ((acEnt2.GetType() == typeof(Autodesk.AutoCAD.DatabaseServices.DBText)))
{
    DBText myText2 = new DBText();
    myText2 = (DBText)acEnt2;
    if ((myText2.Position.X < (myText.Position.X + 5)) && (myText2.Position.X > (myText.Position.X - 5)))
    {
if ((myText2.Position.Y < (myText.Position.Y + 250)) && (myText2.Position.Y > (myText.Position.Y - 250)))
{
    //Se extá no range gera a saída.
    txtOuput += myText2.TextString + "\t";
}
    }
}
    }
    txtOuput += "\n";
}
    }
}
    }

    edo.WriteMessage("\nComando executado com sucesso!");

    //Apresenta em um formulário do windows com uma caixa de texto
    TextoutputForm tofrm = new TextoutputForm();
    tofrm.richTextBox1.Text = txtOuput;
    tofrm.Show();
}

Esse código em si tem alguns problemas.

Como ele só localiza o texto ele não organiza as informações, é possível que as informações venham embaralhadas o que daria um trabalho de reorganiza-las. No meu caso eu descobri que simplesmente elas já tinham sido inseridas em ordem então não gera grandes problemas.

Outro problema é que algum texto estiver duplicado ele aparecerá duas vezes por isso antes de executar é recomendável usar o comando OverKill para matar as duplicatas.
Por fim as informações próximas em formato de texto também serão importadas por isso é sempre necessário fazer uma limpeza e um ajuste nos ranges de busca dos textos próximos.

Com essa ferramenta acho que economizei mais de 1 semana de trabalho.

Esse é mais um exemplo de como um código relativamente simples pode simplificar muito o trabalho repetitivo no AutoCAD. As vezes vemos as informações soltas e sem ordem e pensamos que não é possível automatizar o processo mas pensando um pouco melhor isso é possível sim.

Comentários

Postagens mais visitadas deste blog

Numeração Automática no AutoCAD

Sem dúvida esse é uma ferramenta única que fazia falta a tempos e foi introduzida recentemente no AutoCAD, na última década… Em 2013 tinha feito um programa para criar uma bolinhas de numeração automática usando o conceito de Leader eu fazia um controle dos números dos itens na mão mesmo, depois de um tempo resolvi fazer um menuzinho para controlar o conteúdo do número dos bullets, hoje isso não é mais necessário, existe um comando no próprio AutoCAD para isso e faz parte das Ferramentas Expressas do AutoCAD. Gosto de compartilhar ferramentas e dicas que tendem a ser menos conhecidas ou subutilizadas, mas ainda podem fornecer um impulso para sua produtividade e fluxo de trabalho e que eu mesmo me surpreendi quando as encontrei Hoje, quero apresentar outra ferramenta, a numeração automática. Como o nome indica, o comando Numeração automática permite que você adicione automaticamente um número às etiquetas ou texto em um desenho. Vou mostrar como a numeração automática pode ser usada par...

Alterar a cor de fundo do AutoCAD

Eu sou um adepto do fundo preto, tudo que eu posso mudo a cor do fundo para preto. Nas ultimas versões do AutoCAD tenho notado que não é mais o padrão o fundo preto absoluto, é um cinza escuro. As vezes gosto também de mudar a cor do Layout de branco para preto afinal de contas quando trabalhamos com penas e contraste no model space preto, ver um desenho no layout é impossível.  Você pode mudar sua cor de fundo do AutoCAD para a cor que quiser. Definindo cores personalizadas Primeiro, vá para o menu Opções (botão Aplicativo> Opções), selecione a guia Exibição e clique no botão Cores. Agora você deve ver a caixa de diálogo Cores da janela de desenho: Agora você pode atualizar as cores de qualquer elemento da interface. Isso incluí o plano de fundo em qualquer contexto (selecione Model e Layout). Você pode escolher qualquer uma das predefinições, ou você pode escolher a partir de todo o espectro (basta escolher a opção Selecionar Cor ...). Se você não gost...

Unindo blocos em AutoCAD utilizando .NET

Hoje me deparai com uma necessidade de unir blocos com propriedades então resolvi fazer um comando para realizar esses procedimento. A principio esse procedimento não é tão complexo de ser executado individualmente mas por outro lado gostaria também de analisar um pouco melhor as possibilidades de se manipular blocos utilizando o AutoCAD. Abaixo o código que utilizei: using Autodesk.AutoCAD.ApplicationServices ; using Autodesk.AutoCAD.DatabaseServices ; using Autodesk.AutoCAD.EditorInput ; using Autodesk.AutoCAD.Runtime ; using System.Linq ; // This line is not mandatory, but improves loading performances [assembly: CommandClass(typeof(Merging_AutoCAD_blocks.Comandos))] namespace Merging_AutoCAD_blocks { public class Comandos { /// <summary> /// Uni dois ou mais blocos em um unico bloco. /// </summary> [CommandMethod("MERGBLKS")] public static void UnindoBlocos () {...