Pular para o conteúdo principal

Criando um Layout do AutoCAD com plot e viewport configuradas usando .NET

Esses dias precisei fazer um diagrama unifilar. Esse tipo diagrama vem de uma longa multiplicação diagramática de muitos anos o que significa que os documentos são formado por linhas básicas, em model space e com cada folha em um arquivo dwg separado.


Pensado assim fiz alguns ajustes na elaboração dos documentos e a primeira coisa que queria era colocar todas as folhas em um único documento dwg, ponto crucial.

Se o documento tem poucas folhas é fácil mas e quando o documento tem muitas folhas seria interessante ter algum mecanismo para criar todos os Layout’s de modo automático.

Outro ponto é que sempre que se cria um Layout no AutoCAD o Layout vem sem nenhuma configuração e com uma viewport bizarra no meio do documento.

Usar o Layout é nitidamente uma atividade geral que muitas pessoas precisam automatizar.


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.DatabaseServices;
using System.Collections.Specialized;


namespace AutoCAD.NET_Blog_Ex_2020_03_17
{

    public class myCommands
    {
        [CommandMethod("CriarLayoutRapido")]
        public void CriaLayout()
        {
            Document doc = Application.DocumentManager.MdiActiveDocument;
            if (doc == null)
                return;

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

            //Abre a Transaction
            using (Transaction tr = db.TransactionManager.StartTransaction())
            {
                // cria uma nova aba de Layout
                ObjectId id = LayoutManager.Current.CriarLayout("MeuLayoutNovo");

                // Pega o objeto criado pelo Id
                Layout lay = (Layout)tr.GetObject(id, OpenMode.ForWrite);

                // Faça algumas configurações no layout e obtenha suas extensões
                // TODO: personalizar essa parte (você pode colocar as suas configurações personalizadas aqui)
                lay.SetPlotSettings(
                  "ISO_full_bleed_2A0_(1189.00_x_1682.00_MM)",
                  "monochrome.ctb",
                  "DWF6 ePlot.pc3"
                );

                Extents2d ext = lay.GetMaxExtents();
                
                //Dimensiona a viewport de acordo com as extensões calculadas na linha anterior
                //Eu não uso margem nenhuma para sempre imprimir como PDF e a "borda" da janela ser o limite da pãgina e tudo ficar na
                //escala.
                lay.AplicaViewPort(
                  tr, 2,
                  vp => {
                      vp.ResizeViewport(ext, 1.0);

                      // Aqui voce pode ajustar para dar zoom no objeto ou até selecionar uma parte do model especifica.
                      if (EncontraOsLimitesLimitedoDataBase(db.Extmin, db.Extmax))
                      {
                          vp.FitContentToViewport(new Extents3d(db.Extmin, db.Extmax), 1.0);
                      }

                      //Dá um lock na Viewport.
                      vp.Locked = true;
                  }
                );

                tr.Commit();
            }

            //Dá uma ajeitada para tu ver o que rolou no código.
            ed.Document.SendStringToExecute("_.ZOOM _E ", true, false, false);
            ed.Document.SendStringToExecute("_.ZOOM .7X ", true, false, false);
            ed.Regen();
        }

        
        /// <summary>
        /// Essa função serve para saber qual são os limites mãximos e minimos do desenho.
        /// Se você fizer algo sempre dentro dos limites não ~e necessária essa função.
        /// </summary>
        /// <param name="min">ponto 3d min</param>
        /// <param name="max">ponto 3d max</param>
        /// <returns></returns>
        private bool EncontraOsLimitesLimitedoDataBase(Point3d min, Point3d max)
        {
            bool eok = !(min.X > 0 && min.Y > 0 && min.Z > 0 &&  max.X < 0 && max.Y < 0 && max.Z < 0);
            return eok;              
        }
    }


    public static class myExtensions
    {
        /// <summary>
        /// Inverte a ordem das propriedades X e Y de um Point2d.
        /// Para encontrar o outro extremo da viewport
        /// </summary>
        public static Point2d Swap(this Point2d pt, bool flip = true)
        {
            return flip ? new Point2d(pt.Y, pt.X) : pt;
        }

        /// <summary>
        /// Converte ym ponto 2d em um ponto 3d
        /// </summary>
        /// <param name="pt">Point2d.</param>
        /// <returns>Point3d com Z = 0 </returns>
        public static Point3d ConvPint_2dto3d(this Point2d pt)
        {
            return new Point3d(pt.X, pt.Y, 0);
        }

        /// <summary>
        /// Converte um ponto 3d em 2d.
        /// </summary>
        /// <param name="pt">The Point3d to strip.</param>
        /// <returns>The stripped Point2d.</returns>
        public static Point2d ConvPint_3dto2d(this Point3d pto3d)
        {
            return new Point2d(pto3d.X, pto3d.Y);
        }

        /// <summary>
        /// Cria o lauout com a opção de seleciona-lo como principal
        /// </summary>
        /// <param name="lm"></param>
        /// <param name="nome"></param>
        /// <param name="select"></param>
        /// <returns></returns>
        public static ObjectId CriarLayout(this LayoutManager lm, string nome, bool select = true)
        {
            // First try to get the layout
            ObjectId id = lm.GetLayoutId(nome);
            
            //Se não existe o Lauoyt ainda então o crie:
            if (!id.IsValid)
                id = lm.CreateLayout(nome);            

            //Seleciona o Layout
            if (select)
                lm.CurrentLayout = nome;            

            return id;
        }

        public static void AplicaViewPort(this Layout ilayout, Transaction aTrans, int vpNum, Action<Viewport> f)
        {
            ObjectIdCollection vpIds = ilayout.GetViewports();
            Viewport vp = null;

            //N"ao tem como saber qual ~e a viewport na lista então procura uma a uma.
            foreach (ObjectId vpId in vpIds)
            {
                Viewport vp2 = aTrans.GetObject(vpId, OpenMode.ForWrite) as Viewport;
                if (vp2 != null && vp2.Number == vpNum)
                {
                    vp = vp2;
                    break;
                }
            }

            if (vp == null)
            {
                //Se não encontrou nenhuma viewport no Lauoyt então crie uma
                 var btr =
                  (BlockTableRecord)aTrans.GetObject(ilayout.BlockTableRecordId, 
                                                     OpenMode.ForWrite);

                vp = new Viewport();

                //adiciona a viewport ao banco de dados do desenho
                btr.AppendEntity(vp);
                aTrans.AddNewlyCreatedDBObject(vp, true);

                vp.On = true;
                vp.GridOn = true;
            }

            f(vp);
        }


        public static void SetPlotSettings(this Layout lay, string pageSize, string styleSheet, string device)
        {
            using (var ps = new PlotSettings(lay.ModelType))
            {
                ps.CopyFrom(lay);

                PlotSettingsValidator psv = PlotSettingsValidator.Current;

                //Seleciona a protagem
                StringCollection devs = psv.GetPlotDeviceList();
                if (devs.Contains(device))
                {
                    psv.SetPlotConfigurationName(ps, device, null);
                    psv.RefreshLists(ps);
                }

               
                StringCollection mns = psv.GetCanonicalMediaNameList(ps);
                if (mns.Contains(pageSize))
                {
                    psv.SetCanonicalMediaName(ps, pageSize);
                }


                //Seta as penas de poltagem
                StringCollection ssl = psv.GetPlotStyleSheetList();
                if (ssl.Contains(styleSheet))
                {
                    psv.SetCurrentStyleSheet(ps, styleSheet);
                }

                //Copia a configuração de volta para o layout
                bool upgraded = false;
                if (!lay.IsWriteEnabled)
                {
                    lay.UpgradeOpen();
                    upgraded = true;
                }

                lay.CopyFrom(ps);

                if (upgraded)
                {
                    lay.DowngradeOpen();
                }
            }
        }

        /// <summary>
        /// Determina qual seria o mãximo tamanho permitido apara o Layout
        /// </summary>
        /// 
        public static Extents2d GetMaxExtents(this Layout lay)
        {

            var div = lay.PlotPaperUnits == PlotPaperUnit.Inches ? 25.4 : 1.0;

            var doIt =
              lay.PlotRotation == PlotRotation.Degrees090 ||
              lay.PlotRotation == PlotRotation.Degrees270;

             var min = lay.PlotPaperMargins.MinPoint.Swap(doIt) / div;
            var max =
              (lay.PlotPaperSize.Swap(doIt) -
               lay.PlotPaperMargins.MaxPoint.Swap(doIt).GetAsVector()) / div;

            return new Extents2d(min, max);
        }


        public static void ResizeViewport(
          this Viewport vp, Extents2d ext, double fac = 1.0
        )
        {
            vp.Width = (ext.MaxPoint.X - ext.MinPoint.X) * fac;
            vp.Height = (ext.MaxPoint.Y - ext.MinPoint.Y) * fac;
            vp.CenterPoint =
              (Point2d.Origin + (ext.MaxPoint - ext.MinPoint) * 0.5).ConvPint_2dto3d();
        }

        public static void FitContentToViewport(
          this Viewport vp, Extents3d ext3d, double fac = 1.0
        )
        {
            vp.ViewCenter =
              (ext3d.MinPoint + ((ext3d.MaxPoint - ext3d.MinPoint) * 0.5)).ConvPint_3dto2d();

            var hgt = ext3d.MaxPoint.Y - ext3d.MinPoint.Y;
            var wid = ext3d.MaxPoint.X - ext3d.MinPoint.X;

            var aspect = vp.Width / vp.Height;

            if (wid / hgt > aspect)
                hgt = wid / aspect;


            vp.ViewHeight = hgt;
            
            vp.CustomScale *= fac;
        }
    }
    
}


Observando o código veja que ele cria o layout e defini o tamanho da página. Depois disso o código modifica a viewport existente á criada junto com o Layout. Depois ajusto o zum para deixar o conteúdo mais ou menos preenchido durante esse processo de criação da viewport.

Tem também como deixar a viewport bloqueada. Como as pessoas que trabalham comigo não tem muito conhecimento de como usar o viewport prefiro deixa-las “presas” o que facilita para galera.

Espero que esse código seja útil para mais alguém além de mim.

veja o vídeo da utilização da função:


Código para Download.

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 gosta ai

Trabalhando mais rápido utilizando Express Tools

Se você não está usando o AutoCAD Express Tools, está perdendo tempo. O Express Tools é uma coleção de pequenas ferramentas de aprimoramento de produtividade que são instaladas com o AutoCAD. Eles são criadas usando as APIs do AutoCAD, como o AutoLISP, e, portanto, não estão disponíveis no AutoCAD LT também (aquela versão baratinha do AutoCAD). Aqui algumas possibilidades do Express Tools Nossa jornada começa com a barra de menus do estilo antigo. Ative-o com o comando MENUBAR e no estado 1. Clique em Express no lado direito e ele será expandido para mostrar mais de 10 categorias de ferramentas. Ainda fui mais longe e nos submenus consegui contar mais de 60 outros comandos. Ferramentas para blocos Existe dentro do Express Tools ferramentas específicas para blocos. vamos a algumas: Copy Nernest Objects - com essa ferramente você pode copiar objetos de dentro de um bloco para fora sem precisar explodir o bloco. Export Atribute Information - Você pode ain