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