Create a temporary polyline that is removed after the Regen command

cadVDJ3M
Enthusiast
Enthusiast

Create a temporary polyline that is removed after the Regen command

cadVDJ3M
Enthusiast
Enthusiast

My program checks several existing polylines, and I want to check all of them that don't meet some specific conditions.

 

I thought about duplicating the polyline with a problem with the yellow color, but it would be interesting if this duplicated polyline was temporary, and disappeared when used when the user applied the regen command.

 

Something similar to Autolisp's grdraw.

 

Thanks.

0 Likes
Reply
Accepted solutions (2)
413 Views
4 Replies
Replies (4)

norman.yuan
Mentor
Mentor

In general, you could use Transient Graphics for this kind of temporary graphics. Do a search this forum/the Internet for "Transient Graphics", you would find quite some sample code.

Norman Yuan

Drive CAD With Code

EESignature

hippe013
Advisor
Advisor
Accepted solution

As @norman.yuan points out, using Transients would be ideal for something like this. I use transients all the time so I came up with the following classes.

 

 

Transient Base 

 

Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.Geometry
Imports Autodesk.AutoCAD.GraphicsInterface

Namespace Transients
    Public MustInherit Class TransientBase
        Implements IDisposable

        Public Property Entities As New List(Of Entity)

        Public Overridable Sub SetColor(index As Integer)
            For Each ent As Entity In Entities
                ent.Color = Autodesk.AutoCAD.Colors.Color.FromColorIndex(Autodesk.AutoCAD.Colors.ColorMethod.ByAci, index)
                'ent.ColorIndex = index
            Next
            UpdateTransient()
        End Sub

        Protected Friend Sub AddTransients()
            Dim ctm As TransientManager = TransientManager.CurrentTransientManager
            For Each drawable As Drawable In Entities
                ctm.AddTransient(drawable, TransientDrawingMode.Main, 128, New IntegerCollection)
            Next
        End Sub

        Protected Friend Sub RemoveTransients()
            Dim ctm As TransientManager = TransientManager.CurrentTransientManager
            For Each drawable As Drawable In Entities
                ctm.EraseTransient(drawable, New IntegerCollection)
            Next
            For Each ent As Entity In Entities
                ent.Dispose()
            Next
            Entities.Clear()
        End Sub

        Protected Sub UpdateTransient()
            Dim ctm As TransientManager = TransientManager.CurrentTransientManager
            For Each drawable As Drawable In Entities
                ctm.UpdateTransient(drawable, New IntegerCollection)
            Next
        End Sub

#Region "IDisposable Support"
        Friend disposedValue As Boolean ' To detect redundant calls

        ' IDisposable
        Protected Overridable Sub Dispose(disposing As Boolean)
            If Not disposedValue Then
                If disposing Then
                    ' TODO: dispose managed state (managed objects).
                End If

                ' TODO: free unmanaged resources (unmanaged objects) and override Finalize() below.
                ' TODO: set large fields to null.
                RemoveTransients()

                For Each drawable As Drawable In Entities
                    drawable.Dispose()
                Next
                Entities.Clear()
            End If
            disposedValue = True
        End Sub

        ' TODO: override Finalize() only if Dispose(disposing As Boolean) above has code to free unmanaged resources.
        'Protected Overrides Sub Finalize()
        '    ' Do not change this code.  Put cleanup code in Dispose(disposing As Boolean) above.
        '    Dispose(False)
        '    MyBase.Finalize()
        'End Sub

        ' This code added by Visual Basic to correctly implement the disposable pattern.
        Public Sub Dispose() Implements IDisposable.Dispose
            ' Do not change this code.  Put cleanup code in Dispose(disposing As Boolean) above.
            Dispose(True)
            ' TODO: uncomment the following line if Finalize() is overridden above.
            ' GC.SuppressFinalize(Me)
        End Sub
#End Region

    End Class
End Namespace

 

 

 

Transient that clears upon Regen

 

Imports Autodesk.AutoCAD.DatabaseServices
Imports Autodesk.AutoCAD.ApplicationServices

Namespace Transients
    Public Class RegenClearTransient
        Inherits TransientBase

        Private _doc As Document

        Public Sub New(entity As Entity, doc As Document)

            Me.Entities.Add(entity)
            AddTransients()

            _doc = doc
            AddHandler _doc.CommandWillStart, cmdStartHandler
        End Sub

        Private ReadOnly cmdStartHandler As CommandEventHandler = AddressOf OnCmdStart

        Private Sub OnCmdStart(sender As Object, e As CommandEventArgs)
            If e.GlobalCommandName.Contains("REGEN") Then
                Me.RemoveTransients()
                RemoveHandler _doc.CommandWillStart, cmdStartHandler
            End If
        End Sub

    End Class
End Namespace

 

 

And then an example on how to use it

 

 

Private rcTrans As Transients.RegenClearTransient 'Must have a backer variable for the transient to stay in view.

      
        <CommandMethod("TempPolyTransientExample")>
        Public Sub CmdTempPolyTrans()
            Dim aDoc As Document = Application.DocumentManager.MdiActiveDocument
            Dim db As Database = aDoc.Database
            Dim ed As Editor = aDoc.Editor

            Dim opt As New PromptEntityOptions(vbCrLf + "Select Polyline: ")
            opt.SetRejectMessage(vbCrLf + "Selected entity must be a Polyline. Try Again.")
            opt.AddAllowedClass(GetType(Polyline), False)


            Dim res As PromptEntityResult = ed.GetEntity(opt)

            If res.Status <> PromptStatus.OK Then
                Exit Sub
            End If

            Using tr As Transaction = db.TransactionManager.StartTransaction
                Dim poly As Polyline = tr.GetObject(res.ObjectId, OpenMode.ForRead)


                Dim cPoly As Entity = poly.Clone
                cPoly.ColorIndex = 2

                rcTrans = New Transients.RegenClearTransient(cPoly, aDoc)


                tr.Commit()
            End Using

        End Sub

 

cadVDJ3M
Enthusiast
Enthusiast

 

Thanks @hippe013 since the @norman.yuan talked about transients I've been researching this, but I haven't found such an effective way to eliminate them in a simple way through Regen..

 

I'll convert this code to C# (ie good because I learn more).


0 Likes

cadVDJ3M
Enthusiast
Enthusiast
Accepted solution

Thank you @hippe013  and @norman.yuan  , with the tips provided I managed to solve the issue and understand how Transient Graphics works.

 

Here the solution I applied, a simpler code that meets my needs.

 

The idea of ​​monitoring events is fantastic, and it can be useful for many things... I like this.

 

Here is the final code, with a lot of help from the web.

 

using System.Collections.Generic;
using System;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Geometry;
using Autodesk.AutoCAD.GraphicsInterface;
using Autodesk.AutoCAD.ApplicationServices;
using AcadApplication = Autodesk.AutoCAD.ApplicationServices.Application;
using AcadDocument = Autodesk.AutoCAD.ApplicationServices.Document;



namespace MyTransients
{
    class MyTransients
    {

        public static List<Entity> entities = new List<Entity>();
        public static bool IsMonitoring = false;

        public static void CreateTransient(Entity ent)
        {
            entities.Add(ent);
            TransientManager.CurrentTransientManager.AddTransient(ent, TransientDrawingMode.DirectShortTerm, 128, new IntegerCollection());
            MonitorCommandEvents_Method(); // Initialize Commands Events Monitor
        }

        public static void ClearTransient()
        {
            foreach (var item in entities)
            {
                TransientManager.CurrentTransientManager.EraseTransient(item, new IntegerCollection());
                item.Dispose();
            }
        }

        #region Event Monitor, to capture Autocad Commands

        /// <summary>
        /// Initialize event monitor
        /// </summary>
        public static void MonitorCommandEvents_Method()
        {
            if (!IsMonitoring)
            {
                SubscribeToDoc(AcadApplication.DocumentManager.MdiActiveDocument);
                IsMonitoring = true;

            }
        }


        /// <summary>
        /// Monitored events
        /// </summary>
        /// <param name="doc"></param>
        public static void SubscribeToDoc(AcadDocument doc)
        {
            doc.CommandWillStart += new CommandEventHandler(doc_CommandWillStart);

            //Disabled for future use
            //doc.CommandEnded += new CommandEventHandler(doc_CommandEnded);
            //doc.CommandCancelled += new CommandEventHandler(doc_CommandCancelled);
            //doc.CommandFailed += new CommandEventHandler(doc_CommandFailed);
            //doc.UnknownCommand += new UnknownCommandEventHandler(doc_UnknownCommand);
        }

        static void doc_UnknownCommand(object sender, UnknownCommandEventArgs e)
        {
            (sender as AcadDocument).Editor.WriteMessage(string.Format("\nCommand {0} unknown.\n", e.GlobalCommandName));
        }

        static void doc_CommandFailed(object sender, CommandEventArgs e)
        {
            (sender as AcadDocument).Editor.WriteMessage(string.Format("\nCommand {0} failed.\n", e.GlobalCommandName));
        }

        static void doc_CommandCancelled(object sender, CommandEventArgs e)
        {
            (sender as AcadDocument).Editor.WriteMessage(string.Format("\nCommand {0} cancelled.\n", e.GlobalCommandName));
        }

        static void doc_CommandEnded(object sender, CommandEventArgs e)
        {
            (sender as AcadDocument).Editor.WriteMessage(string.Format("\nCommand {0} ended.\n", e.GlobalCommandName));

        }

        static void doc_CommandWillStart(object sender, CommandEventArgs e)
        {
            if (e.GlobalCommandName.Equals("REGEN", StringComparison.CurrentCultureIgnoreCase))
            {
                ClearTransient();
            }
        }

        #endregion

    }
}