Tuesday, October 8, 2013

Osmode Autocad Snaps SetVariable & GetVariable

Goal
  1. Keep track of current snaps.
  2. Set new snaps.
  3. Perform one or more actions.
  4. Restore initial snaps.
Usefull links



Class Diagram

C# Code
  • First, I create an enumeration to easily sum up multiple snaps.
    /// <summary>
    /// Integer. Initial value 4133. Saved in Registry.
    /// Sets running object snaps.
    /// The setting is stored as a bitcode using the sum of the following values.
    /// To specify more then one object snap, enter the sum of their values.
    /// </summary>
    public enum Snaps
    {
        None = 0,
        Endpoint = 1,
        Midpoint = 2,
        Center = 4,
        Node = 8,
        Quadrant = 16,
        Intersection = 32,
        Insertion = 64,
        Perpendicular = 128,
        Tangent = 256,
        Nearest = 512,
        ClearAll = 1024,
        ApparentIntersection = 2048,
        Extention = 4096,
        Parallel = 8192,
        TrackingLines = 16384
    }
  • My class will implement an interface
    public interface ISnapMode
    {
        int InitialSnapMode { get; }
        int CurrentSnapMode { get; }

        int GetSnapMode();
        void SetSnapMode(int mode);

        void SetInitialSnapMode();
    }
  • The actual class implementation of the ISnapMode Interface
/// <summary>
    ///     Class that will keep track of the initial snap mode when creating an instance of the class and sets the requested snap mode.
    ///     Sets the snapmode to it's original state when disposed.
    /// </summary>
    public class SnapMode : ISnapMode
    {
        #region Variables & Properties

        /// <summary>
        ///     Private Variable. Keeps track of the initial Snap Mode
        /// </summary>
        private readonly int _initialSnapMode;

        /// <summary>
        ///     Public Property. Get the initial Snap Mode before object initialization.
        /// </summary>
        public int InitialSnapMode
        {
            get { return _initialSnapMode; }
        }

        /// <summary>
        ///     Public Property. Get the current snap mode after changing the initial snap mode.
        /// </summary>
        public int CurrentSnapMode
        {
            get { return GetSnapMode(); }
        }

        #endregion

        #region Constructors

        /// <summary>
        ///     Protected default constructor. Initialize an instance of the object SnapMode.
        /// </summary>
        protected SnapMode()
        {
            _initialSnapMode = GetSnapMode();
        }

        /// <summary>
        ///     Overloaded constructor. Initialize an instance of the object SnapMode.
        /// </summary>
        /// <param name="snapTypes"></param>
        public SnapMode(IEnumerable<Snaps> snapTypes)
            : this()
        {
            //Only distinct snaps to calculate the sum of all snap mode bitcode values.
            SetSnapMode(CalculateSnapMode(snapTypes.Distinct()));
        }

        /// <summary>
        ///     Overloaded constructor. Initialize an instance of the object SnapMode.
        /// </summary>
        /// <param name="snap"></param>
        public SnapMode(Snaps snap)
            : this()
        {
            SetSnapMode(int.Parse(snap.ToString()));
        }

        /// <summary>
        ///     Overloaded constructor. Initialize an instance of the object SnapMode.
        /// </summary>
        /// <param name="snapMode">Integer. Requested snapmode. To specify more then one object snap, enter the sum of their values</param>
        public SnapMode(int snapMode)
        {
            SetSnapMode(snapMode);
        }

        #endregion

        #region Implementing ISnapMode

        /// <summary>
        ///     Get the current snap mode.
        /// </summary>
        /// <returns>Current snap mode bitcode value.</returns>
        public int GetSnapMode()
        {
            return int.Parse(Application.GetSystemVariable("osmode").ToString());
        }

        /// <summary>
        ///     Set the snap mode.
        /// </summary>
        /// <param name="snapMode">Snap mode bitcode value.</param>
        public void SetSnapMode(int snapMode)
        {
            Application.SetSystemVariable("osmode", snapMode);
        }

        /// <summary>
        ///     Will calculate the sum of all object snap bitcode values within the collection.
        /// </summary>
        /// <param name="snapTypes">Collection of snaps</param>
        /// <returns>The sum of the snap bitcode values.</returns>
        public int CalculateSnapMode(IEnumerable<Snaps> snapTypes)
        {
            return snapTypes.Aggregate(0, (current, snapType) => current + Convert.ToInt16(snapType));
        }

        public void SetInitialSnapMode()
        {
            SetSnapMode(_initialSnapMode);
        }
        #endregion

    }
  • Example using the previous posts example
[CommandMethod("SnapablePolylineJig")]
        public void SnapablePolylineJig()
        {
            Polyline polyline;

            var mode = new SnapMode(new List<Snaps> { Snaps.Endpoint, Snaps.Center });

            try
            {
                var service = new PolylineJigService();

                polyline = service.Draw(true, true);
            }
            finally
            {
                mode.SetInitialSnapMode();
            }

            if (polyline != null)
            {
                // Use a for loop to get each vertex, one by one
                var vn = polyline.NumberOfVertices;

                var list = new List<Point2d>();

                for (var i = 0; i < vn; i++)
                {
                    // Could also get the 3D point here
                    var pt = polyline.GetPoint2dAt(i);
                    list.Add(new Point2d(pt.X, pt.Y));
                }
            }


            Document doc =
                Application.DocumentManager.MdiActiveDocument;
            Database db = doc.Database;
            Editor ed = doc.Editor;

            // Now let's add the polyline to the modelspace
                Transaction tr =
                    db.TransactionManager.StartTransaction();
                using (tr)
                {
                    BlockTable bt =
                        (BlockTable) tr.GetObject(
                            db.BlockTableId,
                            OpenMode.ForRead
                                         );
                    BlockTableRecord btr =
                        (BlockTableRecord) tr.GetObject(
                            bt[BlockTableRecord.ModelSpace],
                            OpenMode.ForWrite
                                               );
                    ObjectId plineId = btr.AppendEntity(polyline);
                    tr.AddNewlyCreatedDBObject(polyline, true);
                    tr.Commit();
                    ed.WriteMessage("\nPolyline entity is: " +
                                    plineId.ToString()
                        );
                }
           
            // Clear the temp graphics (polyline should be in
            // the same location, if selection was not cancelled)
            // We could "redraw" instead of "regen" here
            ed.Regen();

        }