Pular para o conteúdo principal

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()
        {
            var doc = Application.DocumentManager.MdiActiveDocument;
            if (doc == null)
                return;

            var db = doc.Database;
            var ed = doc.Editor;

            // Obtém o nome do primeiro bloco para mesclar
            var pr = ed.GetString("\nEnter name of first block");
            if (pr.Status != PromptStatus.OK)
                return;

            string first = pr.StringResult.ToUpper();

            using (var tr = doc.TransactionManager.StartTransaction())
            {
                var bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead);

                // Verifique se o primeiro bloco existe
                if (bt.Has(first))
                {
                    // Obtém o nome do segundo bloco para mesclar
                    pr = ed.GetString("\nEnter name of second block");
                    if (pr.Status != PromptStatus.OK)
                        return;

                    string second = pr.StringResult.ToUpper();

                    // Verifique se o segundo bloco existe
                    if (bt.Has(second))
                    {
                        // Obtém o nome do novo bloco
                        pr = ed.GetString("\nEnter name for new block");
                        if (pr.Status != PromptStatus.OK)
                            return;

                        string merged = pr.StringResult.ToUpper();

                        // Verifique se o novo bloco ainda não existe
                        if (!bt.Has(merged))
                        {

                            // Precisamos pegar as coleções dois dois blocos
                            var ids = new ObjectIdCollection();

                            // Open the two blocks to be merged
                            var btr1 = tr.GetObject(bt[first], OpenMode.ForRead) as BlockTableRecord;
                            var btr2 = tr.GetObject(bt[second], OpenMode.ForRead) as BlockTableRecord;

                            // Use o LINQ para obter IEnumerable <ObjectId> para os blocos
                            var en1 = btr1.Cast<ObjectId>();
                            var en2 = btr2.Cast<ObjectId>();

                            // Adicione o conteúdo completo à nova coleção
                            for (int i = 0; i < en1.ToArray<ObjectId>().Count(); i++ )
                            {
                                ids.Add(en1.ToArray<ObjectId>()[i]);
                            }

                            for (int i = 0; i < en2.ToArray<ObjectId>().Count(); i++)
                            {
                                ids.Add(en2.ToArray<ObjectId>()[0]);
                            }

                            // Create a new block table record for our merged block
                            var btr = new BlockTableRecord();
                            btr.Name = merged;

                            //Adicione-o à tabela de blocos e à transação
                            bt.UpgradeOpen();
                            var btrId = bt.Add(btr);
                            tr.AddNewlyCreatedDBObject(btr, true);

                            // clona o conteudo
                            var idMap = new IdMapping();
                            db.DeepCloneObjects(ids, btrId, idMap, false);

                            ed.WriteMessage("\nBloco \"{0}\" criado com sucesso!.", merged);
                        }
                        else
                        {
                            ed.WriteMessage(
                              "\nO desenho já tem o bloco com o nome \"{0}\".", merged
                            );
                        }
                    }
                    else
                    {
                        ed.WriteMessage("\nBloco \"{0}\" não encontrado.", second);
                    }
                }
                else
                {
                    ed.WriteMessage("\nBloco \"{0}\"  não encontrado.", first);
                }

                // executa a Transferência de Ações
                tr.Commit();
            }
        }    
    }
}
Basicamente o que o código faz é reunir dois blocos e seus atributos visíveis e invisíveis em um único bloco. Para isso utilizamos as coleções do Windows tipo Linq.
Outra coisa que utilizamos é o DeepCloneObjects(). Podemos usar DeepCloneObjects() aqui porque estamos no mesmo desenho: se quisermos mover o novo bloco entre os bancos de dados, por algum motivo, usaremos WblockCloneObjects () seguido de Insert(). Essa última abordagem garante que todas as referências sejam seguidas e o conteúdo copiado também: algo que não precisamos ao trabalhar no mesmo banco de dados.

Aqui está o comando MB trabalhando com alguns blocos complexos com varias linhas e unindo-os em um único objeto:

Espero ter ajudado!

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...