Pular para o conteúdo principal

Movendo uma SETA no AutoCAD com texto pré-inserido.

Esses dias comecei a trabalhar em um projeto novo que envolve a inserção de setas com informações no desenho. Buscando um pouco me deparei com esse artigo do Kean Walmsley de como posicionar uma seta com o texto pré-inserido.


Isso realmente é um problema, quem usa essa ferramenta de seta (que no meu trabalho é uma raridade, setas são feitas para serem explodidas!) sabe que é dramático você escolhe uma posição para a seta e o ponto de inflexão depois escreve o texto, finalmente você nota que ficou ruim e é obrigado a editar a posição.

O truque é usar o MLeader a partir de um EntityJig.  Primeiro passo usado pelo Kean foi tornar o MLeader seja database-resident para ser acionado - uma técnica que é bastante comum ao movimentar sólidos ou blocos com atributos  (sem perder as informações contidas nele). O MText aparece no início do líder e, em seguida, o líder é exibido da origem até movermos o mouse para iniciar o ciclo Sampler/Update no jig.

Segue o código em C#:

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.Runtime;


namespace AtuoCADNetBlog_Ex240420
{
    public class myLeader
    {
        class DirectionalLeaderJig : EntityJig
        {
            private Point3d _start, _end;
            private string _contents;
            private int _index;
            private int _lineIndex;

            private bool _started;
            public DirectionalLeaderJig(string txt, Point3d start, MLeader ld) : base(ld)
            {
                // Store info that's passed in, but don't init the MLeader
                _contents = txt;
                _start = start;
                _end = start;
                _started = false;

            }


            // A fairly standard Sampler function
            protected override SamplerStatus Sampler(JigPrompts prompts)
            {
                var po = new JigPromptPointOptions();

                po.UserInputControls = (UserInputControls.Accept3dCoordinates |
               UserInputControls.NoNegativeResponseAccepted);

                po.Message = "\nEnd point";
                var res = prompts.AcquirePoint(po);
                if (_end == res.Value)
                {
                    return SamplerStatus.NoChange;
                }

                else if (res.Status == PromptStatus.OK)
                {
                    _end = res.Value;
                    return SamplerStatus.OK;
                }

                return SamplerStatus.Cancel;
            }



            protected override bool Update()
            {
                var ml = (MLeader)Entity;
                if (!_started)
                {
                    if (_start.DistanceTo(_end) > Tolerance.Global.EqualPoint)
                    {
                        // When the jig actually starts - and we have mouse movement -
                        // we create the MText and init the MLeader
                        ml.ContentType = ContentType.MTextContent;

                        var mt = new MText();

                        mt.Contents = _contents;

                        ml.MText = mt;
                        // Create the MLeader cluster and add a line to it
                        _index = ml.AddLeader();

                        _lineIndex = ml.AddLeaderLine(_index);
                        // Set the vertices on the line
                        ml.AddFirstVertex(_lineIndex, _start);

                        ml.AddLastVertex(_lineIndex, _end);
                        // Make sure we don't do this again
                        _started = true;
                    }
                }
                else
                {
                    // We only make the MLeader visible on the second time through

                    // (this also helps avoid some strange geometry flicker)
                    ml.Visible = true;
                    // We already have a line, so just set its last vertex
                    ml.SetLastVertex(_lineIndex, _end);
                }
                if (_started)
                {
                    // Set the direction of the text to depend on the X of the end-point

                    // (i.e. is if to the left or right of the start-point?)
                    var dl = new Vector3d((_end.X >= _start.X ? 1 : -1), 0, 0);

                    ml.SetDogleg(_index, dl);
                }
                return true;
            }
        }

        [CommandMethod("LEADER2")]
        public void myleadercommand()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            Editor ed = doc.Editor;
            Database db = doc.Database;
            
            // Pede ao usuário para inserir o texto 
            PromptStringOptions promptso = new PromptStringOptions("\nEntre com o Texto:");
            promptso.AllowSpaces = true;
            
            //Caso queira manter um texto vazio pára isnerir e pré-visualizar
            promptso.DefaultValue = "TEXTO";


            PromptResult pResult = ed.GetString(promptso);
            
            //Trata o caso que o usuário não entrou com valor ou entrou com um valor inválido
            if (pResult.Status != PromptStatus.OK)
                return;

            //Pede para o usuário entrar com o ponto da seta.
            PromptPointResult ppResult = ed.GetPoint("\nSelecione o ponto inicial da seta");

            //Trata o erro de seleção do ponto
            if (ppResult.Status != PromptStatus.OK)
                return;

            // Para manipular os objetos tipo db-resident é necessário usar a transaction
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                BlockTable bt = (BlockTable)tr.GetObject(db.BlockTableId, OpenMode.ForRead, false);
                BlockTableRecord btr = (BlockTableRecord)tr.GetObject(db.CurrentSpaceId, OpenMode.ForWrite, false);

                // Criando e passando as informações através de um objeto MLEADER
                //existe outras formas de fazer mas desse jeito a seta nao fica com a tela psicando e não tem risco do usuário
                //acabar clicando em algum lugar e dando um fatality no AutoCAD.
                MLeader mymleader = new MLeader();
                
                //deixa invesivel
                mymleader.Visible = false;
                
                // Criando o jig
                var jig = new DirectionalLeaderJig(pResult.StringResult, ppResult.Value, mymleader);

                // Inclui o objeto já com a posição definida no desenho
                btr.AppendEntity(mymleader);

                tr.AddNewlyCreatedDBObject(mymleader, true);

                // Insere o objeto na tela.
                PromptResult pJigResult = ed.Drag(jig);

                // If all is well, commit
                if (pJigResult.Status == PromptStatus.OK)
                {
                    tr.Commit();                    
                }
                else
                {
                    ed.WriteMessage("Ocorreu um erro na criação da seta, tente novamente.");
                }

            }

        }
  
    }
}

Esse código tem muita aplicação, quem quiser só utilizar já está até compilado, abaixo está a solução do projeto para quem quiser compilar também

Download

Espero ter ajudado mais alguém, até o próximo!

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 () {...