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